summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2020-10-20 11:11:47 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:25 -0400
commitff73762bda4f2c5c7aa2a04b39282c3755d69841 (patch)
treebbd53ccaa9661e8ced1822b9e59d863c479a5287
parent6ca360aa4762c7eaaa587eed79384052d8453552 (diff)
Refactor ujit, define named register constants, code cleanup
-rw-r--r--ujit_compile.c75
1 files changed, 36 insertions, 39 deletions
diff --git a/ujit_compile.c b/ujit_compile.c
index 2ca17d228f..411d2c8ed6 100644
--- a/ujit_compile.c
+++ b/ujit_compile.c
@@ -53,6 +53,17 @@ static codeblock_t* cb = NULL;
static codeblock_t outline_block;
static codeblock_t* ocb = NULL;
+// Register MicroJIT receives the CFP and EC into
+#define REG_CFP RDI
+#define REG_EC RSI
+
+// Register MicroJIT loads the SP into
+#define REG_SP RDX
+
+// Scratch registers used by MicroJIT
+#define REG0 RCX
+#define REG1 R8
+
// Keep track of mapping from instructions to generated code
// See comment for rb_encoded_insn_data in iseq.c
static void
@@ -101,7 +112,7 @@ Get an operand for the adjusted stack pointer address
x86opnd_t ctx_sp_opnd(ctx_t* ctx, size_t n)
{
int32_t offset = (ctx->stack_diff) * 8;
- return mem_opnd(64, R9, offset);
+ return mem_opnd(64, REG_SP, offset);
}
/*
@@ -114,7 +125,7 @@ x86opnd_t ctx_stack_push(ctx_t* ctx, size_t n)
// SP points just above the topmost value
int32_t offset = (ctx->stack_diff - 1) * 8;
- return mem_opnd(64, R9, offset);
+ return mem_opnd(64, REG_SP, offset);
}
/*
@@ -125,7 +136,7 @@ x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n)
{
// SP points just above the topmost value
int32_t offset = (ctx->stack_diff - 1) * 8;
- x86opnd_t top = mem_opnd(64, R9, offset);
+ x86opnd_t top = mem_opnd(64, REG_SP, offset);
ctx->stack_diff -= n;
@@ -136,7 +147,7 @@ x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx)
{
// SP points just above the topmost value
int32_t offset = (ctx->stack_diff - 1 - idx) * 8;
- x86opnd_t opnd = mem_opnd(64, R9, offset);
+ x86opnd_t opnd = mem_opnd(64, REG_SP, offset);
return opnd;
}
@@ -159,15 +170,13 @@ ujit_gen_exit(codeblock_t* cb, ctx_t* ctx, VALUE* exit_pc)
if (ctx->stack_diff != 0)
{
x86opnd_t stack_pointer = ctx_sp_opnd(ctx, 1);
- lea(cb, R9, stack_pointer);
- mov(cb, mem_opnd(64, RDI, 8), R9);
+ lea(cb, REG_SP, stack_pointer);
+ mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG_SP);
}
// Directly return the next PC, which is a constant
mov(cb, RAX, const_ptr_opnd(exit_pc));
-
- // Write PC back into the CFP
- mov(cb, mem_opnd(64, RDI, 0), RAX);
+ mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), RAX);
// Write the post call bytes
for (size_t i = 0; i < sizeof(ujit_post_call_with_ec_bytes); ++i)
@@ -201,21 +210,12 @@ ujit_side_exit(codeblock_t* cb, ctx_t* ctx, VALUE* exit_pc)
/*
Generate a chunk of machine code for one individual bytecode instruction
Eventually, this will handle multiple instructions in a sequence
-
-MicroJIT code gets a pointer to the cfp as the first argument in RDI
-See rb_ujit_empty_func(rb_control_frame_t *cfp) in iseq.c
-
-Throughout the generated code, we store the current stack pointer in R9
-
-System V ABI reference:
-https://wiki.osdev.org/System_V_ABI#x86-64
*/
uint8_t *
ujit_compile_insn(const rb_iseq_t *iseq, unsigned int insn_idx, unsigned int* next_ujit_idx)
{
- if (!cb) {
- return NULL;
- }
+ assert (cb != NULL);
+
VALUE *encoded = iseq->body->iseq_encoded;
// NOTE: if we are ever deployed in production, we
@@ -270,8 +270,8 @@ ujit_compile_insn(const rb_iseq_t *iseq, unsigned int insn_idx, unsigned int* ne
{
ujit_gen_entry(cb);
- // Load the current SP from the CFP into R9
- mov(cb, R9, mem_opnd(64, RDI, 8));
+ // 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
@@ -371,7 +371,7 @@ bool
gen_putself(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
{
// Load self from CFP
- mov(cb, RAX, mem_opnd(64, RDI, 24));
+ mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, self));
// Write it on the stack
x86opnd_t stack_top = ctx_stack_push(ctx, 1);
@@ -384,18 +384,18 @@ bool
gen_getlocal_wc0(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
{
// Load environment pointer EP from CFP
- mov(cb, RDX, member_opnd(RDI, rb_control_frame_t, ep));
+ mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, ep));
// Compute the offset from BP to the local
int32_t local_idx = (int32_t)ctx_get_arg(ctx, 0);
const int32_t offs = -8 * local_idx;
// Load the local from the block
- mov(cb, RCX, mem_opnd(64, RDX, offs));
+ mov(cb, REG0, mem_opnd(64, REG0, offs));
// Write the local at SP
x86opnd_t stack_top = ctx_stack_push(ctx, 1);
- mov(cb, stack_top, RCX);
+ mov(cb, stack_top, REG0);
return true;
}
@@ -417,10 +417,10 @@ gen_setlocal_wc0(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
*/
// Load environment pointer EP from CFP
- mov(cb, RDX, member_opnd(RDI, rb_control_frame_t, ep));
+ mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, ep));
// flags & VM_ENV_FLAG_WB_REQUIRED
- x86opnd_t flags_opnd = mem_opnd(64, RDX, 8 * VM_ENV_DATA_INDEX_FLAGS);
+ x86opnd_t flags_opnd = mem_opnd(64, REG0, 8 * VM_ENV_DATA_INDEX_FLAGS);
test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED));
// Create a size-exit to fall back to the interpreter
@@ -431,12 +431,12 @@ gen_setlocal_wc0(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
// Pop the value to write from the stack
x86opnd_t stack_top = ctx_stack_pop(ctx, 1);
- mov(cb, RCX, stack_top);
+ mov(cb, REG1, stack_top);
// Write the value at the environment pointer
int32_t local_idx = (int32_t)ctx_get_arg(ctx, 0);
const int32_t offs = -8 * local_idx;
- mov(cb, mem_opnd(64, RDX, offs), RCX);
+ mov(cb, mem_opnd(64, REG0, offs), REG1);
return true;
}
@@ -604,11 +604,6 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
- // FIXME: for now, we hardcode ec
- // TODO: hardcode EC
- //mov(cb, RDI, const_ptr_opnd(rb_current_execution_context()));
-
-
// Allocate a new CFP
//ec->cfp--;
@@ -658,8 +653,9 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
// Save the MicroJIT registers
- push(cb, RDI);
- push(cb, R9);
+ push(cb, REG_CFP);
+ push(cb, REG_EC);
+ push(cb, REG_SP);
@@ -671,8 +667,9 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
// Restore MicroJIT registers
- pop(cb, R9);
- pop(cb, RDI);
+ pop(cb, REG_SP);
+ pop(cb, REG_EC);
+ pop(cb, REG_CFP);