mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Prototype type-specialization for temp values
This commit is contained in:
parent
cf4021ca78
commit
0a6e824ad2
3 changed files with 60 additions and 23 deletions
|
@ -230,8 +230,8 @@ static bool
|
||||||
gen_dup(jitstate_t* jit, ctx_t* ctx)
|
gen_dup(jitstate_t* jit, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
x86opnd_t dup_val = ctx_stack_pop(ctx, 1);
|
x86opnd_t dup_val = ctx_stack_pop(ctx, 1);
|
||||||
x86opnd_t loc0 = ctx_stack_push(ctx, 1);
|
x86opnd_t loc0 = ctx_stack_push(ctx, T_NONE);
|
||||||
x86opnd_t loc1 = ctx_stack_push(ctx, 1);
|
x86opnd_t loc1 = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, RAX, dup_val);
|
mov(cb, RAX, dup_val);
|
||||||
mov(cb, loc0, RAX);
|
mov(cb, loc0, RAX);
|
||||||
mov(cb, loc1, RAX);
|
mov(cb, loc1, RAX);
|
||||||
|
@ -257,7 +257,7 @@ static bool
|
||||||
gen_putnil(jitstate_t* jit, ctx_t* ctx)
|
gen_putnil(jitstate_t* jit, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
// Write constant at SP
|
// Write constant at SP
|
||||||
x86opnd_t stack_top = ctx_stack_push(ctx, 1);
|
x86opnd_t stack_top = ctx_stack_push(ctx, T_NIL);
|
||||||
mov(cb, stack_top, imm_opnd(Qnil));
|
mov(cb, stack_top, imm_opnd(Qnil));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ gen_putobject(jitstate_t* jit, ctx_t* ctx)
|
||||||
mov(cb, RAX, mem_opnd(64, RAX, 8)); // One after the opcode
|
mov(cb, RAX, mem_opnd(64, RAX, 8)); // One after the opcode
|
||||||
|
|
||||||
// Write argument at SP
|
// Write argument at SP
|
||||||
x86opnd_t stack_top = ctx_stack_push(ctx, 1);
|
x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, stack_top, RAX);
|
mov(cb, stack_top, RAX);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -285,7 +285,7 @@ gen_putobject_int2fix(jitstate_t* jit, ctx_t* ctx)
|
||||||
int cst_val = (opcode == BIN(putobject_INT2FIX_0_))? 0:1;
|
int cst_val = (opcode == BIN(putobject_INT2FIX_0_))? 0:1;
|
||||||
|
|
||||||
// Write constant at SP
|
// Write constant at SP
|
||||||
x86opnd_t stack_top = ctx_stack_push(ctx, 1);
|
x86opnd_t stack_top = ctx_stack_push(ctx, T_FIXNUM);
|
||||||
mov(cb, stack_top, imm_opnd(INT2FIX(cst_val)));
|
mov(cb, stack_top, imm_opnd(INT2FIX(cst_val)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -298,7 +298,7 @@ gen_putself(jitstate_t* jit, ctx_t* ctx)
|
||||||
mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, self));
|
mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, self));
|
||||||
|
|
||||||
// Write it on the stack
|
// Write it on the stack
|
||||||
x86opnd_t stack_top = ctx_stack_push(ctx, 1);
|
x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, stack_top, RAX);
|
mov(cb, stack_top, RAX);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -318,7 +318,7 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx)
|
||||||
mov(cb, REG0, mem_opnd(64, REG0, offs));
|
mov(cb, REG0, mem_opnd(64, REG0, offs));
|
||||||
|
|
||||||
// Write the local at SP
|
// Write the local at SP
|
||||||
x86opnd_t stack_top = ctx_stack_push(ctx, 1);
|
x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, stack_top, REG0);
|
mov(cb, stack_top, REG0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -437,7 +437,7 @@ gen_getinstancevariable(jitstate_t* jit, ctx_t* ctx)
|
||||||
je_ptr(cb, side_exit);
|
je_ptr(cb, side_exit);
|
||||||
|
|
||||||
// Push the ivar on the stack
|
// Push the ivar on the stack
|
||||||
x86opnd_t out_opnd = ctx_stack_push(ctx, 1);
|
x86opnd_t out_opnd = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, out_opnd, REG0);
|
mov(cb, out_opnd, REG0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -549,7 +549,7 @@ gen_opt_lt(jitstate_t* jit, ctx_t* ctx)
|
||||||
cmovl(cb, REG0, REG1);
|
cmovl(cb, REG0, REG1);
|
||||||
|
|
||||||
// Push the output on the stack
|
// Push the output on the stack
|
||||||
x86opnd_t dst = ctx_stack_push(ctx, 1);
|
x86opnd_t dst = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, dst, REG0);
|
mov(cb, dst, REG0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -589,7 +589,7 @@ gen_opt_minus(jitstate_t* jit, ctx_t* ctx)
|
||||||
add(cb, REG0, imm_opnd(1));
|
add(cb, REG0, imm_opnd(1));
|
||||||
|
|
||||||
// Push the output on the stack
|
// Push the output on the stack
|
||||||
x86opnd_t dst = ctx_stack_push(ctx, 1);
|
x86opnd_t dst = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, dst, REG0);
|
mov(cb, dst, REG0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -613,14 +613,20 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx)
|
||||||
jnz_ptr(cb, side_exit);
|
jnz_ptr(cb, side_exit);
|
||||||
|
|
||||||
// Get the operands and destination from the stack
|
// Get the operands and destination from the stack
|
||||||
|
int arg1_type = ctx_get_top_type(ctx);
|
||||||
x86opnd_t arg1 = ctx_stack_pop(ctx, 1);
|
x86opnd_t arg1 = ctx_stack_pop(ctx, 1);
|
||||||
|
int arg0_type = ctx_get_top_type(ctx);
|
||||||
x86opnd_t arg0 = ctx_stack_pop(ctx, 1);
|
x86opnd_t arg0 = ctx_stack_pop(ctx, 1);
|
||||||
|
|
||||||
// If not fixnums, fall back
|
// If not fixnums, fall back
|
||||||
test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG));
|
if (arg0_type != T_FIXNUM) {
|
||||||
jz_ptr(cb, side_exit);
|
test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG));
|
||||||
test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG));
|
jz_ptr(cb, side_exit);
|
||||||
jz_ptr(cb, side_exit);
|
}
|
||||||
|
if (arg1_type != T_FIXNUM) {
|
||||||
|
test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG));
|
||||||
|
jz_ptr(cb, side_exit);
|
||||||
|
}
|
||||||
|
|
||||||
// Add arg0 + arg1 and test for overflow
|
// Add arg0 + arg1 and test for overflow
|
||||||
mov(cb, REG0, arg0);
|
mov(cb, REG0, arg0);
|
||||||
|
@ -629,7 +635,7 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx)
|
||||||
jo_ptr(cb, side_exit);
|
jo_ptr(cb, side_exit);
|
||||||
|
|
||||||
// Push the output on the stack
|
// Push the output on the stack
|
||||||
x86opnd_t dst = ctx_stack_push(ctx, 1);
|
x86opnd_t dst = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, dst, REG0);
|
mov(cb, dst, REG0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -938,7 +944,7 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx)
|
||||||
pop(cb, REG_CFP);
|
pop(cb, REG_CFP);
|
||||||
|
|
||||||
// Push the return value on the Ruby stack
|
// Push the return value on the Ruby stack
|
||||||
x86opnd_t stack_ret = ctx_stack_push(ctx, 1);
|
x86opnd_t stack_ret = ctx_stack_push(ctx, T_NONE);
|
||||||
mov(cb, stack_ret, RAX);
|
mov(cb, stack_ret, RAX);
|
||||||
|
|
||||||
// If this function needs a Ruby stack frame
|
// If this function needs a Ruby stack frame
|
||||||
|
|
39
ujit_core.c
39
ujit_core.c
|
@ -31,13 +31,18 @@ ctx_sp_opnd(ctx_t* ctx, int32_t offset_bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Make space on the stack for N values
|
Push one new value on the temp stack
|
||||||
Return a pointer to the new stack top
|
Return a pointer to the new stack top
|
||||||
*/
|
*/
|
||||||
x86opnd_t
|
x86opnd_t
|
||||||
ctx_stack_push(ctx_t* ctx, size_t n)
|
ctx_stack_push(ctx_t* ctx, int type)
|
||||||
{
|
{
|
||||||
ctx->stack_size += n;
|
// Keep track of the type of the value
|
||||||
|
RUBY_ASSERT(type <= RUBY_T_MASK);
|
||||||
|
if (ctx->stack_size < MAX_TEMP_TYPES)
|
||||||
|
ctx->temp_types[ctx->stack_size] = type;
|
||||||
|
|
||||||
|
ctx->stack_size += 1;
|
||||||
|
|
||||||
// SP points just above the topmost value
|
// SP points just above the topmost value
|
||||||
int32_t offset = (ctx->stack_size - 1) * 8;
|
int32_t offset = (ctx->stack_size - 1) * 8;
|
||||||
|
@ -51,15 +56,28 @@ Return a pointer to the stack top before the pop operation
|
||||||
x86opnd_t
|
x86opnd_t
|
||||||
ctx_stack_pop(ctx_t* ctx, size_t n)
|
ctx_stack_pop(ctx_t* ctx, size_t n)
|
||||||
{
|
{
|
||||||
|
RUBY_ASSERT(n <= ctx->stack_size);
|
||||||
|
|
||||||
// SP points just above the topmost value
|
// SP points just above the topmost value
|
||||||
int32_t offset = (ctx->stack_size - 1) * 8;
|
int32_t offset = (ctx->stack_size - 1) * 8;
|
||||||
x86opnd_t top = mem_opnd(64, REG_SP, offset);
|
x86opnd_t top = mem_opnd(64, REG_SP, offset);
|
||||||
|
|
||||||
|
// Clear the types of the popped values
|
||||||
|
for (size_t i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
size_t idx = ctx->stack_size - i - 1;
|
||||||
|
if (idx < MAX_TEMP_TYPES)
|
||||||
|
ctx->temp_types[idx] = T_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->stack_size -= n;
|
ctx->stack_size -= n;
|
||||||
|
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get an operand pointing to a slot on the temp stack
|
||||||
|
*/
|
||||||
x86opnd_t
|
x86opnd_t
|
||||||
ctx_stack_opnd(ctx_t* ctx, int32_t idx)
|
ctx_stack_opnd(ctx_t* ctx, int32_t idx)
|
||||||
{
|
{
|
||||||
|
@ -70,6 +88,21 @@ ctx_stack_opnd(ctx_t* ctx, int32_t idx)
|
||||||
return opnd;
|
return opnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the type of the topmost value on the temp stack
|
||||||
|
Returns T_NONE if unknown
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ctx_get_top_type(ctx_t* ctx)
|
||||||
|
{
|
||||||
|
RUBY_ASSERT(n <= ctx->stack_size);
|
||||||
|
|
||||||
|
if (ctx->stack_size > MAX_TEMP_TYPES)
|
||||||
|
return T_NONE;
|
||||||
|
|
||||||
|
return ctx->temp_types[ctx->stack_size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
// Add an incoming branch for a given block version
|
// Add an incoming branch for a given block version
|
||||||
static void add_incoming(block_t* p_block, uint32_t branch_idx)
|
static void add_incoming(block_t* p_block, uint32_t branch_idx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -112,13 +112,11 @@ typedef struct BlockVersion
|
||||||
} block_t;
|
} block_t;
|
||||||
|
|
||||||
// Context object methods
|
// Context object methods
|
||||||
int ctx_get_opcode(ctx_t *ctx);
|
|
||||||
uint32_t ctx_next_idx(ctx_t* ctx);
|
|
||||||
VALUE ctx_get_arg(ctx_t* ctx, size_t arg_idx);
|
|
||||||
x86opnd_t ctx_sp_opnd(ctx_t* ctx, int32_t offset_bytes);
|
x86opnd_t ctx_sp_opnd(ctx_t* ctx, int32_t offset_bytes);
|
||||||
x86opnd_t ctx_stack_push(ctx_t* ctx, size_t n);
|
x86opnd_t ctx_stack_push(ctx_t* ctx, int type);
|
||||||
x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n);
|
x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n);
|
||||||
x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
|
x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
|
||||||
|
int ctx_get_top_type(ctx_t* ctx);
|
||||||
|
|
||||||
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx);
|
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx);
|
||||||
block_t* gen_block_version(blockid_t blockid, const ctx_t* ctx);
|
block_t* gen_block_version(blockid_t blockid, const ctx_t* ctx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue