summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2021-02-11 13:59:59 -0500
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:29 -0400
commita7c1bc61d2becac74743d8ab6efd6d5649b92311 (patch)
tree32b9593c0c2287aa3f6ef1082dcbcc674ff12362
parentfaafe716af5ea2d31eb175885032a6fe46b92834 (diff)
Add missing VM_CHECK_INTS() for correctness
-rw-r--r--ujit_codegen.c64
1 files changed, 31 insertions, 33 deletions
diff --git a/ujit_codegen.c b/ujit_codegen.c
index 452849d53c..90c1af21c4 100644
--- a/ujit_codegen.c
+++ b/ujit_codegen.c
@@ -150,6 +150,20 @@ ujit_entry_prologue(void)
}
/*
+Generate code to check for interrupts and take a side-exit
+*/
+static void
+ujit_check_ints(codeblock_t* cb, uint8_t* side_exit)
+{
+ // Check for interrupts
+ // see RUBY_VM_CHECK_INTS(ec) macro
+ mov(cb, REG0_32, member_opnd(REG_EC, rb_execution_context_t, interrupt_mask));
+ not(cb, REG0_32);
+ test(cb, member_opnd(REG_EC, rb_execution_context_t, interrupt_flag), REG0_32);
+ jnz_ptr(cb, side_exit);
+}
+
+/*
Compile a sequence of bytecode instructions for a given basic block version
*/
void
@@ -894,14 +908,10 @@ gen_branchif_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t
static bool
gen_branchif(jitstate_t* jit, ctx_t* ctx)
{
- // TODO: we need to eventually do an interrupt check
- // The check is supposed to happen only when we jump to the jump target block
- //
- // How can we do this while keeping the check logic out of line?
- // Can we push the VM_CHECK_INTS() into the next block or the stub?
- // Maybe into a transition edge block
- //
- // RUBY_VM_CHECK_INTS(ec);
+ // FIXME: eventually, put VM_CHECK_INTS() only on backward branch targets
+ // Check for interrupts
+ uint8_t* side_exit = ujit_side_exit(jit, ctx);
+ ujit_check_ints(cb, side_exit);
// Test if any bit (outside of the Qnil bit) is on
// RUBY_Qfalse /* ...0000 0000 */
@@ -951,14 +961,10 @@ gen_branchunless_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uin
static bool
gen_branchunless(jitstate_t* jit, ctx_t* ctx)
{
- // TODO: we need to eventually do an interrupt check
- // The check is supposed to happen only when we jump to the jump target block
- //
- // How can we do this while keeping the check logic out of line?
- // Can we push the VM_CHECK_INTS() into the next block or the stub?
- // Maybe into a transition edge block
- //
- // RUBY_VM_CHECK_INTS(ec);
+ // FIXME: eventually, put VM_CHECK_INTS() only on backward branch targets
+ // Check for interrupts
+ uint8_t* side_exit = ujit_side_exit(jit, ctx);
+ ujit_check_ints(cb, side_exit);
// Test if any bit (outside of the Qnil bit) is on
// RUBY_Qfalse /* ...0000 0000 */
@@ -988,15 +994,15 @@ gen_branchunless(jitstate_t* jit, ctx_t* ctx)
static bool
gen_jump(jitstate_t* jit, ctx_t* ctx)
{
+ // FIXME: eventually, put VM_CHECK_INTS() only on backward branch targets
+ // Check for interrupts
+ uint8_t* side_exit = ujit_side_exit(jit, ctx);
+ ujit_check_ints(cb, side_exit);
+
// Get the branch target instruction offsets
uint32_t jump_idx = jit_next_idx(jit) + (int32_t)jit_get_arg(jit, 0);
blockid_t jump_block = { jit->iseq, jump_idx };
- //
- // TODO:
- // RUBY_VM_CHECK_INTS(ec);
- //
-
// Generate the jump instruction
gen_direct_jump(
ctx,
@@ -1027,11 +1033,7 @@ gen_opt_swb_cfunc(jitstate_t* jit, ctx_t* ctx, struct rb_call_data * cd, const r
uint8_t* side_exit = ujit_side_exit(jit, ctx);
// Check for interrupts
- // RUBY_VM_CHECK_INTS(ec)
- mov(cb, REG0_32, member_opnd(REG_EC, rb_execution_context_t, interrupt_mask));
- not(cb, REG0_32);
- test(cb, member_opnd(REG_EC, rb_execution_context_t, interrupt_flag), REG0_32);
- jnz_ptr(cb, side_exit);
+ ujit_check_ints(cb, side_exit);
// Points to the receiver operand on the stack
x86opnd_t recv = ctx_stack_opnd(ctx, argc);
@@ -1261,11 +1263,7 @@ gen_opt_swb_iseq(jitstate_t* jit, ctx_t* ctx, struct rb_call_data * cd, const rb
uint8_t* side_exit = ujit_side_exit(jit, ctx);
// Check for interrupts
- // RUBY_VM_CHECK_INTS(ec)
- mov(cb, REG0_32, member_opnd(REG_EC, rb_execution_context_t, interrupt_mask));
- not(cb, REG0_32);
- test(cb, member_opnd(REG_EC, rb_execution_context_t, interrupt_flag), REG0_32);
- jnz_ptr(cb, side_exit);
+ ujit_check_ints(cb, side_exit);
// Points to the receiver operand on the stack
x86opnd_t recv = ctx_stack_opnd(ctx, argc);
@@ -1478,8 +1476,8 @@ gen_leave(jitstate_t* jit, ctx_t* ctx)
test(cb, flags_opnd, imm_opnd(VM_FRAME_FLAG_FINISH));
jnz_ptr(cb, side_exit);
- // TODO:
- // RUBY_VM_CHECK_INTS(ec);
+ // Check for interrupts
+ ujit_check_ints(cb, side_exit);
// Load the return value
mov(cb, REG0, ctx_stack_pop(ctx, 1));