summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ruby_vm/mjit/insn_compiler.rb46
-rw-r--r--lib/ruby_vm/mjit/invariants.rb10
2 files changed, 48 insertions, 8 deletions
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb
index 7426f678ba..dabc0b385c 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}")
- # 45/101
+ # 46/101
case insn.name
when :nop then nop(jit, ctx, asm)
when :getlocal then getlocal(jit, ctx, asm)
@@ -37,7 +37,7 @@ module RubyVM::MJIT
when :setinstancevariable then setinstancevariable(jit, ctx, asm)
# getclassvariable
# setclassvariable
- # opt_getconstant_path
+ when :opt_getconstant_path then opt_getconstant_path(jit, ctx, asm)
# getconstant
# setconstant
# getglobal
@@ -209,7 +209,47 @@ module RubyVM::MJIT
# getclassvariable
# setclassvariable
- # opt_getconstant_path
+
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def opt_getconstant_path(jit, ctx, asm)
+ ic = C.iseq_inline_constant_cache.new(jit.operand(0))
+ idlist = ic.segments
+
+ # See vm_ic_hit_p(). The same conditions are checked in yjit_constant_ic_update().
+ ice = ic.entry
+ if ice.nil?
+ # In this case, leave a block that unconditionally side exits
+ # for the interpreter to invalidate.
+ return CantCompile
+ end
+
+ # Make sure there is an exit for this block as the interpreter might want
+ # to invalidate this block from yjit_constant_ic_update().
+ Invariants.ensure_block_entry_exit(jit, cause: 'opt_getconstant_path')
+
+ if ice.ic_cref # with cref
+ # Not supported yet
+ return CantCompile
+ else # without cref
+ # TODO: implement this
+ # Optimize for single ractor mode.
+ # if !assume_single_ractor_mode(jit, ocb)
+ # return CantCompile
+ # end
+
+ # Invalidate output code on any constant writes associated with
+ # constants referenced within the current block.
+ #assume_stable_constant_names(jit, ocb, idlist);
+
+ putobject(jit, ctx, asm, val: ice.value)
+ end
+
+ jump_to_next_insn(jit, ctx, asm)
+ EndBlock
+ end
+
# getconstant
# setconstant
# getglobal
diff --git a/lib/ruby_vm/mjit/invariants.rb b/lib/ruby_vm/mjit/invariants.rb
index d291ade9bf..8cb70cf121 100644
--- a/lib/ruby_vm/mjit/invariants.rb
+++ b/lib/ruby_vm/mjit/invariants.rb
@@ -24,14 +24,14 @@ module RubyVM::MJIT
def assume_bop_not_redefined(jit, klass, op)
return false unless C.BASIC_OP_UNREDEFINED_P(klass, op)
- ensure_block_entry_exit(jit.block, cause: 'assume_bop_not_redefined')
+ ensure_block_entry_exit(jit, cause: 'assume_bop_not_redefined')
@bop_blocks << jit.block
true
end
# @param jit [RubyVM::MJIT::JITState]
def assume_method_lookup_stable(jit, cme)
- ensure_block_entry_exit(jit.block, cause: 'assume_method_lookup_stable')
+ ensure_block_entry_exit(jit, cause: 'assume_method_lookup_stable')
@cme_blocks[cme.to_i] << jit.block
end
@@ -80,10 +80,10 @@ module RubyVM::MJIT
end
end
- private
-
+ # @param jit [RubyVM::MJIT::JITState]
# @param block [RubyVM::MJIT::Block]
- def ensure_block_entry_exit(block, cause:)
+ def ensure_block_entry_exit(jit, cause:)
+ block = jit.block
if block.entry_exit.nil?
block.entry_exit = Assembler.new.then do |asm|
@exit_compiler.compile_entry_exit(block.pc, block.ctx, asm, cause:)