9
9
*/
10
10
package org .truffleruby .core .klass ;
11
11
12
+ import java .util .Arrays ;
12
13
import java .util .Set ;
13
14
14
15
import com .oracle .truffle .api .source .SourceSection ;
28
29
@ ExportLibrary (InteropLibrary .class )
29
30
public final class RubyClass extends RubyModule implements ObjectGraphNode {
30
31
32
+ private static final RubyClass [] EMPTY_CLASS_ARRAY = new RubyClass [0 ];
33
+
31
34
public final boolean isSingleton ;
32
35
/** If this is an object's metaclass, then nonSingletonClass is the logical class of the object. */
33
36
public final RubyClass nonSingletonClass ;
34
37
public final RubyDynamicObject attached ;
35
38
public Shape instanceShape ;
36
39
/* a RubyClass, or nil for BasicObject, or null when not yet initialized */
37
40
public Object superclass ;
41
+ public RubyClass [] ancestorClasses ;
42
+
43
+ /** Depth from BasicObject (= 0) in the inheritance hierarchy. */
44
+ public int depth ;
38
45
39
46
public RubyClass (
40
47
RubyClass classClass ,
@@ -50,20 +57,27 @@ public RubyClass(
50
57
assert isSingleton == (instanceShape == null );
51
58
this .isSingleton = isSingleton ;
52
59
this .attached = attached ;
53
- this .superclass = superclass ;
54
60
this .instanceShape = instanceShape ;
55
61
62
+ if (superclass instanceof RubyClass ) {
63
+ updateSuperclass ((RubyClass ) superclass );
64
+ } else { // BasicObject (nil superclass) or uninitialized class (null)
65
+ this .depth = 0 ;
66
+ this .superclass = superclass ;
67
+ this .ancestorClasses = EMPTY_CLASS_ARRAY ;
68
+ }
69
+
56
70
this .nonSingletonClass = computeNonSingletonClass (isSingleton , superclass );
57
71
}
58
72
59
- /** Special constructor to build the 'Class' RubyClass itself */
73
+
74
+ /** Special constructor to build the 'Class' RubyClass itself. The superclass is set later. */
60
75
RubyClass (RubyContext context , Shape classShape ) {
61
76
super (context , classShape , "constructor only for the class Class" );
62
77
this .isSingleton = false ;
63
78
this .attached = null ;
64
79
this .superclass = null ;
65
80
this .instanceShape = classShape ;
66
-
67
81
this .nonSingletonClass = this ;
68
82
}
69
83
@@ -86,10 +100,19 @@ public boolean isInitialized() {
86
100
87
101
public void setSuperClass (RubyClass superclass ) {
88
102
assert this .superclass == null || this .superclass == superclass ;
89
- this . superclass = superclass ;
103
+ updateSuperclass ( superclass ) ;
90
104
fields .setSuperClass (superclass );
91
105
}
92
106
107
+ private void updateSuperclass (RubyClass superclass ) {
108
+ final RubyClass [] superAncestors = superclass .ancestorClasses ;
109
+ final RubyClass [] ancestors = Arrays .copyOf (superAncestors , superAncestors .length + 1 );
110
+ ancestors [superAncestors .length ] = superclass ;
111
+ this .superclass = superclass ;
112
+ this .depth = superclass .depth + 1 ;
113
+ this .ancestorClasses = ancestors ;
114
+ }
115
+
93
116
@ Override
94
117
public void getAdjacentObjects (Set <Object > reachable ) {
95
118
super .getAdjacentObjects (reachable );
0 commit comments