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