sawa
sawa

Reputation: 168101

Why can't I get the allocation source information?

1. String

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?

2. Regxp

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?

Upvotes: 3

Views: 86

Answers (1)

cremno
cremno

Reputation: 4927

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]
    

Upvotes: 2

Related Questions