Created
June 15, 2019 20:11
-
-
Save brixen/ef4e475e0b83292338493104e3a7307e to your computer and use it in GitHub Desktop.
Illustration of Rubinius tagged nil that enables tracing where a nil value originated
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rbx tagged_nil.rb | |
main # Rubinius::Loader at core/loader.rb:852 (+90) | |
script # Rubinius::Loader at core/loader.rb:667 (+343) | |
load_script # Rubinius::CodeLoader at | |
core/code_loader.rb:280 (+60) | |
load # Rubinius::CodeLoader::Source(Rubinius::CodeLoader::Script) at | |
core/code_loader.rb:119 (+81) | |
run_script # Rubinius::CodeLoader::Source(Rubinius::CodeLoader::Script) at | |
core/code_loader.rb:132 (+21) | |
__script__ # Object at tagged_nil.rb:50 (+153) | |
m # B at tagged_nil.rb:40 (+31) | |
m # C at tagged_nil.rb:46 (+3) | |
catch_me_if_you_can! (method_missing) # NilClass at tagged_nil.rb:34 (+361) | |
undefined method catch_me_if_you_can! called on an instance of NilClass originating in 'who_me?' at (dynamic):1 (NoMethodError) | |
An exception occurred running tagged_nil.rb |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class A | |
dynamic_method :who_me? do |g| | |
r0 = g.new_register | |
g.noop | |
g.noop | |
g.r_load_nil r0, 0 | |
g.r_store_stack r0 | |
g.ret | |
end | |
end | |
class NilClass | |
def method_missing(*_, **) | |
sym, = _ | |
m = Rubinius::Mirror::Object.reflect self | |
code_id = m.nil_code_id.to_s 16 | |
ip = m.nil_ip | |
cc = nil | |
ObjectSpace.each_object(Rubinius::CompiledCode) do |c| | |
cc = c if c.code_id.start_with? code_id | |
end | |
if cc | |
msg = "undefined method #{sym} called on an instance of NilClass originating in '#{cc.name}' at #{cc.file}:#{cc.line_from_ip(ip)}" | |
else | |
msg = "undefined method #{sym} called on an instance of NilClass" | |
end | |
raise NoMethodError, msg | |
end | |
end | |
class B | |
def m(a) | |
C.new.m a | |
end | |
end | |
class C | |
def m(a) | |
a.catch_me_if_you_can! | |
end | |
end | |
B.new.m A.new.who_me? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment