can someone explain this?

A

Andy Bogdanov

# First I create a proc:
p = proc {
self::X = Class.new
def self.X
X.new
end
}

# Then I create a module:
A = Module.new(&p)
puts A.X # => #<A::X:0x9c2e774>

# Then i create another module:
B = Module.new(&p)
puts B.X # => #<B::X:0x9c39304>

# Everything seems to be ok.

# And now to the strange part.
# After module B was created A.X started to return instances of B::X
puts A.X # => #<B::X:0x9c38238>

If more modules are created with the same proc method X returns
instances of X from the last created module. If I use "self::X.new"
instead of "X.new" everything works as expected, but I can't understand
why it works like that with "X.new". Is this a bug or it's supposed to
be this way?
 
R

Ryan Davis

# First I create a proc:
p = proc {
self::X = Class.new
def self.X
X.new
end
}

# Then I create a module:
A = Module.new(&p)
puts A.X # => #<A::X:0x9c2e774>

# Then i create another module:
B = Module.new(&p)
puts B.X # => #<B::X:0x9c39304>

# Everything seems to be ok.

# And now to the strange part.
# After module B was created A.X started to return instances of B::X
puts A.X # => #<B::X:0x9c38238>

If more modules are created with the same proc method X returns
instances of X from the last created module. If I use "self::X.new"
instead of "X.new" everything works as expected, but I can't understand
why it works like that with "X.new". Is this a bug or it's supposed to
be this way?

I suggest you send that to ruby-core@
 
M

Michael Edgar

[+ruby-core]

Also note that calling A.module_eval(&p) after your code then changes =
both methods to create A instances.

In Ruby 1.9, there is an inline cache for constant references. Dumping =
the bytecode for the self.X method
shows this in action:

[3,
[:trace, 8],
4,
[:trace, 1],
[:getinlinecache, :label_11, 0],
[:getconstant, :X],
[:setinlinecache, 0],
:label_11,
[:send, :new, 0, nil, 0, 1],
5,
[:trace, 16],
4,
[:leave]]
=20
If you use self::X.new in A/B.X, this forces constant resolution each =
time, and the inline cache is not used:

[3,
[:trace, 8],
4,
[:trace, 1],
[:putself],
[:getconstant, :X],
[:send, :new, 0, nil, 0, 1],
5,
[:trace, 16],
4,
[:leave]]

The proc is compiled only once, and thus so does the method definition. =
The two method objects
are in fact distinct, of course.
=3D> false

My best guess: the two methods likely share the same instruction =
sequence object, and thus the
same inline caches, and the cache is not properly clearing when it =
should be.

Michael Edgar
(e-mail address removed)
http://carboni.ca/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top