When I have a non-frozen non-interned string, I can get its source location (suppose the file name is foo_file.rb):
require "objspace"
ObjectSpace.trace_object_allocations_start
obj = "foo"
ObjectSpace.allocation_sourcefile(obj) # => foo_file.rb
ObjectSpace.allocation_sourceline(obj) # => 4
When I have an interned string, the source location becomes unavailable (note the interning feature with freeze after a string literal):
obj = "foo".freeze
ObjectSpace.allocation_sourcefile(obj) # => nil
ObjectSpace.allocation_sourceline(obj) # => nil
I can confirm that this unavailability is not because it is frozen, but it is because it is interned:
obj = "foo"
obj = obj.freeze
ObjectSpace.allocation_sourcefile(obj) # => foo_file.rb
ObjectSpace.allocation_sourceline(obj) # => 4
Why can't I get the source information from an interned string?
When I have a regex, I can't get the source information even if it is not frozen:
obj = /foo/
obj.frozen? # => false
ObjectSpace.allocation_sourcefile(obj) # => nil
ObjectSpace.allocation_sourceline(obj) # => nil
Why can't I get the source location from a regex even when it is not frozen?
Those two objects were simply allocated before the ObjectSpace.trace_object_allocations_start call or any other Ruby code in this file was executed:
"foo".freeze was allocated at compile time by rb_fstring() (and originally also at parse time)
the additional allocation of "foo" at run time happens only because internally obj = "foo" is actually similar to obj = "foo".dup. Take a look at the definition of the putstring YARV instruction and the rb_str_resurrect() function for more details.
/foo/ was allocated at parse time by reg_compile(). That's it. No duplication here, so it's always the same object (no interning occurs though and it might be surprising behavior to some):
3.times.map{ "foo".object_id }.uniq # => [21063740, 21063720, 21063700]
3.times.map{ "foo".freeze.object_id }.uniq # => [21064340]
3.times.map{ /foo/.object_id }.uniq # => [21065100]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With