1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

remove VM_ENV_DATA_INDEX_ENV_PROC.

* vm_core.h (VM_ENV_DATA_INDEX_ENV_PROC): ep[VM_ENV_DATA_INDEX_ENV_PROC] is
  allocated to mark a Proc which is created from iseq block.
  However, `lep[0]` keeps Proc object itself as a block handler (Proc).
  So we don't need to keep it.

* vm_core.h (VM_ENV_PROCVAL): ditto.

* vm.c (vm_make_env_each): do not need to keep blockprocval as special value.

* vm.c (vm_block_handler_escape): simply return Proc value.

* proc.c (proc_new):  we don't need to check Env because a Proc type block
  handler is a Proc object itself.
  [Bug #14782]

* test/ruby/test_proc.rb: add a test for [Bug #14782]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63494 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2018-05-23 06:56:08 +00:00
parent b32b2a6106
commit e6ad53beaa
4 changed files with 16 additions and 32 deletions

10
proc.c
View file

@ -706,13 +706,6 @@ proc_new(VALUE klass, int8_t is_lambda)
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
if ((block_handler = rb_vm_frame_block_handler(cfp)) != VM_BLOCK_HANDLER_NONE) { if ((block_handler = rb_vm_frame_block_handler(cfp)) != VM_BLOCK_HANDLER_NONE) {
const VALUE *lep = rb_vm_ep_local_ep(cfp->ep);
if (VM_ENV_ESCAPED_P(lep)) {
procval = VM_ENV_PROCVAL(lep);
goto return_existing_proc;
}
if (is_lambda) { if (is_lambda) {
rb_warn(proc_without_block); rb_warn(proc_without_block);
} }
@ -730,13 +723,12 @@ proc_new(VALUE klass, int8_t is_lambda)
case block_handler_type_proc: case block_handler_type_proc:
procval = VM_BH_TO_PROC(block_handler); procval = VM_BH_TO_PROC(block_handler);
return_existing_proc:
if (RBASIC_CLASS(procval) == klass) { if (RBASIC_CLASS(procval) == klass) {
return procval; return procval;
} }
else { else {
VALUE newprocval = rb_proc_dup(procval); VALUE newprocval = rb_proc_dup(procval);
RBASIC_SET_CLASS(newprocval, klass); RBASIC_SET_CLASS(newprocval, klass);
return newprocval; return newprocval;
} }
break; break;

View file

@ -1408,4 +1408,12 @@ class TestProc < Test::Unit::TestCase
m {} m {}
end; end;
end end
def method_for_test_proc_without_block_for_symbol
binding.eval('proc')
end
def test_proc_without_block_for_symbol
assert_equal('1', method_for_test_proc_without_block_for_symbol(&:to_s).call(1), '[Bug #14782]')
end
end end

19
vm.c
View file

@ -634,28 +634,25 @@ check_env_value(const rb_env_t *env)
return Qnil; /* unreachable */ return Qnil; /* unreachable */
} }
static void static VALUE
vm_block_handler_escape(const rb_execution_context_t *ec, VALUE block_handler, VALUE *procvalptr) vm_block_handler_escape(const rb_execution_context_t *ec, VALUE block_handler)
{ {
switch (vm_block_handler_type(block_handler)) { switch (vm_block_handler_type(block_handler)) {
case block_handler_type_ifunc: case block_handler_type_ifunc:
case block_handler_type_iseq: case block_handler_type_iseq:
*procvalptr = rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc); return rb_vm_make_proc(ec, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc);
return;
case block_handler_type_symbol: case block_handler_type_symbol:
case block_handler_type_proc: case block_handler_type_proc:
*procvalptr = block_handler; return block_handler;
return;
} }
VM_UNREACHABLE(vm_block_handler_escape); VM_UNREACHABLE(vm_block_handler_escape);
return; return Qnil;
} }
static VALUE static VALUE
vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *const cfp) vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *const cfp)
{ {
VALUE blockprocval = Qfalse;
const VALUE * const ep = cfp->ep; const VALUE * const ep = cfp->ep;
const rb_env_t *env; const rb_env_t *env;
const rb_iseq_t *env_iseq; const rb_iseq_t *env_iseq;
@ -685,7 +682,7 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep); VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep);
if (block_handler != VM_BLOCK_HANDLER_NONE) { if (block_handler != VM_BLOCK_HANDLER_NONE) {
vm_block_handler_escape(ec, block_handler, &blockprocval); VALUE blockprocval = vm_block_handler_escape(ec, block_handler);
VM_STACK_ENV_WRITE(ep, VM_ENV_DATA_INDEX_SPECVAL, blockprocval); VM_STACK_ENV_WRITE(ep, VM_ENV_DATA_INDEX_SPECVAL, blockprocval);
} }
} }
@ -710,8 +707,7 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
*/ */
env_size = local_size + env_size = local_size +
1 /* envval */ + 1 /* envval */;
(blockprocval ? 1 : 0) /* blockprocval */;
env_body = ALLOC_N(VALUE, env_size); env_body = ALLOC_N(VALUE, env_size);
MEMCPY(env_body, ep - (local_size - 1 /* specval */), VALUE, local_size); MEMCPY(env_body, ep - (local_size - 1 /* specval */), VALUE, local_size);
@ -729,7 +725,6 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
env = vm_env_new(env_ep, env_body, env_size, env_iseq); env = vm_env_new(env_ep, env_body, env_size, env_iseq);
if (blockprocval) RB_OBJ_WRITE(env, &env_ep[2], blockprocval);
cfp->ep = env_ep; cfp->ep = env_ep;
VM_ENV_FLAGS_SET(env_ep, VM_ENV_FLAG_ESCAPED | VM_ENV_FLAG_WB_REQUIRED); 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 */ VM_STACK_ENV_WRITE(ep, 0, (VALUE)env); /* GC mark */

