Skip to content

Commit befb4af

Browse files
committed
Share logic to freeze an object and optimize the node for non-singleton objects
1 parent 77c68a0 commit befb4af

File tree

4 files changed

+31
-42
lines changed

4 files changed

+31
-42
lines changed

src/main/java/org/truffleruby/core/kernel/KernelNodes.java

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -829,30 +829,11 @@ protected int getCacheLimit() {
829829

830830
@CoreMethod(names = "freeze")
831831
public abstract static class KernelFreezeNode extends CoreMethodArrayArgumentsNode {
832-
833-
@Specialization(limit = "getRubyLibraryCacheLimit()", guards = "!isRubyDynamicObject(self)")
832+
@Specialization
834833
protected Object freeze(Object self,
835-
@CachedLibrary("self") RubyLibrary rubyLibrary) {
836-
rubyLibrary.freeze(self);
837-
return self;
834+
@Cached TypeNodes.ObjectFreezeNode objectFreezeNode) {
835+
return objectFreezeNode.execute(self);
838836
}
839-
840-
@Specialization(limit = "getRubyLibraryCacheLimit()", guards = "isRubyDynamicObject(self)")
841-
protected Object freezeDynamicObject(Object self,
842-
@CachedLibrary("self") RubyLibrary rubyLibrary,
843-
@CachedLibrary(limit = "1") RubyLibrary rubyLibraryMetaClass,
844-
@Cached ConditionProfile singletonClassUnfrozenProfile,
845-
@Cached MetaClassNode metaClassNode) {
846-
final RubyClass metaClass = metaClassNode.execute(self);
847-
if (singletonClassUnfrozenProfile.profile(metaClass.isSingleton &&
848-
!(RubyGuards.isRubyClass(self) && ((RubyClass) self).isSingleton) &&
849-
!rubyLibraryMetaClass.isFrozen(metaClass))) {
850-
rubyLibraryMetaClass.freeze(metaClass);
851-
}
852-
rubyLibrary.freeze(self);
853-
return self;
854-
}
855-
856837
}
857838

858839
@GenerateUncached

src/main/java/org/truffleruby/core/support/TypeNodes.java

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.ArrayList;
1313
import java.util.List;
1414

15+
import com.oracle.truffle.api.dsl.Bind;
1516
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
1617
import com.oracle.truffle.api.dsl.GenerateUncached;
1718
import com.oracle.truffle.api.dsl.NeverDefault;
@@ -36,6 +37,7 @@
3637
import org.truffleruby.core.symbol.RubySymbol;
3738
import org.truffleruby.language.Nil;
3839
import org.truffleruby.language.NotProvided;
40+
import org.truffleruby.language.RubyBaseNode;
3941
import org.truffleruby.language.RubyDynamicObject;
4042
import org.truffleruby.language.RubyGuards;
4143
import org.truffleruby.language.RubyNode;
@@ -109,43 +111,49 @@ protected boolean objectEqual(Object a, Object b,
109111
}
110112
}
111113

112-
@Primitive(name = "object_freeze")
113-
public abstract static class ObjectFreezeNode extends PrimitiveArrayArgumentsNode {
114-
@Specialization(limit = "getRubyLibraryCacheLimit()")
114+
public abstract static class ObjectFreezeNode extends RubyBaseNode {
115+
116+
public abstract Object execute(Object self);
117+
118+
@Specialization(guards = "!isRubyDynamicObject(self)", limit = "getRubyLibraryCacheLimit()")
115119
protected Object freeze(Object self,
116120
@CachedLibrary("self") RubyLibrary rubyLibrary) {
117-
assert !(self instanceof RubyDynamicObject && ((RubyDynamicObject) self).getMetaClass().isSingleton)
118-
: "Primitive.object_freeze does not handle instances of singleton classes, see KernelFreezeNode";
119121
rubyLibrary.freeze(self);
120122
return self;
121123
}
122-
}
123124

124-
@Primitive(name = "object_freeze_with_singleton_class")
125-
public abstract static class ObjectFreezeWithSingletonClassNode extends PrimitiveArrayArgumentsNode {
126-
@Specialization(limit = "getRubyLibraryCacheLimit()", guards = "!isRubyDynamicObject(self)")
127-
protected Object freeze(Object self,
128-
@CachedLibrary("self") RubyLibrary rubyLibrary) {
125+
@Specialization(guards = "!metaClass.isSingleton", limit = "getRubyLibraryCacheLimit()")
126+
protected Object freezeNormalObject(RubyDynamicObject self,
127+
@CachedLibrary("self") RubyLibrary rubyLibrary,
128+
@Cached MetaClassNode metaClassNode,
129+
@Bind("metaClassNode.execute(self)") RubyClass metaClass) {
129130
rubyLibrary.freeze(self);
130131
return self;
131132
}
132133

133-
@Specialization(limit = "getRubyLibraryCacheLimit()", guards = "isRubyDynamicObject(self)")
134-
protected Object freezeDynamicObject(Object self,
134+
@Specialization(guards = "metaClass.isSingleton", limit = "getRubyLibraryCacheLimit()")
135+
protected Object freezeSingletonObject(RubyDynamicObject self,
135136
@CachedLibrary("self") RubyLibrary rubyLibrary,
136137
@CachedLibrary(limit = "1") RubyLibrary rubyLibraryMetaClass,
137138
@Cached ConditionProfile singletonClassUnfrozenProfile,
138-
@Cached MetaClassNode metaClassNode) {
139-
final RubyClass metaClass = metaClassNode.execute(self);
140-
if (singletonClassUnfrozenProfile.profile(metaClass.isSingleton &&
141-
!(RubyGuards.isRubyClass(self) && ((RubyClass) self).isSingleton) &&
142-
!rubyLibraryMetaClass.isFrozen(metaClass))) {
139+
@Cached MetaClassNode metaClassNode,
140+
@Bind("metaClassNode.execute(self)") RubyClass metaClass) {
141+
if (singletonClassUnfrozenProfile.profile(
142+
!RubyGuards.isSingletonClass(self) && !rubyLibraryMetaClass.isFrozen(metaClass))) {
143143
rubyLibraryMetaClass.freeze(metaClass);
144144
}
145145
rubyLibrary.freeze(self);
146146
return self;
147147
}
148+
}
148149

150+
@Primitive(name = "object_freeze")
151+
public abstract static class ObjectFreezePrimitive extends PrimitiveArrayArgumentsNode {
152+
@Specialization
153+
protected Object freeze(Object self,
154+
@Cached ObjectFreezeNode objectFreezeNode) {
155+
return objectFreezeNode.execute(self);
156+
}
149157
}
150158

151159
@Primitive(name = "immediate_value?")

src/main/java/org/truffleruby/language/RubyGuards.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public static boolean isNegativeZero(double value) {
226226

227227
// Composite
228228

229-
public static boolean isSingletonClass(RubyModule value) {
229+
public static boolean isSingletonClass(Object value) {
230230
return value instanceof RubyClass && ((RubyClass) value).isSingleton;
231231
}
232232

src/main/ruby/truffleruby/core/marshal.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ def construct(ivar_index = nil, call_proc = true, postpone_freezing = false)
729729

730730
if @freeze && !postpone_freezing && !(Primitive.object_kind_of?(obj, Class) || Primitive.object_kind_of?(obj, Module))
731731
obj = -obj if Primitive.class_of(obj) == String
732-
Primitive.object_freeze_with_singleton_class(obj)
732+
Primitive.object_freeze(obj)
733733
end
734734

735735
return @proc.call(obj) if call_proc and @proc and @call

0 commit comments

Comments
 (0)