MicroJIT: coalesce heap pointer check on self
This commit is contained in:
parent
4d964e2582
commit
fa04478e9e
@ -55,6 +55,9 @@ typedef struct ctx_struct
|
|||||||
// The start of the generated code
|
// The start of the generated code
|
||||||
uint8_t *code_ptr;
|
uint8_t *code_ptr;
|
||||||
|
|
||||||
|
// Whether we know self is a heap object
|
||||||
|
bool self_is_heap_object;
|
||||||
|
|
||||||
} ctx_t;
|
} ctx_t;
|
||||||
|
|
||||||
// MicroJIT code generation function signature
|
// MicroJIT code generation function signature
|
||||||
@ -407,9 +410,7 @@ ujit_compile_insn(const rb_iseq_t *iseq, unsigned int insn_idx, unsigned int *ne
|
|||||||
int first_opcode = opcode_at_pc(iseq, &encoded[insn_idx]);
|
int first_opcode = opcode_at_pc(iseq, &encoded[insn_idx]);
|
||||||
|
|
||||||
// Create codegen context
|
// Create codegen context
|
||||||
ctx_t ctx;
|
ctx_t ctx = { 0 };
|
||||||
ctx.pc = NULL;
|
|
||||||
ctx.stack_diff = 0;
|
|
||||||
ctx.iseq = iseq;
|
ctx.iseq = iseq;
|
||||||
ctx.code_ptr = code_ptr;
|
ctx.code_ptr = code_ptr;
|
||||||
ctx.start_idx = insn_idx;
|
ctx.start_idx = insn_idx;
|
||||||
@ -624,6 +625,22 @@ gen_setlocal_wc0(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that `self` is a pointer to an object on the GC heap
|
||||||
|
static void
|
||||||
|
ensure_self_is_heap_object(codeblock_t *cb, x86opnd_t storage_for_self, uint8_t *side_exit, ctx_t *ctx)
|
||||||
|
{
|
||||||
|
// `self` is constant throughout the entire region, so we only need to do this check once.
|
||||||
|
if (!ctx->self_is_heap_object) {
|
||||||
|
test(cb, storage_for_self, imm_opnd(RUBY_IMMEDIATE_MASK));
|
||||||
|
jnz_ptr(cb, side_exit);
|
||||||
|
cmp(cb, storage_for_self, imm_opnd(Qfalse));
|
||||||
|
je_ptr(cb, side_exit);
|
||||||
|
cmp(cb, storage_for_self, imm_opnd(Qnil));
|
||||||
|
je_ptr(cb, side_exit);
|
||||||
|
ctx->self_is_heap_object = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
gen_getinstancevariable(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
gen_getinstancevariable(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx)
|
||||||
{
|
{
|
||||||
@ -652,13 +669,7 @@ gen_getinstancevariable(codeblock_t* cb, codeblock_t* ocb, ctx_t* 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));
|
||||||
|
|
||||||
// Check that the receiver is a heap object
|
ensure_self_is_heap_object(cb, REG0, side_exit, ctx);
|
||||||
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
|
|
||||||
jnz_ptr(cb, side_exit);
|
|
||||||
cmp(cb, REG0, imm_opnd(Qfalse));
|
|
||||||
je_ptr(cb, side_exit);
|
|
||||||
cmp(cb, REG0, imm_opnd(Qnil));
|
|
||||||
je_ptr(cb, side_exit);
|
|
||||||
|
|
||||||
// Bail if receiver class is different from compiled time call cache class
|
// Bail if receiver class is different from compiled time call cache class
|
||||||
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
|
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
|
||||||
@ -720,13 +731,7 @@ gen_setinstancevariable(codeblock_t* cb, codeblock_t* ocb, ctx_t* 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));
|
||||||
|
|
||||||
// Check that the receiver is a heap object
|
ensure_self_is_heap_object(cb, REG0, side_exit, ctx);
|
||||||
test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
|
|
||||||
jnz_ptr(cb, side_exit);
|
|
||||||
cmp(cb, REG0, imm_opnd(Qfalse));
|
|
||||||
je_ptr(cb, side_exit);
|
|
||||||
cmp(cb, REG0, imm_opnd(Qnil));
|
|
||||||
je_ptr(cb, side_exit);
|
|
||||||
|
|
||||||
// Bail if receiver class is different from compiled time call cache class
|
// Bail if receiver class is different from compiled time call cache class
|
||||||
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
|
x86opnd_t klass_opnd = mem_opnd(64, REG0, offsetof(struct RBasic, klass));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user