Skip to content

Commit deae78c

Browse files
committed
Remove unnecessary invalidations in setSuperClass() and cleanup setting the name of modules
* These invalidations had the side effect of computing the name eagerly for all classes except BasicObject.
1 parent 308f6dc commit deae78c

File tree

5 files changed

+42
-15
lines changed

5 files changed

+42
-15
lines changed

spec/truffle/interop/meta_object_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,19 @@
4141
Truffle::Interop.should_not.has_meta_parents?(Enumerable)
4242
end
4343
end
44+
45+
describe "Truffle::Interop.meta_object?" do
46+
it "returns true for a Class" do
47+
Truffle::Interop.should.meta_object?(String)
48+
Truffle::Interop.should.meta_object?(Class.new)
49+
end
50+
51+
it "returns true for a Module" do
52+
Truffle::Interop.should.meta_object?(Kernel)
53+
Truffle::Interop.should.meta_object?(Module.new)
54+
end
55+
56+
it "returns false for objects" do
57+
Truffle::Interop.should_not.meta_object?(Object.new)
58+
end
59+
end

src/main/java/org/truffleruby/core/klass/RubyClass.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,10 @@ public RubyClass(
5959
assert !isSingleton || givenBaseName == null;
6060
this.isSingleton = isSingleton;
6161
this.attached = attached;
62+
this.nonSingletonClass = computeNonSingletonClass(isSingleton, superclass);
63+
this.directNonSingletonSubclasses = new ConcurrentWeakSet<>();
6264

6365
if (superclass instanceof RubyClass) {
64-
if (lexicalParent == null && givenBaseName != null) {
65-
fields.setFullName(givenBaseName);
66-
}
6766
// superclass should be set after "full name"
6867
this.superclass = superclass;
6968
this.ancestorClasses = computeAncestorClasses((RubyClass) superclass);
@@ -75,13 +74,13 @@ public RubyClass(
7574
}
7675
} else { // BasicObject (nil superclass)
7776
assert superclass == nil;
77+
assert givenBaseName == "BasicObject";
7878
this.superclass = superclass;
7979
this.ancestorClasses = EMPTY_CLASS_ARRAY;
8080
this.depth = 0;
8181
}
8282

83-
this.directNonSingletonSubclasses = new ConcurrentWeakSet<>();
84-
this.nonSingletonClass = computeNonSingletonClass(isSingleton, superclass);
83+
fields.afterConstructed();
8584
}
8685

8786

@@ -91,6 +90,7 @@ public RubyClass(
9190
this.isSingleton = false;
9291
this.attached = null;
9392
this.nonSingletonClass = this;
93+
this.directNonSingletonSubclasses = new ConcurrentWeakSet<>();
9494

9595
RubyClass basicObjectClass = ClassNodes.createBootClass(language, this, nil, "BasicObject");
9696
RubyClass objectClass = ClassNodes.createBootClass(language, this, basicObjectClass, "Object");
@@ -100,8 +100,9 @@ public RubyClass(
100100
this.superclass = superclass;
101101
this.ancestorClasses = computeAncestorClasses(superclass);
102102
this.depth = superclass.depth + 1;
103-
this.directNonSingletonSubclasses = new ConcurrentWeakSet<>();
104103
fields.setSuperClass(superclass);
104+
105+
fields.afterConstructed();
105106
}
106107

107108
private RubyClass computeNonSingletonClass(boolean isSingleton, Object superclassObject) {

src/main/java/org/truffleruby/core/module/ModuleFields.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,27 @@ public ModuleFields(
145145
classVariables = new ClassVariableStorage(language);
146146
start = new PrependMarker(this);
147147
this.includedBy = rubyModule instanceof RubyClass ? null : new ConcurrentWeakSet<>();
148+
149+
if (lexicalParent == null && givenBaseName != null) {
150+
setFullName(givenBaseName);
151+
}
152+
}
153+
154+
/** Compute the name eagerly now as it can cause a Shape transition. We need to do so because
155+
* InteropLibrary$Asserts.assertMetaObject calls getMetaQualifiedName() and if getName() at that point adds the
156+
* object_id property then accepts() asserts that follow will fail. We cannot call this in the ModuleFields
157+
* constructor as the name depends on fields of RubyClass (e.g., isSingleton). */
158+
public void afterConstructed() {
159+
getName();
148160
}
149161

150162
public RubyConstant getAdoptedByLexicalParent(
151163
RubyContext context,
152164
RubyModule lexicalParent,
153165
String name,
154166
Node currentNode) {
167+
assert name != null;
168+
155169
RubyConstant previous = lexicalParent.fields.setConstantInternal(
156170
context,
157171
currentNode,
@@ -981,12 +995,10 @@ public ConcurrentMap<RubyModule, RubyModule> getRefinements() {
981995
return refinements;
982996
}
983997

998+
/** Must be called inside the RubyClass constructor */
984999
public void setSuperClass(RubyClass superclass) {
9851000
assert rubyModule instanceof RubyClass;
9861001
this.parentModule = superclass.fields.start;
987-
newMethodsVersion(new ArrayList<>(methods.keySet()));
988-
newConstantsVersion(new ArrayList<>(constants.keySet()));
989-
newHierarchyVersion();
9901002
}
9911003

9921004
@Override

src/main/java/org/truffleruby/core/module/ModuleNodes.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,11 @@ public static RubyModule createModule(RubyContext context, SourceSection sourceS
161161
sourceSection,
162162
lexicalParent,
163163
name);
164+
165+
module.fields.afterConstructed();
166+
164167
if (lexicalParent != null) {
165168
module.fields.getAdoptedByLexicalParent(context, lexicalParent, name, currentNode);
166-
} else if (name != null) { // bootstrap module
167-
module.fields.setFullName(name);
168169
}
169170
return module;
170171
}

src/main/java/org/truffleruby/core/module/RubyModule.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,7 @@ public RubyModule(
6161

6262
protected RubyModule(RubyLanguage language, Shape classShape, String constructorOnlyForClassClass) {
6363
super(classShape, constructorOnlyForClassClass);
64-
65-
final ModuleFields fields = new ModuleFields(language, null, null, "Class", this);
66-
fields.setFullName("Class");
67-
this.fields = fields;
64+
this.fields = new ModuleFields(language, null, null, "Class", this);
6865
}
6966

7067
public String getName() {

0 commit comments

Comments
 (0)