Skip to content

Commit

Permalink
RJIT: Reorder opt_case_dispatch branches
Browse files Browse the repository at this point in the history
  • Loading branch information
k0kubun committed Mar 19, 2023
1 parent d07d1c7 commit cc9330f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
48 changes: 45 additions & 3 deletions lib/ruby_vm/rjit/insn_compiler.rb
Expand Up @@ -1746,9 +1746,51 @@ def branchnil(jit, ctx, asm)
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def opt_case_dispatch(jit, ctx, asm)
# Just go to === branches for now
ctx.stack_pop
KeepCompiling
# Normally this instruction would lookup the key in a hash and jump to an
# offset based on that.
# Instead we can take the fallback case and continue with the next
# instruction.
# We'd hope that our jitted code will be sufficiently fast without the
# hash lookup, at least for small hashes, but it's worth revisiting this
# assumption in the future.
unless jit.at_current_insn?
defer_compilation(jit, ctx, asm)
return EndBlock
end
starting_context = ctx.dup

case_hash = jit.operand(0, ruby: true)
else_offset = jit.operand(1)

# Try to reorder case/else branches so that ones that are actually used come first.
# Supporting only Fixnum for now so that the implementation can be an equality check.
key_opnd = ctx.stack_pop(1)
comptime_key = jit.peek_at_stack(0)

# Check that all cases are fixnums to avoid having to register BOP assumptions on
# all the types that case hashes support. This spends compile time to save memory.
if fixnum?(comptime_key) && comptime_key <= 2**32 && C.rb_hash_keys(case_hash).all? { |key| fixnum?(key) }
unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_EQQ)
return CantCompile
end

# Check if the key is the same value
asm.cmp(key_opnd, comptime_key)
side_exit = side_exit(jit, starting_context)
jit_chain_guard(:jne, jit, starting_context, asm, side_exit)

# Get the offset for the compile-time key
offset = C.rb_hash_stlike_lookup(case_hash, comptime_key)
# NOTE: If we hit the else branch with various values, it could negatively impact the performance.
jump_offset = offset || else_offset

# Jump to the offset of case or else
target_pc = jit.pc + (jit.insn.len + jump_offset) * C.VALUE.size
jit_direct_jump(jit.iseq, target_pc, ctx, asm)
EndBlock
else
KeepCompiling # continue with === branches
end
end

# @param jit [RubyVM::RJIT::JITState]
Expand Down
23 changes: 20 additions & 3 deletions rjit_c.rb
Expand Up @@ -2,6 +2,9 @@
# Part of this file is generated by tool/rjit/bindgen.rb.
# Run `make rjit-bindgen` to update code between "RJIT bindgen begin" and "RJIT bindgen end".
module RubyVM::RJIT # :nodoc: all
#
# Main: Used by RJIT
#
# This `class << C` section is for calling C functions with Primitive.
# For importing variables or macros, use tool/rjit/bindgen.rb instead.
class << C = Module.new
Expand Down Expand Up @@ -292,10 +295,23 @@ def rb_vm_ep_local_ep(ep)
C.VALUE.new(lep_addr)
end

#
# Utilities: Not used by RJIT, but useful for debugging
#
def rb_hash_keys(hash)
Primitive.cexpr! 'rb_hash_keys(hash)'
end

def rb_hash_stlike_lookup(hash, key)
Primitive.cstmt! %{
VALUE result = Qnil;
rb_hash_stlike_lookup(hash, key, &result);
return result;
}
end
end

#
# Utilities: Not used by RJIT, but useful for debugging
#
class << C
# Convert insn BINs to encoded VM pointers.
def rb_vm_insn_encode(bin)
Primitive.cexpr! 'SIZET2NUM((VALUE)rb_vm_get_insns_address_table()[NUM2INT(bin)])'
Expand All @@ -316,6 +332,7 @@ def rb_iseqw_to_iseq(iseqw)
C::BOP_AND = Primitive.cexpr! %q{ SIZET2NUM(BOP_AND) }
C::BOP_AREF = Primitive.cexpr! %q{ SIZET2NUM(BOP_AREF) }
C::BOP_EQ = Primitive.cexpr! %q{ SIZET2NUM(BOP_EQ) }
C::BOP_EQQ = Primitive.cexpr! %q{ SIZET2NUM(BOP_EQQ) }
C::BOP_FREEZE = Primitive.cexpr! %q{ SIZET2NUM(BOP_FREEZE) }
C::BOP_GE = Primitive.cexpr! %q{ SIZET2NUM(BOP_GE) }
C::BOP_GT = Primitive.cexpr! %q{ SIZET2NUM(BOP_GT) }
Expand Down
1 change: 1 addition & 0 deletions tool/rjit/bindgen.rb
Expand Up @@ -385,6 +385,7 @@ def push_target(target)
BOP_AND
BOP_AREF
BOP_EQ
BOP_EQQ
BOP_FREEZE
BOP_GE
BOP_GT
Expand Down

0 comments on commit cc9330f

Please sign in to comment.