25 static inline const VALUE *
26 VM_EP_LEP(
const VALUE *ep)
28 while (!VM_ENV_LOCAL_P(ep)) {
29 ep = VM_ENV_PREV_EP(ep);
61 static inline const VALUE *
64 return VM_EP_LEP(cfp->
ep);
67 static inline const VALUE *
70 return VM_ENV_PREV_EP(cfp->
ep);
77 const VALUE *ep = VM_CF_LEP(cfp);
78 return VM_ENV_BLOCK_HANDLER(ep);
84 return VM_CF_BLOCK_HANDLER(cfp);
95 if (start <= (
VALUE *)cfp && (
VALUE *)cfp < end) {
110 if (start <= ep && ep < end) {
121 if (VM_EP_IN_HEAP_P(ec, ep)) {
139 rb_vm_ep_in_heap_p(
const VALUE *ep)
141 return vm_ep_in_heap_p_(&
GET_THREAD()->ec, ep);
173 vm_block_handler_verify(block_handler);
174 return block_handler;
181 int omod_shared =
FALSE;
191 scope_visi.visi.module_func = module_func;
194 if (prev_cref !=
NULL && prev_cref != (
void *)1 ) {
195 refinements = CREF_REFINEMENTS(prev_cref);
197 if (!
NIL_P(refinements)) {
199 CREF_OMOD_SHARED_SET(prev_cref);
205 if (pushed_by_eval) CREF_PUSHED_BY_EVAL_SET(cref);
206 if (omod_shared) CREF_OMOD_SHARED_SET(cref);
214 return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval,
FALSE);
220 return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval,
TRUE);
226 VALUE klass = CREF_CLASS(cref);
228 rb_cref_t *next_cref = CREF_NEXT(cref), *new_cref;
229 int pushed_by_eval = CREF_PUSHED_BY_EVAL(cref);
233 if (!
NIL_P(CREF_REFINEMENTS(cref))) {
234 CREF_REFINEMENTS_SET(new_cref,
rb_hash_dup(CREF_REFINEMENTS(cref)));
235 CREF_OMOD_SHARED_UNSET(new_cref);
260 vm_cref_dump(
const char *mesg,
const rb_cref_t *cref)
262 fprintf(stderr,
"vm_cref_dump: %s (%p)\n", mesg, cref);
266 cref = CREF_NEXT(cref);
285 #if VM_COLLECT_USAGE_DETAILS 286 static void vm_collect_usage_operand(
int insn,
int n,
VALUE op);
287 static void vm_collect_usage_insn(
int insn);
288 static void vm_collect_usage_register(
int reg,
int isset);
296 int argc,
const VALUE *argv,
VALUE block_handler);
318 #define ruby_vm_redefined_flag GET_VM()->redefined_flag 327 static void thread_free(
void *ptr);
332 ruby_vm_const_missing_count +=1;
348 klass =
RBASIC(klass)->klass;
357 const char *classname, *filename;
361 classname =
"<unknown>";
398 static VALUE sym_global_method_state, sym_global_constant_state, sym_class_serial;
414 if (sym_global_method_state == 0) {
415 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s)) 416 S(global_method_state);
417 S(global_constant_state);
422 #define SET(name, attr) \ 423 if (key == sym_##name) \ 424 return SERIALT2NUM(attr); \ 425 else if (hash != Qnil) \ 426 rb_hash_aset(hash, sym_##name, SERIALT2NUM(attr)); 428 SET(global_method_state, ruby_vm_global_method_state);
429 SET(global_constant_state, ruby_vm_global_constant_state);
430 SET(class_serial, ruby_vm_class_serial);
445 if (iseq->
body->
type != ISEQ_TYPE_TOP) {
452 (
VALUE)vm_cref_new_toplevel(th),
477 vm_set_eval_stack(th, iseq, 0, &bind->
block);
481 vm_bind_update_env(toplevel_binding, bind, vm_make_env_object(th, th->
ec.
cfp));
501 if (VM_FRAME_RUBYFRAME_P(cfp)) {
512 if (VM_FRAME_RUBYFRAME_P(cfp)) {
519 if (VM_FRAME_RUBYFRAME_P(cfp)) {
540 vm_pop_frame(th, cfp, cfp->
ep);
547 while (th->
ec.
cfp != cfp) {
549 printf(
"skipped frame: %s\n", vm_frametype_name(th->
ec.
cfp));
573 ruby_vm_run_at_exit_hooks(
rb_vm_t *vm)
593 fprintf(stderr,
"---\n");
594 fprintf(stderr,
"envptr: %p\n", (
void *)&env->
ep[0]);
595 fprintf(stderr,
"envval: %10p ", (
void *)env->
ep[1]);
597 fprintf(stderr,
"ep: %10p\n", (
void *)env->
ep);
599 fprintf(stderr,
">>\n");
601 fprintf(stderr,
"<<\n");
607 check_env_value(
const rb_env_t *env)
609 if (check_env(env)) {
619 switch (vm_block_handler_type(block_handler)) {
627 *procvalptr = block_handler;
638 const VALUE *
const ep = cfp->
ep;
641 VALUE *env_body, *env_ep;
642 int local_size, env_size;
644 if (VM_ENV_ESCAPED_P(ep)) {
645 return VM_ENV_ENVVAL(ep);
648 if (!VM_ENV_LOCAL_P(ep)) {
649 const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
651 if (!VM_ENV_ESCAPED_P(prev_ep)) {
654 while (prev_cfp->
ep != prev_ep) {
659 vm_make_env_each(th, prev_cfp);
664 VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep);
667 vm_block_handler_escape(th, block_handler, &blockprocval);
672 if (!VM_FRAME_RUBYFRAME_P(cfp)) {
691 env_size = local_size +
693 (blockprocval ? 1 : 0) ;
695 MEMCPY(env_body, ep - (local_size - 1 ),
VALUE, local_size);
698 for (i = 0; i < local_size; i++) {
699 if (VM_FRAME_RUBYFRAME_P(cfp)) {
701 ep[-local_size + i] = 0;
706 env_iseq = VM_FRAME_RUBYFRAME_P(cfp) ? cfp->
iseq :
NULL;
707 env_ep = &env_body[local_size - 1 ];
709 env = vm_env_new(env_ep, env_body, env_size, env_iseq);
711 if (blockprocval)
RB_OBJ_WRITE(env, &env_ep[2], blockprocval);
714 VM_STACK_ENV_WRITE(ep, 0, (
VALUE)env);
721 VALUE envval = vm_make_env_each(th, cfp);
724 check_env_value((
const rb_env_t *)envval);
735 vm_make_env_object(th, cfp);
745 if (VM_ENV_LOCAL_P(ep)) {
749 return VM_ENV_ENVVAL_PTR(VM_ENV_PREV_EP(ep));
768 collect_local_variables_in_iseq(env->
iseq, vars);
775 if (VM_ENV_ESCAPED_P(ep)) {
776 collect_local_variables_in_env(VM_ENV_ENVVAL_PTR(ep), vars);
788 local_var_list_init(&vars);
789 collect_local_variables_in_env(env, &vars);
790 return local_var_list_finish(&vars);
797 local_var_list_init(&vars);
798 while (collect_local_variables_in_iseq(iseq, &vars)) {
801 return local_var_list_finish(&vars);
810 int8_t safe_level, int8_t is_from_method, int8_t is_lambda)
822 vm_block_type_set(&proc->
block, block_type);
834 switch (vm_block_type(src)) {
852 int8_t safe_level, int8_t is_from_method, int8_t is_lambda)
859 vm_block_type_set(&proc->
block, block->
type);
878 if (!VM_ENV_ESCAPED_P(captured->
ep)) {
880 vm_make_env_object(th, cfp);
899 VALUE bindval, envval;
902 if (cfp == 0 || ruby_level_cfp == 0) {
907 envval = vm_make_env_object(th, cfp);
908 if (cfp == ruby_level_cfp) {
916 vm_bind_update_env(bindval, bind, envval);
929 VALUE path = pathobj_path(pathobj);
930 VALUE realpath = pathobj_realpath(pathobj);
936 ID minibuf[4], *dyns = minibuf;
939 if (dyncount < 0)
return 0;
941 base_block = &bind->
block;
942 base_iseq = vm_block_iseq(base_block);
947 MEMCPY(dyns + 1, dynvars,
ID, dyncount);
960 vm_set_eval_stack(th, iseq, 0, base_block);
961 vm_bind_update_env(bindval, bind, envval = vm_make_env_object(th, th->
ec.
cfp));
1025 for (i=0; i<
argc; i++) {
1029 opt_pc = vm_yield_setup_args(th, iseq, argc, sp, passed_block_handler,
1034 return invoke_block(th, iseq,
self, captured, cref, type, opt_pc);
1037 return invoke_bmethod(th, iseq,
self, captured, me, type, opt_pc);
1043 int argc,
const VALUE *argv,
1045 int is_lambda,
int force_blockarg)
1048 switch (vm_block_handler_type(block_handler)) {
1052 return invoke_iseq_block_from_c(th, captured, captured->
self,
1053 argc, argv, passed_block_handler,
1057 return vm_yield_with_cfunc(th, VM_BH_TO_IFUNC_BLOCK(block_handler),
1058 VM_BH_TO_IFUNC_BLOCK(block_handler)->
self,
1059 argc, argv, passed_block_handler);
1061 return vm_yield_with_symbol(th, VM_BH_TO_SYMBOL(block_handler),
1062 argc, argv, passed_block_handler);
1064 if (force_blockarg ==
FALSE) {
1065 is_lambda = block_proc_is_lambda(VM_BH_TO_PROC(block_handler));
1067 block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
1077 VALUE block_handler = VM_CF_BLOCK_HANDLER(th->
ec.
cfp);
1078 vm_block_handler_verify(block_handler);
1083 return block_handler;
1089 return invoke_block_from_c_bh(th, check_block_handler(th),
1091 cref, is_lambda,
FALSE);
1097 return invoke_block_from_c_bh(th, check_block_handler(th),
1105 return invoke_block_from_c_bh(th, check_block_handler(th),
1106 argc, argv, block_handler,
1113 return invoke_block_from_c_bh(th, check_block_handler(th), 1, &args,
1120 VALUE passed_block_handler,
int is_lambda)
1125 switch (vm_block_type(block)) {
1127 return invoke_iseq_block_from_c(th, &block->
as.
captured,
self, argc, argv, passed_block_handler,
NULL, is_lambda);
1129 return vm_yield_with_cfunc(th, &block->
as.
captured,
self, argc, argv, passed_block_handler);
1131 return vm_yield_with_symbol(th, block->
as.
symbol, argc, argv, passed_block_handler);
1133 is_lambda = block_proc_is_lambda(block->
as.
proc);
1134 block = vm_proc_block(block->
as.
proc);
1143 int argc,
const VALUE *argv,
VALUE passed_block_handler)
1152 val = invoke_block_from_c_proc(th, proc,
self, argc, argv, passed_block_handler, proc->
is_lambda);
1166 int argc,
const VALUE *argv,
VALUE block_handler)
1168 return invoke_block_from_c_proc(th, proc,
self, argc, argv, block_handler,
TRUE);
1173 int argc,
const VALUE *argv,
VALUE passed_block_handler)
1176 vm_block_handler_verify(passed_block_handler);
1179 return vm_invoke_bmethod(th, proc,
self, argc, argv, passed_block_handler);
1182 return vm_invoke_proc(th, proc,
self, argc, argv, passed_block_handler);
1191 while (cfp->
pc == 0) {
1203 cfp = vm_normal_frame(th, cfp);
1204 return lep_svar_get(th, cfp ? VM_CF_LEP(cfp) : 0, key);
1210 cfp = vm_normal_frame(th, cfp);
1211 lep_svar_set(th, cfp ? VM_CF_LEP(cfp) : 0, key, val);
1215 vm_svar_get(
VALUE key)
1218 return vm_cfp_svar_get(th, th->
ec.
cfp, key);
1225 vm_cfp_svar_set(th, th->
ec.
cfp, key, val);
1307 if (pline) *pline = 0;
1316 if (!path)
return 0;
1330 return rb_vm_get_cref(cfp->
ep);
1338 rb_cref_t *cref = vm_cref_replace_with_duplicated_cref(cfp->
ep);
1348 if (cfp->
self !=
self)
return NULL;
1349 if (!vm_env_cref_by_cref(cfp->
ep))
return NULL;
1350 cref = rb_vm_get_cref(cfp->
ep);
1351 if (CREF_CLASS(cref) != cbase)
return NULL;
1360 dp(CREF_CLASS(cref));
1361 printf(
"%ld\n", CREF_VISI(cref));
1362 cref = CREF_NEXT(cref);
1376 return vm_get_cbase(cfp->
ep);
1382 make_localjump_error(
const char *mesg,
VALUE value,
int reason)
1416 VALUE exc = make_localjump_error(mesg, value, reason);
1427 mesg =
"unexpected return";
1430 mesg =
"unexpected break";
1433 mesg =
"unexpected next";
1436 mesg =
"unexpected redo";
1440 mesg =
"retry outside of rescue clause";
1449 return make_localjump_error(mesg, val, state);
1454 rb_vm_jump_tag_but_local_jump(
int state)
1467 while (VM_ENV_LOCAL_P(cfp->
ep)) {
1477 const VALUE *ep = VM_CF_PREV_EP(cfp);
1504 static st_table *vm_opt_method_table = 0;
1507 vm_redefinition_check_flag(
VALUE klass)
1532 int flag = vm_redefinition_check_flag(klass);
1540 check_redefined_method(
ID mid,
VALUE value,
void *data)
1546 if (newme != me) rb_vm_check_redefinition_opt_method(me, me->
owner);
1554 if (!vm_redefinition_check_flag(klass))
return;
1572 vm_init_redefined_flag(
void)
1579 #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0) 1580 #define C(k) add_opt_method(rb_c##k, mid, bop) 1581 OP(PLUS, PLUS), (
C(Integer),
C(Float),
C(String),
C(Array));
1582 OP(MINUS, MINUS), (
C(Integer),
C(Float));
1583 OP(MULT, MULT), (
C(Integer),
C(Float));
1586 OP(Eq, EQ), (
C(Integer),
C(Float),
C(String),
C(Symbol));
1587 OP(Eqq, EQQ), (
C(Integer),
C(Float),
C(Symbol),
C(String),
1588 C(NilClass),
C(TrueClass),
C(FalseClass));
1589 OP(LT, LT), (
C(Integer),
C(Float));
1590 OP(LE, LE), (
C(Integer),
C(Float));
1591 OP(GT, GT), (
C(Integer),
C(Float));
1592 OP(GE, GE), (
C(Integer),
C(Float));
1593 OP(LTLT, LTLT), (
C(String),
C(Array));
1595 OP(ASET, ASET), (
C(Array),
C(Hash));
1596 OP(Length, LENGTH), (
C(Array),
C(String),
C(Hash));
1597 OP(Size, SIZE), (
C(Array),
C(String),
C(Hash));
1598 OP(EmptyP, EMPTY_P), (
C(Array),
C(String),
C(Hash));
1599 OP(Succ, SUCC), (
C(Integer),
C(String),
C(Time));
1601 OP(Freeze, FREEZE), (
C(String));
1602 OP(UMinus, UMINUS), (
C(String));
1615 switch (VM_FRAME_TYPE(cfp)) {
1635 THROW_DATA_CONSUMED_P(err) ==
FALSE) {
1636 return THROW_DATA_VAL(err);
1648 unsigned long type = VM_FRAME_TYPE(cfp);
1649 #define C(t) if (type == VM_FRAME_MAGIC_##t) return #t 1672 switch (VM_FRAME_TYPE(th->
ec.
cfp)) {
1676 THROW_DATA_CONSUMED_SET(err);
1679 if (VM_FRAME_BMETHOD_P(th->
ec.
cfp)) {
1682 if (!will_finish_vm_exec) {
1688 frame_return_value(err));
1690 THROW_DATA_CONSUMED_SET(err);
1694 THROW_DATA_CONSUMED_SET(err);
1795 result = vm_exec_core(th, initial);
1797 if ((state = _tag.state) !=
TAG_NONE) {
1800 goto exception_handler;
1806 const struct iseq_catch_table *ct;
1807 unsigned long epc, cont_pc, cont_sp;
1817 cont_pc = cont_sp = 0;
1838 escape_cfp = THROW_DATA_CATCH_FRAME(err);
1840 if (cfp == escape_cfp) {
1842 if (!VM_FRAME_FINISHED_P(cfp)) {
1843 THROW_DATA_CATCH_FRAME_SET(err, cfp + 1);
1844 THROW_DATA_STATE_SET(err, state =
TAG_BREAK);
1848 if (ct)
for (i = 0; i < ct->size; i++) {
1849 entry = &ct->entries[i];
1850 if (entry->
start < epc && entry->
end >= epc) {
1851 if (entry->
type == CATCH_TYPE_ENSURE) {
1852 catch_iseq = entry->
iseq;
1853 cont_pc = entry->
cont;
1854 cont_sp = entry->
sp;
1859 if (catch_iseq ==
NULL) {
1861 result = THROW_DATA_VAL(err);
1862 THROW_DATA_CATCH_FRAME_SET(err, cfp + 1);
1863 hook_before_rewind(th, th->
ec.
cfp,
TRUE, state, err);
1872 #if OPT_STACK_CACHING 1873 initial = THROW_DATA_VAL(err);
1875 *th->
ec.
cfp->
sp++ = THROW_DATA_VAL(err);
1885 if (ct)
for (i = 0; i < ct->size; i++) {
1886 entry = &ct->entries[i];
1887 if (entry->
start < epc && entry->
end >= epc) {
1889 if (entry->
type == CATCH_TYPE_RESCUE ||
1890 entry->
type == CATCH_TYPE_ENSURE) {
1891 catch_iseq = entry->
iseq;
1892 cont_pc = entry->
cont;
1893 cont_sp = entry->
sp;
1901 if (ct)
for (i = 0; i < ct->size; i++) {
1902 entry = &ct->entries[i];
1903 if (entry->
start < epc && entry->
end >= epc) {
1905 if (entry->
type == CATCH_TYPE_ENSURE) {
1906 catch_iseq = entry->
iseq;
1907 cont_pc = entry->
cont;
1908 cont_sp = entry->
sp;
1911 else if (entry->
type == CATCH_TYPE_RETRY) {
1913 escape_cfp = THROW_DATA_CATCH_FRAME(err);
1914 if (cfp == escape_cfp) {
1923 else if (state ==
TAG_BREAK && !escape_cfp) {
1924 type = CATCH_TYPE_BREAK;
1926 search_restart_point:
1928 if (ct)
for (i = 0; i < ct->size; i++) {
1929 entry = &ct->entries[i];
1931 if (entry->
start < epc && entry->
end >= epc) {
1932 if (entry->
type == CATCH_TYPE_ENSURE) {
1933 catch_iseq = entry->
iseq;
1934 cont_pc = entry->
cont;
1935 cont_sp = entry->
sp;
1938 else if (entry->
type == type) {
1940 cfp->
sp = vm_base_ptr(cfp) + entry->
sp;
1943 #if OPT_STACK_CACHING 1944 initial = THROW_DATA_VAL(err);
1946 *th->
ec.
cfp->
sp++ = THROW_DATA_VAL(err);
1957 type = CATCH_TYPE_REDO;
1958 goto search_restart_point;
1961 type = CATCH_TYPE_NEXT;
1962 goto search_restart_point;
1966 if (ct)
for (i = 0; i < ct->size; i++) {
1967 entry = &ct->entries[i];
1968 if (entry->
start < epc && entry->
end >= epc) {
1970 if (entry->
type == CATCH_TYPE_ENSURE) {
1971 catch_iseq = entry->
iseq;
1972 cont_pc = entry->
cont;
1973 cont_sp = entry->
sp;
1980 if (catch_iseq !=
NULL) {
1982 const int arg_size = 1;
1984 rb_iseq_check(catch_iseq);
1985 cfp->
sp = vm_base_ptr(cfp) + cont_sp;
1995 cfp->
sp + arg_size ,
2005 hook_before_rewind(th, th->
ec.
cfp,
FALSE, state, err);
2007 if (VM_FRAME_FINISHED_P(th->
ec.
cfp)) {
2015 goto exception_handler;
2031 vm_set_top_stack(th, iseq);
2042 vm_set_main_stack(th, iseq);
2053 if (idp) *idp = me->
def->original_id;
2054 if (called_idp) *called_idp = me->
called_id;
2055 if (klassp) *klassp = me->
owner;
2082 if (cfp->
iseq != 0) {
2109 recv, block_handler,
2110 (
VALUE)vm_cref_new_toplevel(th),
2111 0, reg_cfp->
sp, 0, 0);
2127 RUBY_GC_INFO(
"-------------------------------------------------\n");
2159 #undef rb_vm_register_special_exception 2201 rb_vm_living_threads_init(vm);
2202 ruby_vm_run_at_exit_hooks(vm);
2218 ruby_current_vm = 0;
2225 vm_memsize(
const void *ptr)
2246 vm_default_params(
void)
2250 #define SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), SIZET2NUM(vm->default_params.name)); 2251 SET(thread_vm_stack_size);
2252 SET(thread_machine_stack_size);
2253 SET(fiber_vm_stack_size);
2254 SET(fiber_machine_stack_size);
2261 get_param(
const char *
name,
size_t default_value,
size_t min_value)
2264 size_t result = default_value;
2265 if ((envval =
getenv(name)) != 0) {
2266 long val = atol(envval);
2267 if (val < (
long)min_value) {
2268 val = (long)min_value;
2272 if (0) fprintf(stderr,
"%s: %"PRIuSIZE"\n", name, result);
2278 check_machine_stack_size(
size_t *sizep)
2280 #ifdef PTHREAD_STACK_MIN 2281 size_t size = *sizep;
2284 #ifdef PTHREAD_STACK_MIN 2285 if (size < PTHREAD_STACK_MIN) {
2286 *sizep = PTHREAD_STACK_MIN * 2;
2292 vm_default_params_setup(
rb_vm_t *vm)
2295 get_param(
"RUBY_THREAD_VM_STACK_SIZE",
2300 get_param(
"RUBY_THREAD_MACHINE_STACK_SIZE",
2305 get_param(
"RUBY_FIBER_VM_STACK_SIZE",
2310 get_param(
"RUBY_FIBER_MACHINE_STACK_SIZE",
2323 rb_vm_living_threads_init(vm);
2326 vm_default_params_setup(vm);
2331 #define USE_THREAD_DATA_RECYCLE 1 2333 #if USE_THREAD_DATA_RECYCLE 2334 #define RECYCLE_MAX 64 2336 static int thread_recycle_stack_count = 0;
2339 thread_recycle_stack(
size_t size)
2341 if (thread_recycle_stack_count > 0) {
2343 return thread_recycle_stack_slot[--thread_recycle_stack_count];
2351 #define thread_recycle_stack(size) ALLOC_N(VALUE, (size)) 2359 #if USE_THREAD_DATA_RECYCLE 2361 thread_recycle_stack_slot[thread_recycle_stack_count++] = stack;
2382 while (cfp != limit_cfp) {
2383 #if VM_CHECK_MODE > 0 2441 thread_free(
void *ptr)
2452 rb_bug(
"thread_free: locking_mutex must be NULL (%p:%p)", (
void *)th, (
void *)th->
locking_mutex);
2455 rb_bug(
"thread_free: keeping_mutexes must be NULL (%p:%p)", (
void *)th, (
void *)th->
keeping_mutexes);
2466 #ifdef USE_SIGALTSTACK 2473 if (ruby_current_thread == th)
2474 ruby_current_thread =
NULL;
2480 thread_memsize(
const void *ptr)
2494 #define thread_data_type ruby_threadptr_data_type 2502 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2517 thread_alloc(
VALUE klass)
2532 #ifdef USE_SIGALTSTACK 2555 #ifdef NON_SCALAR_THREAD_ID 2556 th->thread_id_string[0] =
'\0';
2559 #if OPT_CALL_THREADED_CODE 2566 ruby_thread_init(
VALUE self)
2584 VALUE self = thread_alloc(klass);
2585 ruby_thread_init(
self);
2596 if (!is_singleton) {
2597 klass = CREF_CLASS(cref);
2598 visi = rb_scope_visibility_get();
2611 if (!is_singleton && rb_scope_module_func_check()) {
2617 #define REWIND_CFP(expr) do { \ 2618 rb_thread_t *th__ = GET_THREAD(); \ 2619 VALUE *const curr_sp = (th__->ec.cfp++)->sp; \ 2620 VALUE *const saved_sp = th__->ec.cfp->sp; \ 2621 th__->ec.cfp->sp = curr_sp; \ 2623 (th__->ec.cfp--)->sp = saved_sp; \ 2673 m_core_set_postexe(
VALUE self)
2681 static VALUE core_hash_merge_kwd(
int argc,
VALUE *argv);
2684 core_hash_merge(
VALUE hash,
long argc,
const VALUE *argv)
2701 core_hash_from_ary(
VALUE ary)
2706 return core_hash_merge_ary(hash, ary);
2727 m_core_hash_merge_ptr(
int argc,
VALUE *argv,
VALUE recv)
2729 VALUE hash = argv[0];
2731 REWIND_CFP(core_hash_merge(hash, argc-1, argv+1));
2752 m_core_hash_merge_kwd(
int argc,
VALUE *argv,
VALUE recv)
2755 REWIND_CFP(hash = core_hash_merge_kwd(argc, argv));
2760 core_hash_merge_kwd(
int argc,
VALUE *argv)
2767 if (argc < 2) hash = kw;
2775 extern VALUE *rb_gc_register_stack_start;
2794 #include <execinfo.h> 2795 #define MAX_NATIVE_TRACE 1024 2796 static void *trace[MAX_NATIVE_TRACE];
2797 int n = (int)backtrace(trace, MAX_NATIVE_TRACE);
2798 char **syms = backtrace_symbols(trace, n);
2805 for (i=0; i<n; i++) {
2813 #if VM_COLLECT_USAGE_DETAILS 2814 static VALUE usage_analysis_insn_stop(
VALUE self);
2815 static VALUE usage_analysis_operand_stop(
VALUE self);
2816 static VALUE usage_analysis_register_stop(
VALUE self);
2854 rb_mRubyVMFrozenCore = fcore;
3006 #if VM_COLLECT_USAGE_DETAILS 3008 #define define_usage_analysis_hash(name) \ 3009 rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_" #name, rb_hash_new()) 3010 define_usage_analysis_hash(
INSN);
3011 define_usage_analysis_hash(REGS);
3012 define_usage_analysis_hash(INSN_BIGRAM);
3022 #if OPT_DIRECT_THREADED_CODE 3024 #elif OPT_TOKEN_THREADED_CODE 3026 #elif OPT_CALL_THREADED_CODE 3030 #if OPT_STACK_CACHING 3033 #if OPT_OPERANDS_UNIFICATION 3036 #if OPT_INSTRUCTIONS_UNIFICATION 3039 #if OPT_INLINE_METHOD_CACHE 3042 #if OPT_BLOCKINLINING 3072 volatile VALUE th_self;
3087 rb_vm_living_threads_insert(vm, th);
3091 th->
ec.
cfp->
pc = iseq->body->iseq_encoded;
3102 vm_init_redefined_flag();
3128 fprintf(stderr,
"[FATAL] failed to allocate memory\n");
3136 ruby_current_vm = vm;
3160 main_to_s(
VALUE obj)
3168 return GET_VM()->top_self;
3182 ruby_vm_verbose_ptr(
rb_vm_t *vm)
3188 ruby_vm_debug_ptr(
rb_vm_t *vm)
3196 return ruby_vm_verbose_ptr(
GET_VM());
3202 return ruby_vm_debug_ptr(
GET_VM());
3213 return GET_VM()->frozen_strings;
3216 #if VM_COLLECT_USAGE_DETAILS 3218 #define HASH_ASET(h, k, v) rb_hash_aset((h), (st_data_t)(k), (st_data_t)(v)) 3232 vm_analysis_insn(
int insn)
3236 static int prev_insn = -1;
3242 CONST_ID(usage_hash,
"USAGE_ANALYSIS_INSN");
3243 CONST_ID(bigram_hash,
"USAGE_ANALYSIS_INSN_BIGRAM");
3247 HASH_ASET(uh,
INT2FIX(insn), ihash);
3255 if (prev_insn != -1) {
3274 vm_analysis_operand(
int insn,
int n,
VALUE op)
3284 CONST_ID(usage_hash,
"USAGE_ANALYSIS_INSN");
3289 HASH_ASET(uh,
INT2FIX(insn), ihash);
3293 HASH_ASET(ihash,
INT2FIX(n), ophash);
3306 vm_analysis_register(
int reg,
int isset)
3311 static const char regstrs[][5] = {
3319 static const char getsetstr[][4] = {
3323 static VALUE syms[
sizeof(regstrs) /
sizeof(regstrs[0])][2];
3327 CONST_ID(usage_hash,
"USAGE_ANALYSIS_REGS");
3332 for (i = 0; i < (int)(
sizeof(regstrs) /
sizeof(regstrs[0])); i++) {
3334 for (j = 0; j < 2; j++) {
3335 snprintf(buff, 0x10,
"%d %s %-4s", i, getsetstr[j], regstrs[i]);
3340 valstr = syms[reg][isset];
3357 usage_analysis_insn_stop(
VALUE self)
3365 usage_analysis_operand_stop(
VALUE self)
3373 usage_analysis_register_stop(
VALUE self)
3387 #if VM_COLLECT_USAGE_DETAILS 3390 vm_collect_usage_insn(
int insn)
3392 if (RUBY_DTRACE_INSN_ENABLED()) {
3396 (*ruby_vm_collect_usage_func_insn)(insn);
3404 vm_collect_usage_operand(
int insn,
int n,
VALUE op)
3406 if (RUBY_DTRACE_INSN_OPERAND_ENABLED()) {
3415 (*ruby_vm_collect_usage_func_operand)(insn, n, op);
3421 vm_collect_usage_register(
int reg,
int isset)
3424 (*ruby_vm_collect_usage_func_register)(reg, isset);
3428 #include "vm_call_iseq_optimized.inc" RUBY_EXTERN VALUE rb_cString
void rb_define_global_const(const char *, VALUE)
#define RBASIC_CLEAR_CLASS(obj)
#define RUBY_VM_THREAD_MACHINE_STACK_SIZE
#define RUBY_ASSERT_MESG(expr, mesg)
#define RUBY_EVENT_B_RETURN
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_thread_t *th, const rb_control_frame_t *cfp)
void rb_hash_bulk_insert(long, const VALUE *, VALUE)
#define VM_DEBUG_BP_CHECK
#define NEXT_CLASS_SERIAL()
rb_serial_t ruby_vm_global_constant_state
VALUE rb_proc_alloc(VALUE klass)
void rb_vm_check_redefinition_by_prepend(VALUE klass)
void rb_bug(const char *fmt,...)
RUBY_EXTERN VALUE rb_cFalseClass
RUBY_EXTERN VALUE rb_cFloat
#define RUBY_EVENT_C_RETURN
VALUE passed_block_handler
#define RUBY_TYPED_FREE_IMMEDIATELY
void(* ruby_vm_collect_usage_func_insn)(int insn)
VALUE ruby_vm_const_missing_count
struct rb_thread_struct * running_thread
#define RUBY_DTRACE_METHOD_RETURN_HOOK(th, klass, id)
void rb_objspace_free(rb_objspace_t *objspace)
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
#define RUBY_EVENT_RETURN
void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
VALUE rb_hash_dup(VALUE hash)
#define RB_OBJ_WRITTEN(a, oldv, b)
void rb_undef_alloc_func(VALUE)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
VALUE local_storage_recursive_hash_for_trace
VALUE rb_iseq_eval_main(const rb_iseq_t *iseq)
#define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN
void rb_vm_mark(void *ptr)
VALUE rb_fstring_cstr(const char *str)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_vm_pop_cfunc_frame(void)
void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE cls, VALUE mesg)
struct rb_method_definition_struct *const def
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
#define TypedData_Wrap_Struct(klass, data_type, sval)
void rb_fiber_reset_root_local_storage(VALUE thval)
VALUE pending_interrupt_mask_stack
void(* ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)
VALUE rb_insns_name_array(void)
const rb_callable_method_entry_t * rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
void ruby_mimfree(void *ptr)
VALUE * rb_ruby_debug_ptr(void)
#define TH_JUMP_TAG(th, st)
#define HASH_REDEFINED_OP_FLAG
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, VALUE passed_block_handler)
VALUE rb_ary_push(VALUE ary, VALUE item)
#define VM_BLOCK_HANDLER_NONE
PUREFUNC(static inline const VALUE *VM_EP_LEP(const VALUE *))
#define RUBY_VM_SIZE_ALIGN
size_t fiber_machine_stack_size
VALUE rb_ary_tmp_new(long capa)
struct rb_iseq_constant_body * body
VALUE rb_backref_get(void)
st_table * frozen_strings
VALUE rb_iv_set(VALUE, const char *, VALUE)
rb_at_exit_list * at_exit
#define VM_TAGGED_PTR_REF(v, mask)
void rb_vm_block_ep_update(VALUE obj, const struct rb_block *dst, const VALUE *ep)
VALUE rb_thread_alloc(VALUE klass)
VALUE rb_insn_operand_intern(const rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, VALUE *pnop, VALUE child)
#define RUBY_MARK_LEAVE(msg)
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
void Init_vm_backtrace(void)
void rb_vm_localjump_error(const char *mesg, VALUE value, int reason)
rb_vm_at_exit_func * func
rb_serial_t rb_next_class_serial(void)
void rb_gc_mark(VALUE ptr)
#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)
VALUE rb_proc_create(VALUE klass, const struct rb_block *block, int8_t safe_level, int8_t is_from_method, int8_t is_lambda)
VALUE rb_sourcefilename(void)
RUBY_EXTERN VALUE rb_cProc
#define RUBY_VM_FIBER_VM_STACK_SIZE
VALUE rb_hash_new_with_size(st_index_t size)
void rb_undef_method(VALUE klass, const char *name)
void rb_gc_mark_locations(const VALUE *start, const VALUE *end)
#define FALSE_REDEFINED_OP_FLAG
#define VM_ENV_DATA_INDEX_ME_CREF
#define RUBY_DTRACE_METHOD_ENTRY_HOOK(th, klass, id)
#define THROW_DATA_P(err)
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
VALUE rb_vm_make_proc(rb_thread_t *th, const struct rb_captured_block *captured, VALUE klass)
enum iseq_catch_table_entry::catch_type type
const VALUE * iseq_encoded
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
void rb_gc_mark_values(long n, const VALUE *values)
rb_cref_t * rb_vm_cref(void)
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
#define RB_TYPE_P(obj, type)
VALUE defined_module_hash
VALUE rb_binding_new(void)
#define MEMZERO(p, type, n)
rb_serial_t ruby_vm_class_serial
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp)
RUBY_EXTERN VALUE rb_cBinding
unsigned short first_lineno
void rb_gc_mark_machine_stack(const rb_execution_context_t *ec)
#define RUBY_VM_THREAD_VM_STACK_SIZE
const char * rb_insns_name(int i)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
const rb_env_t * rb_vm_env_prev_env(const rb_env_t *env)
unsigned int local_table_size
RUBY_EXTERN VALUE rb_cObject
VALUE rb_block_lambda(void)
size_t st_memsize(const st_table *tab)
#define st_init_table_with_size
const rb_data_type_t ruby_threadptr_data_type
size_t fiber_vm_stack_size
VALUE rb_vm_make_proc_lambda(rb_thread_t *th, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda)
#define GetBindingPtr(obj, ptr)
struct rb_vm_struct rb_vm_t
void rb_vm_inc_const_missing_count(void)
void rb_vm_set_progname(VALUE filename)
RUBY_EXTERN VALUE rb_cBasicObject
VALUE rb_proc_create_from_captured(VALUE klass, const struct rb_captured_block *captured, enum rb_block_type block_type, int8_t safe_level, int8_t is_from_method, int8_t is_lambda)
rb_iseq_t * rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
VALUE load_path_check_cache
void rb_vm_block_copy(VALUE obj, const struct rb_block *dst, const struct rb_block *src)
void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
void rb_backref_set(VALUE val)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
RUBY_EXTERN VALUE rb_cTrueClass
#define TRUE_REDEFINED_OP_FLAG
struct rb_method_definition_struct *const def
void rb_define_const(VALUE, const char *, VALUE)
#define RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN
st_table * rb_vm_fstring_table(void)
#define RUBY_MARK_ENTER(msg)
struct st_table * loading_table
#define ALLOCV_N(type, v, n)
const VALUE special_exceptions[ruby_special_error_count]
void ruby_thread_init_stack(rb_thread_t *th)
#define RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, klass, id)
union rb_captured_block::@141 code
#define VM_GUARDED_PREV_EP(ep)
void rb_gc_register_mark_object(VALUE obj)
#define MEMCPY(p1, p2, type, n)
VALUE * rb_gc_stack_start
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename)
rb_iseq_t * rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type type)
int rb_vm_add_root_module(ID id, VALUE module)
void rb_thread_mark(void *ptr)
#define VM_ENV_DATA_INDEX_SPECVAL
#define RUBY_VM_FIBER_MACHINE_STACK_SIZE
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
void * ruby_mimmalloc(size_t size)
void rb_call_end_proc(VALUE data)
VALUE rb_const_get(VALUE, ID)
VALUE local_storage_recursive_hash
rb_hook_list_t event_hooks
#define STRING_REDEFINED_OP_FLAG
void rb_vm_pop_frame(rb_thread_t *th)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
RUBY_EXTERN VALUE rb_cRegexp
void rb_alias_variable(ID, ID)
const VALUE * rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars)
#define RARRAY_CONST_PTR(a)
#define rb_thread_set_current(th)
struct rb_iseq_constant_body::@135 param
parameter information
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
void rb_vm_stack_to_heap(rb_thread_t *th)
struct rb_mutex_struct * keeping_mutexes
VALUE rb_sprintf(const char *format,...)
unsigned long rb_serial_t
struct rb_vm_struct::@139 trap_list
#define RICLASS_IS_ORIGIN
const rb_method_entry_t * rb_method_entry(VALUE klass, ID id)
VALUE rb_class_path(VALUE)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
int rb_frame_method_id_and_class(ID *idp, VALUE *klassp)
VALUE rb_ivar_set(VALUE, ID, VALUE)
size_t thread_vm_stack_size
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
VALUE rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp)
void rb_vm_bugreport(const void *)
void ruby_vm_at_exit(void(*func)(rb_vm_t *))
void rb_clear_method_cache_by_class(VALUE)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
rb_cref_t * rb_vm_cref_new_toplevel(void)
VALUE rb_vm_top_self(void)
#define EXEC_EVENT_HOOK(th_, flag_, self_, id_, called_id_, klass_, data_)
struct rb_thread_struct * main_thread
rb_thread_t * ruby_current_thread
#define REGEXP_REDEFINED_OP_FLAG
RUBY_EXTERN VALUE rb_cInteger
rb_method_visibility_t method_visi
struct rb_at_exit_list * next
void rb_mark_tbl(st_table *tbl)
void Init_native_thread(void)
void rb_alias(VALUE, ID, ID)
VALUE rb_str_concat_literals(size_t, const VALUE *)
const char * rb_id2name(ID)
int rb_sigaltstack_size(void)
int ruby_vm_destruct(rb_vm_t *vm)
const rb_method_entry_t * rb_method_entry_at(VALUE obj, ID id)
enum rb_iseq_constant_body::iseq_type type
#define RUBY_VM_END_CONTROL_FRAME(th)
const rb_callable_method_entry_t * passed_bmethod_me
struct rb_captured_block captured
struct rb_execution_context_struct::@143 machine
void rb_set_end_proc(void(*func)(VALUE), VALUE data)
#define VM_ENV_DATA_INDEX_ENV
register unsigned int len
enum rb_thread_status status
void rb_iter_break_value(VALUE val)
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
VALUE rb_mRubyVMFrozenCore
#define SYMBOL_REDEFINED_OP_FLAG
#define RB_OBJ_WRITE(a, slot, b)
void rb_define_method_id(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc)
VALUE rb_vm_frame_block_handler(const rb_control_frame_t *cfp)
const rb_cref_t * rb_vm_cref_in_context(VALUE self, VALUE cbase)
struct rb_objspace * objspace
rb_vm_t * ruby_current_vm
const VALUE * rb_vm_ep_local_ep(const VALUE *ep)
VALUE rb_lastline_get(void)
const struct iseq_catch_table * catch_table
void rb_thread_recycle_stack_release(VALUE *stack)
#define TIME_REDEFINED_OP_FLAG
VALUE rb_block_proc(void)
NORETURN(static void vm_iter_break(rb_thread_t *th, VALUE val))
VALUE * rb_ruby_verbose_ptr(void)
#define RBASIC_CLASS(obj)
#define RUBY_FREE_LEAVE(msg)
#define rb_thread_raised_reset(th, f)
#define FLOAT_REDEFINED_OP_FLAG
rb_hook_list_t event_hooks
#define RUBY_VM_THREAD_VM_STACK_SIZE_MIN
VALUE rb_hash_aref(VALUE hash, VALUE key)
typedefRUBY_SYMBOL_EXPORT_BEGIN struct re_pattern_buffer Regexp
#define RUBY_FREE_ENTER(msg)
#define EXEC_EVENT_HOOK_AND_POP_FRAME(th_, flag_, self_, id_, called_id_, klass_, data_)
#define RUBY_VM_FIBER_VM_STACK_SIZE_MIN
VALUE rb_class_path_no_cache(VALUE _klass)
const struct rb_block block
#define VM_PROFILE_ATEXIT()
void rb_execution_context_mark(const rb_execution_context_t *ec)
VALUE rb_iseq_eval(const rb_iseq_t *iseq)
rb_event_flag_t ruby_vm_event_flags
void rb_vm_trace_mark_event_hooks(rb_hook_list_t *hooks)
void(* ruby_vm_collect_usage_func_register)(int reg, int isset)
#define RUBY_MARK_UNLESS_NULL(ptr)
size_t thread_machine_stack_size
rb_objspace_t * rb_objspace_alloc(void)
void rb_fiber_mark_self(rb_fiber_t *fib)
VALUE rb_iseq_local_variables(const rb_iseq_t *iseq)
#define INTEGER_REDEFINED_OP_FLAG
#define VM_UNREACHABLE(func)
#define TypedData_Make_Struct(klass, type, data_type, sval)
void rb_vm_at_exit_func(struct rb_vm_struct *)
VALUE rb_iseq_path(const rb_iseq_t *iseq)
VALUE loaded_features_snapshot
size_t rb_gc_stack_maxsize
#define ARRAY_REDEFINED_OP_FLAG
const struct rb_iseq_struct * parent_iseq
rb_cref_t * rb_vm_cref_replace_with_duplicated_cref(void)
rb_execution_context_t ec
int ruby_th_dtrace_setup(rb_thread_t *th, VALUE klass, ID id, struct ruby_dtrace_method_hook_args *args)
#define StringValuePtr(v)
rb_serial_t ruby_vm_global_method_state
struct rb_thread_struct rb_thread_t
const char * rb_source_loc(int *pline)
struct list_head living_threads
void rb_vm_rewind_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
#define RTYPEDDATA_DATA(v)
void rb_vm_gvl_destroy(rb_vm_t *vm)
void rb_lastline_set(VALUE val)
#define NIL_REDEFINED_OP_FLAG
#define CONST_ID(var, str)
rb_id_table_iterator_result
VALUE rb_vm_env_local_variables(const rb_env_t *env)
int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, ID *called_idp, VALUE *klassp)
#define CHECK_VM_STACK_OVERFLOW(cfp, margin)
void Init_vm_objects(void)
VALUE pending_interrupt_queue
RUBY_EXTERN VALUE rb_cSymbol
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
const char * rb_sourcefile(void)
VALUE rb_source_location(int *pline)
const struct rb_block block
RUBY_EXTERN VALUE rb_cTime
VALUE rb_class_new(VALUE super)
Creates a new class.
#define NEW_NODE(t, a0, a1, a2)
struct rb_vm_struct::@140 default_params
VALUE rb_obj_is_thread(VALUE obj)
RUBY_EXTERN VALUE rb_cNilClass
rb_control_frame_t * rb_vm_get_binding_creatable_next_cfp(const rb_thread_t *th, const rb_control_frame_t *cfp)
VALUE rb_binding_alloc(VALUE klass)
#define rb_thread_set_current_raw(th)
#define ruby_vm_redefined_flag
VALUE rb_attr_get(VALUE, ID)
rb_iseq_location_t location
VALUE rb_thread_current_status(const rb_thread_t *th)