mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Thread insn_idx through context object
This commit is contained in:
parent
868a6809e7
commit
bd7cc9ed98
4 changed files with 27 additions and 30 deletions
|
@ -65,7 +65,7 @@ ujit_gen_exit(codeblock_t* cb, ctx_t* ctx, VALUE* exit_pc)
|
||||||
Generate an out-of-line exit to return to the interpreter
|
Generate an out-of-line exit to return to the interpreter
|
||||||
*/
|
*/
|
||||||
static uint8_t *
|
static uint8_t *
|
||||||
ujit_side_exit(codeblock_t* cb, ctx_t* ctx, VALUE* exit_pc)
|
ujit_side_exit(codeblock_t* cb, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
uint8_t* code_ptr = cb_get_ptr(cb, cb->write_pos);
|
uint8_t* code_ptr = cb_get_ptr(cb, cb->write_pos);
|
||||||
|
|
||||||
|
@ -84,6 +84,7 @@ ujit_side_exit(codeblock_t* cb, ctx_t* ctx, VALUE* exit_pc)
|
||||||
// Write back the old instruction at the exit PC
|
// Write back the old instruction at the exit PC
|
||||||
// Otherwise the interpreter may jump right back to the
|
// Otherwise the interpreter may jump right back to the
|
||||||
// JITted code we're trying to exit
|
// JITted code we're trying to exit
|
||||||
|
VALUE* exit_pc = &ctx->iseq->body->iseq_encoded[ctx->insn_idx];
|
||||||
int exit_opcode = opcode_at_pc(ctx->iseq, exit_pc);
|
int exit_opcode = opcode_at_pc(ctx->iseq, exit_pc);
|
||||||
void* exit_instr = (void*)table[exit_opcode];
|
void* exit_instr = (void*)table[exit_opcode];
|
||||||
mov(cb, RAX, const_ptr_opnd(exit_pc));
|
mov(cb, RAX, const_ptr_opnd(exit_pc));
|
||||||
|
@ -101,10 +102,9 @@ Compile a sequence of bytecode instructions starting at `insn_idx`.
|
||||||
Returns `NULL` if compilation fails.
|
Returns `NULL` if compilation fails.
|
||||||
*/
|
*/
|
||||||
uint8_t *
|
uint8_t *
|
||||||
ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry)
|
ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool gen_entry)
|
||||||
{
|
{
|
||||||
assert (cb != NULL);
|
assert (cb != NULL);
|
||||||
unsigned first_insn_idx = insn_idx;
|
|
||||||
VALUE *encoded = iseq->body->iseq_encoded;
|
VALUE *encoded = iseq->body->iseq_encoded;
|
||||||
|
|
||||||
// NOTE: if we are ever deployed in production, we
|
// NOTE: if we are ever deployed in production, we
|
||||||
|
@ -136,7 +136,8 @@ ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry)
|
||||||
// For each instruction to compile
|
// For each instruction to compile
|
||||||
unsigned num_instrs = 0;
|
unsigned num_instrs = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Set the current PC
|
// Set the current instruction
|
||||||
|
ctx.insn_idx = insn_idx;
|
||||||
ctx.pc = &encoded[insn_idx];
|
ctx.pc = &encoded[insn_idx];
|
||||||
|
|
||||||
// Get the current opcode
|
// Get the current opcode
|
||||||
|
@ -187,7 +188,7 @@ ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry)
|
||||||
if (UJIT_DUMP_MODE >= 2) {
|
if (UJIT_DUMP_MODE >= 2) {
|
||||||
// Dump list of compiled instrutions
|
// Dump list of compiled instrutions
|
||||||
fprintf(stderr, "Compiled the following for iseq=%p:\n", (void *)iseq);
|
fprintf(stderr, "Compiled the following for iseq=%p:\n", (void *)iseq);
|
||||||
VALUE *pc = &encoded[first_insn_idx];
|
VALUE *pc = &encoded[ctx.start_idx];
|
||||||
VALUE *end_pc = &encoded[insn_idx];
|
VALUE *end_pc = &encoded[insn_idx];
|
||||||
while (pc < end_pc) {
|
while (pc < end_pc) {
|
||||||
int opcode = opcode_at_pc(iseq, pc);
|
int opcode = opcode_at_pc(iseq, pc);
|
||||||
|
@ -199,15 +200,6 @@ ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry)
|
||||||
return code_ptr;
|
return code_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
gen_dup(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
gen_dup(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
|
@ -248,7 +240,7 @@ static bool
|
||||||
gen_putobject(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
gen_putobject(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
// Load the argument from the bytecode sequence.
|
// Load the argument from the bytecode sequence.
|
||||||
// We need to do this as the argument can chanage due to GC compaction.
|
// We need to do this as the argument can change due to GC compaction.
|
||||||
x86opnd_t pc_imm = const_ptr_opnd((void*)ctx->pc);
|
x86opnd_t pc_imm = const_ptr_opnd((void*)ctx->pc);
|
||||||
mov(cb, RAX, pc_imm);
|
mov(cb, RAX, pc_imm);
|
||||||
mov(cb, RAX, mem_opnd(64, RAX, 8)); // One after the opcode
|
mov(cb, RAX, mem_opnd(64, RAX, 8)); // One after the opcode
|
||||||
|
@ -330,7 +322,7 @@ gen_setlocal_wc0(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED));
|
test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED));
|
||||||
|
|
||||||
// Create a size-exit to fall back to the interpreter
|
// Create a size-exit to fall back to the interpreter
|
||||||
uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc);
|
uint8_t* side_exit = ujit_side_exit(ocb, ctx);
|
||||||
|
|
||||||
// if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
|
// if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
|
||||||
jnz_ptr(cb, side_exit);
|
jnz_ptr(cb, side_exit);
|
||||||
|
@ -386,7 +378,7 @@ gen_getinstancevariable(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
uint32_t ivar_index = ic->entry->index;
|
uint32_t ivar_index = ic->entry->index;
|
||||||
|
|
||||||
// Create a size-exit to fall back to the interpreter
|
// Create a size-exit to fall back to the interpreter
|
||||||
uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc);
|
uint8_t* side_exit = ujit_side_exit(ocb, ctx);
|
||||||
|
|
||||||
// Load self from CFP
|
// Load self from CFP
|
||||||
mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, self));
|
mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, self));
|
||||||
|
@ -448,7 +440,7 @@ gen_setinstancevariable(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
uint32_t ivar_index = ic->entry->index;
|
uint32_t ivar_index = ic->entry->index;
|
||||||
|
|
||||||
// Create a size-exit to fall back to the interpreter
|
// Create a size-exit to fall back to the interpreter
|
||||||
uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc);
|
uint8_t* side_exit = ujit_side_exit(ocb, ctx);
|
||||||
|
|
||||||
// Load self from CFP
|
// Load self from CFP
|
||||||
mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, self));
|
mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, self));
|
||||||
|
@ -501,7 +493,7 @@ gen_opt_lt(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
// Create a size-exit to fall back to the interpreter
|
// Create a size-exit to fall back to the interpreter
|
||||||
// Note: we generate the side-exit before popping operands from the stack
|
// Note: we generate the side-exit before popping operands from the stack
|
||||||
uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc);
|
uint8_t* side_exit = ujit_side_exit(ocb, ctx);
|
||||||
|
|
||||||
// TODO: make a helper function for guarding on op-not-redefined
|
// TODO: make a helper function for guarding on op-not-redefined
|
||||||
// Make sure that minus isn't redefined for integers
|
// Make sure that minus isn't redefined for integers
|
||||||
|
@ -542,7 +534,7 @@ gen_opt_minus(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
// Create a size-exit to fall back to the interpreter
|
// Create a size-exit to fall back to the interpreter
|
||||||
// Note: we generate the side-exit before popping operands from the stack
|
// Note: we generate the side-exit before popping operands from the stack
|
||||||
uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc);
|
uint8_t* side_exit = ujit_side_exit(ocb, ctx);
|
||||||
|
|
||||||
// TODO: make a helper function for guarding on op-not-redefined
|
// TODO: make a helper function for guarding on op-not-redefined
|
||||||
// Make sure that minus isn't redefined for integers
|
// Make sure that minus isn't redefined for integers
|
||||||
|
@ -582,7 +574,7 @@ gen_opt_plus(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
// Create a size-exit to fall back to the interpreter
|
// Create a size-exit to fall back to the interpreter
|
||||||
// Note: we generate the side-exit before popping operands from the stack
|
// Note: we generate the side-exit before popping operands from the stack
|
||||||
uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc);
|
uint8_t* side_exit = ujit_side_exit(ocb, ctx);
|
||||||
|
|
||||||
// TODO: make a helper function for guarding on op-not-redefined
|
// TODO: make a helper function for guarding on op-not-redefined
|
||||||
// Make sure that plus isn't redefined for integers
|
// Make sure that plus isn't redefined for integers
|
||||||
|
@ -711,7 +703,7 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a size-exit to fall back to the interpreter
|
// Create a size-exit to fall back to the interpreter
|
||||||
uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc);
|
uint8_t* side_exit = ujit_side_exit(ocb, ctx);
|
||||||
|
|
||||||
// Check for interrupts
|
// Check for interrupts
|
||||||
// RUBY_VM_CHECK_INTS(ec)
|
// RUBY_VM_CHECK_INTS(ec)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
|
|
||||||
uint8_t *ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry);
|
uint8_t *ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool gen_entry);
|
||||||
|
|
||||||
void ujit_init_codegen(void);
|
void ujit_init_codegen(void);
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ st_index_t blockid_hash(st_data_t arg)
|
||||||
{
|
{
|
||||||
const blockid_t *blockid = (const blockid_t*)arg;
|
const blockid_t *blockid = (const blockid_t*)arg;
|
||||||
st_index_t hash0 = st_numhash((st_data_t)blockid->iseq);
|
st_index_t hash0 = st_numhash((st_data_t)blockid->iseq);
|
||||||
st_index_t hash1 = st_numhash((st_data_t)blockid->idx);
|
st_index_t hash1 = st_numhash((st_data_t)(uint64_t)blockid->idx);
|
||||||
|
|
||||||
// Use XOR to combine the hashes
|
// Use XOR to combine the hashes
|
||||||
return hash0 ^ hash1;
|
return hash0 ^ hash1;
|
||||||
|
@ -31,7 +31,7 @@ static const struct st_hash_type hashtype_blockid = {
|
||||||
|
|
||||||
// Retrieve a basic block version for an (iseq, idx) tuple
|
// Retrieve a basic block version for an (iseq, idx) tuple
|
||||||
// TODO: we need to add a versioning context here
|
// 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 */)
|
uint8_t* get_block_version(const rb_iseq_t *iseq, uint32_t idx)
|
||||||
{
|
{
|
||||||
blockid_t blockid = { iseq, idx };
|
blockid_t blockid = { iseq, idx };
|
||||||
|
|
||||||
|
|
15
ujit_core.h
15
ujit_core.h
|
@ -27,7 +27,7 @@ typedef struct BlockId
|
||||||
const rb_iseq_t *iseq;
|
const rb_iseq_t *iseq;
|
||||||
|
|
||||||
// Instruction index
|
// Instruction index
|
||||||
const unsigned int idx;
|
const uint32_t idx;
|
||||||
|
|
||||||
} blockid_t;
|
} blockid_t;
|
||||||
|
|
||||||
|
@ -39,26 +39,31 @@ typedef struct ctx_struct
|
||||||
// Some of the information here is only needed during
|
// Some of the information here is only needed during
|
||||||
// code generation, eg: current pc
|
// code generation, eg: current pc
|
||||||
|
|
||||||
|
// The start of the generated code
|
||||||
|
uint8_t *code_ptr;
|
||||||
|
|
||||||
// Instruction sequence this is associated with
|
// Instruction sequence this is associated with
|
||||||
const rb_iseq_t *iseq;
|
const rb_iseq_t *iseq;
|
||||||
|
|
||||||
// Index in the iseq of the opcode we are replacing
|
// Index in the iseq of the opcode we are replacing
|
||||||
size_t start_idx;
|
uint32_t start_idx;
|
||||||
|
|
||||||
// The start of the generated code
|
// Index of the current instruction being compiled
|
||||||
uint8_t *code_ptr;
|
uint32_t insn_idx;
|
||||||
|
|
||||||
// Current PC
|
// Current PC
|
||||||
VALUE *pc;
|
VALUE *pc;
|
||||||
|
|
||||||
// Number of values pushed on the temporary stack
|
// Number of values pushed on the temporary stack
|
||||||
int32_t stack_size;
|
uint32_t stack_size;
|
||||||
|
|
||||||
// Whether we know self is a heap object
|
// Whether we know self is a heap object
|
||||||
bool self_is_object;
|
bool self_is_object;
|
||||||
|
|
||||||
} ctx_t;
|
} ctx_t;
|
||||||
|
|
||||||
|
uint8_t* get_block_version(const rb_iseq_t *iseq, uint32_t idx);
|
||||||
|
|
||||||
// Context object methods
|
// Context object methods
|
||||||
int ctx_get_opcode(ctx_t *ctx);
|
int ctx_get_opcode(ctx_t *ctx);
|
||||||
VALUE ctx_get_arg(ctx_t* ctx, size_t arg_idx);
|
VALUE ctx_get_arg(ctx_t* ctx, size_t arg_idx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue