diff options
author | Takashi Kokubun <[email protected]> | 2023-02-14 22:24:32 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2023-03-05 23:28:59 -0800 |
commit | c3ca9448bf62461d84ea333ac83649c5e1b77c6b (patch) | |
tree | 1df29a09d858dae75fcc46593165b03e51319e87 | |
parent | 3774fe4e912afc97649207fdfd17aa8b44903152 (diff) |
Implement all getlocal/setlocal insns
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7448
-rw-r--r-- | lib/ruby_vm/mjit/insn_compiler.rb | 95 | ||||
-rw-r--r-- | lib/ruby_vm/mjit/stats.rb | 2 |
2 files changed, 74 insertions, 23 deletions
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb index a3ebe4a9e5..1a6d442c90 100644 --- a/lib/ruby_vm/mjit/insn_compiler.rb +++ b/lib/ruby_vm/mjit/insn_compiler.rb @@ -23,11 +23,11 @@ module RubyVM::MJIT asm.incr_counter(:mjit_insns_count) asm.comment("Insn: #{insn.name}") - # 40/101 + # 43/101 case insn.name when :nop then nop(jit, ctx, asm) - # getlocal - # setlocal + when :getlocal then getlocal(jit, ctx, asm) + when :setlocal then setlocal(jit, ctx, asm) # getblockparam # setblockparam # getblockparamproxy @@ -123,7 +123,7 @@ module RubyVM::MJIT when :getlocal_WC_0 then getlocal_WC_0(jit, ctx, asm) when :getlocal_WC_1 then getlocal_WC_1(jit, ctx, asm) when :setlocal_WC_0 then setlocal_WC_0(jit, ctx, asm) - # setlocal_WC_1 + when :setlocal_WC_1 then setlocal_WC_1(jit, ctx, asm) when :putobject_INT2FIX_0_ then putobject_INT2FIX_0_(jit, ctx, asm) when :putobject_INT2FIX_1_ then putobject_INT2FIX_1_(jit, ctx, asm) else CantCompile @@ -144,8 +144,24 @@ module RubyVM::MJIT KeepCompiling end - # getlocal - # setlocal + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::Assembler] + def getlocal(jit, ctx, asm) + idx = jit.operand(0) + level = jit.operand(1) + jit_getlocal_generic(jit, ctx, asm, idx:, level:) + end + + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::Assembler] + def setlocal(jit, ctx, asm) + idx = jit.operand(0) + level = jit.operand(1) + jit_setlocal_generic(jit, ctx, asm, idx:, level:) + end + # getblockparam # setblockparam # getblockparamproxy @@ -919,24 +935,10 @@ module RubyVM::MJIT # @param ctx [RubyVM::MJIT::Context] # @param asm [RubyVM::MJIT::Assembler] def getlocal_WC_1(jit, ctx, asm) - # Get operands idx = jit.operand(0) - level = 1 - - # Get EP - ep_reg = :rax - jit_get_ep(asm, level, reg: ep_reg) - - # Get a local variable - asm.mov(:rax, [ep_reg, -idx * C.VALUE.size]) - - # Push it to the stack - stack_top = ctx.stack_push - asm.mov(stack_top, :rax) - KeepCompiling + jit_getlocal_generic(jit, ctx, asm, idx:, level: 1) end - # setlocal_WC_0 # @param jit [RubyVM::MJIT::JITState] # @param ctx [RubyVM::MJIT::Context] # @param asm [RubyVM::MJIT::Assembler] @@ -972,7 +974,13 @@ module RubyVM::MJIT KeepCompiling end - # setlocal_WC_1 + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::Assembler] + def setlocal_WC_1(jit, ctx, asm) + idx = jit.operand(0) + jit_setlocal_generic(jit, ctx, asm, idx:, level: 1) + end # @param jit [RubyVM::MJIT::JITState] # @param ctx [RubyVM::MJIT::Context] @@ -992,6 +1000,49 @@ module RubyVM::MJIT # Helpers # + def jit_getlocal_generic(jit, ctx, asm, idx:, level:) + # Load environment pointer EP at level + ep_reg = :rax + jit_get_ep(asm, level, reg: ep_reg) + + # Get a local variable + asm.mov(:rax, [ep_reg, -idx * C.VALUE.size]) + + # Push it to the stack + stack_top = ctx.stack_push + asm.mov(stack_top, :rax) + KeepCompiling + end + + def jit_setlocal_generic(jit, ctx, asm, idx:, level:) + # Load environment pointer EP at level + ep_reg = :rax + jit_get_ep(asm, level, reg: ep_reg) + + # Write barriers may be required when VM_ENV_FLAG_WB_REQUIRED is set, however write barriers + # only affect heap objects being written. If we know an immediate value is being written we + # can skip this check. + + # flags & VM_ENV_FLAG_WB_REQUIRED + flags_opnd = [ep_reg, C.VALUE.size * C.VM_ENV_DATA_INDEX_FLAGS] + asm.test(flags_opnd, C.VM_ENV_FLAG_WB_REQUIRED) + + # Create a side-exit to fall back to the interpreter + side_exit = side_exit(jit, ctx) + + # if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0 + asm.jnz(side_exit) + + # Pop the value to write from the stack + stack_top = ctx.stack_pop(1) + + # Write the value at the environment pointer + asm.mov(:rcx, stack_top) + asm.mov([ep_reg, -(C.VALUE.size * idx)], :rcx) + + KeepCompiling + end + # Compute the index of a local variable from its slot index def slot_to_local_idx(iseq, slot_idx) # Layout illustration diff --git a/lib/ruby_vm/mjit/stats.rb b/lib/ruby_vm/mjit/stats.rb index 9631a546a0..2ab6af4afe 100644 --- a/lib/ruby_vm/mjit/stats.rb +++ b/lib/ruby_vm/mjit/stats.rb @@ -82,7 +82,7 @@ module RubyVM::MJIT count_width = top_exits.map { |_name, count| format_number(10, count).length }.max + padding top_exits.each do |name, count| ratio = 100.0 * count / total_exits - $stderr.puts "#{format("%#{name_width}s", name)}: #{format_number(count_width, count)} (#{format('%.1f', ratio)}%)" + $stderr.puts "#{format("%#{name_width}s", name)}: #{format_number(count_width, count)} (#{format('%4.1f', ratio)}%)" end end |