ruby-changes:68713
From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:12:32 +0900 (JST)
Subject: [ruby-changes:68713] 0a42428098 (master): Implement branchif in ujit
https://git.ruby-lang.org/ruby.git/commit/?id=0a42428098 From 0a42428098e4dd4c348dd09a8566d643efb59e1c Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...> Date: Thu, 21 Jan 2021 15:05:44 -0500 Subject: Implement branchif in ujit --- ujit_codegen.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/ujit_codegen.c b/ujit_codegen.c index 488e4ca770..5b9372c6ff 100644 --- a/ujit_codegen.c +++ b/ujit_codegen.c @@ -641,6 +641,63 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L641 return true; } +void +gen_branchif_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape) +{ + switch (shape) + { + case SHAPE_NEXT0: + jz_ptr(cb, target1); + break; + + case SHAPE_NEXT1: + jnz_ptr(cb, target0); + break; + + case SHAPE_DEFAULT: + jnz_ptr(cb, target0); + jmp_ptr(cb, target1); + break; + } +} + +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); + + // Test if any bit (outside of the Qnil bit) is on + // RUBY_Qfalse /* ...0000 0000 */ + // RUBY_Qnil /* ...0000 1000 */ + x86opnd_t val_opnd = ctx_stack_pop(ctx, 1); + test(cb, val_opnd, imm_opnd(~Qnil)); + + // Get the branch target instruction offsets + uint32_t next_idx = jit_next_idx(jit); + uint32_t jump_idx = next_idx + (uint32_t)jit_get_arg(jit, 0); + blockid_t next_block = { jit->iseq, next_idx }; + blockid_t jump_block = { jit->iseq, jump_idx }; + + // Generate the branch instructions + gen_branch( + ctx, + jump_block, + ctx, + next_block, + ctx, + gen_branchif_branch + ); + + return true; +} + void gen_branchunless_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape) { @@ -664,9 +721,12 @@ gen_branchunless_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uin https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L721 static bool gen_branchunless(jitstate_t* jit, ctx_t* ctx) { - // TODO: we need to eventually do an interrupt check when jumping/branching + // 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? - // Maybe we can push the check int into the next block or the stub? + // 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); @@ -1014,6 +1074,7 @@ ujit_init_codegen(void) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L1074 ujit_reg_op(BIN(opt_lt), gen_opt_lt, false); ujit_reg_op(BIN(opt_minus), gen_opt_minus, false); ujit_reg_op(BIN(opt_plus), gen_opt_plus, false); + ujit_reg_op(BIN(branchif), gen_branchif, true); ujit_reg_op(BIN(branchunless), gen_branchunless, true); ujit_reg_op(BIN(jump), gen_jump, true); ujit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block, true); -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/