Use a versioning context when compiling blocks

This commit is contained in:
Maxime Chevalier-Boisvert 2020-12-18 15:52:13 -05:00 коммит произвёл Alan Wu
Родитель df16bf97ec
Коммит 542f2ba09e
4 изменённых файлов: 18 добавлений и 12 удалений

Просмотреть файл

@ -129,9 +129,12 @@ uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx)
// Write the interpreter entry prologue // Write the interpreter entry prologue
ujit_gen_entry(cb); ujit_gen_entry(cb);
// Create codegen context
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 = 0;
ujit_compile_block(iseq, insn_idx, &num_instrs); 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) {
@ -152,7 +155,7 @@ 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`.
*/ */
uint8_t * uint8_t *
ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, uint32_t* num_instrs) ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs)
{ {
assert (cb != NULL); assert (cb != NULL);
VALUE *encoded = iseq->body->iseq_encoded; VALUE *encoded = iseq->body->iseq_encoded;
@ -175,9 +178,6 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, uint32_t* num_instr
jit.iseq = iseq; jit.iseq = iseq;
jit.start_idx = insn_idx; jit.start_idx = insn_idx;
// Create codegen context
ctx_t ctx = { 0 };
// For each instruction to compile // For each instruction to compile
for (;;) { for (;;) {
// Set the current instruction // Set the current instruction
@ -201,7 +201,7 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, uint32_t* num_instr
// Call the code generation function // Call the code generation function
codegen_fn gen_fn = (codegen_fn)st_gen_fn; codegen_fn gen_fn = (codegen_fn)st_gen_fn;
if (!gen_fn(&jit, &ctx)) { if (!gen_fn(&jit, ctx)) {
break; break;
} }
@ -222,7 +222,7 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, uint32_t* num_instr
// FIXME: we only need to generate an exit if an instruction fails to compile // FIXME: we only need to generate an exit if an instruction fails to compile
// //
// Generate code to exit to the interpreter // Generate code to exit to the interpreter
ujit_gen_exit(&jit, &ctx, cb, &encoded[insn_idx]); ujit_gen_exit(&jit, ctx, cb, &encoded[insn_idx]);
if (UJIT_DUMP_MODE >= 2) { if (UJIT_DUMP_MODE >= 2) {
// Dump list of compiled instrutions // Dump list of compiled instrutions
@ -958,7 +958,7 @@ gen_branchunless(jitstate_t* jit, ctx_t* ctx)
blockid_t jump_block = { jit->iseq, jump_idx }; blockid_t jump_block = { jit->iseq, jump_idx };
// Generate the branch instructions // Generate the branch instructions
gen_branch(cb, ocb, jump_block, next_block, gen_branchunless_branch); gen_branch(ctx, jump_block, next_block, gen_branchunless_branch);
return true; return true;
} }

Просмотреть файл

@ -2,6 +2,7 @@
#define UJIT_CODEGEN_H 1 #define UJIT_CODEGEN_H 1
#include "stddef.h" #include "stddef.h"
#include "ujit_core.h"
// Code blocks we generate code into // Code blocks we generate code into
codeblock_t* cb; codeblock_t* cb;
@ -29,7 +30,7 @@ typedef bool (*codegen_fn)(jitstate_t* jit, ctx_t* ctx);
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);
uint8_t *ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, uint32_t* num_instrs); uint8_t *ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs);
void ujit_init_codegen(void); void ujit_init_codegen(void);

Просмотреть файл

@ -133,8 +133,9 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
{ {
//fprintf(stderr, "compiling block\n"); //fprintf(stderr, "compiling block\n");
ctx_t ctx = branch->ctx;
uint32_t num_instrs = 0; uint32_t num_instrs = 0;
block_ptr = ujit_compile_block(target.iseq, target.idx, &num_instrs); 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); st_insert(version_tbl, (st_data_t)&target, (st_data_t)block_ptr);
branch->dst_addrs[target_idx] = block_ptr; branch->dst_addrs[target_idx] = block_ptr;
} }
@ -192,7 +193,7 @@ uint8_t* get_branch_target(codeblock_t* ocb, blockid_t target, uint32_t branch_i
return stub_addr; return stub_addr;
} }
void gen_branch(codeblock_t* cb, codeblock_t* ocb, blockid_t target0, blockid_t target1, branchgen_fn gen_fn) void gen_branch(ctx_t* ctx, blockid_t target0, blockid_t target1, branchgen_fn gen_fn)
{ {
// Get branch targets or stubs (code pointers) // Get branch targets or stubs (code pointers)
uint8_t* dst_addr0 = get_branch_target(ocb, target0, num_branches, 0); uint8_t* dst_addr0 = get_branch_target(ocb, target0, num_branches, 0);
@ -207,6 +208,7 @@ void gen_branch(codeblock_t* cb, codeblock_t* ocb, blockid_t target0, blockid_t
// Register this branch entry // Register this branch entry
branch_t branch_entry = { branch_t branch_entry = {
*ctx,
start_pos, start_pos,
end_pos, end_pos,
{ target0, target1 }, { target0, target1 },

Просмотреть файл

@ -56,6 +56,9 @@ typedef void (*branchgen_fn)(codeblock_t* cb, uint8_t* target0, uint8_t* target1
// Store info about an outgoing branch in a code segment // Store info about an outgoing branch in a code segment
typedef struct BranchEntry typedef struct BranchEntry
{ {
// Context right after the branch instruction
ctx_t ctx;
// Positions where the generated code starts and ends // Positions where the generated code starts and ends
uint32_t start_pos; uint32_t start_pos;
uint32_t end_pos; uint32_t end_pos;
@ -83,7 +86,7 @@ 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_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);
void gen_branch(codeblock_t* cb, codeblock_t* ocb, blockid_t target0, blockid_t target1, branchgen_fn gen_fn); void gen_branch(ctx_t* ctx, blockid_t target0, blockid_t target1, branchgen_fn gen_fn);
void ujit_init_core(void); void ujit_init_core(void);