Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

vm.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 vm.c -
4
5 $Author: nagachika $
6
7 Copyright (C) 2004-2007 Koichi Sasada
8
9 **********************************************************************/
10
11 #include "ruby/ruby.h"
12 #include "ruby/vm.h"
13 #include "ruby/st.h"
14 #include "ruby/encoding.h"
15 #include "internal.h"
16
17 #include "gc.h"
18 #include "vm_core.h"
19 #include "iseq.h"
20 #include "eval_intern.h"
21 #include "probes.h"
22 #include "probes_helper.h"
23
24 static inline VALUE *
25 VM_EP_LEP(VALUE *ep)
26 {
27 while (!VM_EP_LEP_P(ep)) {
28 ep = VM_EP_PREV_EP(ep);
29 }
30 return ep;
31 }
32
33 VALUE *
34 rb_vm_ep_local_ep(VALUE *ep)
35 {
36 return VM_EP_LEP(ep);
37 }
38
39 static inline VALUE *
40 VM_CF_LEP(rb_control_frame_t *cfp)
41 {
42 return VM_EP_LEP(cfp->ep);
43 }
44
45 static inline VALUE *
46 VM_CF_PREV_EP(rb_control_frame_t * cfp)
47 {
48 return VM_EP_PREV_EP((cfp)->ep);
49 }
50
51 static inline rb_block_t *
52 VM_CF_BLOCK_PTR(rb_control_frame_t *cfp)
53 {
54 VALUE *ep = VM_CF_LEP(cfp);
55 return VM_EP_BLOCK_PTR(ep);
56 }
57
58 rb_block_t *
59 rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp)
60 {
61 return VM_CF_BLOCK_PTR(cfp);
62 }
63
64 #if VM_COLLECT_USAGE_DETAILS
65 static void vm_collect_usage_operand(int insn, int n, VALUE op);
66 static void vm_collect_usage_insn(int insn);
67 static void vm_collect_usage_register(int reg, int isset);
68 #endif
69
70 static VALUE
71 vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
72 int argc, const VALUE *argv, const rb_block_t *blockptr);
73
74 static rb_serial_t ruby_vm_global_method_state = 1;
75 static rb_serial_t ruby_vm_global_constant_state = 1;
76 static rb_serial_t ruby_vm_class_serial = 1;
77
78 #include "vm_insnhelper.h"
79 #include "vm_insnhelper.c"
80 #include "vm_exec.h"
81 #include "vm_exec.c"
82
83 #include "vm_method.c"
84 #include "vm_eval.c"
85
86 #include <assert.h>
87
88 #define BUFSIZE 0x100
89 #define PROCDEBUG 0
90
91 rb_serial_t
92 rb_next_class_serial(void)
93 {
94 return NEXT_CLASS_SERIAL();
95 }
96
97 VALUE rb_cRubyVM;
98 VALUE rb_cThread;
99 VALUE rb_cEnv;
100 VALUE rb_mRubyVMFrozenCore;
101
102 VALUE ruby_vm_const_missing_count = 0;
103 short ruby_vm_redefined_flag[BOP_LAST_];
104 rb_thread_t *ruby_current_thread = 0;
105 rb_vm_t *ruby_current_vm = 0;
106 rb_event_flag_t ruby_vm_event_flags;
107
108 static void thread_free(void *ptr);
109
110 void
111 rb_vm_inc_const_missing_count(void)
112 {
113 ruby_vm_const_missing_count +=1;
114 }
115
116 /*
117 * call-seq:
118 * RubyVM.stat -> Hash
119 * RubyVM.stat(hsh) -> hsh
120 * RubyVM.stat(Symbol) -> Numeric
121 *
122 * Returns a Hash containing implementation-dependent counters inside the VM.
123 *
124 * This hash includes information about method/constant cache serials:
125 *
126 * {
127 * :global_method_state=>251,
128 * :global_constant_state=>481,
129 * :class_serial=>9029
130 * }
131 *
132 * The contents of the hash are implementation specific and may be changed in
133 * the future.
134 *
135 * This method is only expected to work on C Ruby.
136 */
137
138 static VALUE
139 vm_stat(int argc, VALUE *argv, VALUE self)
140 {
141 static VALUE sym_global_method_state, sym_global_constant_state, sym_class_serial;
142 VALUE arg = Qnil;
143 VALUE hash = Qnil, key = Qnil;
144
145 if (rb_scan_args(argc, argv, "01", &arg) == 1) {
146 if (SYMBOL_P(arg))
147 key = arg;
148 else if (RB_TYPE_P(arg, T_HASH))
149 hash = arg;
150 else
151 rb_raise(rb_eTypeError, "non-hash or symbol given");
152 } else if (arg == Qnil) {
153 hash = rb_hash_new();
154 }
155
156 if (sym_global_method_state == 0) {
157 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
158 S(global_method_state);
159 S(global_constant_state);
160 S(class_serial);
161 #undef S
162 }
163
164 #define SET(name, attr) \
165 if (key == sym_##name) \
166 return SERIALT2NUM(attr); \
167 else if (hash != Qnil) \
168 rb_hash_aset(hash, sym_##name, SERIALT2NUM(attr));
169
170 SET(global_method_state, ruby_vm_global_method_state);
171 SET(global_constant_state, ruby_vm_global_constant_state);
172 SET(class_serial, ruby_vm_class_serial);
173 #undef SET
174
175 if (key != Qnil) /* matched key should return above */
176 rb_raise(rb_eArgError, "unknown key: %s", RSTRING_PTR(rb_id2str(SYM2ID(key))));
177
178 return hash;
179 }
180
181 /* control stack frame */
182
183 static void
184 vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
185 {
186 rb_iseq_t *iseq;
187 GetISeqPtr(iseqval, iseq);
188
189 if (iseq->type != ISEQ_TYPE_TOP) {
190 rb_raise(rb_eTypeError, "Not a toplevel InstructionSequence");
191 }
192
193 /* for return */
194 vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
195 th->top_self, rb_cObject, VM_ENVVAL_BLOCK_PTR(0),
196 iseq->iseq_encoded, th->cfp->sp, iseq->local_size, 0, iseq->stack_max);
197 }
198
199 static void
200 vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref, rb_block_t *base_block)
201 {
202 rb_iseq_t *iseq;
203 GetISeqPtr(iseqval, iseq);
204
205 vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL | VM_FRAME_FLAG_FINISH,
206 base_block->self, base_block->klass,
207 VM_ENVVAL_PREV_EP_PTR(base_block->ep), iseq->iseq_encoded,
208 th->cfp->sp, iseq->local_size, 0, iseq->stack_max);
209
210 if (cref) {
211 th->cfp->ep[-1] = (VALUE)cref;
212 }
213 }
214
215 static void
216 vm_set_main_stack(rb_thread_t *th, VALUE iseqval)
217 {
218 VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
219 rb_binding_t *bind;
220 rb_iseq_t *iseq;
221 rb_env_t *env;
222
223 GetBindingPtr(toplevel_binding, bind);
224 GetEnvPtr(bind->env, env);
225 vm_set_eval_stack(th, iseqval, 0, &env->block);
226
227 /* save binding */
228 GetISeqPtr(iseqval, iseq);
229 if (bind && iseq->local_size > 0) {
230 bind->env = rb_vm_make_env_object(th, th->cfp);
231 }
232 }
233
234 rb_control_frame_t *
235 rb_vm_get_binding_creatable_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
236 {
237 while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
238 if (cfp->iseq) {
239 return (rb_control_frame_t *)cfp;
240 }
241 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
242 }
243 return 0;
244 }
245
246 rb_control_frame_t *
247 rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
248 {
249 while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
250 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
251 return (rb_control_frame_t *)cfp;
252 }
253 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
254 }
255 return 0;
256 }
257
258 static rb_control_frame_t *
259 vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
260 {
261 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
262 return cfp;
263 }
264
265 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
266
267 while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
268 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
269 return cfp;
270 }
271
272 if ((cfp->flag & VM_FRAME_FLAG_PASSED) == 0) {
273 break;
274 }
275 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
276 }
277 return 0;
278 }
279
280 void
281 rb_vm_pop_cfunc_frame(void)
282 {
283 rb_thread_t *th = GET_THREAD();
284 const rb_method_entry_t *me = th->cfp->me;
285 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass, Qnil);
286 RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id);
287 vm_pop_frame(th);
288 }
289
290 void
291 rb_vm_rewind_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
292 {
293 /* check skipped frame */
294 while (th->cfp != cfp) {
295 #if VMDEBUG
296 printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
297 #endif
298 if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_CFUNC) {
299 vm_pop_frame(th);
300 }
301 else { /* unlikely path */
302 rb_vm_pop_cfunc_frame();
303 }
304 }
305 }
306
307 /* obsolete */
308 void
309 rb_frame_pop(void)
310 {
311 rb_thread_t *th = GET_THREAD();
312 vm_pop_frame(th);
313 }
314
315 /* at exit */
316
317 void
318 ruby_vm_at_exit(void (*func)(rb_vm_t *))
319 {
320 rb_ary_push((VALUE)&GET_VM()->at_exit, (VALUE)func);
321 }
322
323 static void
324 ruby_vm_run_at_exit_hooks(rb_vm_t *vm)
325 {
326 VALUE hook = (VALUE)&vm->at_exit;
327
328 while (RARRAY_LEN(hook) > 0) {
329 typedef void rb_vm_at_exit_func(rb_vm_t*);
330 rb_vm_at_exit_func *func = (rb_vm_at_exit_func*)rb_ary_pop(hook);
331 (*func)(vm);
332 }
333 rb_ary_free(hook);
334 }
335
336 /* Env */
337
338 /*
339 env{
340 env[0] // special (block or prev env)
341 env[1] // env object
342 };
343 */
344
345 #define ENV_IN_HEAP_P(th, env) \
346 (!((th)->stack <= (env) && (env) < ((th)->stack + (th)->stack_size)))
347 #define ENV_VAL(env) ((env)[1])
348
349 static void
350 env_mark(void * const ptr)
351 {
352 RUBY_MARK_ENTER("env");
353 if (ptr) {
354 const rb_env_t * const env = ptr;
355
356 if (env->env) {
357 /* TODO: should mark more restricted range */
358 RUBY_GC_INFO("env->env\n");
359 rb_gc_mark_locations(env->env, env->env + env->env_size);
360 }
361
362 RUBY_GC_INFO("env->prev_envval\n");
363 RUBY_MARK_UNLESS_NULL(env->prev_envval);
364 RUBY_MARK_UNLESS_NULL(env->block.self);
365 RUBY_MARK_UNLESS_NULL(env->block.proc);
366
367 if (env->block.iseq) {
368 if (BUILTIN_TYPE(env->block.iseq) == T_NODE) {
369 RUBY_MARK_UNLESS_NULL((VALUE)env->block.iseq);
370 }
371 else {
372 RUBY_MARK_UNLESS_NULL(env->block.iseq->self);
373 }
374 }
375 }
376 RUBY_MARK_LEAVE("env");
377 }
378
379 static void
380 env_free(void * const ptr)
381 {
382 RUBY_FREE_ENTER("env");
383 if (ptr) {
384 rb_env_t *const env = ptr;
385 RUBY_FREE_UNLESS_NULL(env->env);
386 ruby_xfree(ptr);
387 }
388 RUBY_FREE_LEAVE("env");
389 }
390
391 static size_t
392 env_memsize(const void *ptr)
393 {
394 if (ptr) {
395 const rb_env_t * const env = ptr;
396 size_t size = sizeof(rb_env_t);
397 if (env->env) {
398 size += env->env_size * sizeof(VALUE);
399 }
400 return size;
401 }
402 return 0;
403 }
404
405 static const rb_data_type_t env_data_type = {
406 "VM/env",
407 {env_mark, env_free, env_memsize,},
408 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
409 };
410
411 static VALUE
412 env_alloc(void)
413 {
414 VALUE obj;
415 rb_env_t *env;
416 obj = TypedData_Make_Struct(rb_cEnv, rb_env_t, &env_data_type, env);
417 env->env = 0;
418 env->prev_envval = 0;
419 env->block.iseq = 0;
420 return obj;
421 }
422
423 static VALUE check_env_value(VALUE envval);
424
425 static int
426 check_env(rb_env_t * const env)
427 {
428 fprintf(stderr, "---\n");
429 fprintf(stderr, "envptr: %p\n", (void *)&env->block.ep[0]);
430 fprintf(stderr, "envval: %10p ", (void *)env->block.ep[1]);
431 dp(env->block.ep[1]);
432 fprintf(stderr, "ep: %10p\n", (void *)env->block.ep);
433 if (env->prev_envval) {
434 fprintf(stderr, ">>\n");
435 check_env_value(env->prev_envval);
436 fprintf(stderr, "<<\n");
437 }
438 return 1;
439 }
440
441 static VALUE
442 check_env_value(VALUE envval)
443 {
444 rb_env_t *env;
445 GetEnvPtr(envval, env);
446
447 if (check_env(env)) {
448 return envval;
449 }
450 rb_bug("invalid env");
451 return Qnil; /* unreachable */
452 }
453
454 static VALUE
455 vm_make_env_each(rb_thread_t * const th, rb_control_frame_t * const cfp,
456 VALUE *envptr, VALUE * const endptr)
457 {
458 VALUE envval, penvval = 0;
459 rb_env_t *env;
460 VALUE *nenvptr;
461 int i, local_size;
462
463 if (ENV_IN_HEAP_P(th, envptr)) {
464 return ENV_VAL(envptr);
465 }
466
467 if (envptr != endptr) {
468 VALUE *penvptr = GC_GUARDED_PTR_REF(*envptr);
469 rb_control_frame_t *pcfp = cfp;
470
471 if (ENV_IN_HEAP_P(th, penvptr)) {
472 penvval = ENV_VAL(penvptr);
473 }
474 else {
475 while (pcfp->ep != penvptr) {
476 pcfp++;
477 if (pcfp->ep == 0) {
478 SDR();
479 rb_bug("invalid ep");
480 }
481 }
482 penvval = vm_make_env_each(th, pcfp, penvptr, endptr);
483 *envptr = VM_ENVVAL_PREV_EP_PTR(pcfp->ep);
484 }
485 }
486
487 /* allocate env */
488 envval = env_alloc();
489 GetEnvPtr(envval, env);
490
491 if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
492 local_size = 2;
493 }
494 else {
495 local_size = cfp->iseq->local_size;
496 }
497
498 env->env_size = local_size + 1 + 1;
499 env->local_size = local_size;
500 env->env = ALLOC_N(VALUE, env->env_size);
501 env->prev_envval = penvval;
502
503 for (i = 0; i <= local_size; i++) {
504 env->env[i] = envptr[-local_size + i];
505 #if 0
506 fprintf(stderr, "%2d ", &envptr[-local_size + i] - th->stack); dp(env->env[i]);
507 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
508 /* clear value stack for GC */
509 envptr[-local_size + i] = 0;
510 }
511 #endif
512 }
513
514 *envptr = envval; /* GC mark */
515 nenvptr = &env->env[i - 1];
516 nenvptr[1] = envval; /* frame self */
517
518 /* reset ep in cfp */
519 cfp->ep = nenvptr;
520
521 /* as Binding */
522 env->block.self = cfp->self;
523 env->block.ep = cfp->ep;
524 env->block.iseq = cfp->iseq;
525
526 if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
527 /* TODO */
528 env->block.iseq = 0;
529 }
530 return envval;
531 }
532
533 static int
534 collect_local_variables_in_iseq(rb_iseq_t *iseq, const VALUE ary)
535 {
536 int i;
537 if (!iseq) return 0;
538 for (i = 0; i < iseq->local_table_size; i++) {
539 ID lid = iseq->local_table[i];
540 if (rb_is_local_id(lid)) {
541 rb_ary_push(ary, ID2SYM(lid));
542 }
543 }
544 return 1;
545 }
546
547 static int
548 collect_local_variables_in_env(rb_env_t * env, const VALUE ary)
549 {
550
551 while (collect_local_variables_in_iseq(env->block.iseq, ary),
552 env->prev_envval) {
553 GetEnvPtr(env->prev_envval, env);
554 }
555 return 0;
556 }
557
558 static int
559 vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *ep, VALUE ary)
560 {
561 if (ENV_IN_HEAP_P(th, ep)) {
562 rb_env_t *env;
563 GetEnvPtr(ENV_VAL(ep), env);
564 collect_local_variables_in_env(env, ary);
565 return 1;
566 }
567 else {
568 return 0;
569 }
570 }
571
572 static void vm_rewrite_ep_in_errinfo(rb_thread_t *th);
573 static VALUE vm_make_proc_from_block(rb_thread_t *th, rb_block_t *block);
574 static VALUE vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp, VALUE *blockprocptr);
575
576 VALUE
577 rb_vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp)
578 {
579 VALUE blockprocval;
580 return vm_make_env_object(th, cfp, &blockprocval);
581 }
582
583 static VALUE
584 vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp, VALUE *blockprocptr)
585 {
586 VALUE envval;
587 VALUE *lep = VM_CF_LEP(cfp);
588 rb_block_t *blockptr = VM_EP_BLOCK_PTR(lep);
589
590 if (blockptr) {
591 VALUE blockprocval = vm_make_proc_from_block(th, blockptr);
592 rb_proc_t *p;
593 GetProcPtr(blockprocval, p);
594 lep[0] = VM_ENVVAL_BLOCK_PTR(&p->block);
595 *blockprocptr = blockprocval;
596 }
597
598 envval = vm_make_env_each(th, cfp, cfp->ep, lep);
599 vm_rewrite_ep_in_errinfo(th);
600
601 if (PROCDEBUG) {
602 check_env_value(envval);
603 }
604
605 return envval;
606 }
607
608 static void
609 vm_rewrite_ep_in_errinfo(rb_thread_t *th)
610 {
611 rb_control_frame_t *cfp = th->cfp;
612 while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
613 /* rewrite ep in errinfo to point to heap */
614 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) &&
615 (cfp->iseq->type == ISEQ_TYPE_RESCUE ||
616 cfp->iseq->type == ISEQ_TYPE_ENSURE)) {
617 VALUE errinfo = cfp->ep[-2]; /* #$! */
618 if (RB_TYPE_P(errinfo, T_NODE)) {
619 VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(errinfo);
620 if (! ENV_IN_HEAP_P(th, escape_ep)) {
621 VALUE epval = *escape_ep;
622 if (!SPECIAL_CONST_P(epval) && RBASIC(epval)->klass == rb_cEnv) {
623 rb_env_t *epenv;
624 GetEnvPtr(epval, epenv);
625 SET_THROWOBJ_CATCH_POINT(errinfo, (VALUE)(epenv->env + epenv->local_size));
626 }
627 }
628 }
629 }
630 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
631 }
632 }
633
634 void
635 rb_vm_stack_to_heap(rb_thread_t *th)
636 {
637 rb_control_frame_t *cfp = th->cfp;
638 while ((cfp = rb_vm_get_binding_creatable_next_cfp(th, cfp)) != 0) {
639 rb_vm_make_env_object(th, cfp);
640 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
641 }
642 }
643
644 /* Proc */
645
646 static VALUE
647 vm_make_proc_from_block(rb_thread_t *th, rb_block_t *block)
648 {
649 if (!block->proc) {
650 block->proc = rb_vm_make_proc(th, block, rb_cProc);
651 }
652 return block->proc;
653 }
654
655 VALUE
656 rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
657 {
658 VALUE procval, envval, blockprocval = 0;
659 rb_proc_t *proc;
660 rb_control_frame_t *cfp = RUBY_VM_GET_CFP_FROM_BLOCK_PTR(block);
661
662 if (block->proc) {
663 rb_bug("rb_vm_make_proc: Proc value is already created.");
664 }
665
666 envval = vm_make_env_object(th, cfp, &blockprocval);
667
668 if (PROCDEBUG) {
669 check_env_value(envval);
670 }
671 procval = rb_proc_alloc(klass);
672 GetProcPtr(procval, proc);
673 proc->blockprocval = blockprocval;
674 proc->block.self = block->self;
675 proc->block.klass = block->klass;
676 proc->block.ep = block->ep;
677 proc->block.iseq = block->iseq;
678 proc->block.proc = procval;
679 proc->envval = envval;
680 proc->safe_level = th->safe_level;
681
682 if (VMDEBUG) {
683 if (th->stack < block->ep && block->ep < th->stack + th->stack_size) {
684 rb_bug("invalid ptr: block->ep");
685 }
686 }
687
688 return procval;
689 }
690
691 /* Binding */
692
693 VALUE
694 rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp)
695 {
696 rb_control_frame_t *cfp = rb_vm_get_binding_creatable_next_cfp(th, src_cfp);
697 rb_control_frame_t *ruby_level_cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp);
698 VALUE bindval, envval;
699 rb_binding_t *bind;
700 VALUE blockprocval = 0;
701
702 if (cfp == 0 || ruby_level_cfp == 0) {
703 rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
704 }
705
706 while (1) {
707 envval = vm_make_env_object(th, cfp, &blockprocval);
708 if (cfp == ruby_level_cfp) {
709 break;
710 }
711 cfp = rb_vm_get_binding_creatable_next_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
712 }
713
714 bindval = rb_binding_alloc(rb_cBinding);
715 GetBindingPtr(bindval, bind);
716 bind->env = envval;
717 bind->path = ruby_level_cfp->iseq->location.path;
718 bind->blockprocval = blockprocval;
719 bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp);
720
721 return bindval;
722 }
723
724 VALUE *
725 rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars)
726 {
727 VALUE envval = bind->env, path = bind->path, iseqval;
728 rb_env_t *env;
729 rb_block_t *base_block;
730 rb_thread_t *th = GET_THREAD();
731 rb_iseq_t *base_iseq;
732 NODE *node = 0;
733 ID minibuf[4], *dyns = minibuf;
734 VALUE idtmp = 0;
735 VALUE blockprocval = 0;
736
737 if (dyncount < 0) return 0;
738
739 GetEnvPtr(envval, env);
740
741 base_block = &env->block;
742 base_iseq = base_block->iseq;
743
744 if (dyncount >= numberof(minibuf)) dyns = ALLOCV_N(ID, idtmp, dyncount + 1);
745
746 dyns[0] = dyncount;
747 MEMCPY(dyns + 1, dynvars, ID, dyncount);
748 node = NEW_NODE(NODE_SCOPE, dyns, 0, 0);
749
750 iseqval = rb_iseq_new(node, base_iseq->location.label, path, path,
751 base_iseq->self, ISEQ_TYPE_EVAL);
752 node->u1.tbl = 0; /* reset table */
753 ALLOCV_END(idtmp);
754
755 vm_set_eval_stack(th, iseqval, 0, base_block);
756 bind->env = vm_make_env_object(th, th->cfp, &blockprocval);
757 bind->blockprocval = blockprocval;
758 vm_pop_frame(th);
759 GetEnvPtr(bind->env, env);
760
761 return env->env;
762 }
763
764 /* C -> Ruby: block */
765
766 static inline VALUE
767 invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
768 VALUE self, int argc, const VALUE *argv,
769 const rb_block_t *blockptr, const NODE *cref,
770 VALUE defined_class)
771 {
772 if (SPECIAL_CONST_P(block->iseq)) {
773 return Qnil;
774 }
775 else if (BUILTIN_TYPE(block->iseq) != T_NODE) {
776 VALUE ret;
777 const rb_iseq_t *iseq = block->iseq;
778 const rb_control_frame_t *cfp;
779 int i, opt_pc, arg_size = iseq->arg_size;
780 int type = block_proc_is_lambda(block->proc) ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK;
781 const rb_method_entry_t *me = th->passed_bmethod_me;
782 th->passed_bmethod_me = 0;
783 cfp = th->cfp;
784
785 for (i=0; i<argc; i++) {
786 cfp->sp[i] = argv[i];
787 }
788
789 opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr,
790 type == VM_FRAME_MAGIC_LAMBDA);
791
792 if (me != 0) {
793 /* bmethod */
794 vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_BMETHOD,
795 self, defined_class,
796 VM_ENVVAL_PREV_EP_PTR(block->ep),
797 iseq->iseq_encoded + opt_pc,
798 cfp->sp + arg_size, iseq->local_size - arg_size,
799 me, iseq->stack_max);
800
801 RUBY_DTRACE_METHOD_ENTRY_HOOK(th, me->klass, me->called_id);
802 EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, self, me->called_id, me->klass, Qnil);
803 }
804 else {
805 vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
806 self, defined_class,
807 VM_ENVVAL_PREV_EP_PTR(block->ep),
808 iseq->iseq_encoded + opt_pc,
809 cfp->sp + arg_size, iseq->local_size - arg_size,
810 0, iseq->stack_max);
811 }
812
813 if (cref) {
814 th->cfp->ep[-1] = (VALUE)cref;
815 }
816
817 ret = vm_exec(th);
818
819 if (me) {
820 /* bmethod */
821 EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, self, me->called_id, me->klass, ret);
822 RUBY_DTRACE_METHOD_RETURN_HOOK(th, me->klass, me->called_id);
823 }
824
825 return ret;
826 }
827 else {
828 return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr);
829 }
830 }
831
832 static inline const rb_block_t *
833 check_block(rb_thread_t *th)
834 {
835 const rb_block_t *blockptr = VM_CF_BLOCK_PTR(th->cfp);
836
837 if (blockptr == 0) {
838 rb_vm_localjump_error("no block given", Qnil, 0);
839 }
840
841 return blockptr;
842 }
843
844 static inline VALUE
845 vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
846 {
847 const rb_block_t *blockptr = check_block(th);
848 return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref,
849 blockptr->klass);
850 }
851
852 static inline VALUE
853 vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
854 {
855 const rb_block_t *blockptr = check_block(th);
856 return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0,
857 blockptr->klass);
858 }
859
860 static inline VALUE
861 vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, const rb_block_t *blockargptr)
862 {
863 const rb_block_t *blockptr = check_block(th);
864 return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, blockargptr, 0,
865 blockptr->klass);
866 }
867
868 static VALUE
869 vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
870 int argc, const VALUE *argv, const rb_block_t *blockptr)
871 {
872 VALUE val = Qundef;
873 int state;
874 volatile int stored_safe = th->safe_level;
875
876 TH_PUSH_TAG(th);
877 if ((state = EXEC_TAG()) == 0) {
878 if (!proc->is_from_method) {
879 th->safe_level = proc->safe_level;
880 }
881 val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0,
882 defined_class);
883 }
884 TH_POP_TAG();
885
886 if (!proc->is_from_method) {
887 th->safe_level = stored_safe;
888 }
889
890 if (state) {
891 JUMP_TAG(state);
892 }
893 return val;
894 }
895
896 VALUE
897 rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
898 int argc, const VALUE *argv, const rb_block_t *blockptr)
899 {
900 return vm_invoke_proc(th, proc, proc->block.self, proc->block.klass,
901 argc, argv, blockptr);
902 }
903
904 /* special variable */
905
906 static rb_control_frame_t *
907 vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
908 {
909 while (cfp->pc == 0) {
910 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
911 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
912 return 0;
913 }
914 }
915 return cfp;
916 }
917
918 static VALUE
919 vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
920 {
921 cfp = vm_normal_frame(th, cfp);
922 return lep_svar_get(th, cfp ? VM_CF_LEP(cfp) : 0, key);
923 }
924
925 static void
926 vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
927 {
928 cfp = vm_normal_frame(th, cfp);
929 lep_svar_set(th, cfp ? VM_CF_LEP(cfp) : 0, key, val);
930 }
931
932 static VALUE
933 vm_svar_get(VALUE key)
934 {
935 rb_thread_t *th = GET_THREAD();
936 return vm_cfp_svar_get(th, th->cfp, key);
937 }
938
939 static void
940 vm_svar_set(VALUE key, VALUE val)
941 {
942 rb_thread_t *th = GET_THREAD();
943 vm_cfp_svar_set(th, th->cfp, key, val);
944 }
945
946 VALUE
947 rb_backref_get(void)
948 {
949 return vm_svar_get(1);
950 }
951
952 void
953 rb_backref_set(VALUE val)
954 {
955 vm_svar_set(1, val);
956 }
957
958 VALUE
959 rb_lastline_get(void)
960 {
961 return vm_svar_get(0);
962 }
963
964 void
965 rb_lastline_set(VALUE val)
966 {
967 vm_svar_set(0, val);
968 }
969
970 /* misc */
971
972 VALUE
973 rb_sourcefilename(void)
974 {
975 rb_thread_t *th = GET_THREAD();
976 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
977
978 if (cfp) {
979 return cfp->iseq->location.path;
980 }
981 else {
982 return Qnil;
983 }
984 }
985
986 const char *
987 rb_sourcefile(void)
988 {
989 rb_thread_t *th = GET_THREAD();
990 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
991
992 if (cfp) {
993 return RSTRING_PTR(cfp->iseq->location.path);
994 }
995 else {
996 return 0;
997 }
998 }
999
1000 int
1001 rb_sourceline(void)
1002 {
1003 rb_thread_t *th = GET_THREAD();
1004 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
1005
1006 if (cfp) {
1007 return rb_vm_get_sourceline(cfp);
1008 }
1009 else {
1010 return 0;
1011 }
1012 }
1013
1014 NODE *
1015 rb_vm_cref(void)
1016 {
1017 rb_thread_t *th = GET_THREAD();
1018 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
1019
1020 if (cfp == 0) {
1021 return NULL;
1022 }
1023 return rb_vm_get_cref(cfp->iseq, cfp->ep);
1024 }
1025
1026 NODE *
1027 rb_vm_cref_in_context(VALUE self)
1028 {
1029 rb_thread_t *th = GET_THREAD();
1030 const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
1031 if (cfp->self != self) return NULL;
1032 return rb_vm_get_cref(cfp->iseq, cfp->ep);
1033 }
1034
1035 #if 0
1036 void
1037 debug_cref(NODE *cref)
1038 {
1039 while (cref) {
1040 dp(cref->nd_clss);
1041 printf("%ld\n", cref->nd_visi);
1042 cref = cref->nd_next;
1043 }
1044 }
1045 #endif
1046
1047 VALUE
1048 rb_vm_cbase(void)
1049 {
1050 rb_thread_t *th = GET_THREAD();
1051 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
1052
1053 if (cfp == 0) {
1054 rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
1055 }
1056 return vm_get_cbase(cfp->iseq, cfp->ep);
1057 }
1058
1059 /* jump */
1060
1061 static VALUE
1062 make_localjump_error(const char *mesg, VALUE value, int reason)
1063 {
1064 extern VALUE rb_eLocalJumpError;
1065 VALUE exc = rb_exc_new2(rb_eLocalJumpError, mesg);
1066 ID id;
1067
1068 switch (reason) {
1069 case TAG_BREAK:
1070 CONST_ID(id, "break");
1071 break;
1072 case TAG_REDO:
1073 CONST_ID(id, "redo");
1074 break;
1075 case TAG_RETRY:
1076 CONST_ID(id, "retry");
1077 break;
1078 case TAG_NEXT:
1079 CONST_ID(id, "next");
1080 break;
1081 case TAG_RETURN:
1082 CONST_ID(id, "return");
1083 break;
1084 default:
1085 CONST_ID(id, "noreason");
1086 break;
1087 }
1088 rb_iv_set(exc, "@exit_value", value);
1089 rb_iv_set(exc, "@reason", ID2SYM(id));
1090 return exc;
1091 }
1092
1093 void
1094 rb_vm_localjump_error(const char *mesg, VALUE value, int reason)
1095 {
1096 VALUE exc = make_localjump_error(mesg, value, reason);
1097 rb_exc_raise(exc);
1098 }
1099
1100 VALUE
1101 rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
1102 {
1103 VALUE result = Qnil;
1104
1105 if (val == Qundef) {
1106 val = GET_THREAD()->tag->retval;
1107 }
1108 switch (state) {
1109 case 0:
1110 break;
1111 case TAG_RETURN:
1112 result = make_localjump_error("unexpected return", val, state);
1113 break;
1114 case TAG_BREAK:
1115 result = make_localjump_error("unexpected break", val, state);
1116 break;
1117 case TAG_NEXT:
1118 result = make_localjump_error("unexpected next", val, state);
1119 break;
1120 case TAG_REDO:
1121 result = make_localjump_error("unexpected redo", Qnil, state);
1122 break;
1123 case TAG_RETRY:
1124 result = make_localjump_error("retry outside of rescue clause", Qnil, state);
1125 break;
1126 default:
1127 break;
1128 }
1129 return result;
1130 }
1131
1132 void
1133 rb_vm_jump_tag_but_local_jump(int state)
1134 {
1135 VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef);
1136 if (!NIL_P(exc)) rb_exc_raise(exc);
1137 JUMP_TAG(state);
1138 }
1139
1140 NORETURN(static void vm_iter_break(rb_thread_t *th, VALUE val));
1141
1142 static void
1143 vm_iter_break(rb_thread_t *th, VALUE val)
1144 {
1145 rb_control_frame_t *cfp = th->cfp;
1146 VALUE *ep = VM_CF_PREV_EP(cfp);
1147
1148 th->state = TAG_BREAK;
1149 th->errinfo = (VALUE)NEW_THROW_OBJECT(val, (VALUE)ep, TAG_BREAK);
1150 TH_JUMP_TAG(th, TAG_BREAK);
1151 }
1152
1153 void
1154 rb_iter_break(void)
1155 {
1156 vm_iter_break(GET_THREAD(), Qnil);
1157 }
1158
1159 void
1160 rb_iter_break_value(VALUE val)
1161 {
1162 vm_iter_break(GET_THREAD(), val);
1163 }
1164
1165 /* optimization: redefine management */
1166
1167 static st_table *vm_opt_method_table = 0;
1168
1169 static int
1170 vm_redefinition_check_flag(VALUE klass)
1171 {
1172 if (klass == rb_cFixnum) return FIXNUM_REDEFINED_OP_FLAG;
1173 if (klass == rb_cFloat) return FLOAT_REDEFINED_OP_FLAG;
1174 if (klass == rb_cString) return STRING_REDEFINED_OP_FLAG;
1175 if (klass == rb_cArray) return ARRAY_REDEFINED_OP_FLAG;
1176 if (klass == rb_cHash) return HASH_REDEFINED_OP_FLAG;
1177 if (klass == rb_cBignum) return BIGNUM_REDEFINED_OP_FLAG;
1178 if (klass == rb_cSymbol) return SYMBOL_REDEFINED_OP_FLAG;
1179 if (klass == rb_cTime) return TIME_REDEFINED_OP_FLAG;
1180 if (klass == rb_cRegexp) return REGEXP_REDEFINED_OP_FLAG;
1181 return 0;
1182 }
1183
1184 static void
1185 rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
1186 {
1187 st_data_t bop;
1188 if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) {
1189 if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
1190 int flag = vm_redefinition_check_flag(klass);
1191
1192 ruby_vm_redefined_flag[bop] |= flag;
1193 }
1194 }
1195 }
1196
1197 static int
1198 check_redefined_method(st_data_t key, st_data_t value, st_data_t data)
1199 {
1200 ID mid = (ID)key;
1201 rb_method_entry_t *me = (rb_method_entry_t *)value;
1202 VALUE klass = (VALUE)data;
1203 rb_method_entry_t *newme = rb_method_entry(klass, mid, NULL);
1204
1205 if (newme != me)
1206 rb_vm_check_redefinition_opt_method(me, me->klass);
1207 return ST_CONTINUE;
1208 }
1209
1210 void
1211 rb_vm_check_redefinition_by_prepend(VALUE klass)
1212 {
1213 if (!vm_redefinition_check_flag(klass)) return;
1214 st_foreach(RCLASS_M_TBL(RCLASS_ORIGIN(klass)), check_redefined_method,
1215 (st_data_t)klass);
1216 }
1217
1218 static void
1219 add_opt_method(VALUE klass, ID mid, VALUE bop)
1220 {
1221 rb_method_entry_t *me;
1222 if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def &&
1223 me->def->type == VM_METHOD_TYPE_CFUNC) {
1224 st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop);
1225 }
1226 else {
1227 rb_bug("undefined optimized method: %s", rb_id2name(mid));
1228 }
1229 }
1230
1231 static void
1232 vm_init_redefined_flag(void)
1233 {
1234 ID mid;
1235 VALUE bop;
1236
1237 vm_opt_method_table = st_init_numtable();
1238
1239 #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0)
1240 #define C(k) add_opt_method(rb_c##k, mid, bop)
1241 OP(PLUS, PLUS), (C(Fixnum), C(Float), C(String), C(Array));
1242 OP(MINUS, MINUS), (C(Fixnum), C(Float));
1243 OP(MULT, MULT), (C(Fixnum), C(Float));
1244 OP(DIV, DIV), (C(Fixnum), C(Float));
1245 OP(MOD, MOD), (C(Fixnum), C(Float));
1246 OP(Eq, EQ), (C(Fixnum), C(Float), C(String));
1247 OP(Eqq, EQQ), (C(Fixnum), C(Bignum), C(Float), C(Symbol), C(String));
1248 OP(LT, LT), (C(Fixnum), C(Float));
1249 OP(LE, LE), (C(Fixnum), C(Float));
1250 OP(GT, GT), (C(Fixnum), C(Float));
1251 OP(GE, GE), (C(Fixnum), C(Float));
1252 OP(LTLT, LTLT), (C(String), C(Array));
1253 OP(AREF, AREF), (C(Array), C(Hash));
1254 OP(ASET, ASET), (C(Array), C(Hash));
1255 OP(Length, LENGTH), (C(Array), C(String), C(Hash));
1256 OP(Size, SIZE), (C(Array), C(String), C(Hash));
1257 OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash));
1258 OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
1259 OP(EqTilde, MATCH), (C(Regexp), C(String));
1260 OP(Freeze, FREEZE), (C(String));
1261 #undef C
1262 #undef OP
1263 }
1264
1265 /* for vm development */
1266
1267 #if VMDEBUG
1268 static const char *
1269 vm_frametype_name(const rb_control_frame_t *cfp)
1270 {
1271 switch (VM_FRAME_TYPE(cfp)) {
1272 case VM_FRAME_MAGIC_METHOD: return "method";
1273 case VM_FRAME_MAGIC_BLOCK: return "block";
1274 case VM_FRAME_MAGIC_CLASS: return "class";
1275 case VM_FRAME_MAGIC_TOP: return "top";
1276 case VM_FRAME_MAGIC_CFUNC: return "cfunc";
1277 case VM_FRAME_MAGIC_PROC: return "proc";
1278 case VM_FRAME_MAGIC_IFUNC: return "ifunc";
1279 case VM_FRAME_MAGIC_EVAL: return "eval";
1280 case VM_FRAME_MAGIC_LAMBDA: return "lambda";
1281 case VM_FRAME_MAGIC_RESCUE: return "rescue";
1282 default:
1283 rb_bug("unknown frame");
1284 }
1285 }
1286 #endif
1287
1288 /* evaluator body */
1289
1290 /* finish
1291 VMe (h1) finish
1292 VM finish F1 F2
1293 cfunc finish F1 F2 C1
1294 rb_funcall finish F1 F2 C1
1295 VMe finish F1 F2 C1
1296 VM finish F1 F2 C1 F3
1297
1298 F1 - F3 : pushed by VM
1299 C1 : pushed by send insn (CFUNC)
1300
1301 struct CONTROL_FRAME {
1302 VALUE *pc; // cfp[0], program counter
1303 VALUE *sp; // cfp[1], stack pointer
1304 VALUE *bp; // cfp[2], base pointer
1305 rb_iseq_t *iseq; // cfp[3], iseq
1306 VALUE flag; // cfp[4], magic
1307 VALUE self; // cfp[5], self
1308 VALUE *ep; // cfp[6], env pointer
1309 rb_iseq_t * block_iseq; // cfp[7], block iseq
1310 VALUE proc; // cfp[8], always 0
1311 };
1312
1313 struct BLOCK {
1314 VALUE self;
1315 VALUE *ep;
1316 rb_iseq_t *block_iseq;
1317 VALUE proc;
1318 };
1319
1320 struct METHOD_CONTROL_FRAME {
1321 rb_control_frame_t frame;
1322 };
1323
1324 struct METHOD_FRAME {
1325 VALUE arg0;
1326 ...
1327 VALUE argM;
1328 VALUE param0;
1329 ...
1330 VALUE paramN;
1331 VALUE cref;
1332 VALUE special; // lep [1]
1333 struct block_object *block_ptr | 0x01; // lep [0]
1334 };
1335
1336 struct BLOCK_CONTROL_FRAME {
1337 rb_control_frame_t frame;
1338 };
1339
1340 struct BLOCK_FRAME {
1341 VALUE arg0;
1342 ...
1343 VALUE argM;
1344 VALUE param0;
1345 ...
1346 VALUE paramN;
1347 VALUE cref;
1348 VALUE *(prev_ptr | 0x01); // ep[0]
1349 };
1350
1351 struct CLASS_CONTROL_FRAME {
1352 rb_control_frame_t frame;
1353 };
1354
1355 struct CLASS_FRAME {
1356 VALUE param0;
1357 ...
1358 VALUE paramN;
1359 VALUE cref;
1360 VALUE prev_ep; // for frame jump
1361 };
1362
1363 struct C_METHOD_CONTROL_FRAME {
1364 VALUE *pc; // 0
1365 VALUE *sp; // stack pointer
1366 VALUE *bp; // base pointer (used in exception)
1367 rb_iseq_t *iseq; // cmi
1368 VALUE magic; // C_METHOD_FRAME
1369 VALUE self; // ?
1370 VALUE *ep; // ep == lep
1371 rb_iseq_t * block_iseq; //
1372 VALUE proc; // always 0
1373 };
1374
1375 struct C_BLOCK_CONTROL_FRAME {
1376 VALUE *pc; // point only "finish" insn
1377 VALUE *sp; // sp
1378 rb_iseq_t *iseq; // ?
1379 VALUE magic; // C_METHOD_FRAME
1380 VALUE self; // needed?
1381 VALUE *ep; // ep
1382 rb_iseq_t * block_iseq; // 0
1383 };
1384 */
1385
1386
1387 static VALUE
1388 vm_exec(rb_thread_t *th)
1389 {
1390 int state;
1391 VALUE result, err;
1392 VALUE initial = 0;
1393
1394 TH_PUSH_TAG(th);
1395 _tag.retval = Qnil;
1396 if ((state = EXEC_TAG()) == 0) {
1397 vm_loop_start:
1398 result = vm_exec_core(th, initial);
1399 if ((state = th->state) != 0) {
1400 err = result;
1401 th->state = 0;
1402 goto exception_handler;
1403 }
1404 }
1405 else {
1406 int i;
1407 struct iseq_catch_table_entry *entry;
1408 unsigned long epc, cont_pc, cont_sp;
1409 VALUE catch_iseqval;
1410 rb_control_frame_t *cfp;
1411 VALUE type;
1412 VALUE *escape_ep;
1413
1414 err = th->errinfo;
1415
1416 exception_handler:
1417 cont_pc = cont_sp = catch_iseqval = 0;
1418
1419 while (th->cfp->pc == 0 || th->cfp->iseq == 0) {
1420 if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
1421 const rb_method_entry_t *me = th->cfp->me;
1422 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass, Qnil);
1423 RUBY_DTRACE_METHOD_RETURN_HOOK(th, me->klass, me->called_id);
1424 }
1425 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
1426 }
1427
1428 cfp = th->cfp;
1429 epc = cfp->pc - cfp->iseq->iseq_encoded;
1430
1431 escape_ep = NULL;
1432 if (state == TAG_BREAK || state == TAG_RETURN) {
1433 escape_ep = GET_THROWOBJ_CATCH_POINT(err);
1434
1435 if (cfp->ep == escape_ep) {
1436 if (state == TAG_RETURN) {
1437 if (!VM_FRAME_TYPE_FINISH_P(cfp)) {
1438 SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp + 1)->ep);
1439 SET_THROWOBJ_STATE(err, state = TAG_BREAK);
1440 }
1441 else {
1442 for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1443 entry = &cfp->iseq->catch_table[i];
1444 if (entry->start < epc && entry->end >= epc) {
1445 if (entry->type == CATCH_TYPE_ENSURE) {
1446 catch_iseqval = entry->iseq;
1447 cont_pc = entry->cont;
1448 cont_sp = entry->sp;
1449 break;
1450 }
1451 }
1452 }
1453 if (!catch_iseqval) {
1454 result = GET_THROWOBJ_VAL(err);
1455 th->errinfo = Qnil;
1456
1457 switch (VM_FRAME_TYPE(cfp)) {
1458 case VM_FRAME_MAGIC_LAMBDA:
1459 EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
1460 break;
1461 }
1462
1463 vm_pop_frame(th);
1464 goto finish_vme;
1465 }
1466 }
1467 /* through */
1468 }
1469 else {
1470 /* TAG_BREAK */
1471 #if OPT_STACK_CACHING
1472 initial = (GET_THROWOBJ_VAL(err));
1473 #else
1474 *th->cfp->sp++ = (GET_THROWOBJ_VAL(err));
1475 #endif
1476 th->errinfo = Qnil;
1477 goto vm_loop_start;
1478 }
1479 }
1480 }
1481
1482 if (state == TAG_RAISE) {
1483 for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1484 entry = &cfp->iseq->catch_table[i];
1485 if (entry->start < epc && entry->end >= epc) {
1486
1487 if (entry->type == CATCH_TYPE_RESCUE ||
1488 entry->type == CATCH_TYPE_ENSURE) {
1489 catch_iseqval = entry->iseq;
1490 cont_pc = entry->cont;
1491 cont_sp = entry->sp;
1492 break;
1493 }
1494 }
1495 }
1496 }
1497 else if (state == TAG_RETRY) {
1498 for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1499 entry = &cfp->iseq->catch_table[i];
1500 if (entry->start < epc && entry->end >= epc) {
1501
1502 if (entry->type == CATCH_TYPE_ENSURE) {
1503 catch_iseqval = entry->iseq;
1504 cont_pc = entry->cont;
1505 cont_sp = entry->sp;
1506 break;
1507 }
1508 else if (entry->type == CATCH_TYPE_RETRY) {
1509 VALUE *escape_ep;
1510 escape_ep = GET_THROWOBJ_CATCH_POINT(err);
1511 if (cfp->ep == escape_ep) {
1512 cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
1513 th->errinfo = Qnil;
1514 goto vm_loop_start;
1515 }
1516 }
1517 }
1518 }
1519 }
1520 else if (state == TAG_BREAK && ((VALUE)escape_ep & ~0x03) == 0) {
1521 type = CATCH_TYPE_BREAK;
1522
1523 search_restart_point:
1524 for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1525 entry = &cfp->iseq->catch_table[i];
1526
1527 if (entry->start < epc && entry->end >= epc) {
1528 if (entry->type == CATCH_TYPE_ENSURE) {
1529 catch_iseqval = entry->iseq;
1530 cont_pc = entry->cont;
1531 cont_sp = entry->sp;
1532 break;
1533 }
1534 else if (entry->type == type) {
1535 cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
1536 cfp->sp = vm_base_ptr(cfp) + entry->sp;
1537
1538 if (state != TAG_REDO) {
1539 #if OPT_STACK_CACHING
1540 initial = (GET_THROWOBJ_VAL(err));
1541 #else
1542 *th->cfp->sp++ = (GET_THROWOBJ_VAL(err));
1543 #endif
1544 }
1545 th->errinfo = Qnil;
1546 th->state = 0;
1547 goto vm_loop_start;
1548 }
1549 }
1550 }
1551 }
1552 else if (state == TAG_REDO) {
1553 type = CATCH_TYPE_REDO;
1554 goto search_restart_point;
1555 }
1556 else if (state == TAG_NEXT) {
1557 type = CATCH_TYPE_NEXT;
1558 goto search_restart_point;
1559 }
1560 else {
1561 for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1562 entry = &cfp->iseq->catch_table[i];
1563 if (entry->start < epc && entry->end >= epc) {
1564
1565 if (entry->type == CATCH_TYPE_ENSURE) {
1566 catch_iseqval = entry->iseq;
1567 cont_pc = entry->cont;
1568 cont_sp = entry->sp;
1569 break;
1570 }
1571 }
1572 }
1573 }
1574
1575 if (catch_iseqval != 0) {
1576 /* found catch table */
1577 rb_iseq_t *catch_iseq;
1578
1579 /* enter catch scope */
1580 GetISeqPtr(catch_iseqval, catch_iseq);
1581 cfp->sp = vm_base_ptr(cfp) + cont_sp;
1582 cfp->pc = cfp->iseq->iseq_encoded + cont_pc;
1583
1584 /* push block frame */
1585 cfp->sp[0] = err;
1586 vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_RESCUE,
1587 cfp->self, cfp->klass,
1588 VM_ENVVAL_PREV_EP_PTR(cfp->ep),
1589 catch_iseq->iseq_encoded,
1590 cfp->sp + 1 /* push value */,
1591 catch_iseq->local_size - 1,
1592 cfp->me, catch_iseq->stack_max);
1593
1594 state = 0;
1595 th->state = 0;
1596 th->errinfo = Qnil;
1597 goto vm_loop_start;
1598 }
1599 else {
1600 /* skip frame */
1601
1602 switch (VM_FRAME_TYPE(th->cfp)) {
1603 case VM_FRAME_MAGIC_METHOD:
1604 RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0);
1605 EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->cfp->self, 0, 0, Qnil);
1606 break;
1607 case VM_FRAME_MAGIC_BLOCK:
1608 case VM_FRAME_MAGIC_LAMBDA:
1609 if (VM_FRAME_TYPE_BMETHOD_P(th->cfp)) {
1610 EXEC_EVENT_HOOK(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
1611 EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->cfp->self, th->cfp->me->called_id, th->cfp->me->klass, Qnil);
1612 }
1613 else {
1614 EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
1615 }
1616 break;
1617 case VM_FRAME_MAGIC_CLASS:
1618 EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_END, th->cfp->self, 0, 0, Qnil);
1619 break;
1620 }
1621
1622 if (VM_FRAME_TYPE_FINISH_P(th->cfp)) {
1623 vm_pop_frame(th);
1624 th->errinfo = err;
1625 TH_POP_TAG2();
1626 JUMP_TAG(state);
1627 }
1628 else {
1629 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
1630 goto exception_handler;
1631 }
1632 }
1633 }
1634 finish_vme:
1635 TH_POP_TAG();
1636 return result;
1637 }
1638
1639 /* misc */
1640
1641 VALUE
1642 rb_iseq_eval(VALUE iseqval)
1643 {
1644 rb_thread_t *th = GET_THREAD();
1645 VALUE val;
1646
1647 vm_set_top_stack(th, iseqval);
1648
1649 val = vm_exec(th);
1650 RB_GC_GUARD(iseqval); /* prohibit tail call optimization */
1651 return val;
1652 }
1653
1654 VALUE
1655 rb_iseq_eval_main(VALUE iseqval)
1656 {
1657 rb_thread_t *th = GET_THREAD();
1658 VALUE val;
1659
1660 vm_set_main_stack(th, iseqval);
1661
1662 val = vm_exec(th);
1663 RB_GC_GUARD(iseqval); /* prohibit tail call optimization */
1664 return val;
1665 }
1666
1667 int
1668 rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, VALUE *klassp)
1669 {
1670 rb_iseq_t *iseq = cfp->iseq;
1671 if (!iseq && cfp->me) {
1672 if (idp) *idp = cfp->me->def->original_id;
1673 if (klassp) *klassp = cfp->me->klass;
1674 return 1;
1675 }
1676 while (iseq) {
1677 if (RUBY_VM_IFUNC_P(iseq)) {
1678 if (idp) *idp = idIFUNC;
1679 if (klassp) *klassp = 0;
1680 return 1;
1681 }
1682 if (iseq->defined_method_id) {
1683 if (idp) *idp = iseq->defined_method_id;
1684 if (klassp) *klassp = iseq->klass;
1685 return 1;
1686 }
1687 if (iseq->local_iseq == iseq) {
1688 break;
1689 }
1690 iseq = iseq->parent_iseq;
1691 }
1692 return 0;
1693 }
1694
1695 int
1696 rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp)
1697 {
1698 return rb_vm_control_frame_id_and_class(th->cfp, idp, klassp);
1699 }
1700
1701 int
1702 rb_frame_method_id_and_class(ID *idp, VALUE *klassp)
1703 {
1704 return rb_thread_method_id_and_class(GET_THREAD(), idp, klassp);
1705 }
1706
1707 VALUE
1708 rb_thread_current_status(const rb_thread_t *th)
1709 {
1710 const rb_control_frame_t *cfp = th->cfp;
1711 VALUE str = Qnil;
1712
1713 if (cfp->iseq != 0) {
1714 if (cfp->pc != 0) {
1715 rb_iseq_t *iseq = cfp->iseq;
1716 int line_no = rb_vm_get_sourceline(cfp);
1717 char *file = RSTRING_PTR(iseq->location.path);
1718 str = rb_sprintf("%s:%d:in `%s'",
1719 file, line_no, RSTRING_PTR(iseq->location.label));
1720 }
1721 }
1722 else if (cfp->me->def->original_id) {
1723 str = rb_sprintf("`%s#%s' (cfunc)",
1724 rb_class2name(cfp->me->klass),
1725 rb_id2name(cfp->me->def->original_id));
1726 }
1727
1728 return str;
1729 }
1730
1731 VALUE
1732 rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
1733 const rb_block_t *blockptr, VALUE filename)
1734 {
1735 rb_thread_t *th = GET_THREAD();
1736 const rb_control_frame_t *reg_cfp = th->cfp;
1737 volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
1738 VALUE val;
1739
1740 vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
1741 recv, CLASS_OF(recv), VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1, 0, 0);
1742
1743 val = (*func)(arg);
1744
1745 vm_pop_frame(th);
1746 return val;
1747 }
1748
1749 /* vm */
1750
1751 static int
1752 vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t dummy)
1753 {
1754 VALUE thval = (VALUE)key;
1755 rb_gc_mark(thval);
1756 return ST_CONTINUE;
1757 }
1758
1759 void rb_vm_trace_mark_event_hooks(rb_hook_list_t *hooks);
1760
1761 void
1762 rb_vm_mark(void *ptr)
1763 {
1764 int i;
1765
1766 RUBY_MARK_ENTER("vm");
1767 RUBY_GC_INFO("-------------------------------------------------\n");
1768 if (ptr) {
1769 rb_vm_t *vm = ptr;
1770 if (vm->living_threads) {
1771 st_foreach(vm->living_threads, vm_mark_each_thread_func, 0);
1772 }
1773 RUBY_MARK_UNLESS_NULL(vm->thgroup_default);
1774 RUBY_MARK_UNLESS_NULL(vm->mark_object_ary);
1775 RUBY_MARK_UNLESS_NULL(vm->load_path);
1776 RUBY_MARK_UNLESS_NULL(vm->load_path_snapshot);
1777 RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache);
1778 RUBY_MARK_UNLESS_NULL(vm->expanded_load_path);
1779 RUBY_MARK_UNLESS_NULL(vm->loaded_features);
1780 RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot);
1781 RUBY_MARK_UNLESS_NULL(vm->top_self);
1782 RUBY_MARK_UNLESS_NULL(vm->coverages);
1783 RUBY_MARK_UNLESS_NULL(vm->defined_module_hash);
1784 rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count);
1785
1786 if (vm->loading_table) {
1787 rb_mark_tbl(vm->loading_table);
1788 }
1789
1790 rb_vm_trace_mark_event_hooks(&vm->event_hooks);
1791
1792 for (i = 0; i < RUBY_NSIG; i++) {
1793 if (vm->trap_list[i].cmd)
1794 rb_gc_mark(vm->trap_list[i].cmd);
1795 }
1796 if (vm->defined_strings) {
1797 rb_gc_mark_locations(vm->defined_strings, vm->defined_strings + DEFINED_EXPR);
1798 }
1799 }
1800
1801 RUBY_MARK_LEAVE("vm");
1802 }
1803
1804
1805 int
1806 rb_vm_add_root_module(ID id, VALUE module)
1807 {
1808 rb_vm_t *vm = GET_VM();
1809 if (vm->defined_module_hash) {
1810 rb_hash_aset(vm->defined_module_hash, ID2SYM(id), module);
1811 }
1812 return TRUE;
1813 }
1814
1815 #define vm_free 0
1816
1817 int
1818 ruby_vm_destruct(rb_vm_t *vm)
1819 {
1820 RUBY_FREE_ENTER("vm");
1821 if (vm) {
1822 rb_thread_t *th = vm->main_thread;
1823 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1824 struct rb_objspace *objspace = vm->objspace;
1825 #endif
1826 rb_gc_force_recycle(vm->self);
1827 vm->main_thread = 0;
1828 if (th) {
1829 rb_fiber_reset_root_local_storage(th->self);
1830 thread_free(th);
1831 }
1832 if (vm->living_threads) {
1833 st_free_table(vm->living_threads);
1834 vm->living_threads = 0;
1835 }
1836 ruby_vm_run_at_exit_hooks(vm);
1837 rb_vm_gvl_destroy(vm);
1838 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1839 if (objspace) {
1840 rb_objspace_free(objspace);
1841 }
1842 #endif
1843 /* after freeing objspace, you *can't* use ruby_xfree() */
1844 ruby_mimfree(vm);
1845 ruby_current_vm = 0;
1846 }
1847 RUBY_FREE_LEAVE("vm");
1848 return 0;
1849 }
1850
1851 static size_t
1852 vm_memsize(const void *ptr)
1853 {
1854 if (ptr) {
1855 const rb_vm_t *vmobj = ptr;
1856 size_t size = sizeof(rb_vm_t);
1857 if (vmobj->living_threads) {
1858 size += st_memsize(vmobj->living_threads);
1859 }
1860 if (vmobj->defined_strings) {
1861 size += DEFINED_EXPR * sizeof(VALUE);
1862 }
1863 return size;
1864 }
1865 else {
1866 return 0;
1867 }
1868 }
1869
1870 static const rb_data_type_t vm_data_type = {
1871 "VM",
1872 {rb_vm_mark, vm_free, vm_memsize,},
1873 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
1874 };
1875
1876
1877 static VALUE
1878 vm_default_params(void)
1879 {
1880 rb_vm_t *vm = GET_VM();
1881 VALUE result = rb_hash_new();
1882 #define SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), SIZET2NUM(vm->default_params.name));
1883 SET(thread_vm_stack_size);
1884 SET(thread_machine_stack_size);
1885 SET(fiber_vm_stack_size);
1886 SET(fiber_machine_stack_size);
1887 #undef SET
1888 rb_obj_freeze(result);
1889 return result;
1890 }
1891
1892 static size_t
1893 get_param(const char *name, size_t default_value, size_t min_value)
1894 {
1895 const char *envval;
1896 size_t result = default_value;
1897 if ((envval = getenv(name)) != 0) {
1898 long val = atol(envval);
1899 if (val < (long)min_value) {
1900 val = (long)min_value;
1901 }
1902 result = (size_t)(((val -1 + RUBY_VM_SIZE_ALIGN) / RUBY_VM_SIZE_ALIGN) * RUBY_VM_SIZE_ALIGN);
1903 }
1904 if (0) fprintf(stderr, "%s: %"PRIdSIZE"\n", name, result); /* debug print */
1905
1906 return result;
1907 }
1908
1909 static void
1910 check_machine_stack_size(size_t *sizep)
1911 {
1912 #ifdef PTHREAD_STACK_MIN
1913 size_t size = *sizep;
1914 #endif
1915
1916 #ifdef __SYMBIAN32__
1917 *sizep = 64 * 1024; /* 64KB: Let's be slightly more frugal on mobile platform */
1918 #endif
1919
1920 #ifdef PTHREAD_STACK_MIN
1921 if (size < PTHREAD_STACK_MIN) {
1922 *sizep = PTHREAD_STACK_MIN * 2;
1923 }
1924 #endif
1925 }
1926
1927 static void
1928 vm_default_params_setup(rb_vm_t *vm)
1929 {
1930 vm->default_params.thread_vm_stack_size =
1931 get_param("RUBY_THREAD_VM_STACK_SIZE",
1932 RUBY_VM_THREAD_VM_STACK_SIZE,
1933 RUBY_VM_THREAD_VM_STACK_SIZE_MIN);
1934
1935 vm->default_params.thread_machine_stack_size =
1936 get_param("RUBY_THREAD_MACHINE_STACK_SIZE",
1937 RUBY_VM_THREAD_MACHINE_STACK_SIZE,
1938 RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN);
1939
1940 vm->default_params.fiber_vm_stack_size =
1941 get_param("RUBY_FIBER_VM_STACK_SIZE",
1942 RUBY_VM_FIBER_VM_STACK_SIZE,
1943 RUBY_VM_FIBER_VM_STACK_SIZE_MIN);
1944
1945 vm->default_params.fiber_machine_stack_size =
1946 get_param("RUBY_FIBER_MACHINE_STACK_SIZE",
1947 RUBY_VM_FIBER_MACHINE_STACK_SIZE,
1948 RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN);
1949
1950 /* environment dependent check */
1951 check_machine_stack_size(&vm->default_params.thread_machine_stack_size);
1952 check_machine_stack_size(&vm->default_params.fiber_machine_stack_size);
1953 }
1954
1955 static void
1956 vm_init2(rb_vm_t *vm)
1957 {
1958 MEMZERO(vm, rb_vm_t, 1);
1959 vm->src_encoding_index = -1;
1960 vm->at_exit.basic.flags = (T_ARRAY | RARRAY_EMBED_FLAG) & ~RARRAY_EMBED_LEN_MASK; /* len set 0 */
1961 rb_obj_hide((VALUE)&vm->at_exit);
1962
1963 vm_default_params_setup(vm);
1964 }
1965
1966 /* Thread */
1967
1968 #define USE_THREAD_DATA_RECYCLE 1
1969
1970 #if USE_THREAD_DATA_RECYCLE
1971 #define RECYCLE_MAX 64
1972 static VALUE *thread_recycle_stack_slot[RECYCLE_MAX];
1973 static int thread_recycle_stack_count = 0;
1974
1975 static VALUE *
1976 thread_recycle_stack(size_t size)
1977 {
1978 if (thread_recycle_stack_count) {
1979 /* TODO: check stack size if stack sizes are variable */
1980 return thread_recycle_stack_slot[--thread_recycle_stack_count];
1981 }
1982 else {
1983 return ALLOC_N(VALUE, size);
1984 }
1985 }
1986
1987 #else
1988 #define thread_recycle_stack(size) ALLOC_N(VALUE, (size))
1989 #endif
1990
1991 void
1992 rb_thread_recycle_stack_release(VALUE *stack)
1993 {
1994 #if USE_THREAD_DATA_RECYCLE
1995 if (thread_recycle_stack_count < RECYCLE_MAX) {
1996 thread_recycle_stack_slot[thread_recycle_stack_count++] = stack;
1997 return;
1998 }
1999 #endif
2000 ruby_xfree(stack);
2001 }
2002
2003 #ifdef USE_THREAD_RECYCLE
2004 static rb_thread_t *
2005 thread_recycle_struct(void)
2006 {
2007 void *p = ALLOC_N(rb_thread_t, 1);
2008 memset(p, 0, sizeof(rb_thread_t));
2009 return p;
2010 }
2011 #endif
2012
2013 void
2014 rb_thread_mark(void *ptr)
2015 {
2016 rb_thread_t *th = NULL;
2017 RUBY_MARK_ENTER("thread");
2018 if (ptr) {
2019 th = ptr;
2020 if (th->stack) {
2021 VALUE *p = th->stack;
2022 VALUE *sp = th->cfp->sp;
2023 rb_control_frame_t *cfp = th->cfp;
2024 rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);
2025
2026 while (p < sp) {
2027 rb_gc_mark(*p++);
2028 }
2029 rb_gc_mark_locations(p, p + th->mark_stack_len);
2030
2031 while (cfp != limit_cfp) {
2032 rb_iseq_t *iseq = cfp->iseq;
2033 rb_gc_mark(cfp->proc);
2034 rb_gc_mark(cfp->self);
2035 rb_gc_mark(cfp->klass);
2036 if (iseq) {
2037 rb_gc_mark(RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq->self : (VALUE)iseq);
2038 }
2039 if (cfp->me) {
2040 /* TODO: marking `me' can be more sophisticated way */
2041 ((rb_method_entry_t *)cfp->me)->mark = 1;
2042 rb_mark_method_entry(cfp->me);
2043 }
2044 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2045 }
2046 }
2047
2048 /* mark ruby objects */
2049 RUBY_MARK_UNLESS_NULL(th->first_proc);
2050 if (th->first_proc) RUBY_MARK_UNLESS_NULL(th->first_args);
2051
2052 RUBY_MARK_UNLESS_NULL(th->thgroup);
2053 RUBY_MARK_UNLESS_NULL(th->value);
2054 RUBY_MARK_UNLESS_NULL(th->errinfo);
2055 RUBY_MARK_UNLESS_NULL(th->pending_interrupt_queue);
2056 RUBY_MARK_UNLESS_NULL(th->pending_interrupt_mask_stack);
2057 RUBY_MARK_UNLESS_NULL(th->root_svar);
2058 RUBY_MARK_UNLESS_NULL(th->top_self);
2059 RUBY_MARK_UNLESS_NULL(th->top_wrapper);
2060 RUBY_MARK_UNLESS_NULL(th->fiber);
2061 RUBY_MARK_UNLESS_NULL(th->root_fiber);
2062 RUBY_MARK_UNLESS_NULL(th->stat_insn_usage);
2063 RUBY_MARK_UNLESS_NULL(th->last_status);
2064
2065 RUBY_MARK_UNLESS_NULL(th->locking_mutex);
2066
2067 rb_mark_tbl(th->local_storage);
2068
2069 if (GET_THREAD() != th && th->machine.stack_start && th->machine.stack_end) {
2070 rb_gc_mark_machine_stack(th);
2071 rb_gc_mark_locations((VALUE *)&th->machine.regs,
2072 (VALUE *)(&th->machine.regs) +
2073 sizeof(th->machine.regs) / sizeof(VALUE));
2074 }
2075
2076 rb_vm_trace_mark_event_hooks(&th->event_hooks);
2077 }
2078
2079 RUBY_MARK_LEAVE("thread");
2080 }
2081
2082 static void
2083 thread_free(void *ptr)
2084 {
2085 rb_thread_t *th;
2086 RUBY_FREE_ENTER("thread");
2087
2088 if (ptr) {
2089 th = ptr;
2090
2091 if (!th->root_fiber) {
2092 RUBY_FREE_UNLESS_NULL(th->stack);
2093 }
2094
2095 if (th->locking_mutex != Qfalse) {
2096 rb_bug("thread_free: locking_mutex must be NULL (%p:%p)", (void *)th, (void *)th->locking_mutex);
2097 }
2098 if (th->keeping_mutexes != NULL) {
2099 rb_bug("thread_free: keeping_mutexes must be NULL (%p:%p)", (void *)th, (void *)th->keeping_mutexes);
2100 }
2101
2102 if (th->local_storage) {
2103 st_free_table(th->local_storage);
2104 }
2105
2106 if (th->vm && th->vm->main_thread == th) {
2107 RUBY_GC_INFO("main thread\n");
2108 }
2109 else {
2110 #ifdef USE_SIGALTSTACK
2111 if (th->altstack) {
2112 free(th->altstack);
2113 }
2114 #endif
2115 ruby_xfree(ptr);
2116 }
2117 if (ruby_current_thread == th)
2118 ruby_current_thread = NULL;
2119 }
2120 RUBY_FREE_LEAVE("thread");
2121 }
2122
2123 static size_t
2124 thread_memsize(const void *ptr)
2125 {
2126 if (ptr) {
2127 const rb_thread_t *th = ptr;
2128 size_t size = sizeof(rb_thread_t);
2129
2130 if (!th->root_fiber) {
2131 size += th->stack_size * sizeof(VALUE);
2132 }
2133 if (th->local_storage) {
2134 size += st_memsize(th->local_storage);
2135 }
2136 return size;
2137 }
2138 else {
2139 return 0;
2140 }
2141 }
2142
2143 #define thread_data_type ruby_threadptr_data_type
2144 const rb_data_type_t ruby_threadptr_data_type = {
2145 "VM/thread",
2146 {
2147 rb_thread_mark,
2148 thread_free,
2149 thread_memsize,
2150 },
2151 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
2152 };
2153
2154 VALUE
2155 rb_obj_is_thread(VALUE obj)
2156 {
2157 if (rb_typeddata_is_kind_of(obj, &thread_data_type)) {
2158 return Qtrue;
2159 }
2160 else {
2161 return Qfalse;
2162 }
2163 }
2164
2165 static VALUE
2166 thread_alloc(VALUE klass)
2167 {
2168 VALUE volatile obj;
2169 #ifdef USE_THREAD_RECYCLE
2170 rb_thread_t *th = thread_recycle_struct();
2171 obj = TypedData_Wrap_Struct(klass, &thread_data_type, th);
2172 #else
2173 rb_thread_t *th;
2174 obj = TypedData_Make_Struct(klass, rb_thread_t, &thread_data_type, th);
2175 #endif
2176 return obj;
2177 }
2178
2179 static void
2180 th_init(rb_thread_t *th, VALUE self)
2181 {
2182 th->self = self;
2183
2184 /* allocate thread stack */
2185 #ifdef USE_SIGALTSTACK
2186 /* altstack of main thread is reallocated in another place */
2187 th->altstack = malloc(rb_sigaltstack_size());
2188 #endif
2189 /* th->stack_size is word number.
2190 * th->vm->default_params.thread_vm_stack_size is byte size.
2191 */
2192 th->stack_size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE);
2193 th->stack = thread_recycle_stack(th->stack_size);
2194
2195 th->cfp = (void *)(th->stack + th->stack_size);
2196
2197 vm_push_frame(th, 0 /* dummy iseq */, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
2198 Qnil /* dummy self */, Qnil /* dummy klass */, VM_ENVVAL_BLOCK_PTR(0), 0 /* dummy pc */, th->stack, 1, 0, 0);
2199
2200 th->status = THREAD_RUNNABLE;
2201 th->errinfo = Qnil;
2202 th->last_status = Qnil;
2203 th->waiting_fd = -1;
2204 th->root_svar = Qnil;
2205
2206 #if OPT_CALL_THREADED_CODE
2207 th->retval = Qundef;
2208 #endif
2209 }
2210
2211 static VALUE
2212 ruby_thread_init(VALUE self)
2213 {
2214 rb_thread_t *th;
2215 rb_vm_t *vm = GET_THREAD()->vm;
2216 GetThreadPtr(self, th);
2217
2218 th->vm = vm;
2219 th_init(th, self);
2220 rb_ivar_set(self, rb_intern("locals"), rb_hash_new());
2221
2222 th->top_wrapper = 0;
2223 th->top_self = rb_vm_top_self();
2224 th->root_svar = Qnil;
2225 return self;
2226 }
2227
2228 VALUE
2229 rb_thread_alloc(VALUE klass)
2230 {
2231 VALUE self = thread_alloc(klass);
2232 ruby_thread_init(self);
2233 return self;
2234 }
2235
2236 static void
2237 vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
2238 rb_num_t is_singleton, NODE *cref)
2239 {
2240 VALUE klass = cref->nd_clss;
2241 int noex = (int)cref->nd_visi;
2242 rb_iseq_t *miseq;
2243 GetISeqPtr(iseqval, miseq);
2244
2245 if (miseq->klass) {
2246 RB_GC_GUARD(iseqval) = rb_iseq_clone(iseqval, 0);
2247 GetISeqPtr(iseqval, miseq);
2248 }
2249
2250 if (NIL_P(klass)) {
2251 rb_raise(rb_eTypeError, "no class/module to add method");
2252 }
2253
2254 if (is_singleton) {
2255 klass = rb_singleton_class(obj); /* class and frozen checked in this API */
2256 noex = NOEX_PUBLIC;
2257 }
2258
2259 /* dup */
2260 COPY_CREF(miseq->cref_stack, cref);
2261 miseq->cref_stack->nd_visi = NOEX_PUBLIC;
2262 RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
2263 miseq->defined_method_id = id;
2264 rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
2265
2266 if (!is_singleton && noex == NOEX_MODFUNC) {
2267 klass = rb_singleton_class(klass);
2268 rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, NOEX_PUBLIC);
2269 }
2270 }
2271
2272 #define REWIND_CFP(expr) do { \
2273 rb_thread_t *th__ = GET_THREAD(); \
2274 th__->cfp++; expr; th__->cfp--; \
2275 } while (0)
2276
2277 static VALUE
2278 m_core_define_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
2279 {
2280 REWIND_CFP({
2281 vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 0, rb_vm_cref());
2282 });
2283 return sym;
2284 }
2285
2286 static VALUE
2287 m_core_define_singleton_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
2288 {
2289 REWIND_CFP({
2290 vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 1, rb_vm_cref());
2291 });
2292 return sym;
2293 }
2294
2295 static VALUE
2296 m_core_set_method_alias(VALUE self, VALUE cbase, VALUE sym1, VALUE sym2)
2297 {
2298 REWIND_CFP({
2299 rb_alias(cbase, SYM2ID(sym1), SYM2ID(sym2));
2300 });
2301 return Qnil;
2302 }
2303
2304 static VALUE
2305 m_core_set_variable_alias(VALUE self, VALUE sym1, VALUE sym2)
2306 {
2307 REWIND_CFP({
2308 rb_alias_variable(SYM2ID(sym1), SYM2ID(sym2));
2309 });
2310 return Qnil;
2311 }
2312
2313 static VALUE
2314 m_core_undef_method(VALUE self, VALUE cbase, VALUE sym)
2315 {
2316 REWIND_CFP({
2317 rb_undef(cbase, SYM2ID(sym));
2318 rb_clear_method_cache_by_class(self);
2319 });
2320 return Qnil;
2321 }
2322
2323 static VALUE
2324 m_core_set_postexe(VALUE self)
2325 {
2326 rb_set_end_proc(rb_call_end_proc, rb_block_proc());
2327 return Qnil;
2328 }
2329
2330 static VALUE core_hash_merge_ary(VALUE hash, VALUE ary);
2331 static VALUE core_hash_from_ary(VALUE ary);
2332 static VALUE core_hash_merge_kwd(int argc, VALUE *argv);
2333
2334 static VALUE
2335 core_hash_merge(VALUE hash, long argc, const VALUE *argv)
2336 {
2337 long i;
2338
2339 assert(argc % 2 == 0);
2340 for (i=0; i<argc; i+=2) {
2341 rb_hash_aset(hash, argv[i], argv[i+1]);
2342 }
2343 return hash;
2344 }
2345
2346 static VALUE
2347 m_core_hash_from_ary(VALUE self, VALUE ary)
2348 {
2349 VALUE hash;
2350 REWIND_CFP(hash = core_hash_from_ary(ary));
2351 return hash;
2352 }
2353
2354 static VALUE
2355 core_hash_from_ary(VALUE ary)
2356 {
2357 VALUE hash = rb_hash_new();
2358
2359 if (RUBY_DTRACE_HASH_CREATE_ENABLED()) {
2360 RUBY_DTRACE_HASH_CREATE(RARRAY_LEN(ary), rb_sourcefile(), rb_sourceline());
2361 }
2362
2363 return core_hash_merge_ary(hash, ary);
2364 }
2365
2366 static VALUE
2367 m_core_hash_merge_ary(VALUE self, VALUE hash, VALUE ary)
2368 {
2369 REWIND_CFP(core_hash_merge_ary(hash, ary));
2370 return hash;
2371 }
2372
2373 static VALUE
2374 core_hash_merge_ary(VALUE hash, VALUE ary)
2375 {
2376 core_hash_merge(hash, RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
2377 return hash;
2378 }
2379
2380 static VALUE
2381 m_core_hash_merge_ptr(int argc, VALUE *argv, VALUE recv)
2382 {
2383 VALUE hash = argv[0];
2384
2385 REWIND_CFP(core_hash_merge(hash, argc-1, argv+1));
2386
2387 return hash;
2388 }
2389
2390 static int
2391 kwmerge_ii(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
2392 {
2393 if (existing) return ST_STOP;
2394 *value = arg;
2395 return ST_CONTINUE;
2396 }
2397
2398 static int
2399 kwmerge_i(VALUE key, VALUE value, VALUE hash)
2400 {
2401 if (!SYMBOL_P(key)) Check_Type(key, T_SYMBOL);
2402 if (st_update(RHASH_TBL_RAW(hash), key, kwmerge_ii, (st_data_t)value) == 0) { /* !existing */
2403 RB_OBJ_WRITTEN(hash, Qundef, value);
2404 }
2405 return ST_CONTINUE;
2406 }
2407
2408 static int
2409 kwcheck_i(VALUE key, VALUE value, VALUE hash)
2410 {
2411 if (!SYMBOL_P(key)) Check_Type(key, T_SYMBOL);
2412 return ST_CONTINUE;
2413 }
2414
2415 static VALUE
2416 m_core_hash_merge_kwd(int argc, VALUE *argv, VALUE recv)
2417 {
2418 VALUE hash;
2419 REWIND_CFP(hash = core_hash_merge_kwd(argc, argv));
2420 return hash;
2421 }
2422
2423 static VALUE
2424 core_hash_merge_kwd(int argc, VALUE *argv)
2425 {
2426 VALUE hash, kw;
2427 rb_check_arity(argc, 1, 2);
2428 hash = argv[0];
2429 kw = argv[argc-1];
2430 kw = rb_convert_type(kw, T_HASH, "Hash", "to_hash");
2431 if (argc < 2) hash = kw;
2432 rb_hash_foreach(kw, argc < 2 ? kwcheck_i : kwmerge_i, hash);
2433 return hash;
2434 }
2435
2436 extern VALUE *rb_gc_stack_start;
2437 extern size_t rb_gc_stack_maxsize;
2438 #ifdef __ia64
2439 extern VALUE *rb_gc_register_stack_start;
2440 #endif
2441
2442 /* debug functions */
2443
2444 /* :nodoc: */
2445 static VALUE
2446 sdr(void)
2447 {
2448 rb_vm_bugreport();
2449 return Qnil;
2450 }
2451
2452 /* :nodoc: */
2453 static VALUE
2454 nsdr(void)
2455 {
2456 VALUE ary = rb_ary_new();
2457 #if HAVE_BACKTRACE
2458 #include <execinfo.h>
2459 #define MAX_NATIVE_TRACE 1024
2460 static void *trace[MAX_NATIVE_TRACE];
2461 int n = backtrace(trace, MAX_NATIVE_TRACE);
2462 char **syms = backtrace_symbols(trace, n);
2463 int i;
2464
2465 if (syms == 0) {
2466 rb_memerror();
2467 }
2468
2469 for (i=0; i<n; i++) {
2470 rb_ary_push(ary, rb_str_new2(syms[i]));
2471 }
2472 free(syms); /* OK */
2473 #endif
2474 return ary;
2475 }
2476
2477 #if VM_COLLECT_USAGE_DETAILS
2478 static VALUE usage_analysis_insn_stop(VALUE self);
2479 static VALUE usage_analysis_operand_stop(VALUE self);
2480 static VALUE usage_analysis_register_stop(VALUE self);
2481 #endif
2482
2483 void
2484 Init_VM(void)
2485 {
2486 VALUE opts;
2487 VALUE klass;
2488 VALUE fcore;
2489
2490 /* ::RubyVM */
2491 rb_cRubyVM = rb_define_class("RubyVM", rb_cObject);
2492 rb_undef_alloc_func(rb_cRubyVM);
2493 rb_undef_method(CLASS_OF(rb_cRubyVM), "new");
2494 rb_define_singleton_method(rb_cRubyVM, "stat", vm_stat, -1);
2495
2496 /* FrozenCore (hidden) */
2497 fcore = rb_class_new(rb_cBasicObject);
2498 RBASIC(fcore)->flags = T_ICLASS;
2499 klass = rb_singleton_class(fcore);
2500 rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3);
2501 rb_define_method_id(klass, id_core_set_variable_alias, m_core_set_variable_alias, 2);
2502 rb_define_method_id(klass, id_core_undef_method, m_core_undef_method, 2);
2503 rb_define_method_id(klass, id_core_define_method, m_core_define_method, 3);
2504 rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
2505 rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 0);
2506 rb_define_method_id(klass, id_core_hash_from_ary, m_core_hash_from_ary, 1);
2507 rb_define_method_id(klass, id_core_hash_merge_ary, m_core_hash_merge_ary, 2);
2508 rb_define_method_id(klass, id_core_hash_merge_ptr, m_core_hash_merge_ptr, -1);
2509 rb_define_method_id(klass, id_core_hash_merge_kwd, m_core_hash_merge_kwd, -1);
2510 rb_define_method_id(klass, idProc, rb_block_proc, 0);
2511 rb_define_method_id(klass, idLambda, rb_block_lambda, 0);
2512 rb_obj_freeze(fcore);
2513 RBASIC_CLEAR_CLASS(klass);
2514 RCLASS_SET_SUPER(klass, 0);
2515 rb_obj_freeze(klass);
2516 rb_gc_register_mark_object(fcore);
2517 rb_mRubyVMFrozenCore = fcore;
2518
2519 /* ::RubyVM::Env */
2520 rb_cEnv = rb_define_class_under(rb_cRubyVM, "Env", rb_cObject);
2521 rb_undef_alloc_func(rb_cEnv);
2522 rb_undef_method(CLASS_OF(rb_cEnv), "new");
2523
2524 /*
2525 * Document-class: Thread
2526 *
2527 * Threads are the Ruby implementation for a concurrent programming model.
2528 *
2529 * Programs that require multiple threads of execution are a perfect
2530 * candidate for Ruby's Thread class.
2531 *
2532 * For example, we can create a new thread separate from the main thread's
2533 * execution using ::new.
2534 *
2535 * thr = Thread.new { puts "Whats the big deal" }
2536 *
2537 * Then we are able to pause the execution of the main thread and allow
2538 * our new thread to finish, using #join:
2539 *
2540 * thr.join #=> "Whats the big deal"
2541 *
2542 * If we don't call +thr.join+ before the main thread terminates, then all
2543 * other threads including +thr+ will be killed.
2544 *
2545 * Alternatively, you can use an array for handling multiple threads at
2546 * once, like in the following example:
2547 *
2548 * threads = []
2549 * threads << Thread.new { puts "Whats the big deal" }
2550 * threads << Thread.new { 3.times { puts "Threads are fun!" } }
2551 *
2552 * After creating a few threads we wait for them all to finish
2553 * consecutively.
2554 *
2555 * threads.each { |thr| thr.join }
2556 *
2557 * === Thread initialization
2558 *
2559 * In order to create new threads, Ruby provides ::new, ::start, and
2560 * ::fork. A block must be provided with each of these methods, otherwise
2561 * a ThreadError will be raised.
2562 *
2563 * When subclassing the Thread class, the +initialize+ method of your
2564 * subclass will be ignored by ::start and ::fork. Otherwise, be sure to
2565 * call super in your +initialize+ method.
2566 *
2567 * === Thread termination
2568 *
2569 * For terminating threads, Ruby provides a variety of ways to do this.
2570 *
2571 * The class method ::kill, is meant to exit a given thread:
2572 *
2573 * thr = Thread.new { ... }
2574 * Thread.kill(thr) # sends exit() to thr
2575 *
2576 * Alternatively, you can use the instance method #exit, or any of its
2577 * aliases #kill or #terminate.
2578 *
2579 * thr.exit
2580 *
2581 * === Thread status
2582 *
2583 * Ruby provides a few instance methods for querying the state of a given
2584 * thread. To get a string with the current thread's state use #status
2585 *
2586 * thr = Thread.new { sleep }
2587 * thr.status # => "sleep"
2588 * thr.exit
2589 * thr.status # => false
2590 *
2591 * You can also use #alive? to tell if the thread is running or sleeping,
2592 * and #stop? if the thread is dead or sleeping.
2593 *
2594 * === Thread variables and scope
2595 *
2596 * Since threads are created with blocks, the same rules apply to other
2597 * Ruby blocks for variable scope. Any local variables created within this
2598 * block are accessible to only this thread.
2599 *
2600 * ==== Fiber-local vs. Thread-local
2601 *
2602 * Each fiber has its own bucket for Thread#[] storage. When you set a
2603 * new fiber-local it is only accessible within this Fiber. To illustrate:
2604 *
2605 * Thread.new {
2606 * Thread.current[:foo] = "bar"
2607 * Fiber.new {
2608 * p Thread.current[:foo] # => nil
2609 * }.resume
2610 * }.join
2611 *
2612 * This example uses #[] for getting and #[]= for setting fiber-locals,
2613 * you can also use #keys to list the fiber-locals for a given
2614 * thread and #key? to check if a fiber-local exists.
2615 *
2616 * When it comes to thread-locals, they are accessible within the entire
2617 * scope of the thread. Given the following example:
2618 *
2619 * Thread.new{
2620 * Thread.current.thread_variable_set(:foo, 1)
2621 * p Thread.current.thread_variable_get(:foo) # => 1
2622 * Fiber.new{
2623 * Thread.current.thread_variable_set(:foo, 2)
2624 * p Thread.current.thread_variable_get(:foo) # => 2
2625 * }.resume
2626 * p Thread.current.thread_variable_get(:foo) # => 2
2627 * }.join
2628 *
2629 * You can see that the thread-local +:foo+ carried over into the fiber
2630 * and was changed to +2+ by the end of the thread.
2631 *
2632 * This example makes use of #thread_variable_set to create new
2633 * thread-locals, and #thread_variable_get to reference them.
2634 *
2635 * There is also #thread_variables to list all thread-locals, and
2636 * #thread_variable? to check if a given thread-local exists.
2637 *
2638 * === Exception handling
2639 *
2640 * Any thread can raise an exception using the #raise instance method,
2641 * which operates similarly to Kernel#raise.
2642 *
2643 * However, it's important to note that an exception that occurs in any
2644 * thread except the main thread depends on #abort_on_exception. This
2645 * option is +false+ by default, meaning that any unhandled exception will
2646 * cause the thread to terminate silently when waited on by either #join
2647 * or #value. You can change this default by either #abort_on_exception=
2648 * +true+ or setting $DEBUG to +true+.
2649 *
2650 * With the addition of the class method ::handle_interrupt, you can now
2651 * handle exceptions asynchronously with threads.
2652 *
2653 * === Scheduling
2654 *
2655 * Ruby provides a few ways to support scheduling threads in your program.
2656 *
2657 * The first way is by using the class method ::stop, to put the current
2658 * running thread to sleep and schedule the execution of another thread.
2659 *
2660 * Once a thread is asleep, you can use the instance method #wakeup to
2661 * mark your thread as eligible for scheduling.
2662 *
2663 * You can also try ::pass, which attempts to pass execution to another
2664 * thread but is dependent on the OS whether a running thread will switch
2665 * or not. The same goes for #priority, which lets you hint to the thread
2666 * scheduler which threads you want to take precedence when passing
2667 * execution. This method is also dependent on the OS and may be ignored
2668 * on some platforms.
2669 *
2670 */
2671 rb_cThread = rb_define_class("Thread", rb_cObject);
2672 rb_undef_alloc_func(rb_cThread);
2673
2674 #if VM_COLLECT_USAGE_DETAILS
2675 /* ::RubyVM::USAGE_ANALYSIS_* */
2676 #define define_usage_analysis_hash(name) /* shut up rdoc -C */ \
2677 rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_"#name, rb_hash_new())
2678 define_usage_analysis_hash("INSN");
2679 define_usage_analysis_hash("REGS");
2680 define_usage_analysis_hash("INSN_BIGRAM");
2681
2682 rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_INSN_STOP", usage_analysis_insn_stop, 0);
2683 rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_OPERAND_STOP", usage_analysis_operand_stop, 0);
2684 rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_REGISTER_STOP", usage_analysis_register_stop, 0);
2685 #endif
2686
2687 /* ::RubyVM::OPTS, which shows vm build options */
2688 rb_define_const(rb_cRubyVM, "OPTS", opts = rb_ary_new());
2689
2690 #if OPT_DIRECT_THREADED_CODE
2691 rb_ary_push(opts, rb_str_new2("direct threaded code"));
2692 #elif OPT_TOKEN_THREADED_CODE
2693 rb_ary_push(opts, rb_str_new2("token threaded code"));
2694 #elif OPT_CALL_THREADED_CODE
2695 rb_ary_push(opts, rb_str_new2("call threaded code"));
2696 #endif
2697
2698 #if OPT_STACK_CACHING
2699 rb_ary_push(opts, rb_str_new2("stack caching"));
2700 #endif
2701 #if OPT_OPERANDS_UNIFICATION
2702 rb_ary_push(opts, rb_str_new2("operands unification]"));
2703 #endif
2704 #if OPT_INSTRUCTIONS_UNIFICATION
2705 rb_ary_push(opts, rb_str_new2("instructions unification"));
2706 #endif
2707 #if OPT_INLINE_METHOD_CACHE
2708 rb_ary_push(opts, rb_str_new2("inline method cache"));
2709 #endif
2710 #if OPT_BLOCKINLINING
2711 rb_ary_push(opts, rb_str_new2("block inlining"));
2712 #endif
2713
2714 /* ::RubyVM::INSTRUCTION_NAMES */
2715 rb_define_const(rb_cRubyVM, "INSTRUCTION_NAMES", rb_insns_name_array());
2716
2717 /* ::RubyVM::DEFAULT_PARAMS
2718 * This constant variable shows VM's default parameters.
2719 * Note that changing these values does not affect VM execution.
2720 * Specification is not stable and you should not depend on this value.
2721 * Of course, this constant is MRI specific.
2722 */
2723 rb_define_const(rb_cRubyVM, "DEFAULT_PARAMS", vm_default_params());
2724
2725 /* debug functions ::RubyVM::SDR(), ::RubyVM::NSDR() */
2726 #if VMDEBUG
2727 rb_define_singleton_method(rb_cRubyVM, "SDR", sdr, 0);
2728 rb_define_singleton_method(rb_cRubyVM, "NSDR", nsdr, 0);
2729 #else
2730 (void)sdr;
2731 (void)nsdr;
2732 #endif
2733
2734 /* VM bootstrap: phase 2 */
2735 {
2736 rb_vm_t *vm = ruby_current_vm;
2737 rb_thread_t *th = GET_THREAD();
2738 VALUE filename = rb_str_new2("<main>");
2739 volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
2740 volatile VALUE th_self;
2741 rb_iseq_t *iseq;
2742
2743 /* create vm object */
2744 vm->self = TypedData_Wrap_Struct(rb_cRubyVM, &vm_data_type, vm);
2745
2746 /* create main thread */
2747 th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th);
2748 rb_iv_set(th_self, "locals", rb_hash_new());
2749 vm->main_thread = th;
2750 vm->running_thread = th;
2751 th->vm = vm;
2752 th->top_wrapper = 0;
2753 th->top_self = rb_vm_top_self();
2754 rb_thread_set_current(th);
2755
2756 vm->living_threads = st_init_numtable();
2757 st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id);
2758
2759 rb_gc_register_mark_object(iseqval);
2760 GetISeqPtr(iseqval, iseq);
2761 th->cfp->iseq = iseq;
2762 th->cfp->pc = iseq->iseq_encoded;
2763 th->cfp->self = th->top_self;
2764 th->cfp->klass = Qnil;
2765
2766 /*
2767 * The Binding of the top level scope
2768 */
2769 rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new());
2770 }
2771 vm_init_redefined_flag();
2772
2773 /* vm_backtrace.c */
2774 Init_vm_backtrace();
2775 VM_PROFILE_ATEXIT();
2776 }
2777
2778 void
2779 rb_vm_set_progname(VALUE filename)
2780 {
2781 rb_thread_t *th = GET_VM()->main_thread;
2782 rb_control_frame_t *cfp = (void *)(th->stack + th->stack_size);
2783 --cfp;
2784 RB_OBJ_WRITE(cfp->iseq->self, &cfp->iseq->location.path, filename);
2785 }
2786
2787 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2788 struct rb_objspace *rb_objspace_alloc(void);
2789 #endif
2790
2791 void
2792 Init_BareVM(void)
2793 {
2794 /* VM bootstrap: phase 1 */
2795 rb_vm_t * vm = ruby_mimmalloc(sizeof(*vm));
2796 rb_thread_t * th = ruby_mimmalloc(sizeof(*th));
2797 if (!vm || !th) {
2798 fprintf(stderr, "[FATAL] failed to allocate memory\n");
2799 exit(EXIT_FAILURE);
2800 }
2801 MEMZERO(th, rb_thread_t, 1);
2802 rb_thread_set_current_raw(th);
2803
2804 vm_init2(vm);
2805 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2806 vm->objspace = rb_objspace_alloc();
2807 #endif
2808 ruby_current_vm = vm;
2809
2810 Init_native_thread();
2811 th->vm = vm;
2812 th_init(th, 0);
2813 ruby_thread_init_stack(th);
2814 vm->defined_module_hash = rb_hash_new();
2815 }
2816
2817 /* top self */
2818
2819 static VALUE
2820 main_to_s(VALUE obj)
2821 {
2822 return rb_str_new2("main");
2823 }
2824
2825 VALUE
2826 rb_vm_top_self(void)
2827 {
2828 return GET_VM()->top_self;
2829 }
2830
2831 void
2832 Init_top_self(void)
2833 {
2834 rb_vm_t *vm = GET_VM();
2835
2836 vm->top_self = rb_obj_alloc(rb_cObject);
2837 rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0);
2838 rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s");
2839
2840 /* initialize mark object array, hash */
2841 vm->mark_object_ary = rb_ary_tmp_new(1);
2842 }
2843
2844 VALUE *
2845 ruby_vm_verbose_ptr(rb_vm_t *vm)
2846 {
2847 return &vm->verbose;
2848 }
2849
2850 VALUE *
2851 ruby_vm_debug_ptr(rb_vm_t *vm)
2852 {
2853 return &vm->debug;
2854 }
2855
2856 VALUE *
2857 rb_ruby_verbose_ptr(void)
2858 {
2859 return ruby_vm_verbose_ptr(GET_VM());
2860 }
2861
2862 VALUE *
2863 rb_ruby_debug_ptr(void)
2864 {
2865 return ruby_vm_debug_ptr(GET_VM());
2866 }
2867
2868 /* iseq.c */
2869 VALUE rb_insn_operand_intern(rb_iseq_t *iseq,
2870 VALUE insn, int op_no, VALUE op,
2871 int len, size_t pos, VALUE *pnop, VALUE child);
2872
2873 #if VM_COLLECT_USAGE_DETAILS
2874
2875 #define HASH_ASET(h, k, v) rb_hash_aset((h), (st_data_t)(k), (st_data_t)(v))
2876
2877 /* uh = {
2878 * insn(Fixnum) => ihash(Hash)
2879 * }
2880 * ihash = {
2881 * -1(Fixnum) => count, # insn usage
2882 * 0(Fixnum) => ophash, # operand usage
2883 * }
2884 * ophash = {
2885 * val(interned string) => count(Fixnum)
2886 * }
2887 */
2888 static void
2889 vm_analysis_insn(int insn)
2890 {
2891 ID usage_hash;
2892 ID bigram_hash;
2893 static int prev_insn = -1;
2894
2895 VALUE uh;
2896 VALUE ihash;
2897 VALUE cv;
2898
2899 CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
2900 CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
2901 uh = rb_const_get(rb_cRubyVM, usage_hash);
2902 if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
2903 ihash = rb_hash_new();
2904 HASH_ASET(uh, INT2FIX(insn), ihash);
2905 }
2906 if ((cv = rb_hash_aref(ihash, INT2FIX(-1))) == Qnil) {
2907 cv = INT2FIX(0);
2908 }
2909 HASH_ASET(ihash, INT2FIX(-1), INT2FIX(FIX2INT(cv) + 1));
2910
2911 /* calc bigram */
2912 if (prev_insn != -1) {
2913 VALUE bi;
2914 VALUE ary[2];
2915 VALUE cv;
2916
2917 ary[0] = INT2FIX(prev_insn);
2918 ary[1] = INT2FIX(insn);
2919 bi = rb_ary_new4(2, &ary[0]);
2920
2921 uh = rb_const_get(rb_cRubyVM, bigram_hash);
2922 if ((cv = rb_hash_aref(uh, bi)) == Qnil) {
2923 cv = INT2FIX(0);
2924 }
2925 HASH_ASET(uh, bi, INT2FIX(FIX2INT(cv) + 1));
2926 }
2927 prev_insn = insn;
2928 }
2929
2930 static void
2931 vm_analysis_operand(int insn, int n, VALUE op)
2932 {
2933 ID usage_hash;
2934
2935 VALUE uh;
2936 VALUE ihash;
2937 VALUE ophash;
2938 VALUE valstr;
2939 VALUE cv;
2940
2941 CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
2942
2943 uh = rb_const_get(rb_cRubyVM, usage_hash);
2944 if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
2945 ihash = rb_hash_new();
2946 HASH_ASET(uh, INT2FIX(insn), ihash);
2947 }
2948 if ((ophash = rb_hash_aref(ihash, INT2FIX(n))) == Qnil) {
2949 ophash = rb_hash_new();
2950 HASH_ASET(ihash, INT2FIX(n), ophash);
2951 }
2952 /* intern */
2953 valstr = rb_insn_operand_intern(GET_THREAD()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
2954
2955 /* set count */
2956 if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) {
2957 cv = INT2FIX(0);
2958 }
2959 HASH_ASET(ophash, valstr, INT2FIX(FIX2INT(cv) + 1));
2960 }
2961
2962 static void
2963 vm_analysis_register(int reg, int isset)
2964 {
2965 ID usage_hash;
2966 VALUE uh;
2967 VALUE valstr;
2968 static const char regstrs[][5] = {
2969 "pc", /* 0 */
2970 "sp", /* 1 */
2971 "ep", /* 2 */
2972 "cfp", /* 3 */
2973 "self", /* 4 */
2974 "iseq", /* 5 */
2975 };
2976 static const char getsetstr[][4] = {
2977 "get",
2978 "set",
2979 };
2980 static VALUE syms[sizeof(regstrs) / sizeof(regstrs[0])][2];
2981
2982 VALUE cv;
2983
2984 CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
2985 if (syms[0] == 0) {
2986 char buff[0x10];
2987 int i;
2988
2989 for (i = 0; i < (int)(sizeof(regstrs) / sizeof(regstrs[0])); i++) {
2990 int j;
2991 for (j = 0; j < 2; j++) {
2992 snprintf(buff, 0x10, "%d %s %-4s", i, getsetstr[j], regstrs[i]);
2993 syms[i][j] = ID2SYM(rb_intern(buff));
2994 }
2995 }
2996 }
2997 valstr = syms[reg][isset];
2998
2999 uh = rb_const_get(rb_cRubyVM, usage_hash);
3000 if ((cv = rb_hash_aref(uh, valstr)) == Qnil) {
3001 cv = INT2FIX(0);
3002 }
3003 HASH_ASET(uh, valstr, INT2FIX(FIX2INT(cv) + 1));
3004 }
3005
3006 #undef HASH_ASET
3007
3008 void (*ruby_vm_collect_usage_func_insn)(int insn) = vm_analysis_insn;
3009 void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = vm_analysis_operand;
3010 void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = vm_analysis_register;
3011
3012 /* :nodoc: */
3013 static VALUE
3014 usage_analysis_insn_stop(VALUE self)
3015 {
3016 ruby_vm_collect_usage_func_insn = 0;
3017 return Qnil;
3018 }
3019
3020 /* :nodoc: */
3021 static VALUE
3022 usage_analysis_operand_stop(VALUE self)
3023 {
3024 ruby_vm_collect_usage_func_operand = 0;
3025 return Qnil;
3026 }
3027
3028 /* :nodoc: */
3029 static VALUE
3030 usage_analysis_register_stop(VALUE self)
3031 {
3032 ruby_vm_collect_usage_func_register = 0;
3033 return Qnil;
3034 }
3035
3036 #else
3037
3038 void (*ruby_vm_collect_usage_func_insn)(int insn) = NULL;
3039 void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = NULL;
3040 void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = NULL;
3041
3042 #endif
3043
3044 #if VM_COLLECT_USAGE_DETAILS
3045 /* @param insn instruction number */
3046 static void
3047 vm_collect_usage_insn(int insn)
3048 {
3049 if (RUBY_DTRACE_INSN_ENABLED()) {
3050 RUBY_DTRACE_INSN(rb_insns_name(insn));
3051 }
3052 if (ruby_vm_collect_usage_func_insn)
3053 (*ruby_vm_collect_usage_func_insn)(insn);
3054 }
3055
3056 /* @param insn instruction number
3057 * @param n n-th operand
3058 * @param op operand value
3059 */
3060 static void
3061 vm_collect_usage_operand(int insn, int n, VALUE op)
3062 {
3063 if (RUBY_DTRACE_INSN_OPERAND_ENABLED()) {
3064 VALUE valstr;
3065
3066 valstr = rb_insn_operand_intern(GET_THREAD()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
3067
3068 RUBY_DTRACE_INSN_OPERAND(RSTRING_PTR(valstr), rb_insns_name(insn));
3069 RB_GC_GUARD(valstr);
3070 }
3071 if (ruby_vm_collect_usage_func_operand)
3072 (*ruby_vm_collect_usage_func_operand)(insn, n, op);
3073 }
3074
3075 /* @param reg register id. see code of vm_analysis_register() */
3076 /* @param iseset 0: read, 1: write */
3077 static void
3078 vm_collect_usage_register(int reg, int isset)
3079 {
3080 if (ruby_vm_collect_usage_func_register)
3081 (*ruby_vm_collect_usage_func_register)(reg, isset);
3082 }
3083 #endif
3084
core_hash_merge_kwd
static VALUE core_hash_merge_kwd(int argc, VALUE *argv)
Definition: vm.c:2424
rb_cString
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:1583
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2236
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:607
rb_proc_t::is_from_method
int is_from_method
Definition: vm_core.h:706
RUBY_VM_THREAD_MACHINE_STACK_SIZE
#define RUBY_VM_THREAD_MACHINE_STACK_SIZE
Definition: vm_core.h:433
VM_FRAME_MAGIC_BLOCK
#define VM_FRAME_MAGIC_BLOCK
Definition: vm_core.h:760
rb_thread_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:531
RUBY_EVENT_B_RETURN
#define RUBY_EVENT_B_RETURN
Definition: ruby.h:1719
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:494
rb_eLocalJumpError
VALUE rb_eLocalJumpError
Definition: eval.c:27
NEXT_CLASS_SERIAL
#define NEXT_CLASS_SERIAL()
Definition: vm_insnhelper.h:263
m_core_set_postexe
static VALUE m_core_set_postexe(VALUE self)
Definition: vm.c:2324
rb_thread_struct::stack_end
VALUE * stack_end
Definition: vm_core.h:622
rb_env_t::env
VALUE * env
Definition: vm_core.h:714
core_hash_merge
static VALUE core_hash_merge(VALUE hash, long argc, const VALUE *argv)
Definition: vm.c:2335
rb_thread_struct::vm
rb_vm_t * vm
Definition: vm_core.h:526
ruby_vm_global_constant_state
static rb_serial_t ruby_vm_global_constant_state
Definition: vm.c:75
thread_free
static void thread_free(void *ptr)
Definition: vm.c:2083
rb_vm_struct::expanded_load_path
VALUE expanded_load_path
Definition: vm_core.h:375
rb_vm_cref
NODE * rb_vm_cref(void)
Definition: vm.c:1015
rb_env_t::prev_envval
VALUE prev_envval
Definition: vm_core.h:717
rb_proc_alloc
VALUE rb_proc_alloc(VALUE klass)
Definition: proc.c:87
rb_vm_bugreport
void rb_vm_bugreport(void)
Definition: vm_dump.c:713
rb_exc_new2
#define rb_exc_new2
Definition: intern.h:247
MOD
#define MOD(n, d)
Definition: date_core.c:150
rb_vm_check_redefinition_by_prepend
void rb_vm_check_redefinition_by_prepend(VALUE klass)
Definition: vm.c:1211
id_core_set_variable_alias
Definition: id.h:102
rb_ary_pop
VALUE rb_ary_pop(VALUE ary)
Definition: array.c:940
make_localjump_error
static VALUE make_localjump_error(const char *mesg, VALUE value, int reason)
Definition: vm.c:1062
rb_cFloat
RUBY_EXTERN VALUE rb_cFloat
Definition: ruby.h:1566
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
RUBY_EVENT_C_RETURN
#define RUBY_EVENT_C_RETURN
Definition: ruby.h:1713
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:327
rb_method_definition_struct::type
rb_method_type_t type
Definition: method.h:79
rb_vm_add_root_module
int rb_vm_add_root_module(ID id, VALUE module)
Definition: vm.c:1806
vm_memsize
static size_t vm_memsize(const void *ptr)
Definition: vm.c:1852
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1015
rb_vm_struct::at_exit
struct RArray at_exit
Definition: vm_core.h:414
rb_vm_get_binding_creatable_next_cfp
rb_control_frame_t * rb_vm_get_binding_creatable_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
Definition: vm.c:235
vm_exec.h
ruby_vm_const_missing_count
VALUE ruby_vm_const_missing_count
Definition: vm.c:102
TAG_NEXT
#define TAG_NEXT
Definition: eval_intern.h:190
vm_init2
static void vm_init2(rb_vm_t *vm)
Definition: vm.c:1956
rb_gc_mark_locations
#define rb_gc_mark_locations(start, end)
Definition: gc.c:3316
RUBY_VM_IFUNC_P
#define RUBY_VM_IFUNC_P(ptr)
Definition: vm_core.h:834
rb_vm_struct::running_thread
struct rb_thread_struct * running_thread
Definition: vm_core.h:355
vm_get_ruby_level_caller_cfp
static rb_control_frame_t * vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm.c:259
RUBY_DTRACE_METHOD_RETURN_HOOK
#define RUBY_DTRACE_METHOD_RETURN_HOOK(th, klass, id)
Definition: probes_helper.h:58
rb_iseq_new
VALUE rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent, enum iseq_type type)
Definition: iseq.c:413
rb_objspace_free
void rb_objspace_free(rb_objspace_t *objspace)
Definition: gc.c:890
rb_vm_get_sourceline
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:33
VM_ENVVAL_PREV_EP_PTR
#define VM_ENVVAL_PREV_EP_PTR(v)
Definition: vm_core.h:815
RUBY_EVENT_RETURN
#define RUBY_EVENT_RETURN
Definition: ruby.h:1711
st_table
Definition: st.h:69
VM_FRAME_FLAG_FINISH
#define VM_FRAME_FLAG_FINISH
Definition: vm_core.h:776
rb_vm_struct::cmd
VALUE cmd
Definition: vm_core.h:383
rb_thread_struct::local_storage
st_table * local_storage
Definition: vm_core.h:611
rb_id2str
VALUE rb_id2str(ID id)
Definition: ripper.c:17160
ST_STOP
Definition: st.h:100
m_core_hash_merge_ary
static VALUE m_core_hash_merge_ary(VALUE self, VALUE hash, VALUE ary)
Definition: vm.c:2367
rb_control_frame_struct::klass
VALUE klass
Definition: vm_core.h:451
VM_FRAME_TYPE_FINISH_P
#define VM_FRAME_TYPE_FINISH_P(cfp)
Definition: vm_core.h:778
VM_CF_PREV_EP
static VALUE * VM_CF_PREV_EP(rb_control_frame_t *cfp)
Definition: vm.c:46
iseq_catch_table_entry::end
unsigned long end
Definition: iseq.h:66
vm_rewrite_ep_in_errinfo
static void vm_rewrite_ep_in_errinfo(rb_thread_t *th)
Definition: vm.c:609
VM_FRAME_MAGIC_CFUNC
#define VM_FRAME_MAGIC_CFUNC
Definition: vm_core.h:763
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1214
iseq.h
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:519
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:1655
vm_insnhelper.h
vm_push_frame
static rb_control_frame_t * vm_push_frame(rb_thread_t *th, const rb_iseq_t *iseq, VALUE type, VALUE self, VALUE klass, VALUE specval, const VALUE *pc, VALUE *sp, int local_size, const rb_method_entry_t *me, size_t stack_max)
Definition: vm_insnhelper.c:34
RUBY_VM_PREVIOUS_CONTROL_FRAME
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:825
iseq_catch_table_entry::CATCH_TYPE_RETRY
Definition: iseq.h:59
GetProcPtr
#define GetProcPtr(obj, ptr)
Definition: vm_core.h:697
vm_yield
static VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
Definition: vm.c:853
ruby.h
rb_vm_struct::top_self
VALUE top_self
Definition: vm_core.h:371
RUBY_VM_NORMAL_ISEQ_P
#define RUBY_VM_NORMAL_ISEQ_P(ptr)
Definition: vm_core.h:835
SET_THROWOBJ_STATE
#define SET_THROWOBJ_STATE(obj, val)
Definition: eval_intern.h:202
kwcheck_i
static int kwcheck_i(VALUE key, VALUE value, VALUE hash)
Definition: vm.c:2409
RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
Definition: vm_core.h:439
rb_vm_mark
void rb_vm_mark(void *ptr)
Definition: vm.c:1762
FLOAT_REDEFINED_OP_FLAG
#define FLOAT_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:235
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:440
rb_env_t::block
rb_block_t block
Definition: vm_core.h:718
rb_vm_call_cfunc
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename)
Definition: vm.c:1732
rb_vm_pop_cfunc_frame
void rb_vm_pop_cfunc_frame(void)
Definition: vm.c:281
Qtrue
#define Qtrue
Definition: ruby.h:426
st_insert
int st_insert(st_table *, st_data_t, st_data_t)
env_memsize
static size_t env_memsize(const void *ptr)
Definition: vm.c:392
vm_mark_each_thread_func
static int vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t dummy)
Definition: vm.c:1752
rb_cHash
VALUE rb_cHash
Definition: hash.c:67
rb_block_struct::iseq
rb_iseq_t * iseq
Definition: vm_core.h:466
TAG_BREAK
#define TAG_BREAK
Definition: eval_intern.h:189
check_env
static int check_env(rb_env_t *const env)
Definition: vm.c:426
block_proc_is_lambda
static int block_proc_is_lambda(const VALUE procval)
Definition: vm_insnhelper.c:2067
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1027
m_core_undef_method
static VALUE m_core_undef_method(VALUE self, VALUE cbase, VALUE sym)
Definition: vm.c:2314
rb_fiber_reset_root_local_storage
void rb_fiber_reset_root_local_storage(VALUE thval)
Definition: cont.c:1502
rb_thread_struct::pending_interrupt_mask_stack
VALUE pending_interrupt_mask_stack
Definition: vm_core.h:583
GET_THROWOBJ_CATCH_POINT
#define GET_THROWOBJ_CATCH_POINT(obj)
Definition: eval_intern.h:206
rb_thread_struct::regs
jmp_buf regs
Definition: vm_core.h:629
probes.h
ST_CONTINUE
Definition: st.h:100
rb_insns_name_array
VALUE rb_insns_name_array(void)
Definition: compile.c:5607
id
const int id
Definition: nkf.c:209
eval_intern.h
rb_vm_struct::defined_strings
VALUE * defined_strings
Definition: vm_core.h:416
C
#define C(k)
rb_vm_cbase
VALUE rb_vm_cbase(void)
Definition: vm.c:1048
DIV
#define DIV(n, d)
Definition: date_core.c:149
rb_env_t::env_size
int env_size
Definition: vm_core.h:715
rb_block_struct
Definition: vm_core.h:462
ruby_mimfree
void ruby_mimfree(void *ptr)
Definition: gc.c:6267
rb_vm_struct::mark_object_ary
VALUE mark_object_ary
Definition: vm_core.h:366
VM_METHOD_TYPE_ISEQ
Definition: method.h:48
RUBY_EVENT_CALL
#define RUBY_EVENT_CALL
Definition: ruby.h:1710
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
rb_ruby_debug_ptr
VALUE * rb_ruby_debug_ptr(void)
Definition: vm.c:2863
RUBY_NSIG
#define RUBY_NSIG
Definition: vm_core.h:51
TH_JUMP_TAG
#define TH_JUMP_TAG(th, st)
Definition: eval_intern.h:171
rb_control_frame_struct::sp
VALUE * sp
Definition: vm_core.h:447
rb_check_arity
#define rb_check_arity
Definition: intern.h:296
ENV_IN_HEAP_P
#define ENV_IN_HEAP_P(th, env)
Definition: vm.c:345
id_core_undef_method
Definition: id.h:103
rb_thread_struct::waiting_fd
int waiting_fd
Definition: vm_core.h:539
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
st_free_table
void st_free_table(st_table *)
Definition: st.c:334
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:356
RUBY_VM_SIZE_ALIGN
#define RUBY_VM_SIZE_ALIGN
Definition: vm_core.h:429
rb_vm_struct::living_threads
st_table * living_threads
Definition: vm_core.h:357
rb_vm_struct::fiber_machine_stack_size
size_t fiber_machine_stack_size
Definition: vm_core.h:423
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:534
rb_backref_get
VALUE rb_backref_get(void)
Definition: vm.c:947
rb_vm_struct::verbose
VALUE verbose
Definition: vm_core.h:399
VM_ENVVAL_BLOCK_PTR
#define VM_ENVVAL_BLOCK_PTR(v)
Definition: vm_core.h:813
rb_vm_make_proc
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
Definition: vm.c:656
rb_iseq_struct::local_table_size
int local_table_size
Definition: vm_core.h:236
rb_iv_set
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:2609
rb_block_struct::self
VALUE self
Definition: vm_core.h:463
ruby_special_error_count
Definition: vm_core.h:331
NODE_SCOPE
Definition: node.h:23
VM_FRAME_MAGIC_METHOD
#define VM_FRAME_MAGIC_METHOD
Definition: vm_core.h:759
rb_iseq_struct::local_iseq
struct rb_iseq_struct * local_iseq
Definition: vm_core.h:297
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:676
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:532
NOEX_MODFUNC
Definition: method.h:32
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
rb_thread_alloc
VALUE rb_thread_alloc(VALUE klass)
Definition: vm.c:2229
vm_normal_frame
static rb_control_frame_t * vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm.c:907
VM_FRAME_TYPE
#define VM_FRAME_TYPE(cfp)
Definition: vm_core.h:772
lep_svar_set
static void lep_svar_set(rb_thread_t *th, VALUE *lep, rb_num_t key, VALUE val)
Definition: vm_insnhelper.c:197
RUBY_MARK_LEAVE
#define RUBY_MARK_LEAVE(msg)
Definition: gc.h:54
vm_yield_with_block
static VALUE vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, const rb_block_t *blockargptr)
Definition: vm.c:861
gc.h
rb_method_entry_struct::called_id
ID called_id
Definition: method.h:101
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2616
env_mark
static void env_mark(void *const ptr)
Definition: vm.c:350
VM_FRAME_MAGIC_IFUNC
#define VM_FRAME_MAGIC_IFUNC
Definition: vm_core.h:765
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:523
T_HASH
#define T_HASH
Definition: ruby.h:485
rb_iseq_struct::klass
const VALUE klass
Definition: vm_core.h:316
Init_VM
void Init_VM(void)
Definition: vm.c:2484
thread_recycle_stack_count
static int thread_recycle_stack_count
Definition: vm.c:1973
Init_vm_backtrace
void Init_vm_backtrace(void)
Definition: vm_backtrace.c:991
rb_thread_struct::thgroup
VALUE thgroup
Definition: vm_core.h:569
rb_vm_localjump_error
void rb_vm_localjump_error(const char *mesg, VALUE value, int reason)
Definition: vm.c:1094
rb_iseq_struct::stack_max
size_t stack_max
Definition: vm_core.h:289
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:992
rb_hook_list_struct
Definition: vm_core.h:342
SDR
#define SDR()
Definition: vm_core.h:853
rb_thread_struct::last_status
VALUE last_status
Definition: vm_core.h:534
rb_next_class_serial
rb_serial_t rb_next_class_serial(void)
Definition: vm.c:92
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:3604
rb_iseq_struct::defined_method_id
ID defined_method_id
Definition: vm_core.h:319
RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P
#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)
Definition: vm_core.h:831
RUBY_GC_INFO
#define RUBY_GC_INFO
Definition: gc.h:57
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
thread_recycle_stack_slot
static VALUE * thread_recycle_stack_slot[RECYCLE_MAX]
Definition: vm.c:1972
VM_FRAME_MAGIC_RESCUE
#define VM_FRAME_MAGIC_RESCUE
Definition: vm_core.h:768
vm_cfp_svar_get
static VALUE vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
Definition: vm.c:919
TAG_RAISE
#define TAG_RAISE
Definition: eval_intern.h:193
GetEnvPtr
#define GetEnvPtr(obj, ptr)
Definition: vm_core.h:710
st_update
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:867
id_core_hash_merge_ary
Definition: id.h:108
rb_sourcefilename
VALUE rb_sourcefilename(void)
Definition: vm.c:973
lep_svar_get
static VALUE lep_svar_get(rb_thread_t *th, VALUE *lep, rb_num_t key)
Definition: vm_insnhelper.c:174
VM_FRAME_FLAG_BMETHOD
#define VM_FRAME_FLAG_BMETHOD
Definition: vm_core.h:777
rb_vm_invoke_proc
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, const rb_block_t *blockptr)
Definition: vm.c:897
VM_CF_LEP
static VALUE * VM_CF_LEP(rb_control_frame_t *cfp)
Definition: vm.c:40
rb_objspace_alloc
struct rb_objspace * rb_objspace_alloc(void)
Definition: gc.c:873
rb_binding_t::env
VALUE env
Definition: vm_core.h:727
rb_cProc
RUBY_EXTERN VALUE rb_cProc
Definition: ruby.h:1576
vm_yield_setup_args
static int vm_yield_setup_args(rb_thread_t *const th, const rb_iseq_t *iseq, int argc, VALUE *argv, const rb_block_t *blockptr, int lambda)
Definition: vm_insnhelper.c:2300
rb_undef
void rb_undef(VALUE, ID)
Definition: vm_method.c:898
vm_data_type
static const rb_data_type_t vm_data_type
Definition: vm.c:1870
RUBY_VM_FIBER_VM_STACK_SIZE
#define RUBY_VM_FIBER_VM_STACK_SIZE
Definition: vm_core.h:436
rb_thread_struct
Definition: vm_core.h:524
env_alloc
static VALUE env_alloc(void)
Definition: vm.c:412
vm_default_params
static VALUE vm_default_params(void)
Definition: vm.c:1878
sdr
static VALUE sdr(void)
Definition: vm.c:2446
main_to_s
static VALUE main_to_s(VALUE obj)
Definition: vm.c:2820
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1506
rb_vm_cref_in_context
NODE * rb_vm_cref_in_context(VALUE self)
Definition: vm.c:1027
RNode::tbl
ID * tbl
Definition: node.h:247
rb_thread_struct::value
VALUE value
Definition: vm_core.h:570
rb_thread_struct::machine
struct rb_thread_struct::@169 machine
rb_iseq_eval_main
VALUE rb_iseq_eval_main(VALUE iseqval)
Definition: vm.c:1655
rb_mark_method_entry
void rb_mark_method_entry(const rb_method_entry_t *me)
Definition: gc.c:3417
RUBY_DTRACE_METHOD_ENTRY_HOOK
#define RUBY_DTRACE_METHOD_ENTRY_HOOK(th, klass, id)
Definition: probes_helper.h:55
rb_method_definition_struct::original_id
ID original_id
Definition: method.h:80
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE p)
Definition: gc.c:4897
REGEXP_REDEFINED_OP_FLAG
#define REGEXP_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:242
rb_proc_t::envval
VALUE envval
Definition: vm_core.h:703
rb_vm_struct::thgroup_default
VALUE thgroup_default
Definition: vm_core.h:358
vm_opt_method_table
static st_table * vm_opt_method_table
Definition: vm.c:1167
probes_helper.h
VM_FRAME_FLAG_PASSED
#define VM_FRAME_FLAG_PASSED
Definition: vm_core.h:775
sym
#define sym(x)
Definition: date_core.c:3695
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:20
RNode
Definition: node.h:239
iseq_catch_table_entry::type
enum iseq_catch_table_entry::catch_type type
rb_hash_foreach
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
Definition: hash.c:264
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
ruby_vm_collect_usage_func_register
void(* ruby_vm_collect_usage_func_register)(int reg, int isset)
Definition: vm.c:3040
vm_method.c
rb_thread_struct::stack
VALUE * stack
Definition: vm_core.h:529
rb_singleton_class
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1628
Init_top_self
void Init_top_self(void)
Definition: vm.c:2832
rb_vm_control_frame_id_and_class
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, VALUE *klassp)
Definition: vm.c:1668
vm_yield_with_cref
static VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
Definition: vm.c:845
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
check_env_value
static VALUE check_env_value(VALUE envval)
Definition: vm.c:442
rb_iseq_struct::type
enum rb_iseq_struct::iseq_type type
rb_vm_struct::defined_module_hash
VALUE defined_module_hash
Definition: vm_core.h:404
rb_control_frame_struct::proc
VALUE proc
Definition: vm_core.h:454
rb_binding_new
VALUE rb_binding_new(void)
Definition: proc.c:326
rb_control_frame_struct::self
VALUE self
Definition: vm_core.h:450
TH_POP_TAG
#define TH_POP_TAG()
Definition: eval_intern.h:128
st_lookup
int st_lookup(st_table *, st_data_t, st_data_t *)
m_core_define_method
static VALUE m_core_define_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
Definition: vm.c:2278
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1351
ruby_vm_class_serial
static rb_serial_t ruby_vm_class_serial
Definition: vm.c:76
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1154
rb_cBinding
RUBY_EXTERN VALUE rb_cBinding
Definition: ruby.h:1556
rb_binding_t::first_lineno
unsigned short first_lineno
Definition: vm_core.h:730
vm_make_env_each
static VALUE vm_make_env_each(rb_thread_t *const th, rb_control_frame_t *const cfp, VALUE *envptr, VALUE *const endptr)
Definition: vm.c:455
vm_set_main_stack
static void vm_set_main_stack(rb_thread_t *th, VALUE iseqval)
Definition: vm.c:216
rb_ary_free
void rb_ary_free(VALUE ary)
Definition: array.c:540
iseq_catch_table_entry::CATCH_TYPE_RESCUE
Definition: iseq.h:57
RUBY_VM_THREAD_VM_STACK_SIZE
#define RUBY_VM_THREAD_VM_STACK_SIZE
Definition: vm_core.h:431
rb_thread_method_id_and_class
int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp)
Definition: vm.c:1696
BOP_LAST_
Definition: vm_insnhelper.h:61
th_init
static void th_init(rb_thread_t *th, VALUE self)
Definition: vm.c:2180
add_opt_method
static void add_opt_method(VALUE klass, ID mid, VALUE bop)
Definition: vm.c:1219
rb_insns_name
const char * rb_insns_name(int i)
Definition: compile.c:5601
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1333
rb_vm_struct::src_encoding_index
int src_encoding_index
Definition: vm_core.h:397
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1393
EXEC_TAG
#define EXEC_TAG()
Definition: eval_intern.h:168
rb_thread_struct::locking_mutex
VALUE locking_mutex
Definition: vm_core.h:590
BIGNUM_REDEFINED_OP_FLAG
#define BIGNUM_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:239
rb_vm_get_ruby_level_next_cfp
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
Definition: vm.c:247
vm_exec.c
rb_vm_ep_local_ep
VALUE * rb_vm_ep_local_ep(VALUE *ep)
Definition: vm.c:34
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:547
rb_insn_operand_intern
VALUE rb_insn_operand_intern(rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, VALUE *pnop, VALUE child)
Definition: iseq.c:1158
rb_block_lambda
VALUE rb_block_lambda(void)
Definition: proc.c:634
vm_iter_break
static void vm_iter_break(rb_thread_t *th, VALUE val)
Definition: vm.c:1143
invoke_block_from_c
static VALUE invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, VALUE self, int argc, const VALUE *argv, const rb_block_t *blockptr, const NODE *cref, VALUE defined_class)
Definition: vm.c:767
ruby_threadptr_data_type
const rb_data_type_t ruby_threadptr_data_type
Definition: vm.c:2144
rb_vm_struct::fiber_vm_stack_size
size_t fiber_vm_stack_size
Definition: vm_core.h:422
GetBindingPtr
#define GetBindingPtr(obj, ptr)
Definition: vm_core.h:723
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:510
rb_vm_t
struct rb_vm_struct rb_vm_t
rb_vm_inc_const_missing_count
void rb_vm_inc_const_missing_count(void)
Definition: vm.c:111
rb_vm_set_progname
void rb_vm_set_progname(VALUE filename)
Definition: vm.c:2779
rb_cBasicObject
RUBY_EXTERN VALUE rb_cBasicObject
Definition: ruby.h:1552
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:495
dp
#define dp(v)
Definition: vm_debug.h:21
rb_vm_struct::load_path_check_cache
VALUE load_path_check_cache
Definition: vm_core.h:374
snprintf
#define snprintf
Definition: subst.h:6
RCLASS_ORIGIN
#define RCLASS_ORIGIN(c)
Definition: internal.h:297
JUMP_TAG
#define JUMP_TAG(st)
Definition: eval_intern.h:173
rb_control_frame_struct::iseq
rb_iseq_t * iseq
Definition: vm_core.h:448
rb_vm_struct::trap_list
struct rb_vm_struct::@167 trap_list[RUBY_NSIG]
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
VMDEBUG
#define VMDEBUG
Definition: vm_dump.c:19
COPY_CREF
#define COPY_CREF(c1, c2)
Definition: vm_insnhelper.h:184
RCLASS_SET_SUPER
static VALUE RCLASS_SET_SUPER(VALUE klass, VALUE super)
Definition: internal.h:319
UNLIKELY
#define UNLIKELY(x)
Definition: vm_core.h:109
rb_backref_set
void rb_backref_set(VALUE val)
Definition: vm.c:953
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2225
RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN
#define RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN
Definition: vm_core.h:434
vm_stat
static VALUE vm_stat(int argc, VALUE *argv, VALUE self)
Definition: vm.c:139
collect_local_variables_in_iseq
static int collect_local_variables_in_iseq(rb_iseq_t *iseq, const VALUE ary)
Definition: vm.c:534
id_core_hash_merge_ptr
Definition: id.h:109
MATCH
#define MATCH(s, p, c)
Definition: date_parse.c:267
rb_cRubyVM
VALUE rb_cRubyVM
Definition: vm.c:97
check_block
static const rb_block_t * check_block(rb_thread_t *th)
Definition: vm.c:833
check_machine_stack_size
static void check_machine_stack_size(size_t *sizep)
Definition: vm.c:1910
RNode::u1
union RNode::@129 u1
RUBY_MARK_ENTER
#define RUBY_MARK_ENTER(msg)
Definition: gc.h:53
vm_define_method
static void vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval, rb_num_t is_singleton, NODE *cref)
Definition: vm.c:2237
rb_thread_struct::top_self
VALUE top_self
Definition: vm_core.h:551
argc
int argc
Definition: ruby.c:131
rb_vm_struct::loading_table
struct st_table * loading_table
Definition: vm_core.h:379
VM_FRAME_MAGIC_CLASS
#define VM_FRAME_MAGIC_CLASS
Definition: vm_core.h:761
Qfalse
#define Qfalse
Definition: ruby.h:425
ruby_thread_init
static VALUE ruby_thread_init(VALUE self)
Definition: vm.c:2212
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1348
thread_memsize
static size_t thread_memsize(const void *ptr)
Definition: vm.c:2124
ruby_thread_init_stack
void ruby_thread_init_stack(rb_thread_t *th)
Definition: thread.c:497
collect_local_variables_in_env
static int collect_local_variables_in_env(rb_env_t *env, const VALUE ary)
Definition: vm.c:548
RUBY_DTRACE_CMETHOD_RETURN_HOOK
#define RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, klass, id)
Definition: probes_helper.h:64
rb_method_entry_struct
Definition: method.h:97
kwmerge_ii
static int kwmerge_ii(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
Definition: vm.c:2391
rb_frame_pop
void rb_frame_pop(void)
Definition: vm.c:309
TAG_REDO
#define TAG_REDO
Definition: eval_intern.h:192
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:4920
rb_objspace
Definition: gc.c:417
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1352
T_NODE
#define T_NODE
Definition: ruby.h:498
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:92
rb_gc_stack_start
VALUE * rb_gc_stack_start
rb_str_new2
#define rb_str_new2
Definition: intern.h:840
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1801
err
int err
Definition: win32.c:114
id_core_define_method
Definition: id.h:104
rb_vm_make_env_object
VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm.c:577
EXIT_FAILURE
#define EXIT_FAILURE
Definition: eval_intern.h:24
SET_THROWOBJ_CATCH_POINT
#define SET_THROWOBJ_CATCH_POINT(obj, val)
Definition: eval_intern.h:200
vm_make_env_object
static VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp, VALUE *blockprocptr)
Definition: vm.c:584
RArray::basic
struct RBasic basic
Definition: ruby.h:861
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1349
rb_iseq_struct::local_table
ID * local_table
Definition: vm_core.h:235
vm_exec
static VALUE vm_exec(rb_thread_t *th)
Definition: vm.c:1388
RUBY_VM_GET_CFP_FROM_BLOCK_PTR
#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b)
Definition: vm_core.h:839
ruby_vm_debug_ptr
VALUE * ruby_vm_debug_ptr(rb_vm_t *vm)
Definition: vm.c:2851
rb_method_entry
rb_method_entry_t * rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr)
Definition: vm_method.c:617
rb_thread_mark
void rb_thread_mark(void *ptr)
Definition: vm.c:2014
ARRAY_REDEFINED_OP_FLAG
#define ARRAY_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:237
rb_method_entry_struct::klass
VALUE klass
Definition: method.h:102
rb_control_frame_struct
Definition: vm_core.h:445
encoding.h
iseq_catch_table_entry::start
unsigned long start
Definition: iseq.h:65
RUBY_VM_FIBER_MACHINE_STACK_SIZE
#define RUBY_VM_FIBER_MACHINE_STACK_SIZE
Definition: vm_core.h:438
rb_binding_add_dynavars
VALUE * rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars)
Definition: vm.c:725
numberof
#define numberof(array)
Definition: etc.c:595
rb_num_t
unsigned long rb_num_t
Definition: vm_core.h:124
rb_gc_mark_machine_stack
void rb_gc_mark_machine_stack(rb_thread_t *th)
Definition: gc.c:3506
ruby_mimmalloc
void * ruby_mimmalloc(size_t size)
Definition: gc.c:6251
rb_call_end_proc
void rb_call_end_proc(VALUE data)
Definition: eval_jump.c:11
vm_eval.c
TAG_RETURN
#define TAG_RETURN
Definition: eval_intern.h:188
TH_POP_TAG2
#define TH_POP_TAG2()
Definition: eval_intern.h:132
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1880
rb_thread_struct::event_hooks
rb_hook_list_t event_hooks
Definition: vm_core.h:637
iseq_catch_table_entry::CATCH_TYPE_ENSURE
Definition: iseq.h:58
rb_iseq_clone
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase)
Definition: iseq.c:1922
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1697
rb_cRegexp
RUBY_EXTERN VALUE rb_cRegexp
Definition: ruby.h:1581
rb_alias_variable
void rb_alias_variable(ID, ID)
Definition: variable.c:869
core_hash_from_ary
static VALUE core_hash_from_ary(VALUE ary)
Definition: vm.c:2355
RCLASS_M_TBL
#define RCLASS_M_TBL(c)
Definition: internal.h:295
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:886
iseq_catch_table_entry::CATCH_TYPE_NEXT
Definition: iseq.h:62
vm_svar_set
static void vm_svar_set(VALUE key, VALUE val)
Definition: vm.c:940
VM_CF_BLOCK_PTR
static rb_block_t * VM_CF_BLOCK_PTR(rb_control_frame_t *cfp)
Definition: vm.c:52
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
rb_thread_set_current
#define rb_thread_set_current(th)
Definition: vm_core.h:940
VM_EP_PREV_EP
#define VM_EP_PREV_EP(ep)
Definition: vm_core.h:818
TRUE
#define TRUE
Definition: nkf.h:175
rb_vm_struct::special_exceptions
VALUE special_exceptions[ruby_special_error_count]
Definition: vm_core.h:368
idIFUNC
Definition: id.h:99
rb_vm_stack_to_heap
void rb_vm_stack_to_heap(rb_thread_t *th)
Definition: vm.c:635
rb_thread_struct::keeping_mutexes
struct rb_mutex_struct * keeping_mutexes
Definition: vm_core.h:591
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
rb_serial_t
unsigned long rb_serial_t
Definition: internal.h:260
rb_proc_t
Definition: vm_core.h:700
rb_vm_struct::loaded_features
VALUE loaded_features
Definition: vm_core.h:376
S
#define S(s)
rb_binding_t::blockprocval
VALUE blockprocval
Definition: vm_core.h:729
rb_add_method
rb_method_entry_t * rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex)
Definition: vm_method.c:428
vm_set_top_stack
static void vm_set_top_stack(rb_thread_t *th, VALUE iseqval)
Definition: vm.c:184
EXEC_EVENT_HOOK_AND_POP_FRAME
#define EXEC_EVENT_HOOK_AND_POP_FRAME(th_, flag_, self_, id_, klass_, data_)
Definition: vm_core.h:1037
malloc
#define malloc
Definition: ripper.c:96
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:298
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:6242
m_core_define_singleton_method
static VALUE m_core_define_singleton_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
Definition: vm.c:2287
rb_is_local_id
int rb_is_local_id(ID id)
Definition: ripper.c:17301
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
vm_set_eval_stack
static void vm_set_eval_stack(rb_thread_t *th, VALUE iseqval, const NODE *cref, rb_block_t *base_block)
Definition: vm.c:200
rb_frame_method_id_and_class
int rb_frame_method_id_and_class(ID *idp, VALUE *klassp)
Definition: vm.c:1702
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
rb_iseq_struct::parent_iseq
struct rb_iseq_struct * parent_iseq
Definition: vm_core.h:296
FIXNUM_REDEFINED_OP_FLAG
#define FIXNUM_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:234
internal.h
rb_iseq_location_struct::path
const VALUE path
Definition: vm_core.h:197
ID
unsigned long ID
Definition: ruby.h:89
rb_vm_struct::thread_vm_stack_size
size_t thread_vm_stack_size
Definition: vm_core.h:420
rb_vm_make_jump_tag_but_local_jump
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
Definition: vm.c:1101
rb_vm_make_binding
VALUE rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp)
Definition: vm.c:694
ruby_vm_at_exit
void ruby_vm_at_exit(void(*func)(rb_vm_t *))
Definition: vm.c:318
rb_env_t::local_size
int local_size
Definition: vm_core.h:716
VM_EP_LEP
static VALUE * VM_EP_LEP(VALUE *ep)
Definition: vm.c:25
rb_cEnv
VALUE rb_cEnv
Definition: vm.c:99
Qnil
#define Qnil
Definition: ruby.h:427
rb_clear_method_cache_by_class
void rb_clear_method_cache_by_class(VALUE)
Definition: vm_method.c:66
type
int type
Definition: tcltklib.c:112
REWIND_CFP
#define REWIND_CFP(expr)
Definition: vm.c:2272
vm_core.h
VM_FRAME_MAGIC_EVAL
#define VM_FRAME_MAGIC_EVAL
Definition: vm_core.h:766
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:502
rb_iseq_struct::iseq_encoded
VALUE * iseq_encoded
Definition: vm_core.h:226
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_vm_top_self
VALUE rb_vm_top_self(void)
Definition: vm.c:2826
rb_iseq_eval
VALUE rb_iseq_eval(VALUE iseqval)
Definition: vm.c:1642
vm_base_ptr
static VALUE * vm_base_ptr(rb_control_frame_t *cfp)
Definition: vm_insnhelper.c:978
result
static VALUE result
Definition: nkf.c:40
vm_pop_frame
static void vm_pop_frame(rb_thread_t *th)
Definition: vm_insnhelper.c:99
m_core_hash_merge_ptr
static VALUE m_core_hash_merge_ptr(int argc, VALUE *argv, VALUE recv)
Definition: vm.c:2381
rb_iseq_struct::catch_table_size
int catch_table_size
Definition: vm_core.h:293
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1116
iseq_catch_table_entry
Definition: iseq.h:55
RARRAY_EMBED_FLAG
#define RARRAY_EMBED_FLAG
Definition: ruby.h:874
rb_vm_struct::main_thread
struct rb_thread_struct * main_thread
Definition: vm_core.h:354
rb_class2name
const char * rb_class2name(VALUE)
Definition: variable.c:397
rb_obj_hide
VALUE rb_obj_hide(VALUE obj)
Definition: object.c:53
id_core_hash_merge_kwd
Definition: id.h:110
ruby_current_thread
rb_thread_t * ruby_current_thread
Definition: vm.c:104
rb_thread_struct::first_proc
VALUE first_proc
Definition: vm_core.h:615
RARRAY_EMBED_LEN_MASK
#define RARRAY_EMBED_LEN_MASK
Definition: ruby.h:876
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:632
rb_mark_tbl
void rb_mark_tbl(st_table *tbl)
Definition: gc.c:3519
Init_native_thread
void Init_native_thread(void)
SYMBOL_REDEFINED_OP_FLAG
#define SYMBOL_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:240
rb_alias
void rb_alias(VALUE, ID, ID)
Definition: vm_method.c:1244
rb_iseq_struct::location
rb_iseq_location_t location
Definition: vm_core.h:223
TH_PUSH_TAG
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:122
RBasic::flags
VALUE flags
Definition: ruby.h:748
rb_sigaltstack_size
int rb_sigaltstack_size(void)
ruby_vm_destruct
int ruby_vm_destruct(rb_vm_t *vm)
Definition: vm.c:1818
iseq_catch_table_entry::CATCH_TYPE_BREAK
Definition: iseq.h:60
AREF
#define AREF(s, idx)
Definition: cparse.c:93
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:272
rb_control_frame_struct::flag
VALUE flag
Definition: vm_core.h:449
RUBY_DTRACE_HASH_CREATE_ENABLED
#define RUBY_DTRACE_HASH_CREATE_ENABLED()
Definition: probes.h:45
NEW_THROW_OBJECT
#define NEW_THROW_OBJECT(val, pt, st)
Definition: eval_intern.h:198
iseq_catch_table_entry::CATCH_TYPE_REDO
Definition: iseq.h:61
rb_set_end_proc
void rb_set_end_proc(void(*func)(VALUE), VALUE data)
Definition: eval_jump.c:60
rb_memerror
void rb_memerror(void)
Definition: gc.c:5882
rb_proc_t::blockprocval
VALUE blockprocval
Definition: vm_core.h:704
thread_recycle_stack
static VALUE * thread_recycle_stack(size_t size)
Definition: vm.c:1976
getenv
#define getenv(name)
Definition: win32.c:66
OP
#define OP(mid_, bop_)
rb_thread_struct::status
enum rb_thread_status status
Definition: vm_core.h:562
VM_FRAME_MAGIC_TOP
#define VM_FRAME_MAGIC_TOP
Definition: vm_core.h:762
rb_iter_break_value
void rb_iter_break_value(VALUE val)
Definition: vm.c:1160
vm_svar_get
static VALUE vm_svar_get(VALUE key)
Definition: vm.c:933
RUBY_FREE_UNLESS_NULL
#define RUBY_FREE_UNLESS_NULL(ptr)
Definition: gc.h:61
VM_FRAME_MAGIC_PROC
#define VM_FRAME_MAGIC_PROC
Definition: vm_core.h:764
kwmerge_i
static int kwmerge_i(VALUE key, VALUE value, VALUE hash)
Definition: vm.c:2399
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
rb_mRubyVMFrozenCore
VALUE rb_mRubyVMFrozenCore
Definition: vm.c:100
id_core_set_method_alias
Definition: id.h:101
vm_exec_core
static VALUE vm_exec_core(rb_thread_t *th, VALUE initial)
Definition: vm_exec.c:45
rb_thread_struct::first_args
VALUE first_args
Definition: vm_core.h:616
rb_define_method_id
void rb_define_method_id(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1482
vm_collect_local_variables_in_heap
static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *ep, VALUE ary)
Definition: vm.c:559
get_param
static size_t get_param(const char *name, size_t default_value, size_t min_value)
Definition: vm.c:1893
iseq_catch_table_entry::sp
unsigned long sp
Definition: iseq.h:68
size
int size
Definition: encoding.c:49
VM_FRAME_MAGIC_LAMBDA
#define VM_FRAME_MAGIC_LAMBDA
Definition: vm_core.h:767
rb_block_struct::proc
VALUE proc
Definition: vm_core.h:467
rb_vm_struct::objspace
struct rb_objspace * objspace
Definition: vm_core.h:407
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rb_thread_struct::top_wrapper
VALUE top_wrapper
Definition: vm_core.h:552
rb_thread_struct::mark_stack_len
int mark_stack_len
Definition: vm_core.h:631
ruby_current_vm
rb_vm_t * ruby_current_vm
Definition: vm.c:105
rb_iseq_struct::arg_size
int arg_size
Definition: vm_core.h:281
nsdr
static VALUE nsdr(void)
Definition: vm.c:2454
rb_proc_t::safe_level
int safe_level
Definition: vm_core.h:705
rb_cBignum
VALUE rb_cBignum
Definition: bignum.c:35
at_exit
static int at_exit
Definition: tcltklib.c:186
rb_vm_struct::default_params
struct rb_vm_struct::@168 default_params
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:959
vm_get_cbase
static VALUE vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
Definition: vm_insnhelper.c:305
rb_thread_struct::root_svar
VALUE root_svar
Definition: vm_core.h:558
rb_proc_t::block
rb_block_t block
Definition: vm_core.h:701
vm_insnhelper.c
vm_redefinition_check_flag
static int vm_redefinition_check_flag(VALUE klass)
Definition: vm.c:1170
rb_thread_struct::stack_start
VALUE * stack_start
Definition: vm_core.h:621
rb_control_frame_struct::pc
VALUE * pc
Definition: vm_core.h:446
rb_thread_recycle_stack_release
void rb_thread_recycle_stack_release(VALUE *stack)
Definition: vm.c:1992
Init_BareVM
void Init_BareVM(void)
Definition: vm.c:2792
thread_data_type
#define thread_data_type
Definition: vm.c:2143
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:620
cv
static const unsigned char cv[]
Definition: nkf.c:564
rb_method_entry_struct::def
rb_method_definition_t * def
Definition: method.h:100
SET
#define SET(name, attr)
st_memsize
size_t st_memsize(const st_table *)
Definition: st.c:342
NORETURN
NORETURN(static void vm_iter_break(rb_thread_t *th, VALUE val))
PROCDEBUG
#define PROCDEBUG
Definition: vm.c:89
rb_ruby_verbose_ptr
VALUE * rb_ruby_verbose_ptr(void)
Definition: vm.c:2857
rb_control_frame_struct::me
const rb_method_entry_t * me
Definition: vm_core.h:455
RUBY_FREE_LEAVE
#define RUBY_FREE_LEAVE(msg)
Definition: gc.h:56
rb_data_type_struct
Definition: ruby.h:966
rb_event_flag_t
unsigned long rb_event_flag_t
Definition: ruby.h:1740
rb_vm_struct::event_hooks
rb_hook_list_t event_hooks
Definition: vm_core.h:388
RUBY_VM_THREAD_VM_STACK_SIZE_MIN
#define RUBY_VM_THREAD_VM_STACK_SIZE_MIN
Definition: vm_core.h:432
id_core_define_singleton_method
Definition: id.h:105
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:697
Regexp
typedefRUBY_SYMBOL_EXPORT_BEGIN struct re_pattern_buffer Regexp
Definition: re.h:29
RUBY_FREE_ENTER
#define RUBY_FREE_ENTER(msg)
Definition: gc.h:55
STRING_REDEFINED_OP_FLAG
#define STRING_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:236
check_redefined_method
static int check_redefined_method(st_data_t key, st_data_t value, st_data_t data)
Definition: vm.c:1198
vm_cfp_svar_set
static void vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
Definition: vm.c:926
RHASH_TBL_RAW
#define RHASH_TBL_RAW(h)
Definition: internal.h:478
rb_thread_struct::thread_id
rb_nativethread_id_t thread_id
Definition: vm_core.h:561
rb_iseq_struct::catch_table
struct iseq_catch_table_entry * catch_table
Definition: vm_core.h:292
RUBY_VM_FIBER_VM_STACK_SIZE_MIN
#define RUBY_VM_FIBER_VM_STACK_SIZE_MIN
Definition: vm_core.h:437
key
uint8_t key[16]
Definition: random.c:1250
rb_cThread
VALUE rb_cThread
Definition: vm.c:98
ruby_vm_run_at_exit_hooks
static void ruby_vm_run_at_exit_hooks(rb_vm_t *vm)
Definition: vm.c:324
VM_PROFILE_ATEXIT
#define VM_PROFILE_ATEXIT()
Definition: vm_insnhelper.c:1435
rb_control_frame_struct::ep
VALUE * ep
Definition: vm_core.h:452
rb_thread_struct::root_fiber
VALUE root_fiber
Definition: vm_core.h:642
rb_iseq_struct::local_size
int local_size
Definition: vm_core.h:239
rb_thread_struct::fiber
VALUE fiber
Definition: vm_core.h:641
VM_EP_BLOCK_PTR
#define VM_EP_BLOCK_PTR(ep)
Definition: vm_core.h:819
ruby_vm_event_flags
rb_event_flag_t ruby_vm_event_flags
Definition: vm.c:106
rb_vm_trace_mark_event_hooks
void rb_vm_trace_mark_event_hooks(rb_hook_list_t *hooks)
Definition: vm_trace.c:51
m_core_hash_merge_kwd
static VALUE m_core_hash_merge_kwd(int argc, VALUE *argv, VALUE recv)
Definition: vm.c:2416
env_data_type
static const rb_data_type_t env_data_type
Definition: vm.c:405
RUBY_MARK_UNLESS_NULL
#define RUBY_MARK_UNLESS_NULL(ptr)
Definition: gc.h:60
rb_vm_struct::thread_machine_stack_size
size_t thread_machine_stack_size
Definition: vm_core.h:421
rb_vm_struct::load_path_snapshot
VALUE load_path_snapshot
Definition: vm_core.h:373
rb_vm_control_frame_block_ptr
rb_block_t * rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp)
Definition: vm.c:59
rb_binding_t
Definition: vm_core.h:726
RUBY_EVENT_END
#define RUBY_EVENT_END
Definition: ruby.h:1709
ruby_vm_redefined_flag
short ruby_vm_redefined_flag[BOP_LAST_]
Definition: vm.c:103
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1030
st.h
rb_cArray
VALUE rb_cArray
Definition: array.c:27
rb_thread_struct::state
int state
Definition: vm_core.h:537
GetThreadPtr
#define GetThreadPtr(obj, ptr)
Definition: vm_core.h:472
vm.h
rb_vm_struct::loaded_features_snapshot
VALUE loaded_features_snapshot
Definition: vm_core.h:377
rb_gc_stack_maxsize
size_t rb_gc_stack_maxsize
hash
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
rb_vm_struct::debug
VALUE debug
Definition: vm_core.h:399
vm_free
#define vm_free
Definition: vm.c:1815
rb_thread_struct::passed_bmethod_me
const rb_method_entry_t * passed_bmethod_me
Definition: vm_core.h:545
thread_alloc
static VALUE thread_alloc(VALUE klass)
Definition: vm.c:2166
env_free
static void env_free(void *const ptr)
Definition: vm.c:380
TIME_REDEFINED_OP_FLAG
#define TIME_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:241
PRIdSIZE
#define PRIdSIZE
Definition: ruby.h:176
rb_vm_struct::self
VALUE self
Definition: vm_core.h:349
EXEC_EVENT_HOOK
#define EXEC_EVENT_HOOK(th_, flag_, self_, id_, klass_, data_)
Definition: vm_core.h:1034
assert
#define assert(condition)
Definition: ossl.h:45
rb_vm_get_cref
NODE * rb_vm_get_cref(const rb_iseq_t *, const VALUE *)
Definition: vm_insnhelper.c:271
name
const char * name
Definition: nkf.c:208
rb_vm_struct
Definition: vm_core.h:348
rb_iseq_struct::self
VALUE self
Definition: vm_core.h:303
rb_iseq_struct
Definition: vm_core.h:206
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:355
GetISeqPtr
#define GetISeqPtr(obj, ptr)
Definition: vm_core.h:193
iseq_catch_table_entry::cont
unsigned long cont
Definition: iseq.h:67
THREAD_RUNNABLE
Definition: vm_core.h:476
rb_block_struct::klass
VALUE klass
Definition: vm_core.h:464
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17230
m_core_set_variable_alias
static VALUE m_core_set_variable_alias(VALUE self, VALUE sym1, VALUE sym2)
Definition: vm.c:2305
VM_FRAME_TYPE_BMETHOD_P
#define VM_FRAME_TYPE_BMETHOD_P(cfp)
Definition: vm_core.h:779
rb_thread_struct::safe_level
int safe_level
Definition: vm_core.h:532
rb_thread_struct::stack_size
size_t stack_size
Definition: vm_core.h:530
ruby_vm_global_method_state
static rb_serial_t ruby_vm_global_method_state
Definition: vm.c:74
rb_thread_struct::self
VALUE self
Definition: vm_core.h:525
rb_thread_t
struct rb_thread_struct rb_thread_t
m_core_set_method_alias
static VALUE m_core_set_method_alias(VALUE self, VALUE cbase, VALUE sym1, VALUE sym2)
Definition: vm.c:2296
rb_thread_struct::tag
struct rb_vm_tag * tag
Definition: vm_core.h:593
ruby_vm_collect_usage_func_operand
void(* ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)
Definition: vm.c:3039
iseq_catch_table_entry::iseq
VALUE iseq
Definition: iseq.h:64
rb_vm_rewind_cfp
void rb_vm_rewind_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm.c:291
rb_vm_gvl_destroy
void rb_vm_gvl_destroy(rb_vm_t *vm)
Definition: thread.c:272
rb_lastline_set
void rb_lastline_set(VALUE val)
Definition: vm.c:965
rb_vm_tag::retval
VALUE retval
Definition: vm_core.h:490
VM_METHOD_TYPE_CFUNC
Definition: method.h:49
GC_GUARDED_PTR_REF
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:800
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1428
id_core_set_postexe
Definition: id.h:106
vm_invoke_proc
static VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class, int argc, const VALUE *argv, const rb_block_t *blockptr)
Definition: vm.c:869
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1076
ENV_VAL
#define ENV_VAL(env)
Definition: vm.c:347
NOEX_PUBLIC
Definition: method.h:25
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1165
rb_vm_struct::load_path
VALUE load_path
Definition: vm_core.h:372
RECYCLE_MAX
#define RECYCLE_MAX
Definition: vm.c:1971
rb_thread_struct::pending_interrupt_queue
VALUE pending_interrupt_queue
Definition: vm_core.h:581
ruby_vm_collect_usage_func_insn
void(* ruby_vm_collect_usage_func_insn)(int insn)
Definition: vm.c:3038
rb_cSymbol
RUBY_EXTERN VALUE rb_cSymbol
Definition: ruby.h:1585
vm_make_proc_from_block
static VALUE vm_make_proc_from_block(rb_thread_t *th, rb_block_t *block)
Definition: vm.c:647
rb_intern
#define rb_intern(str)
rb_sourcefile
const char * rb_sourcefile(void)
Definition: vm.c:987
m_core_hash_from_ary
static VALUE m_core_hash_from_ary(VALUE self, VALUE ary)
Definition: vm.c:2347
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:354
rb_vm_check_redefinition_opt_method
static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
Definition: vm.c:1185
rb_binding_t::path
VALUE path
Definition: vm_core.h:728
env
#define env
NULL
#define NULL
Definition: _sdbm.c:103
Qundef
#define Qundef
Definition: ruby.h:428
T_ICLASS
#define T_ICLASS
Definition: ruby.h:479
rb_thread_struct::stat_insn_usage
VALUE stat_insn_usage
Definition: vm_core.h:634
rb_thread_struct::errinfo
VALUE errinfo
Definition: vm_core.h:573
rb_cFixnum
RUBY_EXTERN VALUE rb_cFixnum
Definition: ruby.h:1565
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:1587
rb_vm_jump_tag_but_local_jump
void rb_vm_jump_tag_but_local_jump(int state)
Definition: vm.c:1133
VM_EP_LEP_P
#define VM_EP_LEP_P(ep)
Definition: vm_core.h:820
rb_iseq_location_struct::label
const VALUE label
Definition: vm_core.h:200
HASH_REDEFINED_OP_FLAG
#define HASH_REDEFINED_OP_FLAG
Definition: vm_insnhelper.h:238
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:927
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:228
st_foreach
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1034
NEW_NODE
#define NEW_NODE(t, a0, a1, a2)
Definition: node.h:364
GET_THROWOBJ_VAL
#define GET_THROWOBJ_VAL(obj)
Definition: eval_intern.h:205
id_core_hash_from_ary
Definition: id.h:107
free
free(psz)
rb_obj_is_thread
VALUE rb_obj_is_thread(VALUE obj)
Definition: vm.c:2155
core_hash_merge_ary
static VALUE core_hash_merge_ary(VALUE hash, VALUE ary)
Definition: vm.c:2374
ruby_vm_verbose_ptr
VALUE * ruby_vm_verbose_ptr(rb_vm_t *vm)
Definition: vm.c:2845
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
DEFINED_EXPR
Definition: iseq.h:124
rb_binding_alloc
VALUE rb_binding_alloc(VALUE klass)
Definition: proc.c:287
vm_init_redefined_flag
static void vm_init_redefined_flag(void)
Definition: vm.c:1232
rb_thread_set_current_raw
#define rb_thread_set_current_raw(th)
Definition: vm_core.h:939
rb_vm_struct::coverages
VALUE coverages
Definition: vm_core.h:400
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1213
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:1001
argv
char ** argv
Definition: ruby.c:132
TAG_RETRY
#define TAG_RETRY
Definition: eval_intern.h:191
rb_block_struct::ep
VALUE * ep
Definition: vm_core.h:465
RUBY_DTRACE_HASH_CREATE
#define RUBY_DTRACE_HASH_CREATE(arg0, arg1, arg2)
Definition: probes.h:46
vm_yield_with_cfunc
static VALUE vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block, VALUE self, int argc, const VALUE *argv, const rb_block_t *blockargptr)
Definition: vm_insnhelper.c:2081
vm_default_params_setup
static void vm_default_params_setup(rb_vm_t *vm)
Definition: vm.c:1928
rb_thread_current_status
VALUE rb_thread_current_status(const rb_thread_t *th)
Definition: vm.c:1708
rb_env_t
Definition: vm_core.h:713
GET_VM
#define GET_VM()
Definition: vm_core.h:920