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