Skip to content

Commit 5dbe896

Browse files
committed
[GR-25377] Order specializations in *ClassNode nodes by their frequency using SpecializationStatistics
PullRequest: truffleruby/3820
2 parents 2beb695 + 2da4437 commit 5dbe896

File tree

4 files changed

+76
-77
lines changed

4 files changed

+76
-77
lines changed

src/main/java/org/truffleruby/language/objects/ImmutableClassNode.java

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.oracle.truffle.api.dsl.Specialization;
2929
import com.oracle.truffle.api.dsl.TypeSystemReference;
3030

31+
// Specializations are order by their frequency on railsbench using --engine.SpecializationStatistics
3132
@GenerateInline
3233
@GenerateCached(false)
3334
@GenerateUncached
@@ -40,56 +41,44 @@ public final RubyClass execute(Node node, Object value) {
4041

4142
protected abstract RubyClass execute(Node node, Object value, CoreLibrary coreLibrary);
4243

43-
// Cover all primitives, nil and symbols
44-
45-
@Specialization(guards = "value")
46-
protected RubyClass metaClassTrue(boolean value, CoreLibrary coreLibrary) {
47-
return coreLibrary.trueClass;
48-
}
49-
50-
@Specialization(guards = "!value")
51-
protected RubyClass metaClassFalse(boolean value, CoreLibrary coreLibrary) {
52-
return coreLibrary.falseClass;
53-
}
54-
5544
@Specialization
5645
protected RubyClass metaClassInt(int value, CoreLibrary coreLibrary) {
5746
return coreLibrary.integerClass;
5847
}
5948

6049
@Specialization
61-
protected RubyClass metaClassLong(long value, CoreLibrary coreLibrary) {
62-
return coreLibrary.integerClass;
63-
}
64-
65-
@Specialization
66-
protected RubyClass metaClassBignum(RubyBignum value, CoreLibrary coreLibrary) {
67-
return coreLibrary.integerClass;
50+
protected RubyClass metaClassImmutableString(ImmutableRubyString value, CoreLibrary coreLibrary) {
51+
return coreLibrary.stringClass;
6852
}
6953

7054
@Specialization
71-
protected RubyClass metaClassDouble(double value, CoreLibrary coreLibrary) {
72-
return coreLibrary.floatClass;
55+
protected RubyClass metaClassSymbol(RubySymbol value, CoreLibrary coreLibrary) {
56+
return coreLibrary.symbolClass;
7357
}
7458

7559
@Specialization
7660
protected RubyClass metaClassNil(Nil value, CoreLibrary coreLibrary) {
7761
return coreLibrary.nilClass;
7862
}
7963

80-
@Specialization
81-
protected RubyClass metaClassSymbol(RubySymbol value, CoreLibrary coreLibrary) {
82-
return coreLibrary.symbolClass;
64+
@Specialization(guards = "value")
65+
protected RubyClass metaClassTrue(boolean value, CoreLibrary coreLibrary) {
66+
return coreLibrary.trueClass;
67+
}
68+
69+
@Specialization(guards = "!value")
70+
protected RubyClass metaClassFalse(boolean value, CoreLibrary coreLibrary) {
71+
return coreLibrary.falseClass;
8372
}
8473

8574
@Specialization
86-
protected RubyClass metaClassEncoding(RubyEncoding value, CoreLibrary coreLibrary) {
87-
return coreLibrary.encodingClass;
75+
protected RubyClass metaClassLong(long value, CoreLibrary coreLibrary) {
76+
return coreLibrary.integerClass;
8877
}
8978

9079
@Specialization
91-
protected RubyClass metaClassImmutableString(ImmutableRubyString value, CoreLibrary coreLibrary) {
92-
return coreLibrary.stringClass;
80+
protected RubyClass metaClassEncoding(RubyEncoding value, CoreLibrary coreLibrary) {
81+
return coreLibrary.encodingClass;
9382
}
9483

9584
@Specialization
@@ -98,8 +87,18 @@ protected RubyClass metaClassRegexp(RubyRegexp value, CoreLibrary coreLibrary) {
9887
}
9988

10089
@Specialization
101-
protected RubyClass metaClassIntRange(RubyIntOrLongRange value, CoreLibrary coreLibrary) {
90+
protected RubyClass metaClassRange(RubyIntOrLongRange value, CoreLibrary coreLibrary) {
10291
return coreLibrary.rangeClass;
10392
}
10493

94+
@Specialization
95+
protected RubyClass metaClassDouble(double value, CoreLibrary coreLibrary) {
96+
return coreLibrary.floatClass;
97+
}
98+
99+
@Specialization
100+
protected RubyClass metaClassBignum(RubyBignum value, CoreLibrary coreLibrary) {
101+
return coreLibrary.integerClass;
102+
}
103+
105104
}

src/main/java/org/truffleruby/language/objects/LogicalClassNode.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.oracle.truffle.api.dsl.GenerateUncached;
2222
import com.oracle.truffle.api.dsl.Specialization;
2323

24+
// Specializations are order by their frequency on railsbench using --engine.SpecializationStatistics
2425
@GenerateUncached
2526
@TypeSystemReference(NoImplicitCastsToLong.class)
2627
public abstract class LogicalClassNode extends RubyBaseNode {
@@ -36,17 +37,17 @@ public static LogicalClassNode getUncached() {
3637

3738
public abstract RubyClass execute(Object value);
3839

40+
@Specialization
41+
protected RubyClass logicalClassObject(RubyDynamicObject object) {
42+
return object.getLogicalClass();
43+
}
44+
3945
@Specialization(guards = "isPrimitiveOrImmutable(value)")
4046
protected RubyClass logicalClassImmutable(Object value,
4147
@Cached ImmutableClassNode immutableClassNode) {
4248
return immutableClassNode.execute(this, value);
4349
}
4450

45-
@Specialization
46-
protected RubyClass logicalClassObject(RubyDynamicObject object) {
47-
return object.getLogicalClass();
48-
}
49-
5051
@InliningCutoff
5152
@Specialization(guards = "isForeignObject(object)")
5253
protected RubyClass logicalClassForeign(Object object,

src/main/java/org/truffleruby/language/objects/MetaClassNode.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.oracle.truffle.api.dsl.GenerateUncached;
2020
import com.oracle.truffle.api.dsl.Specialization;
2121

22+
// Specializations are order by their frequency on railsbench using --engine.SpecializationStatistics
2223
@GenerateUncached
2324
public abstract class MetaClassNode extends RubyBaseNode {
2425

@@ -33,32 +34,29 @@ public static MetaClassNode getUncached() {
3334

3435
public abstract RubyClass execute(Object value);
3536

36-
@Specialization(guards = "isPrimitiveOrImmutable(value)")
37-
protected RubyClass metaClassImmutable(Object value,
38-
@Cached ImmutableClassNode immutableClassNode) {
39-
return immutableClassNode.execute(this, value);
40-
}
41-
42-
// Cover all RubyDynamicObject cases with cached and uncached
43-
4437
@Specialization(
4538
guards = { "object == cachedObject", "metaClass.isSingleton" },
4639
limit = "getIdentityCacheContextLimit()")
47-
protected RubyClass singletonClassCached(RubyDynamicObject object,
40+
protected RubyClass singleton(RubyDynamicObject object,
4841
@Cached("object") RubyDynamicObject cachedObject,
4942
@Cached("object.getMetaClass()") RubyClass metaClass) {
5043
return metaClass;
5144
}
5245

53-
@Specialization(replaces = "singletonClassCached")
54-
protected RubyClass metaClassObject(RubyDynamicObject object) {
46+
@Specialization(replaces = "singleton")
47+
protected RubyClass object(RubyDynamicObject object) {
5548
return object.getMetaClass();
5649
}
5750

58-
// Foreign object
51+
@Specialization(guards = "isPrimitiveOrImmutable(value)")
52+
protected RubyClass immutable(Object value,
53+
@Cached ImmutableClassNode immutableClassNode) {
54+
return immutableClassNode.execute(this, value);
55+
}
56+
5957
@InliningCutoff
6058
@Specialization(guards = "isForeignObject(object)")
61-
protected RubyClass metaClassForeign(Object object,
59+
protected RubyClass foreign(Object object,
6260
@Cached ForeignClassNode foreignClassNode) {
6361
return foreignClassNode.execute(object);
6462
}

src/main/java/org/truffleruby/language/objects/SingletonClassNode.java

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.oracle.truffle.api.dsl.NodeChild;
2727
import com.oracle.truffle.api.dsl.Specialization;
2828

29+
// Specializations are order by their frequency on railsbench using --engine.SpecializationStatistics
2930
@GenerateUncached
3031
@NodeChild(value = "valueNode", type = RubyNode.class)
3132
public abstract class SingletonClassNode extends RubySourceNode {
@@ -40,6 +41,36 @@ public static SingletonClassNode create() {
4041

4142
public abstract RubyClass executeSingletonClass(Object value);
4243

44+
@Specialization(
45+
// no need to guard on the context, the rubyClass is context-specific
46+
guards = { "rubyClass == cachedClass", "cachedSingletonClass != null" },
47+
limit = "getIdentityCacheContextLimit()")
48+
protected RubyClass singletonClassClassCached(RubyClass rubyClass,
49+
@Cached("rubyClass") RubyClass cachedClass,
50+
@Cached("getSingletonClassOfClassOrNull(getContext(), cachedClass)") RubyClass cachedSingletonClass) {
51+
return cachedSingletonClass;
52+
}
53+
54+
@Specialization(replaces = "singletonClassClassCached")
55+
protected RubyClass singletonClassClassUncached(RubyClass rubyClass) {
56+
return ClassNodes.getSingletonClassOfClass(getContext(), rubyClass);
57+
}
58+
59+
@Specialization(
60+
// no need to guard on the context, the RubyDynamicObject is context-specific
61+
guards = { "object == cachedObject", "!isRubyClass(cachedObject)" },
62+
limit = "getIdentityCacheContextLimit()")
63+
protected RubyClass singletonClassInstanceCached(RubyDynamicObject object,
64+
@Cached("object") RubyDynamicObject cachedObject,
65+
@Cached("getSingletonClassForInstance(getContext(), object)") RubyClass cachedSingletonClass) {
66+
return cachedSingletonClass;
67+
}
68+
69+
@Specialization(guards = "!isRubyClass(object)", replaces = "singletonClassInstanceCached")
70+
protected RubyClass singletonClassInstanceUncached(RubyDynamicObject object) {
71+
return getSingletonClassForInstance(getContext(), object);
72+
}
73+
4374
@Specialization(guards = "value")
4475
protected RubyClass singletonClassTrue(boolean value) {
4576
return coreLibrary().trueClass;
@@ -75,36 +106,6 @@ protected RubyClass singletonClassImmutableObject(ImmutableRubyObject value) {
75106
return noSingletonClass();
76107
}
77108

78-
@Specialization(
79-
// no need to guard on the context, the rubyClass is context-specific
80-
guards = { "rubyClass == cachedClass", "cachedSingletonClass != null" },
81-
limit = "getIdentityCacheContextLimit()")
82-
protected RubyClass singletonClassClassCached(RubyClass rubyClass,
83-
@Cached("rubyClass") RubyClass cachedClass,
84-
@Cached("getSingletonClassOfClassOrNull(getContext(), cachedClass)") RubyClass cachedSingletonClass) {
85-
return cachedSingletonClass;
86-
}
87-
88-
@Specialization(replaces = "singletonClassClassCached")
89-
protected RubyClass singletonClassClassUncached(RubyClass rubyClass) {
90-
return ClassNodes.getSingletonClassOfClass(getContext(), rubyClass);
91-
}
92-
93-
@Specialization(
94-
// no need to guard on the context, the RubyDynamicObject is context-specific
95-
guards = { "object == cachedObject", "!isRubyClass(cachedObject)" },
96-
limit = "getIdentityCacheContextLimit()")
97-
protected RubyClass singletonClassInstanceCached(RubyDynamicObject object,
98-
@Cached("object") RubyDynamicObject cachedObject,
99-
@Cached("getSingletonClassForInstance(getContext(), object)") RubyClass cachedSingletonClass) {
100-
return cachedSingletonClass;
101-
}
102-
103-
@Specialization(guards = "!isRubyClass(object)", replaces = "singletonClassInstanceCached")
104-
protected RubyClass singletonClassInstanceUncached(RubyDynamicObject object) {
105-
return getSingletonClassForInstance(getContext(), object);
106-
}
107-
108109
private RubyClass noSingletonClass() {
109110
throw new RaiseException(getContext(), coreExceptions().typeErrorCantDefineSingleton(this));
110111
}

0 commit comments

Comments
 (0)