[#35631] [Ruby 1.9 - Bug #4558][Open] TestSocket#test_closed_read fails after r31230 — Tomoyuki Chikanaga <redmine@...>

23 messages 2011/04/06

[#35632] [Ruby 1.9 - Bug #4559][Open] Proc#== does not match the documented behaviour — Adam Prescott <redmine@...>

13 messages 2011/04/06

[#35637] [Ruby 1.9 - Bug #4561][Open] 1.9.2 requires parentheses around argument of method call in an array, where 1.8.7 did not — Dave Schweisguth <redmine@...>

9 messages 2011/04/07

[#35666] caching of the ancestor chain — Xavier Noria <fxn@...>

Why does Ruby cache the ancestors chain? I mean, not why the implementation implies that, but why it works that way conceptually.

9 messages 2011/04/09

[#35734] [Ruby 1.9 - Feature #4574][Open] Numeric#within — redmine@...

16 messages 2011/04/13

[#35753] [Ruby 1.9 - Bug #4576][Open] Range#step miss the last value, if end-exclusive and has float number — redmine@...

61 messages 2011/04/14
[#39566] [Ruby 1.9 - Bug #4576] Range#step miss the last value, if end-exclusive and has float number — Marc-Andre Lafortune <ruby-core@...> 2011/09/15

[#39590] [Ruby 1.9 - Bug #4576] Range#step miss the last value, if end-exclusive and has float number — Marc-Andre Lafortune <ruby-core@...> 2011/09/16

[#39593] Re: [Ruby 1.9 - Bug #4576] Range#step miss the last value, if end-exclusive and has float number — Tanaka Akira <akr@...> 2011/09/16

2011/9/17 Marc-Andre Lafortune <ruby-core@marc-andre.ca>:

[#39608] Re: [Ruby 1.9 - Bug #4576] Range#step miss the last value, if end-exclusive and has float number — Masahiro TANAKA <masa16.tanaka@...> 2011/09/17

I have not been watching ruby-core, but let me give a comment for this issue.

[#35765] [Ruby 1.9 - Bug #4579][Open] SecureRandom + OpenSSL may repeat with fork — redmine@...

27 messages 2011/04/15

[#35866] [Ruby 1.9 - Bug #4603][Open] lib/csv.rb: when the :encoding parameter is not provided, the encoding of CSV data is treated as ASCII-8BIT — yu nobuoka <nobuoka@...>

13 messages 2011/04/24

[#35879] [Ruby 1.9 - Bug #4610][Open] Proc#curry behavior is inconsistent with lambdas containing default argument values — Joshua Ballanco <jballanc@...>

11 messages 2011/04/25

[#35883] [Ruby 1.9 - Bug #4611][Open] [BUG] Segementation fault reported — Deryl Doucette <me@...>

15 messages 2011/04/25

[#35895] [Ruby 1.9 - Feature #4614][Open] [RFC/PATCH] thread_pthread.c: lower RUBY_STACK_MIN_LIMIT to 64K — Eric Wong <normalperson@...>

10 messages 2011/04/25

[ruby-core:35729] Re: caching of the ancestor chain

From: Charles Oliver Nutter <headius@...>
Date: 2011-04-12 22:13:25 UTC
List: ruby-core #35729
On Tue, Apr 12, 2011 at 3:53 AM, Xavier Noria <fxn@hashref.com> wrote:
> Since MRI inserts proxies in the ancestor chain that point to the
> actual modules and adjusts the parent pointers to have a linear
> ancestor chain (by linear I mean that you follow the pointers up and
> you're done), you get this
...
>    p C.ancestors # => [C, M, Object, Kernel, BasicObject]
>    p M.ancestors # => [M, N]
>
> That linear ancestor chain is not updated if the ancestors chain of
> involved modules is modified. That's what I meant by "caching".

Ok, I understand. The llist of modules that module M includes is
copied in only at include time, and additional changes are not made
visible to already-included classes.

> Question was whether this was a conscious design/implementation
> decision on behalf of speed.

I think the problem is less about perf and more about maintaining a
simple logical structure for the superclass hierarchy. With the
current mechanism, modules are included in a well-defined order and
live in their own slots in the class hierarchy. Those slots are
occupied by a wrapper that delegates method lookup to the module
itself. Including a module that includes other modules will simply
also include those modules as they exist at include time.

In order to make already-included modules incorporate new module
includes done later, modules would need to have a pointed to their
insertion point in the hierarchy and be able to make new modifications
to that hierarchy upon change. Unlike method table updates, which
largely "just happen" due to the method table delegation, this would
have to be an *active* change, since the class hierarchy would need to
reflect the new modules.

Now this is certainly possible, but no implementation other than JRuby
has the logic in place to support it (not that it's complicated
logic...we're just the only one to have it). In JRuby, each Module
references (weakly) all insertion points in all hierarchies. This was
done to facilitate method-cache invalidation, but also makes your case
possible too.

With a small patch to JRuby:

diff --git a/src/org/jruby/RubyModule.java b/src/org/jruby/RubyModule.java
index a6470b4..7583666 100644
--- a/src/org/jruby/RubyModule.java
+++ b/src/org/jruby/RubyModule.java
@@ -2018,6 +2018,11 @@ public class RubyModule extends RubyObject {
             modules[i].callMethod(context, "append_features", this);
             modules[i].callMethod(context, "included", this);
         }
+
+        // if we've been included elsewhere, make those hierarchies
include us too
+        for (RubyClass cls : includingHierarchies) {
+            cls.include(modules);
+        }

         return this;
     }

Your script works as you would expect:

~/projects/jruby ➔ jruby ancestor_thing.rb
[C, M, N, Object, Kernel]
[M, N]

I have not thought through the implications of such a change, yet.

- Charlie

In This Thread