View file

@ -1084,7 +1084,6 @@ enum {
#define VM_ENV_DATA_INDEX_SPECVAL (-1) /* ep[-1] */ #define VM_ENV_DATA_INDEX_SPECVAL (-1) /* ep[-1] */
#define VM_ENV_DATA_INDEX_FLAGS ( 0) /* ep[ 0] */ #define VM_ENV_DATA_INDEX_FLAGS ( 0) /* ep[ 0] */
#define VM_ENV_DATA_INDEX_ENV ( 1) /* ep[ 1] */ #define VM_ENV_DATA_INDEX_ENV ( 1) /* ep[ 1] */
#define VM_ENV_DATA_INDEX_ENV_PROC ( 2) /* ep[ 2] */
#define VM_ENV_INDEX_LAST_LVAR (-VM_ENV_DATA_SIZE) #define VM_ENV_INDEX_LAST_LVAR (-VM_ENV_DATA_SIZE)
@ -1223,16 +1222,6 @@ VM_ENV_ENVVAL_PTR(const VALUE *ep)
return (const rb_env_t *)VM_ENV_ENVVAL(ep); return (const rb_env_t *)VM_ENV_ENVVAL(ep);
} }
static inline VALUE
VM_ENV_PROCVAL(const VALUE *ep)
{
VM_ASSERT(VM_ENV_ESCAPED_P(ep));
VM_ASSERT(VM_ENV_LOCAL_P(ep));
VM_ASSERT(VM_ENV_BLOCK_HANDLER(ep) != VM_BLOCK_HANDLER_NONE);
return ep[VM_ENV_DATA_INDEX_ENV_PROC];
}
static inline const rb_env_t * static inline const rb_env_t *
vm_env_new(VALUE *env_ep, VALUE *env_body, unsigned int env_size, const rb_iseq_t *iseq) vm_env_new(VALUE *env_ep, VALUE *env_body, unsigned int env_size, const rb_iseq_t *iseq)
{ {