Ruby  2.1.10p492(2016-04-01revision54464)
vm.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  vm.c -
4 
5  $Author: usa $
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");
363  RUBY_MARK_UNLESS_NULL(env->prev_envval);
364  RUBY_MARK_UNLESS_NULL(env->block.self);
365  RUBY_MARK_UNLESS_NULL(env->block.proc);
366 
367  if (env->block.iseq) {
368  if (BUILTIN_TYPE(env->block.iseq) == T_NODE) {
369  RUBY_MARK_UNLESS_NULL((VALUE)env->block.iseq);
370  }
371  else {
372  RUBY_MARK_UNLESS_NULL(env->block.iseq->self);
373  }
374  }
375  }
376  RUBY_MARK_LEAVE("env");
377 }
378 
379 static void
380 env_free(void * const ptr)
381 {
382  RUBY_FREE_ENTER("env");
383  if (ptr) {
384  rb_env_t *const env = ptr;
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;
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");
435  check_env_value(env->prev_envval);
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 /* Binding */
692 
693 VALUE
695 {
697  rb_control_frame_t *ruby_level_cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp);
698  VALUE bindval, envval;
699  rb_binding_t *bind;
700  VALUE blockprocval = 0;
701 
702  if (cfp == 0 || ruby_level_cfp == 0) {
703  rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
704  }
705 
706  while (1) {
707  envval = vm_make_env_object(th, cfp, &blockprocval);
708  if (cfp == ruby_level_cfp) {
709  break;
710  }
712  }
713 
714  bindval = rb_binding_alloc(rb_cBinding);
715  GetBindingPtr(bindval, bind);
716  bind->env = envval;
717  bind->path = ruby_level_cfp->iseq->location.path;
718  bind->blockprocval = blockprocval;
719  bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp);
720 
721  return bindval;
722 }
723 
724 VALUE *
725 rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars)
726 {
727  VALUE envval = bind->env, path = bind->path, iseqval;
728  rb_env_t *env;
729  rb_block_t *base_block;
730  rb_thread_t *th = GET_THREAD();
731  rb_iseq_t *base_iseq;
732  NODE *node = 0;
733  ID minibuf[4], *dyns = minibuf;
734  VALUE idtmp = 0;
735  VALUE blockprocval = 0;
736 
737  if (dyncount < 0) return 0;
738 
739  GetEnvPtr(envval, env);
740 
741  base_block = &env->block;
742  base_iseq = base_block->iseq;
743 
744  if (dyncount >= numberof(minibuf)) dyns = ALLOCV_N(ID, idtmp, dyncount + 1);
745 
746  dyns[0] = dyncount;
747  MEMCPY(dyns + 1, dynvars, ID, dyncount);
748  node = NEW_NODE(NODE_SCOPE, dyns, 0, 0);
749 
750  iseqval = rb_iseq_new(node, base_iseq->location.label, path, path,
751  base_iseq->self, ISEQ_TYPE_EVAL);
752  node->u1.tbl = 0; /* reset table */
753  ALLOCV_END(idtmp);
754 
755  vm_set_eval_stack(th, iseqval, 0, base_block);
756  bind->env = vm_make_env_object(th, th->cfp, &blockprocval);
757  bind->blockprocval = blockprocval;
758  vm_pop_frame(th);
759  GetEnvPtr(bind->env, env);
760 
761  return env->env;
762 }
763 
764 /* C -> Ruby: block */
765 
766 static inline VALUE
768  VALUE self, int argc, const VALUE *argv,
769  const rb_block_t *blockptr, const NODE *cref,
770  VALUE defined_class)
771 {
772  if (SPECIAL_CONST_P(block->iseq)) {
773  return Qnil;
774  }
775  else if (BUILTIN_TYPE(block->iseq) != T_NODE) {
776  VALUE ret;
777  const rb_iseq_t *iseq = block->iseq;
778  const rb_control_frame_t *cfp;
779  int i, opt_pc, arg_size = iseq->arg_size;
781  const rb_method_entry_t *me = th->passed_bmethod_me;
782  th->passed_bmethod_me = 0;
783  cfp = th->cfp;
784 
785  for (i=0; i<argc; i++) {
786  cfp->sp[i] = argv[i];
787  }
788 
789  opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr,
791 
792  if (me != 0) {
793  /* bmethod */
795  self, defined_class,
796  VM_ENVVAL_PREV_EP_PTR(block->ep),
797  iseq->iseq_encoded + opt_pc,
798  cfp->sp + arg_size, iseq->local_size - arg_size,
799  me, iseq->stack_max);
800 
802  EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, self, me->called_id, me->klass, Qnil);
803  }
804  else {
806  self, defined_class,
807  VM_ENVVAL_PREV_EP_PTR(block->ep),
808  iseq->iseq_encoded + opt_pc,
809  cfp->sp + arg_size, iseq->local_size - arg_size,
810  0, iseq->stack_max);
811  }
812 
813  if (cref) {
814  th->cfp->ep[-1] = (VALUE)cref;
815  }
816 
817  ret = vm_exec(th);
818 
819  if (me) {
820  /* bmethod */
821  EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, self, me->called_id, me->klass, ret);
823  }
824 
825  return ret;
826  }
827  else {
828  return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr);
829  }
830 }
831 
832 static inline const rb_block_t *
834 {
835  const rb_block_t *blockptr = VM_CF_BLOCK_PTR(th->cfp);
836 
837  if (blockptr == 0) {
838  rb_vm_localjump_error("no block given", Qnil, 0);
839  }
840 
841  return blockptr;
842 }
843 
844 static inline VALUE
845 vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
846 {
847  const rb_block_t *blockptr = check_block(th);
848  return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref,
849  blockptr->klass);
850 }
851 
852 static inline VALUE
853 vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
854 {
855  const rb_block_t *blockptr = check_block(th);
856  return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0,
857  blockptr->klass);
858 }
859 
860 static inline VALUE
861 vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, const rb_block_t *blockargptr)
862 {
863  const rb_block_t *blockptr = check_block(th);
864  return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, blockargptr, 0,
865  blockptr->klass);
866 }
867 
868 static VALUE
869 vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
870  int argc, const VALUE *argv, const rb_block_t *blockptr)
871 {
872  VALUE val = Qundef;
873  int state;
874  volatile int stored_safe = th->safe_level;
875 
876  TH_PUSH_TAG(th);
877  if ((state = EXEC_TAG()) == 0) {
878  if (!proc->is_from_method) {
879  th->safe_level = proc->safe_level;
880  }
881  val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0,
882  defined_class);
883  }
884  TH_POP_TAG();
885 
886  if (!proc->is_from_method) {
887  th->safe_level = stored_safe;
888  }
889 
890  if (state) {
891  JUMP_TAG(state);
892  }
893  return val;
894 }
895 
896 VALUE
898  int argc, const VALUE *argv, const rb_block_t *blockptr)
899 {
900  return vm_invoke_proc(th, proc, proc->block.self, proc->block.klass,
901  argc, argv, blockptr);
902 }
903 
904 /* special variable */
905 
906 static rb_control_frame_t *
908 {
909  while (cfp->pc == 0) {
912  return 0;
913  }
914  }
915  return cfp;
916 }
917 
918 static VALUE
920 {
921  cfp = vm_normal_frame(th, cfp);
922  return lep_svar_get(th, cfp ? VM_CF_LEP(cfp) : 0, key);
923 }
924 
925 static void
927 {
928  cfp = vm_normal_frame(th, cfp);
929  lep_svar_set(th, cfp ? VM_CF_LEP(cfp) : 0, key, val);
930 }
931 
932 static VALUE
934 {
935  rb_thread_t *th = GET_THREAD();
936  return vm_cfp_svar_get(th, th->cfp, key);
937 }
938 
939 static void
941 {
942  rb_thread_t *th = GET_THREAD();
943  vm_cfp_svar_set(th, th->cfp, key, val);
944 }
945 
946 VALUE
948 {
949  return vm_svar_get(1);
950 }
951 
952 void
954 {
955  vm_svar_set(1, val);
956 }
957 
958 VALUE
960 {
961  return vm_svar_get(0);
962 }
963 
964 void
966 {
967  vm_svar_set(0, val);
968 }
969 
970 /* misc */
971 
972 VALUE
974 {
975  rb_thread_t *th = GET_THREAD();
977 
978  if (cfp) {
979  return cfp->iseq->location.path;
980  }
981  else {
982  return Qnil;
983  }
984 }
985 
986 const char *
988 {
989  rb_thread_t *th = GET_THREAD();
991 
992  if (cfp) {
993  return RSTRING_PTR(cfp->iseq->location.path);
994  }
995  else {
996  return 0;
997  }
998 }
999 
1000 int
1002 {
1003  rb_thread_t *th = GET_THREAD();
1005 
1006  if (cfp) {
1007  return rb_vm_get_sourceline(cfp);
1008  }
1009  else {
1010  return 0;
1011  }
1012 }
1013 
1014 NODE *
1016 {
1017  rb_thread_t *th = GET_THREAD();
1019 
1020  if (cfp == 0) {
1021  return NULL;
1022  }
1023  return rb_vm_get_cref(cfp->iseq, cfp->ep);
1024 }
1025 
1026 NODE *
1028 {
1029  rb_thread_t *th = GET_THREAD();
1031  if (cfp->self != self) return NULL;
1032  return rb_vm_get_cref(cfp->iseq, cfp->ep);
1033 }
1034 
1035 #if 0
1036 void
1037 debug_cref(NODE *cref)
1038 {
1039  while (cref) {
1040  dp(cref->nd_clss);
1041  printf("%ld\n", cref->nd_visi);
1042  cref = cref->nd_next;
1043  }
1044 }
1045 #endif
1046 
1047 VALUE
1049 {
1050  rb_thread_t *th = GET_THREAD();
1052 
1053  if (cfp == 0) {
1054  rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
1055  }
1056  return vm_get_cbase(cfp->iseq, cfp->ep);
1057 }
1058 
1059 /* jump */
1060 
1061 static VALUE
1062 make_localjump_error(const char *mesg, VALUE value, int reason)
1063 {
1064  extern VALUE rb_eLocalJumpError;
1065  VALUE exc = rb_exc_new2(rb_eLocalJumpError, mesg);
1066  ID id;
1067 
1068  switch (reason) {
1069  case TAG_BREAK:
1070  CONST_ID(id, "break");
1071  break;
1072  case TAG_REDO:
1073  CONST_ID(id, "redo");
1074  break;
1075  case TAG_RETRY:
1076  CONST_ID(id, "retry");
1077  break;
1078  case TAG_NEXT:
1079  CONST_ID(id, "next");
1080  break;
1081  case TAG_RETURN:
1082  CONST_ID(id, "return");
1083  break;
1084  default:
1085  CONST_ID(id, "noreason");
1086  break;
1087  }
1088  rb_iv_set(exc, "@exit_value", value);
1089  rb_iv_set(exc, "@reason", ID2SYM(id));
1090  return exc;
1091 }
1092 
1093 void
1094 rb_vm_localjump_error(const char *mesg, VALUE value, int reason)
1095 {
1096  VALUE exc = make_localjump_error(mesg, value, reason);
1097  rb_exc_raise(exc);
1098 }
1099 
1100 VALUE
1102 {
1103  VALUE result = Qnil;
1104 
1105  if (val == Qundef) {
1106  val = GET_THREAD()->tag->retval;
1107  }
1108  switch (state) {
1109  case 0:
1110  break;
1111  case TAG_RETURN:
1112  result = make_localjump_error("unexpected return", val, state);
1113  break;
1114  case TAG_BREAK:
1115  result = make_localjump_error("unexpected break", val, state);
1116  break;
1117  case TAG_NEXT:
1118  result = make_localjump_error("unexpected next", val, state);
1119  break;
1120  case TAG_REDO:
1121  result = make_localjump_error("unexpected redo", Qnil, state);
1122  break;
1123  case TAG_RETRY:
1124  result = make_localjump_error("retry outside of rescue clause", Qnil, state);
1125  break;
1126  default:
1127  break;
1128  }
1129  return result;
1130 }
1131 
1132 void
1134 {
1136  if (!NIL_P(exc)) rb_exc_raise(exc);
1137  JUMP_TAG(state);
1138 }
1139 
1140 NORETURN(static void vm_iter_break(rb_thread_t *th, VALUE val));
1141 
1142 static void
1144 {
1145  rb_control_frame_t *cfp = th->cfp;
1146  VALUE *ep = VM_CF_PREV_EP(cfp);
1147 
1148  th->state = TAG_BREAK;
1150  TH_JUMP_TAG(th, TAG_BREAK);
1151 }
1152 
1153 void
1155 {
1157 }
1158 
1159 void
1161 {
1163 }
1164 
1165 /* optimization: redefine management */
1166 
1168 
1169 static int
1171 {
1172  if (klass == rb_cFixnum) return FIXNUM_REDEFINED_OP_FLAG;
1173  if (klass == rb_cFloat) return FLOAT_REDEFINED_OP_FLAG;
1174  if (klass == rb_cString) return STRING_REDEFINED_OP_FLAG;
1175  if (klass == rb_cArray) return ARRAY_REDEFINED_OP_FLAG;
1176  if (klass == rb_cHash) return HASH_REDEFINED_OP_FLAG;
1177  if (klass == rb_cBignum) return BIGNUM_REDEFINED_OP_FLAG;
1178  if (klass == rb_cSymbol) return SYMBOL_REDEFINED_OP_FLAG;
1179  if (klass == rb_cTime) return TIME_REDEFINED_OP_FLAG;
1180  if (klass == rb_cRegexp) return REGEXP_REDEFINED_OP_FLAG;
1181  return 0;
1182 }
1183 
1184 static void
1186 {
1187  st_data_t bop;
1188  if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) {
1189  if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
1190  int flag = vm_redefinition_check_flag(klass);
1191 
1192  ruby_vm_redefined_flag[bop] |= flag;
1193  }
1194  }
1195 }
1196 
1197 static int
1199 {
1200  ID mid = (ID)key;
1201  rb_method_entry_t *me = (rb_method_entry_t *)value;
1202  VALUE klass = (VALUE)data;
1203  rb_method_entry_t *newme = rb_method_entry(klass, mid, NULL);
1204 
1205  if (newme != me)
1207  return ST_CONTINUE;
1208 }
1209 
1210 void
1212 {
1213  if (!vm_redefinition_check_flag(klass)) return;
1215  (st_data_t)klass);
1216 }
1217 
1218 static void
1219 add_opt_method(VALUE klass, ID mid, VALUE bop)
1220 {
1221  rb_method_entry_t *me;
1222  if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def &&
1223  me->def->type == VM_METHOD_TYPE_CFUNC) {
1225  }
1226  else {
1227  rb_bug("undefined optimized method: %s", rb_id2name(mid));
1228  }
1229 }
1230 
1231 static void
1233 {
1234  ID mid;
1235  VALUE bop;
1236 
1238 
1239 #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0)
1240 #define C(k) add_opt_method(rb_c##k, mid, bop)
1241  OP(PLUS, PLUS), (C(Fixnum), C(Float), C(String), C(Array));
1242  OP(MINUS, MINUS), (C(Fixnum), C(Float));
1243  OP(MULT, MULT), (C(Fixnum), C(Float));
1244  OP(DIV, DIV), (C(Fixnum), C(Float));
1245  OP(MOD, MOD), (C(Fixnum), C(Float));
1246  OP(Eq, EQ), (C(Fixnum), C(Float), C(String));
1247  OP(Eqq, EQQ), (C(Fixnum), C(Bignum), C(Float), C(Symbol), C(String));
1248  OP(LT, LT), (C(Fixnum), C(Float));
1249  OP(LE, LE), (C(Fixnum), C(Float));
1250  OP(GT, GT), (C(Fixnum), C(Float));
1251  OP(GE, GE), (C(Fixnum), C(Float));
1252  OP(LTLT, LTLT), (C(String), C(Array));
1253  OP(AREF, AREF), (C(Array), C(Hash));
1254  OP(ASET, ASET), (C(Array), C(Hash));
1255  OP(Length, LENGTH), (C(Array), C(String), C(Hash));
1256  OP(Size, SIZE), (C(Array), C(String), C(Hash));
1257  OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash));
1258  OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
1259  OP(EqTilde, MATCH), (C(Regexp), C(String));
1260  OP(Freeze, FREEZE), (C(String));
1261 #undef C
1262 #undef OP
1263 }
1264 
1265 /* for vm development */
1266 
1267 #if VMDEBUG
1268 static const char *
1269 vm_frametype_name(const rb_control_frame_t *cfp)
1270 {
1271  switch (VM_FRAME_TYPE(cfp)) {
1272  case VM_FRAME_MAGIC_METHOD: return "method";
1273  case VM_FRAME_MAGIC_BLOCK: return "block";
1274  case VM_FRAME_MAGIC_CLASS: return "class";
1275  case VM_FRAME_MAGIC_TOP: return "top";
1276  case VM_FRAME_MAGIC_CFUNC: return "cfunc";
1277  case VM_FRAME_MAGIC_PROC: return "proc";
1278  case VM_FRAME_MAGIC_IFUNC: return "ifunc";
1279  case VM_FRAME_MAGIC_EVAL: return "eval";
1280  case VM_FRAME_MAGIC_LAMBDA: return "lambda";
1281  case VM_FRAME_MAGIC_RESCUE: return "rescue";
1282  default:
1283  rb_bug("unknown frame");
1284  }
1285 }
1286 #endif
1287 
1288 static void
1289 hook_before_rewind(rb_thread_t *th, rb_control_frame_t *cfp, int will_finish_vm_exec)
1290 {
1291  switch (VM_FRAME_TYPE(th->cfp)) {
1292  case VM_FRAME_MAGIC_METHOD:
1295  break;
1296  case VM_FRAME_MAGIC_BLOCK:
1297  case VM_FRAME_MAGIC_LAMBDA:
1298  if (VM_FRAME_TYPE_BMETHOD_P(th->cfp)) {
1299  EXEC_EVENT_HOOK(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
1300 
1301  if (!will_finish_vm_exec) {
1302  /* kick RUBY_EVENT_RETURN at invoke_block_from_c() for bmethod */
1304  th->cfp->me->called_id,
1305  th->cfp->me->klass, Qnil);
1306  }
1307  }
1308  else {
1310  }
1311  break;
1312  case VM_FRAME_MAGIC_CLASS:
1314  break;
1315  }
1316 }
1317 
1318 /* evaluator body */
1319 
1320 /* finish
1321  VMe (h1) finish
1322  VM finish F1 F2
1323  cfunc finish F1 F2 C1
1324  rb_funcall finish F1 F2 C1
1325  VMe finish F1 F2 C1
1326  VM finish F1 F2 C1 F3
1327 
1328  F1 - F3 : pushed by VM
1329  C1 : pushed by send insn (CFUNC)
1330 
1331  struct CONTROL_FRAME {
1332  VALUE *pc; // cfp[0], program counter
1333  VALUE *sp; // cfp[1], stack pointer
1334  VALUE *bp; // cfp[2], base pointer
1335  rb_iseq_t *iseq; // cfp[3], iseq
1336  VALUE flag; // cfp[4], magic
1337  VALUE self; // cfp[5], self
1338  VALUE *ep; // cfp[6], env pointer
1339  rb_iseq_t * block_iseq; // cfp[7], block iseq
1340  VALUE proc; // cfp[8], always 0
1341  };
1342 
1343  struct BLOCK {
1344  VALUE self;
1345  VALUE *ep;
1346  rb_iseq_t *block_iseq;
1347  VALUE proc;
1348  };
1349 
1350  struct METHOD_CONTROL_FRAME {
1351  rb_control_frame_t frame;
1352  };
1353 
1354  struct METHOD_FRAME {
1355  VALUE arg0;
1356  ...
1357  VALUE argM;
1358  VALUE param0;
1359  ...
1360  VALUE paramN;
1361  VALUE cref;
1362  VALUE special; // lep [1]
1363  struct block_object *block_ptr | 0x01; // lep [0]
1364  };
1365 
1366  struct BLOCK_CONTROL_FRAME {
1367  rb_control_frame_t frame;
1368  };
1369 
1370  struct BLOCK_FRAME {
1371  VALUE arg0;
1372  ...
1373  VALUE argM;
1374  VALUE param0;
1375  ...
1376  VALUE paramN;
1377  VALUE cref;
1378  VALUE *(prev_ptr | 0x01); // ep[0]
1379  };
1380 
1381  struct CLASS_CONTROL_FRAME {
1382  rb_control_frame_t frame;
1383  };
1384 
1385  struct CLASS_FRAME {
1386  VALUE param0;
1387  ...
1388  VALUE paramN;
1389  VALUE cref;
1390  VALUE prev_ep; // for frame jump
1391  };
1392 
1393  struct C_METHOD_CONTROL_FRAME {
1394  VALUE *pc; // 0
1395  VALUE *sp; // stack pointer
1396  VALUE *bp; // base pointer (used in exception)
1397  rb_iseq_t *iseq; // cmi
1398  VALUE magic; // C_METHOD_FRAME
1399  VALUE self; // ?
1400  VALUE *ep; // ep == lep
1401  rb_iseq_t * block_iseq; //
1402  VALUE proc; // always 0
1403  };
1404 
1405  struct C_BLOCK_CONTROL_FRAME {
1406  VALUE *pc; // point only "finish" insn
1407  VALUE *sp; // sp
1408  rb_iseq_t *iseq; // ?
1409  VALUE magic; // C_METHOD_FRAME
1410  VALUE self; // needed?
1411  VALUE *ep; // ep
1412  rb_iseq_t * block_iseq; // 0
1413  };
1414  */
1415 
1416 static VALUE
1418 {
1419  int state;
1420  VALUE result, err;
1421  VALUE initial = 0;
1422 
1423  TH_PUSH_TAG(th);
1424  _tag.retval = Qnil;
1425  if ((state = EXEC_TAG()) == 0) {
1426  vm_loop_start:
1427  result = vm_exec_core(th, initial);
1428  if ((state = th->state) != 0) {
1429  err = result;
1430  th->state = 0;
1431  goto exception_handler;
1432  }
1433  }
1434  else {
1435  int i;
1436  struct iseq_catch_table_entry *entry;
1437  unsigned long epc, cont_pc, cont_sp;
1438  VALUE catch_iseqval;
1439  rb_control_frame_t *cfp;
1440  VALUE type;
1441  VALUE *escape_ep;
1442 
1443  err = th->errinfo;
1444 
1445  exception_handler:
1446  cont_pc = cont_sp = catch_iseqval = 0;
1447 
1448  while (th->cfp->pc == 0 || th->cfp->iseq == 0) {
1450  const rb_method_entry_t *me = th->cfp->me;
1453  }
1455  }
1456 
1457  cfp = th->cfp;
1458  epc = cfp->pc - cfp->iseq->iseq_encoded;
1459 
1460  escape_ep = NULL;
1461  if (state == TAG_BREAK || state == TAG_RETURN) {
1462  escape_ep = GET_THROWOBJ_CATCH_POINT(err);
1463 
1464  if (cfp->ep == escape_ep) {
1465  if (state == TAG_RETURN) {
1466  if (!VM_FRAME_TYPE_FINISH_P(cfp)) {
1467  SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp + 1)->ep);
1468  SET_THROWOBJ_STATE(err, state = TAG_BREAK);
1469  }
1470  else {
1471  for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1472  entry = &cfp->iseq->catch_table[i];
1473  if (entry->start < epc && entry->end >= epc) {
1474  if (entry->type == CATCH_TYPE_ENSURE) {
1475  catch_iseqval = entry->iseq;
1476  cont_pc = entry->cont;
1477  cont_sp = entry->sp;
1478  break;
1479  }
1480  }
1481  }
1482  if (!catch_iseqval) {
1483  th->errinfo = Qnil;
1485  hook_before_rewind(th, th->cfp, TRUE);
1486  vm_pop_frame(th);
1487  goto finish_vme;
1488  }
1489  }
1490  /* through */
1491  }
1492  else {
1493  /* TAG_BREAK */
1494 #if OPT_STACK_CACHING
1495  initial = (GET_THROWOBJ_VAL(err));
1496 #else
1497  *th->cfp->sp++ = (GET_THROWOBJ_VAL(err));
1498 #endif
1499  th->errinfo = Qnil;
1500  goto vm_loop_start;
1501  }
1502  }
1503  }
1504 
1505  if (state == TAG_RAISE) {
1506  for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1507  entry = &cfp->iseq->catch_table[i];
1508  if (entry->start < epc && entry->end >= epc) {
1509 
1510  if (entry->type == CATCH_TYPE_RESCUE ||
1511  entry->type == CATCH_TYPE_ENSURE) {
1512  catch_iseqval = entry->iseq;
1513  cont_pc = entry->cont;
1514  cont_sp = entry->sp;
1515  break;
1516  }
1517  }
1518  }
1519  }
1520  else if (state == TAG_RETRY) {
1521  for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1522  entry = &cfp->iseq->catch_table[i];
1523  if (entry->start < epc && entry->end >= epc) {
1524 
1525  if (entry->type == CATCH_TYPE_ENSURE) {
1526  catch_iseqval = entry->iseq;
1527  cont_pc = entry->cont;
1528  cont_sp = entry->sp;
1529  break;
1530  }
1531  else if (entry->type == CATCH_TYPE_RETRY) {
1532  VALUE *escape_ep;
1533  escape_ep = GET_THROWOBJ_CATCH_POINT(err);
1534  if (cfp->ep == escape_ep) {
1535  cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
1536  th->errinfo = Qnil;
1537  goto vm_loop_start;
1538  }
1539  }
1540  }
1541  }
1542  }
1543  else if (state == TAG_BREAK && ((VALUE)escape_ep & ~0x03) == 0) {
1545 
1546  search_restart_point:
1547  for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1548  entry = &cfp->iseq->catch_table[i];
1549 
1550  if (entry->start < epc && entry->end >= epc) {
1551  if (entry->type == CATCH_TYPE_ENSURE) {
1552  catch_iseqval = entry->iseq;
1553  cont_pc = entry->cont;
1554  cont_sp = entry->sp;
1555  break;
1556  }
1557  else if (entry->type == type) {
1558  cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
1559  cfp->sp = vm_base_ptr(cfp) + entry->sp;
1560 
1561  if (state != TAG_REDO) {
1562 #if OPT_STACK_CACHING
1563  initial = (GET_THROWOBJ_VAL(err));
1564 #else
1565  *th->cfp->sp++ = (GET_THROWOBJ_VAL(err));
1566 #endif
1567  }
1568  th->errinfo = Qnil;
1569  th->state = 0;
1570  goto vm_loop_start;
1571  }
1572  }
1573  }
1574  }
1575  else if (state == TAG_REDO) {
1577  goto search_restart_point;
1578  }
1579  else if (state == TAG_NEXT) {
1581  goto search_restart_point;
1582  }
1583  else {
1584  for (i = 0; i < cfp->iseq->catch_table_size; i++) {
1585  entry = &cfp->iseq->catch_table[i];
1586  if (entry->start < epc && entry->end >= epc) {
1587 
1588  if (entry->type == CATCH_TYPE_ENSURE) {
1589  catch_iseqval = entry->iseq;
1590  cont_pc = entry->cont;
1591  cont_sp = entry->sp;
1592  break;
1593  }
1594  }
1595  }
1596  }
1597 
1598  if (catch_iseqval != 0) {
1599  /* found catch table */
1600  rb_iseq_t *catch_iseq;
1601 
1602  /* enter catch scope */
1603  GetISeqPtr(catch_iseqval, catch_iseq);
1604  cfp->sp = vm_base_ptr(cfp) + cont_sp;
1605  cfp->pc = cfp->iseq->iseq_encoded + cont_pc;
1606 
1607  /* push block frame */
1608  cfp->sp[0] = err;
1609  vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_RESCUE,
1610  cfp->self, cfp->klass,
1611  VM_ENVVAL_PREV_EP_PTR(cfp->ep),
1612  catch_iseq->iseq_encoded,
1613  cfp->sp + 1 /* push value */,
1614  catch_iseq->local_size - 1,
1615  cfp->me, catch_iseq->stack_max);
1616 
1617  state = 0;
1618  th->state = 0;
1619  th->errinfo = Qnil;
1620  goto vm_loop_start;
1621  }
1622  else {
1623  /* skip frame */
1624  hook_before_rewind(th, th->cfp, FALSE);
1625 
1626  if (VM_FRAME_TYPE_FINISH_P(th->cfp)) {
1627  vm_pop_frame(th);
1628  th->errinfo = err;
1629  TH_POP_TAG2();
1630  JUMP_TAG(state);
1631  }
1632  else {
1634  goto exception_handler;
1635  }
1636  }
1637  }
1638  finish_vme:
1639  TH_POP_TAG();
1640  return result;
1641 }
1642 
1643 /* misc */
1644 
1645 VALUE
1647 {
1648  rb_thread_t *th = GET_THREAD();
1649  VALUE val;
1650 
1651  vm_set_top_stack(th, iseqval);
1652 
1653  val = vm_exec(th);
1654  RB_GC_GUARD(iseqval); /* prohibit tail call optimization */
1655  return val;
1656 }
1657 
1658 VALUE
1660 {
1661  rb_thread_t *th = GET_THREAD();
1662  VALUE val;
1663 
1664  vm_set_main_stack(th, iseqval);
1665 
1666  val = vm_exec(th);
1667  RB_GC_GUARD(iseqval); /* prohibit tail call optimization */
1668  return val;
1669 }
1670 
1671 int
1673 {
1674  rb_iseq_t *iseq = cfp->iseq;
1675  if (!iseq && cfp->me) {
1676  if (idp) *idp = cfp->me->def->original_id;
1677  if (klassp) *klassp = cfp->me->klass;
1678  return 1;
1679  }
1680  while (iseq) {
1681  if (RUBY_VM_IFUNC_P(iseq)) {
1682  if (idp) *idp = idIFUNC;
1683  if (klassp) *klassp = 0;
1684  return 1;
1685  }
1686  if (iseq->defined_method_id) {
1687  if (idp) *idp = iseq->defined_method_id;
1688  if (klassp) *klassp = iseq->klass;
1689  return 1;
1690  }
1691  if (iseq->local_iseq == iseq) {
1692  break;
1693  }
1694  iseq = iseq->parent_iseq;
1695  }
1696  return 0;
1697 }
1698 
1699 int
1701 {
1702  return rb_vm_control_frame_id_and_class(th->cfp, idp, klassp);
1703 }
1704 
1705 int
1707 {
1708  return rb_thread_method_id_and_class(GET_THREAD(), idp, klassp);
1709 }
1710 
1711 VALUE
1713 {
1714  const rb_control_frame_t *cfp = th->cfp;
1715  VALUE str = Qnil;
1716 
1717  if (cfp->iseq != 0) {
1718  if (cfp->pc != 0) {
1719  rb_iseq_t *iseq = cfp->iseq;
1720  int line_no = rb_vm_get_sourceline(cfp);
1721  char *file = RSTRING_PTR(iseq->location.path);
1722  str = rb_sprintf("%s:%d:in `%s'",
1723  file, line_no, RSTRING_PTR(iseq->location.label));
1724  }
1725  }
1726  else if (cfp->me->def->original_id) {
1727  str = rb_sprintf("`%s#%s' (cfunc)",
1728  rb_class2name(cfp->me->klass),
1729  rb_id2name(cfp->me->def->original_id));
1730  }
1731 
1732  return str;
1733 }
1734 
1735 VALUE
1737  const rb_block_t *blockptr, VALUE filename)
1738 {
1739  rb_thread_t *th = GET_THREAD();
1740  const rb_control_frame_t *reg_cfp = th->cfp;
1741  volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
1742  VALUE val;
1743 
1745  recv, CLASS_OF(recv), VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1, 0, 0);
1746 
1747  val = (*func)(arg);
1748 
1749  vm_pop_frame(th);
1750  return val;
1751 }
1752 
1753 /* vm */
1754 
1755 static int
1757 {
1758  VALUE thval = (VALUE)key;
1759  rb_gc_mark(thval);
1760  return ST_CONTINUE;
1761 }
1762 
1764 
1765 void
1766 rb_vm_mark(void *ptr)
1767 {
1768  int i;
1769 
1770  RUBY_MARK_ENTER("vm");
1771  RUBY_GC_INFO("-------------------------------------------------\n");
1772  if (ptr) {
1773  rb_vm_t *vm = ptr;
1774  if (vm->living_threads) {
1776  }
1789 
1790  if (vm->loading_table) {
1792  }
1793 
1795 
1796  for (i = 0; i < RUBY_NSIG; i++) {
1797  if (vm->trap_list[i].cmd)
1798  rb_gc_mark(vm->trap_list[i].cmd);
1799  }
1800  if (vm->defined_strings) {
1802  }
1803  }
1804 
1805  RUBY_MARK_LEAVE("vm");
1806 }
1807 
1808 
1809 int
1811 {
1812  rb_vm_t *vm = GET_VM();
1813  if (vm->defined_module_hash) {
1814  rb_hash_aset(vm->defined_module_hash, ID2SYM(id), module);
1815  }
1816  return TRUE;
1817 }
1818 
1819 #define vm_free 0
1820 
1821 int
1823 {
1824  RUBY_FREE_ENTER("vm");
1825  if (vm) {
1826  rb_thread_t *th = vm->main_thread;
1827 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1828  struct rb_objspace *objspace = vm->objspace;
1829 #endif
1831  vm->main_thread = 0;
1832  if (th) {
1834  thread_free(th);
1835  }
1836  if (vm->living_threads) {
1838  vm->living_threads = 0;
1839  }
1841  rb_vm_gvl_destroy(vm);
1842 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1843  if (objspace) {
1844  rb_objspace_free(objspace);
1845  }
1846 #endif
1847  /* after freeing objspace, you *can't* use ruby_xfree() */
1848  ruby_mimfree(vm);
1849  ruby_current_vm = 0;
1850  }
1851  RUBY_FREE_LEAVE("vm");
1852  return 0;
1853 }
1854 
1855 static size_t
1856 vm_memsize(const void *ptr)
1857 {
1858  if (ptr) {
1859  const rb_vm_t *vmobj = ptr;
1860  size_t size = sizeof(rb_vm_t);
1861  if (vmobj->living_threads) {
1862  size += st_memsize(vmobj->living_threads);
1863  }
1864  if (vmobj->defined_strings) {
1865  size += DEFINED_EXPR * sizeof(VALUE);
1866  }
1867  return size;
1868  }
1869  else {
1870  return 0;
1871  }
1872 }
1873 
1875  "VM",
1878 };
1879 
1880 
1881 static VALUE
1883 {
1884  rb_vm_t *vm = GET_VM();
1885  VALUE result = rb_hash_new();
1886 #define SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), SIZET2NUM(vm->default_params.name));
1887  SET(thread_vm_stack_size);
1888  SET(thread_machine_stack_size);
1889  SET(fiber_vm_stack_size);
1890  SET(fiber_machine_stack_size);
1891 #undef SET
1893  return result;
1894 }
1895 
1896 static size_t
1897 get_param(const char *name, size_t default_value, size_t min_value)
1898 {
1899  const char *envval;
1900  size_t result = default_value;
1901  if ((envval = getenv(name)) != 0) {
1902  long val = atol(envval);
1903  if (val < (long)min_value) {
1904  val = (long)min_value;
1905  }
1907  }
1908  if (0) fprintf(stderr, "%s: %"PRIdSIZE"\n", name, result); /* debug print */
1909 
1910  return result;
1911 }
1912 
1913 static void
1915 {
1916 #ifdef PTHREAD_STACK_MIN
1917  size_t size = *sizep;
1918 #endif
1919 
1920 #ifdef __SYMBIAN32__
1921  *sizep = 64 * 1024; /* 64KB: Let's be slightly more frugal on mobile platform */
1922 #endif
1923 
1924 #ifdef PTHREAD_STACK_MIN
1925  if (size < PTHREAD_STACK_MIN) {
1926  *sizep = PTHREAD_STACK_MIN * 2;
1927  }
1928 #endif
1929 }
1930 
1931 static void
1933 {
1935  get_param("RUBY_THREAD_VM_STACK_SIZE",
1938 
1940  get_param("RUBY_THREAD_MACHINE_STACK_SIZE",
1943 
1945  get_param("RUBY_FIBER_VM_STACK_SIZE",
1948 
1950  get_param("RUBY_FIBER_MACHINE_STACK_SIZE",
1953 
1954  /* environment dependent check */
1957 }
1958 
1959 static void
1961 {
1962  MEMZERO(vm, rb_vm_t, 1);
1963  vm->src_encoding_index = -1;
1964  vm->at_exit.basic.flags = (T_ARRAY | RARRAY_EMBED_FLAG) & ~RARRAY_EMBED_LEN_MASK; /* len set 0 */
1965  rb_obj_hide((VALUE)&vm->at_exit);
1966 
1968 }
1969 
1970 /* Thread */
1971 
1972 #define USE_THREAD_DATA_RECYCLE 1
1973 
1974 #if USE_THREAD_DATA_RECYCLE
1975 #define RECYCLE_MAX 64
1978 
1979 static VALUE *
1981 {
1983  /* TODO: check stack size if stack sizes are variable */
1985  }
1986  else {
1987  return ALLOC_N(VALUE, size);
1988  }
1989 }
1990 
1991 #else
1992 #define thread_recycle_stack(size) ALLOC_N(VALUE, (size))
1993 #endif
1994 
1995 void
1997 {
1998 #if USE_THREAD_DATA_RECYCLE
2001  return;
2002  }
2003 #endif
2004  ruby_xfree(stack);
2005 }
2006 
2007 #ifdef USE_THREAD_RECYCLE
2008 static rb_thread_t *
2009 thread_recycle_struct(void)
2010 {
2011  void *p = ALLOC_N(rb_thread_t, 1);
2012  memset(p, 0, sizeof(rb_thread_t));
2013  return p;
2014 }
2015 #endif
2016 
2017 void
2018 rb_thread_mark(void *ptr)
2019 {
2020  rb_thread_t *th = NULL;
2021  RUBY_MARK_ENTER("thread");
2022  if (ptr) {
2023  th = ptr;
2024  if (th->stack) {
2025  VALUE *p = th->stack;
2026  VALUE *sp = th->cfp->sp;
2027  rb_control_frame_t *cfp = th->cfp;
2028  rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);
2029 
2030  while (p < sp) {
2031  rb_gc_mark(*p++);
2032  }
2034 
2035  while (cfp != limit_cfp) {
2036  rb_iseq_t *iseq = cfp->iseq;
2037  rb_gc_mark(cfp->proc);
2038  rb_gc_mark(cfp->self);
2039  rb_gc_mark(cfp->klass);
2040  if (iseq) {
2041  rb_gc_mark(RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq->self : (VALUE)iseq);
2042  }
2043  if (cfp->me) {
2044  /* TODO: marking `me' can be more sophisticated way */
2045  ((rb_method_entry_t *)cfp->me)->mark = 1;
2046  rb_mark_method_entry(cfp->me);
2047  }
2048  cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2049  }
2050  }
2051 
2052  /* mark ruby objects */
2055 
2068 
2070 
2072 
2073  if (GET_THREAD() != th && th->machine.stack_start && th->machine.stack_end) {
2076  (VALUE *)(&th->machine.regs) +
2077  sizeof(th->machine.regs) / sizeof(VALUE));
2078  }
2079 
2081  }
2082 
2083  RUBY_MARK_LEAVE("thread");
2084 }
2085 
2086 static void
2087 thread_free(void *ptr)
2088 {
2089  rb_thread_t *th;
2090  RUBY_FREE_ENTER("thread");
2091 
2092  if (ptr) {
2093  th = ptr;
2094 
2095  if (!th->root_fiber) {
2097  }
2098 
2099  if (th->locking_mutex != Qfalse) {
2100  rb_bug("thread_free: locking_mutex must be NULL (%p:%p)", (void *)th, (void *)th->locking_mutex);
2101  }
2102  if (th->keeping_mutexes != NULL) {
2103  rb_bug("thread_free: keeping_mutexes must be NULL (%p:%p)", (void *)th, (void *)th->keeping_mutexes);
2104  }
2105 
2106  if (th->local_storage) {
2108  }
2109 
2110  if (th->vm && th->vm->main_thread == th) {
2111  RUBY_GC_INFO("main thread\n");
2112  }
2113  else {
2114 #ifdef USE_SIGALTSTACK
2115  if (th->altstack) {
2116  free(th->altstack);
2117  }
2118 #endif
2119  ruby_xfree(ptr);
2120  }
2121  if (ruby_current_thread == th)
2123  }
2124  RUBY_FREE_LEAVE("thread");
2125 }
2126 
2127 static size_t
2128 thread_memsize(const void *ptr)
2129 {
2130  if (ptr) {
2131  const rb_thread_t *th = ptr;
2132  size_t size = sizeof(rb_thread_t);
2133 
2134  if (!th->root_fiber) {
2135  size += th->stack_size * sizeof(VALUE);
2136  }
2137  if (th->local_storage) {
2138  size += st_memsize(th->local_storage);
2139  }
2140  return size;
2141  }
2142  else {
2143  return 0;
2144  }
2145 }
2146 
2147 #define thread_data_type ruby_threadptr_data_type
2149  "VM/thread",
2150  {
2152  thread_free,
2154  },
2156 };
2157 
2158 VALUE
2160 {
2162  return Qtrue;
2163  }
2164  else {
2165  return Qfalse;
2166  }
2167 }
2168 
2169 static VALUE
2171 {
2172  VALUE volatile obj;
2173 #ifdef USE_THREAD_RECYCLE
2174  rb_thread_t *th = thread_recycle_struct();
2175  obj = TypedData_Wrap_Struct(klass, &thread_data_type, th);
2176 #else
2177  rb_thread_t *th;
2179 #endif
2180  return obj;
2181 }
2182 
2183 static void
2185 {
2186  th->self = self;
2187 
2188  /* allocate thread stack */
2189 #ifdef USE_SIGALTSTACK
2190  /* altstack of main thread is reallocated in another place */
2191  th->altstack = malloc(rb_sigaltstack_size());
2192 #endif
2193  /* th->stack_size is word number.
2194  * th->vm->default_params.thread_vm_stack_size is byte size.
2195  */
2196  th->stack_size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE);
2198 
2199  th->cfp = (void *)(th->stack + th->stack_size);
2200 
2201  vm_push_frame(th, 0 /* dummy iseq */, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
2202  Qnil /* dummy self */, Qnil /* dummy klass */, VM_ENVVAL_BLOCK_PTR(0), 0 /* dummy pc */, th->stack, 1, 0, 0);
2203 
2204  th->status = THREAD_RUNNABLE;
2205  th->errinfo = Qnil;
2206  th->last_status = Qnil;
2207  th->waiting_fd = -1;
2208  th->root_svar = Qnil;
2209 
2210 #if OPT_CALL_THREADED_CODE
2211  th->retval = Qundef;
2212 #endif
2213 }
2214 
2215 static VALUE
2217 {
2218  rb_thread_t *th;
2219  rb_vm_t *vm = GET_THREAD()->vm;
2220  GetThreadPtr(self, th);
2221 
2222  th->vm = vm;
2223  th_init(th, self);
2224  rb_ivar_set(self, rb_intern("locals"), rb_hash_new());
2225 
2226  th->top_wrapper = 0;
2227  th->top_self = rb_vm_top_self();
2228  th->root_svar = Qnil;
2229  return self;
2230 }
2231 
2232 VALUE
2234 {
2235  VALUE self = thread_alloc(klass);
2236  ruby_thread_init(self);
2237  return self;
2238 }
2239 
2240 static void
2242  rb_num_t is_singleton, NODE *cref)
2243 {
2244  VALUE klass = cref->nd_clss;
2245  int noex = (int)cref->nd_visi;
2246  rb_iseq_t *miseq;
2247  GetISeqPtr(iseqval, miseq);
2248 
2249  if (miseq->klass) {
2250  RB_GC_GUARD(iseqval) = rb_iseq_clone(iseqval, 0);
2251  GetISeqPtr(iseqval, miseq);
2252  }
2253 
2254  if (NIL_P(klass)) {
2255  rb_raise(rb_eTypeError, "no class/module to add method");
2256  }
2257 
2258  if (is_singleton) {
2259  klass = rb_singleton_class(obj); /* class and frozen checked in this API */
2260  noex = NOEX_PUBLIC;
2261  }
2262 
2263  /* dup */
2264  COPY_CREF(miseq->cref_stack, cref);
2265  miseq->cref_stack->nd_visi = NOEX_PUBLIC;
2266  RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
2267  miseq->defined_method_id = id;
2268  rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
2269 
2270  if (!is_singleton && noex == NOEX_MODFUNC) {
2271  klass = rb_singleton_class(klass);
2272  rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, NOEX_PUBLIC);
2273  }
2274 }
2275 
2276 #define REWIND_CFP(expr) do { \
2277  rb_thread_t *th__ = GET_THREAD(); \
2278  VALUE *const curr_sp = (th__->cfp++)->sp; \
2279  VALUE *const saved_sp = th__->cfp->sp; \
2280  th__->cfp->sp = curr_sp; \
2281  expr; \
2282  (th__->cfp--)->sp = saved_sp; \
2283 } while (0)
2284 
2285 static VALUE
2287 {
2288  REWIND_CFP({
2289  vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 0, rb_vm_cref());
2290  });
2291  return sym;
2292 }
2293 
2294 static VALUE
2296 {
2297  REWIND_CFP({
2298  vm_define_method(GET_THREAD(), cbase, SYM2ID(sym), iseqval, 1, rb_vm_cref());
2299  });
2300  return sym;
2301 }
2302 
2303 static VALUE
2305 {
2306  REWIND_CFP({
2307  rb_alias(cbase, SYM2ID(sym1), SYM2ID(sym2));
2308  });
2309  return Qnil;
2310 }
2311 
2312 static VALUE
2314 {
2315  REWIND_CFP({
2316  rb_alias_variable(SYM2ID(sym1), SYM2ID(sym2));
2317  });
2318  return Qnil;
2319 }
2320 
2321 static VALUE
2323 {
2324  REWIND_CFP({
2325  rb_undef(cbase, SYM2ID(sym));
2327  });
2328  return Qnil;
2329 }
2330 
2331 static VALUE
2333 {
2335  return Qnil;
2336 }
2337 
2339 static VALUE core_hash_from_ary(VALUE ary);
2340 static VALUE core_hash_merge_kwd(int argc, VALUE *argv);
2341 
2342 static VALUE
2344 {
2345  long i;
2346 
2347  assert(argc % 2 == 0);
2348  for (i=0; i<argc; i+=2) {
2349  rb_hash_aset(hash, argv[i], argv[i+1]);
2350  }
2351  return hash;
2352 }
2353 
2354 static VALUE
2356 {
2357  VALUE hash;
2359  return hash;
2360 }
2361 
2362 static VALUE
2364 {
2365  VALUE hash = rb_hash_new();
2366 
2369  }
2370 
2371  return core_hash_merge_ary(hash, ary);
2372 }
2373 
2374 static VALUE
2376 {
2378  return hash;
2379 }
2380 
2381 static VALUE
2383 {
2385  return hash;
2386 }
2387 
2388 static VALUE
2390 {
2391  VALUE hash = argv[0];
2392 
2394 
2395  return hash;
2396 }
2397 
2398 static int
2399 kwmerge_ii(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
2400 {
2401  if (existing) return ST_STOP;
2402  *value = arg;
2403  return ST_CONTINUE;
2404 }
2405 
2406 static int
2408 {
2409  if (!SYMBOL_P(key)) Check_Type(key, T_SYMBOL);
2410  if (st_update(RHASH_TBL_RAW(hash), key, kwmerge_ii, (st_data_t)value) == 0) { /* !existing */
2411  RB_OBJ_WRITTEN(hash, Qundef, value);
2412  }
2413  return ST_CONTINUE;
2414 }
2415 
2416 static int
2418 {
2419  if (!SYMBOL_P(key)) Check_Type(key, T_SYMBOL);
2420  return ST_CONTINUE;
2421 }
2422 
2423 static VALUE
2425 {
2426  VALUE hash;
2428  return hash;
2429 }
2430 
2431 static VALUE
2433 {
2434  VALUE hash, kw;
2435  rb_check_arity(argc, 1, 2);
2436  hash = argv[0];
2437  kw = argv[argc-1];
2438  kw = rb_convert_type(kw, T_HASH, "Hash", "to_hash");
2439  if (argc < 2) hash = kw;
2441  return hash;
2442 }
2443 
2444 extern VALUE *rb_gc_stack_start;
2445 extern size_t rb_gc_stack_maxsize;
2446 #ifdef __ia64
2447 extern VALUE *rb_gc_register_stack_start;
2448 #endif
2449 
2450 /* debug functions */
2451 
2452 /* :nodoc: */
2453 static VALUE
2454 sdr(void)
2455 {
2456  rb_vm_bugreport();
2457  return Qnil;
2458 }
2459 
2460 /* :nodoc: */
2461 static VALUE
2462 nsdr(void)
2463 {
2464  VALUE ary = rb_ary_new();
2465 #if HAVE_BACKTRACE
2466 #include <execinfo.h>
2467 #define MAX_NATIVE_TRACE 1024
2468  static void *trace[MAX_NATIVE_TRACE];
2469  int n = backtrace(trace, MAX_NATIVE_TRACE);
2470  char **syms = backtrace_symbols(trace, n);
2471  int i;
2472 
2473  if (syms == 0) {
2474  rb_memerror();
2475  }
2476 
2477  for (i=0; i<n; i++) {
2478  rb_ary_push(ary, rb_str_new2(syms[i]));
2479  }
2480  free(syms); /* OK */
2481 #endif
2482  return ary;
2483 }
2484 
2485 #if VM_COLLECT_USAGE_DETAILS
2486 static VALUE usage_analysis_insn_stop(VALUE self);
2487 static VALUE usage_analysis_operand_stop(VALUE self);
2488 static VALUE usage_analysis_register_stop(VALUE self);
2489 #endif
2490 
2491 void
2492 Init_VM(void)
2493 {
2494  VALUE opts;
2495  VALUE klass;
2496  VALUE fcore;
2497 
2498  /* ::RubyVM */
2499  rb_cRubyVM = rb_define_class("RubyVM", rb_cObject);
2503 
2504  /* FrozenCore (hidden) */
2505  fcore = rb_class_new(rb_cBasicObject);
2506  RBASIC(fcore)->flags = T_ICLASS;
2507  klass = rb_singleton_class(fcore);
2518  rb_define_method_id(klass, idProc, rb_block_proc, 0);
2519  rb_define_method_id(klass, idLambda, rb_block_lambda, 0);
2520  rb_obj_freeze(fcore);
2521  RBASIC_CLEAR_CLASS(klass);
2522  RCLASS_SET_SUPER(klass, 0);
2523  rb_obj_freeze(klass);
2525  rb_mRubyVMFrozenCore = fcore;
2526 
2527  /* ::RubyVM::Env */
2530  rb_undef_method(CLASS_OF(rb_cEnv), "new");
2531 
2532  /*
2533  * Document-class: Thread
2534  *
2535  * Threads are the Ruby implementation for a concurrent programming model.
2536  *
2537  * Programs that require multiple threads of execution are a perfect
2538  * candidate for Ruby's Thread class.
2539  *
2540  * For example, we can create a new thread separate from the main thread's
2541  * execution using ::new.
2542  *
2543  * thr = Thread.new { puts "Whats the big deal" }
2544  *
2545  * Then we are able to pause the execution of the main thread and allow
2546  * our new thread to finish, using #join:
2547  *
2548  * thr.join #=> "Whats the big deal"
2549  *
2550  * If we don't call +thr.join+ before the main thread terminates, then all
2551  * other threads including +thr+ will be killed.
2552  *
2553  * Alternatively, you can use an array for handling multiple threads at
2554  * once, like in the following example:
2555  *
2556  * threads = []
2557  * threads << Thread.new { puts "Whats the big deal" }
2558  * threads << Thread.new { 3.times { puts "Threads are fun!" } }
2559  *
2560  * After creating a few threads we wait for them all to finish
2561  * consecutively.
2562  *
2563  * threads.each { |thr| thr.join }
2564  *
2565  * === Thread initialization
2566  *
2567  * In order to create new threads, Ruby provides ::new, ::start, and
2568  * ::fork. A block must be provided with each of these methods, otherwise
2569  * a ThreadError will be raised.
2570  *
2571  * When subclassing the Thread class, the +initialize+ method of your
2572  * subclass will be ignored by ::start and ::fork. Otherwise, be sure to
2573  * call super in your +initialize+ method.
2574  *
2575  * === Thread termination
2576  *
2577  * For terminating threads, Ruby provides a variety of ways to do this.
2578  *
2579  * The class method ::kill, is meant to exit a given thread:
2580  *
2581  * thr = Thread.new { ... }
2582  * Thread.kill(thr) # sends exit() to thr
2583  *
2584  * Alternatively, you can use the instance method #exit, or any of its
2585  * aliases #kill or #terminate.
2586  *
2587  * thr.exit
2588  *
2589  * === Thread status
2590  *
2591  * Ruby provides a few instance methods for querying the state of a given
2592  * thread. To get a string with the current thread's state use #status
2593  *
2594  * thr = Thread.new { sleep }
2595  * thr.status # => "sleep"
2596  * thr.exit
2597  * thr.status # => false
2598  *
2599  * You can also use #alive? to tell if the thread is running or sleeping,
2600  * and #stop? if the thread is dead or sleeping.
2601  *
2602  * === Thread variables and scope
2603  *
2604  * Since threads are created with blocks, the same rules apply to other
2605  * Ruby blocks for variable scope. Any local variables created within this
2606  * block are accessible to only this thread.
2607  *
2608  * ==== Fiber-local vs. Thread-local
2609  *
2610  * Each fiber has its own bucket for Thread#[] storage. When you set a
2611  * new fiber-local it is only accessible within this Fiber. To illustrate:
2612  *
2613  * Thread.new {
2614  * Thread.current[:foo] = "bar"
2615  * Fiber.new {
2616  * p Thread.current[:foo] # => nil
2617  * }.resume
2618  * }.join
2619  *
2620  * This example uses #[] for getting and #[]= for setting fiber-locals,
2621  * you can also use #keys to list the fiber-locals for a given
2622  * thread and #key? to check if a fiber-local exists.
2623  *
2624  * When it comes to thread-locals, they are accessible within the entire
2625  * scope of the thread. Given the following example:
2626  *
2627  * Thread.new{
2628  * Thread.current.thread_variable_set(:foo, 1)
2629  * p Thread.current.thread_variable_get(:foo) # => 1
2630  * Fiber.new{
2631  * Thread.current.thread_variable_set(:foo, 2)
2632  * p Thread.current.thread_variable_get(:foo) # => 2
2633  * }.resume
2634  * p Thread.current.thread_variable_get(:foo) # => 2
2635  * }.join
2636  *
2637  * You can see that the thread-local +:foo+ carried over into the fiber
2638  * and was changed to +2+ by the end of the thread.
2639  *
2640  * This example makes use of #thread_variable_set to create new
2641  * thread-locals, and #thread_variable_get to reference them.
2642  *
2643  * There is also #thread_variables to list all thread-locals, and
2644  * #thread_variable? to check if a given thread-local exists.
2645  *
2646  * === Exception handling
2647  *
2648  * Any thread can raise an exception using the #raise instance method,
2649  * which operates similarly to Kernel#raise.
2650  *
2651  * However, it's important to note that an exception that occurs in any
2652  * thread except the main thread depends on #abort_on_exception. This
2653  * option is +false+ by default, meaning that any unhandled exception will
2654  * cause the thread to terminate silently when waited on by either #join
2655  * or #value. You can change this default by either #abort_on_exception=
2656  * +true+ or setting $DEBUG to +true+.
2657  *
2658  * With the addition of the class method ::handle_interrupt, you can now
2659  * handle exceptions asynchronously with threads.
2660  *
2661  * === Scheduling
2662  *
2663  * Ruby provides a few ways to support scheduling threads in your program.
2664  *
2665  * The first way is by using the class method ::stop, to put the current
2666  * running thread to sleep and schedule the execution of another thread.
2667  *
2668  * Once a thread is asleep, you can use the instance method #wakeup to
2669  * mark your thread as eligible for scheduling.
2670  *
2671  * You can also try ::pass, which attempts to pass execution to another
2672  * thread but is dependent on the OS whether a running thread will switch
2673  * or not. The same goes for #priority, which lets you hint to the thread
2674  * scheduler which threads you want to take precedence when passing
2675  * execution. This method is also dependent on the OS and may be ignored
2676  * on some platforms.
2677  *
2678  */
2679  rb_cThread = rb_define_class("Thread", rb_cObject);
2681 
2682 #if VM_COLLECT_USAGE_DETAILS
2683  /* ::RubyVM::USAGE_ANALYSIS_* */
2684 #define define_usage_analysis_hash(name) /* shut up rdoc -C */ \
2685  rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_"#name, rb_hash_new())
2686  define_usage_analysis_hash("INSN");
2687  define_usage_analysis_hash("REGS");
2688  define_usage_analysis_hash("INSN_BIGRAM");
2689 
2690  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_INSN_STOP", usage_analysis_insn_stop, 0);
2691  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_OPERAND_STOP", usage_analysis_operand_stop, 0);
2692  rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_REGISTER_STOP", usage_analysis_register_stop, 0);
2693 #endif
2694 
2695  /* ::RubyVM::OPTS, which shows vm build options */
2696  rb_define_const(rb_cRubyVM, "OPTS", opts = rb_ary_new());
2697 
2698 #if OPT_DIRECT_THREADED_CODE
2699  rb_ary_push(opts, rb_str_new2("direct threaded code"));
2700 #elif OPT_TOKEN_THREADED_CODE
2701  rb_ary_push(opts, rb_str_new2("token threaded code"));
2702 #elif OPT_CALL_THREADED_CODE
2703  rb_ary_push(opts, rb_str_new2("call threaded code"));
2704 #endif
2705 
2706 #if OPT_STACK_CACHING
2707  rb_ary_push(opts, rb_str_new2("stack caching"));
2708 #endif
2709 #if OPT_OPERANDS_UNIFICATION
2710  rb_ary_push(opts, rb_str_new2("operands unification]"));
2711 #endif
2712 #if OPT_INSTRUCTIONS_UNIFICATION
2713  rb_ary_push(opts, rb_str_new2("instructions unification"));
2714 #endif
2715 #if OPT_INLINE_METHOD_CACHE
2716  rb_ary_push(opts, rb_str_new2("inline method cache"));
2717 #endif
2718 #if OPT_BLOCKINLINING
2719  rb_ary_push(opts, rb_str_new2("block inlining"));
2720 #endif
2721 
2722  /* ::RubyVM::INSTRUCTION_NAMES */
2723  rb_define_const(rb_cRubyVM, "INSTRUCTION_NAMES", rb_insns_name_array());
2724 
2725  /* ::RubyVM::DEFAULT_PARAMS
2726  * This constant variable shows VM's default parameters.
2727  * Note that changing these values does not affect VM execution.
2728  * Specification is not stable and you should not depend on this value.
2729  * Of course, this constant is MRI specific.
2730  */
2731  rb_define_const(rb_cRubyVM, "DEFAULT_PARAMS", vm_default_params());
2732 
2733  /* debug functions ::RubyVM::SDR(), ::RubyVM::NSDR() */
2734 #if VMDEBUG
2737 #else
2738  (void)sdr;
2739  (void)nsdr;
2740 #endif
2741 
2742  /* VM bootstrap: phase 2 */
2743  {
2744  rb_vm_t *vm = ruby_current_vm;
2745  rb_thread_t *th = GET_THREAD();
2746  VALUE filename = rb_str_new2("<main>");
2747  volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
2748  volatile VALUE th_self;
2749  rb_iseq_t *iseq;
2750 
2751  /* create vm object */
2753 
2754  /* create main thread */
2755  th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th);
2756  rb_iv_set(th_self, "locals", rb_hash_new());
2757  vm->main_thread = th;
2758  vm->running_thread = th;
2759  th->vm = vm;
2760  th->top_wrapper = 0;
2761  th->top_self = rb_vm_top_self();
2763 
2765  st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id);
2766 
2767  rb_gc_register_mark_object(iseqval);
2768  GetISeqPtr(iseqval, iseq);
2769  th->cfp->iseq = iseq;
2770  th->cfp->pc = iseq->iseq_encoded;
2771  th->cfp->self = th->top_self;
2772  th->cfp->klass = Qnil;
2773 
2774  /*
2775  * The Binding of the top level scope
2776  */
2777  rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new());
2778  }
2780 
2781  /* vm_backtrace.c */
2784 }
2785 
2786 void
2788 {
2789  rb_thread_t *th = GET_VM()->main_thread;
2790  rb_control_frame_t *cfp = (void *)(th->stack + th->stack_size);
2791  --cfp;
2792  RB_OBJ_WRITE(cfp->iseq->self, &cfp->iseq->location.path, filename);
2793 }
2794 
2795 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2796 struct rb_objspace *rb_objspace_alloc(void);
2797 #endif
2798 
2799 void
2801 {
2802  /* VM bootstrap: phase 1 */
2803  rb_vm_t * vm = ruby_mimmalloc(sizeof(*vm));
2804  rb_thread_t * th = ruby_mimmalloc(sizeof(*th));
2805  if (!vm || !th) {
2806  fprintf(stderr, "[FATAL] failed to allocate memory\n");
2807  exit(EXIT_FAILURE);
2808  }
2809  MEMZERO(th, rb_thread_t, 1);
2811 
2812  vm_init2(vm);
2813 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2814  vm->objspace = rb_objspace_alloc();
2815 #endif
2816  ruby_current_vm = vm;
2817 
2819  th->vm = vm;
2820  th_init(th, 0);
2823 }
2824 
2825 /* top self */
2826 
2827 static VALUE
2829 {
2830  return rb_str_new2("main");
2831 }
2832 
2833 VALUE
2835 {
2836  return GET_VM()->top_self;
2837 }
2838 
2839 void
2841 {
2842  rb_vm_t *vm = GET_VM();
2843 
2846  rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s");
2847 
2848  /* initialize mark object array, hash */
2850 }
2851 
2852 VALUE *
2854 {
2855  return &vm->verbose;
2856 }
2857 
2858 VALUE *
2860 {
2861  return &vm->debug;
2862 }
2863 
2864 VALUE *
2866 {
2867  return ruby_vm_verbose_ptr(GET_VM());
2868 }
2869 
2870 VALUE *
2872 {
2873  return ruby_vm_debug_ptr(GET_VM());
2874 }
2875 
2876 /* iseq.c */
2878  VALUE insn, int op_no, VALUE op,
2879  int len, size_t pos, VALUE *pnop, VALUE child);
2880 
2881 #if VM_COLLECT_USAGE_DETAILS
2882 
2883 #define HASH_ASET(h, k, v) rb_hash_aset((h), (st_data_t)(k), (st_data_t)(v))
2884 
2885 /* uh = {
2886  * insn(Fixnum) => ihash(Hash)
2887  * }
2888  * ihash = {
2889  * -1(Fixnum) => count, # insn usage
2890  * 0(Fixnum) => ophash, # operand usage
2891  * }
2892  * ophash = {
2893  * val(interned string) => count(Fixnum)
2894  * }
2895  */
2896 static void
2897 vm_analysis_insn(int insn)
2898 {
2899  ID usage_hash;
2900  ID bigram_hash;
2901  static int prev_insn = -1;
2902 
2903  VALUE uh;
2904  VALUE ihash;
2905  VALUE cv;
2906 
2907  CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
2908  CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
2909  uh = rb_const_get(rb_cRubyVM, usage_hash);
2910  if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
2911  ihash = rb_hash_new();
2912  HASH_ASET(uh, INT2FIX(insn), ihash);
2913  }
2914  if ((cv = rb_hash_aref(ihash, INT2FIX(-1))) == Qnil) {
2915  cv = INT2FIX(0);
2916  }
2917  HASH_ASET(ihash, INT2FIX(-1), INT2FIX(FIX2INT(cv) + 1));
2918 
2919  /* calc bigram */
2920  if (prev_insn != -1) {
2921  VALUE bi;
2922  VALUE ary[2];
2923  VALUE cv;
2924 
2925  ary[0] = INT2FIX(prev_insn);
2926  ary[1] = INT2FIX(insn);
2927  bi = rb_ary_new4(2, &ary[0]);
2928 
2929  uh = rb_const_get(rb_cRubyVM, bigram_hash);
2930  if ((cv = rb_hash_aref(uh, bi)) == Qnil) {
2931  cv = INT2FIX(0);
2932  }
2933  HASH_ASET(uh, bi, INT2FIX(FIX2INT(cv) + 1));
2934  }
2935  prev_insn = insn;
2936 }
2937 
2938 static void
2939 vm_analysis_operand(int insn, int n, VALUE op)
2940 {
2941  ID usage_hash;
2942 
2943  VALUE uh;
2944  VALUE ihash;
2945  VALUE ophash;
2946  VALUE valstr;
2947  VALUE cv;
2948 
2949  CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
2950 
2951  uh = rb_const_get(rb_cRubyVM, usage_hash);
2952  if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
2953  ihash = rb_hash_new();
2954  HASH_ASET(uh, INT2FIX(insn), ihash);
2955  }
2956  if ((ophash = rb_hash_aref(ihash, INT2FIX(n))) == Qnil) {
2957  ophash = rb_hash_new();
2958  HASH_ASET(ihash, INT2FIX(n), ophash);
2959  }
2960  /* intern */
2961  valstr = rb_insn_operand_intern(GET_THREAD()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
2962 
2963  /* set count */
2964  if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) {
2965  cv = INT2FIX(0);
2966  }
2967  HASH_ASET(ophash, valstr, INT2FIX(FIX2INT(cv) + 1));
2968 }
2969 
2970 static void
2971 vm_analysis_register(int reg, int isset)
2972 {
2973  ID usage_hash;
2974  VALUE uh;
2975  VALUE valstr;
2976  static const char regstrs[][5] = {
2977  "pc", /* 0 */
2978  "sp", /* 1 */
2979  "ep", /* 2 */
2980  "cfp", /* 3 */
2981  "self", /* 4 */
2982  "iseq", /* 5 */
2983  };
2984  static const char getsetstr[][4] = {
2985  "get",
2986  "set",
2987  };
2988  static VALUE syms[sizeof(regstrs) / sizeof(regstrs[0])][2];
2989 
2990  VALUE cv;
2991 
2992  CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
2993  if (syms[0] == 0) {
2994  char buff[0x10];
2995  int i;
2996 
2997  for (i = 0; i < (int)(sizeof(regstrs) / sizeof(regstrs[0])); i++) {
2998  int j;
2999  for (j = 0; j < 2; j++) {
3000  snprintf(buff, 0x10, "%d %s %-4s", i, getsetstr[j], regstrs[i]);
3001  syms[i][j] = ID2SYM(rb_intern(buff));
3002  }
3003  }
3004  }
3005  valstr = syms[reg][isset];
3006 
3007  uh = rb_const_get(rb_cRubyVM, usage_hash);
3008  if ((cv = rb_hash_aref(uh, valstr)) == Qnil) {
3009  cv = INT2FIX(0);
3010  }
3011  HASH_ASET(uh, valstr, INT2FIX(FIX2INT(cv) + 1));
3012 }
3013 
3014 #undef HASH_ASET
3015 
3016 void (*ruby_vm_collect_usage_func_insn)(int insn) = vm_analysis_insn;
3017 void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = vm_analysis_operand;
3018 void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = vm_analysis_register;
3019 
3020 /* :nodoc: */
3021 static VALUE
3022 usage_analysis_insn_stop(VALUE self)
3023 {
3025  return Qnil;
3026 }
3027 
3028 /* :nodoc: */
3029 static VALUE
3030 usage_analysis_operand_stop(VALUE self)
3031 {
3033  return Qnil;
3034 }
3035 
3036 /* :nodoc: */
3037 static VALUE
3038 usage_analysis_register_stop(VALUE self)
3039 {
3041  return Qnil;
3042 }
3043 
3044 #else
3045 
3047 void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = NULL;
3048 void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = NULL;
3049 
3050 #endif
3051 
3052 #if VM_COLLECT_USAGE_DETAILS
3053 /* @param insn instruction number */
3054 static void
3055 vm_collect_usage_insn(int insn)
3056 {
3057  if (RUBY_DTRACE_INSN_ENABLED()) {
3058  RUBY_DTRACE_INSN(rb_insns_name(insn));
3059  }
3061  (*ruby_vm_collect_usage_func_insn)(insn);
3062 }
3063 
3064 /* @param insn instruction number
3065  * @param n n-th operand
3066  * @param op operand value
3067  */
3068 static void
3069 vm_collect_usage_operand(int insn, int n, VALUE op)
3070 {
3071  if (RUBY_DTRACE_INSN_OPERAND_ENABLED()) {
3072  VALUE valstr;
3073 
3074  valstr = rb_insn_operand_intern(GET_THREAD()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
3075 
3076  RUBY_DTRACE_INSN_OPERAND(RSTRING_PTR(valstr), rb_insns_name(insn));
3077  RB_GC_GUARD(valstr);
3078  }
3080  (*ruby_vm_collect_usage_func_operand)(insn, n, op);
3081 }
3082 
3083 /* @param reg register id. see code of vm_analysis_register() */
3084 /* @param iseset 0: read, 1: write */
3085 static void
3086 vm_collect_usage_register(int reg, int isset)
3087 {
3089  (*ruby_vm_collect_usage_func_register)(reg, isset);
3090 }
3091 #endif
3092 
static VALUE core_hash_merge_kwd(int argc, VALUE *argv)
Definition: vm.c:2432
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:1591
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2239
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:609
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:760
rb_control_frame_t * cfp
Definition: vm_core.h:531
#define RUBY_EVENT_B_RETURN
Definition: ruby.h:1727
#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:2332
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:2343
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:2087
VALUE expanded_load_path
Definition: vm_core.h:375
NODE * rb_vm_cref(void)
Definition: vm.c:1015
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:1211
VALUE rb_ary_pop(VALUE ary)
Definition: array.c:944
static VALUE make_localjump_error(const char *mesg, VALUE value, int reason)
Definition: vm.c:1062
RUBY_EXTERN VALUE rb_cFloat
Definition: ruby.h:1574
#define RARRAY_LEN(a)
Definition: ruby.h:878
#define RUBY_EVENT_C_RETURN
Definition: ruby.h:1721
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:1810
static size_t vm_memsize(const void *ptr)
Definition: vm.c:1856
#define FALSE
Definition: nkf.h:174
#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
void(* ruby_vm_collect_usage_func_insn)(int insn)
Definition: vm.c:3046
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:1960
#define rb_gc_mark_locations(start, end)
Definition: gc.c:3319
#define RUBY_VM_IFUNC_P(ptr)
Definition: vm_core.h:834
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:815
#define RUBY_EVENT_RETURN
Definition: ruby.h:1719
Definition: st.h:69
#define VM_FRAME_FLAG_FINISH
Definition: vm_core.h:776
VALUE cmd
Definition: vm_core.h:383
st_table * local_storage
Definition: vm_core.h:611
VALUE rb_id2str(ID id)
Definition: ripper.c:17201
Definition: st.h:100
static VALUE m_core_hash_merge_ary(VALUE self, VALUE hash, VALUE ary)
Definition: vm.c:2375
#define VM_FRAME_TYPE_FINISH_P(cfp)
Definition: vm_core.h:778
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:763
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1222
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:519
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1646
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:825
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:853
VALUE top_self
Definition: vm_core.h:371
#define RUBY_VM_NORMAL_ISEQ_P(ptr)
Definition: vm_core.h:835
#define SET_THROWOBJ_STATE(obj, val)
Definition: eval_intern.h:202
static int kwcheck_i(VALUE key, VALUE value, VALUE hash)
Definition: vm.c:2417
#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
Definition: vm_core.h:439
void rb_vm_mark(void *ptr)
Definition: vm.c:1766
#define FLOAT_REDEFINED_OP_FLAG
#define CLASS_OF(v)
Definition: ruby.h:440
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename)
Definition: vm.c:1736
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:1756
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:2322
void rb_fiber_reset_root_local_storage(VALUE thval)
Definition: cont.c:1511
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
void(* ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)
Definition: vm.c:3047
VALUE rb_insns_name_array(void)
Definition: compile.c:5618
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:1048
#define DIV(n, d)
Definition: date_core.c:149
void ruby_mimfree(void *ptr)
Definition: gc.c:6270
VALUE mark_object_ary
Definition: vm_core.h:366
#define RUBY_EVENT_CALL
Definition: ruby.h:1718
VALUE rb_eTypeError
Definition: error.c:548
VALUE * rb_ruby_debug_ptr(void)
Definition: vm.c:2871
#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:900
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
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:538
VALUE rb_backref_get(void)
Definition: vm.c:947
VALUE verbose
Definition: vm_core.h:399
#define VM_ENVVAL_BLOCK_PTR(v)
Definition: vm_core.h:813
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:2612
#define VM_FRAME_MAGIC_METHOD
Definition: vm_core.h:759
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:657
#define Check_Type(v, t)
Definition: ruby.h:532
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
VALUE rb_thread_alloc(VALUE klass)
Definition: vm.c:2233
static rb_control_frame_t * vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm.c:907
#define VM_FRAME_TYPE(cfp)
Definition: vm_core.h:772
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:861
ID called_id
Definition: method.h:101
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2637
static void env_mark(void *const ptr)
Definition: vm.c:350
#define VM_FRAME_MAGIC_IFUNC
Definition: vm_core.h:765
#define RB_GC_GUARD(v)
Definition: ruby.h:523
#define T_HASH
Definition: ruby.h:485
static void hook_before_rewind(rb_thread_t *th, rb_control_frame_t *cfp, int will_finish_vm_exec)
Definition: vm.c:1289
void Init_VM(void)
Definition: vm.c:2492
static int thread_recycle_stack_count
Definition: vm.c:1977
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:1094
size_t stack_max
Definition: vm_core.h:289
#define DATA_PTR(dta)
Definition: ruby.h:992
#define SDR()
Definition: vm_core.h:853
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:3607
#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)
Definition: vm_core.h:831
#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:1976
#define VM_FRAME_MAGIC_RESCUE
Definition: vm_core.h:768
static VALUE vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
Definition: vm.c:919
#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:973
static VALUE lep_svar_get(rb_thread_t *th, VALUE *lep, rb_num_t key)
#define VM_FRAME_FLAG_BMETHOD
Definition: vm_core.h:777
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, const rb_block_t *blockptr)
Definition: vm.c:897
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:1584
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:910
static const rb_data_type_t vm_data_type
Definition: vm.c:1874
#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:1882
static VALUE sdr(void)
Definition: vm.c:2454
static VALUE main_to_s(VALUE obj)
Definition: vm.c:2828
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1497
NODE * rb_vm_cref_in_context(VALUE self)
Definition: vm.c:1027
ID * tbl
Definition: node.h:247
struct rb_thread_struct::@169 machine
VALUE rb_iseq_eval_main(VALUE iseqval)
Definition: vm.c:1659
void rb_mark_method_entry(const rb_method_entry_t *me)
Definition: gc.c:3420
#define RUBY_DTRACE_METHOD_ENTRY_HOOK(th, klass, id)
Definition: probes_helper.h:55
void rb_gc_force_recycle(VALUE p)
Definition: gc.c:4900
#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:1167
#define VM_FRAME_FLAG_PASSED
Definition: vm_core.h:775
#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:273
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
VALUE * stack
Definition: vm_core.h:529
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1619
void Init_top_self(void)
Definition: vm.c:2840
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, VALUE *klassp)
Definition: vm.c:1672
static VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
Definition: vm.c:845
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1672
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:326
#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:2286
#define MEMZERO(p, type, n)
Definition: ruby.h:1359
static rb_serial_t ruby_vm_class_serial
Definition: vm.c:76
void rb_iter_break(void)
Definition: vm.c:1154
RUBY_EXTERN VALUE rb_cBinding
Definition: ruby.h:1564
unsigned short first_lineno
Definition: vm_core.h:730
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:544
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:1700
static void th_init(rb_thread_t *th, VALUE self)
Definition: vm.c:2184
static void add_opt_method(VALUE klass, ID mid, VALUE bop)
Definition: vm.c:1219
const char * rb_insns_name(int i)
Definition: compile.c:5612
#define ALLOC_N(type, n)
Definition: ruby.h:1341
int src_encoding_index
Definition: vm_core.h:397
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1402
#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:1561
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:1159
VALUE rb_block_lambda(void)
Definition: proc.c:634
static void vm_iter_break(rb_thread_t *th, VALUE val)
Definition: vm.c:1143
static VALUE invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, VALUE self, int argc, const VALUE *argv, const rb_block_t *blockptr, const NODE *cref, VALUE defined_class)
Definition: vm.c:767
const rb_data_type_t ruby_threadptr_data_type
Definition: vm.c:2148
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:2787
RUBY_EXTERN VALUE rb_cBasicObject
Definition: ruby.h:1560
VALUE rb_ary_new(void)
Definition: array.c:499
#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:953
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:611
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2228
#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:833
static void check_machine_stack_size(size_t *sizep)
Definition: vm.c:1914
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:2241
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:761
#define Qfalse
Definition: ruby.h:425
static VALUE ruby_thread_init(VALUE self)
Definition: vm.c:2216
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1356
static size_t thread_memsize(const void *ptr)
Definition: vm.c:2128
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:2399
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:4923
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1360
#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:1804
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:1357
ID * local_table
Definition: vm_core.h:235
static VALUE vm_exec(rb_thread_t *th)
Definition: vm.c:1417
#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b)
Definition: vm_core.h:839
VALUE * ruby_vm_debug_ptr(rb_vm_t *vm)
Definition: vm.c:2859
rb_method_entry_t * rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr)
Definition: vm_method.c:617
void rb_thread_mark(void *ptr)
Definition: vm.c:2018
#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:725
#define numberof(array)
Definition: etc.c:602
unsigned long rb_num_t
Definition: vm_core.h:124
void rb_gc_mark_machine_stack(rb_thread_t *th)
Definition: gc.c:3509
void * ruby_mimmalloc(size_t size)
Definition: gc.c:6254
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:1923
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1688
RUBY_EXTERN VALUE rb_cRegexp
Definition: ruby.h:1589
void rb_alias_variable(ID, ID)
Definition: variable.c:869
static VALUE core_hash_from_ary(VALUE ary)
Definition: vm.c:2363
#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:940
static rb_block_t * VM_CF_BLOCK_PTR(rb_control_frame_t *cfp)
Definition: vm.c:52
#define rb_thread_set_current(th)
Definition: vm_core.h:942
#define VM_EP_PREV_EP(ep)
Definition: vm_core.h:818
#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)
VALUE blockprocval
Definition: vm_core.h:729
rb_method_entry_t * rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex)
Definition: vm_method.c:428
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:1039
#define malloc
Definition: ripper.c:96
VALUE rb_hash_new(void)
Definition: hash.c:307
void ruby_xfree(void *x)
Definition: gc.c:6245
static VALUE m_core_define_singleton_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
Definition: vm.c:2295
int rb_is_local_id(ID id)
Definition: ripper.c:17342
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1719
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:1706
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
#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:1101
VALUE rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp)
Definition: vm.c:694
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:2276
#define VM_FRAME_MAGIC_EVAL
Definition: vm_core.h:766
#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:2834
VALUE rb_iseq_eval(VALUE iseqval)
Definition: vm.c:1646
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:2389
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:3522
void Init_native_thread(void)
#define SYMBOL_REDEFINED_OP_FLAG
void rb_alias(VALUE, ID, ID)
Definition: vm_method.c:1255
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:1822
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:5885
VALUE blockprocval
Definition: vm_core.h:704
static VALUE * thread_recycle_stack(size_t size)
Definition: vm.c:1980
#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:762
void rb_iter_break_value(VALUE val)
Definition: vm.c:1160
static VALUE vm_svar_get(VALUE key)
Definition: vm.c:933
#define RUBY_FREE_UNLESS_NULL(ptr)
Definition: gc.h:61
#define VM_FRAME_MAGIC_PROC
Definition: vm_core.h:764
static int kwmerge_i(VALUE key, VALUE value, VALUE hash)
Definition: vm.c:2407
#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:1473
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:1897
unsigned long sp
Definition: iseq.h:68
int size
Definition: encoding.c:49
#define VM_FRAME_MAGIC_LAMBDA
Definition: vm_core.h:767
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:2462
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:959
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:1170
VALUE * stack_start
Definition: vm_core.h:621
void rb_thread_recycle_stack_release(VALUE *stack)
Definition: vm.c:1996
void Init_BareVM(void)
Definition: vm.c:2800
#define thread_data_type
Definition: vm.c:2147
VALUE rb_block_proc(void)
Definition: proc.c:620
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:2865
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:1748
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:706
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:1198
static void vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
Definition: vm.c:926
#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:819
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:2424
void(* ruby_vm_collect_usage_func_register)(int reg, int isset)
Definition: vm.c:3048
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:1717
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:1819
const rb_method_entry_t * passed_bmethod_me
Definition: vm_core.h:545
static VALUE thread_alloc(VALUE klass)
Definition: vm.c:2170
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:1036
#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:17271
static VALUE m_core_set_variable_alias(VALUE self, VALUE sym1, VALUE sym2)
Definition: vm.c:2313
#define VM_FRAME_TYPE_BMETHOD_P(cfp)
Definition: vm_core.h:779
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:2304
struct rb_vm_tag * tag
Definition: vm_core.h:593
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:965
VALUE retval
Definition: vm_core.h:490
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:800
#define CONST_ID(var, str)
Definition: ruby.h:1436
static VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class, int argc, const VALUE *argv, const rb_block_t *blockptr)
Definition: vm.c:869
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1070
#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:1975
VALUE pending_interrupt_queue
Definition: vm_core.h:581
RUBY_EXTERN VALUE rb_cSymbol
Definition: ruby.h:1593
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:987
static VALUE m_core_hash_from_ary(VALUE self, VALUE ary)
Definition: vm.c:2355
#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:1185
VALUE path
Definition: vm_core.h:728
#define env
#define NULL
Definition: _sdbm.c:102
#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:1573
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:1595
void rb_vm_jump_tag_but_local_jump(int state)
Definition: vm.c:1133
#define VM_EP_LEP_P(ep)
Definition: vm_core.h:820
const VALUE label
Definition: vm_core.h:200
#define HASH_REDEFINED_OP_FLAG
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:929
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:2159
static VALUE core_hash_merge_ary(VALUE hash, VALUE ary)
Definition: vm.c:2382
VALUE * ruby_vm_verbose_ptr(rb_vm_t *vm)
Definition: vm.c:2853
VALUE rb_eArgError
Definition: error.c:549
VALUE rb_binding_alloc(VALUE klass)
Definition: proc.c:287
static void vm_init_redefined_flag(void)
Definition: vm.c:1232
#define rb_thread_set_current_raw(th)
Definition: vm_core.h:941
VALUE coverages
Definition: vm_core.h:400
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1221
int rb_sourceline(void)
Definition: vm.c:1001
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:1932
VALUE rb_thread_current_status(const rb_thread_t *th)
Definition: vm.c:1712
#define GET_VM()
Definition: vm_core.h:922