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