diff options
author | Takashi Kokubun <[email protected]> | 2023-02-13 23:05:56 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2023-03-05 23:28:59 -0800 |
commit | bc50b0475a64dbae293c29bf3e6b72ba12424c99 (patch) | |
tree | dd6f18bc22ce6e31df27944a4671f8e5106ecb59 | |
parent | 67cc53214cdb5900ccc75e195d8e9c85dea519f9 (diff) |
Implement opt_and and opt_or
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7448
-rw-r--r-- | lib/ruby_vm/mjit/assembler.rb | 27 | ||||
-rw-r--r-- | lib/ruby_vm/mjit/insn_compiler.rb | 86 | ||||
-rw-r--r-- | mjit_c.rb | 8 | ||||
-rwxr-xr-x | tool/mjit/bindgen.rb | 2 |
4 files changed, 118 insertions, 5 deletions
diff --git a/lib/ruby_vm/mjit/assembler.rb b/lib/ruby_vm/mjit/assembler.rb index 5ea24266fc..bbc9691b56 100644 --- a/lib/ruby_vm/mjit/assembler.rb +++ b/lib/ruby_vm/mjit/assembler.rb @@ -121,6 +121,16 @@ module RubyVM::MJIT mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg], imm: imm8(src_imm), ) + # AND r64, r/m64 (Mod 01: [reg]+disp8) + in [Symbol => dst_reg, [Symbol => src_reg, Integer => src_disp]] if r64?(dst_reg) && r64?(src_reg) && imm8?(src_disp) + # REX.W + 23 /r + # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r) + insn( + prefix: REX_W, + opcode: 0x23, + mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg], + disp: imm8(src_disp), + ) else raise NotImplementedError, "and: not-implemented operands: #{dst.inspect}, #{src.inspect}" end @@ -545,6 +555,23 @@ module RubyVM::MJIT end end + def or(dst, src) + case [dst, src] + # OR r64, r/m64 (Mod 01: [reg]+disp8) + in [Symbol => dst_reg, [Symbol => src_reg, Integer => src_disp]] if r64?(dst_reg) && r64?(src_reg) && imm8?(src_disp) + # REX.W + 0B /r + # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r) + insn( + prefix: REX_W, + opcode: 0x0b, + mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg], + disp: imm8(src_disp), + ) + else + raise NotImplementedError, "or: not-implemented operands: #{dst.inspect}, #{src.inspect}" + end + end + def push(src) case src # PUSH r64 diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb index cc62a267ad..95d837b073 100644 --- a/lib/ruby_vm/mjit/insn_compiler.rb +++ b/lib/ruby_vm/mjit/insn_compiler.rb @@ -23,7 +23,7 @@ module RubyVM::MJIT asm.incr_counter(:mjit_insns_count) asm.comment("Insn: #{insn.name}") - # 36/101 + # 38/101 case insn.name when :nop then nop(jit, ctx, asm) # getlocal @@ -105,8 +105,8 @@ module RubyVM::MJIT when :opt_gt then opt_gt(jit, ctx, asm) when :opt_ge then opt_ge(jit, ctx, asm) when :opt_ltlt then opt_ltlt(jit, ctx, asm) - # opt_and - # opt_or + when :opt_and then opt_and(jit, ctx, asm) + when :opt_or then opt_or(jit, ctx, asm) when :opt_aref then opt_aref(jit, ctx, asm) # opt_aset # opt_aset_with @@ -648,8 +648,84 @@ module RubyVM::MJIT opt_send_without_block(jit, ctx, asm) end - # opt_and - # opt_or + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::Assembler] + def opt_and(jit, ctx, asm) + unless jit.at_current_insn? + defer_compilation(jit, ctx, asm) + return EndBlock + end + + if two_fixnums_on_stack?(jit) + # Create a side-exit to fall back to the interpreter + # Note: we generate the side-exit before popping operands from the stack + side_exit = side_exit(jit, ctx) + + unless Invariants.assume_bop_not_redefined(jit, C.INTEGER_REDEFINED_OP_FLAG, C.BOP_AND) + return CantCompile + end + + # Check that both operands are fixnums + guard_two_fixnums(jit, ctx, asm, side_exit) + + # Get the operands and destination from the stack + arg1 = ctx.stack_pop(1) + arg0 = ctx.stack_pop(1) + + asm.comment('bitwise and') + asm.mov(:rax, arg0) + asm.and(:rax, arg1) + + # Push the return value onto the stack + dst = ctx.stack_push + asm.mov(dst, :rax) + + KeepCompiling + else + opt_send_without_block(jit, ctx, asm) + end + end + + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::Assembler] + def opt_or(jit, ctx, asm) + unless jit.at_current_insn? + defer_compilation(jit, ctx, asm) + return EndBlock + end + + if two_fixnums_on_stack?(jit) + # Create a side-exit to fall back to the interpreter + # Note: we generate the side-exit before popping operands from the stack + side_exit = side_exit(jit, ctx) + + unless Invariants.assume_bop_not_redefined(jit, C.INTEGER_REDEFINED_OP_FLAG, C.BOP_OR) + return CantCompile + end + + # Check that both operands are fixnums + guard_two_fixnums(jit, ctx, asm, side_exit) + + # Get the operands and destination from the stack + asm.comment('bitwise or') + arg1 = ctx.stack_pop(1) + arg0 = ctx.stack_pop(1) + + # Do the bitwise or arg0 | arg1 + asm.mov(:rax, arg0) + asm.or(:rax, arg1) + + # Push the return value onto the stack + dst = ctx.stack_push + asm.mov(dst, :rax) + + KeepCompiling + else + opt_send_without_block(jit, ctx, asm) + end + end # @param jit [RubyVM::MJIT::JITState] # @param ctx [RubyVM::MJIT::Context] @@ -329,6 +329,10 @@ module RubyVM::MJIT # :nodoc: all Primitive.cexpr! %q{ UINT2NUM(ARRAY_REDEFINED_OP_FLAG) } end + def C.BOP_AND + Primitive.cexpr! %q{ UINT2NUM(BOP_AND) } + end + def C.BOP_AREF Primitive.cexpr! %q{ UINT2NUM(BOP_AREF) } end @@ -357,6 +361,10 @@ module RubyVM::MJIT # :nodoc: all Primitive.cexpr! %q{ UINT2NUM(BOP_MOD) } end + def C.BOP_OR + Primitive.cexpr! %q{ UINT2NUM(BOP_OR) } + end + def C.BOP_PLUS Primitive.cexpr! %q{ UINT2NUM(BOP_PLUS) } end diff --git a/tool/mjit/bindgen.rb b/tool/mjit/bindgen.rb index 4c03912a30..74072e07c8 100755 --- a/tool/mjit/bindgen.rb +++ b/tool/mjit/bindgen.rb @@ -348,6 +348,7 @@ generator = BindingGenerator.new( VM_ENV_DATA_INDEX_SPECVAL ], UINT: %w[ + BOP_AND BOP_AREF BOP_GE BOP_GT @@ -355,6 +356,7 @@ generator = BindingGenerator.new( BOP_LT BOP_MINUS BOP_MOD + BOP_OR BOP_PLUS ARRAY_REDEFINED_OP_FLAG HASH_REDEFINED_OP_FLAG |