b) a + b end def call(...) recv(...) end call(1, 2) Stack self 1 2 ME BH TYPE self 1 2 CALL_INFO memcpy( ) ISEQs tagged as forwardable Call sites tagged as forwarding CALL_INFO
def recv(a, b) a + b end def call(...) recv(...) end # def run # call(1, 2) # call(1, 2) # call(1, 2) # ... eval "def run; " + 200.times.map { "call(1, 2)" }.join("; ") + "; end" 200000.times do run end
class B < A; end a = A.new b = B.new def call_method(obj) obj.a # never hits inline cache end # def run(a, b) # call_method(a) # call_method(b) # call_method(a) # call_method(b) # ... eval "def run(a, b); " + 200.times.map { "call_method(a); call_method(b)" }.join("; ") + "; end" 200000.times do run(a, b) end opt_send_without_block Never hits inline cache
end end class B < A; end a = A.new b = B.new def call_method(obj) obj.a { } # Always send instruction end # def run(a, b) # call_method(a) # call_method(b) # call_method(a) # call_method(b) # ... eval "def run(a, b); " + 200.times.map { "call_method(a); call_method(b)" }.join("; ") + "; end" 200000.times do run(a, b) end send Never hits inline cache
@a = a @b = a end end def call(a, b) Foo.new(a:, b:) end # def run # call(1, 2) # call(1, 2) # ... eval "def run; " + 200.times.map { "call(1, 2)" }.join("; ") + "; end" 200000.times do run end