diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-07-28 19:13:26 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-07-28 19:13:26 +0000 |
commit | e06698d257cf03e3c42f87029821c077f5f6f0e6 (patch) | |
tree | 62f7990169aa2b7f2b5e54a909eb0aec0ee7e2f8 | |
parent | c3ceb1bff26a0dc59d7b93647e3a58c57e7c0440 (diff) | |
download | ruby-e06698d257cf03e3c42f87029821c077f5f6f0e6.tar.gz |
* vm.c, internal.h: remove RubyVM::Env class and all of env objects
are imemo objects (imemo_env).
* NEWS: describe this change. I believe nobody touch these objects
because there are no method defined.
* vm_core.h: remove the following definitions.
* rb_cEnv decl.
* GetEnvPtr() because Env is no longer T_DATA object.
* vm_core.h (rb_env_t): fix layout for imemo values.
* vm_core.h (vm_assert_env): added.
* vm_core.h (vm_env_new): added.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55768 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | gc.c | 125 | ||||
-rw-r--r-- | internal.h | 16 | ||||
-rw-r--r-- | proc.c | 81 | ||||
-rw-r--r-- | vm.c | 172 | ||||
-rw-r--r-- | vm_core.h | 52 | ||||
-rw-r--r-- | vm_dump.c | 17 | ||||
-rw-r--r-- | vm_insnhelper.c | 2 |
9 files changed, 215 insertions, 272 deletions
@@ -1,3 +1,21 @@ +Fri Jul 29 03:49:04 2016 Koichi Sasada <ko1@atdot.net> + + * vm.c, internal.h: remove RubyVM::Env class and all of env objects + are imemo objects (imemo_env). + + * NEWS: describe this change. I believe nobody touch these objects + because there are no method defined. + + * vm_core.h: remove the following definitions. + * rb_cEnv decl. + * GetEnvPtr() because Env is no longer T_DATA object. + + * vm_core.h (rb_env_t): fix layout for imemo values. + + * vm_core.h (vm_assert_env): added. + + * vm_core.h (vm_env_new): added. + Thu Jul 28 19:53:21 2016 Koichi Sasada <ko1@atdot.net> * vm_core.h: revisit the structure of frame, block and env. @@ -66,6 +66,10 @@ with all sufficient information, see the ChangeLog file or Redmine * Regexp#match? [Feature #8110] This returns bool and doesn't save backref. +* RubyVM::Env + + * RubyVM::Env was removed. + * String * String#upcase, String#downcase, String#capitalize, String#swapcase and @@ -421,6 +421,7 @@ typedef struct RVALUE { struct MEMO memo; struct rb_method_entry_struct ment; const rb_iseq_t iseq; + rb_env_t env; } imemo; struct { struct RBasic basic; @@ -2272,17 +2273,19 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_IMEMO: - { - switch (imemo_type(obj)) { - case imemo_ment: - rb_free_method_entry(&RANY(obj)->as.imemo.ment); - break; - case imemo_iseq: - rb_iseq_free(&RANY(obj)->as.imemo.iseq); - break; - default: - break; - } + switch (imemo_type(obj)) { + case imemo_ment: + rb_free_method_entry(&RANY(obj)->as.imemo.ment); + break; + case imemo_iseq: + rb_iseq_free(&RANY(obj)->as.imemo.iseq); + break; + case imemo_env: + VM_ASSERT(VM_ENV_ESCAPED_P(RANY(obj)->as.imemo.env.ep)); + xfree((VALUE *)RANY(obj)->as.imemo.env.env); + break; + default: + break; } return 0; @@ -3988,10 +3991,9 @@ rb_gc_mark_locations(const VALUE *start, const VALUE *end) gc_mark_locations(&rb_objspace, start, end); } -void -rb_gc_mark_values(long n, const VALUE *values) +static void +gc_mark_values(rb_objspace_t *objspace, long n, const VALUE *values) { - rb_objspace_t *objspace = &rb_objspace; long i; for (i=0; i<n; i++) { @@ -3999,6 +4001,13 @@ rb_gc_mark_values(long n, const VALUE *values) } } +void +rb_gc_mark_values(long n, const VALUE *values) +{ + rb_objspace_t *objspace = &rb_objspace; + gc_mark_values(objspace, n, values); +} + static int mark_entry(st_data_t key, st_data_t value, st_data_t data) { @@ -4392,6 +4401,55 @@ gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj) } static void +gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) +{ + switch (imemo_type(obj)) { + case imemo_env: + { + const rb_env_t *env = (const rb_env_t *)obj; + VM_ASSERT(VM_ENV_ESCAPED_P(env->ep)); + gc_mark_values(objspace, (long)env->env_size, env->env); + VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); + gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env)); + gc_mark(objspace, (VALUE)env->iseq); + } + return; + case imemo_cref: + gc_mark(objspace, RANY(obj)->as.imemo.cref.klass); + gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next); + gc_mark(objspace, RANY(obj)->as.imemo.cref.refinements); + return; + case imemo_svar: + gc_mark(objspace, RANY(obj)->as.imemo.svar.cref_or_me); + gc_mark(objspace, RANY(obj)->as.imemo.svar.lastline); + gc_mark(objspace, RANY(obj)->as.imemo.svar.backref); + gc_mark(objspace, RANY(obj)->as.imemo.svar.others); + return; + case imemo_throw_data: + gc_mark(objspace, RANY(obj)->as.imemo.throw_data.throw_obj); + return; + case imemo_ifunc: + gc_mark_maybe(objspace, (VALUE)RANY(obj)->as.imemo.ifunc.data); + return; + case imemo_memo: + gc_mark(objspace, RANY(obj)->as.imemo.memo.v1); + gc_mark(objspace, RANY(obj)->as.imemo.memo.v2); + gc_mark_maybe(objspace, RANY(obj)->as.imemo.memo.u3.value); + return; + case imemo_ment: + mark_method_entry(objspace, &RANY(obj)->as.imemo.ment); + return; + case imemo_iseq: + rb_iseq_mark((rb_iseq_t *)obj); + return; +#if VM_CHECK_MODE > 0 + default: + VM_UNREACHABLE(gc_mark_imemo); +#endif + } +} + +static void gc_mark_children(rb_objspace_t *objspace, VALUE obj) { register RVALUE *any = RANY(obj); @@ -4413,40 +4471,8 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) return; /* no need to mark class. */ case T_IMEMO: - switch (imemo_type(obj)) { - case imemo_none: - rb_bug("unreachable"); - return; - case imemo_cref: - gc_mark(objspace, RANY(obj)->as.imemo.cref.klass); - gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next); - gc_mark(objspace, RANY(obj)->as.imemo.cref.refinements); - return; - case imemo_svar: - gc_mark(objspace, RANY(obj)->as.imemo.svar.cref_or_me); - gc_mark(objspace, RANY(obj)->as.imemo.svar.lastline); - gc_mark(objspace, RANY(obj)->as.imemo.svar.backref); - gc_mark(objspace, RANY(obj)->as.imemo.svar.others); - return; - case imemo_throw_data: - gc_mark(objspace, RANY(obj)->as.imemo.throw_data.throw_obj); - return; - case imemo_ifunc: - gc_mark_maybe(objspace, (VALUE)RANY(obj)->as.imemo.ifunc.data); - return; - case imemo_memo: - gc_mark(objspace, RANY(obj)->as.imemo.memo.v1); - gc_mark(objspace, RANY(obj)->as.imemo.memo.v2); - gc_mark_maybe(objspace, RANY(obj)->as.imemo.memo.u3.value); - return; - case imemo_ment: - mark_method_entry(objspace, &RANY(obj)->as.imemo.ment); - return; - case imemo_iseq: - rb_iseq_mark((rb_iseq_t *)obj); - return; - } - rb_bug("T_IMEMO: unreachable"); + gc_mark_imemo(objspace, obj); + return; } gc_mark(objspace, any->as.basic.klass); @@ -9241,7 +9267,7 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) const char *imemo_name; switch (imemo_type(obj)) { #define IMEMO_NAME(x) case imemo_##x: imemo_name = #x; break; - IMEMO_NAME(none); + IMEMO_NAME(env); IMEMO_NAME(cref); IMEMO_NAME(svar); IMEMO_NAME(throw_data); @@ -9249,7 +9275,6 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) IMEMO_NAME(memo); IMEMO_NAME(ment); IMEMO_NAME(iseq); - default: rb_bug("unknown IMEMO"); #undef IMEMO_NAME } snprintf(buff, buff_size, "%s %s", buff, imemo_name); diff --git a/internal.h b/internal.h index b9fa536140..d92c0fc374 100644 --- a/internal.h +++ b/internal.h @@ -685,15 +685,15 @@ struct RIMemo { }; enum imemo_type { - imemo_none = 0, - imemo_cref = 1, - imemo_svar = 2, + imemo_env = 0, + imemo_cref = 1, + imemo_svar = 2, imemo_throw_data = 3, - imemo_ifunc = 4, - imemo_memo = 5, - imemo_ment = 6, - imemo_iseq = 7, - imemo_mask = 0x07 + imemo_ifunc = 4, + imemo_memo = 5, + imemo_ment = 6, + imemo_iseq = 7, + imemo_mask = 0x07 }; static inline enum imemo_type @@ -392,15 +392,12 @@ bind_eval(int argc, VALUE *argv, VALUE bindval) } static const VALUE * -get_local_variable_ptr(VALUE envval, ID lid) +get_local_variable_ptr(const rb_env_t *env, ID lid) { - rb_env_t *env; - do { const rb_iseq_t *iseq; unsigned int i; - GetEnvPtr(envval, env); iseq = env->iseq; if (iseq && RUBY_VM_NORMAL_ISEQ_P(iseq)) { @@ -413,7 +410,7 @@ get_local_variable_ptr(VALUE envval, ID lid) else { return NULL; } - } while ((envval = rb_vm_env_prev_envval(env)) != Qfalse); + } while ((env = rb_vm_env_prev_env(env)) != NULL); return NULL; } @@ -470,8 +467,7 @@ bind_local_variables(VALUE bindval) const rb_env_t *env; GetBindingPtr(bindval, bind); - GetEnvPtr(VM_ENV_ENVVAL(vm_block_ep(&bind->block)), env); - + env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); return rb_vm_env_local_variables(env); } @@ -503,7 +499,7 @@ bind_local_variable_get(VALUE bindval, VALUE sym) GetBindingPtr(bindval, bind); - if ((ptr = get_local_variable_ptr(VM_ENV_ENVVAL(vm_block_ep(&bind->block)), lid)) == NULL) { + if ((ptr = get_local_variable_ptr(VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)), lid)) == NULL) { sym = ID2SYM(lid); undefined: rb_name_err_raise("local variable `%1$s' not defined for %2$s", @@ -543,19 +539,19 @@ bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val) ID lid = check_local_id(bindval, &sym); rb_binding_t *bind; const VALUE *ptr; - VALUE envval; + const rb_env_t *env; if (!lid) lid = rb_intern_str(sym); GetBindingPtr(bindval, bind); - envval = VM_ENV_ENVVAL(vm_block_ep(&bind->block)); - if ((ptr = get_local_variable_ptr(envval, lid)) == NULL) { + env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); + if ((ptr = get_local_variable_ptr(env, lid)) == NULL) { /* not found. create new env */ ptr = rb_binding_add_dynavars(bind, 1, &lid); - envval = VM_ENV_ENVVAL(vm_block_ep(&bind->block)); + env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); } - RB_OBJ_WRITE(envval, ptr, val); + RB_OBJ_WRITE(env, ptr, val); return val; } @@ -586,7 +582,7 @@ bind_local_variable_defined_p(VALUE bindval, VALUE sym) if (!lid) return Qfalse; GetBindingPtr(bindval, bind); - return get_local_variable_ptr(VM_ENV_ENVVAL(vm_block_ep(&bind->block)), lid) ? Qtrue : Qfalse; + return get_local_variable_ptr(VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)), lid) ? Qtrue : Qfalse; } /* @@ -2705,36 +2701,36 @@ localjump_reason(VALUE exc) rb_cref_t *rb_vm_cref_new_toplevel(void); /* vm.c */ static inline void -env_write(VALUE env, const VALUE *ep, int index, VALUE v) +env_write(VALUE envval, const VALUE *ep, int index, VALUE v) { VM_ASSERT(VM_ENV_ESCAPED_P(ep)); - VM_ASSERT(env == VM_ENV_ENVVAL(ep)); - VM_ASSERT(vm_env_ep(env) == ep); + VM_ASSERT(envval == VM_ENV_ENVVAL(ep)); + VM_ASSERT(vm_assert_env(envval)); - RB_OBJ_WRITE(env, &ep[index], v); + RB_OBJ_WRITE(envval, &ep[index], v); } -static VALUE -env_clone(VALUE envval, const rb_cref_t *cref) +static const rb_env_t * +env_clone(const rb_env_t *env, const rb_cref_t *cref) { - VALUE newenvval = TypedData_Wrap_Struct(RBASIC_CLASS(envval), RTYPEDDATA_TYPE(envval), 0); - rb_env_t *env, *newenv; - int envsize; + VALUE *new_ep; + VALUE *new_body; + const rb_env_t *new_env; + + VM_ASSERT(env->ep > env->env); + VM_ASSERT(VM_ENV_ESCAPED_P(env->ep)); if (cref == NULL) { cref = rb_vm_cref_new_toplevel(); } - GetEnvPtr(envval, env); - envsize = sizeof(rb_env_t) + (env->env_size - 1) * sizeof(VALUE); - newenv = xmalloc(envsize); - memcpy(newenv, env, envsize); - VM_ASSERT(env->ep > env->env); - newenv->ep = &newenv->env[env->ep - env->env]; - VM_FORCE_WRITE(&newenv->ep[VM_ENV_DATA_INDEX_ENV], newenvval); - RTYPEDDATA_DATA(newenvval) = newenv; - env_write(newenvval, newenv->ep, VM_ENV_DATA_INDEX_ME_CREF, (VALUE)cref); - return newenvval; + new_body = ALLOC_N(VALUE, env->env_size); + MEMCPY(new_body, env->env, VALUE, env->env_size); + new_ep = &new_body[env->ep - env->env]; + new_env = vm_env_new(new_ep, new_body, env->env_size, env->iseq); + RB_OBJ_WRITE(new_env, &new_ep[VM_ENV_DATA_INDEX_ME_CREF], (VALUE)cref); + VM_ASSERT(VM_ENV_ESCAPED_P(new_ep)); + return new_env; } /* @@ -2755,12 +2751,12 @@ env_clone(VALUE envval, const rb_cref_t *cref) static VALUE proc_binding(VALUE self) { - VALUE bindval, envval = Qundef, binding_self = Qundef; + VALUE bindval, binding_self = Qundef; rb_binding_t *bind; const rb_proc_t *proc; const rb_iseq_t *iseq = NULL; const struct rb_block *block; - const rb_env_t *env; + const rb_env_t *env = NULL; GetProcPtr(self, proc); block = &proc->block; @@ -2770,7 +2766,7 @@ proc_binding(VALUE self) case block_type_iseq: iseq = block->as.captured.code.iseq; binding_self = block->as.captured.self; - envval = VM_ENV_ENVVAL(block->as.captured.ep); + env = VM_ENV_ENVVAL_PTR(block->as.captured.ep); break; case block_type_proc: GetProcPtr(block->as.proc, proc); @@ -2783,16 +2779,12 @@ proc_binding(VALUE self) const struct vm_ifunc *ifunc = block->as.captured.code.ifunc; if (IS_METHOD_PROC_IFUNC(ifunc)) { VALUE method = (VALUE)ifunc->data; - rb_env_t *newenv; - - iseq = rb_method_iseq(method); - envval = VM_ENV_ENVVAL(block->as.captured.ep); - envval = env_clone(envval, method_cref(method)); binding_self = method_receiver(method); - - GetEnvPtr(envval, newenv); + iseq = rb_method_iseq(method); + env = VM_ENV_ENVVAL_PTR(block->as.captured.ep); + env = env_clone(env, method_cref(method)); /* set empty iseq */ - newenv->iseq = rb_iseq_new(NULL, rb_str_new2("<empty iseq>"), rb_str_new2("<empty_iseq>"), Qnil, 0, ISEQ_TYPE_TOP); + RB_OBJ_WRITE(env, &env->iseq, rb_iseq_new(NULL, rb_str_new2("<empty iseq>"), rb_str_new2("<empty_iseq>"), Qnil, 0, ISEQ_TYPE_TOP)); break; } else { @@ -2805,7 +2797,6 @@ proc_binding(VALUE self) bindval = rb_binding_alloc(rb_cBinding); GetBindingPtr(bindval, bind); - GetEnvPtr(envval, env); bind->block.as.captured.self = binding_self; bind->block.as.captured.code.iseq = env->iseq; @@ -98,8 +98,6 @@ VM_CFP_IN_HEAP_P(const rb_thread_t *th, const rb_control_frame_t *cfp) } } -static int envval_p(VALUE envval); - static int VM_EP_IN_HEAP_P(const rb_thread_t *th, const VALUE *ep) { @@ -120,11 +118,10 @@ vm_ep_in_heap_p_(const rb_thread_t *th, const VALUE *ep) VALUE envval = ep[VM_ENV_DATA_INDEX_ENV]; /* VM_ENV_ENVVAL(ep); */ if (envval != Qundef) { - rb_env_t *env; + const rb_env_t *env = (const rb_env_t *)envval; + VM_ASSERT(vm_assert_env(envval)); VM_ASSERT(VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)); - VM_ASSERT(envval_p(envval)); - GetEnvPtr(envval, env); VM_ASSERT(env->ep == ep); } return TRUE; @@ -268,8 +265,7 @@ vm_cref_dump(const char *mesg, const rb_cref_t *cref) static void vm_bind_update_env(rb_binding_t *bind, VALUE envval) { - rb_env_t *env; - GetEnvPtr(envval, env); + const rb_env_t *env = (rb_env_t *)envval; bind->block.as.captured.code.iseq = env->iseq; bind->block.as.captured.ep = env->ep; } @@ -309,7 +305,6 @@ rb_next_class_serial(void) VALUE rb_cRubyVM; VALUE rb_cThread; -VALUE rb_cEnv; VALUE rb_mRubyVMFrozenCore; #define ruby_vm_redefined_flag GET_VM()->redefined_flag @@ -583,100 +578,29 @@ ruby_vm_run_at_exit_hooks(rb_vm_t *vm) /* Env */ -/* - env{ - env[0] // special (block or prev env) - env[1] // env object - }; - */ - -static void -env_mark(void * const ptr) -{ - const rb_env_t * const env = ptr; - - /* TODO: should mark more restricted range */ - RUBY_GC_INFO("env->env\n"); - VM_ASSERT(VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_ESCAPED)); - - rb_gc_mark_values((long)env->env_size, env->env); - VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); - - RUBY_MARK_UNLESS_NULL(rb_vm_env_prev_envval(env)); - RUBY_MARK_UNLESS_NULL((VALUE)env->iseq); - RUBY_MARK_LEAVE("env"); -} - -static size_t -env_memsize(const void *ptr) -{ - const rb_env_t * const env = ptr; - size_t size = sizeof(rb_env_t); - - size += (env->env_size - 1) * sizeof(VALUE); - return size; -} - -#if VM_CHECK_MODE > 0 -static void -env_free(void *ptr) -{ - if (ptr) { - rb_env_t * const env = ptr; - VM_ASSERT(VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_ESCAPED)); - free(env); - } -} -#else -#define env_free RUBY_TYPED_DEFAULT_FREE -#endif - -static const rb_data_type_t env_data_type = { - "VM/env", - {env_mark, env_free, env_memsize,}, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED -}; - -#if VM_CHECK_MODE > 0 -static int -envval_p(VALUE envval) -{ - if (rb_typeddata_is_kind_of(envval, &env_data_type)) { - return TRUE; - } - else { - rb_obj_info_dump(envval); - return FALSE; - } -} -#endif - -static VALUE check_env_value(VALUE envval); +static VALUE check_env_value(const rb_env_t *env); static int -check_env(rb_env_t * const env) +check_env(const rb_env_t *env) { fprintf(stderr, "---\n"); fprintf(stderr, "envptr: %p\n", (void *)&env->ep[0]); fprintf(stderr, "envval: %10p ", (void *)env->ep[1]); dp(env->ep[1]); fprintf(stderr, "ep: %10p\n", (void *)env->ep); - if (rb_vm_env_prev_envval(env)) { + if (rb_vm_env_prev_env(env)) { fprintf(stderr, ">>\n"); - check_env_value(rb_vm_env_prev_envval(env)); + check_env_value(rb_vm_env_prev_env(env)); fprintf(stderr, "<<\n"); } return 1; } static VALUE -check_env_value(VALUE envval) +check_env_value(const rb_env_t *env) { - rb_env_t *env; - GetEnvPtr(envval, env); - if (check_env(env)) { - return envval; + return (VALUE)env; } rb_bug("invalid env"); return Qnil; /* unreachable */ @@ -703,10 +627,11 @@ vm_block_handler_escape(rb_thread_t *th, VALUE block_handler, VALUE *procvalptr) static VALUE vm_make_env_each(rb_thread_t *const th, rb_control_frame_t *const cfp) { - VALUE envval, blockprocval = Qfalse; + VALUE blockprocval = Qfalse; const VALUE * const ep = cfp->ep; - rb_env_t *env; - const VALUE *new_ep; + const rb_env_t *env; + const rb_iseq_t *env_iseq; + VALUE *env_body, *env_ep; int local_size, env_size; if (VM_ENV_ESCAPED_P(ep)) { @@ -759,12 +684,8 @@ vm_make_env_each(rb_thread_t *const th, rb_control_frame_t *const cfp) env_size = local_size + 1 /* envval */ + (blockprocval ? 1 : 0) /* blockprocval */; - envval = TypedData_Wrap_Struct(rb_cEnv, &env_data_type, 0); - env = xmalloc(sizeof(rb_env_t) + (env_size - 1 /* rb_env_t::env[1] */) * sizeof(VALUE)); - env->env_size = env_size; - - /* setup env */ - MEMCPY((VALUE *)env->env, ep - (local_size - 1 /* specval */), VALUE, local_size); + env_body = ALLOC_N(VALUE, env_size); + MEMCPY(env_body, ep - (local_size - 1 /* specval */), VALUE, local_size); #if 0 for (i = 0; i < local_size; i++) { @@ -775,29 +696,16 @@ vm_make_env_each(rb_thread_t *const th, rb_control_frame_t *const cfp) } #endif - /* be careful not to trigger GC after this */ - RTYPEDDATA_DATA(envval) = env; + env_iseq = RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) ? cfp->iseq : NULL; + env_ep = &env_body[local_size - 1 /* specval */]; - new_ep = &env->env[local_size - 1 /* specval */]; - RB_OBJ_WRITE(envval, &new_ep[1], envval); - if (blockprocval) RB_OBJ_WRITE(envval, &new_ep[2], blockprocval); - VM_ENV_FLAGS_SET(new_ep, VM_ENV_FLAG_ESCAPED | VM_ENV_FLAG_WB_REQUIRED); + env = vm_env_new(env_ep, env_body, env_size, env_iseq); - /* - * must happen after TypedData_Wrap_Struct to ensure penvval is markable - * in case object allocation triggers GC and clobbers penvval. - */ - VM_STACK_ENV_WRITE(ep, 0, envval); /* GC mark */ - - /* setup env object */ - env->ep = cfp->ep = new_ep; - env->iseq = cfp->iseq; - - if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { - env->iseq = NULL; - } - - return envval; + if (blockprocval) RB_OBJ_WRITE(env, &env_ep[2], blockprocval); + cfp->ep = env_ep; + VM_ENV_FLAGS_SET(env_ep, VM_ENV_FLAG_ESCAPED | VM_ENV_FLAG_WB_REQUIRED); + VM_STACK_ENV_WRITE(ep, 0, (VALUE)env); /* GC mark */ + return (VALUE)env; } static VALUE @@ -806,7 +714,7 @@ vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp) VALUE envval = vm_make_env_each(th, cfp); if (PROCDEBUG) { - check_env_value(envval); + check_env_value((const rb_env_t *)envval); } return envval; @@ -822,16 +730,16 @@ rb_vm_stack_to_heap(rb_thread_t *th) } } -VALUE -rb_vm_env_prev_envval(const rb_env_t *env) +const rb_env_t * +rb_vm_env_prev_env(const rb_env_t *env) { const VALUE *ep = env->ep; if (VM_ENV_LOCAL_P(ep)) { - return Qfalse; + return NULL; } else { - return VM_ENV_ENVVAL(VM_ENV_PREV_EP(ep)); + return VM_ENV_ENVVAL_PTR(VM_ENV_PREV_EP(ep)); } } @@ -849,20 +757,16 @@ collect_local_variables_in_iseq(const rb_iseq_t *iseq, const struct local_var_li static void collect_local_variables_in_env(const rb_env_t *env, const struct local_var_list *vars) { - VALUE prev_envval; - - while (collect_local_variables_in_iseq(env->iseq, vars), (prev_envval = rb_vm_env_prev_envval(env)) != Qfalse) { - GetEnvPtr(prev_envval, env); - } + do { + collect_local_variables_in_iseq(env->iseq, vars); + } while ((env = rb_vm_env_prev_env(env)) != NULL); } static int vm_collect_local_variables_in_heap(rb_thread_t *th, const VALUE *ep, const struct local_var_list *vars) { if (VM_ENV_ESCAPED_P(ep)) { - rb_env_t *env; - GetEnvPtr(VM_ENV_ENVVAL(ep), env); - collect_local_variables_in_env(env, vars); + collect_local_variables_in_env(VM_ENV_ENVVAL_PTR(ep), vars); return 1; } else { @@ -1010,10 +914,9 @@ rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp) const VALUE * rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) { - VALUE envval; - VALUE path = bind->path; + VALUE envval, path = bind->path; const struct rb_block *base_block; - rb_env_t *env; + const rb_env_t *env; rb_thread_t *th = GET_THREAD(); const rb_iseq_t *base_iseq, *iseq; NODE *node = 0; @@ -1045,7 +948,7 @@ rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) vm_bind_update_env(bind, envval = vm_make_env_object(th, th->cfp)); rb_vm_pop_frame(th); - GetEnvPtr(envval, env); + env = (const rb_env_t *)envval; return env->env; } @@ -2859,11 +2762,6 @@ Init_VM(void) rb_gc_register_mark_object(fcore); rb_mRubyVMFrozenCore = fcore; - /* ::RubyVM::Env */ - rb_cEnv = rb_define_class_under(rb_cRubyVM, "Env", rb_cObject); - rb_undef_alloc_func(rb_cEnv); - rb_undef_method(CLASS_OF(rb_cEnv), "new"); - /* * Document-class: Thread * @@ -858,7 +858,6 @@ VALUE rb_iseq_coverage(const rb_iseq_t *iseq); RUBY_EXTERN VALUE rb_cISeq; RUBY_EXTERN VALUE rb_cRubyVM; -RUBY_EXTERN VALUE rb_cEnv; RUBY_EXTERN VALUE rb_mRubyVMFrozenCore; RUBY_SYMBOL_EXPORT_END @@ -872,14 +871,12 @@ typedef struct { int8_t is_lambda; /* bool */ } rb_proc_t; -#define GetEnvPtr(obj, ptr) \ - GetCoreDataFromValue((obj), rb_env_t, (ptr)) - typedef struct { - int env_size; - const VALUE *ep; + VALUE flags; /* imemo header */ const rb_iseq_t *iseq; - const VALUE env[1]; /* flexible array */ + const VALUE *ep; + const VALUE *env; + unsigned int env_size; } rb_env_t; extern const rb_data_type_t ruby_binding_data_type; @@ -1070,11 +1067,29 @@ VM_ENV_ESCAPED_P(const VALUE *ep) return VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED) ? 1 : 0; } +#if VM_CHECK_MODE > 0 +static inline int +vm_assert_env(VALUE obj) +{ + VM_ASSERT(RB_TYPE_P(obj, T_IMEMO)); + VM_ASSERT(imemo_type(obj) == imemo_env); + return 1; +} +#endif + static inline VALUE VM_ENV_ENVVAL(const VALUE *ep) { + VALUE envval = ep[VM_ENV_DATA_INDEX_ENV]; VM_ASSERT(VM_ENV_ESCAPED_P(ep)); - return ep[VM_ENV_DATA_INDEX_ENV]; + VM_ASSERT(vm_assert_env(envval)); + return envval; +} + +static inline const rb_env_t * +VM_ENV_ENVVAL_PTR(const VALUE *ep) +{ + return (const rb_env_t *)VM_ENV_ENVVAL(ep); } static inline VALUE @@ -1087,6 +1102,15 @@ VM_ENV_PROCVAL(const VALUE *ep) return ep[VM_ENV_DATA_INDEX_ENV_PROC]; } +static inline const rb_env_t * +vm_env_new(VALUE *env_ep, VALUE *env_body, unsigned int env_size, const rb_iseq_t *iseq) +{ + rb_env_t *env = (rb_env_t *)rb_imemo_new(imemo_env, (VALUE)env_ep, (VALUE)env_body, 0, (VALUE)iseq); + env->env_size = env_size; + env_ep[VM_ENV_DATA_INDEX_ENV] = (VALUE)env; + return env; +} + static inline void VM_FORCE_WRITE(const VALUE *ptr, VALUE v) { @@ -1107,16 +1131,6 @@ VM_STACK_ENV_WRITE(const VALUE *ep, int index, VALUE v) VM_FORCE_WRITE(&ep[index], v); } -#if VM_CHECK_MODE > 0 -static inline const VALUE * -vm_env_ep(VALUE envval) -{ - rb_env_t *env; - GetEnvPtr(envval, env); - return env->ep; -} -#endif - const VALUE *rb_vm_ep_local_ep(const VALUE *ep); VALUE rb_vm_frame_block_handler(const rb_control_frame_t *cfp); @@ -1381,7 +1395,7 @@ VALUE rb_vm_make_proc_lambda(rb_thread_t *th, const struct rb_captured_block *ca VALUE rb_vm_make_proc(rb_thread_t *th, const struct rb_captured_block *captured, VALUE klass); VALUE rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp); VALUE rb_vm_env_local_variables(const rb_env_t *env); -VALUE rb_vm_env_prev_envval(const rb_env_t *env); +const rb_env_t *rb_vm_env_prev_env(const rb_env_t *env); const VALUE *rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars); void rb_vm_inc_const_missing_count(void); void rb_vm_gvl_destroy(rb_vm_t *vm); @@ -182,14 +182,12 @@ rb_vmdebug_stack_dump_raw_current(void) } void -rb_vmdebug_env_dump_raw(rb_env_t *env, const VALUE *ep) +rb_vmdebug_env_dump_raw(const rb_env_t *env, const VALUE *ep) { - int i; + unsigned int i; fprintf(stderr, "-- env --------------------\n"); while (env) { - VALUE prev_envval; - fprintf(stderr, "--\n"); for (i = 0; i < env->env_size; i++) { fprintf(stderr, "%04d: %08"PRIxVALUE" (%p)", i, env->env[i], (void *)&env->env[i]); @@ -197,12 +195,7 @@ rb_vmdebug_env_dump_raw(rb_env_t *env, const VALUE *ep) fprintf(stderr, "\n"); } - if ((prev_envval = rb_vm_env_prev_envval(env)) != Qfalse) { - GetEnvPtr(prev_envval, env); - } - else { - env = NULL; - } + env = rb_vm_env_prev_env(env); } fprintf(stderr, "---------------------------\n"); } @@ -210,14 +203,14 @@ rb_vmdebug_env_dump_raw(rb_env_t *env, const VALUE *ep) void rb_vmdebug_proc_dump_raw(rb_proc_t *proc) { - rb_env_t *env; + const rb_env_t *env; char *selfstr; VALUE val = rb_inspect(vm_block_self(&proc->block)); selfstr = StringValueCStr(val); fprintf(stderr, "-- proc -------------------\n"); fprintf(stderr, "self: %s\n", selfstr); - GetEnvPtr(VM_ENV_ENVVAL(vm_block_ep(&proc->block)), env); + env = VM_ENV_ENVVAL_PTR(vm_block_ep(&proc->block)); rb_vmdebug_env_dump_raw(env, vm_block_ep(&proc->block)); } diff --git a/vm_insnhelper.c b/vm_insnhelper.c index b425a2a5cc..9b29124709 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -73,7 +73,7 @@ static void vm_check_frame_detail(VALUE type, int req_block, int req_me, int req_cref, VALUE specval, VALUE cref_or_me) { unsigned int magic = (unsigned int)(type & VM_FRAME_MAGIC_MASK); - enum imemo_type cref_or_me_type = imemo_none; + enum imemo_type cref_or_me_type = imemo_env; /* impossible value */ if (RB_TYPE_P(cref_or_me, T_IMEMO)) { cref_or_me_type = imemo_type(cref_or_me); |