Class: RubyVM::RJIT::Invariants
- Inherits:
-
Object
- Object
- RubyVM::RJIT::Invariants
- Defined in:
- lib/ruby_vm/rjit/invariants.rb
Class Method Summary collapse
- .assume_bop_not_redefined(jit, klass, op) ⇒ Object
- .assume_method_basic_definition(jit, klass, mid) ⇒ Object
- .assume_method_lookup_stable(jit, cme) ⇒ Object
- .assume_stable_constant_names(jit, idlist) ⇒ Object
- .ensure_block_entry_exit(jit, cause:) ⇒ Object
-
.initialize(cb, ocb, compiler, exit_compiler) ⇒ Object
Called by RubyVM::RJIT::Compiler to lazily initialize this.
- .on_cme_invalidate(cme) ⇒ Object
- .on_constant_ic_update(iseq, ic, insn_idx) ⇒ Object
- .on_constant_state_changed(id) ⇒ Object
- .on_tracing_invalidate_all ⇒ Object
- .on_update_references ⇒ Object
- .record_global_inval_patch(asm, target) ⇒ Object
Class Method Details
.assume_bop_not_redefined(jit, klass, op) ⇒ Object
27 28 29 30 31 32 33 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 27 def assume_bop_not_redefined(jit, klass, op) return false unless C.BASIC_OP_UNREDEFINED_P(klass, op) ensure_block_entry_exit(jit, cause: 'assume_bop_not_redefined') @bop_blocks << jit.block true end |
.assume_method_basic_definition(jit, klass, mid) ⇒ Object
42 43 44 45 46 47 48 49 50 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 42 def assume_method_basic_definition(jit, klass, mid) if C.rb_method_basic_definition_p(klass, mid) cme = C.rb_callable_method_entry(klass, mid) assume_method_lookup_stable(jit, cme) true else false end end |
.assume_method_lookup_stable(jit, cme) ⇒ Object
36 37 38 39 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 36 def assume_method_lookup_stable(jit, cme) ensure_block_entry_exit(jit, cause: 'assume_method_lookup_stable') @cme_blocks[cme.to_i] << jit.block end |
.assume_stable_constant_names(jit, idlist) ⇒ Object
52 53 54 55 56 57 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 52 def assume_stable_constant_names(jit, idlist) (0..).each do |i| break if (id = idlist[i]) == 0 @const_blocks[id] << jit.block end end |
.ensure_block_entry_exit(jit, cause:) ⇒ Object
119 120 121 122 123 124 125 126 127 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 119 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:) @ocb.write(asm) end end end |
.initialize(cb, ocb, compiler, exit_compiler) ⇒ Object
Called by RubyVM::RJIT::Compiler to lazily initialize this
11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 11 def initialize(cb, ocb, compiler, exit_compiler) @cb = cb @ocb = ocb @compiler = compiler @exit_compiler = exit_compiler @bop_blocks = Set.new # TODO: actually invalidate this @cme_blocks = Hash.new { |h, k| h[k] = Set.new } @const_blocks = Hash.new { |h, k| h[k] = Set.new } @patches = {} # freeze # workaround a binding.irb issue. TODO: resurrect this end |
.on_cme_invalidate(cme) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 69 def on_cme_invalidate(cme) @cme_blocks.fetch(cme.to_i, []).each do |block| @cb.with_write_addr(block.start_addr) do asm = Assembler.new asm.comment('on_cme_invalidate') asm.jmp(block.entry_exit) @cb.write(asm) end # TODO: re-generate branches that refer to this block end @cme_blocks.delete(cme.to_i) end |
.on_constant_ic_update(iseq, ic, insn_idx) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 82 def on_constant_ic_update(iseq, ic, insn_idx) # TODO: check multi ractor as well if ic.entry.ic_cref # No need to recompile the slowpath return end pc = iseq.body.iseq_encoded + insn_idx insn_name = Compiler.decode_insn(pc.*).name if insn_name != :opt_getconstant_path && insn_name != :trace_opt_getconstant_path raise 'insn_idx was not at opt_getconstant_path' end if ic.to_i != pc[1] raise 'insn_idx + 1 was not at the updated IC' end @compiler.invalidate_blocks(iseq, pc.to_i) end |
.on_constant_state_changed(id) ⇒ Object
100 101 102 103 104 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 100 def on_constant_state_changed(id) @const_blocks.fetch(id, []).each do |block| @compiler.invalidate_block(block) end end |
.on_tracing_invalidate_all ⇒ Object
106 107 108 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 106 def on_tracing_invalidate_all invalidate_all end |
.on_update_references ⇒ Object
110 111 112 113 114 115 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 110 def on_update_references # Give up. In order to support GC.compact, you'd have to update ISEQ # addresses in BranchStub, etc. Ideally, we'd need to update moved # pointers in JITed code here, but we just invalidate all for now. invalidate_all end |
.record_global_inval_patch(asm, target) ⇒ Object
60 61 62 63 64 65 66 67 |
# File 'lib/ruby_vm/rjit/invariants.rb', line 60 def record_global_inval_patch(asm, target) asm.pos_marker do |address| if @patches.key?(address) raise 'multiple patches in the same address' end @patches[address] = target end end |