mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Refactorings in ujit. Implement Ruby jump instruction.
This commit is contained in:
parent
1744c15578
commit
2cc0db12fe
3 changed files with 130 additions and 20 deletions
|
@ -972,7 +972,70 @@ gen_branchunless(jitstate_t* jit, ctx_t* ctx)
|
|||
blockid_t jump_block = { jit->iseq, jump_idx };
|
||||
|
||||
// Generate the branch instructions
|
||||
gen_branch(ctx, jump_block, next_block, gen_branchunless_branch);
|
||||
gen_branch(
|
||||
ctx,
|
||||
jump_block,
|
||||
ctx,
|
||||
next_block,
|
||||
ctx,
|
||||
gen_branchunless_branch
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
gen_jump_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case SHAPE_NEXT0:
|
||||
break;
|
||||
|
||||
case SHAPE_NEXT1:
|
||||
assert (false);
|
||||
break;
|
||||
|
||||
case SHAPE_DEFAULT:
|
||||
jmp_ptr(cb, target0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
gen_jump(jitstate_t* jit, ctx_t* ctx)
|
||||
{
|
||||
// Get the branch target instruction offsets
|
||||
uint32_t next_idx = jit_next_idx(jit);
|
||||
uint32_t jump_idx = next_idx + (uint32_t)jit_get_arg(jit, 0);
|
||||
blockid_t jump_block = { jit->iseq, jump_idx };
|
||||
|
||||
//
|
||||
// TODO:
|
||||
// RUBY_VM_CHECK_INTS(ec);
|
||||
//
|
||||
|
||||
//print_str(cb, "jump!");
|
||||
//print_int(cb, imm_opnd(jump_idx));
|
||||
|
||||
// If the jump target was already compiled
|
||||
if (find_block_version(jump_block, ctx))
|
||||
{
|
||||
// Generate the jump instruction
|
||||
gen_branch(
|
||||
ctx,
|
||||
jump_block,
|
||||
ctx,
|
||||
BLOCKID_NULL,
|
||||
ctx,
|
||||
gen_jump_branch
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No need for a jump, compile the target block right here
|
||||
gen_block_version(jump_block, ctx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1024,4 +1087,5 @@ ujit_init_codegen(void)
|
|||
ujit_reg_op(BIN(opt_plus), gen_opt_plus, false);
|
||||
//ujit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block);
|
||||
ujit_reg_op(BIN(branchunless), gen_branchunless, true);
|
||||
ujit_reg_op(BIN(jump), gen_jump, true);
|
||||
}
|
||||
|
|
60
ujit_core.c
60
ujit_core.c
|
@ -70,7 +70,7 @@ ctx_stack_opnd(ctx_t* ctx, int32_t idx)
|
|||
}
|
||||
|
||||
// Retrieve a basic block version for an (iseq, idx) tuple
|
||||
uint8_t* find_block_version(blockid_t block)
|
||||
uint8_t* find_block_version(blockid_t block, const ctx_t* ctx)
|
||||
{
|
||||
// If there exists a version for this block id
|
||||
st_data_t st_version;
|
||||
|
@ -78,9 +78,28 @@ uint8_t* find_block_version(blockid_t block)
|
|||
return (uint8_t*)st_version;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: use the ctx parameter to search available versions
|
||||
//
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Compile a new block version immediately
|
||||
uint8_t* gen_block_version(blockid_t block, const ctx_t* ctx)
|
||||
{
|
||||
// Copy the context object to avoid modifying it
|
||||
ctx_t ctx_copy = *ctx;
|
||||
|
||||
uint32_t num_instrs = 0;
|
||||
uint8_t* block_ptr = ujit_compile_block(block.iseq, block.idx, &ctx_copy, &num_instrs);
|
||||
|
||||
// Keep track of the new block version
|
||||
st_insert(version_tbl, (st_data_t)&block, (st_data_t)block_ptr);
|
||||
|
||||
return block_ptr;
|
||||
}
|
||||
|
||||
// Called by the generated code when a branch stub is executed
|
||||
// Triggers compilation of branches and code patching
|
||||
uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
|
||||
|
@ -89,6 +108,7 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
|
|||
assert (target_idx < 2);
|
||||
branch_t *branch = &branch_entries[branch_idx];
|
||||
blockid_t target = branch->targets[target_idx];
|
||||
ctx_t* target_ctx = &branch->target_ctxs[target_idx];
|
||||
|
||||
//fprintf(stderr, "\nstub hit, branch idx: %d, target idx: %d\n", branch_idx, target_idx);
|
||||
//fprintf(stderr, "cb->write_pos=%ld\n", cb->write_pos);
|
||||
|
@ -107,20 +127,18 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
|
|||
}
|
||||
|
||||
// Try to find a compiled version of this block
|
||||
uint8_t* block_ptr = find_block_version(target);
|
||||
uint8_t* block_ptr = find_block_version(target, target_ctx);
|
||||
|
||||
// If this block hasn't yet been compiled
|
||||
if (!block_ptr)
|
||||
{
|
||||
//fprintf(stderr, "compiling block\n");
|
||||
|
||||
ctx_t ctx = branch->ctx;
|
||||
uint32_t num_instrs = 0;
|
||||
block_ptr = ujit_compile_block(target.iseq, target.idx, &ctx, &num_instrs);
|
||||
st_insert(version_tbl, (st_data_t)&target, (st_data_t)block_ptr);
|
||||
branch->dst_addrs[target_idx] = block_ptr;
|
||||
block_ptr = gen_block_version(target, target_ctx);
|
||||
}
|
||||
|
||||
// Update the branch target address
|
||||
branch->dst_addrs[target_idx] = block_ptr;
|
||||
|
||||
//fprintf(stderr, "rewrite branch at %d\n", branch->start_pos);
|
||||
|
||||
// Rewrite the branch with the new jump target address
|
||||
|
@ -138,9 +156,15 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
|
|||
|
||||
// Get a version or stub corresponding to a branch target
|
||||
// TODO: need incoming and target versioning contexts
|
||||
uint8_t* get_branch_target(codeblock_t* ocb, blockid_t target, uint32_t branch_idx, uint32_t target_idx)
|
||||
uint8_t* get_branch_target(
|
||||
blockid_t target,
|
||||
const ctx_t* ctx,
|
||||
codeblock_t* ocb,
|
||||
uint32_t branch_idx,
|
||||
uint32_t target_idx
|
||||
)
|
||||
{
|
||||
uint8_t* block_code = find_block_version(target);
|
||||
uint8_t* block_code = find_block_version(target, ctx);
|
||||
|
||||
if (block_code)
|
||||
return block_code;
|
||||
|
@ -174,11 +198,18 @@ uint8_t* get_branch_target(codeblock_t* ocb, blockid_t target, uint32_t branch_i
|
|||
return stub_addr;
|
||||
}
|
||||
|
||||
void gen_branch(ctx_t* ctx, blockid_t target0, blockid_t target1, branchgen_fn gen_fn)
|
||||
void gen_branch(
|
||||
const ctx_t* src_ctx,
|
||||
blockid_t target0,
|
||||
const ctx_t* ctx0,
|
||||
blockid_t target1,
|
||||
const ctx_t* ctx1,
|
||||
branchgen_fn gen_fn
|
||||
)
|
||||
{
|
||||
// Get branch targets or stubs (code pointers)
|
||||
uint8_t* dst_addr0 = get_branch_target(ocb, target0, num_branches, 0);
|
||||
uint8_t* dst_addr1 = get_branch_target(ocb, target1, num_branches, 1);
|
||||
uint8_t* dst_addr0 = get_branch_target(target0, ctx0, ocb, num_branches, 0);
|
||||
uint8_t* dst_addr1 = get_branch_target(target1, ctx1, ocb, num_branches, 1);
|
||||
|
||||
uint32_t start_pos = (uint32_t)cb->write_pos;
|
||||
|
||||
|
@ -189,10 +220,11 @@ void gen_branch(ctx_t* ctx, blockid_t target0, blockid_t target1, branchgen_fn g
|
|||
|
||||
// Register this branch entry
|
||||
branch_t branch_entry = {
|
||||
*ctx,
|
||||
start_pos,
|
||||
end_pos,
|
||||
*src_ctx,
|
||||
{ target0, target1 },
|
||||
{ *ctx0, *ctx1 },
|
||||
{ dst_addr0, dst_addr1 },
|
||||
gen_fn,
|
||||
SHAPE_DEFAULT
|
||||
|
|
24
ujit_core.h
24
ujit_core.h
|
@ -42,6 +42,9 @@ typedef struct BlockId
|
|||
|
||||
} blockid_t;
|
||||
|
||||
// Null block id constant
|
||||
static const blockid_t BLOCKID_NULL = { 0, 0 };
|
||||
|
||||
/// Branch code shape enumeration
|
||||
enum uint8_t
|
||||
{
|
||||
|
@ -56,15 +59,16 @@ typedef void (*branchgen_fn)(codeblock_t* cb, uint8_t* target0, uint8_t* target1
|
|||
// Store info about an outgoing branch in a code segment
|
||||
typedef struct BranchEntry
|
||||
{
|
||||
// Context right after the branch instruction
|
||||
ctx_t ctx;
|
||||
|
||||
// Positions where the generated code starts and ends
|
||||
uint32_t start_pos;
|
||||
uint32_t end_pos;
|
||||
|
||||
// Branch target blocks
|
||||
// Context right after the branch instruction
|
||||
ctx_t src_ctx;
|
||||
|
||||
// Branch target blocks and their contexts
|
||||
blockid_t targets[2];
|
||||
ctx_t target_ctxs[2];
|
||||
|
||||
// Jump target addresses
|
||||
uint8_t* dst_addrs[2];
|
||||
|
@ -86,7 +90,17 @@ x86opnd_t ctx_stack_push(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);
|
||||
|
||||
void gen_branch(ctx_t* ctx, blockid_t target0, blockid_t target1, branchgen_fn gen_fn);
|
||||
uint8_t* find_block_version(blockid_t block, const ctx_t* ctx);
|
||||
uint8_t* gen_block_version(blockid_t block, const ctx_t* ctx);
|
||||
|
||||
void gen_branch(
|
||||
const ctx_t* src_ctx,
|
||||
blockid_t target0,
|
||||
const ctx_t* ctx0,
|
||||
blockid_t target1,
|
||||
const ctx_t* ctx1,
|
||||
branchgen_fn gen_fn
|
||||
);
|
||||
|
||||
void ujit_init_core(void);
|
||||
|
||||
|
|
Loading…
Reference in a new issue