mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Implement getblockparamproxy
* Implement getblockparamproxy * Parallel runner: wait for timeout thread to terminate after killing Or else the leak cheaker could sees the thread as running and cause test failures in test-tool. * Add a comment, use jne * Comment about where 0x3 comes from
This commit is contained in:
parent
ce928473d0
commit
7eef8f09c0
3 changed files with 88 additions and 13 deletions
|
@ -858,26 +858,50 @@ assert_equal 'raised', %q{
|
|||
|
||||
# test calling Ruby method with a block
|
||||
assert_equal '[1, 2, 42]', %q{
|
||||
def thing(a, b)
|
||||
[a, b, yield]
|
||||
end
|
||||
def thing(a, b)
|
||||
[a, b, yield]
|
||||
end
|
||||
|
||||
def use
|
||||
thing(1,2) { 42 }
|
||||
end
|
||||
def use
|
||||
thing(1,2) { 42 }
|
||||
end
|
||||
|
||||
use
|
||||
use
|
||||
use
|
||||
use
|
||||
}
|
||||
|
||||
# test calling C method with a block
|
||||
assert_equal '[42, 42]', %q{
|
||||
def use(array, initial)
|
||||
array.reduce(initial) { |a, b| a + b }
|
||||
end
|
||||
def use(array, initial)
|
||||
array.reduce(initial) { |a, b| a + b }
|
||||
end
|
||||
|
||||
use([], 0)
|
||||
[use([2, 2], 38), use([14, 14, 14], 0)]
|
||||
use([], 0)
|
||||
[use([2, 2], 38), use([14, 14, 14], 0)]
|
||||
}
|
||||
|
||||
# test calling block param
|
||||
assert_equal '[1, 2, 42]', %q{
|
||||
def foo(&block)
|
||||
block.call
|
||||
end
|
||||
|
||||
[foo {1}, foo {2}, foo {42}]
|
||||
}
|
||||
|
||||
# test calling block param failing
|
||||
assert_equal '42', %q{
|
||||
def foo(&block)
|
||||
block.call
|
||||
end
|
||||
|
||||
foo {} # warmup
|
||||
|
||||
begin
|
||||
foo
|
||||
rescue NoMethodError => e
|
||||
42 if nil == e.receiver
|
||||
end
|
||||
}
|
||||
|
||||
# test calling method taking block param
|
||||
|
|
|
@ -221,6 +221,8 @@ yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
|
|||
{
|
||||
uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
|
||||
|
||||
ADD_COMMENT(cb, "exit to interpreter");
|
||||
|
||||
VALUE *exit_pc = jit->pc;
|
||||
|
||||
// YJIT only ever patches the first instruction in an iseq
|
||||
|
@ -2527,6 +2529,52 @@ gen_opt_getinlinecache(jitstate_t *jit, ctx_t *ctx)
|
|||
return YJIT_END_BLOCK;
|
||||
}
|
||||
|
||||
// Push the explict block parameter onto the temporary stack. Part of the
|
||||
// interpreter's scheme for avoiding Proc allocations when delegating
|
||||
// explict block parameters.
|
||||
static codegen_status_t
|
||||
gen_getblockparamproxy(jitstate_t *jit, ctx_t *ctx)
|
||||
{
|
||||
// A mirror of the interpreter code. Checking for the case
|
||||
// where it's pushing rb_block_param_proxy.
|
||||
uint8_t *side_exit = yjit_side_exit(jit, ctx);
|
||||
|
||||
// EP level
|
||||
VALUE level = jit_get_arg(jit, 1);
|
||||
|
||||
if (level != 0) {
|
||||
// Bail on non zero level to make getting the ep simple
|
||||
return YJIT_CANT_COMPILE;
|
||||
}
|
||||
|
||||
// Load environment pointer EP from CFP
|
||||
mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, ep));
|
||||
|
||||
// Bail when VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) is non zero
|
||||
test(cb, mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_FLAGS), imm_opnd(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM));
|
||||
jnz_ptr(cb, side_exit);
|
||||
|
||||
// Load the block handler for the current frame
|
||||
// note, VM_ASSERT(VM_ENV_LOCAL_P(ep))
|
||||
mov(cb, REG0, mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_SPECVAL));
|
||||
|
||||
// Block handler is a tagged pointer. Look at the tag. 0x03 is from VM_BH_ISEQ_BLOCK_P().
|
||||
and(cb, REG0_8, imm_opnd(0x3));
|
||||
|
||||
// Bail unless VM_BH_ISEQ_BLOCK_P(bh). This also checks for null.
|
||||
cmp(cb, REG0_8, imm_opnd(0x1));
|
||||
jne_ptr(cb, side_exit);
|
||||
|
||||
// Push rb_block_param_proxy. It's a root, so no need to use jit_mov_gc_ptr.
|
||||
mov(cb, REG0, const_ptr_opnd((void *)rb_block_param_proxy));
|
||||
RUBY_ASSERT(!SPECIAL_CONST_P(rb_block_param_proxy));
|
||||
x86opnd_t top = ctx_stack_push(ctx, TYPE_HEAP);
|
||||
mov(cb, top, REG0);
|
||||
|
||||
return YJIT_KEEP_COMPILING;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
yjit_reg_op(int opcode, codegen_fn gen_fn)
|
||||
{
|
||||
|
@ -2588,6 +2636,7 @@ yjit_init_codegen(void)
|
|||
yjit_reg_op(BIN(branchunless), gen_branchunless);
|
||||
yjit_reg_op(BIN(branchnil), gen_branchnil);
|
||||
yjit_reg_op(BIN(jump), gen_jump);
|
||||
yjit_reg_op(BIN(getblockparamproxy), gen_getblockparamproxy);
|
||||
yjit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block);
|
||||
yjit_reg_op(BIN(send), gen_send);
|
||||
yjit_reg_op(BIN(leave), gen_leave);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#define REG0_32 EAX
|
||||
#define REG1_32 ECX
|
||||
|
||||
#define REG0_8 AL
|
||||
|
||||
// Maximum number of temp value types we keep track of
|
||||
#define MAX_TEMP_TYPES 8
|
||||
|
||||
|
|
Loading…
Reference in a new issue