Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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
38 RUBY_FUNC_EXPORTED
39 #else
40 MJIT_FUNC_EXPORTED
41 #endif
42 VALUE vm_exec(rb_execution_context_t *, int);
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 }
67 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
68 }
69
70 return NULL;
71 }
72 }
73
74 const VALUE *
75 rb_vm_ep_local_ep(const VALUE *ep)
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
102 rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp)
103 {
104 return VM_FRAME_CFRAME_KW_P(cfp);
105 }
106
107 /* -- Remove In 3.0 -- */
108 int
109 rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp)
110 {
111 return VM_FRAME_CFRAME_EMPTY_KW_P(cfp);
112 }
113
114 VALUE
115 rb_vm_frame_block_handler(const rb_control_frame_t *cfp)
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 {
206 VALUE block_handler = ec->passed_block_handler;
207 ec->passed_block_handler = VM_BLOCK_HANDLER_NONE;
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 {
221 rb_scope_visibility_t visi;
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 *
298 rb_vm_cref_new_toplevel(void)
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);
336 extern VALUE rb_vm_invoke_bmethod(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self,
337 int argc, const VALUE *argv, int kw_splat, VALUE block_handler,
338 const rb_callable_method_entry_t *me);
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
357 rb_serial_t
358 rb_next_class_serial(void)
359 {
360 rb_serial_t class_serial = NEXT_CLASS_SERIAL();
361 mjit_add_class_serial(class_serial);
362 return class_serial;
363 }
364
365 VALUE rb_cRubyVM;
366 VALUE rb_cThread;
367 VALUE rb_mRubyVMFrozenCore;
368 VALUE rb_block_param_proxy;
369
370 #define ruby_vm_redefined_flag GET_VM()->redefined_flag
371 VALUE ruby_vm_const_missing_count = 0;
372 rb_vm_t *ruby_current_vm_ptr = NULL;
373 rb_execution_context_t *ruby_current_execution_context_ptr = NULL;
374
375 rb_event_flag_t ruby_vm_event_flags;
376 rb_event_flag_t ruby_vm_event_enabled_global_flags;
377 unsigned int ruby_vm_event_local_num;
378
379 rb_serial_t ruby_vm_global_method_state = 1;
380 rb_serial_t ruby_vm_global_constant_state = 1;
381 rb_serial_t ruby_vm_class_serial = 1;
382
383 static void thread_free(void *ptr);
384
385 void
386 rb_vm_inc_const_missing_count(void)
387 {
388 ruby_vm_const_missing_count +=1;
389 }
390
391 MJIT_FUNC_EXPORTED int
392 rb_dtrace_setup(rb_execution_context_t *ec, VALUE klass, ID id,
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)) {
405 klass = rb_attr_get(klass, id__attached__);
406 if (NIL_P(klass)) return FALSE;
407 }
408 type = BUILTIN_TYPE(klass);
409 if (type == T_CLASS || type == T_ICLASS || type == T_MODULE) {
410 VALUE name = rb_class_path(klass);
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,
506 VM_BLOCK_HANDLER_NONE,
507 (VALUE)vm_cref_new_toplevel(ec), /* cref or me */
508 iseq->body->iseq_encoded, ec->cfp->sp,
509 iseq->body->local_table_size, iseq->body->stack_max);
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 */
518 iseq->body->iseq_encoded,
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
540 rb_control_frame_t *
541 rb_vm_get_binding_creatable_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
542 {
543 while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
544 if (cfp->iseq) {
545 return (rb_control_frame_t *)cfp;
546 }
547 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
548 }
549 return 0;
550 }
551
552 MJIT_FUNC_EXPORTED rb_control_frame_t *
553 rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
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 }
560 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
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
574 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
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 }
584 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
585 }
586 return 0;
587 }
588
589 MJIT_STATIC void
590 rb_vm_pop_cfunc_frame(void)
591 {
592 rb_execution_context_t *ec = GET_EC();
593 rb_control_frame_t *cfp = ec->cfp;
594 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
595
596 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, cfp->self, me->def->original_id, me->called_id, me->owner, Qnil);
597 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
598 vm_pop_frame(ec, cfp, cfp->ep);
599 }
600
601 #ifndef MJIT_HEADER
602
603 void
604 rb_vm_rewind_cfp(rb_execution_context_t *ec, rb_control_frame_t *cfp)
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 */
615 rb_vm_pop_cfunc_frame();
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();
626 rb_at_exit_list *nl = ALLOC(rb_at_exit_list);
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)) {
680 case block_handler_type_ifunc:
681 case block_handler_type_iseq:
682 return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc);
683
684 case block_handler_type_symbol:
685 case block_handler_type_proc:
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)) {
709 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
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
723 if (block_handler != VM_BLOCK_HANDLER_NONE) {
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)) {
730 local_size = VM_ENV_DATA_SIZE;
731 }
732 else {
733 local_size = cfp->iseq->body->local_table_size + VM_ENV_DATA_SIZE;
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
786 rb_vm_stack_to_heap(rb_execution_context_t *ec)
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);
791 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
792 }
793 }
794
795 const rb_env_t *
796 rb_vm_env_prev_env(const rb_env_t *env)
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
840 rb_vm_env_local_variables(const rb_env_t *env)
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
849 rb_iseq_local_variables(const rb_iseq_t *iseq)
850 {
851 struct local_var_list vars;
852 local_var_list_init(&vars);
853 while (collect_local_variables_in_iseq(iseq, &vars)) {
854 iseq = iseq->body->parent_iseq;
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
920 rb_proc_dup(VALUE self)
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
932 MJIT_FUNC_EXPORTED VALUE
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
953 rb_vm_make_binding(const rb_execution_context_t *ec, const rb_control_frame_t *src_cfp)
954 {
955 rb_control_frame_t *cfp = rb_vm_get_binding_creatable_next_cfp(ec, src_cfp);
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 }
969 cfp = rb_vm_get_binding_creatable_next_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
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;
991 rb_execution_context_t *ec = GET_EC();
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,
1038 VM_GUARDED_PREV_EP(captured->ep),
1039 (VALUE)cref, /* cref or method */
1040 iseq->body->iseq_encoded + opt_pc,
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
1055 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
1056
1057 vm_push_frame(ec, iseq, type | VM_FRAME_FLAG_BMETHOD, self,
1058 VM_GUARDED_PREV_EP(captured->ep),
1059 (VALUE)me,
1060 iseq->body->iseq_encoded + opt_pc,
1061 ec->cfp->sp + arg_size,
1062 iseq->body->local_table_size - arg_size,
1063 iseq->body->stack_max);
1064
1065 RUBY_DTRACE_METHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
1066 EXEC_EVENT_HOOK(ec, RUBY_EVENT_CALL, self, me->def->original_id, me->called_id, me->owner, Qnil);
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,
1071 me->def->original_id, me->called_id, me->owner, Qnil, FALSE);
1072 }
1073 VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);
1074 ret = vm_exec(ec, TRUE);
1075
1076 EXEC_EVENT_HOOK(ec, RUBY_EVENT_RETURN, self, me->def->original_id, me->called_id, me->owner, ret);
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 }
1082 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
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
1104 CHECK_VM_STACK_OVERFLOW(cfp, argc);
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)) {
1131 case block_handler_type_iseq:
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 }
1138 case block_handler_type_ifunc:
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);
1142 case block_handler_type_symbol:
1143 return vm_yield_with_symbol(ec, VM_BH_TO_SYMBOL(block_handler),
1144 argc, argv, kw_splat, passed_block_handler);
1145 case block_handler_type_proc:
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);
1161 if (UNLIKELY(block_handler == VM_BLOCK_HANDLER_NONE)) {
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,
1196 RB_NO_KEYWORDS, VM_BLOCK_HANDLER_NONE, NULL, FALSE, TRUE);
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,
1209 const rb_callable_method_entry_t *me)
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
1241 MJIT_FUNC_EXPORTED VALUE
1242 rb_vm_invoke_bmethod(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self,
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
1248 MJIT_FUNC_EXPORTED VALUE
1249 rb_vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc,
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) {
1269 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
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
1304 rb_backref_get(void)
1305 {
1306 return vm_svar_get(GET_EC(), VM_SVAR_BACKREF);
1307 }
1308
1309 void
1310 rb_backref_set(VALUE val)
1311 {
1312 vm_svar_set(GET_EC(), VM_SVAR_BACKREF, val);
1313 }
1314
1315 VALUE
1316 rb_lastline_get(void)
1317 {
1318 return vm_svar_get(GET_EC(), VM_SVAR_LASTLINE);
1319 }
1320
1321 void
1322 rb_lastline_set(VALUE val)
1323 {
1324 vm_svar_set(GET_EC(), VM_SVAR_LASTLINE, val);
1325 }
1326
1327 /* misc */
1328
1329 /* in intern.h */
1330 const char *
1331 rb_sourcefile(void)
1332 {
1333 const rb_execution_context_t *ec = GET_EC();
1334 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
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
1346 rb_sourceline(void)
1347 {
1348 const rb_execution_context_t *ec = GET_EC();
1349 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
1350
1351 if (cfp) {
1352 return rb_vm_get_sourceline(cfp);
1353 }
1354 else {
1355 return 0;
1356 }
1357 }
1358
1359 VALUE
1360 rb_source_location(int *pline)
1361 {
1362 const rb_execution_context_t *ec = GET_EC();
1363 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
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 *
1376 rb_source_location_cstr(int *pline)
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 *
1384 rb_vm_cref(void)
1385 {
1386 const rb_execution_context_t *ec = GET_EC();
1387 return vm_ec_cref(ec);
1388 }
1389
1390 rb_cref_t *
1391 rb_vm_cref_replace_with_duplicated_cref(void)
1392 {
1393 const rb_execution_context_t *ec = GET_EC();
1394 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
1395 rb_cref_t *cref = vm_cref_replace_with_duplicated_cref(cfp->ep);
1396 return cref;
1397 }
1398
1399 const rb_cref_t *
1400 rb_vm_cref_in_context(VALUE self, VALUE cbase)
1401 {
1402 const rb_execution_context_t *ec = GET_EC();
1403 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
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
1425 rb_vm_cbase(void)
1426 {
1427 const rb_execution_context_t *ec = GET_EC();
1428 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
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;
1442 VALUE exc = rb_exc_new2(rb_eLocalJumpError, mesg);
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
1478 rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
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
1510 rb_vm_jump_tag_but_local_jump(int state)
1511 {
1512 VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef);
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)) {
1521 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
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
1546 rb_iter_break(void)
1547 {
1548 vm_iter_break(GET_EC(), Qnil);
1549 }
1550
1551 void
1552 rb_iter_break_value(VALUE val)
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 {
1565 if (klass == rb_cInteger) return INTEGER_REDEFINED_OP_FLAG;
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;
1574 if (klass == rb_cTrueClass) return TRUE_REDEFINED_OP_FLAG;
1575 if (klass == rb_cFalseClass) return FALSE_REDEFINED_OP_FLAG;
1576 if (klass == rb_cProc) return PROC_REDEFINED_OP_FLAG;
1577 return 0;
1578 }
1579
1580 int
1581 rb_vm_check_optimizable_mid(VALUE mid)
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:
1595 case VM_METHOD_TYPE_OPTIMIZED:
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;
1606 if (RB_TYPE_P(klass, T_ICLASS) && FL_TEST(klass, RICLASS_IS_ORIGIN)) {
1607 klass = RBASIC_CLASS(klass);
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
1631 rb_vm_check_redefinition_by_prepend(VALUE klass)
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 {
1640 const rb_method_entry_t *me = rb_method_entry_at(klass, mid);
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:
1764 RUBY_DTRACE_METHOD_RETURN_HOOK(ec, 0, 0);
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) {
1783 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(ec->cfp);
1784
1785 /* kick RUBY_EVENT_RETURN at invoke_block_from_c() for bmethod */
1786 EXEC_EVENT_HOOK_AND_POP_FRAME(ec, RUBY_EVENT_RETURN, ec->cfp->self,
1787 rb_vm_frame_method_entry(ec->cfp)->def->original_id,
1788 rb_vm_frame_method_entry(ec->cfp)->called_id,
1789 rb_vm_frame_method_entry(ec->cfp)->owner,
1790 frame_return_value(err));
1791
1792 VM_ASSERT(me->def->type == VM_METHOD_TYPE_BMETHOD);
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,
1797 rb_vm_frame_method_entry(ec->cfp)->def->original_id,
1798 rb_vm_frame_method_entry(ec->cfp)->called_id,
1799 rb_vm_frame_method_entry(ec->cfp)->owner,
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:
1815 EXEC_EVENT_HOOK_AND_POP_FRAME(ec, RUBY_EVENT_END, ec->cfp->self, 0, 0, 0, Qnil);
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;
1926 rb_ec_raised_reset(ec, RAISED_STACKOVERFLOW);
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;
1953 rb_control_frame_t *cfp;
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)) {
1962 EXEC_EVENT_HOOK_AND_POP_FRAME(ec, RUBY_EVENT_C_RETURN, ec->cfp->self,
1963 rb_vm_frame_method_entry(ec->cfp)->def->original_id,
1964 rb_vm_frame_method_entry(ec->cfp)->called_id,
1965 rb_vm_frame_method_entry(ec->cfp)->owner, Qnil);
1966 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec,
1967 rb_vm_frame_method_entry(ec->cfp)->owner,
1968 rb_vm_frame_method_entry(ec->cfp)->def->original_id);
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,
2131 VM_GUARDED_PREV_EP(cfp->ep),
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
2163 rb_iseq_eval(const rb_iseq_t *iseq)
2164 {
2165 rb_execution_context_t *ec = GET_EC();
2166 VALUE val;
2167 vm_set_top_stack(ec, iseq);
2168 val = vm_exec(ec, TRUE);
2169 return val;
2170 }
2171
2172 VALUE
2173 rb_iseq_eval_main(const rb_iseq_t *iseq)
2174 {
2175 rb_execution_context_t *ec = GET_EC();
2176 VALUE val;
2177
2178 vm_set_main_stack(ec, iseq);
2179 val = vm_exec(ec, TRUE);
2180 return val;
2181 }
2182
2183 int
2184 rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp)
2185 {
2186 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
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
2206 rb_frame_method_id_and_class(ID *idp, VALUE *klassp)
2207 {
2208 return rb_ec_frame_method_id_and_class(GET_EC(), idp, 0, klassp);
2209 }
2210
2211 VALUE
2212 rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
2213 VALUE block_handler, VALUE filename)
2214 {
2215 rb_execution_context_t *ec = GET_EC();
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
2220 vm_push_frame(ec, iseq, VM_FRAME_MAGIC_TOP | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH,
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
2234 rb_vm_update_references(void *ptr)
2235 {
2236 if (ptr) {
2237 rb_vm_t *vm = ptr;
2238 rb_gc_update_tbl_refs(vm->frozen_strings);
2239 }
2240 }
2241
2242 void
2243 rb_vm_mark(void *ptr)
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 }
2256 rb_gc_mark(vm->thgroup_default);
2257 rb_gc_mark(vm->mark_object_ary);
2258
2259 len = RARRAY_LEN(vm->mark_object_ary);
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);
2275 rb_gc_mark(vm->load_path_snapshot);
2276 RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache);
2277 rb_gc_mark(vm->expanded_load_path);
2278 rb_gc_mark(vm->loaded_features);
2279 rb_gc_mark(vm->loaded_features_snapshot);
2280 rb_gc_mark(vm->top_self);
2281 rb_gc_mark(vm->orig_progname);
2282 RUBY_MARK_UNLESS_NULL(vm->coverages);
2283 /* Prevent classes from moving */
2284 rb_mark_tbl(vm->defined_module_hash);
2285
2286 if (vm->loading_table) {
2287 rb_mark_tbl(vm->loading_table);
2288 }
2289
2290 rb_hook_list_mark(&vm->global_hooks);
2291
2292 rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd);
2293
2294 mjit_mark();
2295 }
2296
2297 RUBY_MARK_LEAVE("vm");
2298 }
2299
2300 #undef rb_vm_register_special_exception
2301 void
2302 rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE cls, VALUE mesg)
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;
2308 rb_gc_register_mark_object(exc);
2309 }
2310
2311 int
2312 rb_vm_add_root_module(ID id, VALUE module)
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
2329 ruby_vm_destruct(rb_vm_t *vm)
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) {
2338 rb_fiber_reset_root_local_storage(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);
2345 st_free_table(vm->loading_table);
2346 vm->loading_table = 0;
2347 }
2348 if (vm->frozen_strings) {
2349 st_free_table(vm->frozen_strings);
2350 vm->frozen_strings = 0;
2351 }
2352 rb_vm_gvl_destroy(vm);
2353 RB_ALTSTACK_FREE(vm->main_altstack);
2354 if (objspace) {
2355 rb_objspace_free(objspace);
2356 }
2357 /* after freeing objspace, you *can't* use ruby_xfree() */
2358 ruby_mimfree(vm);
2359 ruby_current_vm_ptr = NULL;
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,},
2382 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
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 {
2435 vm->default_params.thread_vm_stack_size =
2436 get_param("RUBY_THREAD_VM_STACK_SIZE",
2437 RUBY_VM_THREAD_VM_STACK_SIZE,
2438 RUBY_VM_THREAD_VM_STACK_SIZE_MIN);
2439
2440 vm->default_params.thread_machine_stack_size =
2441 get_param("RUBY_THREAD_MACHINE_STACK_SIZE",
2442 RUBY_VM_THREAD_MACHINE_STACK_SIZE,
2443 RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN);
2444
2445 vm->default_params.fiber_vm_stack_size =
2446 get_param("RUBY_FIBER_VM_STACK_SIZE",
2447 RUBY_VM_FIBER_VM_STACK_SIZE,
2448 RUBY_VM_FIBER_VM_STACK_SIZE_MIN);
2449
2450 vm->default_params.fiber_machine_stack_size =
2451 get_param("RUBY_FIBER_MACHINE_STACK_SIZE",
2452 RUBY_VM_FIBER_MACHINE_STACK_SIZE,
2453 RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN);
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);
2465 vm->thread_report_on_exception = 1;
2466 vm->src_encoding_index = -1;
2467
2468 vm_default_params_setup(vm);
2469 }
2470
2471 void
2472 rb_execution_context_update(const rb_execution_context_t *ec)
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;
2483 cfp->self = rb_gc_location(cfp->self);
2484 cfp->iseq = (rb_iseq_t *)rb_gc_location((VALUE)cfp->iseq);
2485 cfp->block_code = (void *)rb_gc_location((VALUE)cfp->block_code);
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)) {
2490 prev_ep[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV]);
2491 }
2492 }
2493
2494 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2495 }
2496 }
2497 }
2498
2499 void
2500 rb_execution_context_mark(const rb_execution_context_t *ec)
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));
2515 rb_gc_mark_movable(cfp->self);
2516 rb_gc_mark_movable((VALUE)cfp->iseq);
2517 rb_gc_mark_movable((VALUE)cfp->block_code);
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)) {
2522 rb_gc_mark_movable(prev_ep[VM_ENV_DATA_INDEX_ENV]);
2523 }
2524 }
2525
2526 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
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 ) {
2534 rb_gc_mark_machine_stack(ec);
2535 rb_gc_mark_locations((VALUE *)&ec->machine.regs,
2536 (VALUE *)(&ec->machine.regs) +
2537 sizeof(ec->machine.regs) / (sizeof(VALUE)));
2538 }
2539
2540 RUBY_MARK_UNLESS_NULL(ec->errinfo);
2541 RUBY_MARK_UNLESS_NULL(ec->root_svar);
2542 rb_mark_tbl(ec->local_storage);
2543 RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash);
2544 RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash_for_trace);
2545 RUBY_MARK_UNLESS_NULL(ec->private_const_reference);
2546 }
2547
2548 void rb_fiber_mark_self(rb_fiber_t *fib);
2549 void rb_fiber_update_self(rb_fiber_t *fib);
2550 void rb_threadptr_root_fiber_setup(rb_thread_t *th);
2551 void rb_threadptr_root_fiber_release(rb_thread_t *th);
2552
2553 static void
2554 thread_compact(void *ptr)
2555 {
2556 rb_thread_t *th = ptr;
2557 rb_fiber_update_self(th->ec->fiber_ptr);
2558
2559 if (th->root_fiber) rb_fiber_update_self(th->root_fiber);
2560
2561 rb_execution_context_update(th->ec);
2562 }
2563
2564 static void
2565 thread_mark(void *ptr)
2566 {
2567 rb_thread_t *th = ptr;
2568 RUBY_MARK_ENTER("thread");
2569 rb_fiber_mark_self(th->ec->fiber_ptr);
2570
2571 /* mark ruby objects */
2572 switch (th->invoke_type) {
2573 case thread_invoke_type_proc:
2574 RUBY_MARK_UNLESS_NULL(th->invoke_arg.proc.proc);
2575 RUBY_MARK_UNLESS_NULL(th->invoke_arg.proc.args);
2576 break;
2577 case thread_invoke_type_func:
2578 rb_gc_mark_maybe((VALUE)th->invoke_arg.func.arg);
2579 break;
2580 default:
2581 break;
2582 }
2583
2584 RUBY_MARK_UNLESS_NULL(th->thgroup);
2585 RUBY_MARK_UNLESS_NULL(th->value);
2586 RUBY_MARK_UNLESS_NULL(th->pending_interrupt_queue);
2587 RUBY_MARK_UNLESS_NULL(th->pending_interrupt_mask_stack);
2588 RUBY_MARK_UNLESS_NULL(th->top_self);
2589 RUBY_MARK_UNLESS_NULL(th->top_wrapper);
2590 if (th->root_fiber) rb_fiber_mark_self(th->root_fiber);
2591
2592 /* Ensure EC stack objects are pinned */
2593 rb_execution_context_mark(th->ec);
2594 RUBY_MARK_UNLESS_NULL(th->stat_insn_usage);
2595 RUBY_MARK_UNLESS_NULL(th->last_status);
2596 RUBY_MARK_UNLESS_NULL(th->locking_mutex);
2597 RUBY_MARK_UNLESS_NULL(th->name);
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
2615 rb_threadptr_root_fiber_release(th);
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
2643 const rb_data_type_t ruby_threadptr_data_type = {
2644 "VM/thread",
2645 {
2646 thread_mark,
2647 thread_free,
2648 thread_memsize,
2649 thread_compact,
2650 },
2651 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2652 };
2653
2654 VALUE
2655 rb_obj_is_thread(VALUE obj)
2656 {
2657 if (rb_typeddata_is_kind_of(obj, &thread_data_type)) {
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;
2670 obj = TypedData_Make_Struct(klass, rb_thread_t, &thread_data_type, th);
2671
2672 return obj;
2673 }
2674
2675 inline void
2676 rb_ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
2677 {
2678 ec->vm_stack = stack;
2679 ec->vm_stack_size = size;
2680 }
2681
2682 void
2683 rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size)
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 */,
2691 VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_CFRAME /* dummy frame */,
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
2699 rb_ec_clear_vm_stack(rb_execution_context_t *ec)
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;
2711 rb_threadptr_root_fiber_setup(th);
2712
2713 if (self == 0) {
2714 size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE);
2715 rb_ec_initialize_vm_stack(th->ec, ALLOC_N(VALUE, size), size);
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;
2727 th->ec->local_storage_recursive_hash = Qnil;
2728 th->ec->local_storage_recursive_hash_for_trace = Qnil;
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;
2737 th->report_on_exception = th->vm->thread_report_on_exception;
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
2756 rb_thread_alloc(VALUE klass)
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));
2795 rb_clear_method_cache_by_class(self);
2796 });
2797 return Qnil;
2798 }
2799
2800 static VALUE
2801 m_core_set_postexe(VALUE self)
2802 {
2803 rb_set_end_proc(rb_call_end_proc, rb_block_proc());
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 {
2888 rb_vm_bugreport(NULL);
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);
2970 rb_undef_alloc_func(rb_cRubyVM);
2971 rb_undef_method(CLASS_OF(rb_cRubyVM), "new");
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);
2992 RBASIC_CLEAR_CLASS(klass);
2993 rb_obj_freeze(klass);
2994 rb_gc_register_mark_object(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);
3165 rb_undef_alloc_func(rb_cThread);
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 {
3244 rb_vm_t *vm = ruby_current_vm_ptr;
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 */
3253 th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th);
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
3263 rb_gc_register_mark_object((VALUE)iseq);
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
3278 rb_block_param_proxy = rb_obj_alloc(rb_cObject);
3279 rb_add_method(rb_singleton_class(rb_block_param_proxy), idCall, VM_METHOD_TYPE_OPTIMIZED,
3280 (void *)OPTIMIZED_METHOD_TYPE_BLOCK_CALL, METHOD_VISI_PUBLIC);
3281 rb_obj_freeze(rb_block_param_proxy);
3282 rb_gc_register_mark_object(rb_block_param_proxy);
3283
3284 /* vm_backtrace.c */
3285 Init_vm_backtrace();
3286 }
3287
3288 void
3289 rb_vm_set_progname(VALUE filename)
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
3295 rb_iseq_pathobj_set(cfp->iseq, rb_str_dup(filename), rb_iseq_realpath(cfp->iseq));
3296 }
3297
3298 extern const struct st_hash_type rb_fstring_hash_type;
3299
3300 void
3301 Init_BareVM(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);
3320 ruby_thread_init_stack(th);
3321 }
3322
3323 void
3324 Init_vm_objects(void)
3325 {
3326 rb_vm_t *vm = GET_VM();
3327
3328 vm->defined_module_hash = st_init_numtable();
3329
3330 /* initialize mark object array, hash */
3331 vm->mark_object_ary = rb_ary_tmp_new(128);
3332 vm->loading_table = st_init_strtable();
3333 vm->frozen_strings = st_init_table_with_size(&rb_fstring_hash_type, 1000);
3334 }
3335
3336 /* top self */
3337
3338 static VALUE
3339 main_to_s(VALUE obj)
3340 {
3341 return rb_str_new2("main");
3342 }
3343
3344 VALUE
3345 rb_vm_top_self(void)
3346 {
3347 return GET_VM()->top_self;
3348 }
3349
3350 void
3351 Init_top_self(void)
3352 {
3353 rb_vm_t *vm = GET_VM();
3354
3355 vm->top_self = rb_obj_alloc(rb_cObject);
3356 rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0);
3357 rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s");
3358 }
3359
3360 static VALUE *
3361 ruby_vm_verbose_ptr(rb_vm_t *vm)
3362 {
3363 return &vm->verbose;
3364 }
3365
3366 static VALUE *
3367 ruby_vm_debug_ptr(rb_vm_t *vm)
3368 {
3369 return &vm->debug;
3370 }
3371
3372 VALUE *
3373 rb_ruby_verbose_ptr(void)
3374 {
3375 return ruby_vm_verbose_ptr(GET_VM());
3376 }
3377
3378 VALUE *
3379 rb_ruby_debug_ptr(void)
3380 {
3381 return ruby_vm_debug_ptr(GET_VM());
3382 }
3383
3384 /* iseq.c */
3385 VALUE rb_insn_operand_intern(const rb_iseq_t *iseq,
3386 VALUE insn, int op_no, VALUE op,
3387 int len, size_t pos, VALUE *pnop, VALUE child);
3388
3389 st_table *
3390 rb_vm_fstring_table(void)
3391 {
3392 return GET_VM()->frozen_strings;
3393 }
3394
3395 #if VM_COLLECT_USAGE_DETAILS
3396
3397 #define HASH_ASET(h, k, v) rb_hash_aset((h), (st_data_t)(k), (st_data_t)(v))
3398
3399 /* uh = {
3400 * insn(Fixnum) => ihash(Hash)
3401 * }
3402 * ihash = {
3403 * -1(Fixnum) => count, # insn usage
3404 * 0(Fixnum) => ophash, # operand usage
3405 * }
3406 * ophash = {
3407 * val(interned string) => count(Fixnum)
3408 * }
3409 */
3410 static void
3411 vm_analysis_insn(int insn)
3412 {
3413 ID usage_hash;
3414 ID bigram_hash;
3415 static int prev_insn = -1;
3416
3417 VALUE uh;
3418 VALUE ihash;
3419 VALUE cv;
3420
3421 CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3422 CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
3423 uh = rb_const_get(rb_cRubyVM, usage_hash);
3424 if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
3425 ihash = rb_hash_new();
3426 HASH_ASET(uh, INT2FIX(insn), ihash);
3427 }
3428 if ((cv = rb_hash_aref(ihash, INT2FIX(-1))) == Qnil) {
3429 cv = INT2FIX(0);
3430 }
3431 HASH_ASET(ihash, INT2FIX(-1), INT2FIX(FIX2INT(cv) + 1));
3432
3433 /* calc bigram */
3434 if (prev_insn != -1) {
3435 VALUE bi;
3436 VALUE ary[2];
3437 VALUE cv;
3438
3439 ary[0] = INT2FIX(prev_insn);
3440 ary[1] = INT2FIX(insn);
3441 bi = rb_ary_new4(2, &ary[0]);
3442
3443 uh = rb_const_get(rb_cRubyVM, bigram_hash);
3444 if ((cv = rb_hash_aref(uh, bi)) == Qnil) {
3445 cv = INT2FIX(0);
3446 }
3447 HASH_ASET(uh, bi, INT2FIX(FIX2INT(cv) + 1));
3448 }
3449 prev_insn = insn;
3450 }
3451
3452 static void
3453 vm_analysis_operand(int insn, int n, VALUE op)
3454 {
3455 ID usage_hash;
3456
3457 VALUE uh;
3458 VALUE ihash;
3459 VALUE ophash;
3460 VALUE valstr;
3461 VALUE cv;
3462
3463 CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3464
3465 uh = rb_const_get(rb_cRubyVM, usage_hash);
3466 if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
3467 ihash = rb_hash_new();
3468 HASH_ASET(uh, INT2FIX(insn), ihash);
3469 }
3470 if ((ophash = rb_hash_aref(ihash, INT2FIX(n))) == Qnil) {
3471 ophash = rb_hash_new();
3472 HASH_ASET(ihash, INT2FIX(n), ophash);
3473 }
3474 /* intern */
3475 valstr = rb_insn_operand_intern(GET_EC()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
3476
3477 /* set count */
3478 if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) {
3479 cv = INT2FIX(0);
3480 }
3481 HASH_ASET(ophash, valstr, INT2FIX(FIX2INT(cv) + 1));
3482 }
3483
3484 static void
3485 vm_analysis_register(int reg, int isset)
3486 {
3487 ID usage_hash;
3488 VALUE uh;
3489 VALUE valstr;
3490 static const char regstrs[][5] = {
3491 "pc", /* 0 */
3492 "sp", /* 1 */
3493 "ep", /* 2 */
3494 "cfp", /* 3 */
3495 "self", /* 4 */
3496 "iseq", /* 5 */
3497 };
3498 static const char getsetstr[][4] = {
3499 "get",
3500 "set",
3501 };
3502 static VALUE syms[sizeof(regstrs) / sizeof(regstrs[0])][2];
3503
3504 VALUE cv;
3505
3506 CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
3507 if (syms[0] == 0) {
3508 char buff[0x10];
3509 int i;
3510
3511 for (i = 0; i < (int)(sizeof(regstrs) / sizeof(regstrs[0])); i++) {
3512 int j;
3513 for (j = 0; j < 2; j++) {
3514 snprintf(buff, 0x10, "%d %s %-4s", i, getsetstr[j], regstrs[i]);
3515 syms[i][j] = ID2SYM(rb_intern(buff));
3516 }
3517 }
3518 }
3519 valstr = syms[reg][isset];
3520
3521 uh = rb_const_get(rb_cRubyVM, usage_hash);
3522 if ((cv = rb_hash_aref(uh, valstr)) == Qnil) {
3523 cv = INT2FIX(0);
3524 }
3525 HASH_ASET(uh, valstr, INT2FIX(FIX2INT(cv) + 1));
3526 }
3527
3528 #undef HASH_ASET
3529
3530 static void (*ruby_vm_collect_usage_func_insn)(int insn) = NULL;
3531 static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = NULL;
3532 static void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = NULL;
3533
3534 /* :nodoc: */
3535 static VALUE
3536 usage_analysis_insn_start(VALUE self)
3537 {
3538 ruby_vm_collect_usage_func_insn = vm_analysis_insn;
3539 return Qnil;
3540 }
3541
3542 /* :nodoc: */
3543 static VALUE
3544 usage_analysis_operand_start(VALUE self)
3545 {
3546 ruby_vm_collect_usage_func_operand = vm_analysis_operand;
3547 return Qnil;
3548 }
3549
3550 /* :nodoc: */
3551 static VALUE
3552 usage_analysis_register_start(VALUE self)
3553 {
3554 ruby_vm_collect_usage_func_register = vm_analysis_register;
3555 return Qnil;
3556 }
3557
3558 /* :nodoc: */
3559 static VALUE
3560 usage_analysis_insn_stop(VALUE self)
3561 {
3562 ruby_vm_collect_usage_func_insn = 0;
3563 return Qnil;
3564 }
3565
3566 /* :nodoc: */
3567 static VALUE
3568 usage_analysis_operand_stop(VALUE self)
3569 {
3570 ruby_vm_collect_usage_func_operand = 0;
3571 return Qnil;
3572 }
3573
3574 /* :nodoc: */
3575 static VALUE
3576 usage_analysis_register_stop(VALUE self)
3577 {
3578 ruby_vm_collect_usage_func_register = 0;
3579 return Qnil;
3580 }
3581
3582 /* :nodoc: */
3583 static VALUE
3584 usage_analysis_insn_running(VALUE self)
3585 {
3586 if (ruby_vm_collect_usage_func_insn == 0) return Qfalse;
3587 return Qtrue;
3588 }
3589
3590 /* :nodoc: */
3591 static VALUE
3592 usage_analysis_operand_running(VALUE self)
3593 {
3594 if (ruby_vm_collect_usage_func_operand == 0) return Qfalse;
3595 return Qtrue;
3596 }
3597
3598 /* :nodoc: */
3599 static VALUE
3600 usage_analysis_register_running(VALUE self)
3601 {
3602 if (ruby_vm_collect_usage_func_register == 0) return Qfalse;
3603 return Qtrue;
3604 }
3605
3606 /* :nodoc: */
3607 static VALUE
3608 usage_analysis_insn_clear(VALUE self)
3609 {
3610 ID usage_hash;
3611 ID bigram_hash;
3612 VALUE uh;
3613 VALUE bh;
3614
3615 CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3616 CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
3617 uh = rb_const_get(rb_cRubyVM, usage_hash);
3618 bh = rb_const_get(rb_cRubyVM, bigram_hash);
3619 rb_hash_clear(uh);
3620 rb_hash_clear(bh);
3621
3622 return Qtrue;
3623 }
3624
3625 /* :nodoc: */
3626 static VALUE
3627 usage_analysis_operand_clear(VALUE self)
3628 {
3629 ID usage_hash;
3630 VALUE uh;
3631
3632 CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
3633 uh = rb_const_get(rb_cRubyVM, usage_hash);
3634 rb_hash_clear(uh);
3635
3636 return Qtrue;
3637 }
3638
3639 /* :nodoc: */
3640 static VALUE
3641 usage_analysis_register_clear(VALUE self)
3642 {
3643 ID usage_hash;
3644 VALUE uh;
3645
3646 CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
3647 uh = rb_const_get(rb_cRubyVM, usage_hash);
3648 rb_hash_clear(uh);
3649
3650 return Qtrue;
3651 }
3652
3653 #else
3654
3655 MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_insn)(int insn)) = NULL;
3656 MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)) = NULL;
3657 MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int isset)) = NULL;
3658
3659 #endif
3660
3661 #if VM_COLLECT_USAGE_DETAILS
3662 /* @param insn instruction number */
3663 static void
3664 vm_collect_usage_insn(int insn)
3665 {
3666 if (RUBY_DTRACE_INSN_ENABLED()) {
3667 RUBY_DTRACE_INSN(rb_insns_name(insn));
3668 }
3669 if (ruby_vm_collect_usage_func_insn)
3670 (*ruby_vm_collect_usage_func_insn)(insn);
3671 }
3672
3673 /* @param insn instruction number
3674 * @param n n-th operand
3675 * @param op operand value
3676 */
3677 static void
3678 vm_collect_usage_operand(int insn, int n, VALUE op)
3679 {
3680 if (RUBY_DTRACE_INSN_OPERAND_ENABLED()) {
3681 VALUE valstr;
3682
3683 valstr = rb_insn_operand_intern(GET_EC()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
3684
3685 RUBY_DTRACE_INSN_OPERAND(RSTRING_PTR(valstr), rb_insns_name(insn));
3686 RB_GC_GUARD(valstr);
3687 }
3688 if (ruby_vm_collect_usage_func_operand)
3689 (*ruby_vm_collect_usage_func_operand)(insn, n, op);
3690 }
3691
3692 /* @param reg register id. see code of vm_analysis_register() */
3693 /* @param isset 0: read, 1: write */
3694 static void
3695 vm_collect_usage_register(int reg, int isset)
3696 {
3697 if (ruby_vm_collect_usage_func_register)
3698 (*ruby_vm_collect_usage_func_register)(reg, isset);
3699 }
3700 #endif
3701
3702 #endif /* #ifndef MJIT_HEADER */
3703
3704 #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
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:1818
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:10150
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
rb_f_raise
VALUE rb_f_raise(int argc, VALUE *argv)
Definition: eval.c:726
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
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
mjit_add_class_serial
void mjit_add_class_serial(rb_serial_t class_serial)
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
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:10187
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
vars
const VALUE int int int int int int VALUE * vars[]
Definition: rb_mjit_min_header-2.7.0.h:6462
reg_cfp
rb_control_frame_t * reg_cfp
Definition: rb_mjit_min_header-2.7.0.h:15146
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
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:1501
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7063
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
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
rb_gc_update_tbl_refs
void rb_gc_update_tbl_refs(st_table *ptr)
Definition: gc.c:7983
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
size_t
long unsigned int size_t
Definition: rb_mjit_min_header-2.7.0.h:666
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:1981
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
cbase
VALUE cbase
Definition: rb_mjit_min_header-2.7.0.h:16133
SET
#define SET(name, attr)
id_core_raise
@ id_core_raise
Definition: id.h:128
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
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
rb_hash_clear
VALUE rb_hash_clear(VALUE hash)
Definition: hash.c:2696
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
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:4699
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
RUBY_DTRACE_INSN_ENABLED
#define RUBY_DTRACE_INSN_ENABLED()
Definition: rb_mjit_min_header-2.7.0.h:11295
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:1964
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
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.0.h:8771
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
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:8111
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.0.h:8877
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
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
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
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
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
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:3379
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
VM_FRAME_FLAG_LAMBDA
@ VM_FRAME_FLAG_LAMBDA
Definition: vm_core.h:1180
Qfalse
#define Qfalse
Definition: ruby.h:467
idCall
@ idCall
Definition: rb_mjit_min_header-2.7.0.h:8727
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:1537
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:1586
dp
#define dp(v)
Definition: vm_debug.h:21
rb_iseq_struct::aux
union rb_iseq_struct::@181 aux
printf
int int int printf(const char *__restrict,...) __attribute__((__format__(__printf__
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
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.0.h:14544
st.h
NULL
#define NULL
Definition: _sdbm.c:101
exit
void exit(int __status) __attribute__((__noreturn__))
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:1880
rb_gc_mark_vm_stack_values
void rb_gc_mark_vm_stack_values(long n, const VALUE *values)
Definition: gc.c:4739
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
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.0.h:10860
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
VM_ASSERT
#define VM_ASSERT(expr)
Definition: vm_core.h:56
rb_vm_struct::debug
VALUE debug
Definition: vm_core.h:645
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.0.h:15146
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:2306
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:1507
VM_BLOCK_HANDLER_NONE
#define VM_BLOCK_HANDLER_NONE
Definition: vm_core.h:1291
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
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
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.0.h:9688
RCLASS_ORIGIN
#define RCLASS_ORIGIN(c)
Definition: internal.h:1075
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
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
block_type_proc
@ block_type_proc
Definition: vm_core.h:748
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
mjit_mark
void mjit_mark(void)
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:33
rb_node_init
void rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
Definition: node.c:1095
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.0.h:14544
rb_gc_mark_maybe
void rb_gc_mark_maybe(VALUE obj)
Definition: gc.c:5044
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
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
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
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
atol
long atol(const char *__nptr)
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
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.0.h:9892
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
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
list_for_each
#define list_for_each(h, i, member)
Definition: rb_mjit_min_header-2.7.0.h:9094
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:3345
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:2120
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
long
#define long
Definition: rb_mjit_min_header-2.7.0.h:2880
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
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:3351
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
RUBY_DTRACE_INSN
#define RUBY_DTRACE_INSN(insns_name)
Definition: rb_mjit_min_header-2.7.0.h:11296
vm_core.h
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.0.h:1485
rb_hash_bulk_insert
void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
Definition: hash.c:4515
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:4981
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
entries
struct iseq_catch_table_entry entries[]
Definition: rb_mjit_min_header-2.7.0.h:10827
T_CLASS
#define T_CLASS
Definition: ruby.h:524
RUBY_DTRACE_INSN_OPERAND_ENABLED
#define RUBY_DTRACE_INSN_OPERAND_ENABLED()
Definition: rb_mjit_min_header-2.7.0.h:11297
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::verbose
VALUE verbose
Definition: vm_core.h:645
rb_fiber_struct
Definition: cont.c:226
rb_execution_context_struct::stack_start
VALUE * stack_start
Definition: vm_core.h:887
probes_helper.h
mjit_enabled
#define mjit_enabled
Definition: internal.h:1760
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:5206
vm_insnhelper.c
rb_objspace_free
void rb_objspace_free(rb_objspace_t *objspace)
Definition: gc.c:1600
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
METHOD_VISI_PUBLIC
@ METHOD_VISI_PUBLIC
Definition: method.h:28
rb_vm_struct::cmd
VALUE cmd[RUBY_NSIG]
Definition: vm_core.h:626
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1461
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
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
me
const rb_callable_method_entry_t * me
Definition: rb_mjit_min_header-2.7.0.h:13226
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
mjit_pause
VALUE mjit_pause(_Bool wait_p)
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
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.0.h:2836
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:10217
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.0.h:12521
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_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
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:667
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:3390
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
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
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
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
rb_iseq_constant_body::iseq_encoded
VALUE * iseq_encoded
Definition: vm_core.h:325
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
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
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
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.0.h:5363
rb_eSysStackError
VALUE rb_eSysStackError
Definition: eval.c:34
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
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2779
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
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:1346
block_handler_type_symbol
@ block_handler_type_symbol
Definition: vm_core.h:740
isset
#define isset(a, i)
Definition: rb_mjit_min_header-2.7.0.h:11085
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
PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN
Definition: rb_mjit_min_header-2.7.0.h:4107
rb_method_definition_struct::original_id
ID original_id
Definition: method.h:179
rb_mRubyVMFrozenCore
VALUE rb_mRubyVMFrozenCore
Definition: vm.c:367
rb_vm_pop_frame
MJIT_STATIC void rb_vm_pop_frame(rb_execution_context_t *ec)
Definition: rb_mjit_min_header-2.7.0.h:12308
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
DEFINED_EXPR
@ DEFINED_EXPR
Definition: iseq.h:298
int8_t
__int8_t int8_t
Definition: rb_mjit_min_header-2.7.0.h:1165
rb_method_definition_struct
Definition: method.h:163
vm_exec.h
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5212
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:4715
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
idProc
@ idProc
Definition: rb_mjit_min_header-2.7.0.h:8704
rb_scope_visi_struct
Definition: method.h:35
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
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:9578
rb_method_entry_struct
Definition: method.h:51
rb_mark_tbl
void rb_mark_tbl(st_table *tbl)
Definition: gc.c:5005
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
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.0.h:13504
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
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
realpath
char * realpath(const char *__restrict path, char *__restrict resolved_path)
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:2123
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.0.h:13504
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:3373
mjit_resume
VALUE mjit_resume(void)
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:1865
UNALIGNED_MEMBER_PTR
#define UNALIGNED_MEMBER_PTR(ptr, mem)
Definition: internal.h:2685
iseq_catch_table
Definition: rb_mjit_min_header-2.7.0.h:10860
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
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
id__attached__
@ id__attached__
Definition: rb_mjit_min_header-2.7.0.h:8708
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
idLambda
@ idLambda
Definition: rb_mjit_min_header-2.7.0.h:8705
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
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
RUBY_DTRACE_INSN_OPERAND
#define RUBY_DTRACE_INSN_OPERAND(val, insns_name)
Definition: rb_mjit_min_header-2.7.0.h:11298
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_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
cfp
rb_control_frame_t * cfp
Definition: rb_mjit_min_header-2.7.0.h:14544
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
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