Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
vm.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  vm.c -
4 
5  $Author$
6 
7  Copyright (C) 2004-2007 Koichi Sasada
8 
9 **********************************************************************/
10 
11 #include "internal.h"
12 #include "ruby/vm.h"
13 #include "ruby/st.h"
14 
15 #define vm_exec rb_vm_exec
16 
17 #include "gc.h"
18 #include "vm_core.h"
19 #include "vm_debug.h"
20 #include "iseq.h"
21 #include "eval_intern.h"
22 #include "builtin.h"
23 
24 #ifndef MJIT_HEADER
25 #include "probes.h"
26 #else
27 #include "probes.dmyh"
28 #endif
29 #include "probes_helper.h"
30 
31 VALUE rb_str_concat_literals(size_t, const VALUE*);
32 
33 /* :FIXME: This #ifdef is because we build pch in case of mswin and
34  * not in case of other situations. That distinction might change in
35  * a future. We would better make it detectable in something better
36  * than just _MSC_VER. */
37 #ifdef _MSC_VER
39 #else
41 #endif
43 
44 PUREFUNC(static inline const VALUE *VM_EP_LEP(const VALUE *));
45 static inline const VALUE *
46 VM_EP_LEP(const VALUE *ep)
47 {
48  while (!VM_ENV_LOCAL_P(ep)) {
49  ep = VM_ENV_PREV_EP(ep);
50  }
51  return ep;
52 }
53 
54 static inline const rb_control_frame_t *
55 rb_vm_search_cf_from_ep(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE * const ep)
56 {
57  if (!ep) {
58  return NULL;
59  }
60  else {
61  const rb_control_frame_t * const eocfp = RUBY_VM_END_CONTROL_FRAME(ec); /* end of control frame pointer */
62 
63  while (cfp < eocfp) {
64  if (cfp->ep == ep) {
65  return cfp;
66  }
68  }
69 
70  return NULL;
71  }
72 }
73 
74 const VALUE *
76 {
77  return VM_EP_LEP(ep);
78 }
79 
80 PUREFUNC(static inline const VALUE *VM_CF_LEP(const rb_control_frame_t * const cfp));
81 static inline const VALUE *
82 VM_CF_LEP(const rb_control_frame_t * const cfp)
83 {
84  return VM_EP_LEP(cfp->ep);
85 }
86 
87 static inline const VALUE *
88 VM_CF_PREV_EP(const rb_control_frame_t * const cfp)
89 {
90  return VM_ENV_PREV_EP(cfp->ep);
91 }
92 
93 PUREFUNC(static inline VALUE VM_CF_BLOCK_HANDLER(const rb_control_frame_t * const cfp));
94 static inline VALUE
95 VM_CF_BLOCK_HANDLER(const rb_control_frame_t * const cfp)
96 {
97  const VALUE *ep = VM_CF_LEP(cfp);
98  return VM_ENV_BLOCK_HANDLER(ep);
99 }
100 
101 int
103 {
104  return VM_FRAME_CFRAME_KW_P(cfp);
105 }
106 
107 /* -- Remove In 3.0 -- */
108 int
110 {
111  return VM_FRAME_CFRAME_EMPTY_KW_P(cfp);
112 }
113 
114 VALUE
116 {
117  return VM_CF_BLOCK_HANDLER(cfp);
118 }
119 
120 #if VM_CHECK_MODE > 0
121 static int
122 VM_CFP_IN_HEAP_P(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
123 {
124  const VALUE *start = ec->vm_stack;
125  const VALUE *end = (VALUE *)ec->vm_stack + ec->vm_stack_size;
126  VM_ASSERT(start != NULL);
127 
128  if (start <= (VALUE *)cfp && (VALUE *)cfp < end) {
129  return FALSE;
130  }
131  else {
132  return TRUE;
133  }
134 }
135 
136 static int
137 VM_EP_IN_HEAP_P(const rb_execution_context_t *ec, const VALUE *ep)
138 {
139  const VALUE *start = ec->vm_stack;
140  const VALUE *end = (VALUE *)ec->cfp;
141  VM_ASSERT(start != NULL);
142 
143  if (start <= ep && ep < end) {
144  return FALSE;
145  }
146  else {
147  return TRUE;
148  }
149 }
150 
151 int
152 vm_ep_in_heap_p_(const rb_execution_context_t *ec, const VALUE *ep)
153 {
154  if (VM_EP_IN_HEAP_P(ec, ep)) {
155  VALUE envval = ep[VM_ENV_DATA_INDEX_ENV]; /* VM_ENV_ENVVAL(ep); */
156 
157  if (envval != Qundef) {
158  const rb_env_t *env = (const rb_env_t *)envval;
159 
160  VM_ASSERT(vm_assert_env(envval));
161  VM_ASSERT(VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED));
162  VM_ASSERT(env->ep == ep);
163  }
164  return TRUE;
165  }
166  else {
167  return FALSE;
168  }
169 }
170 
171 int
172 rb_vm_ep_in_heap_p(const VALUE *ep)
173 {
174  const rb_execution_context_t *ec = GET_EC();
175  if (ec->vm_stack == NULL) return TRUE;
176  return vm_ep_in_heap_p_(ec, ep);
177 }
178 #endif
179 
180 static struct rb_captured_block *
181 VM_CFP_TO_CAPTURED_BLOCK(const rb_control_frame_t *cfp)
182 {
183  VM_ASSERT(!VM_CFP_IN_HEAP_P(GET_EC(), cfp));
184  return (struct rb_captured_block *)&cfp->self;
185 }
186 
187 static rb_control_frame_t *
188 VM_CAPTURED_BLOCK_TO_CFP(const struct rb_captured_block *captured)
189 {
190  rb_control_frame_t *cfp = ((rb_control_frame_t *)((VALUE *)(captured) - 3));
191  VM_ASSERT(!VM_CFP_IN_HEAP_P(GET_EC(), cfp));
192  VM_ASSERT(sizeof(rb_control_frame_t)/sizeof(VALUE) == 7 + VM_DEBUG_BP_CHECK ? 1 : 0);
193  return cfp;
194 }
195 
196 static int
197 VM_BH_FROM_CFP_P(VALUE block_handler, const rb_control_frame_t *cfp)
198 {
199  const struct rb_captured_block *captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
200  return VM_TAGGED_PTR_REF(block_handler, 0x03) == captured;
201 }
202 
203 static VALUE
204 vm_passed_block_handler(rb_execution_context_t *ec)
205 {
208  vm_block_handler_verify(block_handler);
209  return block_handler;
210 }
211 
212 static rb_cref_t *
213 vm_cref_new0(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval, int use_prev_prev)
214 {
215  VALUE refinements = Qnil;
216  int omod_shared = FALSE;
217  rb_cref_t *cref;
218 
219  /* scope */
220  union {
222  VALUE value;
223  } scope_visi;
224 
225  scope_visi.visi.method_visi = visi;
226  scope_visi.visi.module_func = module_func;
227 
228  /* refinements */
229  if (prev_cref != NULL && prev_cref != (void *)1 /* TODO: why CREF_NEXT(cref) is 1? */) {
230  refinements = CREF_REFINEMENTS(prev_cref);
231 
232  if (!NIL_P(refinements)) {
233  omod_shared = TRUE;
234  CREF_OMOD_SHARED_SET(prev_cref);
235  }
236  }
237 
238  cref = (rb_cref_t *)rb_imemo_new(imemo_cref, klass, (VALUE)(use_prev_prev ? CREF_NEXT(prev_cref) : prev_cref), scope_visi.value, refinements);
239 
240  if (pushed_by_eval) CREF_PUSHED_BY_EVAL_SET(cref);
241  if (omod_shared) CREF_OMOD_SHARED_SET(cref);
242 
243  return cref;
244 }
245 
246 static rb_cref_t *
247 vm_cref_new(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval)
248 {
249  return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, FALSE);
250 }
251 
252 static rb_cref_t *
253 vm_cref_new_use_prev(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval)
254 {
255  return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, TRUE);
256 }
257 
258 static int
259 ref_delete_symkey(VALUE key, VALUE value, VALUE unused)
260 {
261  return SYMBOL_P(key) ? ST_DELETE : ST_CONTINUE;
262 }
263 
264 static rb_cref_t *
265 vm_cref_dup(const rb_cref_t *cref)
266 {
267  VALUE klass = CREF_CLASS(cref);
268  const rb_scope_visibility_t *visi = CREF_SCOPE_VISI(cref);
269  rb_cref_t *next_cref = CREF_NEXT(cref), *new_cref;
270  int pushed_by_eval = CREF_PUSHED_BY_EVAL(cref);
271 
272  new_cref = vm_cref_new(klass, visi->method_visi, visi->module_func, next_cref, pushed_by_eval);
273 
274  if (!NIL_P(CREF_REFINEMENTS(cref))) {
275  VALUE ref = rb_hash_dup(CREF_REFINEMENTS(cref));
276  rb_hash_foreach(ref, ref_delete_symkey, Qnil);
277  CREF_REFINEMENTS_SET(new_cref, ref);
278  CREF_OMOD_SHARED_UNSET(new_cref);
279  }
280 
281  return new_cref;
282 }
283 
284 static rb_cref_t *
285 vm_cref_new_toplevel(rb_execution_context_t *ec)
286 {
287  rb_cref_t *cref = vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE /* toplevel visibility is private */, FALSE, NULL, FALSE);
288  VALUE top_wrapper = rb_ec_thread_ptr(ec)->top_wrapper;
289 
290  if (top_wrapper) {
291  cref = vm_cref_new(top_wrapper, METHOD_VISI_PRIVATE, FALSE, cref, FALSE);
292  }
293 
294  return cref;
295 }
296 
297 rb_cref_t *
299 {
300  return vm_cref_new_toplevel(GET_EC());
301 }
302 
303 static void
304 vm_cref_dump(const char *mesg, const rb_cref_t *cref)
305 {
306  fprintf(stderr, "vm_cref_dump: %s (%p)\n", mesg, (void *)cref);
307 
308  while (cref) {
309  fprintf(stderr, "= cref| klass: %s\n", RSTRING_PTR(rb_class_path(CREF_CLASS(cref))));
310  cref = CREF_NEXT(cref);
311  }
312 }
313 
314 void
315 rb_vm_block_ep_update(VALUE obj, const struct rb_block *dst, const VALUE *ep)
316 {
317  *((const VALUE **)&dst->as.captured.ep) = ep;
318  RB_OBJ_WRITTEN(obj, Qundef, VM_ENV_ENVVAL(ep));
319 }
320 
321 static void
322 vm_bind_update_env(VALUE bindval, rb_binding_t *bind, VALUE envval)
323 {
324  const rb_env_t *env = (rb_env_t *)envval;
325  RB_OBJ_WRITE(bindval, &bind->block.as.captured.code.iseq, env->iseq);
326  rb_vm_block_ep_update(bindval, &bind->block, env->ep);
327 }
328 
329 #if VM_COLLECT_USAGE_DETAILS
330 static void vm_collect_usage_operand(int insn, int n, VALUE op);
331 static void vm_collect_usage_insn(int insn);
332 static void vm_collect_usage_register(int reg, int isset);
333 #endif
334 
335 static VALUE vm_make_env_object(const rb_execution_context_t *ec, rb_control_frame_t *cfp);
337  int argc, const VALUE *argv, int kw_splat, VALUE block_handler,
339 static VALUE vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE block_handler);
340 
341 #include "mjit.h"
342 #include "vm_insnhelper.h"
343 #include "vm_exec.h"
344 #include "vm_insnhelper.c"
345 
346 #ifndef MJIT_HEADER
347 
348 #include "vm_exec.c"
349 
350 #include "vm_method.c"
351 #endif /* #ifndef MJIT_HEADER */
352 #include "vm_eval.c"
353 #ifndef MJIT_HEADER
354 
355 #define PROCDEBUG 0
356 
359 {
360  rb_serial_t class_serial = NEXT_CLASS_SERIAL();
361  mjit_add_class_serial(class_serial);
362  return class_serial;
363 }
364 
369 
370 #define ruby_vm_redefined_flag GET_VM()->redefined_flag
374 
378 
382 
383 static void thread_free(void *ptr);
384 
385 void
387 {
389 }
390 
393  struct ruby_dtrace_method_hook_args *args)
394 {
395  enum ruby_value_type type;
396  if (!klass) {
397  if (!ec) ec = GET_EC();
398  if (!rb_ec_frame_method_id_and_class(ec, &id, 0, &klass) || !klass)
399  return FALSE;
400  }
401  if (RB_TYPE_P(klass, T_ICLASS)) {
402  klass = RBASIC(klass)->klass;
403  }
404  else if (FL_TEST(klass, FL_SINGLETON)) {
406  if (NIL_P(klass)) return FALSE;
407  }
409  if (type == T_CLASS || type == T_ICLASS || type == T_MODULE) {
411  const char *classname, *filename;
412  const char *methodname = rb_id2name(id);
413  if (methodname && (filename = rb_source_location_cstr(&args->line_no)) != 0) {
414  if (NIL_P(name) || !(classname = StringValuePtr(name)))
415  classname = "<unknown>";
416  args->classname = classname;
417  args->methodname = methodname;
418  args->filename = filename;
419  args->klass = klass;
420  args->name = name;
421  return TRUE;
422  }
423  }
424  return FALSE;
425 }
426 
427 /*
428  * call-seq:
429  * RubyVM.stat -> Hash
430  * RubyVM.stat(hsh) -> hsh
431  * RubyVM.stat(Symbol) -> Numeric
432  *
433  * Returns a Hash containing implementation-dependent counters inside the VM.
434  *
435  * This hash includes information about method/constant cache serials:
436  *
437  * {
438  * :global_method_state=>251,
439  * :global_constant_state=>481,
440  * :class_serial=>9029
441  * }
442  *
443  * The contents of the hash are implementation specific and may be changed in
444  * the future.
445  *
446  * This method is only expected to work on C Ruby.
447  */
448 
449 static VALUE
450 vm_stat(int argc, VALUE *argv, VALUE self)
451 {
452  static VALUE sym_global_method_state, sym_global_constant_state, sym_class_serial;
453  VALUE arg = Qnil;
454  VALUE hash = Qnil, key = Qnil;
455 
456  if (rb_check_arity(argc, 0, 1) == 1) {
457  arg = argv[0];
458  if (SYMBOL_P(arg))
459  key = arg;
460  else if (RB_TYPE_P(arg, T_HASH))
461  hash = arg;
462  else
463  rb_raise(rb_eTypeError, "non-hash or symbol given");
464  }
465  else {
466  hash = rb_hash_new();
467  }
468 
469  if (sym_global_method_state == 0) {
470 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
471  S(global_method_state);
472  S(global_constant_state);
473  S(class_serial);
474 #undef S
475  }
476 
477 #define SET(name, attr) \
478  if (key == sym_##name) \
479  return SERIALT2NUM(attr); \
480  else if (hash != Qnil) \
481  rb_hash_aset(hash, sym_##name, SERIALT2NUM(attr));
482 
483  SET(global_method_state, ruby_vm_global_method_state);
484  SET(global_constant_state, ruby_vm_global_constant_state);
485  SET(class_serial, ruby_vm_class_serial);
486 #undef SET
487 
488  if (!NIL_P(key)) { /* matched key should return above */
489  rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
490  }
491 
492  return hash;
493 }
494 
495 /* control stack frame */
496 
497 static void
498 vm_set_top_stack(rb_execution_context_t *ec, const rb_iseq_t *iseq)
499 {
500  if (iseq->body->type != ISEQ_TYPE_TOP) {
501  rb_raise(rb_eTypeError, "Not a toplevel InstructionSequence");
502  }
503 
504  /* for return */
505  vm_push_frame(ec, iseq, VM_FRAME_MAGIC_TOP | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH, rb_ec_thread_ptr(ec)->top_self,
507  (VALUE)vm_cref_new_toplevel(ec), /* cref or me */
508  iseq->body->iseq_encoded, ec->cfp->sp,
510 }
511 
512 static void
513 vm_set_eval_stack(rb_execution_context_t *ec, const rb_iseq_t *iseq, const rb_cref_t *cref, const struct rb_block *base_block)
514 {
515  vm_push_frame(ec, iseq, VM_FRAME_MAGIC_EVAL | VM_FRAME_FLAG_FINISH,
516  vm_block_self(base_block), VM_GUARDED_PREV_EP(vm_block_ep(base_block)),
517  (VALUE)cref, /* cref or me */
519  ec->cfp->sp, iseq->body->local_table_size,
520  iseq->body->stack_max);
521 }
522 
523 static void
524 vm_set_main_stack(rb_execution_context_t *ec, const rb_iseq_t *iseq)
525 {
526  VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
527  rb_binding_t *bind;
528 
529  GetBindingPtr(toplevel_binding, bind);
530  RUBY_ASSERT_MESG(bind, "TOPLEVEL_BINDING is not built");
531 
532  vm_set_eval_stack(ec, iseq, 0, &bind->block);
533 
534  /* save binding */
535  if (iseq->body->local_table_size > 0) {
536  vm_bind_update_env(toplevel_binding, bind, vm_make_env_object(ec, ec->cfp));
537  }
538 }
539 
542 {
543  while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
544  if (cfp->iseq) {
545  return (rb_control_frame_t *)cfp;
546  }
548  }
549  return 0;
550 }
551 
554 {
555  if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) bp();
556  while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
557  if (VM_FRAME_RUBYFRAME_P(cfp)) {
558  return (rb_control_frame_t *)cfp;
559  }
561  }
562  return 0;
563 }
564 
565 #endif /* #ifndef MJIT_HEADER */
566 
567 static rb_control_frame_t *
568 vm_get_ruby_level_caller_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
569 {
570  if (VM_FRAME_RUBYFRAME_P(cfp)) {
571  return (rb_control_frame_t *)cfp;
572  }
573 
575 
576  while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
577  if (VM_FRAME_RUBYFRAME_P(cfp)) {
578  return (rb_control_frame_t *)cfp;
579  }
580 
581  if (VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_PASSED) == FALSE) {
582  break;
583  }
585  }
586  return 0;
587 }
588 
589 MJIT_STATIC void
591 {
593  rb_control_frame_t *cfp = ec->cfp;
595 
598  vm_pop_frame(ec, cfp, cfp->ep);
599 }
600 
601 #ifndef MJIT_HEADER
602 
603 void
605 {
606  /* check skipped frame */
607  while (ec->cfp != cfp) {
608 #if VMDEBUG
609  printf("skipped frame: %s\n", vm_frametype_name(ec->cfp));
610 #endif
611  if (VM_FRAME_TYPE(ec->cfp) != VM_FRAME_MAGIC_CFUNC) {
612  rb_vm_pop_frame(ec);
613  }
614  else { /* unlikely path */
616  }
617  }
618 }
619 
620 /* at exit */
621 
622 void
623 ruby_vm_at_exit(void (*func)(rb_vm_t *))
624 {
625  rb_vm_t *vm = GET_VM();
627  nl->func = func;
628  nl->next = vm->at_exit;
629  vm->at_exit = nl;
630 }
631 
632 static void
633 ruby_vm_run_at_exit_hooks(rb_vm_t *vm)
634 {
635  rb_at_exit_list *l = vm->at_exit;
636 
637  while (l) {
638  rb_at_exit_list* t = l->next;
639  rb_vm_at_exit_func *func = l->func;
640  ruby_xfree(l);
641  l = t;
642  (*func)(vm);
643  }
644 }
645 
646 /* Env */
647 
648 static VALUE check_env_value(const rb_env_t *env);
649 
650 static int
651 check_env(const rb_env_t *env)
652 {
653  fprintf(stderr, "---\n");
654  fprintf(stderr, "envptr: %p\n", (void *)&env->ep[0]);
655  fprintf(stderr, "envval: %10p ", (void *)env->ep[1]);
656  dp(env->ep[1]);
657  fprintf(stderr, "ep: %10p\n", (void *)env->ep);
658  if (rb_vm_env_prev_env(env)) {
659  fprintf(stderr, ">>\n");
660  check_env_value(rb_vm_env_prev_env(env));
661  fprintf(stderr, "<<\n");
662  }
663  return 1;
664 }
665 
666 static VALUE
667 check_env_value(const rb_env_t *env)
668 {
669  if (check_env(env)) {
670  return (VALUE)env;
671  }
672  rb_bug("invalid env");
673  return Qnil; /* unreachable */
674 }
675 
676 static VALUE
677 vm_block_handler_escape(const rb_execution_context_t *ec, VALUE block_handler)
678 {
679  switch (vm_block_handler_type(block_handler)) {
682  return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc);
683 
686  return block_handler;
687  }
688  VM_UNREACHABLE(vm_block_handler_escape);
689  return Qnil;
690 }
691 
692 static VALUE
693 vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *const cfp)
694 {
695  const VALUE * const ep = cfp->ep;
696  const rb_env_t *env;
697  const rb_iseq_t *env_iseq;
698  VALUE *env_body, *env_ep;
699  int local_size, env_size;
700 
701  if (VM_ENV_ESCAPED_P(ep)) {
702  return VM_ENV_ENVVAL(ep);
703  }
704 
705  if (!VM_ENV_LOCAL_P(ep)) {
706  const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
707 
708  if (!VM_ENV_ESCAPED_P(prev_ep)) {
710 
711  while (prev_cfp->ep != prev_ep) {
712  prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(prev_cfp);
713  VM_ASSERT(prev_cfp->ep != NULL);
714  }
715 
716  vm_make_env_each(ec, prev_cfp);
717  VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep));
718  }
719  }
720  else {
721  VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep);
722 
724  VALUE blockprocval = vm_block_handler_escape(ec, block_handler);
725  VM_STACK_ENV_WRITE(ep, VM_ENV_DATA_INDEX_SPECVAL, blockprocval);
726  }
727  }
728 
729  if (!VM_FRAME_RUBYFRAME_P(cfp)) {
731  }
732  else {
734  }
735 
736  /*
737  * # local variables on a stack frame (N == local_size)
738  * [lvar1, lvar2, ..., lvarN, SPECVAL]
739  * ^
740  * ep[0]
741  *
742  * # moved local variables
743  * [lvar1, lvar2, ..., lvarN, SPECVAL, Envval, BlockProcval (if needed)]
744  * ^ ^
745  * env->env[0] ep[0]
746  */
747 
748  env_size = local_size +
749  1 /* envval */;
750  env_body = ALLOC_N(VALUE, env_size);
751  MEMCPY(env_body, ep - (local_size - 1 /* specval */), VALUE, local_size);
752 
753 #if 0
754  for (i = 0; i < local_size; i++) {
755  if (VM_FRAME_RUBYFRAME_P(cfp)) {
756  /* clear value stack for GC */
757  ep[-local_size + i] = 0;
758  }
759  }
760 #endif
761 
762  env_iseq = VM_FRAME_RUBYFRAME_P(cfp) ? cfp->iseq : NULL;
763  env_ep = &env_body[local_size - 1 /* specval */];
764 
765  env = vm_env_new(env_ep, env_body, env_size, env_iseq);
766 
767  cfp->ep = env_ep;
768  VM_ENV_FLAGS_SET(env_ep, VM_ENV_FLAG_ESCAPED | VM_ENV_FLAG_WB_REQUIRED);
769  VM_STACK_ENV_WRITE(ep, 0, (VALUE)env); /* GC mark */
770  return (VALUE)env;
771 }
772 
773 static VALUE
774 vm_make_env_object(const rb_execution_context_t *ec, rb_control_frame_t *cfp)
775 {
776  VALUE envval = vm_make_env_each(ec, cfp);
777 
778  if (PROCDEBUG) {
779  check_env_value((const rb_env_t *)envval);
780  }
781 
782  return envval;
783 }
784 
785 void
787 {
788  rb_control_frame_t *cfp = ec->cfp;
789  while ((cfp = rb_vm_get_binding_creatable_next_cfp(ec, cfp)) != 0) {
790  vm_make_env_object(ec, cfp);
792  }
793 }
794 
795 const rb_env_t *
797 {
798  const VALUE *ep = env->ep;
799 
800  if (VM_ENV_LOCAL_P(ep)) {
801  return NULL;
802  }
803  else {
804  return VM_ENV_ENVVAL_PTR(VM_ENV_PREV_EP(ep));
805  }
806 }
807 
808 static int
809 collect_local_variables_in_iseq(const rb_iseq_t *iseq, const struct local_var_list *vars)
810 {
811  unsigned int i;
812  if (!iseq) return 0;
813  for (i = 0; i < iseq->body->local_table_size; i++) {
814  local_var_list_add(vars, iseq->body->local_table[i]);
815  }
816  return 1;
817 }
818 
819 static void
820 collect_local_variables_in_env(const rb_env_t *env, const struct local_var_list *vars)
821 {
822  do {
823  collect_local_variables_in_iseq(env->iseq, vars);
824  } while ((env = rb_vm_env_prev_env(env)) != NULL);
825 }
826 
827 static int
828 vm_collect_local_variables_in_heap(const VALUE *ep, const struct local_var_list *vars)
829 {
830  if (VM_ENV_ESCAPED_P(ep)) {
831  collect_local_variables_in_env(VM_ENV_ENVVAL_PTR(ep), vars);
832  return 1;
833  }
834  else {
835  return 0;
836  }
837 }
838 
839 VALUE
841 {
842  struct local_var_list vars;
843  local_var_list_init(&vars);
844  collect_local_variables_in_env(env, &vars);
845  return local_var_list_finish(&vars);
846 }
847 
848 VALUE
850 {
851  struct local_var_list vars;
852  local_var_list_init(&vars);
853  while (collect_local_variables_in_iseq(iseq, &vars)) {
855  }
856  return local_var_list_finish(&vars);
857 }
858 
859 /* Proc */
860 
861 static VALUE
862 vm_proc_create_from_captured(VALUE klass,
863  const struct rb_captured_block *captured,
864  enum rb_block_type block_type,
865  int8_t is_from_method, int8_t is_lambda)
866 {
867  VALUE procval = rb_proc_alloc(klass);
868  rb_proc_t *proc = RTYPEDDATA_DATA(procval);
869 
870  VM_ASSERT(VM_EP_IN_HEAP_P(GET_EC(), captured->ep));
871 
872  /* copy block */
873  RB_OBJ_WRITE(procval, &proc->block.as.captured.self, captured->self);
874  RB_OBJ_WRITE(procval, &proc->block.as.captured.code.val, captured->code.val);
875  rb_vm_block_ep_update(procval, &proc->block, captured->ep);
876 
877  vm_block_type_set(&proc->block, block_type);
878  proc->is_from_method = is_from_method;
879  proc->is_lambda = is_lambda;
880 
881  return procval;
882 }
883 
884 void
885 rb_vm_block_copy(VALUE obj, const struct rb_block *dst, const struct rb_block *src)
886 {
887  /* copy block */
888  switch (vm_block_type(src)) {
889  case block_type_iseq:
890  case block_type_ifunc:
891  RB_OBJ_WRITE(obj, &dst->as.captured.self, src->as.captured.self);
892  RB_OBJ_WRITE(obj, &dst->as.captured.code.val, src->as.captured.code.val);
893  rb_vm_block_ep_update(obj, dst, src->as.captured.ep);
894  break;
895  case block_type_symbol:
896  RB_OBJ_WRITE(obj, &dst->as.symbol, src->as.symbol);
897  break;
898  case block_type_proc:
899  RB_OBJ_WRITE(obj, &dst->as.proc, src->as.proc);
900  break;
901  }
902 }
903 
904 static VALUE
905 proc_create(VALUE klass, const struct rb_block *block, int8_t is_from_method, int8_t is_lambda)
906 {
907  VALUE procval = rb_proc_alloc(klass);
908  rb_proc_t *proc = RTYPEDDATA_DATA(procval);
909 
910  VM_ASSERT(VM_EP_IN_HEAP_P(GET_EC(), vm_block_ep(block)));
911  rb_vm_block_copy(procval, &proc->block, block);
912  vm_block_type_set(&proc->block, block->type);
913  proc->is_from_method = is_from_method;
914  proc->is_lambda = is_lambda;
915 
916  return procval;
917 }
918 
919 VALUE
921 {
922  VALUE procval;
923  rb_proc_t *src;
924 
925  GetProcPtr(self, src);
926  procval = proc_create(rb_cProc, &src->block, src->is_from_method, src->is_lambda);
927  RB_GC_GUARD(self); /* for: body = rb_proc_dup(body) */
928  return procval;
929 }
930 
931 
933 rb_vm_make_proc_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda)
934 {
935  VALUE procval;
936 
937  if (!VM_ENV_ESCAPED_P(captured->ep)) {
938  rb_control_frame_t *cfp = VM_CAPTURED_BLOCK_TO_CFP(captured);
939  vm_make_env_object(ec, cfp);
940  }
941  VM_ASSERT(VM_EP_IN_HEAP_P(ec, captured->ep));
942  VM_ASSERT(imemo_type_p(captured->code.val, imemo_iseq) ||
943  imemo_type_p(captured->code.val, imemo_ifunc));
944 
945  procval = vm_proc_create_from_captured(klass, captured,
946  imemo_type(captured->code.val) == imemo_iseq ? block_type_iseq : block_type_ifunc, FALSE, is_lambda);
947  return procval;
948 }
949 
950 /* Binding */
951 
952 VALUE
954 {
956  rb_control_frame_t *ruby_level_cfp = rb_vm_get_ruby_level_next_cfp(ec, src_cfp);
957  VALUE bindval, envval;
958  rb_binding_t *bind;
959 
960  if (cfp == 0 || ruby_level_cfp == 0) {
961  rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
962  }
963 
964  while (1) {
965  envval = vm_make_env_object(ec, cfp);
966  if (cfp == ruby_level_cfp) {
967  break;
968  }
970  }
971 
972  bindval = rb_binding_alloc(rb_cBinding);
973  GetBindingPtr(bindval, bind);
974  vm_bind_update_env(bindval, bind, envval);
975  RB_OBJ_WRITE(bindval, &bind->block.as.captured.self, cfp->self);
976  RB_OBJ_WRITE(bindval, &bind->block.as.captured.code.iseq, cfp->iseq);
977  RB_OBJ_WRITE(bindval, &bind->pathobj, ruby_level_cfp->iseq->body->location.pathobj);
978  bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp);
979 
980  return bindval;
981 }
982 
983 const VALUE *
984 rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars)
985 {
986  VALUE envval, pathobj = bind->pathobj;
987  VALUE path = pathobj_path(pathobj);
988  VALUE realpath = pathobj_realpath(pathobj);
989  const struct rb_block *base_block;
990  const rb_env_t *env;
992  const rb_iseq_t *base_iseq, *iseq;
993  rb_ast_body_t ast;
994  NODE tmp_node;
995  ID minibuf[4], *dyns = minibuf;
996  VALUE idtmp = 0;
997 
998  if (dyncount < 0) return 0;
999 
1000  base_block = &bind->block;
1001  base_iseq = vm_block_iseq(base_block);
1002 
1003  if (dyncount >= numberof(minibuf)) dyns = ALLOCV_N(ID, idtmp, dyncount + 1);
1004 
1005  dyns[0] = dyncount;
1006  MEMCPY(dyns + 1, dynvars, ID, dyncount);
1007  rb_node_init(&tmp_node, NODE_SCOPE, (VALUE)dyns, 0, 0);
1008  ast.root = &tmp_node;
1009  ast.compile_option = 0;
1010  ast.line_count = -1;
1011 
1012  if (base_iseq) {
1013  iseq = rb_iseq_new(&ast, base_iseq->body->location.label, path, realpath, base_iseq, ISEQ_TYPE_EVAL);
1014  }
1015  else {
1016  VALUE tempstr = rb_fstring_lit("<temp>");
1017  iseq = rb_iseq_new_top(&ast, tempstr, tempstr, tempstr, NULL);
1018  }
1019  tmp_node.nd_tbl = 0; /* reset table */
1020  ALLOCV_END(idtmp);
1021 
1022  vm_set_eval_stack(ec, iseq, 0, base_block);
1023  vm_bind_update_env(bindval, bind, envval = vm_make_env_object(ec, ec->cfp));
1024  rb_vm_pop_frame(ec);
1025 
1026  env = (const rb_env_t *)envval;
1027  return env->env;
1028 }
1029 
1030 /* C -> Ruby: block */
1031 
1032 static inline VALUE
1033 invoke_block(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE self, const struct rb_captured_block *captured, const rb_cref_t *cref, VALUE type, int opt_pc)
1034 {
1035  int arg_size = iseq->body->param.size;
1036 
1037  vm_push_frame(ec, iseq, type | VM_FRAME_FLAG_FINISH, self,
1039  (VALUE)cref, /* cref or method */
1041  ec->cfp->sp + arg_size,
1042  iseq->body->local_table_size - arg_size,
1043  iseq->body->stack_max);
1044  return vm_exec(ec, TRUE);
1045 }
1046 
1047 static VALUE
1048 invoke_bmethod(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE self, const struct rb_captured_block *captured, const rb_callable_method_entry_t *me, VALUE type, int opt_pc)
1049 {
1050  /* bmethod */
1051  int arg_size = iseq->body->param.size;
1052  VALUE ret;
1053  rb_hook_list_t *hooks;
1054 
1056 
1057  vm_push_frame(ec, iseq, type | VM_FRAME_FLAG_BMETHOD, self,
1059  (VALUE)me,
1061  ec->cfp->sp + arg_size,
1062  iseq->body->local_table_size - arg_size,
1063  iseq->body->stack_max);
1064 
1067 
1068  if (UNLIKELY((hooks = me->def->body.bmethod.hooks) != NULL) &&
1069  hooks->events & RUBY_EVENT_CALL) {
1070  rb_exec_event_hook_orig(ec, hooks, RUBY_EVENT_CALL, self,
1072  }
1073  VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);
1074  ret = vm_exec(ec, TRUE);
1075 
1077  if ((hooks = me->def->body.bmethod.hooks) != NULL &&
1078  hooks->events & RUBY_EVENT_RETURN) {
1079  rb_exec_event_hook_orig(ec, hooks, RUBY_EVENT_RETURN, self,
1080  me->def->original_id, me->called_id, me->owner, ret, FALSE);
1081  }
1083  return ret;
1084 }
1085 
1086 ALWAYS_INLINE(static VALUE
1087  invoke_iseq_block_from_c(rb_execution_context_t *ec, const struct rb_captured_block *captured,
1088  VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler,
1089  const rb_cref_t *cref, int is_lambda, const rb_callable_method_entry_t *me));
1090 
1091 static inline VALUE
1092 invoke_iseq_block_from_c(rb_execution_context_t *ec, const struct rb_captured_block *captured,
1093  VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler,
1094  const rb_cref_t *cref, int is_lambda, const rb_callable_method_entry_t *me)
1095 {
1096  const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
1097  int i, opt_pc;
1098  VALUE type = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0);
1099  rb_control_frame_t *cfp = ec->cfp;
1100  VALUE *sp = cfp->sp;
1101 
1102  stack_check(ec);
1103 
1105  vm_check_canary(ec, sp);
1106  cfp->sp = sp + argc;
1107  for (i=0; i<argc; i++) {
1108  sp[i] = argv[i];
1109  }
1110 
1111  opt_pc = vm_yield_setup_args(ec, iseq, argc, sp, kw_splat, passed_block_handler,
1112  (is_lambda ? arg_setup_method : arg_setup_block));
1113  cfp->sp = sp;
1114 
1115  if (me == NULL) {
1116  return invoke_block(ec, iseq, self, captured, cref, type, opt_pc);
1117  }
1118  else {
1119  return invoke_bmethod(ec, iseq, self, captured, me, type, opt_pc);
1120  }
1121 }
1122 
1123 static inline VALUE
1124 invoke_block_from_c_bh(rb_execution_context_t *ec, VALUE block_handler,
1125  int argc, const VALUE *argv,
1126  int kw_splat, VALUE passed_block_handler, const rb_cref_t *cref,
1127  int is_lambda, int force_blockarg)
1128 {
1129  again:
1130  switch (vm_block_handler_type(block_handler)) {
1132  {
1133  const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler);
1134  return invoke_iseq_block_from_c(ec, captured, captured->self,
1135  argc, argv, kw_splat, passed_block_handler,
1136  cref, is_lambda, NULL);
1137  }
1139  return vm_yield_with_cfunc(ec, VM_BH_TO_IFUNC_BLOCK(block_handler),
1140  VM_BH_TO_IFUNC_BLOCK(block_handler)->self,
1141  argc, argv, kw_splat, passed_block_handler, NULL);
1143  return vm_yield_with_symbol(ec, VM_BH_TO_SYMBOL(block_handler),
1144  argc, argv, kw_splat, passed_block_handler);
1146  if (force_blockarg == FALSE) {
1147  is_lambda = block_proc_is_lambda(VM_BH_TO_PROC(block_handler));
1148  }
1149  block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
1150  goto again;
1151  }
1152  VM_UNREACHABLE(invoke_block_from_c_splattable);
1153  return Qundef;
1154 }
1155 
1156 static inline VALUE
1157 check_block_handler(rb_execution_context_t *ec)
1158 {
1159  VALUE block_handler = VM_CF_BLOCK_HANDLER(ec->cfp);
1160  vm_block_handler_verify(block_handler);
1162  rb_vm_localjump_error("no block given", Qnil, 0);
1163  }
1164 
1165  return block_handler;
1166 }
1167 
1168 static VALUE
1169 vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat, const rb_cref_t *cref, int is_lambda)
1170 {
1171  return invoke_block_from_c_bh(ec, check_block_handler(ec),
1172  argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE,
1173  cref, is_lambda, FALSE);
1174 }
1175 
1176 static VALUE
1177 vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat)
1178 {
1179  return invoke_block_from_c_bh(ec, check_block_handler(ec),
1180  argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE,
1181  NULL, FALSE, FALSE);
1182 }
1183 
1184 static VALUE
1185 vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler, int kw_splat)
1186 {
1187  return invoke_block_from_c_bh(ec, check_block_handler(ec),
1188  argc, argv, kw_splat, block_handler,
1189  NULL, FALSE, FALSE);
1190 }
1191 
1192 static VALUE
1193 vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args)
1194 {
1195  return invoke_block_from_c_bh(ec, check_block_handler(ec), 1, &args,
1197 }
1198 
1199 ALWAYS_INLINE(static VALUE
1200  invoke_block_from_c_proc(rb_execution_context_t *ec, const rb_proc_t *proc,
1201  VALUE self, int argc, const VALUE *argv,
1202  int kw_splat, VALUE passed_block_handler, int is_lambda,
1203  const rb_callable_method_entry_t *me));
1204 
1205 static inline VALUE
1206 invoke_block_from_c_proc(rb_execution_context_t *ec, const rb_proc_t *proc,
1207  VALUE self, int argc, const VALUE *argv,
1208  int kw_splat, VALUE passed_block_handler, int is_lambda,
1210 {
1211  const struct rb_block *block = &proc->block;
1212 
1213  again:
1214  switch (vm_block_type(block)) {
1215  case block_type_iseq:
1216  return invoke_iseq_block_from_c(ec, &block->as.captured, self, argc, argv, kw_splat, passed_block_handler, NULL, is_lambda, me);
1217  case block_type_ifunc:
1218  if (kw_splat == 1 && RHASH_EMPTY_P(argv[argc-1])) {
1219  argc--;
1220  kw_splat = 2;
1221  }
1222  return vm_yield_with_cfunc(ec, &block->as.captured, self, argc, argv, kw_splat, passed_block_handler, me);
1223  case block_type_symbol:
1224  return vm_yield_with_symbol(ec, block->as.symbol, argc, argv, kw_splat, passed_block_handler);
1225  case block_type_proc:
1226  is_lambda = block_proc_is_lambda(block->as.proc);
1227  block = vm_proc_block(block->as.proc);
1228  goto again;
1229  }
1230  VM_UNREACHABLE(invoke_block_from_c_proc);
1231  return Qundef;
1232 }
1233 
1234 static VALUE
1235 vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self,
1236  int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler)
1237 {
1238  return invoke_block_from_c_proc(ec, proc, self, argc, argv, kw_splat, passed_block_handler, proc->is_lambda, NULL);
1239 }
1240 
1243  int argc, const VALUE *argv, int kw_splat, VALUE block_handler, const rb_callable_method_entry_t *me)
1244 {
1245  return invoke_block_from_c_proc(ec, proc, self, argc, argv, kw_splat, block_handler, TRUE, me);
1246 }
1247 
1250  int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler)
1251 {
1252  VALUE self = vm_block_self(&proc->block);
1253  vm_block_handler_verify(passed_block_handler);
1254 
1255  if (proc->is_from_method) {
1256  return rb_vm_invoke_bmethod(ec, proc, self, argc, argv, kw_splat, passed_block_handler, NULL);
1257  }
1258  else {
1259  return vm_invoke_proc(ec, proc, self, argc, argv, kw_splat, passed_block_handler);
1260  }
1261 }
1262 
1263 /* special variable */
1264 
1265 static rb_control_frame_t *
1266 vm_normal_frame(const rb_execution_context_t *ec, rb_control_frame_t *cfp)
1267 {
1268  while (cfp->pc == 0) {
1270  if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
1271  return 0;
1272  }
1273  }
1274  return cfp;
1275 }
1276 
1277 static VALUE
1278 vm_cfp_svar_get(const rb_execution_context_t *ec, rb_control_frame_t *cfp, VALUE key)
1279 {
1280  cfp = vm_normal_frame(ec, cfp);
1281  return lep_svar_get(ec, cfp ? VM_CF_LEP(cfp) : 0, key);
1282 }
1283 
1284 static void
1285 vm_cfp_svar_set(const rb_execution_context_t *ec, rb_control_frame_t *cfp, VALUE key, const VALUE val)
1286 {
1287  cfp = vm_normal_frame(ec, cfp);
1288  lep_svar_set(ec, cfp ? VM_CF_LEP(cfp) : 0, key, val);
1289 }
1290 
1291 static VALUE
1292 vm_svar_get(const rb_execution_context_t *ec, VALUE key)
1293 {
1294  return vm_cfp_svar_get(ec, ec->cfp, key);
1295 }
1296 
1297 static void
1298 vm_svar_set(const rb_execution_context_t *ec, VALUE key, VALUE val)
1299 {
1300  vm_cfp_svar_set(ec, ec->cfp, key, val);
1301 }
1302 
1303 VALUE
1305 {
1306  return vm_svar_get(GET_EC(), VM_SVAR_BACKREF);
1307 }
1308 
1309 void
1311 {
1312  vm_svar_set(GET_EC(), VM_SVAR_BACKREF, val);
1313 }
1314 
1315 VALUE
1317 {
1318  return vm_svar_get(GET_EC(), VM_SVAR_LASTLINE);
1319 }
1320 
1321 void
1323 {
1324  vm_svar_set(GET_EC(), VM_SVAR_LASTLINE, val);
1325 }
1326 
1327 /* misc */
1328 
1329 /* in intern.h */
1330 const char *
1332 {
1333  const rb_execution_context_t *ec = GET_EC();
1335 
1336  if (cfp) {
1337  return RSTRING_PTR(rb_iseq_path(cfp->iseq));
1338  }
1339  else {
1340  return 0;
1341  }
1342 }
1343 
1344 /* in intern.h */
1345 int
1347 {
1348  const rb_execution_context_t *ec = GET_EC();
1350 
1351  if (cfp) {
1352  return rb_vm_get_sourceline(cfp);
1353  }
1354  else {
1355  return 0;
1356  }
1357 }
1358 
1359 VALUE
1361 {
1362  const rb_execution_context_t *ec = GET_EC();
1364 
1365  if (cfp && VM_FRAME_RUBYFRAME_P(cfp)) {
1366  if (pline) *pline = rb_vm_get_sourceline(cfp);
1367  return rb_iseq_path(cfp->iseq);
1368  }
1369  else {
1370  if (pline) *pline = 0;
1371  return Qnil;
1372  }
1373 }
1374 
1375 MJIT_FUNC_EXPORTED const char *
1377 {
1378  VALUE path = rb_source_location(pline);
1379  if (NIL_P(path)) return NULL;
1380  return RSTRING_PTR(path);
1381 }
1382 
1383 rb_cref_t *
1385 {
1386  const rb_execution_context_t *ec = GET_EC();
1387  return vm_ec_cref(ec);
1388 }
1389 
1390 rb_cref_t *
1392 {
1393  const rb_execution_context_t *ec = GET_EC();
1395  rb_cref_t *cref = vm_cref_replace_with_duplicated_cref(cfp->ep);
1396  return cref;
1397 }
1398 
1399 const rb_cref_t *
1401 {
1402  const rb_execution_context_t *ec = GET_EC();
1404  const rb_cref_t *cref;
1405  if (!cfp || cfp->self != self) return NULL;
1406  if (!vm_env_cref_by_cref(cfp->ep)) return NULL;
1407  cref = vm_get_cref(cfp->ep);
1408  if (CREF_CLASS(cref) != cbase) return NULL;
1409  return cref;
1410 }
1411 
1412 #if 0
1413 void
1414 debug_cref(rb_cref_t *cref)
1415 {
1416  while (cref) {
1417  dp(CREF_CLASS(cref));
1418  printf("%ld\n", CREF_VISI(cref));
1419  cref = CREF_NEXT(cref);
1420  }
1421 }
1422 #endif
1423 
1424 VALUE
1426 {
1427  const rb_execution_context_t *ec = GET_EC();
1429 
1430  if (cfp == 0) {
1431  rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
1432  }
1433  return vm_get_cbase(cfp->ep);
1434 }
1435 
1436 /* jump */
1437 
1438 static VALUE
1439 make_localjump_error(const char *mesg, VALUE value, int reason)
1440 {
1441  extern VALUE rb_eLocalJumpError;
1443  ID id;
1444 
1445  switch (reason) {
1446  case TAG_BREAK:
1447  CONST_ID(id, "break");
1448  break;
1449  case TAG_REDO:
1450  CONST_ID(id, "redo");
1451  break;
1452  case TAG_RETRY:
1453  CONST_ID(id, "retry");
1454  break;
1455  case TAG_NEXT:
1456  CONST_ID(id, "next");
1457  break;
1458  case TAG_RETURN:
1459  CONST_ID(id, "return");
1460  break;
1461  default:
1462  CONST_ID(id, "noreason");
1463  break;
1464  }
1465  rb_iv_set(exc, "@exit_value", value);
1466  rb_iv_set(exc, "@reason", ID2SYM(id));
1467  return exc;
1468 }
1469 
1470 MJIT_FUNC_EXPORTED void
1471 rb_vm_localjump_error(const char *mesg, VALUE value, int reason)
1472 {
1473  VALUE exc = make_localjump_error(mesg, value, reason);
1474  rb_exc_raise(exc);
1475 }
1476 
1477 VALUE
1479 {
1480  const char *mesg;
1481 
1482  switch (state) {
1483  case TAG_RETURN:
1484  mesg = "unexpected return";
1485  break;
1486  case TAG_BREAK:
1487  mesg = "unexpected break";
1488  break;
1489  case TAG_NEXT:
1490  mesg = "unexpected next";
1491  break;
1492  case TAG_REDO:
1493  mesg = "unexpected redo";
1494  val = Qnil;
1495  break;
1496  case TAG_RETRY:
1497  mesg = "retry outside of rescue clause";
1498  val = Qnil;
1499  break;
1500  default:
1501  return Qnil;
1502  }
1503  if (val == Qundef) {
1504  val = GET_EC()->tag->retval;
1505  }
1506  return make_localjump_error(mesg, val, state);
1507 }
1508 
1509 void
1511 {
1513  if (!NIL_P(exc)) rb_exc_raise(exc);
1514  EC_JUMP_TAG(GET_EC(), state);
1515 }
1516 
1517 static rb_control_frame_t *
1518 next_not_local_frame(rb_control_frame_t *cfp)
1519 {
1520  while (VM_ENV_LOCAL_P(cfp->ep)) {
1522  }
1523  return cfp;
1524 }
1525 
1526 NORETURN(static void vm_iter_break(rb_execution_context_t *ec, VALUE val));
1527 
1528 static void
1529 vm_iter_break(rb_execution_context_t *ec, VALUE val)
1530 {
1531  rb_control_frame_t *cfp = next_not_local_frame(ec->cfp);
1532  const VALUE *ep = VM_CF_PREV_EP(cfp);
1533  const rb_control_frame_t *target_cfp = rb_vm_search_cf_from_ep(ec, cfp, ep);
1534 
1535 #if 0 /* raise LocalJumpError */
1536  if (!target_cfp) {
1537  rb_vm_localjump_error("unexpected break", val, TAG_BREAK);
1538  }
1539 #endif
1540 
1541  ec->errinfo = (VALUE)THROW_DATA_NEW(val, target_cfp, TAG_BREAK);
1542  EC_JUMP_TAG(ec, TAG_BREAK);
1543 }
1544 
1545 void
1547 {
1548  vm_iter_break(GET_EC(), Qnil);
1549 }
1550 
1551 void
1553 {
1554  vm_iter_break(GET_EC(), val);
1555 }
1556 
1557 /* optimization: redefine management */
1558 
1559 static st_table *vm_opt_method_table = 0;
1560 static st_table *vm_opt_mid_table = 0;
1561 
1562 static int
1563 vm_redefinition_check_flag(VALUE klass)
1564 {
1566  if (klass == rb_cFloat) return FLOAT_REDEFINED_OP_FLAG;
1567  if (klass == rb_cString) return STRING_REDEFINED_OP_FLAG;
1568  if (klass == rb_cArray) return ARRAY_REDEFINED_OP_FLAG;
1569  if (klass == rb_cHash) return HASH_REDEFINED_OP_FLAG;
1570  if (klass == rb_cSymbol) return SYMBOL_REDEFINED_OP_FLAG;
1571  if (klass == rb_cTime) return TIME_REDEFINED_OP_FLAG;
1572  if (klass == rb_cRegexp) return REGEXP_REDEFINED_OP_FLAG;
1573  if (klass == rb_cNilClass) return NIL_REDEFINED_OP_FLAG;
1576  if (klass == rb_cProc) return PROC_REDEFINED_OP_FLAG;
1577  return 0;
1578 }
1579 
1580 int
1582 {
1583  if (!vm_opt_mid_table) {
1584  return FALSE;
1585  }
1586 
1587  return st_lookup(vm_opt_mid_table, mid, NULL);
1588 }
1589 
1590 static int
1591 vm_redefinition_check_method_type(const rb_method_definition_t *def)
1592 {
1593  switch (def->type) {
1594  case VM_METHOD_TYPE_CFUNC:
1596  return TRUE;
1597  default:
1598  return FALSE;
1599  }
1600 }
1601 
1602 static void
1603 rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
1604 {
1605  st_data_t bop;
1608  }
1609  if (vm_redefinition_check_method_type(me->def)) {
1610  if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
1611  int flag = vm_redefinition_check_flag(klass);
1612 
1613  ruby_vm_redefined_flag[bop] |= flag;
1614  }
1615  }
1616 }
1617 
1618 static enum rb_id_table_iterator_result
1619 check_redefined_method(ID mid, VALUE value, void *data)
1620 {
1621  VALUE klass = (VALUE)data;
1622  const rb_method_entry_t *me = (rb_method_entry_t *)value;
1623  const rb_method_entry_t *newme = rb_method_entry(klass, mid);
1624 
1625  if (newme != me) rb_vm_check_redefinition_opt_method(me, me->owner);
1626 
1627  return ID_TABLE_CONTINUE;
1628 }
1629 
1630 void
1632 {
1633  if (!vm_redefinition_check_flag(klass)) return;
1634  rb_id_table_foreach(RCLASS_M_TBL(RCLASS_ORIGIN(klass)), check_redefined_method, (void *)klass);
1635 }
1636 
1637 static void
1638 add_opt_method(VALUE klass, ID mid, VALUE bop)
1639 {
1641 
1642  if (me && vm_redefinition_check_method_type(me->def)) {
1643  st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop);
1644  st_insert(vm_opt_mid_table, (st_data_t)mid, (st_data_t)Qtrue);
1645  }
1646  else {
1647  rb_bug("undefined optimized method: %s", rb_id2name(mid));
1648  }
1649 }
1650 
1651 static void
1652 vm_init_redefined_flag(void)
1653 {
1654  ID mid;
1655  VALUE bop;
1656 
1657  vm_opt_method_table = st_init_numtable();
1658  vm_opt_mid_table = st_init_numtable();
1659 
1660 #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0)
1661 #define C(k) add_opt_method(rb_c##k, mid, bop)
1662  OP(PLUS, PLUS), (C(Integer), C(Float), C(String), C(Array));
1663  OP(MINUS, MINUS), (C(Integer), C(Float));
1664  OP(MULT, MULT), (C(Integer), C(Float));
1665  OP(DIV, DIV), (C(Integer), C(Float));
1666  OP(MOD, MOD), (C(Integer), C(Float));
1667  OP(Eq, EQ), (C(Integer), C(Float), C(String), C(Symbol));
1668  OP(Eqq, EQQ), (C(Integer), C(Float), C(Symbol), C(String),
1669  C(NilClass), C(TrueClass), C(FalseClass));
1670  OP(LT, LT), (C(Integer), C(Float));
1671  OP(LE, LE), (C(Integer), C(Float));
1672  OP(GT, GT), (C(Integer), C(Float));
1673  OP(GE, GE), (C(Integer), C(Float));
1674  OP(LTLT, LTLT), (C(String), C(Array));
1675  OP(AREF, AREF), (C(Array), C(Hash), C(Integer));
1676  OP(ASET, ASET), (C(Array), C(Hash));
1677  OP(Length, LENGTH), (C(Array), C(String), C(Hash));
1678  OP(Size, SIZE), (C(Array), C(String), C(Hash));
1679  OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash));
1680  OP(Succ, SUCC), (C(Integer), C(String), C(Time));
1681  OP(EqTilde, MATCH), (C(Regexp), C(String));
1682  OP(Freeze, FREEZE), (C(String));
1683  OP(UMinus, UMINUS), (C(String));
1684  OP(Max, MAX), (C(Array));
1685  OP(Min, MIN), (C(Array));
1686  OP(Call, CALL), (C(Proc));
1687  OP(And, AND), (C(Integer));
1688  OP(Or, OR), (C(Integer));
1689  OP(NilP, NIL_P), (C(NilClass));
1690 #undef C
1691 #undef OP
1692 }
1693 
1694 /* for vm development */
1695 
1696 #if VMDEBUG
1697 static const char *
1698 vm_frametype_name(const rb_control_frame_t *cfp)
1699 {
1700  switch (VM_FRAME_TYPE(cfp)) {
1701  case VM_FRAME_MAGIC_METHOD: return "method";
1702  case VM_FRAME_MAGIC_BLOCK: return "block";
1703  case VM_FRAME_MAGIC_CLASS: return "class";
1704  case VM_FRAME_MAGIC_TOP: return "top";
1705  case VM_FRAME_MAGIC_CFUNC: return "cfunc";
1706  case VM_FRAME_MAGIC_IFUNC: return "ifunc";
1707  case VM_FRAME_MAGIC_EVAL: return "eval";
1708  case VM_FRAME_MAGIC_RESCUE: return "rescue";
1709  default:
1710  rb_bug("unknown frame");
1711  }
1712 }
1713 #endif
1714 
1715 static VALUE
1716 frame_return_value(const struct vm_throw_data *err)
1717 {
1718  if (THROW_DATA_P(err) &&
1719  THROW_DATA_STATE(err) == TAG_BREAK &&
1720  THROW_DATA_CONSUMED_P(err) == FALSE) {
1721  return THROW_DATA_VAL(err);
1722  }
1723  else {
1724  return Qnil;
1725  }
1726 }
1727 
1728 #if 0
1729 /* for debug */
1730 static const char *
1731 frame_name(const rb_control_frame_t *cfp)
1732 {
1733  unsigned long type = VM_FRAME_TYPE(cfp);
1734 #define C(t) if (type == VM_FRAME_MAGIC_##t) return #t
1735  C(METHOD);
1736  C(BLOCK);
1737  C(CLASS);
1738  C(TOP);
1739  C(CFUNC);
1740  C(PROC);
1741  C(IFUNC);
1742  C(EVAL);
1743  C(LAMBDA);
1744  C(RESCUE);
1745  C(DUMMY);
1746 #undef C
1747  return "unknown";
1748 }
1749 #endif
1750 
1751 static void
1752 hook_before_rewind(rb_execution_context_t *ec, const rb_control_frame_t *cfp,
1753  int will_finish_vm_exec, int state, struct vm_throw_data *err)
1754 {
1755  if (state == TAG_RAISE && RBASIC_CLASS(err) == rb_eSysStackError) {
1756  return;
1757  }
1758  else {
1759  const rb_iseq_t *iseq = cfp->iseq;
1760  rb_hook_list_t *local_hooks = iseq->aux.exec.local_hooks;
1761 
1762  switch (VM_FRAME_TYPE(ec->cfp)) {
1763  case VM_FRAME_MAGIC_METHOD:
1765  EXEC_EVENT_HOOK_AND_POP_FRAME(ec, RUBY_EVENT_RETURN, ec->cfp->self, 0, 0, 0, frame_return_value(err));
1766 
1767  if (UNLIKELY(local_hooks && local_hooks->events & RUBY_EVENT_RETURN)) {
1768  rb_exec_event_hook_orig(ec, local_hooks, RUBY_EVENT_RETURN,
1769  ec->cfp->self, 0, 0, 0, frame_return_value(err), TRUE);
1770  }
1771 
1772  THROW_DATA_CONSUMED_SET(err);
1773  break;
1774  case VM_FRAME_MAGIC_BLOCK:
1775  if (VM_FRAME_BMETHOD_P(ec->cfp)) {
1776  EXEC_EVENT_HOOK(ec, RUBY_EVENT_B_RETURN, ec->cfp->self, 0, 0, 0, frame_return_value(err));
1777  if (UNLIKELY(local_hooks && local_hooks->events & RUBY_EVENT_B_RETURN)) {
1778  rb_exec_event_hook_orig(ec, local_hooks, RUBY_EVENT_B_RETURN,
1779  ec->cfp->self, 0, 0, 0, frame_return_value(err), FALSE);
1780  }
1781 
1782  if (!will_finish_vm_exec) {
1784 
1785  /* kick RUBY_EVENT_RETURN at invoke_block_from_c() for bmethod */
1790  frame_return_value(err));
1791 
1793  local_hooks = me->def->body.bmethod.hooks;
1794 
1795  if (UNLIKELY(local_hooks && local_hooks->events & RUBY_EVENT_RETURN)) {
1796  rb_exec_event_hook_orig(ec, local_hooks, RUBY_EVENT_RETURN, ec->cfp->self,
1800  frame_return_value(err), TRUE);
1801  }
1802  }
1803  THROW_DATA_CONSUMED_SET(err);
1804  }
1805  else {
1806  EXEC_EVENT_HOOK_AND_POP_FRAME(ec, RUBY_EVENT_B_RETURN, ec->cfp->self, 0, 0, 0, frame_return_value(err));
1807  if (UNLIKELY(local_hooks && local_hooks->events & RUBY_EVENT_B_RETURN)) {
1808  rb_exec_event_hook_orig(ec, local_hooks, RUBY_EVENT_B_RETURN,
1809  ec->cfp->self, 0, 0, 0, frame_return_value(err), TRUE);
1810  }
1811  THROW_DATA_CONSUMED_SET(err);
1812  }
1813  break;
1814  case VM_FRAME_MAGIC_CLASS:
1816  break;
1817  }
1818  }
1819 }
1820 
1821 /* evaluator body */
1822 
1823 /* finish
1824  VMe (h1) finish
1825  VM finish F1 F2
1826  cfunc finish F1 F2 C1
1827  rb_funcall finish F1 F2 C1
1828  VMe finish F1 F2 C1
1829  VM finish F1 F2 C1 F3
1830 
1831  F1 - F3 : pushed by VM
1832  C1 : pushed by send insn (CFUNC)
1833 
1834  struct CONTROL_FRAME {
1835  VALUE *pc; // cfp[0], program counter
1836  VALUE *sp; // cfp[1], stack pointer
1837  rb_iseq_t *iseq; // cfp[2], iseq
1838  VALUE self; // cfp[3], self
1839  const VALUE *ep; // cfp[4], env pointer
1840  const void *block_code; // cfp[5], block code
1841  };
1842 
1843  struct rb_captured_block {
1844  VALUE self;
1845  VALUE *ep;
1846  union code;
1847  };
1848 
1849  struct METHOD_ENV {
1850  VALUE param0;
1851  ...
1852  VALUE paramN;
1853  VALUE lvar1;
1854  ...
1855  VALUE lvarM;
1856  VALUE cref; // ep[-2]
1857  VALUE special; // ep[-1]
1858  VALUE flags; // ep[ 0] == lep[0]
1859  };
1860 
1861  struct BLOCK_ENV {
1862  VALUE block_param0;
1863  ...
1864  VALUE block_paramN;
1865  VALUE block_lvar1;
1866  ...
1867  VALUE block_lvarM;
1868  VALUE cref; // ep[-2]
1869  VALUE special; // ep[-1]
1870  VALUE flags; // ep[ 0]
1871  };
1872 
1873  struct CLASS_ENV {
1874  VALUE class_lvar0;
1875  ...
1876  VALUE class_lvarN;
1877  VALUE cref;
1878  VALUE prev_ep; // for frame jump
1879  VALUE flags;
1880  };
1881 
1882  struct C_METHOD_CONTROL_FRAME {
1883  VALUE *pc; // 0
1884  VALUE *sp; // stack pointer
1885  rb_iseq_t *iseq; // cmi
1886  VALUE self; // ?
1887  VALUE *ep; // ep == lep
1888  void *code; //
1889  };
1890 
1891  struct C_BLOCK_CONTROL_FRAME {
1892  VALUE *pc; // point only "finish" insn
1893  VALUE *sp; // sp
1894  rb_iseq_t *iseq; // ?
1895  VALUE self; //
1896  VALUE *ep; // ep
1897  void *code; //
1898  };
1899 
1900  If mjit_exec is already called before calling vm_exec, `mjit_enable_p` should
1901  be FALSE to avoid calling `mjit_exec` twice.
1902  */
1903 
1904 static inline VALUE
1905 vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state,
1906  VALUE errinfo, VALUE *initial);
1907 
1908 VALUE
1909 vm_exec(rb_execution_context_t *ec, int mjit_enable_p)
1910 {
1911  enum ruby_tag_type state;
1912  VALUE result = Qundef;
1913  VALUE initial = 0;
1914 
1915  EC_PUSH_TAG(ec);
1916 
1917  _tag.retval = Qnil;
1918  if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1919  if (!mjit_enable_p || (result = mjit_exec(ec)) == Qundef) {
1920  result = vm_exec_core(ec, initial);
1921  }
1922  goto vm_loop_start; /* fallback to the VM */
1923  }
1924  else {
1925  result = ec->errinfo;
1927  while ((result = vm_exec_handle_exception(ec, state, result, &initial)) == Qundef) {
1928  /* caught a jump, exec the handler */
1929  result = vm_exec_core(ec, initial);
1930  vm_loop_start:
1931  VM_ASSERT(ec->tag == &_tag);
1932  /* when caught `throw`, `tag.state` is set. */
1933  if ((state = _tag.state) == TAG_NONE) break;
1934  _tag.state = TAG_NONE;
1935  }
1936  }
1937  EC_POP_TAG();
1938  return result;
1939 }
1940 
1941 static inline VALUE
1942 vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state,
1943  VALUE errinfo, VALUE *initial)
1944 {
1945  struct vm_throw_data *err = (struct vm_throw_data *)errinfo;
1946 
1947  for (;;) {
1948  unsigned int i;
1949  const struct iseq_catch_table_entry *entry;
1950  const struct iseq_catch_table *ct;
1951  unsigned long epc, cont_pc, cont_sp;
1952  const rb_iseq_t *catch_iseq;
1954  VALUE type;
1955  const rb_control_frame_t *escape_cfp;
1956 
1957  cont_pc = cont_sp = 0;
1958  catch_iseq = NULL;
1959 
1960  while (ec->cfp->pc == 0 || ec->cfp->iseq == 0) {
1961  if (UNLIKELY(VM_FRAME_TYPE(ec->cfp) == VM_FRAME_MAGIC_CFUNC)) {
1969  }
1970  rb_vm_pop_frame(ec);
1971  }
1972 
1973  cfp = ec->cfp;
1974  epc = cfp->pc - cfp->iseq->body->iseq_encoded;
1975 
1976  escape_cfp = NULL;
1977  if (state == TAG_BREAK || state == TAG_RETURN) {
1978  escape_cfp = THROW_DATA_CATCH_FRAME(err);
1979 
1980  if (cfp == escape_cfp) {
1981  if (state == TAG_RETURN) {
1982  if (!VM_FRAME_FINISHED_P(cfp)) {
1983  THROW_DATA_CATCH_FRAME_SET(err, cfp + 1);
1984  THROW_DATA_STATE_SET(err, state = TAG_BREAK);
1985  }
1986  else {
1987  ct = cfp->iseq->body->catch_table;
1988  if (ct) for (i = 0; i < ct->size; i++) {
1989  entry = UNALIGNED_MEMBER_PTR(ct, entries[i]);
1990  if (entry->start < epc && entry->end >= epc) {
1991  if (entry->type == CATCH_TYPE_ENSURE) {
1992  catch_iseq = entry->iseq;
1993  cont_pc = entry->cont;
1994  cont_sp = entry->sp;
1995  break;
1996  }
1997  }
1998  }
1999  if (catch_iseq == NULL) {
2000  ec->errinfo = Qnil;
2001  THROW_DATA_CATCH_FRAME_SET(err, cfp + 1);
2002  hook_before_rewind(ec, ec->cfp, TRUE, state, err);
2003  rb_vm_pop_frame(ec);
2004  return THROW_DATA_VAL(err);
2005  }
2006  }
2007  /* through */
2008  }
2009  else {
2010  /* TAG_BREAK */
2011 #if OPT_STACK_CACHING
2012  *initial = THROW_DATA_VAL(err);
2013 #else
2014  *ec->cfp->sp++ = THROW_DATA_VAL(err);
2015 #endif
2016  ec->errinfo = Qnil;
2017  return Qundef;
2018  }
2019  }
2020  }
2021 
2022  if (state == TAG_RAISE) {
2023  ct = cfp->iseq->body->catch_table;
2024  if (ct) for (i = 0; i < ct->size; i++) {
2025  entry = UNALIGNED_MEMBER_PTR(ct, entries[i]);
2026  if (entry->start < epc && entry->end >= epc) {
2027 
2028  if (entry->type == CATCH_TYPE_RESCUE ||
2029  entry->type == CATCH_TYPE_ENSURE) {
2030  catch_iseq = entry->iseq;
2031  cont_pc = entry->cont;
2032  cont_sp = entry->sp;
2033  break;
2034  }
2035  }
2036  }
2037  }
2038  else if (state == TAG_RETRY) {
2039  ct = cfp->iseq->body->catch_table;
2040  if (ct) for (i = 0; i < ct->size; i++) {
2041  entry = UNALIGNED_MEMBER_PTR(ct, entries[i]);
2042  if (entry->start < epc && entry->end >= epc) {
2043 
2044  if (entry->type == CATCH_TYPE_ENSURE) {
2045  catch_iseq = entry->iseq;
2046  cont_pc = entry->cont;
2047  cont_sp = entry->sp;
2048  break;
2049  }
2050  else if (entry->type == CATCH_TYPE_RETRY) {
2051  const rb_control_frame_t *escape_cfp;
2052  escape_cfp = THROW_DATA_CATCH_FRAME(err);
2053  if (cfp == escape_cfp) {
2054  cfp->pc = cfp->iseq->body->iseq_encoded + entry->cont;
2055  ec->errinfo = Qnil;
2056  return Qundef;
2057  }
2058  }
2059  }
2060  }
2061  }
2062  else if (state == TAG_BREAK && !escape_cfp) {
2063  type = CATCH_TYPE_BREAK;
2064 
2065  search_restart_point:
2066  ct = cfp->iseq->body->catch_table;
2067  if (ct) for (i = 0; i < ct->size; i++) {
2068  entry = UNALIGNED_MEMBER_PTR(ct, entries[i]);
2069 
2070  if (entry->start < epc && entry->end >= epc) {
2071  if (entry->type == CATCH_TYPE_ENSURE) {
2072  catch_iseq = entry->iseq;
2073  cont_pc = entry->cont;
2074  cont_sp = entry->sp;
2075  break;
2076  }
2077  else if (entry->type == type) {
2078  cfp->pc = cfp->iseq->body->iseq_encoded + entry->cont;
2079  cfp->sp = vm_base_ptr(cfp) + entry->sp;
2080 
2081  if (state != TAG_REDO) {
2082 #if OPT_STACK_CACHING
2083  *initial = THROW_DATA_VAL(err);
2084 #else
2085  *ec->cfp->sp++ = THROW_DATA_VAL(err);
2086 #endif
2087  }
2088  ec->errinfo = Qnil;
2089  VM_ASSERT(ec->tag->state == TAG_NONE);
2090  return Qundef;
2091  }
2092  }
2093  }
2094  }
2095  else if (state == TAG_REDO) {
2096  type = CATCH_TYPE_REDO;
2097  goto search_restart_point;
2098  }
2099  else if (state == TAG_NEXT) {
2100  type = CATCH_TYPE_NEXT;
2101  goto search_restart_point;
2102  }
2103  else {
2104  ct = cfp->iseq->body->catch_table;
2105  if (ct) for (i = 0; i < ct->size; i++) {
2106  entry = UNALIGNED_MEMBER_PTR(ct, entries[i]);
2107  if (entry->start < epc && entry->end >= epc) {
2108 
2109  if (entry->type == CATCH_TYPE_ENSURE) {
2110  catch_iseq = entry->iseq;
2111  cont_pc = entry->cont;
2112  cont_sp = entry->sp;
2113  break;
2114  }
2115  }
2116  }
2117  }
2118 
2119  if (catch_iseq != NULL) { /* found catch table */
2120  /* enter catch scope */
2121  const int arg_size = 1;
2122 
2123  rb_iseq_check(catch_iseq);
2124  cfp->sp = vm_base_ptr(cfp) + cont_sp;
2125  cfp->pc = cfp->iseq->body->iseq_encoded + cont_pc;
2126 
2127  /* push block frame */
2128  cfp->sp[0] = (VALUE)err;
2129  vm_push_frame(ec, catch_iseq, VM_FRAME_MAGIC_RESCUE,
2130  cfp->self,
2132  0, /* cref or me */
2133  catch_iseq->body->iseq_encoded,
2134  cfp->sp + arg_size /* push value */,
2135  catch_iseq->body->local_table_size - arg_size,
2136  catch_iseq->body->stack_max);
2137 
2138  state = 0;
2139  ec->tag->state = TAG_NONE;
2140  ec->errinfo = Qnil;
2141 
2142  return Qundef;
2143  }
2144  else {
2145  hook_before_rewind(ec, ec->cfp, FALSE, state, err);
2146 
2147  if (VM_FRAME_FINISHED_P(ec->cfp)) {
2148  rb_vm_pop_frame(ec);
2149  ec->errinfo = (VALUE)err;
2150  ec->tag = ec->tag->prev;
2151  EC_JUMP_TAG(ec, state);
2152  }
2153  else {
2154  rb_vm_pop_frame(ec);
2155  }
2156  }
2157  }
2158 }
2159 
2160 /* misc */
2161 
2162 VALUE
2164 {
2166  VALUE val;
2167  vm_set_top_stack(ec, iseq);
2168  val = vm_exec(ec, TRUE);
2169  return val;
2170 }
2171 
2172 VALUE
2174 {
2176  VALUE val;
2177 
2178  vm_set_main_stack(ec, iseq);
2179  val = vm_exec(ec, TRUE);
2180  return val;
2181 }
2182 
2183 int
2185 {
2187 
2188  if (me) {
2189  if (idp) *idp = me->def->original_id;
2190  if (called_idp) *called_idp = me->called_id;
2191  if (klassp) *klassp = me->owner;
2192  return TRUE;
2193  }
2194  else {
2195  return FALSE;
2196  }
2197 }
2198 
2199 int
2200 rb_ec_frame_method_id_and_class(const rb_execution_context_t *ec, ID *idp, ID *called_idp, VALUE *klassp)
2201 {
2202  return rb_vm_control_frame_id_and_class(ec->cfp, idp, called_idp, klassp);
2203 }
2204 
2205 int
2207 {
2208  return rb_ec_frame_method_id_and_class(GET_EC(), idp, 0, klassp);
2209 }
2210 
2211 VALUE
2213  VALUE block_handler, VALUE filename)
2214 {
2216  const rb_control_frame_t *reg_cfp = ec->cfp;
2217  const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
2218  VALUE val;
2219 
2221  recv, block_handler,
2222  (VALUE)vm_cref_new_toplevel(ec), /* cref or me */
2223  0, reg_cfp->sp, 0, 0);
2224 
2225  val = (*func)(arg);
2226 
2227  rb_vm_pop_frame(ec);
2228  return val;
2229 }
2230 
2231 /* vm */
2232 
2233 void
2235 {
2236  if (ptr) {
2237  rb_vm_t *vm = ptr;
2239  }
2240 }
2241 
2242 void
2244 {
2245  RUBY_MARK_ENTER("vm");
2246  RUBY_GC_INFO("-------------------------------------------------\n");
2247  if (ptr) {
2248  rb_vm_t *vm = ptr;
2249  rb_thread_t *th = 0;
2250  long i, len;
2251  const VALUE *obj_ary;
2252 
2253  list_for_each(&vm->living_threads, th, vmlt_node) {
2254  rb_gc_mark(th->self);
2255  }
2258 
2260  obj_ary = RARRAY_CONST_PTR(vm->mark_object_ary);
2261  for (i=0; i < len; i++) {
2262  const VALUE *ptr;
2263  long j, jlen;
2264 
2265  rb_gc_mark(*obj_ary);
2266  jlen = RARRAY_LEN(*obj_ary);
2267  ptr = RARRAY_CONST_PTR(*obj_ary);
2268  for (j=0; j < jlen; j++) {
2269  rb_gc_mark(*ptr++);
2270  }
2271  obj_ary++;
2272  }
2273 
2274  rb_gc_mark(vm->load_path);
2280  rb_gc_mark(vm->top_self);
2283  /* Prevent classes from moving */
2285 
2286  if (vm->loading_table) {
2288  }
2289 
2291 
2293 
2294  mjit_mark();
2295  }
2296 
2297  RUBY_MARK_LEAVE("vm");
2298 }
2299 
2300 #undef rb_vm_register_special_exception
2301 void
2303 {
2304  rb_vm_t *vm = GET_VM();
2305  VALUE exc = rb_exc_new3(cls, rb_obj_freeze(mesg));
2306  OBJ_FREEZE(exc);
2307  ((VALUE *)vm->special_exceptions)[sp] = exc;
2309 }
2310 
2311 int
2313 {
2314  rb_vm_t *vm = GET_VM();
2315 
2316  st_insert(vm->defined_module_hash, (st_data_t)module, (st_data_t)module);
2317 
2318  return TRUE;
2319 }
2320 
2321 static int
2322 free_loading_table_entry(st_data_t key, st_data_t value, st_data_t arg)
2323 {
2324  xfree((char *)key);
2325  return ST_DELETE;
2326 }
2327 
2328 int
2330 {
2331  RUBY_FREE_ENTER("vm");
2332 
2333  if (vm) {
2334  rb_thread_t *th = vm->main_thread;
2335  struct rb_objspace *objspace = vm->objspace;
2336  vm->main_thread = 0;
2337  if (th) {
2339  thread_free(th);
2340  }
2341  rb_vm_living_threads_init(vm);
2342  ruby_vm_run_at_exit_hooks(vm);
2343  if (vm->loading_table) {
2344  st_foreach(vm->loading_table, free_loading_table_entry, 0);
2346  vm->loading_table = 0;
2347  }
2348  if (vm->frozen_strings) {
2350  vm->frozen_strings = 0;
2351  }
2352  rb_vm_gvl_destroy(vm);
2354  if (objspace) {
2355  rb_objspace_free(objspace);
2356  }
2357  /* after freeing objspace, you *can't* use ruby_xfree() */
2358  ruby_mimfree(vm);
2360  }
2361  RUBY_FREE_LEAVE("vm");
2362  return 0;
2363 }
2364 
2365 static size_t
2366 vm_memsize(const void *ptr)
2367 {
2368  const rb_vm_t *vmobj = ptr;
2369  size_t size = sizeof(rb_vm_t);
2370 
2371  size += vmobj->living_thread_num * sizeof(rb_thread_t);
2372 
2373  if (vmobj->defined_strings) {
2374  size += DEFINED_EXPR * sizeof(VALUE);
2375  }
2376  return size;
2377 }
2378 
2379 static const rb_data_type_t vm_data_type = {
2380  "VM",
2381  {NULL, NULL, vm_memsize,},
2383 };
2384 
2385 
2386 static VALUE
2387 vm_default_params(void)
2388 {
2389  rb_vm_t *vm = GET_VM();
2390  VALUE result = rb_hash_new_with_size(4);
2391 #define SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), SIZET2NUM(vm->default_params.name));
2392  SET(thread_vm_stack_size);
2393  SET(thread_machine_stack_size);
2394  SET(fiber_vm_stack_size);
2395  SET(fiber_machine_stack_size);
2396 #undef SET
2397  rb_obj_freeze(result);
2398  return result;
2399 }
2400 
2401 static size_t
2402 get_param(const char *name, size_t default_value, size_t min_value)
2403 {
2404  const char *envval;
2405  size_t result = default_value;
2406  if ((envval = getenv(name)) != 0) {
2407  long val = atol(envval);
2408  if (val < (long)min_value) {
2409  val = (long)min_value;
2410  }
2411  result = (size_t)(((val -1 + RUBY_VM_SIZE_ALIGN) / RUBY_VM_SIZE_ALIGN) * RUBY_VM_SIZE_ALIGN);
2412  }
2413  if (0) fprintf(stderr, "%s: %"PRIuSIZE"\n", name, result); /* debug print */
2414 
2415  return result;
2416 }
2417 
2418 static void
2419 check_machine_stack_size(size_t *sizep)
2420 {
2421 #ifdef PTHREAD_STACK_MIN
2422  size_t size = *sizep;
2423 #endif
2424 
2425 #ifdef PTHREAD_STACK_MIN
2426  if (size < PTHREAD_STACK_MIN) {
2427  *sizep = PTHREAD_STACK_MIN * 2;
2428  }
2429 #endif
2430 }
2431 
2432 static void
2433 vm_default_params_setup(rb_vm_t *vm)
2434 {
2436  get_param("RUBY_THREAD_VM_STACK_SIZE",
2439 
2441  get_param("RUBY_THREAD_MACHINE_STACK_SIZE",
2444 
2446  get_param("RUBY_FIBER_VM_STACK_SIZE",
2449 
2451  get_param("RUBY_FIBER_MACHINE_STACK_SIZE",
2454 
2455  /* environment dependent check */
2456  check_machine_stack_size(&vm->default_params.thread_machine_stack_size);
2457  check_machine_stack_size(&vm->default_params.fiber_machine_stack_size);
2458 }
2459 
2460 static void
2461 vm_init2(rb_vm_t *vm)
2462 {
2463  MEMZERO(vm, rb_vm_t, 1);
2464  rb_vm_living_threads_init(vm);
2466  vm->src_encoding_index = -1;
2467 
2468  vm_default_params_setup(vm);
2469 }
2470 
2471 void
2473 {
2474  /* update VM stack */
2475  if (ec->vm_stack) {
2476  VM_ASSERT(ec->cfp);
2477 
2478  rb_control_frame_t *cfp = ec->cfp;
2479  rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
2480 
2481  while (cfp != limit_cfp) {
2482  const VALUE *ep = cfp->ep;
2486 
2487  if (!VM_ENV_LOCAL_P(ep)) {
2488  VALUE *prev_ep = (VALUE *)VM_ENV_PREV_EP(ep);
2489  if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
2491  }
2492  }
2493 
2495  }
2496  }
2497 }
2498 
2499 void
2501 {
2502  /* mark VM stack */
2503  if (ec->vm_stack) {
2504  VM_ASSERT(ec->cfp);
2505  VALUE *p = ec->vm_stack;
2506  VALUE *sp = ec->cfp->sp;
2507  rb_control_frame_t *cfp = ec->cfp;
2508  rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
2509 
2510  rb_gc_mark_vm_stack_values((long)(sp - p), p);
2511 
2512  while (cfp != limit_cfp) {
2513  const VALUE *ep = cfp->ep;
2514  VM_ASSERT(!!VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED) == vm_ep_in_heap_p_(ec, ep));
2518 
2519  if (!VM_ENV_LOCAL_P(ep)) {
2520  const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
2521  if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
2523  }
2524  }
2525 
2527  }
2528  }
2529 
2530  /* mark machine stack */
2531  if (ec->machine.stack_start && ec->machine.stack_end &&
2532  ec != GET_EC() /* marked for current ec at the first stage of marking */
2533  ) {
2535  rb_gc_mark_locations((VALUE *)&ec->machine.regs,
2536  (VALUE *)(&ec->machine.regs) +
2537  sizeof(ec->machine.regs) / (sizeof(VALUE)));
2538  }
2539 
2546 }
2547 
2548 void rb_fiber_mark_self(rb_fiber_t *fib);
2549 void rb_fiber_update_self(rb_fiber_t *fib);
2552 
2553 static void
2554 thread_compact(void *ptr)
2555 {
2556  rb_thread_t *th = ptr;
2558 
2560 
2562 }
2563 
2564 static void
2565 thread_mark(void *ptr)
2566 {
2567  rb_thread_t *th = ptr;
2568  RUBY_MARK_ENTER("thread");
2570 
2571  /* mark ruby objects */
2572  switch (th->invoke_type) {
2573  case thread_invoke_type_proc:
2576  break;
2577  case thread_invoke_type_func:
2579  break;
2580  default:
2581  break;
2582  }
2583 
2591 
2592  /* Ensure EC stack objects are pinned */
2598 
2599  RUBY_MARK_LEAVE("thread");
2600 }
2601 
2602 static void
2603 thread_free(void *ptr)
2604 {
2605  rb_thread_t *th = ptr;
2606  RUBY_FREE_ENTER("thread");
2607 
2608  if (th->locking_mutex != Qfalse) {
2609  rb_bug("thread_free: locking_mutex must be NULL (%p:%p)", (void *)th, (void *)th->locking_mutex);
2610  }
2611  if (th->keeping_mutexes != NULL) {
2612  rb_bug("thread_free: keeping_mutexes must be NULL (%p:%p)", (void *)th, (void *)th->keeping_mutexes);
2613  }
2614 
2616 
2617  if (th->vm && th->vm->main_thread == th) {
2618  RUBY_GC_INFO("main thread\n");
2619  }
2620  else {
2621  ruby_xfree(ptr);
2622  }
2623 
2624  RUBY_FREE_LEAVE("thread");
2625 }
2626 
2627 static size_t
2628 thread_memsize(const void *ptr)
2629 {
2630  const rb_thread_t *th = ptr;
2631  size_t size = sizeof(rb_thread_t);
2632 
2633  if (!th->root_fiber) {
2634  size += th->ec->vm_stack_size * sizeof(VALUE);
2635  }
2636  if (th->ec->local_storage) {
2637  size += st_memsize(th->ec->local_storage);
2638  }
2639  return size;
2640 }
2641 
2642 #define thread_data_type ruby_threadptr_data_type
2644  "VM/thread",
2645  {
2646  thread_mark,
2647  thread_free,
2648  thread_memsize,
2649  thread_compact,
2650  },
2652 };
2653 
2654 VALUE
2656 {
2658  return Qtrue;
2659  }
2660  else {
2661  return Qfalse;
2662  }
2663 }
2664 
2665 static VALUE
2666 thread_alloc(VALUE klass)
2667 {
2668  VALUE obj;
2669  rb_thread_t *th;
2671 
2672  return obj;
2673 }
2674 
2675 inline void
2677 {
2678  ec->vm_stack = stack;
2679  ec->vm_stack_size = size;
2680 }
2681 
2682 void
2684 {
2685  rb_ec_set_vm_stack(ec, stack, size);
2686 
2687  ec->cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
2688 
2689  vm_push_frame(ec,
2690  NULL /* dummy iseq */,
2692  Qnil /* dummy self */, VM_BLOCK_HANDLER_NONE /* dummy block ptr */,
2693  0 /* dummy cref/me */,
2694  0 /* dummy pc */, ec->vm_stack, 0, 0
2695  );
2696 }
2697 
2698 void
2700 {
2701  rb_ec_set_vm_stack(ec, NULL, 0);
2702 
2703  // Avoid dangling pointers:
2704  ec->cfp = NULL;
2705 }
2706 
2707 static void
2708 th_init(rb_thread_t *th, VALUE self)
2709 {
2710  th->self = self;
2712 
2713  if (self == 0) {
2714  size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE);
2716  }
2717  else {
2718  VM_ASSERT(th->ec->cfp == NULL);
2719  VM_ASSERT(th->ec->vm_stack == NULL);
2720  VM_ASSERT(th->ec->vm_stack_size == 0);
2721  }
2722 
2723  th->status = THREAD_RUNNABLE;
2724  th->last_status = Qnil;
2725  th->ec->errinfo = Qnil;
2726  th->ec->root_svar = Qfalse;
2729 #ifdef NON_SCALAR_THREAD_ID
2730  th->thread_id_string[0] = '\0';
2731 #endif
2732 
2733 #if OPT_CALL_THREADED_CODE
2734  th->retval = Qundef;
2735 #endif
2736  th->name = Qnil;
2738 }
2739 
2740 static VALUE
2741 ruby_thread_init(VALUE self)
2742 {
2743  rb_thread_t *th = rb_thread_ptr(self);
2744  rb_vm_t *vm = GET_THREAD()->vm;
2745 
2746  th->vm = vm;
2747  th_init(th, self);
2748 
2749  th->top_wrapper = 0;
2750  th->top_self = rb_vm_top_self();
2751  th->ec->root_svar = Qfalse;
2752  return self;
2753 }
2754 
2755 VALUE
2757 {
2758  VALUE self = thread_alloc(klass);
2759  ruby_thread_init(self);
2760  return self;
2761 }
2762 
2763 #define REWIND_CFP(expr) do { \
2764  rb_execution_context_t *ec__ = GET_EC(); \
2765  VALUE *const curr_sp = (ec__->cfp++)->sp; \
2766  VALUE *const saved_sp = ec__->cfp->sp; \
2767  ec__->cfp->sp = curr_sp; \
2768  expr; \
2769  (ec__->cfp--)->sp = saved_sp; \
2770 } while (0)
2771 
2772 static VALUE
2773 m_core_set_method_alias(VALUE self, VALUE cbase, VALUE sym1, VALUE sym2)
2774 {
2775  REWIND_CFP({
2776  rb_alias(cbase, SYM2ID(sym1), SYM2ID(sym2));
2777  });
2778  return Qnil;
2779 }
2780 
2781 static VALUE
2782 m_core_set_variable_alias(VALUE self, VALUE sym1, VALUE sym2)
2783 {
2784  REWIND_CFP({
2785  rb_alias_variable(SYM2ID(sym1), SYM2ID(sym2));
2786  });
2787  return Qnil;
2788 }
2789 
2790 static VALUE
2791 m_core_undef_method(VALUE self, VALUE cbase, VALUE sym)
2792 {
2793  REWIND_CFP({
2794  rb_undef(cbase, SYM2ID(sym));
2796  });
2797  return Qnil;
2798 }
2799 
2800 static VALUE
2801 m_core_set_postexe(VALUE self)
2802 {
2804  return Qnil;
2805 }
2806 
2807 static VALUE core_hash_merge_kwd(VALUE hash, VALUE kw);
2808 
2809 static VALUE
2810 core_hash_merge(VALUE hash, long argc, const VALUE *argv)
2811 {
2812  Check_Type(hash, T_HASH);
2813  VM_ASSERT(argc % 2 == 0);
2814  rb_hash_bulk_insert(argc, argv, hash);
2815  return hash;
2816 }
2817 
2818 static VALUE
2819 m_core_hash_merge_ptr(int argc, VALUE *argv, VALUE recv)
2820 {
2821  VALUE hash = argv[0];
2822 
2823  REWIND_CFP(hash = core_hash_merge(hash, argc-1, argv+1));
2824 
2825  return hash;
2826 }
2827 
2828 static int
2829 kwmerge_i(VALUE key, VALUE value, VALUE hash)
2830 {
2831  rb_hash_aset(hash, key, value);
2832  return ST_CONTINUE;
2833 }
2834 
2835 static VALUE
2836 m_core_hash_merge_kwd(VALUE recv, VALUE hash, VALUE kw)
2837 {
2838  REWIND_CFP(hash = core_hash_merge_kwd(hash, kw));
2839  return hash;
2840 }
2841 
2842 static VALUE
2843 core_hash_merge_kwd(VALUE hash, VALUE kw)
2844 {
2845  rb_hash_foreach(rb_to_hash_type(kw), kwmerge_i, hash);
2846  return hash;
2847 }
2848 
2849 /* Returns true if JIT is enabled */
2850 static VALUE
2851 mjit_enabled_p(VALUE _)
2852 {
2853  return mjit_enabled ? Qtrue : Qfalse;
2854 }
2855 
2856 static VALUE
2857 mjit_pause_m(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
2858 {
2859  VALUE options = Qnil;
2860  VALUE wait = Qtrue;
2861  rb_scan_args(argc, argv, "0:", &options);
2862 
2863  if (!NIL_P(options)) {
2864  static ID keyword_ids[1];
2865  if (!keyword_ids[0])
2866  keyword_ids[0] = rb_intern("wait");
2867  rb_get_kwargs(options, keyword_ids, 0, 1, &wait);
2868  }
2869 
2870  return mjit_pause(RTEST(wait));
2871 }
2872 
2873 static VALUE
2874 mjit_resume_m(VALUE _)
2875 {
2876  return mjit_resume();
2877 }
2878 
2879 extern VALUE *rb_gc_stack_start;
2880 extern size_t rb_gc_stack_maxsize;
2881 
2882 /* debug functions */
2883 
2884 /* :nodoc: */
2885 static VALUE
2886 sdr(VALUE self)
2887 {
2889  return Qnil;
2890 }
2891 
2892 /* :nodoc: */
2893 static VALUE
2894 nsdr(VALUE self)
2895 {
2896  VALUE ary = rb_ary_new();
2897 #if HAVE_BACKTRACE
2898 #include <execinfo.h>
2899 #define MAX_NATIVE_TRACE 1024
2900  static void *trace[MAX_NATIVE_TRACE];
2901  int n = (int)backtrace(trace, MAX_NATIVE_TRACE);
2902  char **syms = backtrace_symbols(trace, n);
2903  int i;
2904 
2905  if (syms == 0) {
2906  rb_memerror();
2907  }
2908 
2909  for (i=0; i<n; i++) {
2910  rb_ary_push(ary, rb_str_new2(syms[i]));
2911  }
2912  free(syms); /* OK */
2913 #endif
2914  return ary;
2915 }
2916 
2917 #if VM_COLLECT_USAGE_DETAILS
2918 static VALUE usage_analysis_insn_start(VALUE self);
2919 static VALUE usage_analysis_operand_start(VALUE self);
2920 static VALUE usage_analysis_register_start(VALUE self);
2921 static VALUE usage_analysis_insn_stop(VALUE self);
2922 static VALUE usage_analysis_operand_stop(VALUE self);
2923 static VALUE usage_analysis_register_stop(VALUE self);
2924 static VALUE usage_analysis_insn_running(VALUE self);
2925 static VALUE usage_analysis_operand_running(VALUE self);
2926 static VALUE usage_analysis_register_running(VALUE self);
2927 static VALUE usage_analysis_insn_clear(VALUE self);
2928 static VALUE usage_analysis_operand_clear(VALUE self);
2929 static VALUE usage_analysis_register_clear(VALUE self);
2930 #endif
2931 
2932 static VALUE
2933 f_raise(int c, VALUE *v, VALUE _)
2934 {
2935  return rb_f_raise(c, v);
2936 }
2937 
2938 static VALUE
2939 f_proc(VALUE _)
2940 {
2941  return rb_block_proc();
2942 }
2943 
2944 static VALUE
2945 f_lambda(VALUE _)
2946 {
2947  return rb_block_lambda();
2948 }
2949 
2950 void
2951 Init_VM(void)
2952 {
2953  VALUE opts;
2954  VALUE klass;
2955  VALUE fcore;
2956  VALUE mjit;
2957 
2958  /*
2959  * Document-class: RubyVM
2960  *
2961  * The RubyVM module only exists on MRI. +RubyVM+ is not defined in
2962  * other Ruby implementations such as JRuby and TruffleRuby.
2963  *
2964  * The RubyVM module provides some access to MRI internals.
2965  * This module is for very limited purposes, such as debugging,
2966  * prototyping, and research. Normal users must not use it.
2967  * This module is not portable between Ruby implementations.
2968  */
2969  rb_cRubyVM = rb_define_class("RubyVM", rb_cObject);
2972  rb_define_singleton_method(rb_cRubyVM, "stat", vm_stat, -1);
2973 #if USE_DEBUG_COUNTER
2974  rb_define_singleton_method(rb_cRubyVM, "reset_debug_counters", rb_debug_counter_reset, 0);
2975  rb_define_singleton_method(rb_cRubyVM, "show_debug_counters", rb_debug_counter_show, 0);
2976 #endif
2977 
2978  /* FrozenCore (hidden) */
2979  fcore = rb_class_new(rb_cBasicObject);
2980  RBASIC(fcore)->flags = T_ICLASS;
2981  klass = rb_singleton_class(fcore);
2982  rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3);
2983  rb_define_method_id(klass, id_core_set_variable_alias, m_core_set_variable_alias, 2);
2984  rb_define_method_id(klass, id_core_undef_method, m_core_undef_method, 2);
2985  rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 0);
2986  rb_define_method_id(klass, id_core_hash_merge_ptr, m_core_hash_merge_ptr, -1);
2987  rb_define_method_id(klass, id_core_hash_merge_kwd, m_core_hash_merge_kwd, 2);
2988  rb_define_method_id(klass, id_core_raise, f_raise, -1);
2989  rb_define_method_id(klass, idProc, f_proc, 0);
2990  rb_define_method_id(klass, idLambda, f_lambda, 0);
2991  rb_obj_freeze(fcore);
2995  rb_mRubyVMFrozenCore = fcore;
2996 
2997  /* ::RubyVM::MJIT
2998  * Provides access to the Method JIT compiler of MRI.
2999  * Of course, this module is MRI specific.
3000  */
3001  mjit = rb_define_module_under(rb_cRubyVM, "MJIT");
3002  rb_define_singleton_method(mjit, "enabled?", mjit_enabled_p, 0);
3003  rb_define_singleton_method(mjit, "pause", mjit_pause_m, -1);
3004  rb_define_singleton_method(mjit, "resume", mjit_resume_m, 0);
3005 
3006  /*
3007  * Document-class: Thread
3008  *
3009  * Threads are the Ruby implementation for a concurrent programming model.
3010  *
3011  * Programs that require multiple threads of execution are a perfect
3012  * candidate for Ruby's Thread class.
3013  *
3014  * For example, we can create a new thread separate from the main thread's
3015  * execution using ::new.
3016  *
3017  * thr = Thread.new { puts "What's the big deal" }
3018  *
3019  * Then we are able to pause the execution of the main thread and allow
3020  * our new thread to finish, using #join:
3021  *
3022  * thr.join #=> "What's the big deal"
3023  *
3024  * If we don't call +thr.join+ before the main thread terminates, then all
3025  * other threads including +thr+ will be killed.
3026  *
3027  * Alternatively, you can use an array for handling multiple threads at
3028  * once, like in the following example:
3029  *
3030  * threads = []
3031  * threads << Thread.new { puts "What's the big deal" }
3032  * threads << Thread.new { 3.times { puts "Threads are fun!" } }
3033  *
3034  * After creating a few threads we wait for them all to finish
3035  * consecutively.
3036  *
3037  * threads.each { |thr| thr.join }
3038  *
3039  * To retrieve the last value of a thread, use #value
3040  *
3041  * thr = Thread.new { sleep 1; "Useful value" }
3042  * thr.value #=> "Useful value"
3043  *
3044  * === Thread initialization
3045  *
3046  * In order to create new threads, Ruby provides ::new, ::start, and
3047  * ::fork. A block must be provided with each of these methods, otherwise
3048  * a ThreadError will be raised.
3049  *
3050  * When subclassing the Thread class, the +initialize+ method of your
3051  * subclass will be ignored by ::start and ::fork. Otherwise, be sure to
3052  * call super in your +initialize+ method.
3053  *
3054  * === Thread termination
3055  *
3056  * For terminating threads, Ruby provides a variety of ways to do this.
3057  *
3058  * The class method ::kill, is meant to exit a given thread:
3059  *
3060  * thr = Thread.new { sleep }
3061  * Thread.kill(thr) # sends exit() to thr
3062  *
3063  * Alternatively, you can use the instance method #exit, or any of its
3064  * aliases #kill or #terminate.
3065  *
3066  * thr.exit
3067  *
3068  * === Thread status
3069  *
3070  * Ruby provides a few instance methods for querying the state of a given
3071  * thread. To get a string with the current thread's state use #status
3072  *
3073  * thr = Thread.new { sleep }
3074  * thr.status # => "sleep"
3075  * thr.exit
3076  * thr.status # => false
3077  *
3078  * You can also use #alive? to tell if the thread is running or sleeping,
3079  * and #stop? if the thread is dead or sleeping.
3080  *
3081  * === Thread variables and scope
3082  *
3083  * Since threads are created with blocks, the same rules apply to other
3084  * Ruby blocks for variable scope. Any local variables created within this
3085  * block are accessible to only this thread.
3086  *
3087  * ==== Fiber-local vs. Thread-local
3088  *
3089  * Each fiber has its own bucket for Thread#[] storage. When you set a
3090  * new fiber-local it is only accessible within this Fiber. To illustrate:
3091  *
3092  * Thread.new {
3093  * Thread.current[:foo] = "bar"
3094  * Fiber.new {
3095  * p Thread.current[:foo] # => nil
3096  * }.resume
3097  * }.join
3098  *
3099  * This example uses #[] for getting and #[]= for setting fiber-locals,
3100  * you can also use #keys to list the fiber-locals for a given
3101  * thread and #key? to check if a fiber-local exists.
3102  *
3103  * When it comes to thread-locals, they are accessible within the entire
3104  * scope of the thread. Given the following example:
3105  *
3106  * Thread.new{
3107  * Thread.current.thread_variable_set(:foo, 1)
3108  * p Thread.current.thread_variable_get(:foo) # => 1
3109  * Fiber.new{
3110  * Thread.current.thread_variable_set(:foo, 2)
3111  * p Thread.current.thread_variable_get(:foo) # => 2
3112  * }.resume
3113  * p Thread.current.thread_variable_get(:foo) # => 2
3114  * }.join
3115  *
3116  * You can see that the thread-local +:foo+ carried over into the fiber
3117  * and was changed to +2+ by the end of the thread.
3118  *
3119  * This example makes use of #thread_variable_set to create new
3120  * thread-locals, and #thread_variable_get to reference them.
3121  *
3122  * There is also #thread_variables to list all thread-locals, and
3123  * #thread_variable? to check if a given thread-local exists.
3124  *
3125  * === Exception handling
3126  *
3127  * When an unhandled exception is raised inside a thread, it will
3128  * terminate. By default, this exception will not propagate to other
3129  * threads. The exception is stored and when another thread calls #value
3130  * or #join, the exception will be re-raised in that thread.
3131  *
3132  * t = Thread.new{ raise 'something went wrong' }
3133  * t.value #=> RuntimeError: something went wrong
3134  *
3135  * An exception can be raised from outside the thread using the
3136  * Thread#raise instance method, which takes the same parameters as
3137  * Kernel#raise.
3138  *
3139  * Setting Thread.abort_on_exception = true, Thread#abort_on_exception =
3140  * true, or $DEBUG = true will cause a subsequent unhandled exception
3141  * raised in a thread to be automatically re-raised in the main thread.
3142  *
3143  * With the addition of the class method ::handle_interrupt, you can now
3144  * handle exceptions asynchronously with threads.
3145  *
3146  * === Scheduling
3147  *
3148  * Ruby provides a few ways to support scheduling threads in your program.
3149  *
3150  * The first way is by using the class method ::stop, to put the current
3151  * running thread to sleep and schedule the execution of another thread.
3152  *
3153  * Once a thread is asleep, you can use the instance method #wakeup to
3154  * mark your thread as eligible for scheduling.
3155  *
3156  * You can also try ::pass, which attempts to pass execution to another
3157  * thread but is dependent on the OS whether a running thread will switch
3158  * or not. The same goes for #priority, which lets you hint to the thread
3159  * scheduler which threads you want to take precedence when passing
3160  * execution. This method is also dependent on the OS and may be ignored
3161  * on some platforms.
3162  *
3163  */
3164  rb_cThread = rb_define_class("Thread", rb_cObject);
3166 
3167 #if VM_COLLECT_USAGE_DETAILS
3168  /* ::RubyVM::USAGE_ANALYSIS_* */
3169 #define define_usage_analysis_hash(name) /* shut up rdoc -C */ \
3170  rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_" #name, rb_hash_new())
3171  define_usage_analysis_hash(INSN);
3172  define_usage_analysis_hash(REGS);
3173  define_usage_analysis_hash(INSN_BIGRAM);
3174 
3175  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_INSN_START", usage_analysis_insn_start, 0);
3176  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_OPERAND_START", usage_analysis_operand_start, 0);
3177  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_REGISTER_START", usage_analysis_register_start, 0);
3178  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_INSN_STOP", usage_analysis_insn_stop, 0);
3179  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_OPERAND_STOP", usage_analysis_operand_stop, 0);
3180  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_REGISTER_STOP", usage_analysis_register_stop, 0);
3181  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_INSN_RUNNING", usage_analysis_insn_running, 0);
3182  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_OPERAND_RUNNING", usage_analysis_operand_running, 0);
3183  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_REGISTER_RUNNING", usage_analysis_register_running, 0);
3184  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_INSN_CLEAR", usage_analysis_insn_clear, 0);
3185  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_OPERAND_CLEAR", usage_analysis_operand_clear, 0);
3186  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_REGISTER_CLEAR", usage_analysis_register_clear, 0);
3187 #endif
3188 
3189  /* ::RubyVM::OPTS
3190  * An Array of VM build options.
3191  * This constant is MRI specific.
3192  */
3193  rb_define_const(rb_cRubyVM, "OPTS", opts = rb_ary_new());
3194 
3195 #if OPT_DIRECT_THREADED_CODE
3196  rb_ary_push(opts, rb_str_new2("direct threaded code"));
3197 #elif OPT_TOKEN_THREADED_CODE
3198  rb_ary_push(opts, rb_str_new2("token threaded code"));
3199 #elif OPT_CALL_THREADED_CODE
3200  rb_ary_push(opts, rb_str_new2("call threaded code"));
3201 #endif
3202 
3203 #if OPT_STACK_CACHING
3204  rb_ary_push(opts, rb_str_new2("stack caching"));
3205 #endif
3206 #if OPT_OPERANDS_UNIFICATION
3207  rb_ary_push(opts, rb_str_new2("operands unification"));
3208 #endif
3209 #if OPT_INSTRUCTIONS_UNIFICATION
3210  rb_ary_push(opts, rb_str_new2("instructions unification"));
3211 #endif
3212 #if OPT_INLINE_METHOD_CACHE
3213  rb_ary_push(opts, rb_str_new2("inline method cache"));
3214 #endif
3215 #if OPT_BLOCKINLINING
3216  rb_ary_push(opts, rb_str_new2("block inlining"));
3217 #endif
3218 
3219  /* ::RubyVM::INSTRUCTION_NAMES
3220  * A list of bytecode instruction names in MRI.
3221  * This constant is MRI specific.
3222  */
3223  rb_define_const(rb_cRubyVM, "INSTRUCTION_NAMES", rb_insns_name_array());
3224 
3225  /* ::RubyVM::DEFAULT_PARAMS
3226  * This constant exposes the VM's default parameters.
3227  * Note that changing these values does not affect VM execution.
3228  * Specification is not stable and you should not depend on this value.
3229  * Of course, this constant is MRI specific.
3230  */
3231  rb_define_const(rb_cRubyVM, "DEFAULT_PARAMS", vm_default_params());
3232 
3233  /* debug functions ::RubyVM::SDR(), ::RubyVM::NSDR() */
3234 #if VMDEBUG
3235  rb_define_singleton_method(rb_cRubyVM, "SDR", sdr, 0);
3236  rb_define_singleton_method(rb_cRubyVM, "NSDR", nsdr, 0);
3237 #else
3238  (void)sdr;
3239  (void)nsdr;
3240 #endif
3241 
3242  /* VM bootstrap: phase 2 */
3243  {
3245  rb_thread_t *th = GET_THREAD();
3246  VALUE filename = rb_fstring_lit("<main>");
3247  const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
3248 
3249  /* create vm object */
3250  vm->self = TypedData_Wrap_Struct(rb_cRubyVM, &vm_data_type, vm);
3251 
3252  /* create main thread */
3254  vm->main_thread = th;
3255  vm->running_thread = th;
3256  th->vm = vm;
3257  th->top_wrapper = 0;
3258  th->top_self = rb_vm_top_self();
3259  rb_thread_set_current(th);
3260 
3261  rb_vm_living_threads_insert(vm, th);
3262 
3264  th->ec->cfp->iseq = iseq;
3265  th->ec->cfp->pc = iseq->body->iseq_encoded;
3266  th->ec->cfp->self = th->top_self;
3267 
3268  VM_ENV_FLAGS_UNSET(th->ec->cfp->ep, VM_FRAME_FLAG_CFRAME);
3269  VM_STACK_ENV_WRITE(th->ec->cfp->ep, VM_ENV_DATA_INDEX_ME_CREF, (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, FALSE, NULL, FALSE));
3270 
3271  /*
3272  * The Binding of the top level scope
3273  */
3274  rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new());
3275  }
3276  vm_init_redefined_flag();
3277 
3283 
3284  /* vm_backtrace.c */
3286 }
3287 
3288 void
3290 {
3291  rb_thread_t *th = GET_VM()->main_thread;
3292  rb_control_frame_t *cfp = (void *)(th->ec->vm_stack + th->ec->vm_stack_size);
3293  --cfp;
3294 
3296 }
3297 
3298 extern const struct st_hash_type rb_fstring_hash_type;
3299 
3300 void
3302 {
3303  /* VM bootstrap: phase 1 */
3304  rb_vm_t * vm = ruby_mimmalloc(sizeof(*vm));
3305  rb_thread_t * th = ruby_mimmalloc(sizeof(*th));
3306  if (!vm || !th) {
3307  fprintf(stderr, "[FATAL] failed to allocate memory\n");
3308  exit(EXIT_FAILURE);
3309  }
3310  MEMZERO(th, rb_thread_t, 1);
3311  vm_init2(vm);
3312 
3313  vm->objspace = rb_objspace_alloc();
3314  ruby_current_vm_ptr = vm;
3315 
3316  Init_native_thread(th);
3317  th->vm = vm;
3318  th_init(th, 0);
3319  rb_thread_set_current_raw(th);
3321 }
3322 
3323 void
3325 {
3326  rb_vm_t *vm = GET_VM();
3327 
3329 
3330  /* initialize mark object array, hash */
3331  vm->mark_object_ary = rb_ary_tmp_new(128);
3334 
3336 }
3337 
3338 /* top self */
3339 
3340 static VALUE
3341 main_to_s(VALUE obj)
3342 {
3343  return rb_str_new2("main");
3344 }
3345 
3346 VALUE
3348 {
3349  return GET_VM()->top_self;
3350 }
3351 
3352 void
3354 {
3355  rb_vm_t *vm = GET_VM();
3356 
3358  rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0);
3359  rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s");
3360 }
3361 
3362 static VALUE *
3363 ruby_vm_verbose_ptr(rb_vm_t *vm)
3364 {
3365  return &vm->verbose;
3366 }
3367 
3368 static VALUE *
3369 ruby_vm_debug_ptr(rb_vm_t *vm)
3370 {
3371  return &vm->debug;
3372 }
3373 
3374 VALUE *
3376 {
3377  return ruby_vm_verbose_ptr(GET_VM());
3378 }
3379 
3380 VALUE *
3382 {
3383  return ruby_vm_debug_ptr(GET_VM());
3384 }
3385 
3386 /* iseq.c */
3388  VALUE insn, int op_no, VALUE op,
3389  int len, size_t pos, VALUE *pnop, VALUE child);
3390 
3391 st_table *
3393 {
3394  return GET_VM()->frozen_strings;
3395 }
3396 
3397 #if VM_COLLECT_USAGE_DETAILS
3398 
3399 #define HASH_ASET(h, k, v) rb_hash_aset((h), (st_data_t)(k), (st_data_t)(v))
3400 
3401 /* uh = {
3402  * insn(Fixnum) => ihash(Hash)
3403  * }
3404  * ihash = {
3405  * -1(Fixnum) => count, # insn usage
3406  * 0(Fixnum) => ophash, # operand usage
3407  * }
3408  * ophash = {
3409  * val(interned string) => count(Fixnum)
3410  * }
3411  */
3412 static void
3413 vm_analysis_insn(int insn)
3414 {
3415  ID usage_hash;
3416  ID bigram_hash;
3417  static int prev_insn = -1;
3418 
3419  VALUE uh;
3420  VALUE ihash;
3421  VALUE cv;
3422 
3423  CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3424  CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
3425  uh = rb_const_get(rb_cRubyVM, usage_hash);
3426  if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
3427  ihash = rb_hash_new();
3428  HASH_ASET(uh, INT2FIX(insn), ihash);
3429  }
3430  if ((cv = rb_hash_aref(ihash, INT2FIX(-1))) == Qnil) {
3431  cv = INT2FIX(0);
3432  }
3433  HASH_ASET(ihash, INT2FIX(-1), INT2FIX(FIX2INT(cv) + 1));
3434 
3435  /* calc bigram */
3436  if (prev_insn != -1) {
3437  VALUE bi;
3438  VALUE ary[2];
3439  VALUE cv;
3440 
3441  ary[0] = INT2FIX(prev_insn);
3442  ary[1] = INT2FIX(insn);
3443  bi = rb_ary_new4(2, &ary[0]);
3444 
3445  uh = rb_const_get(rb_cRubyVM, bigram_hash);
3446  if ((cv = rb_hash_aref(uh, bi)) == Qnil) {
3447  cv = INT2FIX(0);
3448  }
3449  HASH_ASET(uh, bi, INT2FIX(FIX2INT(cv) + 1));
3450  }
3451  prev_insn = insn;
3452 }
3453 
3454 static void
3455 vm_analysis_operand(int insn, int n, VALUE op)
3456 {
3457  ID usage_hash;
3458 
3459  VALUE uh;
3460  VALUE ihash;
3461  VALUE ophash;
3462  VALUE valstr;
3463  VALUE cv;
3464 
3465  CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3466 
3467  uh = rb_const_get(rb_cRubyVM, usage_hash);
3468  if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
3469  ihash = rb_hash_new();
3470  HASH_ASET(uh, INT2FIX(insn), ihash);
3471  }
3472  if ((ophash = rb_hash_aref(ihash, INT2FIX(n))) == Qnil) {
3473  ophash = rb_hash_new();
3474  HASH_ASET(ihash, INT2FIX(n), ophash);
3475  }
3476  /* intern */
3477  valstr = rb_insn_operand_intern(GET_EC()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
3478 
3479  /* set count */
3480  if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) {
3481  cv = INT2FIX(0);
3482  }
3483  HASH_ASET(ophash, valstr, INT2FIX(FIX2INT(cv) + 1));
3484 }
3485 
3486 static void
3487 vm_analysis_register(int reg, int isset)
3488 {
3489  ID usage_hash;
3490  VALUE uh;
3491  VALUE valstr;
3492  static const char regstrs[][5] = {
3493  "pc", /* 0 */
3494  "sp", /* 1 */
3495  "ep", /* 2 */
3496  "cfp", /* 3 */
3497  "self", /* 4 */
3498  "iseq", /* 5 */
3499  };
3500  static const char getsetstr[][4] = {
3501  "get",
3502  "set",
3503  };
3504  static VALUE syms[sizeof(regstrs) / sizeof(regstrs[0])][2];
3505 
3506  VALUE cv;
3507 
3508  CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
3509  if (syms[0] == 0) {
3510  char buff[0x10];
3511  int i;
3512 
3513  for (i = 0; i < (int)(sizeof(regstrs) / sizeof(regstrs[0])); i++) {
3514  int j;
3515  for (j = 0; j < 2; j++) {
3516  snprintf(buff, 0x10, "%d %s %-4s", i, getsetstr[j], regstrs[i]);
3517  syms[i][j] = ID2SYM(rb_intern(buff));
3518  }
3519  }
3520  }
3521  valstr = syms[reg][isset];
3522 
3523  uh = rb_const_get(rb_cRubyVM, usage_hash);
3524  if ((cv = rb_hash_aref(uh, valstr)) == Qnil) {
3525  cv = INT2FIX(0);
3526  }
3527  HASH_ASET(uh, valstr, INT2FIX(FIX2INT(cv) + 1));
3528 }
3529 
3530 #undef HASH_ASET
3531 
3532 static void (*ruby_vm_collect_usage_func_insn)(int insn) = NULL;
3533 static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = NULL;
3534 static void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = NULL;
3535 
3536 /* :nodoc: */
3537 static VALUE
3538 usage_analysis_insn_start(VALUE self)
3539 {
3540  ruby_vm_collect_usage_func_insn = vm_analysis_insn;
3541  return Qnil;
3542 }
3543 
3544 /* :nodoc: */
3545 static VALUE
3546 usage_analysis_operand_start(VALUE self)
3547 {
3548  ruby_vm_collect_usage_func_operand = vm_analysis_operand;
3549  return Qnil;
3550 }
3551 
3552 /* :nodoc: */
3553 static VALUE
3554 usage_analysis_register_start(VALUE self)
3555 {
3556  ruby_vm_collect_usage_func_register = vm_analysis_register;
3557  return Qnil;
3558 }
3559 
3560 /* :nodoc: */
3561 static VALUE
3562 usage_analysis_insn_stop(VALUE self)
3563 {
3564  ruby_vm_collect_usage_func_insn = 0;
3565  return Qnil;
3566 }
3567 
3568 /* :nodoc: */
3569 static VALUE
3570 usage_analysis_operand_stop(VALUE self)
3571 {
3572  ruby_vm_collect_usage_func_operand = 0;
3573  return Qnil;
3574 }
3575 
3576 /* :nodoc: */
3577 static VALUE
3578 usage_analysis_register_stop(VALUE self)
3579 {
3580  ruby_vm_collect_usage_func_register = 0;
3581  return Qnil;
3582 }
3583 
3584 /* :nodoc: */
3585 static VALUE
3586 usage_analysis_insn_running(VALUE self)
3587 {
3588  if (ruby_vm_collect_usage_func_insn == 0) return Qfalse;
3589  return Qtrue;
3590 }
3591 
3592 /* :nodoc: */
3593 static VALUE
3594 usage_analysis_operand_running(VALUE self)
3595 {
3596  if (ruby_vm_collect_usage_func_operand == 0) return Qfalse;
3597  return Qtrue;
3598 }
3599 
3600 /* :nodoc: */
3601 static VALUE
3602 usage_analysis_register_running(VALUE self)
3603 {
3604  if (ruby_vm_collect_usage_func_register == 0) return Qfalse;
3605  return Qtrue;
3606 }
3607 
3608 /* :nodoc: */
3609 static VALUE
3610 usage_analysis_insn_clear(VALUE self)
3611 {
3612  ID usage_hash;
3613  ID bigram_hash;
3614  VALUE uh;
3615  VALUE bh;
3616 
3617  CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3618  CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
3619  uh = rb_const_get(rb_cRubyVM, usage_hash);
3620  bh = rb_const_get(rb_cRubyVM, bigram_hash);
3621  rb_hash_clear(uh);
3622  rb_hash_clear(bh);
3623 
3624  return Qtrue;
3625 }
3626 
3627 /* :nodoc: */
3628 static VALUE
3629 usage_analysis_operand_clear(VALUE self)
3630 {
3631  ID usage_hash;
3632  VALUE uh;
3633 
3634  CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3635  uh = rb_const_get(rb_cRubyVM, usage_hash);
3636  rb_hash_clear(uh);
3637 
3638  return Qtrue;
3639 }
3640 
3641 /* :nodoc: */
3642 static VALUE
3643 usage_analysis_register_clear(VALUE self)
3644 {
3645  ID usage_hash;
3646  VALUE uh;
3647 
3648  CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
3649  uh = rb_const_get(rb_cRubyVM, usage_hash);
3650  rb_hash_clear(uh);
3651 
3652  return Qtrue;
3653 }
3654 
3655 #else
3656 
3657 MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_insn)(int insn)) = NULL;
3658 MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)) = NULL;
3659 MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int isset)) = NULL;
3660 
3661 #endif
3662 
3663 #if VM_COLLECT_USAGE_DETAILS
3664 /* @param insn instruction number */
3665 static void
3666 vm_collect_usage_insn(int insn)
3667 {
3668  if (RUBY_DTRACE_INSN_ENABLED()) {
3670  }
3671  if (ruby_vm_collect_usage_func_insn)
3672  (*ruby_vm_collect_usage_func_insn)(insn);
3673 }
3674 
3675 /* @param insn instruction number
3676  * @param n n-th operand
3677  * @param op operand value
3678  */
3679 static void
3680 vm_collect_usage_operand(int insn, int n, VALUE op)
3681 {
3683  VALUE valstr;
3684 
3685  valstr = rb_insn_operand_intern(GET_EC()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
3686 
3688  RB_GC_GUARD(valstr);
3689  }
3690  if (ruby_vm_collect_usage_func_operand)
3691  (*ruby_vm_collect_usage_func_operand)(insn, n, op);
3692 }
3693 
3694 /* @param reg register id. see code of vm_analysis_register() */
3695 /* @param isset 0: read, 1: write */
3696 static void
3697 vm_collect_usage_register(int reg, int isset)
3698 {
3699  if (ruby_vm_collect_usage_func_register)
3700  (*ruby_vm_collect_usage_func_register)(reg, isset);
3701 }
3702 #endif
3703 
3704 #endif /* #ifndef MJIT_HEADER */
3705 
3706 #include "vm_call_iseq_optimized.inc" /* required from vm_insnhelper.c */
rb_cArray
VALUE rb_cArray
Definition: array.c:27
rb_iseq_realpath
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
Definition: iseq.c:1033
NEXT_CLASS_SERIAL
#define NEXT_CLASS_SERIAL()
Definition: vm_insnhelper.h:188
METHOD_VISI_PRIVATE
@ METHOD_VISI_PRIVATE
Definition: method.h:29
rb_vm_struct::running_thread
const struct rb_thread_struct * running_thread
Definition: vm_core.h:584
rb_ec_set_vm_stack
void rb_ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
Definition: vm.c:2676
RUBY_DTRACE_METHOD_RETURN_HOOK
#define RUBY_DTRACE_METHOD_RETURN_HOOK(ec, klass, id)
Definition: probes_helper.h:33
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5425
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
ID
unsigned long ID
Definition: ruby.h:103
rb_to_hash_type
VALUE rb_to_hash_type(VALUE hash)
Definition: hash.c:1840
list_for_each
#define list_for_each(h, i, member)
Definition: rb_mjit_min_header-2.7.1.h:9021
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:10169
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
rb_fstring_hash_type
const struct st_hash_type rb_fstring_hash_type
Definition: string.c:260
rb_block_type
rb_block_type
Definition: vm_core.h:744
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5703
rb_f_raise
VALUE rb_f_raise(int argc, VALUE *argv)
Definition: eval.c:727
rb_id2name
const char * rb_id2name(ID)
Definition: symbol.c:801
rb_define_method_id
void rb_define_method_id(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1542
rb_block::proc
VALUE proc
Definition: vm_core.h:755
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
rb_vm_add_root_module
int rb_vm_add_root_module(ID id, VALUE module)
Definition: vm.c:2312
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
rb_hook_list_struct
Definition: vm_core.h:565
rb_fiber_mark_self
void rb_fiber_mark_self(rb_fiber_t *fib)
TRUE
#define TRUE
Definition: nkf.h:175
rb_vm_update_references
void rb_vm_update_references(void *ptr)
Definition: vm.c:2234
long
#define long
Definition: rb_mjit_min_header-2.7.1.h:2848
ruby_current_execution_context_ptr
rb_execution_context_t * ruby_current_execution_context_ptr
Definition: vm.c:373
rb_at_exit_list::func
rb_vm_at_exit_func * func
Definition: vm_core.h:556
block_handler_type_iseq
@ block_handler_type_iseq
Definition: vm_core.h:738
rb_vm_jump_tag_but_local_jump
void rb_vm_jump_tag_but_local_jump(int state)
Definition: vm.c:1510
iseq_insn_data
Definition: compile.c:74
rb_iseq_eval
VALUE rb_iseq_eval(const rb_iseq_t *iseq)
Definition: vm.c:2163
ruby_mimmalloc
void * ruby_mimmalloc(size_t size)
Definition: gc.c:10206
rb_vm_struct::objspace
struct rb_objspace * objspace
Definition: vm_core.h:651
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_execution_context_struct::private_const_reference
VALUE private_const_reference
Definition: vm_core.h:883
idProc
@ idProc
Definition: rb_mjit_min_header-2.7.1.h:8631
RUBY_MARK_LEAVE
#define RUBY_MARK_LEAVE(msg)
Definition: gc.h:56
rb_thread_alloc
VALUE rb_thread_alloc(VALUE klass)
Definition: vm.c:2756
rb_thread_struct::top_self
VALUE top_self
Definition: vm_core.h:923
THREAD_RUNNABLE
@ THREAD_RUNNABLE
Definition: vm_core.h:783
iseq_catch_table_entry::iseq
rb_iseq_t * iseq
Definition: iseq.h:247
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13179
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.1.h:5324
VM_FRAME_FLAG_FINISH
@ VM_FRAME_FLAG_FINISH
Definition: vm_core.h:1177
id
const int id
Definition: nkf.c:209
rb_vm_struct::thread_report_on_exception
unsigned int thread_report_on_exception
Definition: vm_core.h:604
rb_exc_new3
#define rb_exc_new3
Definition: intern.h:293
env
#define env
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_thread_struct::invoke_type
enum rb_thread_struct::@190 invoke_type
rb_iseq_struct
Definition: vm_core.h:456
ruby_value_type
ruby_value_type
Definition: ruby.h:486
rb_vm_invoke_proc
MJIT_FUNC_EXPORTED VALUE rb_vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler)
Definition: vm.c:1249
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1523
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7065
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
vm_method.c
VM_METHOD_TYPE_OPTIMIZED
@ VM_METHOD_TYPE_OPTIMIZED
Kernel::send, Proc::call, etc.
Definition: method.h:111
entries
struct iseq_catch_table_entry entries[]
Definition: rb_mjit_min_header-2.7.1.h:10752
rb_gc_update_tbl_refs
void rb_gc_update_tbl_refs(st_table *ptr)
Definition: gc.c:7985
VM_GUARDED_PREV_EP
#define VM_GUARDED_PREV_EP(ep)
Definition: vm_core.h:1290
VM_FRAME_MAGIC_METHOD
@ VM_FRAME_MAGIC_METHOD
Definition: vm_core.h:1163
RUBY_GC_INFO
#define RUBY_GC_INFO
Definition: gc.h:59
gc.h
rb_insns_name_array
VALUE rb_insns_name_array(void)
Definition: compile.c:8767
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1986
rb_execution_context_struct::local_storage
st_table * local_storage
Definition: vm_core.h:860
rb_binding_new
VALUE rb_binding_new(void)
Definition: proc.c:364
SET
#define SET(name, attr)
id_core_raise
@ id_core_raise
Definition: id.h:128
rb_vm_struct::thread_machine_stack_size
size_t thread_machine_stack_size
Definition: vm_core.h:664
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5417
rb_hash_clear
VALUE rb_hash_clear(VALUE hash)
Definition: hash.c:2764
VM_ENV_DATA_INDEX_ME_CREF
#define VM_ENV_DATA_INDEX_ME_CREF
Definition: vm_core.h:1193
bp
#define bp()
Definition: internal.h:1445
PROCDEBUG
#define PROCDEBUG
Definition: vm.c:355
ruby_current_vm_ptr
rb_vm_t * ruby_current_vm_ptr
Definition: vm.c:372
rb_binding_t::pathobj
const VALUE pathobj
Definition: vm_core.h:1070
rb_block::captured
struct rb_captured_block captured
Definition: vm_core.h:753
iseq_catch_table_entry::cont
unsigned int cont
Definition: iseq.h:251
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
VM_TAGGED_PTR_REF
#define VM_TAGGED_PTR_REF(v, mask)
Definition: vm_core.h:1146
rb_gc_mark_locations
void rb_gc_mark_locations(const VALUE *start, const VALUE *end)
Definition: gc.c:4701
VM_ENV_FLAG_ESCAPED
@ VM_ENV_FLAG_ESCAPED
Definition: vm_core.h:1187
ruby_vm_event_local_num
unsigned int ruby_vm_event_local_num
Definition: vm.c:377
rb_next_class_serial
rb_serial_t rb_next_class_serial(void)
Definition: vm.c:358
rb_thread_struct::top_wrapper
VALUE top_wrapper
Definition: vm_core.h:924
rb_callable_method_entry_struct::owner
const VALUE owner
Definition: method.h:64
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
EXEC_EVENT_HOOK
#define EXEC_EVENT_HOOK(ec_, flag_, self_, id_, called_id_, klass_, data_)
Definition: vm_core.h:1935
rb_proc_t::block
const struct rb_block block
Definition: vm_core.h:1050
rb_iseq_new_top
rb_iseq_t * rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
Definition: iseq.c:769
rb_objspace
Definition: gc.c:676
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2032
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:653
VALUE
unsigned long VALUE
Definition: ruby.h:102
GET_VM
#define GET_VM()
Definition: vm_core.h:1764
PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN
Definition: rb_mjit_min_header-2.7.1.h:4075
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
rb_ast_body_struct
Definition: node.h:394
rb_clear_method_cache_by_class
void rb_clear_method_cache_by_class(VALUE)
Definition: vm_method.c:93
FALSE_REDEFINED_OP_FLAG
#define FALSE_REDEFINED_OP_FLAG
Definition: vm_core.h:714
rb_intern
#define rb_intern(str)
rb_scope_visi_struct::method_visi
rb_method_visibility_t method_visi
Definition: rb_mjit_min_header-2.7.1.h:8698
OPTIMIZED_METHOD_TYPE_BLOCK_CALL
@ OPTIMIZED_METHOD_TYPE_BLOCK_CALL
Definition: method.h:159
rb_thread_struct::invoke_arg
union rb_thread_struct::@189 invoke_arg
RUBY_DTRACE_INSN
#define RUBY_DTRACE_INSN(insns_name)
Definition: rb_mjit_min_header-2.7.1.h:11221
rb_vm_make_jump_tag_but_local_jump
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
Definition: vm.c:1478
block_type_symbol
@ block_type_symbol
Definition: vm_core.h:747
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
VM_FRAME_MAGIC_CFUNC
@ VM_FRAME_MAGIC_CFUNC
Definition: vm_core.h:1167
rb_callable_method_entry_struct
Definition: method.h:59
rb_gc_location
VALUE rb_gc_location(VALUE value)
Definition: gc.c:8113
rb_thread_struct::proc
VALUE proc
Definition: vm_core.h:965
iseq_catch_table_entry
Definition: iseq.h:225
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:2048
rb_cProc
RUBY_EXTERN VALUE rb_cProc
Definition: ruby.h:2038
ruby_vm_event_enabled_global_flags
rb_event_flag_t ruby_vm_event_enabled_global_flags
Definition: vm.c:376
rb_binding_add_dynavars
const VALUE * rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars)
Definition: vm.c:984
VM_FRAME_FLAG_CFRAME
@ VM_FRAME_FLAG_CFRAME
Definition: vm_core.h:1179
block_handler_type_proc
@ block_handler_type_proc
Definition: vm_core.h:741
rb_vm_cframe_empty_keyword_p
int rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp)
Definition: vm.c:109
INTEGER_REDEFINED_OP_FLAG
#define INTEGER_REDEFINED_OP_FLAG
Definition: vm_core.h:703
imemo_iseq
@ imemo_iseq
Definition: internal.h:1140
rb_method_definition_struct::type
rb_method_type_t type
Definition: rb_mjit_min_header-2.7.1.h:8804
RUBY_EVENT_END
#define RUBY_EVENT_END
Definition: ruby.h:2244
VM_ENV_DATA_SIZE
#define VM_ENV_DATA_SIZE
Definition: vm_core.h:1191
rb_thread_struct::func
VALUE(* func)(void *)
Definition: vm_core.h:970
rb_vm_call_cfunc
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename)
Definition: vm.c:2212
ruby_vm_at_exit
void ruby_vm_at_exit(void(*func)(rb_vm_t *))
Definition: vm.c:623
iseq_catch_table_entry::end
unsigned int end
Definition: iseq.h:250
rb_id_table_iterator_result
rb_id_table_iterator_result
Definition: id_table.h:8
rb_cFloat
RUBY_EXTERN VALUE rb_cFloat
Definition: ruby.h:2028
ruby_vm_class_serial
rb_serial_t ruby_vm_class_serial
Definition: vm.c:381
RUBY_VM_SIZE_ALIGN
#define RUBY_VM_SIZE_ALIGN
Definition: vm_core.h:674
rb_vm_struct::default_params
struct rb_vm_struct::@185 default_params
rb_method_entry_at
const rb_method_entry_t * rb_method_entry_at(VALUE obj, ID id)
Definition: vm_method.c:756
rb_iseq_path
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:1027
getenv
#define getenv(name)
Definition: win32.c:73
rb_vm_mark
void rb_vm_mark(void *ptr)
Definition: vm.c:2243
EC_JUMP_TAG
#define EC_JUMP_TAG(ec, st)
Definition: eval_intern.h:184
rb_vm_struct::loaded_features
VALUE loaded_features
Definition: vm_core.h:619
rb_vm_struct::living_thread_num
int living_thread_num
Definition: vm_core.h:597
ruby_dtrace_method_hook_args::name
volatile VALUE name
Definition: probes_helper.h:12
rb_iseq_constant_body::location
rb_iseq_location_t location
Definition: vm_core.h:399
idCall
@ idCall
Definition: rb_mjit_min_header-2.7.1.h:8654
vm_exec
#define vm_exec
Definition: vm.c:15
rb_sourcefile
const char * rb_sourcefile(void)
Definition: vm.c:1331
rb_execution_context_struct::tag
struct rb_vm_tag * tag
Definition: vm_core.h:849
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5562
VM_ENV_DATA_INDEX_SPECVAL
#define VM_ENV_DATA_INDEX_SPECVAL
Definition: vm_core.h:1194
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
SYMBOL_REDEFINED_OP_FLAG
#define SYMBOL_REDEFINED_OP_FLAG
Definition: vm_core.h:709
RUBY_EVENT_B_RETURN
#define RUBY_EVENT_B_RETURN
Definition: ruby.h:2254
rb_method_visibility_t
rb_method_visibility_t
Definition: method.h:26
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.1.h:13426
rb_vm_ep_local_ep
const VALUE * rb_vm_ep_local_ep(const VALUE *ep)
Definition: vm.c:75
vm_check_canary
#define vm_check_canary(ec, sp)
Definition: vm_insnhelper.c:257
rb_vm_tag::prev
struct rb_vm_tag * prev
Definition: vm_core.h:803
Qundef
#define Qundef
Definition: ruby.h:470
THROW_DATA_P
#define THROW_DATA_P(err)
Definition: internal.h:1201
RUBY_VM_THREAD_MACHINE_STACK_SIZE
#define RUBY_VM_THREAD_MACHINE_STACK_SIZE
Definition: vm_core.h:678
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
rb_ruby_debug_ptr
VALUE * rb_ruby_debug_ptr(void)
Definition: vm.c:3381
rb_dtrace_setup
MJIT_FUNC_EXPORTED int rb_dtrace_setup(rb_execution_context_t *ec, VALUE klass, ID id, struct ruby_dtrace_method_hook_args *args)
Definition: vm.c:392
rb_captured_block::self
VALUE self
Definition: vm_core.h:728
EXIT_FAILURE
#define EXIT_FAILURE
Definition: eval_intern.h:32
Regexp
typedefRUBY_SYMBOL_EXPORT_BEGIN struct re_pattern_buffer Regexp
Definition: re.h:29
rb_vm_register_special_exception_str
void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE cls, VALUE mesg)
Definition: vm.c:2302
VM_FRAME_MAGIC_IFUNC
@ VM_FRAME_MAGIC_IFUNC
Definition: vm_core.h:1168
GET_EC
#define GET_EC()
Definition: vm_core.h:1766
NORETURN
NORETURN(static void vm_iter_break(rb_execution_context_t *ec, VALUE val))
ptr
struct RIMemo * ptr
Definition: debug.c:74
me
const rb_callable_method_entry_t * me
Definition: rb_mjit_min_header-2.7.1.h:13151
int8_t
__int8_t int8_t
Definition: rb_mjit_min_header-2.7.1.h:1160
VM_FRAME_FLAG_LAMBDA
@ VM_FRAME_FLAG_LAMBDA
Definition: vm_core.h:1180
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:1559
rb_iseq_new
rb_iseq_t * rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type type)
Definition: iseq.c:761
rb_vm_struct::at_exit
rb_at_exit_list * at_exit
Definition: vm_core.h:653
rb_vm_struct::expanded_load_path
VALUE expanded_load_path
Definition: vm_core.h:618
rb_iseq_constant_body::parent_iseq
const struct rb_iseq_struct * parent_iseq
Definition: vm_core.h:417
rb_cInteger
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:2031
rb_objspace_alloc
rb_objspace_t * rb_objspace_alloc(void)
Definition: gc.c:1587
dp
#define dp(v)
Definition: vm_debug.h:21
rb_iseq_struct::aux
union rb_iseq_struct::@181 aux
rb_gc_stack_start
VALUE * rb_gc_stack_start
RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
Definition: vm_core.h:687
id_core_undef_method
@ id_core_undef_method
Definition: id.h:122
st.h
NULL
#define NULL
Definition: _sdbm.c:101
vm.h
ST_DELETE
@ ST_DELETE
Definition: st.h:99
ruby_dtrace_method_hook_args::klass
volatile VALUE klass
Definition: probes_helper.h:11
rb_threadptr_root_fiber_release
void rb_threadptr_root_fiber_release(rb_thread_t *th)
Definition: cont.c:1895
rb_gc_mark_vm_stack_values
void rb_gc_mark_vm_stack_values(long n, const VALUE *values)
Definition: gc.c:4741
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
vm_debug.h
C
#define C(k)
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
FLOAT_REDEFINED_OP_FLAG
#define FLOAT_REDEFINED_OP_FLAG
Definition: vm_core.h:704
rb_vm_pop_cfunc_frame
MJIT_STATIC void rb_vm_pop_cfunc_frame(void)
Definition: vm.c:590
RUBY_EVENT_CALL
#define RUBY_EVENT_CALL
Definition: ruby.h:2245
rb_vm_cbase
VALUE rb_vm_cbase(void)
Definition: vm.c:1425
isset
#define isset(a, i)
Definition: rb_mjit_min_header-2.7.1.h:11010
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
rb_method_definition_struct::bmethod
rb_method_bmethod_t bmethod
Definition: method.h:174
iseq_catch_table::size
unsigned int size
Definition: rb_mjit_min_header-2.7.1.h:10785
id_core_hash_merge_kwd
@ id_core_hash_merge_kwd
Definition: id.h:127
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
rb_thread_struct::ec
rb_execution_context_t * ec
Definition: vm_core.h:915
VM_FRAME_MAGIC_CLASS
@ VM_FRAME_MAGIC_CLASS
Definition: vm_core.h:1165
RB_UNUSED_VAR
#define RB_UNUSED_VAR(x)
Definition: ruby.h:591
RUBY_DTRACE_INSN_OPERAND
#define RUBY_DTRACE_INSN_OPERAND(val, insns_name)
Definition: rb_mjit_min_header-2.7.1.h:11223
VM_ASSERT
#define VM_ASSERT(expr)
Definition: vm_core.h:56
rb_vm_struct::debug
VALUE debug
Definition: vm_core.h:645
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
rb_vm_cframe_keyword_p
int rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp)
Definition: vm.c:102
rb_imemo_new
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
Definition: gc.c:2308
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1575
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
ruby_dtrace_method_hook_args::methodname
const char * methodname
Definition: probes_helper.h:8
rb_vm_struct::load_path
VALUE load_path
Definition: vm_core.h:615
S
#define S(s)
rb_hash_new_with_size
MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:1529
VM_BLOCK_HANDLER_NONE
#define VM_BLOCK_HANDLER_NONE
Definition: vm_core.h:1291
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.1.h:13426
ruby_thread_init_stack
void ruby_thread_init_stack(rb_thread_t *th)
Definition: thread.c:647
RUBY_VM_FIBER_VM_STACK_SIZE
#define RUBY_VM_FIBER_VM_STACK_SIZE
Definition: vm_core.h:681
realpath
char * realpath(const char *__restrict path, char *__restrict resolved_path)
rb_control_frame_struct::sp
VALUE * sp
Definition: vm_core.h:762
rb_ast_body_struct::compile_option
VALUE compile_option
Definition: node.h:396
st_init_table_with_size
st_table * st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
Definition: st.c:577
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
Init_vm_objects
void Init_vm_objects(void)
Definition: vm.c:3324
rb_vm_struct::main_altstack
void * main_altstack
Definition: rb_mjit_min_header-2.7.1.h:9613
RCLASS_ORIGIN
#define RCLASS_ORIGIN(c)
Definition: internal.h:1075
idLambda
@ idLambda
Definition: rb_mjit_min_header-2.7.1.h:8632
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:847
rb_iseq_constant_body::local_table
const ID * local_table
Definition: vm_core.h:411
Init_native_thread
void Init_native_thread(rb_thread_t *th)
rb_callable_method_entry_struct::called_id
ID called_id
Definition: method.h:63
block_type_proc
@ block_type_proc
Definition: vm_core.h:748
void
void
Definition: rb_mjit_min_header-2.7.1.h:13198
rb_method_definition_struct::body
union rb_method_definition_struct::@118 body
rb_vm_frame_block_handler
VALUE rb_vm_frame_block_handler(const rb_control_frame_t *cfp)
Definition: vm.c:115
probes.h
rb_alias_variable
void rb_alias_variable(ID, ID)
Definition: variable.c:756
rb_alias
void rb_alias(VALUE, ID, ID)
Definition: vm_method.c:1581
RICLASS_IS_ORIGIN
#define RICLASS_IS_ORIGIN
Definition: internal.h:1085
MATCH
#define MATCH(s)
PRIuSIZE
#define PRIuSIZE
Definition: ruby.h:208
T_ICLASS
#define T_ICLASS
Definition: ruby.h:525
id_core_set_method_alias
@ id_core_set_method_alias
Definition: id.h:120
rb_block::type
enum rb_block_type type
Definition: vm_core.h:757
rb_scope_visi_struct::module_func
unsigned int module_func
Definition: method.h:37
rb_iseq_constant_body::param
struct rb_iseq_constant_body::@178 param
parameter information
RUBY_VM_FIBER_VM_STACK_SIZE_MIN
#define RUBY_VM_FIBER_VM_STACK_SIZE_MIN
Definition: vm_core.h:682
imemo_type
imemo_type
Definition: internal.h:1132
rb_cNilClass
RUBY_EXTERN VALUE rb_cNilClass
Definition: ruby.h:2036
rb_vm_cref_replace_with_duplicated_cref
rb_cref_t * rb_vm_cref_replace_with_duplicated_cref(void)
Definition: vm.c:1391
rb_eLocalJumpError
VALUE rb_eLocalJumpError
Definition: eval.c:34
rb_node_init
void rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
Definition: node.c:1095
rb_gc_mark_maybe
void rb_gc_mark_maybe(VALUE obj)
Definition: gc.c:5046
VM_ENV_DATA_INDEX_ENV
#define VM_ENV_DATA_INDEX_ENV
Definition: vm_core.h:1196
rb_vm_struct::coverages
VALUE coverages
Definition: vm_core.h:646
VM_FRAME_FLAG_PASSED
@ VM_FRAME_FLAG_PASSED
Definition: vm_core.h:1176
rb_id_table_foreach
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
Definition: id_table.c:292
rb_ec_clear_vm_stack
void rb_ec_clear_vm_stack(rb_execution_context_t *ec)
Definition: vm.c:2699
VM_FRAME_MAGIC_RESCUE
@ VM_FRAME_MAGIC_RESCUE
Definition: vm_core.h:1170
VM_UNREACHABLE
#define VM_UNREACHABLE(func)
Definition: vm_core.h:57
rb_cRubyVM
VALUE rb_cRubyVM
Definition: vm.c:365
rb_hook_list_struct::events
rb_event_flag_t events
Definition: vm_core.h:567
EC_POP_TAG
#define EC_POP_TAG()
Definition: eval_intern.h:137
TAG_REDO
#define TAG_REDO
Definition: vm_core.h:202
rb_cBasicObject
RUBY_EXTERN VALUE rb_cBasicObject
Definition: ruby.h:2009
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
RCLASS_M_TBL
#define RCLASS_M_TBL(c)
Definition: internal.h:1069
ruby_dtrace_method_hook_args::filename
const char * filename
Definition: probes_helper.h:9
rb_captured_block::ep
const VALUE * ep
Definition: vm_core.h:729
ruby_vm_event_flags
rb_event_flag_t ruby_vm_event_flags
Definition: vm.c:375
cfp
rb_control_frame_t * cfp
Definition: rb_mjit_min_header-2.7.1.h:14481
rb_str_concat_literals
VALUE rb_str_concat_literals(size_t, const VALUE *)
Definition: string.c:2974
rb_vm_make_binding
VALUE rb_vm_make_binding(const rb_execution_context_t *ec, const rb_control_frame_t *src_cfp)
Definition: vm.c:953
rb_vm_struct::main_thread
struct rb_thread_struct * main_thread
Definition: vm_core.h:581
rb_vm_block_copy
void rb_vm_block_copy(VALUE obj, const struct rb_block *dst, const struct rb_block *src)
Definition: vm.c:885
HASH_REDEFINED_OP_FLAG
#define HASH_REDEFINED_OP_FLAG
Definition: vm_core.h:707
ruby_dtrace_method_hook_args::line_no
int line_no
Definition: probes_helper.h:10
TIME_REDEFINED_OP_FLAG
#define TIME_REDEFINED_OP_FLAG
Definition: vm_core.h:710
rb_vm_invoke_bmethod
VALUE rb_vm_invoke_bmethod(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE block_handler, const rb_callable_method_entry_t *me)
Definition: vm.c:1242
iseq.h
rb_vm_t
struct rb_vm_struct rb_vm_t
rb_iseq_location_struct::label
VALUE label
Definition: vm_core.h:275
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
rb_iseq_constant_body::local_table_size
unsigned int local_table_size
Definition: vm_core.h:435
cbase
VALUE cbase
Definition: rb_mjit_min_header-2.7.1.h:16070
wait
int wait(int *status)
Definition: win32.c:5189
rb_block_param_proxy
VALUE rb_block_param_proxy
Definition: vm.c:368
rb_thread_struct::status
enum rb_thread_status status
Definition: rb_mjit_min_header-2.7.1.h:9817
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
rb_serial_t
unsigned long rb_serial_t
Definition: internal.h:1014
METHOD
Definition: proc.c:33
rb_thread_struct::thgroup
VALUE thgroup
Definition: vm_core.h:943
rb_vm_top_self
VALUE rb_vm_top_self(void)
Definition: vm.c:3347
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1509
rb_vm_struct::orig_progname
VALUE orig_progname
Definition: vm_core.h:645
rb_cSymbol
RUBY_EXTERN VALUE rb_cSymbol
Definition: ruby.h:2046
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
Definition: ruby.h:1131
sym
#define sym(x)
Definition: date_core.c:3716
OP
#define OP(mid_, bop_)
VM_METHOD_TYPE_CFUNC
@ VM_METHOD_TYPE_CFUNC
C method.
Definition: method.h:103
rb_fiber_reset_root_local_storage
void rb_fiber_reset_root_local_storage(rb_thread_t *th)
Definition: cont.c:2135
rb_vm_block_ep_update
void rb_vm_block_ep_update(VALUE obj, const struct rb_block *dst, const VALUE *ep)
Definition: vm.c:315
st_init_strtable
st_table * st_init_strtable(void)
Definition: st.c:668
rb_execution_context_struct::errinfo
VALUE errinfo
Definition: vm_core.h:875
RUBY_NSIG
#define RUBY_NSIG
Definition: vm_core.h:106
ruby_vm_redefined_flag
#define ruby_vm_redefined_flag
Definition: vm.c:370
CALL
#define CALL(n)
Definition: inits.c:16
rb_exc_new2
#define rb_exc_new2
Definition: intern.h:292
Init_VM
void Init_VM(void)
Definition: vm.c:2951
rb_iseq_constant_body::size
unsigned int size
Definition: vm_core.h:365
rb_execution_context_struct::passed_block_handler
VALUE passed_block_handler
Definition: vm_core.h:876
rb_cref_struct
CREF (Class REFerence)
Definition: method.h:41
mjit.h
rb_thread_t
struct rb_thread_struct rb_thread_t
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_vm_cref
rb_cref_t * rb_vm_cref(void)
Definition: vm.c:1384
DIV
#define DIV(n, d)
Definition: date_core.c:162
VM_ENV_FLAG_LOCAL
@ VM_ENV_FLAG_LOCAL
Definition: vm_core.h:1186
vars
const VALUE int int int int int int VALUE * vars[]
Definition: rb_mjit_min_header-2.7.1.h:6423
Init_vm_backtrace
void Init_vm_backtrace(void)
Definition: vm_backtrace.c:1045
rb_vm_struct::load_path_check_cache
VALUE load_path_check_cache
Definition: vm_core.h:617
st_hash_type
Definition: st.h:61
vm_throw_data
THROW_DATA.
Definition: internal.h:1193
VM_METHOD_TYPE_BMETHOD
@ VM_METHOD_TYPE_BMETHOD
Definition: method.h:106
rb_iseq_constant_body::catch_table
struct iseq_catch_table * catch_table
Definition: vm_core.h:414
rb_block::as
union rb_block::@187 as
rb_vm_cref_in_context
const rb_cref_t * rb_vm_cref_in_context(VALUE self, VALUE cbase)
Definition: vm.c:1400
EC_EXEC_TAG
#define EC_EXEC_TAG()
Definition: eval_intern.h:181
rb_env_t
Definition: vm_core.h:1055
rb_vm_struct::special_exceptions
const VALUE special_exceptions[ruby_special_error_count]
Definition: vm_core.h:611
rb_lastline_set
void rb_lastline_set(VALUE val)
Definition: vm.c:1322
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
rb_binding_t::block
const struct rb_block block
Definition: vm_core.h:1069
Init_top_self
void Init_top_self(void)
Definition: vm.c:3353
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
vm_core.h
rb_hash_bulk_insert
void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
Definition: hash.c:4584
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
rb_iseq_local_variables
VALUE rb_iseq_local_variables(const rb_iseq_t *iseq)
Definition: vm.c:849
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_gc_mark_machine_stack
void rb_gc_mark_machine_stack(const rb_execution_context_t *ec)
Definition: gc.c:4983
ALWAYS_INLINE
ALWAYS_INLINE(static VALUE invoke_iseq_block_from_c(rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler, const rb_cref_t *cref, int is_lambda, const rb_callable_method_entry_t *me))
RBASIC_CLASS
#define RBASIC_CLASS(obj)
Definition: ruby.h:906
rb_cFalseClass
RUBY_EXTERN VALUE rb_cFalseClass
Definition: ruby.h:2022
rb_execution_context_struct::vm_stack
VALUE * vm_stack
Definition: vm_core.h:845
Init_BareVM
void Init_BareVM(void)
Definition: vm.c:3301
ALLOC
#define ALLOC(type)
Definition: ruby.h:1664
rb_vm_struct::thread_vm_stack_size
size_t thread_vm_stack_size
Definition: vm_core.h:663
rb_vm_struct::fiber_vm_stack_size
size_t fiber_vm_stack_size
Definition: vm_core.h:665
T_CLASS
#define T_CLASS
Definition: ruby.h:524
AREF
#define AREF(s, idx)
Definition: cparse.c:97
RAISED_STACKOVERFLOW
@ RAISED_STACKOVERFLOW
Definition: eval_intern.h:255
RUBY_FREE_LEAVE
#define RUBY_FREE_LEAVE(msg)
Definition: gc.h:58
block_handler_type_ifunc
@ block_handler_type_ifunc
Definition: vm_core.h:739
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
rb_vm_struct::cmd
VALUE cmd[RUBY_NSIG]
Definition: vm_core.h:626
rb_vm_struct::verbose
VALUE verbose
Definition: vm_core.h:645
rb_fiber_struct
Definition: cont.c:226
size_t
unsigned int size_t
Definition: rb_mjit_min_header-2.7.1.h:660
rb_execution_context_struct::stack_start
VALUE * stack_start
Definition: vm_core.h:887
mjit_resume
VALUE mjit_resume(void)
probes_helper.h
mjit_enabled
#define mjit_enabled
Definition: internal.h:1765
RUBY_FREE_ENTER
#define RUBY_FREE_ENTER(msg)
Definition: gc.h:57
ruby_vm_destruct
int ruby_vm_destruct(rb_vm_t *vm)
Definition: vm.c:2329
rb_control_frame_struct
Definition: vm_core.h:760
MIN
#define MIN(a, b)
Definition: ffi.c:30
STRING_REDEFINED_OP_FLAG
#define STRING_REDEFINED_OP_FLAG
Definition: vm_core.h:705
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Definition: ruby.h:1179
StringValuePtr
#define StringValuePtr(v)
Definition: ruby.h:603
rb_at_exit_list
Definition: vm_core.h:555
size
int size
Definition: encoding.c:58
ruby_special_exceptions
ruby_special_exceptions
Definition: vm_core.h:506
FALSE
#define FALSE
Definition: nkf.h:174
rb_ast_body_struct::line_count
int line_count
Definition: node.h:397
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:1316
rb_thread_struct::root_fiber
rb_fiber_t * root_fiber
Definition: vm_core.h:985
rb_set_end_proc
void rb_set_end_proc(void(*func)(VALUE), VALUE data)
Definition: eval_jump.c:59
rb_gc_mark_movable
void rb_gc_mark_movable(VALUE ptr)
Definition: gc.c:5208
vm_insnhelper.c
rb_objspace_free
void rb_objspace_free(rb_objspace_t *objspace)
Definition: gc.c:1602
id_core_set_postexe
@ id_core_set_postexe
Definition: id.h:125
rb_proc_alloc
VALUE rb_proc_alloc(VALUE klass)
Definition: proc.c:145
TAG_RETRY
#define TAG_RETRY
Definition: vm_core.h:201
mjit_add_class_serial
void mjit_add_class_serial(rb_serial_t class_serial)
METHOD_VISI_PUBLIC
@ METHOD_VISI_PUBLIC
Definition: method.h:28
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1483
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1752
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1546
rb_vm_at_exit_func
void rb_vm_at_exit_func(struct rb_vm_struct *)
Definition: vm_core.h:553
rb_vm_tag::state
enum ruby_tag_type state
Definition: vm_core.h:804
arg_setup_method
@ arg_setup_method
Definition: vm_args.c:36
iseq_catch_table_entry::type
enum iseq_catch_table_entry::catch_type type
rb_vm_check_redefinition_by_prepend
void rb_vm_check_redefinition_by_prepend(VALUE klass)
Definition: vm.c:1631
REGEXP_REDEFINED_OP_FLAG
#define REGEXP_REDEFINED_OP_FLAG
Definition: vm_core.h:711
rb_iseq_location_struct::pathobj
VALUE pathobj
Definition: vm_core.h:273
ruby_dtrace_method_hook_args
Definition: probes_helper.h:6
reg_cfp
rb_control_frame_t * reg_cfp
Definition: rb_mjit_min_header-2.7.1.h:15083
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1508
ruby_vm_global_constant_state
rb_serial_t ruby_vm_global_constant_state
Definition: vm.c:380
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
rb_gc_stack_maxsize
size_t rb_gc_stack_maxsize
GetProcPtr
#define GetProcPtr(obj, ptr)
Definition: vm_core.h:1046
rb_cHash
VALUE rb_cHash
Definition: hash.c:92
rb_thread_struct::locking_mutex
VALUE locking_mutex
Definition: vm_core.h:958
VM_FRAME_MAGIC_TOP
@ VM_FRAME_MAGIC_TOP
Definition: vm_core.h:1166
key
key
Definition: openssl_missing.h:181
T_HASH
#define T_HASH
Definition: ruby.h:531
ruby_threadptr_data_type
const rb_data_type_t ruby_threadptr_data_type
Definition: vm.c:2643
path
VALUE path
Definition: rb_mjit_min_header-2.7.1.h:7300
rb_cThread
VALUE rb_cThread
Definition: vm.c:366
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1072
RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN
#define RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN
Definition: vm_core.h:679
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:872
rb_thread_struct::last_status
VALUE last_status
Definition: vm_core.h:917
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
rb_ec_initialize_vm_stack
void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
Definition: vm.c:2683
VM_SVAR_LASTLINE
@ VM_SVAR_LASTLINE
Definition: vm_core.h:1121
T_MODULE
#define T_MODULE
Definition: ruby.h:526
ruby_mimfree
void ruby_mimfree(void *ptr)
Definition: gc.c:10236
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:241
rb_thread_struct::name
VALUE name
Definition: vm_core.h:989
RUBY_MARK_UNLESS_NULL
#define RUBY_MARK_UNLESS_NULL(ptr)
Definition: gc.h:66
MAYBE_UNUSED
MAYBE_UNUSED(static void(*ruby_vm_collect_usage_func_insn)(int insn))
rb_vm_frame_method_entry
const MJIT_STATIC rb_callable_method_entry_t * rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
Definition: rb_mjit_min_header-2.7.1.h:12446
TAG_RAISE
#define TAG_RAISE
Definition: vm_core.h:203
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
rb_thread_struct::vm
rb_vm_t * vm
Definition: vm_core.h:913
st_foreach
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1718
rb_method_bmethod_struct::hooks
struct rb_hook_list_struct * hooks
Definition: method.h:153
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.1.h:6333
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:105
RUBY_DTRACE_METHOD_ENTRY_HOOK
#define RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, klass, id)
Definition: probes_helper.h:30
rb_vm_struct::mark_object_ary
VALUE mark_object_ary
Definition: vm_core.h:610
rb_proc_t::is_from_method
unsigned int is_from_method
Definition: vm_core.h:1051
rb_execution_context_struct::machine
struct rb_execution_context_struct::@188 machine
rb_hook_list_mark
void rb_hook_list_mark(rb_hook_list_t *hooks)
Definition: vm_trace.c:53
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_event_flag_t
uint32_t rb_event_flag_t
Definition: ruby.h:2278
rb_add_method
void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi)
Definition: vm_method.c:674
Max
#define Max(a, b)
Definition: bigdecimal.h:344
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:668
local_var_list
Definition: vm_eval.c:14
VM_FRAME_MAGIC_DUMMY
@ VM_FRAME_MAGIC_DUMMY
Definition: vm_core.h:1171
rb_vm_fstring_table
st_table * rb_vm_fstring_table(void)
Definition: vm.c:3392
rb_execution_context_struct::vm_stack_size
size_t vm_stack_size
Definition: vm_core.h:846
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
rb_control_frame_struct::self
VALUE self
Definition: vm_core.h:764
rb_backref_get
VALUE rb_backref_get(void)
Definition: vm.c:1304
RUBY_MARK_ENTER
#define RUBY_MARK_ENTER(msg)
Definition: gc.h:55
RUBY_DTRACE_CMETHOD_RETURN_HOOK
#define RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, klass, id)
Definition: probes_helper.h:39
internal.h
VM_FRAME_MAGIC_BLOCK
@ VM_FRAME_MAGIC_BLOCK
Definition: vm_core.h:1164
rb_call_end_proc
void rb_call_end_proc(VALUE data)
Definition: eval_jump.c:11
argv
char ** argv
Definition: ruby.c:223
RUBY_VM_THREAD_VM_STACK_SIZE
#define RUBY_VM_THREAD_VM_STACK_SIZE
Definition: vm_core.h:676
rb_execution_context_struct::fiber_ptr
rb_fiber_t * fiber_ptr
Definition: vm_core.h:856
VM_FRAME_FLAG_BMETHOD
@ VM_FRAME_FLAG_BMETHOD
Definition: vm_core.h:1178
rb_vm_struct::load_path_snapshot
VALUE load_path_snapshot
Definition: vm_core.h:616
rb_control_frame_struct::block_code
const void * block_code
Definition: vm_core.h:766
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2892
rb_vm_localjump_error
MJIT_FUNC_EXPORTED void rb_vm_localjump_error(const char *mesg, VALUE value, int reason)
Definition: vm.c:1471
RUBY_DTRACE_INSN_ENABLED
#define RUBY_DTRACE_INSN_ENABLED()
Definition: rb_mjit_min_header-2.7.1.h:11220
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
rb_iseq_constant_body::iseq_encoded
VALUE * iseq_encoded
Definition: vm_core.h:325
block_handler
rb_control_frame_t struct rb_calling_info const struct rb_call_info VALUE block_handler
Definition: rb_mjit_min_header-2.7.1.h:15083
rb_method_entry
const rb_method_entry_t * rb_method_entry(VALUE klass, ID id)
Definition: vm_method.c:837
rb_vm_rewind_cfp
void rb_vm_rewind_cfp(rb_execution_context_t *ec, rb_control_frame_t *cfp)
Definition: vm.c:604
rb_vm_get_ruby_level_next_cfp
MJIT_FUNC_EXPORTED rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
Definition: vm.c:553
rb_vm_struct::trap_list
struct rb_vm_struct::@184 trap_list
rb_vm_struct::loaded_features_snapshot
VALUE loaded_features_snapshot
Definition: vm_core.h:620
rb_vm_struct::src_encoding_index
int src_encoding_index
Definition: vm_core.h:639
rb_eSysStackError
VALUE rb_eSysStackError
Definition: eval.c:35
rb_captured_block::iseq
const rb_iseq_t * iseq
Definition: vm_core.h:731
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
GET_THREAD
#define GET_THREAD()
Definition: vm_core.h:1765
rb_thread_struct::pending_interrupt_mask_stack
VALUE pending_interrupt_mask_stack
Definition: vm_core.h:953
rb_thread_struct::value
VALUE value
Definition: vm_core.h:944
ruby_dtrace_method_hook_args::classname
const char * classname
Definition: probes_helper.h:7
id_core_set_variable_alias
@ id_core_set_variable_alias
Definition: id.h:121
VM_SVAR_BACKREF
@ VM_SVAR_BACKREF
Definition: vm_core.h:1122
rb_control_frame_struct::iseq
const rb_iseq_t * iseq
Definition: vm_core.h:763
rb_vm_env_local_variables
VALUE rb_vm_env_local_variables(const rb_env_t *env)
Definition: vm.c:840
rb_captured_block::code
union rb_captured_block::@186 code
rb_captured_block
Definition: vm_core.h:727
rb_ec_frame_method_id_and_class
int rb_ec_frame_method_id_and_class(const rb_execution_context_t *ec, ID *idp, ID *called_idp, VALUE *klassp)
Definition: vm.c:2200
rb_vm_control_frame_id_and_class
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp)
Definition: vm.c:2184
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
MJIT_STATIC
#define MJIT_STATIC
Definition: intern.h:47
rb_vm_get_binding_creatable_next_cfp
rb_control_frame_t * rb_vm_get_binding_creatable_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
Definition: vm.c:541
rb_source_location_cstr
const MJIT_FUNC_EXPORTED char * rb_source_location_cstr(int *pline)
Definition: vm.c:1376
rb_captured_block::val
VALUE val
Definition: vm_core.h:733
rb_vm_struct::fiber_machine_stack_size
size_t fiber_machine_stack_size
Definition: vm_core.h:666
rb_vm_struct::top_self
VALUE top_self
Definition: vm_core.h:614
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
ruby_vm_const_missing_count
VALUE ruby_vm_const_missing_count
Definition: vm.c:371
rb_vm_struct::frozen_strings
st_table * frozen_strings
Definition: vm_core.h:656
local_size
rb_control_frame_t struct rb_calling_info const rb_callable_method_entry_t int int int local_size
Definition: rb_mjit_min_header-2.7.1.h:14481
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2847
int
__inline__ int
Definition: rb_mjit_min_header-2.7.1.h:2807
rb_cString
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:2044
rb_vm_struct::living_threads
struct list_head living_threads
Definition: vm_core.h:595
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
TAG_NONE
#define TAG_NONE
Definition: vm_core.h:197
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:1346
block_handler_type_symbol
@ block_handler_type_symbol
Definition: vm_core.h:740
rb_binding_t
Definition: vm_core.h:1068
GetBindingPtr
#define GetBindingPtr(obj, ptr)
Definition: vm_core.h:1065
rb_vm_stack_to_heap
void rb_vm_stack_to_heap(rb_execution_context_t *ec)
Definition: vm.c:786
argc
int argc
Definition: ruby.c:222
VM_ENV_FLAG_WB_REQUIRED
@ VM_ENV_FLAG_WB_REQUIRED
Definition: vm_core.h:1188
REWIND_CFP
#define REWIND_CFP(expr)
Definition: vm.c:2763
rb_vm_struct::defined_module_hash
st_table * defined_module_hash
Definition: vm_core.h:649
rb_vm_cref_new_toplevel
rb_cref_t * rb_vm_cref_new_toplevel(void)
Definition: vm.c:298
id_core_hash_merge_ptr
@ id_core_hash_merge_ptr
Definition: id.h:126
VM_DEBUG_BP_CHECK
#define VM_DEBUG_BP_CHECK
Definition: vm_core.h:720
rb_vm_struct::self
VALUE self
Definition: vm_core.h:577
rb_singleton_class
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1725
MOD
#define MOD(n, d)
Definition: date_core.c:163
rb_vm_bugreport
void rb_vm_bugreport(const void *)
Definition: vm_dump.c:918
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
free
#define free(x)
Definition: dln.c:52
RB_NO_KEYWORDS
#define RB_NO_KEYWORDS
Definition: ruby.h:1977
ruby_vm_global_method_state
rb_serial_t ruby_vm_global_method_state
Definition: vm.c:379
err
int err
Definition: win32.c:135
rb_vm_struct::defined_strings
VALUE * defined_strings
Definition: vm_core.h:655
rb_proc_dup
VALUE rb_proc_dup(VALUE self)
Definition: vm.c:920
rb_cTrueClass
RUBY_EXTERN VALUE rb_cTrueClass
Definition: ruby.h:2049
OR
#define OR(d, d0, d1, bl)
Definition: crypt.c:125
rb_data_type_struct
Definition: ruby.h:1148
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
rb_thread_struct::report_on_exception
unsigned int report_on_exception
Definition: vm_core.h:935
rb_vm_struct
Definition: vm_core.h:576
rb_obj_is_thread
VALUE rb_obj_is_thread(VALUE obj)
Definition: vm.c:2655
xfree
#define xfree
Definition: defines.h:216
rb_method_definition_struct::original_id
ID original_id
Definition: method.h:179
rb_mRubyVMFrozenCore
VALUE rb_mRubyVMFrozenCore
Definition: vm.c:367
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12257
rb_vm_pop_frame
MJIT_STATIC void rb_vm_pop_frame(rb_execution_context_t *ec)
Definition: rb_mjit_min_header-2.7.1.h:12233
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
DEFINED_EXPR
@ DEFINED_EXPR
Definition: iseq.h:298
atol
long atol(const char *__nptr)
rb_method_definition_struct
Definition: method.h:163
vm_exec.h
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5214
imemo_cref
@ imemo_cref
class reference
Definition: internal.h:1134
rb_gc_mark_values
void rb_gc_mark_values(long n, const VALUE *values)
Definition: gc.c:4717
MJIT_FUNC_EXPORTED
#define MJIT_FUNC_EXPORTED
Definition: defines.h:396
rb_vm_struct::global_hooks
rb_hook_list_t global_hooks
Definition: vm_core.h:630
TAG_NEXT
#define TAG_NEXT
Definition: vm_core.h:200
ARRAY_REDEFINED_OP_FLAG
#define ARRAY_REDEFINED_OP_FLAG
Definition: vm_core.h:706
_
#define _(args)
Definition: dln.h:28
EC_PUSH_TAG
#define EC_PUSH_TAG(ec)
Definition: eval_intern.h:130
rb_iter_break_value
void rb_iter_break_value(VALUE val)
Definition: vm.c:1552
RUBY_EVENT_C_RETURN
#define RUBY_EVENT_C_RETURN
Definition: ruby.h:2248
block_type_ifunc
@ block_type_ifunc
Definition: vm_core.h:746
RUBY_ASSERT_MESG
#define RUBY_ASSERT_MESG(expr, mesg)
Definition: assert.h:19
st_memsize
size_t st_memsize(const st_table *tab)
Definition: st.c:719
rb_vm_struct::thgroup_default
VALUE thgroup_default
Definition: vm_core.h:596
rb_callable_method_entry_struct::def
struct rb_method_definition_struct *const def
Definition: method.h:62
Qtrue
#define Qtrue
Definition: ruby.h:468
vm_eval.c
rb_scope_visi_struct
Definition: method.h:35
exit
void exit(int __status) __attribute__((__noreturn__))
rb_iseq_pathobj_set
void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
Definition: iseq.c:469
rb_control_frame_struct::ep
const VALUE * ep
Definition: vm_core.h:765
rb_at_exit_list::next
struct rb_at_exit_list * next
Definition: vm_core.h:557
len
uint8_t len
Definition: escape.c:17
rb_class_path
VALUE rb_class_path(VALUE)
Definition: variable.c:153
printf
int int int printf(const char *__restrict,...) __attribute__((__format__(__printf__
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
RUBY_VM_THREAD_VM_STACK_SIZE_MIN
#define RUBY_VM_THREAD_VM_STACK_SIZE_MIN
Definition: vm_core.h:677
rb_binding_alloc
VALUE rb_binding_alloc(VALUE klass)
Definition: proc.c:331
rb_memerror
void rb_memerror(void)
Definition: gc.c:9597
rb_method_entry_struct
Definition: method.h:51
rb_mark_tbl
void rb_mark_tbl(st_table *tbl)
Definition: gc.c:5007
rb_iseq_struct::body
struct rb_iseq_constant_body * body
Definition: vm_core.h:460
PROC_REDEFINED_OP_FLAG
#define PROC_REDEFINED_OP_FLAG
Definition: vm_core.h:715
rb_cBinding
RUBY_EXTERN VALUE rb_cBinding
Definition: ruby.h:2015
iseq_catch_table_entry::sp
unsigned int sp
Definition: iseq.h:252
rb_control_frame_struct::pc
const VALUE * pc
Definition: vm_core.h:761
Size
Definition: pyobjc-tc.c:15
RUBY_EVENT_RETURN
#define RUBY_EVENT_RETURN
Definition: ruby.h:2246
rb_block::symbol
VALUE symbol
Definition: vm_core.h:754
thread_data_type
#define thread_data_type
Definition: vm.c:2642
rb_block
Definition: vm_core.h:751
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
PUREFUNC
PUREFUNC(static inline const VALUE *VM_EP_LEP(const VALUE *))
TAG_BREAK
#define TAG_BREAK
Definition: vm_core.h:199
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
rb_fiber_update_self
void rb_fiber_update_self(rb_fiber_t *fib)
Definition: cont.c:961
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.1.h:1479
rb_thread_struct::pending_interrupt_queue
VALUE pending_interrupt_queue
Definition: vm_core.h:952
rb_thread_struct::self
VALUE self
Definition: vm_core.h:912
eval_intern.h
rb_vm_set_progname
void rb_vm_set_progname(VALUE filename)
Definition: vm.c:3289
vm_exec.c
RB_ALTSTACK_FREE
#define RB_ALTSTACK_FREE(var)
Definition: vm_core.h:142
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
Min
#define Min(a, b)
Definition: bigdecimal.h:345
RUBY_DTRACE_INSN_OPERAND_ENABLED
#define RUBY_DTRACE_INSN_OPERAND_ENABLED()
Definition: rb_mjit_min_header-2.7.1.h:11222
rb_vm_get_sourceline
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:68
builtin.h
rb_execution_context_struct::root_svar
VALUE root_svar
Definition: vm_core.h:866
rb_ast_body_struct::root
const NODE * root
Definition: node.h:395
Qnil
#define Qnil
Definition: ruby.h:469
rb_thread_struct::keeping_mutexes
struct rb_mutex_struct * keeping_mutexes
Definition: vm_core.h:959
rb_vm_check_optimizable_mid
int rb_vm_check_optimizable_mid(VALUE mid)
Definition: vm.c:1581
rb_execution_context_mark
void rb_execution_context_mark(const rb_execution_context_t *ec)
Definition: vm.c:2500
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: internal.h:2128
id__attached__
@ id__attached__
Definition: rb_mjit_min_header-2.7.1.h:8635
rb_insns_name
const char * rb_insns_name(int i)
Definition: compile.c:8761
rb_ruby_verbose_ptr
VALUE * rb_ruby_verbose_ptr(void)
Definition: vm.c:3375
rb_execution_context_struct::local_storage_recursive_hash_for_trace
VALUE local_storage_recursive_hash_for_trace
Definition: vm_core.h:862
RUBY_VM_FIBER_MACHINE_STACK_SIZE
#define RUBY_VM_FIBER_MACHINE_STACK_SIZE
Definition: vm_core.h:683
NIL_REDEFINED_OP_FLAG
#define NIL_REDEFINED_OP_FLAG
Definition: vm_core.h:712
rb_undef
void rb_undef(VALUE, ID)
Definition: vm_method.c:1200
st_lookup
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
rb_threadptr_root_fiber_setup
void rb_threadptr_root_fiber_setup(rb_thread_t *th)
Definition: cont.c:1880
UNALIGNED_MEMBER_PTR
#define UNALIGNED_MEMBER_PTR(ptr, mem)
Definition: internal.h:2690
iseq_catch_table
Definition: rb_mjit_min_header-2.7.1.h:10785
rb_frame_method_id_and_class
int rb_frame_method_id_and_class(ID *idp, VALUE *klassp)
Definition: vm.c:2206
rb_iseq_struct::exec
struct rb_iseq_struct::@181::@183 exec
rb_cRegexp
RUBY_EXTERN VALUE rb_cRegexp
Definition: ruby.h:2042
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:722
rb_iseq_eval_main
VALUE rb_iseq_eval_main(const rb_iseq_t *iseq)
Definition: vm.c:2173
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
numberof
#define numberof(array)
Definition: etc.c:618
vm_insnhelper.h
rb_thread_struct
Definition: vm_core.h:910
rb_execution_context_struct::local_storage_recursive_hash
VALUE local_storage_recursive_hash
Definition: vm_core.h:861
arg_setup_block
@ arg_setup_block
Definition: vm_args.c:37
st_free_table
void st_free_table(st_table *tab)
Definition: st.c:709
rb_proc_t
Definition: vm_core.h:1049
rb_vm_gvl_destroy
void rb_vm_gvl_destroy(rb_vm_t *vm)
Definition: thread.c:421
st_table
Definition: st.h:79
mjit_mark
void mjit_mark(void)
block_type_iseq
@ block_type_iseq
Definition: vm_core.h:745
iseq_catch_table_entry::start
unsigned int start
Definition: iseq.h:249
RUBY_VM_PREVIOUS_CONTROL_FRAME
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:1384
NODE_SCOPE
@ NODE_SCOPE
Definition: node.h:32
rb_insn_operand_intern
VALUE rb_insn_operand_intern(const rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, VALUE *pnop, VALUE child)
TRUE_REDEFINED_OP_FLAG
#define TRUE_REDEFINED_OP_FLAG
Definition: vm_core.h:713
ID_TABLE_CONTINUE
@ ID_TABLE_CONTINUE
Definition: id_table.h:9
rb_thread_struct::stat_insn_usage
VALUE stat_insn_usage
Definition: vm_core.h:982
rb_block_lambda
VALUE rb_block_lambda(void)
Definition: proc.c:856
ruby_tag_type
ruby_tag_type
Definition: vm_core.h:184
rb_binding_t::first_lineno
unsigned short first_lineno
Definition: vm_core.h:1071
RTEST
#define RTEST(v)
Definition: ruby.h:481
imemo_ifunc
@ imemo_ifunc
iterator function
Definition: internal.h:1137
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
opt_pc
rb_control_frame_t struct rb_calling_info const rb_callable_method_entry_t int opt_pc
Definition: rb_mjit_min_header-2.7.1.h:14481
rb_vm_struct::loading_table
struct st_table * loading_table
Definition: vm_core.h:622
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:415
rb_iv_set
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:3307
rb_vm_env_prev_env
const rb_env_t * rb_vm_env_prev_env(const rb_env_t *env)
Definition: vm.c:796
rb_vm_make_proc_lambda
MJIT_FUNC_EXPORTED VALUE rb_vm_make_proc_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda)
Definition: vm.c:933
RNode
Definition: node.h:149
CHECK_VM_STACK_OVERFLOW
#define CHECK_VM_STACK_OVERFLOW(cfp, margin)
Definition: vm_core.h:1746
rb_execution_context_update
void rb_execution_context_update(const rb_execution_context_t *ec)
Definition: vm.c:2472
rb_execution_context_struct::stack_end
VALUE * stack_end
Definition: vm_core.h:888
VM_FRAME_MAGIC_EVAL
@ VM_FRAME_MAGIC_EVAL
Definition: vm_core.h:1169
TAG_RETURN
#define TAG_RETURN
Definition: vm_core.h:198
rb_iseq_constant_body::stack_max
unsigned int stack_max
Definition: vm_core.h:439
MAX
#define MAX(a, b)
Definition: regint.h:296
rb_objspace_gc_enable
VALUE rb_objspace_gc_enable(rb_objspace_t *objspace)
Definition: gc.c:9218
mjit_pause
VALUE mjit_pause(_Bool wait_p)
rb_source_location
VALUE rb_source_location(int *pline)
Definition: vm.c:1360
rb_backref_set
void rb_backref_set(VALUE val)
Definition: vm.c:1310
EXEC_EVENT_HOOK_AND_POP_FRAME
#define EXEC_EVENT_HOOK_AND_POP_FRAME(ec_, flag_, self_, id_, called_id_, klass_, data_)
Definition: vm_core.h:1938
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.1.h:2804
rb_proc_t::is_lambda
unsigned int is_lambda
Definition: vm_core.h:1052
name
const char * name
Definition: nkf.c:208
rb_execution_context_struct
Definition: vm_core.h:843
rb_ec_raised_reset
#define rb_ec_raised_reset(ec, f)
Definition: eval_intern.h:259
rb_vm_inc_const_missing_count
void rb_vm_inc_const_missing_count(void)
Definition: vm.c:386
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:837
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2387