Progress on code invalidation
This commit is contained in:
parent
3a74011ff8
commit
ef08af9376
@ -133,8 +133,7 @@ uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx)
|
|||||||
ctx_t ctx = { 0 };
|
ctx_t ctx = { 0 };
|
||||||
|
|
||||||
// Compile the block starting at this instruction
|
// Compile the block starting at this instruction
|
||||||
uint32_t num_instrs = 0;
|
uint32_t num_instrs = ujit_compile_block(iseq, insn_idx, &ctx);
|
||||||
ujit_compile_block(iseq, insn_idx, &ctx, &num_instrs);
|
|
||||||
|
|
||||||
// If no instructions were compiled
|
// If no instructions were compiled
|
||||||
if (num_instrs == 0) {
|
if (num_instrs == 0) {
|
||||||
@ -154,8 +153,8 @@ uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx)
|
|||||||
/*
|
/*
|
||||||
Compile a sequence of bytecode instructions starting at `insn_idx`.
|
Compile a sequence of bytecode instructions starting at `insn_idx`.
|
||||||
*/
|
*/
|
||||||
void
|
uint32_t
|
||||||
ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs)
|
ujit_compile_block(/*version_t* version,*/ const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
assert (cb != NULL);
|
assert (cb != NULL);
|
||||||
VALUE *encoded = iseq->body->iseq_encoded;
|
VALUE *encoded = iseq->body->iseq_encoded;
|
||||||
@ -175,10 +174,13 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_
|
|||||||
|
|
||||||
// Initialize JIT state object
|
// Initialize JIT state object
|
||||||
jitstate_t jit = {
|
jitstate_t jit = {
|
||||||
|
NULL,
|
||||||
iseq,
|
iseq,
|
||||||
insn_idx
|
insn_idx
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t num_instrs = 0;
|
||||||
|
|
||||||
// For each instruction to compile
|
// For each instruction to compile
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Set the current instruction
|
// Set the current instruction
|
||||||
@ -209,7 +211,7 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_
|
|||||||
// Move to the next instruction
|
// Move to the next instruction
|
||||||
p_last_op = p_desc;
|
p_last_op = p_desc;
|
||||||
insn_idx += insn_len(opcode);
|
insn_idx += insn_len(opcode);
|
||||||
(*num_instrs)++;
|
num_instrs++;
|
||||||
|
|
||||||
// If this instruction terminates this block
|
// If this instruction terminates this block
|
||||||
if (p_desc->is_branch) {
|
if (p_desc->is_branch) {
|
||||||
@ -234,6 +236,8 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_
|
|||||||
pc += insn_len(opcode);
|
pc += insn_len(opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return num_instrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -11,6 +11,9 @@ codeblock_t* ocb;
|
|||||||
// Code generation state
|
// Code generation state
|
||||||
typedef struct JITState
|
typedef struct JITState
|
||||||
{
|
{
|
||||||
|
// Block version being compiled
|
||||||
|
version_t* version;
|
||||||
|
|
||||||
// Instruction sequence this is associated with
|
// Instruction sequence this is associated with
|
||||||
const rb_iseq_t *iseq;
|
const rb_iseq_t *iseq;
|
||||||
|
|
||||||
@ -42,7 +45,7 @@ typedef struct OpDesc
|
|||||||
|
|
||||||
uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx);
|
uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx);
|
||||||
|
|
||||||
void ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs);
|
uint32_t ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx);
|
||||||
|
|
||||||
void ujit_init_codegen(void);
|
void ujit_init_codegen(void);
|
||||||
|
|
||||||
|
29
ujit_core.c
29
ujit_core.c
@ -95,9 +95,8 @@ version_t* gen_block_version(blockid_t blockid, const ctx_t* ctx)
|
|||||||
|
|
||||||
// Compile the block version
|
// Compile the block version
|
||||||
ctx_t ctx_copy = *ctx;
|
ctx_t ctx_copy = *ctx;
|
||||||
uint32_t num_instrs = 0;
|
|
||||||
p_version->start_pos = cb->write_pos;
|
p_version->start_pos = cb->write_pos;
|
||||||
ujit_compile_block(blockid.iseq, blockid.idx, &ctx_copy, &num_instrs);
|
ujit_compile_block(blockid.iseq, blockid.idx, &ctx_copy);
|
||||||
p_version->end_pos = cb->write_pos;
|
p_version->end_pos = cb->write_pos;
|
||||||
|
|
||||||
// Keep track of the new block version
|
// Keep track of the new block version
|
||||||
@ -159,7 +158,7 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get a version or stub corresponding to a branch target
|
// Get a version or stub corresponding to a branch target
|
||||||
// TODO: need incoming and target versioning contexts
|
// TODO: need incoming and target contexts
|
||||||
uint8_t* get_branch_target(
|
uint8_t* get_branch_target(
|
||||||
blockid_t target,
|
blockid_t target,
|
||||||
const ctx_t* ctx,
|
const ctx_t* ctx,
|
||||||
@ -237,6 +236,30 @@ void gen_branch(
|
|||||||
assert (num_branches < MAX_BRANCHES);
|
assert (num_branches < MAX_BRANCHES);
|
||||||
branch_entries[num_branches] = branch_entry;
|
branch_entries[num_branches] = branch_entry;
|
||||||
num_branches++;
|
num_branches++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate one specific block version
|
||||||
|
void invalidate(version_t* version)
|
||||||
|
{
|
||||||
|
// All branches jumping to the block should be atomically patched with jumps going to a stub instead.
|
||||||
|
|
||||||
|
// There can also be other blocks falling through to the invalidated block because they immediately precede it.
|
||||||
|
// - If an incoming fall-through branch is too short to be patched, we may need to invalidate its block
|
||||||
|
// - This may not be an issue in practice, because the block we go to could have space
|
||||||
|
// - We can force any block that may need to be invalidated to have sufficient space to contain a jump to a stub
|
||||||
|
|
||||||
|
// If the block is an entry point, it needs to be unmapped from its iseq
|
||||||
|
// Unmap/remap anything at this iseq/idx
|
||||||
|
|
||||||
|
// Optional: may want to recompile a new deoptimized entry point
|
||||||
|
// Call continuation addresses on the stack can also be atomically replaced by jumps going to the stub.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int blockid_cmp(st_data_t arg0, st_data_t arg1)
|
int blockid_cmp(st_data_t arg0, st_data_t arg1)
|
||||||
|
@ -122,6 +122,8 @@ void gen_branch(
|
|||||||
branchgen_fn gen_fn
|
branchgen_fn gen_fn
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void invalidate(version_t* version);
|
||||||
|
|
||||||
void ujit_init_core(void);
|
void ujit_init_core(void);
|
||||||
|
|
||||||
#endif // #ifndef UJIT_CORE_H
|
#endif // #ifndef UJIT_CORE_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user