Skip to content

Commit 9de3ec8

Browse files
committed
[GR-17457] Refactor ReferenceEqualNode
PullRequest: truffleruby/3851
2 parents 0f8092e + b6a5d10 commit 9de3ec8

13 files changed

+120
-113
lines changed

src/main/java/org/truffleruby/core/VMPrimitiveNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
import org.truffleruby.annotations.Primitive;
5656
import org.truffleruby.builtins.PrimitiveArrayArgumentsNode;
5757
import org.truffleruby.core.array.RubyArray;
58-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
58+
import org.truffleruby.core.basicobject.ReferenceEqualNode;
5959
import org.truffleruby.core.cast.NameToJavaStringNode;
6060
import org.truffleruby.core.cast.ToRubyIntegerNode;
6161
import org.truffleruby.core.encoding.Encodings;
@@ -118,7 +118,7 @@ protected Object doCatch(Object tag, RubyProc block,
118118
return yieldNode.yield(block, tag);
119119
} catch (ThrowException e) {
120120
catchProfile.enter(this);
121-
if (matchProfile.profile(this, referenceEqualNode.executeReferenceEqual(e.getTag(), tag))) {
121+
if (matchProfile.profile(this, referenceEqualNode.execute(e.getTag(), tag))) {
122122
return e.getValue();
123123
} else {
124124
throw e;

src/main/java/org/truffleruby/core/basicobject/BasicObjectNodes.java

Lines changed: 4 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.truffleruby.annotations.Split;
2626
import org.truffleruby.builtins.CoreMethodArrayArgumentsNode;
2727
import org.truffleruby.core.basicobject.BasicObjectNodesFactory.InstanceExecNodeFactory;
28-
import org.truffleruby.core.basicobject.BasicObjectNodesFactory.ReferenceEqualNodeFactory;
2928
import org.truffleruby.core.cast.BooleanCastNode;
3029
import org.truffleruby.core.cast.NameToJavaStringNode;
3130
import org.truffleruby.core.cast.ToIntNode;
@@ -48,7 +47,6 @@
4847
import org.truffleruby.language.NotProvided;
4948
import org.truffleruby.language.RubyBaseNode;
5049
import org.truffleruby.language.RubyDynamicObject;
51-
import org.truffleruby.language.RubyGuards;
5250
import org.truffleruby.language.RubyNode;
5351
import org.truffleruby.language.RubySourceNode;
5452
import org.truffleruby.language.arguments.ArgumentsDescriptor;
@@ -123,93 +121,15 @@ protected boolean equal(VirtualFrame frame, Object a, Object b) {
123121
/** This node is not trivial because primitives must be compared by value and never by identity. Also, this node
124122
* must consider (byte) n and (short) n and (int) n and (long) n equal, as well as (float) n and (double) n. So even
125123
* if a and b have different classes they might still be equal if they are primitives. */
126-
@GenerateUncached
127124
@GenerateNodeFactory
128125
@CoreMethod(names = { "equal?", "==" }, required = 1)
129-
@NodeChild(value = "argumentNodes", type = RubyNode[].class)
130-
public abstract static class ReferenceEqualNode extends RubySourceNode {
131-
132-
@NeverDefault
133-
public static ReferenceEqualNode create() {
134-
return ReferenceEqualNodeFactory.create(null);
135-
}
136-
137-
public static ReferenceEqualNode create(RubyNode[] argumentNodes) {
138-
return ReferenceEqualNodeFactory.create(argumentNodes);
139-
}
140-
141-
public static ReferenceEqualNode getUncached() {
142-
return ReferenceEqualNodeFactory.getUncached();
143-
}
126+
public abstract static class BasicObjectEqualNode extends CoreMethodArrayArgumentsNode {
144127

145-
public abstract boolean executeReferenceEqual(Object a, Object b);
146-
147-
abstract RubyNode[] getArgumentNodes();
148128

149129
@Specialization
150-
protected boolean equal(boolean a, boolean b) {
151-
return a == b;
152-
}
153-
154-
@Specialization
155-
protected boolean equal(int a, int b) {
156-
return a == b;
157-
}
158-
159-
@Specialization
160-
protected boolean equal(long a, long b) {
161-
return a == b;
162-
}
163-
164-
@Specialization
165-
protected boolean equal(double a, double b) {
166-
return Double.doubleToRawLongBits(a) == Double.doubleToRawLongBits(b);
167-
}
168-
169-
@Specialization(guards = { "isNonPrimitiveRubyObject(a)", "isNonPrimitiveRubyObject(b)" })
170-
protected boolean equalRubyObjects(Object a, Object b) {
171-
return a == b;
172-
}
173-
174-
@Specialization(guards = { "isNonPrimitiveRubyObject(a)", "isPrimitive(b)" })
175-
protected boolean rubyObjectPrimitive(Object a, Object b) {
176-
return false;
177-
}
178-
179-
@Specialization(guards = { "isPrimitive(a)", "isNonPrimitiveRubyObject(b)" })
180-
protected boolean primitiveRubyObject(Object a, Object b) {
181-
return false;
182-
}
183-
184-
@Specialization(guards = { "isPrimitive(a)", "isPrimitive(b)", "!comparablePrimitives(a, b)" })
185-
protected boolean nonComparablePrimitives(Object a, Object b) {
186-
return false;
187-
}
188-
189-
@Specialization(guards = "isForeignObject(a) || isForeignObject(b)", limit = "getInteropCacheLimit()")
190-
protected boolean equalForeign(Object a, Object b,
191-
@CachedLibrary("a") InteropLibrary lhsInterop,
192-
@CachedLibrary("b") InteropLibrary rhsInterop) {
193-
if (lhsInterop.hasIdentity(a)) {
194-
return lhsInterop.isIdentical(a, b, rhsInterop);
195-
} else {
196-
return a == b;
197-
}
198-
}
199-
200-
protected static boolean isNonPrimitiveRubyObject(Object object) {
201-
return object instanceof RubyDynamicObject || object instanceof ImmutableRubyObject;
202-
}
203-
204-
protected static boolean comparablePrimitives(Object a, Object b) {
205-
return (a instanceof Boolean && b instanceof Boolean) ||
206-
(RubyGuards.isImplicitLong(a) && RubyGuards.isImplicitLong(b)) ||
207-
(RubyGuards.isDouble(a) && RubyGuards.isDouble(b));
208-
}
209-
210-
@Override
211-
public RubyNode cloneUninitialized() {
212-
return create(cloneUninitialized(getArgumentNodes())).copyFlags(this);
130+
protected boolean equal(Object a, Object b,
131+
@Cached ReferenceEqualNode referenceEqualNode) {
132+
return referenceEqualNode.execute(a, b);
213133
}
214134
}
215135

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.core.basicobject;
11+
12+
import com.oracle.truffle.api.dsl.GenerateUncached;
13+
import com.oracle.truffle.api.dsl.Specialization;
14+
import com.oracle.truffle.api.interop.InteropLibrary;
15+
import com.oracle.truffle.api.library.CachedLibrary;
16+
import org.truffleruby.language.ImmutableRubyObject;
17+
import org.truffleruby.language.RubyBaseNode;
18+
import org.truffleruby.language.RubyDynamicObject;
19+
import org.truffleruby.language.RubyGuards;
20+
21+
@GenerateUncached
22+
public abstract class ReferenceEqualNode extends RubyBaseNode {
23+
24+
public abstract boolean execute(Object a, Object b);
25+
26+
@Specialization
27+
protected boolean equal(boolean a, boolean b) {
28+
return a == b;
29+
}
30+
31+
@Specialization
32+
protected boolean equal(int a, int b) {
33+
return a == b;
34+
}
35+
36+
@Specialization
37+
protected boolean equal(long a, long b) {
38+
return a == b;
39+
}
40+
41+
@Specialization
42+
protected boolean equal(double a, double b) {
43+
return Double.doubleToRawLongBits(a) == Double.doubleToRawLongBits(b);
44+
}
45+
46+
@Specialization(guards = { "isNonPrimitiveRubyObject(a)", "isNonPrimitiveRubyObject(b)" })
47+
protected boolean equalRubyObjects(Object a, Object b) {
48+
return a == b;
49+
}
50+
51+
@Specialization(guards = { "isNonPrimitiveRubyObject(a)", "isPrimitive(b)" })
52+
protected boolean rubyObjectPrimitive(Object a, Object b) {
53+
return false;
54+
}
55+
56+
@Specialization(guards = { "isPrimitive(a)", "isNonPrimitiveRubyObject(b)" })
57+
protected boolean primitiveRubyObject(Object a, Object b) {
58+
return false;
59+
}
60+
61+
@Specialization(guards = { "isPrimitive(a)", "isPrimitive(b)", "!comparablePrimitives(a, b)" })
62+
protected boolean nonComparablePrimitives(Object a, Object b) {
63+
return false;
64+
}
65+
66+
@Specialization(guards = "isForeignObject(a) || isForeignObject(b)", limit = "getInteropCacheLimit()")
67+
protected boolean equalForeign(Object a, Object b,
68+
@CachedLibrary("a") InteropLibrary lhsInterop,
69+
@CachedLibrary("b") InteropLibrary rhsInterop) {
70+
if (lhsInterop.hasIdentity(a)) {
71+
return lhsInterop.isIdentical(a, b, rhsInterop);
72+
} else {
73+
return a == b;
74+
}
75+
}
76+
77+
protected static boolean comparablePrimitives(Object a, Object b) {
78+
return (a instanceof Boolean && b instanceof Boolean) ||
79+
(RubyGuards.isImplicitLong(a) && RubyGuards.isImplicitLong(b)) ||
80+
(RubyGuards.isDouble(a) && RubyGuards.isDouble(b));
81+
}
82+
83+
84+
protected static boolean isNonPrimitiveRubyObject(Object object) {
85+
return object instanceof RubyDynamicObject || object instanceof ImmutableRubyObject;
86+
}
87+
}

src/main/java/org/truffleruby/core/hash/CompareByRubyIdentityWrapper.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
package org.truffleruby.core.hash;
1111

12-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
12+
import org.truffleruby.core.basicobject.ReferenceEqualNodeGen;
1313
import org.truffleruby.core.hash.HashingNodes.ToHashByIdentity;
1414

1515
/** Wraps a value so that it will compared and hashed according to Ruby identity semantics. These semantics differ from
@@ -31,8 +31,8 @@ public int hashCode() {
3131
@Override
3232
public boolean equals(Object obj) {
3333
return obj instanceof CompareByRubyIdentityWrapper &&
34-
ReferenceEqualNode
34+
ReferenceEqualNodeGen
3535
.getUncached()
36-
.executeReferenceEqual(value, ((CompareByRubyIdentityWrapper) obj).value);
36+
.execute(value, ((CompareByRubyIdentityWrapper) obj).value);
3737
}
3838
}

src/main/java/org/truffleruby/core/hash/CompareHashKeysNode.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import com.oracle.truffle.api.dsl.Cached;
1313
import com.oracle.truffle.api.dsl.GenerateUncached;
1414
import com.oracle.truffle.api.dsl.Specialization;
15-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
15+
import org.truffleruby.core.basicobject.ReferenceEqualNode;
1616
import org.truffleruby.core.kernel.KernelNodes.SameOrEqlNode;
1717
import org.truffleruby.language.RubyBaseNode;
1818

@@ -31,14 +31,14 @@ public abstract boolean execute(boolean compareByIdentity, Object key, int hashe
3131
public static boolean referenceEqualKeys(ReferenceEqualNode refEqual, boolean compareByIdentity, Object key,
3232
int hashed, Object otherKey, int otherHashed) {
3333
return compareByIdentity
34-
? refEqual.executeReferenceEqual(key, otherKey)
35-
: hashed == otherHashed && refEqual.executeReferenceEqual(key, otherKey);
34+
? refEqual.execute(key, otherKey)
35+
: hashed == otherHashed && refEqual.execute(key, otherKey);
3636
}
3737

3838
@Specialization(guards = "compareByIdentity")
3939
protected boolean refEquals(boolean compareByIdentity, Object key, int hashed, Object otherKey, int otherHashed,
4040
@Cached ReferenceEqualNode refEqual) {
41-
return refEqual.executeReferenceEqual(key, otherKey);
41+
return refEqual.execute(key, otherKey);
4242
}
4343

4444
@Specialization(guards = "!compareByIdentity")

src/main/java/org/truffleruby/core/hash/library/PackedHashStoreLibrary.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import org.truffleruby.collections.PEBiFunction;
3737
import org.truffleruby.core.array.ArrayHelpers;
3838
import org.truffleruby.core.array.RubyArray;
39-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
39+
import org.truffleruby.core.basicobject.ReferenceEqualNode;
4040
import org.truffleruby.core.cast.BooleanCastNode;
4141
import org.truffleruby.core.hash.CompareHashKeysNode;
4242
import org.truffleruby.core.hash.Entry;

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
import org.truffleruby.core.array.ArrayUtils;
4444
import org.truffleruby.core.array.RubyArray;
4545
import org.truffleruby.core.basicobject.BasicObjectNodes.ObjectIDNode;
46-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
46+
import org.truffleruby.core.basicobject.ReferenceEqualNode;
4747
import org.truffleruby.core.binding.BindingNodes;
4848
import org.truffleruby.core.binding.RubyBinding;
4949
import org.truffleruby.core.cast.BooleanCastNode;
@@ -195,7 +195,7 @@ public static SameOrEqualNode create() {
195195
@Specialization
196196
protected boolean sameOrEqual(Object a, Object b,
197197
@Cached ReferenceEqualNode referenceEqualNode) {
198-
if (sameProfile.profile(referenceEqualNode.executeReferenceEqual(a, b))) {
198+
if (sameProfile.profile(referenceEqualNode.execute(a, b))) {
199199
return true;
200200
} else {
201201
return areEqual(a, b);
@@ -245,7 +245,7 @@ public static SameOrEqlNode getUncached() {
245245

246246
public abstract boolean execute(Object a, Object b);
247247

248-
@Specialization(guards = "referenceEqual.executeReferenceEqual(a, b)", limit = "1")
248+
@Specialization(guards = "referenceEqual.execute(a, b)", limit = "1")
249249
protected boolean refEqual(Object a, Object b,
250250
@Cached @Shared ReferenceEqualNode referenceEqual) {
251251
return true;
@@ -256,7 +256,7 @@ protected boolean refEqualOrEql(Object a, Object b,
256256
@Cached @Shared ReferenceEqualNode referenceEqual,
257257
@Cached DispatchNode eql,
258258
@Cached BooleanCastNode booleanCast) {
259-
return referenceEqual.executeReferenceEqual(a, b) || booleanCast.execute(eql.call(a, "eql?", b));
259+
return referenceEqual.execute(a, b) || booleanCast.execute(eql.call(a, "eql?", b));
260260
}
261261
}
262262

@@ -936,14 +936,14 @@ protected int hashForeign(Object value,
936936
@CoreMethod(names = "initialize_copy", required = 1, alwaysInlined = true)
937937
public abstract static class InitializeCopyNode extends AlwaysInlinedMethodNode {
938938

939-
@Specialization(guards = "equalNode.executeReferenceEqual(self, from)", limit = "1")
939+
@Specialization(guards = "equalNode.execute(self, from)", limit = "1")
940940
protected Object initializeCopySame(Frame callerFrame, Object self, Object[] rubyArgs, RootCallTarget target,
941941
@Bind("getArgument(rubyArgs, 0)") Object from,
942942
@Cached @Shared ReferenceEqualNode equalNode) {
943943
return self;
944944
}
945945

946-
@Specialization(guards = "!equalNode.executeReferenceEqual(self, from)", limit = "1")
946+
@Specialization(guards = "!equalNode.execute(self, from)", limit = "1")
947947
protected Object initializeCopy(Frame callerFrame, Object self, Object[] rubyArgs, RootCallTarget target,
948948
@Bind("getArgument(rubyArgs, 0)") Object from,
949949
@Cached @Shared ReferenceEqualNode equalNode,

src/main/java/org/truffleruby/core/method/MethodNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import org.truffleruby.builtins.PrimitiveArrayArgumentsNode;
2020
import org.truffleruby.core.Hashing;
2121
import org.truffleruby.core.array.RubyArray;
22-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
22+
import org.truffleruby.core.basicobject.ReferenceEqualNode;
2323
import org.truffleruby.core.inlined.AlwaysInlinedMethodNode;
2424
import org.truffleruby.core.klass.RubyClass;
2525
import org.truffleruby.core.module.MethodLookupResult;
@@ -103,7 +103,7 @@ public abstract static class EqualNode extends CoreMethodArrayArgumentsNode {
103103
protected boolean equal(RubyMethod a, RubyMethod b,
104104
@Cached ReferenceEqualNode referenceEqualNode) {
105105
return referenceEqualNode
106-
.executeReferenceEqual(a.receiver, b.receiver) &&
106+
.execute(a.receiver, b.receiver) &&
107107
a.method.getDeclaringModule() == b.method.getDeclaringModule() &&
108108
MethodNodes.areInternalMethodEqual(a.method, b.method);
109109
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import org.truffleruby.annotations.Primitive;
2424
import org.truffleruby.builtins.PrimitiveArrayArgumentsNode;
2525
import org.truffleruby.core.array.RubyArray;
26-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
26+
import org.truffleruby.core.basicobject.ReferenceEqualNode;
2727
import org.truffleruby.core.cast.BooleanCastNode;
2828
import org.truffleruby.core.cast.ToIntNode;
2929
import org.truffleruby.core.cast.ToLongNode;
@@ -108,7 +108,7 @@ public abstract static class EqualPrimitiveNode extends PrimitiveArrayArgumentsN
108108
@Specialization
109109
protected boolean equal(Object a, Object b,
110110
@Cached ReferenceEqualNode referenceEqualNode) {
111-
return referenceEqualNode.executeReferenceEqual(a, b);
111+
return referenceEqualNode.execute(a, b);
112112
}
113113
}
114114

src/main/java/org/truffleruby/extra/AtomicReferenceNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import org.truffleruby.annotations.CoreMethod;
1616
import org.truffleruby.builtins.CoreMethodArrayArgumentsNode;
1717
import org.truffleruby.annotations.CoreModule;
18-
import org.truffleruby.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
18+
import org.truffleruby.core.basicobject.ReferenceEqualNode;
1919
import org.truffleruby.core.klass.RubyClass;
2020
import org.truffleruby.language.Nil;
2121
import org.truffleruby.language.NotProvided;
@@ -100,7 +100,7 @@ protected boolean compareAndSetPrimitive(RubyAtomicReference self, Object expect
100100
final Object currentValue = self.value.get();
101101

102102
if (RubyGuards.isPrimitive(currentValue) &&
103-
equalNode.executeReferenceEqual(expectedValue, currentValue)) {
103+
equalNode.execute(expectedValue, currentValue)) {
104104
if (self.value.compareAndSet(currentValue, newValue)) {
105105
return true;
106106
}

0 commit comments

Comments
 (0)