diff --git a/ujit_codegen.c b/ujit_codegen.c index c51f7b1944..4897e38cde 100644 --- a/ujit_codegen.c +++ b/ujit_codegen.c @@ -34,6 +34,9 @@ static void ujit_gen_entry(codeblock_t* cb) { cb_write_pre_call_bytes(cb); + + // Load the current SP from the CFP into REG_SP + mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp)); } /** @@ -98,7 +101,7 @@ Compile a sequence of bytecode instructions starting at `insn_idx`. Returns `NULL` if compilation fails. */ uint8_t * -ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx) +ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry) { assert (cb != NULL); unsigned first_insn_idx = insn_idx; @@ -147,12 +150,10 @@ ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx) break; } - // Write the pre call bytes before the first instruction - if (num_instrs == 0) { + // If requested, write the interpreter entry + // prologue before the first instruction + if (gen_entry && num_instrs == 0) { ujit_gen_entry(cb); - - // Load the current SP from the CFP into REG_SP - mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp)); } // Call the code generation function diff --git a/ujit_codegen.h b/ujit_codegen.h index 7c03420097..5216dbb1be 100644 --- a/ujit_codegen.h +++ b/ujit_codegen.h @@ -3,7 +3,7 @@ #include "stddef.h" -uint8_t * ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx); +uint8_t *ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry); void ujit_init_codegen(void); diff --git a/ujit_core.c b/ujit_core.c index 261a33315f..c981ef0e30 100644 --- a/ujit_core.c +++ b/ujit_core.c @@ -2,35 +2,56 @@ #include "ujit_asm.h" #include "ujit_iface.h" #include "ujit_core.h" - - - +#include "ujit_codegen.h" // Table of block versions indexed by (iseq, index) tuples st_table * version_tbl; -/* -struct st_hash_type { - int (*compare)(st_data_t, st_data_t); // st_compare_func* - st_index_t (*hash)(st_data_t); // st_hash_func* -}; - -static const struct st_hash_type st_hashtype_num = { - st_numcmp, - st_numhash, -}; - -strcasehash(st_data_t arg) +int blockid_cmp(st_data_t arg0, st_data_t arg1) { - register const char *string = (const char *)arg; - ... + const blockid_t *block0 = (const blockid_t*)arg0; + const blockid_t *block1 = (const blockid_t*)arg1; + return block0->iseq == block1->iseq && block0->idx == block1->idx; } -*/ +st_index_t blockid_hash(st_data_t arg) +{ + const blockid_t *blockid = (const blockid_t*)arg; + st_index_t hash0 = st_numhash((st_data_t)blockid->iseq); + st_index_t hash1 = st_numhash((st_data_t)blockid->idx); + // Use XOR to combine the hashes + return hash0 ^ hash1; +} +static const struct st_hash_type hashtype_blockid = { + blockid_cmp, + blockid_hash, +}; +// Retrieve a basic block version for an (iseq, idx) tuple +// TODO: we need to add a versioning context here +uint8_t* get_block_version(const rb_iseq_t *iseq, unsigned int idx /*, ctx_t* ctx */) +{ + blockid_t blockid = { iseq, idx }; + // If there exists a version for this block id + st_data_t st_version; + if (rb_st_lookup(version_tbl, (st_data_t)&blockid, &st_version)) { + return (uint8_t*)st_version; + } + + uint8_t* code_ptr = ujit_compile_block(iseq, idx, false); + + st_insert(version_tbl, (st_data_t)&blockid, (st_data_t)code_ptr); + + return code_ptr; +} + +// +// Method to generate stubs for branches +// TODO: get_branch_stub() or get_branch() function +// // Get the current instruction opcode from the context object int @@ -96,3 +117,10 @@ ctx_stack_opnd(ctx_t* ctx, int32_t idx) return opnd; } + +void +ujit_init_core(void) +{ + // Initialize the version hash table + version_tbl = st_init_table(&hashtype_blockid); +} diff --git a/ujit_core.h b/ujit_core.h index 320be8fa01..f42ff84ace 100644 --- a/ujit_core.h +++ b/ujit_core.h @@ -20,6 +20,17 @@ // Maximum number of versions per block #define MAX_VERSIONS 5 +// Tuple of (iseq, idx) used to idenfity basic blocks +typedef struct BlockId +{ + // Instruction sequence + const rb_iseq_t *iseq; + + // Instruction index + const unsigned int idx; + +} blockid_t; + // Code generation context typedef struct ctx_struct { @@ -48,6 +59,7 @@ typedef struct ctx_struct } ctx_t; +// Context object methods int ctx_get_opcode(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); @@ -55,4 +67,6 @@ 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 ujit_init_core(void); + #endif // #ifndef UJIT_CORE_H diff --git a/ujit_iface.c b/ujit_iface.c index ac541b7cdc..e30e3afa3b 100644 --- a/ujit_iface.c +++ b/ujit_iface.c @@ -233,7 +233,7 @@ rb_ujit_compile_iseq(const rb_iseq_t *iseq) VALUE *encoded = (VALUE *)iseq->body->iseq_encoded; // Compile a block version starting at the first instruction - uint8_t* native_code_ptr = ujit_compile_block(iseq, 0); + uint8_t* native_code_ptr = ujit_compile_block(iseq, 0, true); if (native_code_ptr) { encoded[0] = (VALUE)native_code_ptr; @@ -253,7 +253,7 @@ rb_ujit_init(void) rb_ujit_enabled = true; - // Initialize ujit codegen + ujit_init_core(); ujit_init_codegen(); // Initialize the GC hooks