Skip to content

Commit edc7f95

Browse files
committed
Split SameOrEqualNode to support DSL inlining
1 parent 220bd81 commit edc7f95

File tree

3 files changed

+78
-84
lines changed

3 files changed

+78
-84
lines changed

src/main/java/org/truffleruby/core/array/ArrayNodes.java

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,6 @@ protected RubyArray concatManyGeneral(RubyArray array, Object first, Object[] re
664664
@ImportStatic(ArrayGuards.class)
665665
public abstract static class DeleteNode extends CoreMethodArrayArgumentsNode {
666666

667-
@Child private SameOrEqualNode sameOrEqualNode = SameOrEqualNode.create();
668667
@Child private TypeNodes.CheckFrozenNode raiseIfFrozenNode;
669668

670669
@Specialization(
@@ -673,12 +672,13 @@ public abstract static class DeleteNode extends CoreMethodArrayArgumentsNode {
673672
protected Object delete(RubyArray array, Object value, Object maybeBlock,
674673
@Bind("array.getStore()") Object store,
675674
@CachedLibrary("store") ArrayStoreLibrary stores,
676-
@Cached @Shared IntValueProfile arraySizeProfile,
677-
@Cached @Shared LoopConditionProfile loopProfile,
675+
@Cached @Shared SameOrEqualNode sameOrEqualNode,
676+
@Cached @Shared InlinedIntValueProfile arraySizeProfile,
677+
@Cached @Shared InlinedLoopConditionProfile loopProfile,
678678
@Cached @Shared CallBlockNode yieldNode) {
679679

680680
return delete(array, value, maybeBlock, true, store, store, stores, stores, arraySizeProfile, loopProfile,
681-
yieldNode);
681+
yieldNode, sameOrEqualNode);
682682
}
683683

684684
@Specialization(
@@ -688,13 +688,14 @@ protected Object delete(RubyArray array, Object value, Object maybeBlock,
688688
@Bind("array.getStore()") Object store,
689689
@CachedLibrary("store") ArrayStoreLibrary stores,
690690
@CachedLibrary(limit = "1") ArrayStoreLibrary newStores,
691-
@Cached @Shared IntValueProfile arraySizeProfile,
692-
@Cached @Shared LoopConditionProfile loopProfile,
691+
@Cached @Shared SameOrEqualNode sameOrEqualNode,
692+
@Cached @Shared InlinedIntValueProfile arraySizeProfile,
693+
@Cached @Shared InlinedLoopConditionProfile loopProfile,
693694
@Cached @Shared CallBlockNode yieldNode) {
694695

695-
final Object newStore = stores.allocator(store).allocate(arraySizeProfile.profile(array.size));
696+
final Object newStore = stores.allocator(store).allocate(arraySizeProfile.profile(this, array.size));
696697
return delete(array, value, maybeBlock, false, store, newStore, stores, newStores, arraySizeProfile,
697-
loopProfile, yieldNode);
698+
loopProfile, yieldNode, sameOrEqualNode);
698699
}
699700

700701
private Object delete(RubyArray array, Object value, Object maybeBlock,
@@ -703,22 +704,23 @@ private Object delete(RubyArray array, Object value, Object maybeBlock,
703704
Object newStore,
704705
ArrayStoreLibrary oldStores,
705706
ArrayStoreLibrary newStores,
706-
IntValueProfile arraySizeProfile,
707-
LoopConditionProfile loopProfile,
708-
CallBlockNode yieldNode) {
707+
InlinedIntValueProfile arraySizeProfile,
708+
InlinedLoopConditionProfile loopProfile,
709+
CallBlockNode yieldNode,
710+
SameOrEqualNode sameOrEqualNode) {
709711

710712
assert !sameStores || (oldStore == newStore && oldStores == newStores);
711713

712-
final int size = arraySizeProfile.profile(array.size);
714+
final int size = arraySizeProfile.profile(this, array.size);
713715
Object found = nil;
714716

715717
int i = 0;
716718
int n = 0;
717719
try {
718-
while (loopProfile.inject(n < size)) {
720+
while (loopProfile.inject(this, n < size)) {
719721
final Object stored = oldStores.read(oldStore, n);
720722

721-
if (sameOrEqualNode.executeSameOrEqual(stored, value)) {
723+
if (sameOrEqualNode.execute(this, stored, value)) {
722724
checkFrozen(array);
723725
found = stored;
724726
n++;
@@ -731,7 +733,7 @@ private Object delete(RubyArray array, Object value, Object maybeBlock,
731733
TruffleSafepoint.poll(this);
732734
}
733735
} finally {
734-
profileAndReportLoopCount(loopProfile, n);
736+
profileAndReportLoopCount(this, loopProfile, n);
735737
}
736738

737739
if (i != n) {
@@ -865,45 +867,45 @@ public void accept(CallBlockNode yieldNode, RubyArray array, Object state, Objec
865867
@ImportStatic(ArrayGuards.class)
866868
public abstract static class EqualNode extends PrimitiveArrayArgumentsNode {
867869

868-
@Child private SameOrEqualNode sameOrEqualNode = SameOrEqualNode.create();
869-
870870
@Specialization(
871871
guards = { "stores.accepts(bStore)", "stores.isPrimitive(aStore)" },
872872
limit = "storageStrategyLimit()")
873-
protected boolean equalSamePrimitiveType(RubyArray a, RubyArray b,
873+
protected static boolean equalSamePrimitiveType(RubyArray a, RubyArray b,
874874
@Bind("a.getStore()") Object aStore,
875875
@Bind("b.getStore()") Object bStore,
876876
@CachedLibrary("aStore") ArrayStoreLibrary stores,
877-
@Cached ConditionProfile sameProfile,
878-
@Cached IntValueProfile arraySizeProfile,
879-
@Cached ConditionProfile sameSizeProfile,
880-
@Cached BranchProfile trueProfile,
881-
@Cached BranchProfile falseProfile,
882-
@Cached LoopConditionProfile loopProfile) {
877+
@Cached InlinedConditionProfile sameProfile,
878+
@Cached InlinedIntValueProfile arraySizeProfile,
879+
@Cached InlinedConditionProfile sameSizeProfile,
880+
@Cached InlinedBranchProfile trueProfile,
881+
@Cached InlinedBranchProfile falseProfile,
882+
@Cached InlinedLoopConditionProfile loopProfile,
883+
@Cached SameOrEqualNode sameOrEqualNode,
884+
@Bind("this") Node node) {
883885

884-
if (sameProfile.profile(a == b)) {
886+
if (sameProfile.profile(node, a == b)) {
885887
return true;
886888
}
887889

888-
final int size = arraySizeProfile.profile(a.size);
890+
final int size = arraySizeProfile.profile(node, a.size);
889891

890-
if (!sameSizeProfile.profile(size == b.size)) {
892+
if (!sameSizeProfile.profile(node, size == b.size)) {
891893
return false;
892894
}
893895

894896
int i = 0;
895897
try {
896-
for (; loopProfile.inject(i < size); i++) {
897-
if (!sameOrEqualNode.executeSameOrEqual(stores.read(aStore, i), stores.read(bStore, i))) {
898-
falseProfile.enter();
898+
for (; loopProfile.inject(node, i < size); i++) {
899+
if (!sameOrEqualNode.execute(node, stores.read(aStore, i), stores.read(bStore, i))) {
900+
falseProfile.enter(node);
899901
return false;
900902
}
901-
TruffleSafepoint.poll(this);
903+
TruffleSafepoint.poll(node);
902904
}
903905
} finally {
904-
profileAndReportLoopCount(loopProfile, i);
906+
profileAndReportLoopCount(node, loopProfile, i);
905907
}
906-
trueProfile.enter();
908+
trueProfile.enter(node);
907909
return true;
908910
}
909911

@@ -1091,27 +1093,27 @@ protected static long hash(VirtualFrame frame, RubyArray array,
10911093
@ReportPolymorphism
10921094
public abstract static class IncludeNode extends ArrayCoreMethodNode {
10931095

1094-
@Child private SameOrEqualNode sameOrEqualNode = SameOrEqualNode.create();
1095-
10961096
@Specialization(limit = "storageStrategyLimit()")
1097-
protected boolean include(RubyArray array, Object value,
1097+
protected static boolean include(RubyArray array, Object value,
10981098
@Bind("array.getStore()") Object store,
10991099
@CachedLibrary("store") ArrayStoreLibrary stores,
1100-
@Cached IntValueProfile arraySizeProfile,
1101-
@Cached LoopConditionProfile loopProfile) {
1100+
@Cached SameOrEqualNode sameOrEqualNode,
1101+
@Cached InlinedIntValueProfile arraySizeProfile,
1102+
@Cached InlinedLoopConditionProfile loopProfile,
1103+
@Bind("this") Node node) {
11021104

11031105
int n = 0;
11041106
try {
1105-
for (; loopProfile.inject(n < arraySizeProfile.profile(array.size)); n++) {
1107+
for (; loopProfile.inject(node, n < arraySizeProfile.profile(node, array.size)); n++) {
11061108
final Object stored = stores.read(store, n);
11071109

1108-
if (sameOrEqualNode.executeSameOrEqual(stored, value)) {
1110+
if (sameOrEqualNode.execute(node, stored, value)) {
11091111
return true;
11101112
}
1111-
TruffleSafepoint.poll(this);
1113+
TruffleSafepoint.poll(node);
11121114
}
11131115
} finally {
1114-
profileAndReportLoopCount(loopProfile, n);
1116+
profileAndReportLoopCount(node, loopProfile, n);
11151117
}
11161118

11171119
return false;

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

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
import org.truffleruby.core.hash.RubyHash;
7171
import org.truffleruby.core.hash.library.PackedHashStoreLibrary;
7272
import org.truffleruby.core.inlined.AlwaysInlinedMethodNode;
73-
import org.truffleruby.core.kernel.KernelNodesFactory.SameOrEqualNodeFactory;
7473
import org.truffleruby.core.klass.RubyClass;
7574
import org.truffleruby.core.method.MethodFilter;
7675
import org.truffleruby.core.method.RubyMethod;
@@ -116,6 +115,7 @@
116115
import org.truffleruby.language.dispatch.DispatchConfiguration;
117116
import org.truffleruby.language.dispatch.DispatchNode;
118117
import org.truffleruby.language.dispatch.InternalRespondToNode;
118+
import org.truffleruby.language.dispatch.LazyDispatchNode;
119119
import org.truffleruby.language.dispatch.RubyCallNode;
120120
import org.truffleruby.language.loader.EvalLoader;
121121
import org.truffleruby.language.globals.ReadGlobalVariableNodeGen;
@@ -177,53 +177,44 @@ public abstract class KernelNodes {
177177
/** Check if operands are the same object or call #==. Known as rb_equal() in MRI. The fact Kernel#=== uses this is
178178
* pure coincidence. */
179179
@Primitive(name = "same_or_equal?")
180-
public abstract static class SameOrEqualNode extends PrimitiveArrayArgumentsNode {
180+
public abstract static class SameOrEqualPrimitiveNode extends PrimitiveArrayArgumentsNode {
181181

182-
@Child private DispatchNode equalNode;
183-
@Child private BooleanCastNode booleanCastNode;
184-
185-
private final ConditionProfile sameProfile = ConditionProfile.create();
182+
@Specialization
183+
protected boolean doSameOrEqual(Object a, Object b,
184+
@Cached SameOrEqualNode sameOrEqualNode) {
185+
return sameOrEqualNode.execute(this, a, b);
186186

187-
public static SameOrEqualNode create() {
188-
return SameOrEqualNodeFactory.create(null);
189187
}
188+
}
190189

191-
public abstract boolean executeSameOrEqual(Object a, Object b);
190+
@GenerateCached(false)
191+
@GenerateInline
192+
public abstract static class SameOrEqualNode extends RubyBaseNode {
193+
194+
public abstract boolean execute(Node node, Object a, Object b);
192195

193196
@Specialization
194-
protected boolean sameOrEqual(Object a, Object b,
197+
protected static boolean sameOrEqual(Node node, Object a, Object b,
198+
@Cached LazyDispatchNode lazyEqualNode,
199+
@Cached BooleanCastNode booleanCastNode,
200+
@Cached InlinedConditionProfile sameProfile,
195201
@Cached ReferenceEqualNode referenceEqualNode) {
196-
if (sameProfile.profile(referenceEqualNode.execute(a, b))) {
202+
if (sameProfile.profile(node, referenceEqualNode.execute(a, b))) {
197203
return true;
198204
} else {
199-
return areEqual(a, b);
205+
final var equalNode = lazyEqualNode.get(node);
206+
return booleanCastNode.execute(equalNode.call(a, "==", b));
200207
}
201208
}
202-
203-
private boolean areEqual(Object left, Object right) {
204-
if (equalNode == null) {
205-
CompilerDirectives.transferToInterpreterAndInvalidate();
206-
equalNode = insert(DispatchNode.create());
207-
}
208-
209-
if (booleanCastNode == null) {
210-
CompilerDirectives.transferToInterpreterAndInvalidate();
211-
booleanCastNode = insert(BooleanCastNode.create());
212-
}
213-
214-
return booleanCastNode.execute(equalNode.call(left, "==", right));
215-
}
216-
217209
}
218210

219211
@CoreMethod(names = "===", required = 1)
220212
public abstract static class CaseCompareNode extends CoreMethodArrayArgumentsNode {
221213

222-
@Child private SameOrEqualNode sameOrEqualNode = SameOrEqualNode.create();
223-
224214
@Specialization
225-
protected boolean caseCmp(Object a, Object b) {
226-
return sameOrEqualNode.executeSameOrEqual(a, b);
215+
protected boolean caseCmp(Object a, Object b,
216+
@Cached SameOrEqualNode sameOrEqualNode) {
217+
return sameOrEqualNode.execute(this, a, b);
227218
}
228219

229220
}
@@ -345,11 +336,10 @@ protected static boolean loadFeature(Object featureString, Object expandedPathSt
345336
@CoreMethod(names = { "<=>" }, required = 1)
346337
public abstract static class CompareNode extends CoreMethodArrayArgumentsNode {
347338

348-
@Child private SameOrEqualNode sameOrEqualNode = SameOrEqualNode.create();
349-
350339
@Specialization
351-
protected Object compare(Object self, Object other) {
352-
if (sameOrEqualNode.executeSameOrEqual(self, other)) {
340+
protected Object compare(Object self, Object other,
341+
@Cached SameOrEqualNode sameOrEqualNode) {
342+
if (sameOrEqualNode.execute(this, self, other)) {
353343
return 0;
354344
} else {
355345
return nil;

src/main/java/org/truffleruby/core/regexp/TruffleRegexpNodes.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,18 +279,19 @@ public abstract static class RegexpUnionNode extends CoreMethodArrayArgumentsNod
279279
@Child StringAppendPrimitiveNode appendNode = StringAppendPrimitiveNode.create();
280280
@Child AsTruffleStringNode asTruffleStringNode = AsTruffleStringNode.create();
281281
@Child ToSNode toSNode = ToSNode.create();
282-
@Child DispatchNode copyNode = DispatchNode.create();
283-
@Child private SameOrEqualNode sameOrEqualNode = SameOrEqualNode.create();
284282
private final RubyStringLibrary rubyStringLibrary = RubyStringLibrary.create();
285283
private final RubyStringLibrary regexpStringLibrary = RubyStringLibrary.create();
286284

287285
@Specialization(
288-
guards = "argsMatch(frame, cachedArgs, args)",
286+
guards = "argsMatch(node, frame, cachedArgs, args, sameOrEqualNode)",
289287
limit = "getDefaultCacheLimit()")
290-
protected Object fastUnion(VirtualFrame frame, RubyString str, Object sep, Object[] args,
288+
protected static Object fastUnion(VirtualFrame frame, RubyString str, Object sep, Object[] args,
289+
@Cached DispatchNode copyNode,
290+
@Cached SameOrEqualNode sameOrEqualNode,
291291
@Cached(value = "args", dimensions = 1) Object[] cachedArgs,
292292
@Cached @Shared InlinedBranchProfile errorProfile,
293-
@Cached("buildUnion(str, sep, args, errorProfile)") RubyRegexp union) {
293+
@Cached("buildUnion(str, sep, args, errorProfile)") RubyRegexp union,
294+
@Bind("this") Node node) {
294295
return copyNode.call(union, "clone");
295296
}
296297

@@ -332,12 +333,13 @@ public Object string(Object obj) {
332333
}
333334

334335
@ExplodeLoop
335-
protected boolean argsMatch(VirtualFrame frame, Object[] cachedArgs, Object[] args) {
336+
protected static boolean argsMatch(Node node, VirtualFrame frame, Object[] cachedArgs, Object[] args,
337+
SameOrEqualNode sameOrEqualNode) {
336338
if (cachedArgs.length != args.length) {
337339
return false;
338340
} else {
339341
for (int i = 0; i < cachedArgs.length; i++) {
340-
if (!sameOrEqualNode.executeSameOrEqual(cachedArgs[i], args[i])) {
342+
if (!sameOrEqualNode.execute(node, cachedArgs[i], args[i])) {
341343
return false;
342344
}
343345
}

0 commit comments

Comments
 (0)