Skip to content

Commit

Permalink
RJIT: Refactor getlocal and setlocal
Browse files Browse the repository at this point in the history
  • Loading branch information
k0kubun committed Apr 2, 2023
1 parent 6002b12 commit 8968b47
Showing 1 changed file with 38 additions and 76 deletions.
114 changes: 38 additions & 76 deletions lib/ruby_vm/rjit/insn_compiler.rb
Expand Up @@ -154,6 +154,22 @@ def getlocal(jit, ctx, asm)
jit_getlocal_generic(jit, ctx, asm, idx:, level:)
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def getlocal_WC_0(jit, ctx, asm)
idx = jit.operand(0)
jit_getlocal_generic(jit, ctx, asm, idx:, level: 0)
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def getlocal_WC_1(jit, ctx, asm)
idx = jit.operand(0)
jit_getlocal_generic(jit, ctx, asm, idx:, level: 1)
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
Expand All @@ -163,6 +179,22 @@ def setlocal(jit, ctx, asm)
jit_setlocal_generic(jit, ctx, asm, idx:, level:)
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def setlocal_WC_0(jit, ctx, asm)
idx = jit.operand(0)
jit_setlocal_generic(jit, ctx, asm, idx:, level: 0)
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::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::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
Expand Down Expand Up @@ -2528,75 +2560,6 @@ def opt_invokebuiltin_delegate_leave(jit, ctx, asm)
# opt_invokebuiltin_delegate is always followed by leave insn
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def getlocal_WC_0(jit, ctx, asm)
# Get operands
idx = jit.operand(0)

# Get EP
asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:ep)])

# Get a local variable
asm.mov(:rax, [:rax, -idx * C.VALUE.size])

# Push it to the stack
stack_top = ctx.stack_push
asm.mov(stack_top, :rax)
KeepCompiling
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def getlocal_WC_1(jit, ctx, asm)
idx = jit.operand(0)
jit_getlocal_generic(jit, ctx, asm, idx:, level: 1)
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def setlocal_WC_0(jit, ctx, asm)
slot_idx = jit.operand(0)

# Load environment pointer EP (level 0) from CFP
ep_reg = :rax
jit_get_ep(asm, 0, 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, -8 * slot_idx], :rcx)

KeepCompiling
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::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::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
Expand Down Expand Up @@ -3332,15 +3295,17 @@ def stack_swap(_jit, ctx, asm, offset0, offset1)
end

def jit_getlocal_generic(jit, ctx, asm, idx:, level:)
# Load environment pointer EP at level
# Load environment pointer EP (level 0) from CFP
ep_reg = :rax
jit_get_ep(asm, level, reg: ep_reg)

# Get a local variable
# Load the local from the block
# val = *(vm_get_ep(GET_EP(), level) - idx);
asm.mov(:rax, [ep_reg, -idx * C.VALUE.size])

# Push it to the stack
# Write the local at SP
stack_top = ctx.stack_push

asm.mov(stack_top, :rax)
KeepCompiling
end
Expand All @@ -3358,11 +3323,8 @@ def jit_setlocal_generic(jit, ctx, asm, idx:, level:)
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)
asm.jnz(side_exit(jit, ctx))

# Pop the value to write from the stack
stack_top = ctx.stack_pop(1)
Expand Down

0 comments on commit 8968b47

Please sign in to comment.