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