Ruby  2.1.10p492(2016-04-01revision54464)
vm_insnhelper.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  vm_insnhelper.c - instruction helper functions.
4 
5  $Author: usa $
6 
7  Copyright (C) 2007 Koichi Sasada
8 
9 **********************************************************************/
10 
11 /* finish iseq array */
12 #include "insns.inc"
13 #include <math.h>
14 #include "constant.h"
15 #include "internal.h"
16 #include "probes.h"
17 #include "probes_helper.h"
18 
19 /* control stack frame */
20 
21 #ifndef INLINE
22 #define INLINE inline
23 #endif
24 
26 
27 static void
29 {
31 }
32 
33 static inline rb_control_frame_t *
35  const rb_iseq_t *iseq,
36  VALUE type,
37  VALUE self,
38  VALUE klass,
39  VALUE specval,
40  const VALUE *pc,
41  VALUE *sp,
42  int local_size,
43  const rb_method_entry_t *me,
44  size_t stack_max)
45 {
46  rb_control_frame_t *const cfp = th->cfp - 1;
47  int i;
48 
49  /* check stack overflow */
50  CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + (int)stack_max);
51 
52  th->cfp = cfp;
53 
54  /* setup vm value stack */
55 
56  /* initialize local variables */
57  for (i=0; i < local_size; i++) {
58  *sp++ = Qnil;
59  }
60 
61  /* set special val */
62  *sp = specval;
63 
64  /* setup vm control frame stack */
65 
66  cfp->pc = (VALUE *)pc;
67  cfp->sp = sp + 1;
68 #if VM_DEBUG_BP_CHECK
69  cfp->bp_check = sp + 1;
70 #endif
71  cfp->ep = sp;
72  cfp->iseq = (rb_iseq_t *) iseq;
73  cfp->flag = type;
74  cfp->self = self;
75  cfp->block_iseq = 0;
76  cfp->proc = 0;
77  cfp->me = me;
78  if (klass) {
79  cfp->klass = klass;
80  }
81  else {
83  if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, prev_cfp)) {
84  cfp->klass = Qnil;
85  }
86  else {
87  cfp->klass = prev_cfp->klass;
88  }
89  }
90 
91  if (VMDEBUG == 2) {
92  SDR();
93  }
94 
95  return cfp;
96 }
97 
98 static inline void
100 {
102 
103  if (VMDEBUG == 2) {
104  SDR();
105  }
106 }
107 
108 /* method dispatch */
109 static inline VALUE
110 rb_arg_error_new(int argc, int min, int max)
111 {
112  VALUE err_mess = 0;
113  if (min == max) {
114  err_mess = rb_sprintf("wrong number of arguments (%d for %d)", argc, min);
115  }
116  else if (max == UNLIMITED_ARGUMENTS) {
117  err_mess = rb_sprintf("wrong number of arguments (%d for %d+)", argc, min);
118  }
119  else {
120  err_mess = rb_sprintf("wrong number of arguments (%d for %d..%d)", argc, min, max);
121  }
122  return rb_exc_new3(rb_eArgError, err_mess);
123 }
124 
125 NORETURN(static void argument_error(const rb_iseq_t *iseq, int miss_argc, int min_argc, int max_argc));
126 static void
127 argument_error(const rb_iseq_t *iseq, int miss_argc, int min_argc, int max_argc)
128 {
130  VALUE exc = rb_arg_error_new(miss_argc, min_argc, max_argc);
131  VALUE at;
132 
133  if (iseq) {
134  vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, Qnil /* self */, Qnil /* klass */, Qnil /* specval*/,
135  iseq->iseq_encoded, th->cfp->sp, 0 /* local_size */, 0 /* me */, 0 /* stack_max */);
136  at = rb_vm_backtrace_object();
137  vm_pop_frame(th);
138  }
139  else {
140  at = rb_vm_backtrace_object();
141  }
142 
143  rb_iv_set(exc, "bt_locations", at);
144  rb_funcall(exc, rb_intern("set_backtrace"), 1, at);
145  rb_exc_raise(exc);
146 }
147 
148 void
149 rb_error_arity(int argc, int min, int max)
150 {
151  rb_exc_raise(rb_arg_error_new(argc, min, max));
152 }
153 
154 /* svar */
155 
156 static inline NODE *
158 {
159  VALUE *svar;
160 
161  if (lep && th->root_lep != lep) {
162  svar = &lep[-1];
163  }
164  else {
165  svar = &th->root_svar;
166  }
167  if (NIL_P(*svar)) {
168  *svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
169  }
170  return (NODE *)*svar;
171 }
172 
173 static VALUE
175 {
176  NODE *svar = lep_svar_place(th, lep);
177 
178  switch (key) {
179  case 0:
180  return svar->u1.value;
181  case 1:
182  return svar->u2.value;
183  default: {
184  const VALUE ary = svar->u3.value;
185 
186  if (NIL_P(ary)) {
187  return Qnil;
188  }
189  else {
190  return rb_ary_entry(ary, key - DEFAULT_SPECIAL_VAR_COUNT);
191  }
192  }
193  }
194 }
195 
196 static void
198 {
199  NODE *svar = lep_svar_place(th, lep);
200 
201  switch (key) {
202  case 0:
203  RB_OBJ_WRITE(svar, &svar->u1.value, val);
204  return;
205  case 1:
206  RB_OBJ_WRITE(svar, &svar->u2.value, val);
207  return;
208  default: {
209  VALUE ary = svar->u3.value;
210 
211  if (NIL_P(ary)) {
212  RB_OBJ_WRITE(svar, &svar->u3.value, ary = rb_ary_new());
213  }
214  rb_ary_store(ary, key - DEFAULT_SPECIAL_VAR_COUNT, val);
215  }
216  }
217 }
218 
219 static inline VALUE
221 {
222  VALUE val;
223 
224  if (type == 0) {
225  val = lep_svar_get(th, lep, key);
226  }
227  else {
228  VALUE backref = lep_svar_get(th, lep, 1);
229 
230  if (type & 0x01) {
231  switch (type >> 1) {
232  case '&':
233  val = rb_reg_last_match(backref);
234  break;
235  case '`':
236  val = rb_reg_match_pre(backref);
237  break;
238  case '\'':
239  val = rb_reg_match_post(backref);
240  break;
241  case '+':
242  val = rb_reg_match_last(backref);
243  break;
244  default:
245  rb_bug("unexpected back-ref");
246  }
247  }
248  else {
249  val = rb_reg_nth_match((int)(type >> 1), backref);
250  }
251  }
252  return val;
253 }
254 
255 static NODE *
256 vm_get_cref0(const rb_iseq_t *iseq, const VALUE *ep)
257 {
258  while (1) {
259  if (VM_EP_LEP_P(ep)) {
260  if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return NULL;
261  return iseq->cref_stack;
262  }
263  else if (ep[-1] != Qnil) {
264  return (NODE *)ep[-1];
265  }
266  ep = VM_EP_PREV_EP(ep);
267  }
268 }
269 
270 NODE *
271 rb_vm_get_cref(const rb_iseq_t *iseq, const VALUE *ep)
272 {
273  NODE *cref = vm_get_cref0(iseq, ep);
274 
275  if (cref == 0) {
276  rb_bug("rb_vm_get_cref: unreachable");
277  }
278  return cref;
279 }
280 
281 void
282 rb_vm_rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **new_cref_ptr)
283 {
284  NODE *new_node;
285  while (node) {
286  if (node->nd_clss == old_klass) {
287  new_node = NEW_CREF(new_klass);
288  COPY_CREF_OMOD(new_node, node);
289  RB_OBJ_WRITE(new_node, &new_node->nd_next, node->nd_next);
290  *new_cref_ptr = new_node;
291  return;
292  }
293  new_node = NEW_CREF(node->nd_clss);
294  COPY_CREF_OMOD(new_node, node);
295  node = node->nd_next;
296  *new_cref_ptr = new_node;
297  new_cref_ptr = &new_node->nd_next;
298  }
299  *new_cref_ptr = NULL;
300 }
301 
302 static NODE *
304 {
306  NODE *cref = NEW_CREF(klass);
307  cref->nd_refinements = Qnil;
308  cref->nd_visi = noex;
309 
310  if (blockptr) {
311  RB_OBJ_WRITE(cref, &cref->nd_next, vm_get_cref0(blockptr->iseq, blockptr->ep));
312  }
313  else if (cfp) {
314  RB_OBJ_WRITE(cref, &cref->nd_next, vm_get_cref0(cfp->iseq, cfp->ep));
315  }
316  /* TODO: why cref->nd_next is 1? */
317  if (cref->nd_next && cref->nd_next != (void *) 1 &&
318  !NIL_P(cref->nd_next->nd_refinements)) {
319  COPY_CREF_OMOD(cref, cref->nd_next);
320  }
321 
322  return cref;
323 }
324 
325 static inline VALUE
326 vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
327 {
328  NODE *cref = rb_vm_get_cref(iseq, ep);
329  VALUE klass = Qundef;
330 
331  while (cref) {
332  if ((klass = cref->nd_clss) != 0) {
333  break;
334  }
335  cref = cref->nd_next;
336  }
337 
338  return klass;
339 }
340 
341 static inline VALUE
342 vm_get_const_base(const rb_iseq_t *iseq, const VALUE *ep)
343 {
344  NODE *cref = rb_vm_get_cref(iseq, ep);
345  VALUE klass = Qundef;
346 
347  while (cref) {
348  if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
349  (klass = cref->nd_clss) != 0) {
350  break;
351  }
352  cref = cref->nd_next;
353  }
354 
355  return klass;
356 }
357 
358 static inline void
360 {
361  VALUE str;
362  if (!RB_TYPE_P(klass, T_CLASS) && !RB_TYPE_P(klass, T_MODULE)) {
363  str = rb_inspect(klass);
364  rb_raise(rb_eTypeError, "%s is not a class/module",
365  StringValuePtr(str));
366  }
367 }
368 
369 static inline VALUE
371 {
372  if (RB_TYPE_P(klass, T_MODULE) &&
373  FL_TEST(klass, RMODULE_IS_OVERLAID) &&
374  RB_TYPE_P(cfp->klass, T_ICLASS) &&
375  RBASIC(cfp->klass)->klass == klass) {
376  return cfp->klass;
377  }
378  else {
379  return klass;
380  }
381 }
382 
383 static inline VALUE
385  VALUE orig_klass, ID id, int is_defined)
386 {
387  VALUE val;
388 
389  if (orig_klass == Qnil) {
390  /* in current lexical scope */
391  const NODE *root_cref = rb_vm_get_cref(iseq, th->cfp->ep);
392  const NODE *cref;
393  VALUE klass = orig_klass;
394 
395  while (root_cref && root_cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) {
396  root_cref = root_cref->nd_next;
397  }
398  cref = root_cref;
399  while (cref && cref->nd_next) {
400  if (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) {
401  klass = Qnil;
402  }
403  else {
404  klass = cref->nd_clss;
405  }
406  cref = cref->nd_next;
407 
408  if (!NIL_P(klass)) {
409  VALUE av, am = 0;
410  st_data_t data;
411  search_continue:
412  if (RCLASS_CONST_TBL(klass) &&
413  st_lookup(RCLASS_CONST_TBL(klass), id, &data)) {
414  val = ((rb_const_entry_t*)data)->value;
415  if (val == Qundef) {
416  if (am == klass) break;
417  am = klass;
418  if (is_defined) return 1;
419  if (rb_autoloading_value(klass, id, &av)) return av;
420  rb_autoload_load(klass, id);
421  goto search_continue;
422  }
423  else {
424  if (is_defined) {
425  return 1;
426  }
427  else {
428  return val;
429  }
430  }
431  }
432  }
433  }
434 
435  /* search self */
436  if (root_cref && !NIL_P(root_cref->nd_clss)) {
437  klass = vm_get_iclass(th->cfp, root_cref->nd_clss);
438  }
439  else {
440  klass = CLASS_OF(th->cfp->self);
441  }
442 
443  if (is_defined) {
444  return rb_const_defined(klass, id);
445  }
446  else {
447  return rb_const_get(klass, id);
448  }
449  }
450  else {
451  vm_check_if_namespace(orig_klass);
452  if (is_defined) {
453  return rb_public_const_defined_from(orig_klass, id);
454  }
455  else {
456  return rb_public_const_get_from(orig_klass, id);
457  }
458  }
459 }
460 
461 static inline VALUE
463 {
464  VALUE klass;
465 
466  if (!cref) {
467  rb_bug("vm_get_cvar_base: no cref");
468  }
469 
470  while (cref->nd_next &&
471  (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON) ||
472  (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL))) {
473  cref = cref->nd_next;
474  }
475  if (!cref->nd_next) {
476  rb_warn("class variable access from toplevel");
477  }
478 
479  klass = vm_get_iclass(cfp, cref->nd_clss);
480 
481  if (NIL_P(klass)) {
482  rb_raise(rb_eTypeError, "no class variables available");
483  }
484  return klass;
485 }
486 
487 static VALUE
489 {
490  if (rb_const_defined_at(cbase, id)) return cbase;
491  if (cbase == rb_cObject) {
492  VALUE tmp = RCLASS_SUPER(cbase);
493  while (tmp) {
494  if (rb_const_defined_at(tmp, id)) return tmp;
495  tmp = RCLASS_SUPER(tmp);
496  }
497  }
498  return 0;
499 }
500 
501 #ifndef USE_IC_FOR_IVAR
502 #define USE_IC_FOR_IVAR 1
503 #endif
504 
505 static inline VALUE
506 vm_getivar(VALUE obj, ID id, IC ic, rb_call_info_t *ci, int is_attr)
507 {
508 #if USE_IC_FOR_IVAR
509  if (RB_TYPE_P(obj, T_OBJECT)) {
510  VALUE val = Qundef;
511  VALUE klass = RBASIC(obj)->klass;
512 
513  if (LIKELY((!is_attr && ic->ic_serial == RCLASS_SERIAL(klass)) ||
514  (is_attr && ci->aux.index > 0))) {
515  long index = !is_attr ? (long)ic->ic_value.index : ci->aux.index - 1;
516  long len = ROBJECT_NUMIV(obj);
517  VALUE *ptr = ROBJECT_IVPTR(obj);
518 
519  if (index < len) {
520  val = ptr[index];
521  }
522  }
523  else {
525  long len = ROBJECT_NUMIV(obj);
526  VALUE *ptr = ROBJECT_IVPTR(obj);
527  struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
528 
529  if (iv_index_tbl) {
530  if (st_lookup(iv_index_tbl, id, &index)) {
531  if ((long)index < len) {
532  val = ptr[index];
533  }
534  if (!is_attr) {
535  ic->ic_value.index = index;
536  ic->ic_serial = RCLASS_SERIAL(klass);
537  }
538  else { /* call_info */
539  ci->aux.index = index + 1;
540  }
541  }
542  }
543  }
544 
545  if (UNLIKELY(val == Qundef)) {
546  if (!is_attr) rb_warning("instance variable %s not initialized", rb_id2name(id));
547  val = Qnil;
548  }
549  return val;
550  }
551 #endif /* USE_IC_FOR_IVAR */
552  if (is_attr)
553  return rb_attr_get(obj, id);
554  return rb_ivar_get(obj, id);
555 }
556 
557 static inline VALUE
558 vm_setivar(VALUE obj, ID id, VALUE val, IC ic, rb_call_info_t *ci, int is_attr)
559 {
560 #if USE_IC_FOR_IVAR
561  rb_check_frozen(obj);
562 
563  if (RB_TYPE_P(obj, T_OBJECT)) {
564  VALUE klass = RBASIC(obj)->klass;
566 
567  if (LIKELY(
568  (!is_attr && ic->ic_serial == RCLASS_SERIAL(klass)) ||
569  (is_attr && ci->aux.index > 0))) {
570  long index = !is_attr ? (long)ic->ic_value.index : ci->aux.index-1;
571  long len = ROBJECT_NUMIV(obj);
572  VALUE *ptr = ROBJECT_IVPTR(obj);
573 
574  if (index < len) {
575  RB_OBJ_WRITE(obj, &ptr[index], val);
576  return val; /* inline cache hit */
577  }
578  }
579  else {
580  struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
581 
582  if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
583  if (!is_attr) {
584  ic->ic_value.index = index;
585  ic->ic_serial = RCLASS_SERIAL(klass);
586  }
587  else {
588  ci->aux.index = index + 1;
589  }
590  }
591  /* fall through */
592  }
593  }
594 #endif /* USE_IC_FOR_IVAR */
595  return rb_ivar_set(obj, id, val);
596 }
597 
598 static VALUE
600 {
601  return vm_getivar(obj, id, ic, 0, 0);
602 }
603 
604 static void
606 {
607  vm_setivar(obj, id, val, ic, 0, 0);
608 }
609 
610 static VALUE
612  rb_num_t throw_state, VALUE throwobj)
613 {
614  int state = (int)(throw_state & 0xff);
615  int flag = (int)(throw_state & 0x8000);
616  rb_num_t level = throw_state >> 16;
617 
618  if (state != 0) {
619  VALUE *pt = 0;
620  if (flag != 0) {
621  pt = (void *) 1;
622  }
623  else {
624  if (state == TAG_BREAK) {
625  rb_control_frame_t *cfp = GET_CFP();
626  VALUE *ep = GET_EP();
627  int is_orphan = 1;
628  rb_iseq_t *base_iseq = GET_ISEQ();
629 
630  search_parent:
631  if (cfp->iseq->type != ISEQ_TYPE_BLOCK) {
632  if (cfp->iseq->type == ISEQ_TYPE_CLASS) {
634  ep = cfp->ep;
635  goto search_parent;
636  }
637  ep = VM_EP_PREV_EP(ep);
638  base_iseq = base_iseq->parent_iseq;
639 
640  while ((VALUE *) cfp < th->stack + th->stack_size) {
641  if (cfp->ep == ep) {
642  goto search_parent;
643  }
645  }
646  rb_bug("VM (throw): can't find break base.");
647  }
648 
649  if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
650  /* lambda{... break ...} */
651  is_orphan = 0;
652  pt = cfp->ep;
653  state = TAG_RETURN;
654  }
655  else {
656  ep = VM_EP_PREV_EP(ep);
657 
658  while ((VALUE *)cfp < th->stack + th->stack_size) {
659  if (cfp->ep == ep) {
660  VALUE epc = cfp->pc - cfp->iseq->iseq_encoded;
661  rb_iseq_t *iseq = cfp->iseq;
662  int i;
663 
664  for (i=0; i<iseq->catch_table_size; i++) {
665  struct iseq_catch_table_entry *entry = &iseq->catch_table[i];
666 
667  if (entry->type == CATCH_TYPE_BREAK &&
668  entry->start < epc && entry->end >= epc) {
669  if (entry->cont == epc) {
670  goto found;
671  }
672  else {
673  break;
674  }
675  }
676  }
677  break;
678 
679  found:
680  pt = ep;
681  is_orphan = 0;
682  break;
683  }
685  }
686  }
687 
688  if (is_orphan) {
689  rb_vm_localjump_error("break from proc-closure", throwobj, TAG_BREAK);
690  }
691  }
692  else if (state == TAG_RETRY) {
693  rb_num_t i;
694  pt = VM_EP_PREV_EP(GET_EP());
695  for (i = 0; i < level; i++) {
696  pt = GC_GUARDED_PTR_REF((VALUE *) * pt);
697  }
698  }
699  else if (state == TAG_RETURN) {
700  rb_control_frame_t *cfp = GET_CFP();
701  VALUE *ep = GET_EP();
702  VALUE *target_lep = VM_CF_LEP(cfp);
703  int in_class_frame = 0;
704 
705  /* check orphan and get dfp */
706  while ((VALUE *) cfp < th->stack + th->stack_size) {
707  VALUE *lep = VM_CF_LEP(cfp);
708 
709  if (!target_lep) {
710  target_lep = lep;
711  }
712 
713  if (lep == target_lep && cfp->iseq->type == ISEQ_TYPE_CLASS) {
714  in_class_frame = 1;
715  target_lep = 0;
716  }
717 
718  if (lep == target_lep) {
719  if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
720  VALUE *tep = ep;
721 
722  if (in_class_frame) {
723  /* lambda {class A; ... return ...; end} */
724  ep = cfp->ep;
725  goto valid_return;
726  }
727 
728  while (target_lep != tep) {
729  if (cfp->ep == tep) {
730  /* in lambda */
731  ep = cfp->ep;
732  goto valid_return;
733  }
734  tep = VM_EP_PREV_EP(tep);
735  }
736  }
737  }
738 
739  if (cfp->ep == target_lep && cfp->iseq->type == ISEQ_TYPE_METHOD) {
740  ep = target_lep;
741  goto valid_return;
742  }
743 
745  }
746 
747  rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
748 
749  valid_return:
750  pt = ep;
751  }
752  else {
753  rb_bug("isns(throw): unsupport throw type");
754  }
755  }
756  th->state = state;
757  return (VALUE)NEW_THROW_OBJECT(throwobj, (VALUE) pt, state);
758  }
759  else {
760  /* continue throw */
761  VALUE err = throwobj;
762 
763  if (FIXNUM_P(err)) {
764  th->state = FIX2INT(err);
765  }
766  else if (SYMBOL_P(err)) {
767  th->state = TAG_THROW;
768  }
769  else if (BUILTIN_TYPE(err) == T_NODE) {
770  th->state = GET_THROWOBJ_STATE(err);
771  }
772  else {
773  th->state = TAG_RAISE;
774  /*th->state = FIX2INT(rb_ivar_get(err, idThrowState));*/
775  }
776  return err;
777  }
778 }
779 
780 static inline void
782 {
783  int is_splat = flag & 0x01;
784  rb_num_t space_size = num + is_splat;
785  VALUE *base = cfp->sp;
786  const VALUE *ptr;
787  rb_num_t len;
788 
789  if (!RB_TYPE_P(ary, T_ARRAY)) {
790  ary = rb_ary_to_ary(ary);
791  }
792 
793  cfp->sp += space_size;
794 
795  ptr = RARRAY_CONST_PTR(ary);
796  len = (rb_num_t)RARRAY_LEN(ary);
797 
798  if (flag & 0x02) {
799  /* post: ..., nil ,ary[-1], ..., ary[0..-num] # top */
800  rb_num_t i = 0, j;
801 
802  if (len < num) {
803  for (i=0; i<num-len; i++) {
804  *base++ = Qnil;
805  }
806  }
807  for (j=0; i<num; i++, j++) {
808  VALUE v = ptr[len - j - 1];
809  *base++ = v;
810  }
811  if (is_splat) {
812  *base = rb_ary_new4(len - j, ptr);
813  }
814  }
815  else {
816  /* normal: ary[num..-1], ary[num-2], ary[num-3], ..., ary[0] # top */
817  rb_num_t i;
818  VALUE *bptr = &base[space_size - 1];
819 
820  for (i=0; i<num; i++) {
821  if (len <= i) {
822  for (; i<num; i++) {
823  *bptr-- = Qnil;
824  }
825  break;
826  }
827  *bptr-- = ptr[i];
828  }
829  if (is_splat) {
830  if (num > len) {
831  *bptr = rb_ary_new();
832  }
833  else {
834  *bptr = rb_ary_new4(len - num, ptr + num);
835  }
836  }
837  }
838  RB_GC_GUARD(ary);
839 }
840 
842 
843 static void
845 {
846  VALUE klass = CLASS_OF(recv);
847 
848 #if OPT_INLINE_METHOD_CACHE
849  if (LIKELY(GET_GLOBAL_METHOD_STATE() == ci->method_state && RCLASS_SERIAL(klass) == ci->class_serial)) {
850  /* cache hit! */
851  return;
852  }
853 #endif
854 
855  ci->me = rb_method_entry(klass, ci->mid, &ci->defined_class);
856  ci->klass = klass;
857  ci->call = vm_call_general;
858 #if OPT_INLINE_METHOD_CACHE
860  ci->class_serial = RCLASS_SERIAL(klass);
861 #endif
862 }
863 
864 static inline int
866 {
867  if (me && me->def->type == VM_METHOD_TYPE_CFUNC &&
868  me->def->body.cfunc.func == func) {
869  return 1;
870  }
871  else {
872  return 0;
873  }
874 }
875 
876 static
877 #ifndef NO_BIG_INLINE
878 inline
879 #endif
880 VALUE
882 {
883  if (FIXNUM_2_P(recv, obj) &&
885  return (recv == obj) ? Qtrue : Qfalse;
886  }
887  else if (FLONUM_2_P(recv, obj) &&
889  return (recv == obj) ? Qtrue : Qfalse;
890  }
891  else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
892  if (RBASIC_CLASS(recv) == rb_cFloat &&
893  RBASIC_CLASS(obj) == rb_cFloat &&
895  double a = RFLOAT_VALUE(recv);
896  double b = RFLOAT_VALUE(obj);
897 
898  if (isnan(a) || isnan(b)) {
899  return Qfalse;
900  }
901  return (a == b) ? Qtrue : Qfalse;
902  }
903  else if (RBASIC_CLASS(recv) == rb_cString &&
904  RBASIC_CLASS(obj) == rb_cString &&
906  return rb_str_equal(recv, obj);
907  }
908  }
909 
910  {
911  vm_search_method(ci, recv);
912 
913  if (check_cfunc(ci->me, rb_obj_equal)) {
914  return recv == obj ? Qtrue : Qfalse;
915  }
916  }
917 
918  return Qundef;
919 }
920 
921 VALUE
923 {
924  rb_call_info_t ci;
925  ci.mid = idEq;
926  ci.klass = 0;
927  ci.method_state = 0;
928  ci.me = NULL;
929  ci.defined_class = 0;
930  return opt_eq_func(obj1, obj2, &ci);
931 }
932 
933 static VALUE
934 vm_call0(rb_thread_t*, VALUE, ID, int, const VALUE*, const rb_method_entry_t*, VALUE);
935 
936 static VALUE
938 {
939  switch (type) {
941  return pattern;
943  if (!rb_obj_is_kind_of(pattern, rb_cModule)) {
944  rb_raise(rb_eTypeError, "class or module required for rescue clause");
945  }
946  /* fall through */
948  VALUE defined_class;
949  rb_method_entry_t *me = rb_method_entry_with_refinements(CLASS_OF(pattern), idEqq, &defined_class);
950  if (me) {
951  return vm_call0(GET_THREAD(), pattern, idEqq, 1, &target, me, defined_class);
952  }
953  else {
954  /* fallback to funcall (e.g. method_missing) */
955  return rb_funcall2(pattern, idEqq, 1, &target);
956  }
957  }
958  default:
959  rb_bug("check_match: unreachable");
960  }
961 }
962 
963 
964 #if defined(_MSC_VER) && _MSC_VER < 1300
965 #define CHECK_CMP_NAN(a, b) if (isnan(a) || isnan(b)) return Qfalse;
966 #else
967 #define CHECK_CMP_NAN(a, b) /* do nothing */
968 #endif
969 
970 static inline VALUE
971 double_cmp_lt(double a, double b)
972 {
973  CHECK_CMP_NAN(a, b);
974  return a < b ? Qtrue : Qfalse;
975 }
976 
977 static inline VALUE
978 double_cmp_le(double a, double b)
979 {
980  CHECK_CMP_NAN(a, b);
981  return a <= b ? Qtrue : Qfalse;
982 }
983 
984 static inline VALUE
985 double_cmp_gt(double a, double b)
986 {
987  CHECK_CMP_NAN(a, b);
988  return a > b ? Qtrue : Qfalse;
989 }
990 
991 static inline VALUE
992 double_cmp_ge(double a, double b)
993 {
994  CHECK_CMP_NAN(a, b);
995  return a >= b ? Qtrue : Qfalse;
996 }
997 
998 static VALUE *
1000 {
1002  VALUE *bp = prev_cfp->sp + cfp->iseq->local_size + 1;
1003 
1004  if (cfp->iseq->type == ISEQ_TYPE_METHOD) {
1005  /* adjust `self' */
1006  bp += 1;
1007  }
1008 
1009 #if VM_DEBUG_BP_CHECK
1010  if (bp != cfp->bp_check) {
1011  fprintf(stderr, "bp_check: %ld, bp: %ld\n",
1012  (long)(cfp->bp_check - GET_THREAD()->stack),
1013  (long)(bp - GET_THREAD()->stack));
1014  rb_bug("vm_base_ptr: unreachable");
1015  }
1016 #endif
1017 
1018  return bp;
1019 }
1020 
1021 /* method call processes with call_info */
1022 
1023 static void
1025 {
1026 #define SAVE_RESTORE_CI(expr, ci) do { \
1027  int saved_argc = (ci)->argc; rb_block_t *saved_blockptr = (ci)->blockptr; /* save */ \
1028  expr; \
1029  (ci)->argc = saved_argc; (ci)->blockptr = saved_blockptr; /* restore */ \
1030 } while (0)
1031 
1032  if (UNLIKELY(ci->flag & VM_CALL_ARGS_BLOCKARG)) {
1033  rb_proc_t *po;
1034  VALUE proc;
1035 
1036  proc = *(--cfp->sp);
1037 
1038  if (proc != Qnil) {
1039  if (!rb_obj_is_proc(proc)) {
1040  VALUE b;
1041 
1042  SAVE_RESTORE_CI(b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"), ci);
1043 
1044  if (NIL_P(b) || !rb_obj_is_proc(b)) {
1046  "wrong argument type %s (expected Proc)",
1047  rb_obj_classname(proc));
1048  }
1049  proc = b;
1050  }
1051  GetProcPtr(proc, po);
1052  ci->blockptr = &po->block;
1053  RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
1054  }
1055  }
1056  else if (ci->blockiseq != 0) { /* likely */
1058  ci->blockptr->iseq = ci->blockiseq;
1059  ci->blockptr->proc = 0;
1060  }
1061 
1062  /* expand top of stack? */
1063 
1064  if (UNLIKELY(ci->flag & VM_CALL_ARGS_SPLAT)) {
1065  VALUE ary = *(cfp->sp - 1);
1066  const VALUE *ptr;
1067  int i;
1068  VALUE tmp;
1069 
1070  SAVE_RESTORE_CI(tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a"), ci);
1071 
1072  if (NIL_P(tmp)) {
1073  /* do nothing */
1074  }
1075  else {
1076  long len = RARRAY_LEN(tmp);
1077  ptr = RARRAY_CONST_PTR(tmp);
1078  cfp->sp -= 1;
1079 
1080  CHECK_VM_STACK_OVERFLOW(cfp, len);
1081 
1082  for (i = 0; i < len; i++) {
1083  *cfp->sp++ = ptr[i];
1084  }
1085  ci->argc += i-1;
1086  }
1087  }
1088 }
1089 
1090 static inline int
1092 {
1093  VALUE keyword_hash = 0, orig_hash;
1094  int optional = iseq->arg_keywords - iseq->arg_keyword_required;
1095  VALUE *const sp = th->cfp->sp;
1096  const int mark_stack_len = th->mark_stack_len;
1097 
1098  th->cfp->sp += argc;
1099  th->mark_stack_len -= argc;
1100 
1101  if (argc > m &&
1102  !NIL_P(orig_hash = rb_check_hash_type(orig_argv[argc-1])) &&
1103  (keyword_hash = rb_extract_keywords(&orig_hash)) != 0) {
1104  if (!orig_hash) {
1105  argc--;
1106  }
1107  else {
1108  orig_argv[argc-1] = orig_hash;
1109  }
1110  }
1111  rb_get_kwargs(keyword_hash, iseq->arg_keyword_table, iseq->arg_keyword_required,
1112  (iseq->arg_keyword_check ? optional : -1-optional),
1113  NULL);
1114 
1115  if (!keyword_hash) {
1116  keyword_hash = rb_hash_new();
1117  }
1118 
1119  th->cfp->sp = sp;
1120  th->mark_stack_len = mark_stack_len;
1121 
1122  *kwd = keyword_hash;
1123 
1124  return argc;
1125 }
1126 
1127 static inline int
1129 {
1130  const int m = iseq->argc;
1131  const int opts = iseq->arg_opts - (iseq->arg_opts > 0);
1132  const int min = m + iseq->arg_post_len;
1133  const int max = (iseq->arg_rest == -1) ? m + opts + iseq->arg_post_len : UNLIMITED_ARGUMENTS;
1134  const int orig_argc = ci->argc;
1135  int argc = orig_argc;
1136  VALUE *argv = orig_argv;
1137  VALUE keyword_hash = Qnil;
1138  rb_num_t opt_pc = 0;
1139 
1140  th->mark_stack_len = argc + iseq->arg_size;
1141 
1142  /* keyword argument */
1143  if (iseq->arg_keyword != -1) {
1144  argc = vm_callee_setup_keyword_arg(th, iseq, argc, min, orig_argv, &keyword_hash);
1145  }
1146 
1147  /* mandatory */
1148  if ((argc < min) || (argc > max && max != UNLIMITED_ARGUMENTS)) {
1149  argument_error(iseq, argc, min, max);
1150  }
1151 
1152  argv += m;
1153  argc -= m;
1154 
1155  /* post arguments */
1156  if (iseq->arg_post_len) {
1157  if (!(orig_argc < iseq->arg_post_start)) {
1158  VALUE *new_argv = ALLOCA_N(VALUE, argc);
1159  MEMCPY(new_argv, argv, VALUE, argc);
1160  argv = new_argv;
1161  }
1162 
1163  MEMCPY(&orig_argv[iseq->arg_post_start], &argv[argc -= iseq->arg_post_len],
1164  VALUE, iseq->arg_post_len);
1165  }
1166 
1167  /* opt arguments */
1168  if (iseq->arg_opts) {
1169  if (argc > opts) {
1170  argc -= opts;
1171  argv += opts;
1172  opt_pc = iseq->arg_opt_table[opts]; /* no opt */
1173  }
1174  else {
1175  int i;
1176  for (i = argc; i<opts; i++) {
1177  orig_argv[i + m] = Qnil;
1178  }
1179  opt_pc = iseq->arg_opt_table[argc];
1180  argc = 0;
1181  }
1182  }
1183 
1184  /* rest arguments */
1185  if (iseq->arg_rest != -1) {
1186  orig_argv[iseq->arg_rest] = rb_ary_new4(argc, argv);
1187  argc = 0;
1188  }
1189 
1190  /* keyword argument */
1191  if (iseq->arg_keyword != -1) {
1192  int i;
1193  int arg_keywords_end = iseq->arg_keyword - (iseq->arg_block != -1);
1194  for (i = iseq->arg_keywords; 0 < i; i--) {
1195  orig_argv[arg_keywords_end - i] = Qnil;
1196  }
1197  orig_argv[iseq->arg_keyword] = keyword_hash;
1198  }
1199 
1200  /* block arguments */
1201  if (iseq->arg_block != -1) {
1202  VALUE blockval = Qnil;
1203  const rb_block_t *blockptr = ci->blockptr;
1204 
1205  if (blockptr) {
1206  /* make Proc object */
1207  if (blockptr->proc == 0) {
1208  rb_proc_t *proc;
1209  blockval = rb_vm_make_proc(th, blockptr, rb_cProc);
1210  GetProcPtr(blockval, proc);
1211  ci->blockptr = &proc->block;
1212  }
1213  else {
1214  blockval = blockptr->proc;
1215  }
1216  }
1217 
1218  orig_argv[iseq->arg_block] = blockval; /* Proc or nil */
1219  }
1220 
1221  th->mark_stack_len = 0;
1222  return (int)opt_pc;
1223 }
1224 
1228 
1229 static inline void
1231  VALUE *argv, int is_lambda)
1232 {
1233  if (LIKELY(iseq->arg_simple & 0x01)) {
1234  /* simple check */
1235  if (ci->argc != iseq->argc) {
1236  argument_error(iseq, ci->argc, iseq->argc, iseq->argc);
1237  }
1238  ci->aux.opt_pc = 0;
1239  CI_SET_FASTPATH(ci,
1240  (UNLIKELY(ci->flag & VM_CALL_TAILCALL) ?
1243  (!is_lambda &&
1244  !(ci->flag & VM_CALL_ARGS_SPLAT) && /* argc may differ for each calls */
1245  !(ci->me->flag & NOEX_PROTECTED)));
1246  }
1247  else {
1248  ci->aux.opt_pc = vm_callee_setup_arg_complex(th, ci, iseq, argv);
1249  }
1250 }
1251 
1252 static VALUE
1254 {
1255  vm_callee_setup_arg(th, ci, ci->me->def->body.iseq, cfp->sp - ci->argc, 0);
1256  return vm_call_iseq_setup_2(th, cfp, ci);
1257 }
1258 
1259 static VALUE
1261 {
1262  if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) {
1263  return vm_call_iseq_setup_normal(th, cfp, ci);
1264  }
1265  else {
1266  return vm_call_iseq_setup_tailcall(th, cfp, ci);
1267  }
1268 }
1269 
1270 static inline VALUE
1272 {
1273  int i, local_size;
1274  VALUE *argv = cfp->sp - ci->argc;
1275  rb_iseq_t *iseq = ci->me->def->body.iseq;
1276  VALUE *sp = argv + iseq->arg_size;
1277 
1278  /* clear local variables (arg_size...local_size) */
1279  for (i = iseq->arg_size, local_size = iseq->local_size; i < local_size; i++) {
1280  *sp++ = Qnil;
1281  }
1282 
1285  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max);
1286 
1287  cfp->sp = argv - 1 /* recv */;
1288  return Qundef;
1289 }
1290 
1291 static inline VALUE
1293 {
1294  int i;
1295  VALUE *argv = cfp->sp - ci->argc;
1296  rb_iseq_t *iseq = ci->me->def->body.iseq;
1297  VALUE *src_argv = argv;
1298  VALUE *sp_orig, *sp;
1299  VALUE finish_flag = VM_FRAME_TYPE_FINISH_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
1300 
1301  cfp = th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); /* pop cf */
1302 
1303  RUBY_VM_CHECK_INTS(th);
1304 
1305  sp_orig = sp = cfp->sp;
1306 
1307  /* push self */
1308  sp[0] = ci->recv;
1309  sp++;
1310 
1311  /* copy arguments */
1312  for (i=0; i < iseq->arg_size; i++) {
1313  *sp++ = src_argv[i];
1314  }
1315 
1316  /* clear local variables */
1317  for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
1318  *sp++ = Qnil;
1319  }
1320 
1321  vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
1323  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max);
1324 
1325  cfp->sp = sp_orig;
1326  return Qundef;
1327 }
1328 
1329 static VALUE
1331 {
1332  return (*func)(recv, rb_ary_new4(argc, argv));
1333 }
1334 
1335 static VALUE
1337 {
1338  return (*func)(argc, argv, recv);
1339 }
1340 
1341 static VALUE
1343 {
1344  return (*func)(recv);
1345 }
1346 
1347 static VALUE
1349 {
1350  return (*func)(recv, argv[0]);
1351 }
1352 
1353 static VALUE
1355 {
1356  return (*func)(recv, argv[0], argv[1]);
1357 }
1358 
1359 static VALUE
1361 {
1362  return (*func)(recv, argv[0], argv[1], argv[2]);
1363 }
1364 
1365 static VALUE
1367 {
1368  return (*func)(recv, argv[0], argv[1], argv[2], argv[3]);
1369 }
1370 
1371 static VALUE
1373 {
1374  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
1375 }
1376 
1377 static VALUE
1379 {
1380  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
1381 }
1382 
1383 static VALUE
1385 {
1386  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
1387 }
1388 
1389 static VALUE
1391 {
1392  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
1393 }
1394 
1395 static VALUE
1397 {
1398  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
1399 }
1400 
1401 static VALUE
1403 {
1404  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
1405 }
1406 
1407 static VALUE
1409 {
1410  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
1411 }
1412 
1413 static VALUE
1415 {
1416  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
1417 }
1418 
1419 static VALUE
1421 {
1422  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]);
1423 }
1424 
1425 static VALUE
1427 {
1428  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]);
1429 }
1430 
1431 static VALUE
1433 {
1434  return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]);
1435 }
1436 
1437 #ifndef VM_PROFILE
1438 #define VM_PROFILE 0
1439 #endif
1440 
1441 #if VM_PROFILE
1442 static int vm_profile_counter[4];
1443 #define VM_PROFILE_UP(x) (vm_profile_counter[x]++)
1444 #define VM_PROFILE_ATEXIT() atexit(vm_profile_show_result)
1445 static void
1446 vm_profile_show_result(void)
1447 {
1448  fprintf(stderr, "VM Profile results: \n");
1449  fprintf(stderr, "r->c call: %d\n", vm_profile_counter[0]);
1450  fprintf(stderr, "r->c popf: %d\n", vm_profile_counter[1]);
1451  fprintf(stderr, "c->c call: %d\n", vm_profile_counter[2]);
1452  fprintf(stderr, "r->c popf: %d\n", vm_profile_counter[3]);
1453 }
1454 #else
1455 #define VM_PROFILE_UP(x)
1456 #define VM_PROFILE_ATEXIT()
1457 #endif
1458 
1459 static inline
1460 const rb_method_cfunc_t *
1462 {
1463 #if VM_DEBUG_VERIFY_METHOD_CACHE
1464  switch (me->def->type) {
1465  case VM_METHOD_TYPE_CFUNC:
1467  break;
1468 # define METHOD_BUG(t) case VM_METHOD_TYPE_##t: rb_bug("wrong method type: " #t)
1469  METHOD_BUG(ISEQ);
1470  METHOD_BUG(ATTRSET);
1471  METHOD_BUG(IVAR);
1472  METHOD_BUG(BMETHOD);
1473  METHOD_BUG(ZSUPER);
1474  METHOD_BUG(UNDEF);
1475  METHOD_BUG(OPTIMIZED);
1476  METHOD_BUG(MISSING);
1477  METHOD_BUG(REFINED);
1478 # undef METHOD_BUG
1479  default:
1480  rb_bug("wrong method type: %d", me->def->type);
1481  }
1482 #endif
1483  return &me->def->body.cfunc;
1484 }
1485 
1486 static VALUE
1488 {
1489  VALUE val;
1490  const rb_method_entry_t *me = ci->me;
1491  const rb_method_cfunc_t *cfunc = vm_method_cfunc_entry(me);
1492  int len = cfunc->argc;
1493 
1494  /* don't use `ci' after EXEC_EVENT_HOOK because ci can be override */
1495  VALUE recv = ci->recv;
1496  VALUE defined_class = ci->defined_class;
1497  rb_block_t *blockptr = ci->blockptr;
1498  int argc = ci->argc;
1499 
1501  EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qundef);
1502 
1503  vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class,
1504  VM_ENVVAL_BLOCK_PTR(blockptr), 0, th->cfp->sp, 1, me, 0);
1505 
1506  if (len >= 0) rb_check_arity(argc, len, len);
1507 
1508  reg_cfp->sp -= argc + 1;
1509  VM_PROFILE_UP(0);
1510  val = (*cfunc->invoker)(cfunc->func, recv, argc, reg_cfp->sp + 1);
1511 
1512  if (reg_cfp != th->cfp + 1) {
1513  rb_bug("vm_call_cfunc - cfp consistency error");
1514  }
1515 
1516  vm_pop_frame(th);
1517 
1518  EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass, val);
1520 
1521  return val;
1522 }
1523 
1524 #if OPT_CALL_CFUNC_WITHOUT_FRAME
1525 static VALUE
1526 vm_call_cfunc_latter(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
1527 {
1528  VALUE val;
1529  int argc = ci->argc;
1530  VALUE *argv = STACK_ADDR_FROM_TOP(argc);
1531  const rb_method_cfunc_t *cfunc = vm_method_cfunc_entry(ci->me);
1532 
1533  th->passed_ci = ci;
1534  reg_cfp->sp -= argc + 1;
1535  ci->aux.inc_sp = argc + 1;
1536  VM_PROFILE_UP(0);
1537  val = (*cfunc->invoker)(cfunc->func, ci, argv);
1538 
1539  /* check */
1540  if (reg_cfp == th->cfp) { /* no frame push */
1541  if (UNLIKELY(th->passed_ci != ci)) {
1542  rb_bug("vm_call_cfunc_latter: passed_ci error (ci: %p, passed_ci: %p)", ci, th->passed_ci);
1543  }
1544  th->passed_ci = 0;
1545  }
1546  else {
1547  if (UNLIKELY(reg_cfp != RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp))) {
1548  rb_bug("vm_call_cfunc_latter: cfp consistency error (%p, %p)", reg_cfp, th->cfp+1);
1549  }
1550  vm_pop_frame(th);
1551  VM_PROFILE_UP(1);
1552  }
1553 
1554  return val;
1555 }
1556 
1557 static VALUE
1559 {
1560  VALUE val;
1561  const rb_method_entry_t *me = ci->me;
1562  int len = vm_method_cfunc_entry(me)->argc;
1563  VALUE recv = ci->recv;
1564 
1565  if (len >= 0) rb_check_arity(ci->argc, len, len);
1566 
1568  EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qnil);
1569 
1570  if (!(ci->me->flag & NOEX_PROTECTED) &&
1571  !(ci->flag & VM_CALL_ARGS_SPLAT)) {
1572  CI_SET_FASTPATH(ci, vm_call_cfunc_latter, 1);
1573  }
1574  val = vm_call_cfunc_latter(th, reg_cfp, ci);
1575 
1576  EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass, val);
1578 
1579  return val;
1580 }
1581 
1582 void
1583 vm_call_cfunc_push_frame(rb_thread_t *th)
1584 {
1585  rb_call_info_t *ci = th->passed_ci;
1586  const rb_method_entry_t *me = ci->me;
1587  th->passed_ci = 0;
1588 
1590  VM_ENVVAL_BLOCK_PTR(ci->blockptr), 0, th->cfp->sp + ci->aux.inc_sp, 1, me);
1591 
1592  if (ci->call != vm_call_general) {
1594  }
1595 }
1596 #else /* OPT_CALL_CFUNC_WITHOUT_FRAME */
1597 static VALUE
1599 {
1600  return vm_call_cfunc_with_frame(th, reg_cfp, ci);
1601 }
1602 #endif
1603 
1604 static VALUE
1606 {
1607  VALUE val = vm_getivar(ci->recv, ci->me->def->body.attr.id, 0, ci, 1);
1608  cfp->sp -= 1;
1609  return val;
1610 }
1611 
1612 static VALUE
1614 {
1615  VALUE val = vm_setivar(ci->recv, ci->me->def->body.attr.id, *(cfp->sp - 1), 0, ci, 1);
1616  cfp->sp -= 2;
1617  return val;
1618 }
1619 
1620 static inline VALUE
1622 {
1623  rb_proc_t *proc;
1624  VALUE val;
1625 
1626  /* control block frame */
1627  th->passed_bmethod_me = ci->me;
1628  GetProcPtr(ci->me->def->body.proc, proc);
1629  val = vm_invoke_proc(th, proc, ci->recv, ci->defined_class, ci->argc, argv, ci->blockptr);
1630 
1631  return val;
1632 }
1633 
1634 static VALUE
1636 {
1637  VALUE *argv = ALLOCA_N(VALUE, ci->argc);
1638  MEMCPY(argv, cfp->sp - ci->argc, VALUE, ci->argc);
1639  cfp->sp += - ci->argc - 1;
1640 
1641  return vm_call_bmethod_body(th, ci, argv);
1642 }
1643 
1644 static
1645 #ifdef _MSC_VER
1646 __forceinline
1647 #else
1648 inline
1649 #endif
1651 
1652 static VALUE
1654 {
1655  int i = ci->argc - 1;
1656  VALUE sym;
1657  rb_call_info_t ci_entry;
1658 
1659  if (ci->argc == 0) {
1660  rb_raise(rb_eArgError, "no method name given");
1661  }
1662 
1663  ci_entry = *ci; /* copy ci entry */
1664  ci = &ci_entry;
1665 
1666  sym = TOPN(i);
1667 
1668  if (SYMBOL_P(sym)) {
1669  ci->mid = SYM2ID(sym);
1670  }
1671  else if (!(ci->mid = rb_check_id(&sym))) {
1672  if (rb_method_basic_definition_p(CLASS_OF(ci->recv), idMethodMissing)) {
1674  rb_exc_raise(exc);
1675  }
1676  ci->mid = rb_to_id(sym);
1677  }
1678 
1679  /* shift arguments */
1680  if (i > 0) {
1681  MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
1682  }
1683  ci->me =
1685  ci->mid, &ci->defined_class);
1686  ci->argc -= 1;
1687  DEC_SP(1);
1688 
1690 
1691  return vm_call_method(th, reg_cfp, ci);
1692 }
1693 
1694 static VALUE
1696 {
1697  rb_proc_t *proc;
1698  int argc = ci->argc;
1699  VALUE *argv = ALLOCA_N(VALUE, argc);
1700  GetProcPtr(ci->recv, proc);
1701  MEMCPY(argv, cfp->sp - argc, VALUE, argc);
1702  cfp->sp -= argc + 1;
1703 
1704  return rb_vm_invoke_proc(th, proc, argc, argv, ci->blockptr);
1705 }
1706 
1707 static VALUE
1709 {
1710  VALUE *argv = STACK_ADDR_FROM_TOP(ci->argc);
1711  rb_call_info_t ci_entry;
1712 
1713  ci_entry.flag = VM_CALL_FCALL | VM_CALL_OPT_SEND;
1714  ci_entry.argc = ci->argc+1;
1715  ci_entry.mid = idMethodMissing;
1716  ci_entry.blockptr = ci->blockptr;
1717  ci_entry.recv = ci->recv;
1718  ci_entry.me = rb_method_entry(CLASS_OF(ci_entry.recv), idMethodMissing, &ci_entry.defined_class);
1719 
1720  /* shift arguments: m(a, b, c) #=> method_missing(:m, a, b, c) */
1721  CHECK_VM_STACK_OVERFLOW(reg_cfp, 1);
1722  if (ci->argc > 0) {
1723  MEMMOVE(argv+1, argv, VALUE, ci->argc);
1724  }
1725  argv[0] = ID2SYM(ci->mid);
1726  INC_SP(1);
1727 
1729  return vm_call_method(th, reg_cfp, &ci_entry);
1730 }
1731 
1732 static inline VALUE
1734 {
1735  if (NIL_P(refinements)) {
1736  return Qnil;
1737  }
1738  return rb_hash_lookup(refinements, klass);
1739 }
1740 
1743 
1744 static rb_control_frame_t *
1746 {
1747  rb_control_frame_t *top_cfp = cfp;
1748 
1749  if (cfp->iseq && cfp->iseq->type == ISEQ_TYPE_BLOCK) {
1750  rb_iseq_t *local_iseq = cfp->iseq->local_iseq;
1751  do {
1752  cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1754  /* TODO: orphan block */
1755  return top_cfp;
1756  }
1757  } while (cfp->iseq != local_iseq);
1758  }
1759  return cfp;
1760 }
1761 
1762 static
1763 #ifdef _MSC_VER
1764 __forceinline
1765 #else
1766 inline
1767 #endif
1768 VALUE
1770 {
1771  int enable_fastpath = 1;
1772  rb_call_info_t ci_temp;
1773 
1774  start_method_dispatch:
1775  if (ci->me != 0) {
1776  if ((ci->me->flag == 0)) {
1777  VALUE klass;
1778 
1779  normal_method_dispatch:
1780  switch (ci->me->def->type) {
1781  case VM_METHOD_TYPE_ISEQ:{
1782  CI_SET_FASTPATH(ci, vm_call_iseq_setup, enable_fastpath);
1783  return vm_call_iseq_setup(th, cfp, ci);
1784  }
1786  case VM_METHOD_TYPE_CFUNC:
1787  CI_SET_FASTPATH(ci, vm_call_cfunc, enable_fastpath);
1788  return vm_call_cfunc(th, cfp, ci);
1789  case VM_METHOD_TYPE_ATTRSET:{
1790  rb_check_arity(ci->argc, 1, 1);
1791  ci->aux.index = 0;
1792  CI_SET_FASTPATH(ci, vm_call_attrset, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
1793  return vm_call_attrset(th, cfp, ci);
1794  }
1795  case VM_METHOD_TYPE_IVAR:{
1796  rb_check_arity(ci->argc, 0, 0);
1797  ci->aux.index = 0;
1798  CI_SET_FASTPATH(ci, vm_call_ivar, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
1799  return vm_call_ivar(th, cfp, ci);
1800  }
1801  case VM_METHOD_TYPE_MISSING:{
1802  ci->aux.missing_reason = 0;
1803  CI_SET_FASTPATH(ci, vm_call_method_missing, enable_fastpath);
1804  return vm_call_method_missing(th, cfp, ci);
1805  }
1806  case VM_METHOD_TYPE_BMETHOD:{
1807  CI_SET_FASTPATH(ci, vm_call_bmethod, enable_fastpath);
1808  return vm_call_bmethod(th, cfp, ci);
1809  }
1810  case VM_METHOD_TYPE_ZSUPER:{
1811  klass = ci->me->klass;
1812  klass = RCLASS_ORIGIN(klass);
1813  zsuper_method_dispatch:
1814  klass = RCLASS_SUPER(klass);
1815  if (!klass) {
1816  ci->me = 0;
1817  goto start_method_dispatch;
1818  }
1819  ci_temp = *ci;
1820  ci = &ci_temp;
1821 
1822  ci->me = rb_method_entry(klass, ci->mid, &ci->defined_class);
1823 
1824  if (ci->me != 0) {
1825  goto normal_method_dispatch;
1826  }
1827  else {
1828  goto start_method_dispatch;
1829  }
1830  }
1832  switch (ci->me->def->body.optimize_type) {
1833  case OPTIMIZED_METHOD_TYPE_SEND:
1834  CI_SET_FASTPATH(ci, vm_call_opt_send, enable_fastpath);
1835  return vm_call_opt_send(th, cfp, ci);
1836  case OPTIMIZED_METHOD_TYPE_CALL:
1837  CI_SET_FASTPATH(ci, vm_call_opt_call, enable_fastpath);
1838  return vm_call_opt_call(th, cfp, ci);
1839  default:
1840  rb_bug("vm_call_method: unsupported optimized method type (%d)",
1841  ci->me->def->body.optimize_type);
1842  }
1843  break;
1844  }
1845  case VM_METHOD_TYPE_UNDEF:
1846  break;
1847  case VM_METHOD_TYPE_REFINED:{
1848  NODE *cref = rb_vm_get_cref(cfp->iseq, cfp->ep);
1849  VALUE refinements = cref ? cref->nd_refinements : Qnil;
1850  VALUE refinement, defined_class;
1851  rb_method_entry_t *me;
1852 
1853  refinement = find_refinement(refinements,
1854  ci->defined_class);
1855  if (NIL_P(refinement)) {
1856  goto no_refinement_dispatch;
1857  }
1858  me = rb_method_entry(refinement, ci->mid, &defined_class);
1859  if (me) {
1860  if (ci->call == vm_call_super_method) {
1861  rb_control_frame_t *top_cfp = current_method_entry(th, cfp);
1862  if (top_cfp->me &&
1863  rb_method_definition_eq(me->def, top_cfp->me->def)) {
1864  goto no_refinement_dispatch;
1865  }
1866  }
1867  ci->me = me;
1868  ci->defined_class = defined_class;
1869  if (me->def->type != VM_METHOD_TYPE_REFINED) {
1870  goto start_method_dispatch;
1871  }
1872  }
1873 
1874  no_refinement_dispatch:
1875  if (ci->me->def->body.orig_me) {
1876  ci->me = ci->me->def->body.orig_me;
1877  if (UNDEFINED_METHOD_ENTRY_P(ci->me)) {
1878  ci->me = 0;
1879  }
1880  goto start_method_dispatch;
1881  }
1882  else {
1883  klass = ci->me->klass;
1884  goto zsuper_method_dispatch;
1885  }
1886  }
1887  }
1888  rb_bug("vm_call_method: unsupported method type (%d)", ci->me->def->type);
1889  }
1890  else {
1891  int noex_safe;
1892  if (!(ci->flag & VM_CALL_FCALL) && (ci->me->flag & NOEX_MASK) & NOEX_PRIVATE) {
1893  int stat = NOEX_PRIVATE;
1894 
1895  if (ci->flag & VM_CALL_VCALL) {
1896  stat |= NOEX_VCALL;
1897  }
1898  ci->aux.missing_reason = stat;
1900  return vm_call_method_missing(th, cfp, ci);
1901  }
1902  else if (!(ci->flag & VM_CALL_OPT_SEND) && (ci->me->flag & NOEX_MASK) & NOEX_PROTECTED) {
1903  enable_fastpath = 0;
1904  if (!rb_obj_is_kind_of(cfp->self, ci->defined_class)) {
1906  return vm_call_method_missing(th, cfp, ci);
1907  }
1908  else {
1909  goto normal_method_dispatch;
1910  }
1911  }
1912  else if ((noex_safe = NOEX_SAFE(ci->me->flag)) > th->safe_level && (noex_safe > 2)) {
1913  rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(ci->mid));
1914  }
1915  else {
1916  goto normal_method_dispatch;
1917  }
1918  }
1919  }
1920  else {
1921  /* method missing */
1922  int stat = 0;
1923  if (ci->flag & VM_CALL_VCALL) {
1924  stat |= NOEX_VCALL;
1925  }
1926  if (ci->flag & VM_CALL_SUPER) {
1927  stat |= NOEX_SUPER;
1928  }
1929  if (ci->mid == idMethodMissing) {
1930  rb_control_frame_t *reg_cfp = cfp;
1931  VALUE *argv = STACK_ADDR_FROM_TOP(ci->argc);
1932  rb_raise_method_missing(th, ci->argc, argv, ci->recv, stat);
1933  }
1934  else {
1935  ci->aux.missing_reason = stat;
1937  return vm_call_method_missing(th, cfp, ci);
1938  }
1939  }
1940 
1941  rb_bug("vm_call_method: unreachable");
1942 }
1943 
1944 static VALUE
1946 {
1947  return vm_call_method(th, reg_cfp, ci);
1948 }
1949 
1950 static VALUE
1952 {
1953  return vm_call_method(th, reg_cfp, ci);
1954 }
1955 
1956 /* super */
1957 
1958 static inline VALUE
1960 {
1961  if (BUILTIN_TYPE(klass) == T_ICLASS &&
1962  FL_TEST(RBASIC(klass)->klass, RMODULE_IS_REFINEMENT)) {
1963  klass = RBASIC(klass)->klass;
1964  }
1965  klass = RCLASS_ORIGIN(klass);
1966  return RCLASS_SUPER(klass);
1967 }
1968 
1969 static void
1971 {
1972  rb_raise(rb_eNoMethodError, "super called outside of method");
1973 }
1974 
1975 static int
1977 {
1978  while (iseq && !iseq->klass) {
1979  iseq = iseq->parent_iseq;
1980  }
1981 
1982  if (iseq == 0) {
1983  return -1;
1984  }
1985 
1986  ci->mid = iseq->defined_method_id;
1987 
1988  if (iseq != iseq->local_iseq) {
1989  /* defined by Module#define_method() */
1990  rb_control_frame_t *lcfp = GET_CFP();
1991 
1992  if (!sigval) {
1993  /* zsuper */
1994  return -2;
1995  }
1996 
1997  while (lcfp->iseq != iseq) {
1998  rb_thread_t *th = GET_THREAD();
1999  VALUE *tep = VM_EP_PREV_EP(lcfp->ep);
2000  while (1) {
2001  lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
2003  return -1;
2004  }
2005  if (lcfp->ep == tep) {
2006  break;
2007  }
2008  }
2009  }
2010 
2011  /* temporary measure for [Bug #2420] [Bug #3136] */
2012  if (!lcfp->me) {
2013  return -1;
2014  }
2015 
2016  ci->mid = lcfp->me->def->original_id;
2018  }
2019  else {
2020  ci->klass = vm_search_normal_superclass(reg_cfp->klass);
2021  }
2022 
2023  return 0;
2024 }
2025 
2026 static void
2028 {
2029  VALUE current_defined_class;
2030  rb_iseq_t *iseq = GET_ISEQ();
2031  VALUE sigval = TOPN(ci->argc);
2032 
2033  current_defined_class = GET_CFP()->klass;
2034  if (NIL_P(current_defined_class)) {
2035  vm_super_outside();
2036  }
2037 
2038  if (!NIL_P(RCLASS_REFINED_CLASS(current_defined_class))) {
2039  current_defined_class = RCLASS_REFINED_CLASS(current_defined_class);
2040  }
2041 
2042  if (BUILTIN_TYPE(current_defined_class) != T_MODULE &&
2043  BUILTIN_TYPE(current_defined_class) != T_ICLASS && /* bound UnboundMethod */
2044  !FL_TEST(current_defined_class, RMODULE_INCLUDED_INTO_REFINEMENT) &&
2045  !rb_obj_is_kind_of(ci->recv, current_defined_class)) {
2046  VALUE m = RB_TYPE_P(current_defined_class, T_ICLASS) ?
2047  RBASIC(current_defined_class)->klass : current_defined_class;
2048 
2050  "self has wrong type to call super in this context: "
2051  "%"PRIsVALUE" (expected %"PRIsVALUE")",
2052  rb_obj_class(ci->recv), m);
2053  }
2054 
2055  switch (vm_search_superclass(GET_CFP(), iseq, sigval, ci)) {
2056  case -1:
2057  vm_super_outside();
2058  case -2:
2060  "implicit argument passing of super from method defined"
2061  " by define_method() is not supported."
2062  " Specify all arguments explicitly.");
2063  }
2064  if (!ci->klass) {
2065  /* bound instance method of module */
2068  return;
2069  }
2070 
2071  /* TODO: use inline cache */
2072  ci->me = rb_method_entry(ci->klass, ci->mid, &ci->defined_class);
2073  ci->call = vm_call_super_method;
2074 
2075  while (iseq && !iseq->klass) {
2076  iseq = iseq->parent_iseq;
2077  }
2078 
2079  if (ci->me && ci->me->def->type == VM_METHOD_TYPE_ISEQ && ci->me->def->body.iseq == iseq) {
2080  ci->klass = RCLASS_SUPER(ci->defined_class);
2081  ci->me = rb_method_entry(ci->klass, ci->mid, &ci->defined_class);
2082  }
2083 }
2084 
2085 /* yield */
2086 
2087 static inline int
2089 {
2090  rb_proc_t *proc;
2091 
2092  if (procval) {
2093  GetProcPtr(procval, proc);
2094  return proc->is_lambda;
2095  }
2096  else {
2097  return 0;
2098  }
2099 }
2100 
2101 static inline VALUE
2103  VALUE self, int argc, const VALUE *argv,
2104  const rb_block_t *blockargptr)
2105 {
2106  NODE *ifunc = (NODE *) block->iseq;
2107  VALUE val, arg, blockarg;
2108  int lambda = block_proc_is_lambda(block->proc);
2109 
2110  if (lambda) {
2111  arg = rb_ary_new4(argc, argv);
2112  }
2113  else if (argc == 0) {
2114  arg = Qnil;
2115  }
2116  else {
2117  arg = argv[0];
2118  }
2119 
2120  if (blockargptr) {
2121  if (blockargptr->proc) {
2122  blockarg = blockargptr->proc;
2123  }
2124  else {
2125  blockarg = rb_vm_make_proc(th, blockargptr, rb_cProc);
2126  }
2127  }
2128  else {
2129  blockarg = Qnil;
2130  }
2131 
2132  vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, self,
2133  0, VM_ENVVAL_PREV_EP_PTR(block->ep), 0,
2134  th->cfp->sp, 1, 0, 0);
2135 
2136  val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg);
2137 
2138  th->cfp++;
2139  return val;
2140 }
2141 
2142 
2143 /*--
2144  * @brief on supplied all of optional, rest and post parameters.
2145  * @pre iseq is block style (not lambda style)
2146  */
2147 static inline int
2149  int argc, VALUE *argv)
2150 {
2151  rb_num_t opt_pc = 0;
2152  int i;
2153  const int m = iseq->argc;
2154  const int r = iseq->arg_rest;
2155  int len = iseq->arg_post_len;
2156  int start = iseq->arg_post_start;
2157  int rsize = argc > m ? argc - m : 0; /* # of arguments which did not consumed yet */
2158  int psize = rsize > len ? len : rsize; /* # of post arguments */
2159  int osize = 0; /* # of opt arguments */
2160  VALUE ary;
2161 
2162  /* reserves arguments for post parameters */
2163  rsize -= psize;
2164 
2165  if (iseq->arg_opts) {
2166  const int opts = iseq->arg_opts - 1;
2167  if (rsize > opts) {
2168  osize = opts;
2169  opt_pc = iseq->arg_opt_table[opts];
2170  }
2171  else {
2172  osize = rsize;
2173  opt_pc = iseq->arg_opt_table[rsize];
2174  }
2175  }
2176  rsize -= osize;
2177 
2178  if (0) {
2179  printf(" argc: %d\n", argc);
2180  printf(" len: %d\n", len);
2181  printf("start: %d\n", start);
2182  printf("rsize: %d\n", rsize);
2183  }
2184 
2185  if (r == -1) {
2186  /* copy post argument */
2187  MEMMOVE(&argv[start], &argv[m+osize], VALUE, psize);
2188  }
2189  else {
2190  ary = rb_ary_new4(rsize, &argv[r]);
2191 
2192  /* copy post argument */
2193  MEMMOVE(&argv[start], &argv[m+rsize+osize], VALUE, psize);
2194  argv[r] = ary;
2195  }
2196 
2197  for (i=psize; i<len; i++) {
2198  argv[start + i] = Qnil;
2199  }
2200 
2201  return (int)opt_pc;
2202 }
2203 
2204 static inline int
2206  int orig_argc, VALUE *argv,
2207  const rb_block_t *blockptr)
2208 {
2209  int i;
2210  int argc = orig_argc;
2211  const int m = iseq->argc;
2212  const int min = m + iseq->arg_post_len;
2213  VALUE ary, arg0;
2214  VALUE keyword_hash = Qnil;
2215  int opt_pc = 0;
2216 
2217  th->mark_stack_len = argc;
2218 
2219  /*
2220  * yield [1, 2]
2221  * => {|a|} => a = [1, 2]
2222  * => {|a, b|} => a, b = [1, 2]
2223  */
2224  arg0 = argv[0];
2225  if (!(iseq->arg_simple & 0x02) && /* exclude {|a|} */
2226  (min > 0 || /* positional arguments exist */
2227  iseq->arg_opts > 2 || /* multiple optional arguments exist */
2228  iseq->arg_keyword != -1 || /* any keyword arguments */
2229  0) &&
2230  argc == 1 && !NIL_P(ary = rb_check_array_type(arg0))) { /* rhs is only an array */
2231  th->mark_stack_len = argc = RARRAY_LENINT(ary);
2232 
2233  CHECK_VM_STACK_OVERFLOW(th->cfp, argc);
2234 
2235  MEMCPY(argv, RARRAY_CONST_PTR(ary), VALUE, argc);
2236  }
2237  else {
2238  /* vm_push_frame current argv is at the top of sp because vm_invoke_block
2239  * set sp at the first element of argv.
2240  * Therefore when rb_check_array_type(arg0) called to_ary and called to_ary
2241  * or method_missing run vm_push_frame, it initializes local variables.
2242  * see also https://bugs.ruby-lang.org/issues/8484
2243  */
2244  argv[0] = arg0;
2245  }
2246 
2247  /* keyword argument */
2248  if (iseq->arg_keyword != -1) {
2249  argc = vm_callee_setup_keyword_arg(th, iseq, argc, min, argv, &keyword_hash);
2250  }
2251 
2252  for (i=argc; i<m; i++) {
2253  argv[i] = Qnil;
2254  }
2255 
2256  if (iseq->arg_rest == -1 && iseq->arg_opts == 0) {
2257  const int arg_size = iseq->arg_size;
2258  if (arg_size < argc) {
2259  /*
2260  * yield 1, 2
2261  * => {|a|} # truncate
2262  */
2263  th->mark_stack_len = argc = arg_size;
2264  }
2265  }
2266  else {
2267  int r = iseq->arg_rest;
2268 
2269  if (iseq->arg_post_len ||
2270  iseq->arg_opts) { /* TODO: implement simple version for (iseq->arg_post_len==0 && iseq->arg_opts > 0) */
2271  opt_pc = vm_yield_setup_block_args_complex(th, iseq, argc, argv);
2272  }
2273  else {
2274  if (argc < r) {
2275  /* yield 1
2276  * => {|a, b, *r|}
2277  */
2278  for (i=argc; i<r; i++) {
2279  argv[i] = Qnil;
2280  }
2281  argv[r] = rb_ary_new();
2282  }
2283  else {
2284  argv[r] = rb_ary_new4(argc-r, &argv[r]);
2285  }
2286  }
2287 
2288  th->mark_stack_len = iseq->arg_size;
2289  }
2290 
2291  /* keyword argument */
2292  if (iseq->arg_keyword != -1) {
2293  int arg_keywords_end = iseq->arg_keyword - (iseq->arg_block != -1);
2294  for (i = iseq->arg_keywords; 0 < i; i--) {
2295  argv[arg_keywords_end - i] = Qnil;
2296  }
2297  argv[iseq->arg_keyword] = keyword_hash;
2298  }
2299 
2300  /* {|&b|} */
2301  if (iseq->arg_block != -1) {
2302  VALUE procval = Qnil;
2303 
2304  if (blockptr) {
2305  if (blockptr->proc == 0) {
2306  procval = rb_vm_make_proc(th, blockptr, rb_cProc);
2307  }
2308  else {
2309  procval = blockptr->proc;
2310  }
2311  }
2312 
2313  argv[iseq->arg_block] = procval;
2314  }
2315 
2316  th->mark_stack_len = 0;
2317  return opt_pc;
2318 }
2319 
2320 static inline int
2322  int argc, VALUE *argv, const rb_block_t *blockptr, int lambda)
2323 {
2324  if (0) { /* for debug */
2325  printf(" argc: %d\n", argc);
2326  printf("iseq argc: %d\n", iseq->argc);
2327  printf("iseq opts: %d\n", iseq->arg_opts);
2328  printf("iseq rest: %d\n", iseq->arg_rest);
2329  printf("iseq post: %d\n", iseq->arg_post_len);
2330  printf("iseq blck: %d\n", iseq->arg_block);
2331  printf("iseq smpl: %d\n", iseq->arg_simple);
2332  printf(" lambda: %s\n", lambda ? "true" : "false");
2333  }
2334 
2335  if (lambda) {
2336  /* call as method */
2337  rb_call_info_t ci_entry;
2338  ci_entry.flag = 0;
2339  ci_entry.argc = argc;
2340  ci_entry.blockptr = (rb_block_t *)blockptr;
2341  vm_callee_setup_arg(th, &ci_entry, iseq, argv, 1);
2342  return ci_entry.aux.opt_pc;
2343  }
2344  else {
2345  return vm_yield_setup_block_args(th, iseq, argc, argv, blockptr);
2346  }
2347 }
2348 
2349 static VALUE
2351 {
2352  const rb_block_t *block = VM_CF_BLOCK_PTR(reg_cfp);
2353  rb_iseq_t *iseq;
2354  VALUE type = GET_ISEQ()->local_iseq->type;
2355 
2356  if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) {
2357  rb_vm_localjump_error("no block given (yield)", Qnil, 0);
2358  }
2359  iseq = block->iseq;
2360 
2361  if (UNLIKELY(ci->flag & VM_CALL_ARGS_SPLAT)) {
2362  vm_caller_setup_args(th, GET_CFP(), ci);
2363  }
2364 
2365  if (BUILTIN_TYPE(iseq) != T_NODE) {
2366  int opt_pc;
2367  const int arg_size = iseq->arg_size;
2368  int is_lambda = block_proc_is_lambda(block->proc);
2369  VALUE * const rsp = GET_SP() - ci->argc;
2370  SET_SP(rsp);
2371 
2372  opt_pc = vm_yield_setup_args(th, iseq, ci->argc, rsp, 0, is_lambda);
2373 
2374  vm_push_frame(th, iseq,
2376  block->self,
2377  block->klass,
2378  VM_ENVVAL_PREV_EP_PTR(block->ep),
2379  iseq->iseq_encoded + opt_pc,
2380  rsp + arg_size,
2381  iseq->local_size - arg_size, 0, iseq->stack_max);
2382 
2383  return Qundef;
2384  }
2385  else {
2386  VALUE val = vm_yield_with_cfunc(th, block, block->self, ci->argc, STACK_ADDR_FROM_TOP(ci->argc), 0);
2387  POPN(ci->argc); /* TODO: should put before C/yield? */
2388  return val;
2389  }
2390 }
2391 
2392 static VALUE
2394 {
2395  rb_block_t *blockptr;
2396  rb_thread_t *th = GET_THREAD();
2398 
2399  if (cfp == 0) {
2400  rb_bug("vm_make_proc_with_iseq: unreachable");
2401  }
2402 
2403  blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
2404  blockptr->iseq = blockiseq;
2405  blockptr->proc = 0;
2406 
2407  return rb_vm_make_proc(th, blockptr, rb_cProc);
2408 }
2409 
2410 static VALUE
2412 {
2414  return rb_proc_call_with_block(proc, 0, 0, Qnil);
2415 }
2416 
2417 static VALUE
2419 {
2420  union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)data;
2421  is->once.running_thread = NULL;
2422  return Qnil;
2423 }
VALUE data
Definition: tcltklib.c:3360
rb_serial_t class_serial
Definition: vm_core.h:164
VALUE rb_reg_match_last(VALUE)
Definition: re.c:1604
#define RB_TYPE_P(obj, type)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: ripper.y:20
#define VM_FRAME_MAGIC_BLOCK
Definition: vm_core.h:760
rb_control_frame_t * cfp
Definition: vm_core.h:531
#define VM_CALL_ARGS_BLOCKARG
Definition: vm_core.h:745
#define DEFAULT_SPECIAL_VAR_COUNT
Definition: iseq.h:132
struct rb_block_struct * blockptr
Definition: vm_core.h:173
#define UNDEFINED_METHOD_ENTRY_P(me)
Definition: method.h:110
#define RUBY_VM_CHECK_INTS(th)
Definition: vm_core.h:991
int arg_simple
Definition: vm_core.h:275
#define rb_check_arity
static VALUE opt_eq_func(VALUE recv, VALUE obj, CALL_INFO ci)
static VALUE vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
int register char * block
Definition: crypt.c:949
VALUE sym
Definition: tkutil.c:1299
VALUE rb_reg_last_match(VALUE)
Definition: re.c:1541
static VALUE call_cfunc_0(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
VP_EXPORT int
Definition: bigdecimal.c:5172
NODE *const cref_stack
Definition: vm_core.h:315
rb_funcall2(argv[0], id_yield, argc-1, argv+1)
static void argument_error(const rb_iseq_t *iseq, int miss_argc, int min_argc, int max_argc)
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1179
void rb_bug(const char *fmt,...)
Definition: error.c:327
rb_method_type_t type
Definition: method.h:79
VALUE * root_lep
Definition: vm_core.h:557
#define RB_OBJ_WRITE(a, slot, b)
static VALUE vm_get_iclass(rb_control_frame_t *cfp, VALUE klass)
static VALUE vm_call_opt_call(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
rb_method_attr_t attr
Definition: method.h:84
#define rb_hash_lookup
Definition: tcltklib.c:269
RUBY_EXTERN VALUE rb_cModule
Definition: ripper.y:1580
static VALUE VALUE th
Definition: tcltklib.c:2944
static VALUE vm_call_general(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
#define VM_CALL_FCALL
Definition: vm_core.h:746
#define VM_ENVVAL_PREV_EP_PTR(v)
Definition: vm_core.h:815
Definition: constant.h:19
static VALUE vm_call_bmethod(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
#define VM_FRAME_FLAG_FINISH
Definition: vm_core.h:776
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:2612
static int vm_yield_setup_block_args(rb_thread_t *th, const rb_iseq_t *iseq, int orig_argc, VALUE *argv, const rb_block_t *blockptr)
rb_serial_t method_state
Definition: vm_core.h:163
ID * arg_keyword_table
Definition: vm_core.h:287
#define VM_FRAME_TYPE_FINISH_P(cfp)
Definition: vm_core.h:778
#define UNLIMITED_ARGUMENTS
#define FL_TEST(x, f)
unsigned long end
Definition: iseq.h:66
#define TAG_THROW
Definition: eval_intern.h:194
#define VM_FRAME_MAGIC_CFUNC
Definition: vm_core.h:763
static int max(int a, int b)
Definition: strftime.c:141
int st_lookup(st_table *, st_data_t, st_data_t *)
static VALUE find_refinement(VALUE refinements, VALUE klass)
#define d1
static rb_control_frame_t * vm_push_frame(rb_thread_t *th, const rb_iseq_t *iseq, VALUE type, VALUE self, VALUE klass, VALUE specval, const VALUE *pc, VALUE *sp, int local_size, const rb_method_entry_t *me, size_t stack_max)
Definition: vm_insnhelper.c:34
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:825
#define GetProcPtr(obj, ptr)
Definition: vm_core.h:697
static VALUE vm_get_const_base(const rb_iseq_t *iseq, const VALUE *ep)
rb_method_flag_t flag
Definition: method.h:98
#define RUBY_VM_NORMAL_ISEQ_P(ptr)
Definition: vm_core.h:835
#define FLOAT_REDEFINED_OP_FLAG
#define T_ICLASS
VALUE proc
Definition: tcltklib.c:2955
rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts))
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1909
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
static int vm_callee_setup_keyword_arg(rb_thread_t *th, const rb_iseq_t *iseq, int argc, int m, VALUE *orig_argv, VALUE *kwd)
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1880
vm_check_match_type
Definition: vm_core.h:735
union rb_method_definition_struct::@149 body
rb_iseq_t * iseq
Definition: vm_core.h:466
#define TAG_BREAK
Definition: eval_intern.h:189
static int block_proc_is_lambda(const VALUE procval)
static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
#define rb_check_frozen(obj)
#define T_NODE
#define RUBY_EVENT_C_RETURN
rb_method_entry_t * rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
Definition: vm_method.c:706
static VALUE call_cfunc_10(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
struct rb_method_entry_struct * orig_me
Definition: method.h:92
VALUE target
Definition: tcltklib.c:5510
#define RFLOAT_VALUE(v)
#define RCLASS_ORIGIN(c)
static void vm_expandarray(rb_control_frame_t *cfp, VALUE ary, rb_num_t num, int flag)
#define sysstack_error
Definition: vm_core.h:901
Real * a
Definition: bigdecimal.c:1198
VALUE rb_eTypeError
Definition: error.c:548
RB_GC_GUARD(args)
VALUE exc
Definition: tcltklib.c:3088
static VALUE vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
VALUE(* call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci)
Definition: vm_core.h:182
#define CLASS_OF(v)
#define UNDEF
NIL_P(eventloop_thread)
Definition: tcltklib.c:4056
static const rb_method_cfunc_t * vm_method_cfunc_entry(const rb_method_entry_t *me)
#define ROBJECT_IVPTR(o)
#define T_ARRAY
#define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)
Definition: vm_core.h:838
#define VM_ENVVAL_BLOCK_PTR(v)
Definition: vm_core.h:813
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
Definition: vm.c:656
VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE)
Definition: proc.c:756
static VALUE vm_call_cfunc_with_frame(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
RUBY_EXTERN VALUE rb_cFloat
Definition: ripper.y:1574
static VALUE vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
#define VM_FRAME_MAGIC_METHOD
Definition: vm_core.h:759
struct rb_iseq_struct * local_iseq
Definition: vm_core.h:297
#define MEMMOVE(p1, p2, type, n)
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
#define VM_FRAME_TYPE(cfp)
Definition: vm_core.h:772
static void lep_svar_set(rb_thread_t *th, VALUE *lep, rb_num_t key, VALUE val)
return Qtrue
Definition: tcltklib.c:9618
VALUE rb_obj_class(VALUE)
Definition: object.c:226
ID called_id
Definition: method.h:101
#define NEW_CREF(a)
VALUE entry[3]
Definition: ossl_x509name.c:99
#define VM_FRAME_MAGIC_IFUNC
Definition: vm_core.h:765
#define VM_PROFILE_UP(x)
int index
Definition: tcltklib.c:4468
#define VM_CALL_ARGS_SPLAT
Definition: vm_core.h:744
const VALUE klass
Definition: vm_core.h:316
#define SET_SP(x)
void rb_vm_localjump_error(const char *mesg, VALUE value, int reason)
Definition: vm.c:1094
size_t stack_max
Definition: vm_core.h:289
#define FIXNUM_2_P(a, b)
int arg_keyword
Definition: vm_core.h:283
VALUE rb_eSecurityError
Definition: error.c:557
#define rb_ary_new4
#define SDR()
Definition: vm_core.h:853
ID defined_method_id
Definition: vm_core.h:319
#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)
Definition: vm_core.h:831
#define STACK_ADDR_FROM_TOP(n)
Definition: vm_insnhelper.h:86
r
Definition: bigdecimal.c:1212
#define GET_GLOBAL_METHOD_STATE()
tmp
Definition: enum.c:447
#define TAG_RAISE
Definition: eval_intern.h:193
static VALUE vm_getinstancevariable(VALUE obj, ID id, IC ic)
static VALUE vm_once_clear(VALUE data)
VALUE rb_reg_nth_match(int, VALUE)
Definition: re.c:1515
static VALUE lep_svar_get(rb_thread_t *th, VALUE *lep, rb_num_t key)
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, const rb_block_t *blockptr)
Definition: vm.c:897
static VALUE * VM_CF_LEP(rb_control_frame_t *cfp)
Definition: vm.c:40
#define DEC_SP(x)
static int vm_yield_setup_args(rb_thread_t *const th, const rb_iseq_t *iseq, int argc, VALUE *argv, const rb_block_t *blockptr, int lambda)
static VALUE vm_getspecial(rb_thread_t *th, VALUE *lep, rb_num_t key, rb_num_t type)
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: ripper.c:17365
#define ID2SYM(x)
static VALUE vm_search_const_defined_class(const VALUE cbase, ID id)
if(args--[1]==0)
Definition: array.c:3187
int arg_post_len
Definition: vm_core.h:279
memo state
Definition: enum.c:2432
#define LIKELY(x)
Definition: vm_core.h:108
#define T_OBJECT
VALUE rb_reg_match_post(VALUE)
Definition: re.c:1586
static VALUE vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
#define VM_CALL_VCALL
Definition: vm_core.h:747
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
static VALUE call_cfunc_11(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
flag
Definition: tcltklib.c:2046
static VALUE vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:2542
i
Definition: enum.c:446
VALUE ary
Definition: enum.c:674
#define RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, klass, id)
Definition: probes_helper.h:61
static void vm_check_if_namespace(VALUE klass)
static void vm_caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
VALUE rb_autoload_load(VALUE, ID)
Definition: variable.c:1769
Definition: ripper.y:240
enum iseq_catch_table_entry::catch_type type
#define NORETURN(x)
Definition: ruby.h:33
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
static VALUE vm_call_ivar(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
enum rb_method_definition_struct::@149::method_optimized_type optimize_type
#define GET_CFP()
#define rb_exc_new3
VALUE rb_extract_keywords(VALUE *orighash)
Definition: class.c:1894
enum rb_iseq_struct::iseq_type type
static VALUE vm_make_proc_with_iseq(rb_iseq_t *blockiseq)
static NODE * vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
rb_method_cfunc_t cfunc
Definition: method.h:83
int arg_keyword_required
Definition: vm_core.h:286
static VALUE call_cfunc_15(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
BDIGIT m
Definition: bigdecimal.c:5209
static VALUE make_no_method_exception(VALUE exc, const char *format, VALUE obj, int argc, const VALUE *argv)
Definition: vm_eval.c:642
return Qfalse
Definition: tcltklib.c:6790
#define FIXNUM_P(f)
#define SAVE_RESTORE_CI(expr, ci)
#define RARRAY_LEN(a)
#define ROBJECT_NUMIV(o)
#define Qnil
Definition: enum.c:67
#define StringValuePtr(v)
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
Definition: vm.c:247
#define val
Definition: tcltklib.c:1935
void rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv, VALUE obj, int call_status)
Definition: vm_eval.c:736
rb_iseq_t * block_iseq
Definition: vm_core.h:453
VALUE rb_eRuntimeError
Definition: error.c:547
#define POPN(n)
Definition: vm_insnhelper.h:84
static VALUE char * str
Definition: tcltklib.c:3539
#define RARRAY_CONST_PTR(a)
VALUE rb_ary_new(void)
Definition: array.c:499
#define FLONUM_2_P(a, b)
static int vm_yield_setup_block_args_complex(rb_thread_t *th, const rb_iseq_t *iseq, int argc, VALUE *argv)
unsigned long ID
Definition: ripper.y:89
int argc
argument information
Definition: vm_core.h:274
#define RCLASS_SUPER(c)
#define CHECK_CMP_NAN(a, b)
rb_iseq_t * iseq
Definition: vm_core.h:448
int arg_post_start
Definition: vm_core.h:280
#define VMDEBUG
Definition: vm_dump.c:19
#define UNLIKELY(x)
Definition: vm_core.h:109
VALUE rb_eNoMethodError
Definition: error.c:556
static VALUE VALUE obj
Definition: tcltklib.c:3150
#define FIX2INT(x)
static VALUE vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VALUE throwobj)
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:794
VALUE value
Definition: ripper.y:246
VALUE * arg_opt_table
Definition: vm_core.h:282
#define ANYARGS
#define RBASIC_CLASS(obj)
int arg_keywords
Definition: vm_core.h:285
static VALUE call_cfunc_2(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
Definition: vm_core.h:141
static VALUE vm_call_attrset(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
int rb_public_const_defined_from(VALUE klass, ID id)
Definition: variable.c:2139
static int vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq, VALUE sigval, rb_call_info_t *ci)
#define RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, klass, id)
Definition: probes_helper.h:64
Definition: method.h:97
VALUE rb_check_hash_type(VALUE)
Definition: hash.c:597
rb_iseq_t * blockiseq
Definition: vm_core.h:160
static VALUE vm_call_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
static int check_cfunc(const rb_method_entry_t *me, VALUE(*func)())
int err
Definition: win32.c:114
static VALUE call_cfunc_1(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
#define ALLOCA_N(type, n)
static VALUE call_cfunc_9(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
static VALUE call_cfunc_3(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
static int VALUE key
Definition: tkutil.c:265
int len
Definition: enumerator.c:1332
rb_method_entry_t * rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr)
Definition: vm_method.c:617
VALUE(* func)(ANYARGS)
Definition: method.h:66
#define TOPN(n)
Definition: vm_insnhelper.h:83
VALUE klass
Definition: method.h:102
unsigned long start
Definition: iseq.h:65
unsigned long rb_num_t
Definition: vm_core.h:124
VALUE arg
Definition: enum.c:2427
#define rb_long2int(n)
#define TAG_RETURN
Definition: eval_intern.h:188
#define VM_CALL_SUPER
Definition: vm_core.h:749
Definition: vm_core.h:133
gz level
Definition: zlib.c:2264
VALUE rb_ary_to_ary(VALUE obj)
Definition: array.c:1530
VALUE * argv
Definition: tcltklib.c:1969
rb_method_entry_t * rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
Definition: vm_method.c:688
rb_iseq_t *const iseq
Definition: method.h:82
static rb_block_t * VM_CF_BLOCK_PTR(rb_control_frame_t *cfp)
Definition: vm.c:52
#define VM_EP_PREV_EP(ep)
Definition: vm_core.h:818
static VALUE vm_call0(rb_thread_t *, VALUE, ID, int, const VALUE *, const rb_method_entry_t *, VALUE)
static VALUE call_cfunc_13(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
int rb_const_defined(VALUE, ID)
Definition: variable.c:2127
#define CI_SET_FASTPATH(ci, func, enabled)
VALUE v
Definition: enum.c:845
static VALUE vm_call_opt_send(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
struct rb_iseq_struct * parent_iseq
Definition: vm_core.h:296
#define FIXNUM_REDEFINED_OP_FLAG
static int min(int a, int b)
Definition: strftime.c:131
VALUE rb_vm_backtrace_object(void)
Definition: vm_backtrace.c:536
union RNode::@114 u3
int type
Definition: tcltklib.c:112
VALUE * iseq_encoded
Definition: vm_core.h:226
int rb_autoloading_value(VALUE mod, ID id, VALUE *value)
Definition: variable.c:1715
int argc
Definition: tcltklib.c:1968
static VALUE * vm_base_ptr(rb_control_frame_t *cfp)
static void vm_pop_frame(rb_thread_t *th)
Definition: vm_insnhelper.c:99
int catch_table_size
Definition: vm_core.h:293
Definition: iseq.h:55
int rb_const_defined_at(VALUE, ID)
Definition: variable.c:2133
Definition: ripper.y:85
#define VM_CALL_OPT_SEND
Definition: vm_core.h:750
static NODE * lep_svar_place(rb_thread_t *th, VALUE *lep)
static VALUE check_match(VALUE pattern, VALUE target, enum vm_check_match_type type)
static VALUE call_cfunc_m2(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1127
static VALUE vm_search_normal_superclass(VALUE klass)
#define isnan(x)
Definition: win32.h:376
Definition: iseq.h:60
static VALUE call_cfunc_12(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
static VALUE vm_call_bmethod_body(rb_thread_t *th, rb_call_info_t *ci, const VALUE *argv)
VALUE(* invoker)(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
Definition: method.h:67
static VALUE call_cfunc_5(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
static rb_control_frame_t * current_method_entry(rb_thread_t *th, rb_control_frame_t *cfp)
char ** av
Definition: tcltklib.c:8870
static VALUE double_cmp_le(double a, double b)
VALUE flags
Definition: ripper.y:241
static VALUE rb_arg_error_new(int argc, int min, int max)
#define RCLASS_SERIAL(c)
rb_serial_t ic_serial
Definition: vm_core.h:134
RUBY_EXTERN VALUE rb_cString
Definition: ripper.y:1591
Real * b
Definition: bigdecimal.c:1198
static VALUE vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
return ptr
Definition: tcltklib.c:789
VALUE rb_equal_opt(VALUE obj1, VALUE obj2)
static VALUE double_cmp_gt(double a, double b)
VALUE rb_obj_is_proc(VALUE)
Definition: proc.c:94
#define NEW_THROW_OBJECT(val, pt, st)
Definition: eval_intern.h:198
#define RCLASS_CONST_TBL(c)
#define MEMCPY(p1, p2, type, n)
static void vm_search_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
static VALUE vm_once_exec(rb_iseq_t *iseq)
static VALUE call_cfunc_7(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
ID rb_to_id(VALUE)
Definition: string.c:8734
#define NEW_IF(c, t, e)
static VALUE double_cmp_ge(double a, double b)
VALUE rb_obj_equal(VALUE obj1, VALUE obj2)
Definition: object.c:142
unsigned long sp
Definition: iseq.h:68
#define RMODULE_IS_OVERLAID
#define VM_FRAME_MAGIC_LAMBDA
Definition: vm_core.h:767
int is_lambda
Definition: vm_core.h:707
int mark_stack_len
Definition: vm_core.h:631
static void vm_setinstancevariable(VALUE obj, ID id, VALUE val, IC ic)
int arg_keyword_check
Definition: vm_core.h:284
#define SYMBOL_P(x)
static VALUE vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
#define FL_SINGLETON
VALUE root_svar
Definition: vm_core.h:558
rb_block_t block
Definition: vm_core.h:701
#define Qundef
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:646
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1585
#define T_CLASS
static VALUE call_cfunc_m1(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
size_t index
Definition: vm_core.h:136
rb_method_definition_t * def
Definition: method.h:100
static VALUE vm_call_method_missing(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
const rb_method_entry_t * me
Definition: vm_core.h:455
#define INC_SP(x)
static void vm_search_method(rb_call_info_t *ci, VALUE recv)
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:632
void rb_error_arity(int argc, int min, int max)
static VALUE call_cfunc_14(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
#define STRING_REDEFINED_OP_FLAG
VALUE rb_reg_match_pre(VALUE)
Definition: re.c:1559
struct iseq_catch_table_entry * catch_table
Definition: vm_core.h:292
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1561
static int vm_callee_setup_arg_complex(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t *iseq, VALUE *orig_argv)
#define RBASIC(obj)
#define RARRAY_LENINT(ary)
klass
Definition: tcltklib.c:3496
int local_size
Definition: vm_core.h:239
static VALUE vm_get_cvar_base(NODE *cref, rb_control_frame_t *cfp)
struct rb_thread_struct * running_thread
Definition: vm_core.h:143
#define GET_EP()
static VALUE call_cfunc_6(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
Definition: ripper.y:86
static VALUE vm_call_iseq_setup(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
#define NOEX_SAFE(n)
Definition: method.h:41
#define VM_CALL_TAILCALL
Definition: vm_core.h:748
rb_ivar_set(yielder, id_memo, LONG2NUM(++count))
static VALUE call_cfunc_4(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
union RNode::@113 u2
const rb_method_entry_t * passed_bmethod_me
Definition: vm_core.h:545
#define T_MODULE
rb_call_info_t * passed_ci
Definition: vm_core.h:548
#define EXEC_EVENT_HOOK(th_, flag_, self_, id_, klass_, data_)
Definition: vm_core.h:1036
static NODE * vm_get_cref0(const rb_iseq_t *iseq, const VALUE *ep)
NODE * rb_vm_get_cref(const rb_iseq_t *, const VALUE *)
unsigned long cont
Definition: iseq.h:67
RUBY_EXTERN VALUE rb_cProc
Definition: ripper.y:1584
VALUE rb_hash_new(void)
Definition: hash.c:307
const char * rb_id2name(ID id)
Definition: ripper.c:17271
size_t stack_size
Definition: vm_core.h:530
#define GET_SP()
#define BUILTIN_TYPE(x)
#define PRIsVALUE
VALUE iseq
Definition: iseq.h:64
VALUE opts
Definition: tcltklib.c:6160
unsigned long VALUE
Definition: ripper.y:88
void rb_warning(const char *fmt,...)
Definition: error.c:236
static void vm_callee_setup_arg(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t *iseq, VALUE *argv, int is_lambda)
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:800
union rb_call_info_struct::@189 aux
static void vm_super_outside(void)
#define GET_ISEQ()
#define ROBJECT_IV_INDEX_TBL(o)
static VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class, int argc, const VALUE *argv, const rb_block_t *blockptr)
Definition: vm.c:869
static rb_control_frame_t * vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
#define RMODULE_IS_REFINEMENT
static VALUE vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, VALUE orig_klass, ID id, int is_defined)
VALUE rb_public_const_get_from(VALUE klass, ID id)
Definition: variable.c:1892
#define CHECK_VM_STACK_OVERFLOW(cfp, margin)
Definition: vm_core.h:912
#define SPECIAL_CONST_P(x)
#define BASIC_OP_UNREDEFINED_P(op, klass)
static VALUE vm_setivar(VALUE obj, ID id, VALUE val, IC ic, rb_call_info_t *ci, int is_attr)
struct iseq_inline_storage_entry::@188 once
#define rb_intern(str)
#define stat(path, st)
Definition: win32.h:213
#define NODE_FL_CREF_PUSHED_BY_EVAL
VALUE j
Definition: enum.c:1347
#define NULL
Definition: _sdbm.c:102
#define T_DATA
#define RCLASS_REFINED_CLASS(c)
union RNode::@112 u1
int method_missing_reason
Definition: vm_core.h:649
#define GET_THROWOBJ_STATE(obj)
Definition: eval_intern.h:207
#define VM_EP_LEP_P(ep)
Definition: vm_core.h:820
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:929
#define RUBY_EVENT_C_CALL
void rb_warn(const char *fmt,...)
Definition: error.c:223
#define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
Definition: vm_core.h:910
#define SYM2ID(x)
#define bp()
Definition: vm_debug.h:25
VALUE rb_eArgError
Definition: error.c:549
#define COPY_CREF_OMOD(c1, c2)
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2652
static VALUE vm_getivar(VALUE obj, ID id, IC ic, rb_call_info_t *ci, int is_attr)
static VALUE call_cfunc_8(VALUE(*func)(ANYARGS), VALUE recv, int argc, const VALUE *argv)
void rb_vm_rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **new_cref_ptr)
static VALUE double_cmp_lt(double a, double b)
static void vm_stackoverflow(void)
Definition: vm_insnhelper.c:28
const rb_method_entry_t * me
Definition: vm_core.h:168
#define TAG_RETRY
Definition: eval_intern.h:191
VALUE * ep
Definition: vm_core.h:465
union iseq_inline_cache_entry::@187 ic_value
static VALUE vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block, VALUE self, int argc, const VALUE *argv, const rb_block_t *blockargptr)
VALUE rb_inspect(VALUE)
Definition: object.c:470
#define RMODULE_INCLUDED_INTO_REFINEMENT