From fccbc2d278226a2dfe5cffe4918724b0110c5781 Mon Sep 17 00:00:00 2001 From: ko1 Date: Mon, 12 Jun 2017 02:20:09 +0000 Subject: * proc.c (get_local_variable_ptr): return found env ptr. Returned env will be used by write barrier at `bind_local_variable_set()'. [Bug #13605] * test/ruby/test_proc.rb: add a test for this issue. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59063 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- proc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'proc.c') diff --git a/proc.c b/proc.c index c166fc9c0e..25bb36e15b 100644 --- a/proc.c +++ b/proc.c @@ -386,8 +386,9 @@ bind_eval(int argc, VALUE *argv, VALUE bindval) } static const VALUE * -get_local_variable_ptr(const rb_env_t *env, ID lid) +get_local_variable_ptr(const rb_env_t **envp, ID lid) { + const rb_env_t *env = *envp; do { if (!VM_ENV_FLAGS(env->ep, VM_FRAME_FLAG_CFRAME)) { const rb_iseq_t *iseq = env->iseq; @@ -397,15 +398,18 @@ get_local_variable_ptr(const rb_env_t *env, ID lid) for (i=0; ibody->local_table_size; i++) { if (iseq->body->local_table[i] == lid) { + *envp = env; return &env->env[i]; } } } else { + *envp = NULL; return NULL; } } while ((env = rb_vm_env_prev_env(env)) != NULL); + *envp = NULL; return NULL; } @@ -488,12 +492,14 @@ bind_local_variable_get(VALUE bindval, VALUE sym) ID lid = check_local_id(bindval, &sym); const rb_binding_t *bind; const VALUE *ptr; + const rb_env_t *env; if (!lid) goto undefined; GetBindingPtr(bindval, bind); - if ((ptr = get_local_variable_ptr(VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)), lid)) == NULL) { + env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); + if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) { sym = ID2SYM(lid); undefined: rb_name_err_raise("local variable `%1$s' not defined for %2$s", @@ -540,7 +546,7 @@ bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val) GetBindingPtr(bindval, bind); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); - if ((ptr = get_local_variable_ptr(env, lid)) == NULL) { + if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) { /* not found. create new env */ ptr = rb_binding_add_dynavars(bindval, bind, 1, &lid); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); @@ -573,11 +579,13 @@ bind_local_variable_defined_p(VALUE bindval, VALUE sym) { ID lid = check_local_id(bindval, &sym); const rb_binding_t *bind; + const rb_env_t *env; if (!lid) return Qfalse; GetBindingPtr(bindval, bind); - return get_local_variable_ptr(VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)), lid) ? Qtrue : Qfalse; + env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); + return get_local_variable_ptr(&env, lid) ? Qtrue : Qfalse; } /* -- cgit v1.2.3