From 8b8470d098607548ff33792b831a2290c12248ed Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Tue, 27 Oct 2020 11:10:19 -0400 Subject: [PATCH] Added RUBY_VM_CHECK_INTS to CFUNC calls --- ujit_asm.c | 39 ++++++++++++++++++++++++++------------- ujit_asm.h | 2 +- ujit_asm_tests.c | 1 + ujit_compile.c | 12 +++++++++--- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/ujit_asm.c b/ujit_asm.c index 0b833445b2..3ffc5503b0 100644 --- a/ujit_asm.c +++ b/ujit_asm.c @@ -1507,26 +1507,39 @@ void sub(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1) } /// test - Logical Compare -void test(codeblock_t* cb, x86opnd_t rm_opnd, x86opnd_t imm_opnd) +void test(codeblock_t* cb, x86opnd_t rm_opnd, x86opnd_t test_opnd) { assert (rm_opnd.type == OPND_REG || rm_opnd.type == OPND_MEM); - assert (imm_opnd.type == OPND_IMM); - assert (imm_opnd.as.imm >= 0); - assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= 32); - assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= rm_opnd.num_bits); + assert (test_opnd.type == OPND_REG || test_opnd.type == OPND_IMM); - // Use the smallest operand size possible - rm_opnd = resize_opnd(rm_opnd, unsig_imm_size(imm_opnd.as.unsig_imm)); - - if (rm_opnd.num_bits == 8) + // If the second operand is an immediate + if (test_opnd.type == OPND_IMM) { - cb_write_rm(cb, false, false, NO_OPND, rm_opnd, 0x00, 1, 0xF6); - cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits); + x86opnd_t imm_opnd = test_opnd; + assert (imm_opnd.as.imm >= 0); + assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= 32); + assert (unsig_imm_size(imm_opnd.as.unsig_imm) <= rm_opnd.num_bits); + + // Use the smallest operand size possible + rm_opnd = resize_opnd(rm_opnd, unsig_imm_size(imm_opnd.as.unsig_imm)); + + if (rm_opnd.num_bits == 8) + { + cb_write_rm(cb, false, false, NO_OPND, rm_opnd, 0x00, 1, 0xF6); + cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits); + } + else + { + cb_write_rm(cb, rm_opnd.num_bits == 16, false, NO_OPND, rm_opnd, 0x00, 1, 0xF7); + cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits); + } } else { - cb_write_rm(cb, rm_opnd.num_bits == 16, false, NO_OPND, rm_opnd, 0x00, 1, 0xF7); - cb_write_int(cb, imm_opnd.as.imm, rm_opnd.num_bits); + // For now, 32-bit operands only + assert (test_opnd.num_bits == rm_opnd.num_bits); + assert (test_opnd.num_bits == 32); + cb_write_rm(cb, false, false, test_opnd, rm_opnd, 0xFF, 1, 0x85); } } diff --git a/ujit_asm.h b/ujit_asm.h index ca5e8884ce..cf8c72f30d 100644 --- a/ujit_asm.h +++ b/ujit_asm.h @@ -372,7 +372,7 @@ void sar(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void shl(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void shr(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void sub(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); -void test(codeblock_t* cb, x86opnd_t rm_opnd, x86opnd_t imm_opnd); +void test(codeblock_t* cb, x86opnd_t rm_opnd, x86opnd_t test_opnd); void ud2(codeblock_t* cb); void xor(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); diff --git a/ujit_asm_tests.c b/ujit_asm_tests.c index afe8e15b93..532fb5367c 100644 --- a/ujit_asm_tests.c +++ b/ujit_asm_tests.c @@ -314,6 +314,7 @@ void run_tests() cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, 0), imm_opnd(1)); check_bytes(cb, "F60601"); cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, 16), imm_opnd(1)); check_bytes(cb, "F6461001"); cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, -16), imm_opnd(1)); check_bytes(cb, "F646F001"); + cb_set_pos(cb, 0); test(cb, mem_opnd(32, RSI, 64), EAX); check_bytes(cb, "854640"); // xor cb_set_pos(cb, 0); xor(cb, EAX, EAX); check_bytes(cb, "31C0"); diff --git a/ujit_compile.c b/ujit_compile.c index e97e79d038..ac561f4c36 100644 --- a/ujit_compile.c +++ b/ujit_compile.c @@ -63,6 +63,8 @@ static codeblock_t* ocb = NULL; // Scratch registers used by MicroJIT #define REG0 RAX #define REG1 RCX +#define REG0_32 EAX +#define REG1_32 ECX // Keep track of mapping from instructions to generated code // See comment for rb_encoded_insn_data in iseq.c @@ -537,6 +539,13 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx) // Create a size-exit to fall back to the interpreter uint8_t* side_exit = ujit_side_exit(ocb, ctx, ctx->pc); + // 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); + // Points to the receiver operand on the stack x86opnd_t recv = ctx_stack_opnd(ctx, argc); mov(cb, REG0, recv); @@ -683,9 +692,6 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx) x86opnd_t stack_ret = ctx_stack_push(ctx, 1); mov(cb, stack_ret, RAX); - // TODO: later - // RUBY_VM_CHECK_INTS(ec); - // Pop the stack frame (ec->cfp++) add( cb,