Skip to content

Commit 0c4cfdb

Browse files
committed
DSL-inline CompactHashStore helper nodes and CompareHashKeysNode
1 parent 867d26e commit 0c4cfdb

File tree

7 files changed

+99
-91
lines changed

7 files changed

+99
-91
lines changed

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

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -909,46 +909,46 @@ Object equalNotArray(RubyArray a, Object b) {
909909
@ImportStatic(ArrayGuards.class)
910910
public abstract static class EqlNode extends PrimitiveArrayArgumentsNode {
911911

912-
@Child private SameOrEqlNode eqlNode = SameOrEqlNode.create();
913-
914912
@Specialization(
915913
guards = { "stores.accepts(bStore)", "stores.isPrimitive(aStore)" },
916914
limit = "storageStrategyLimit()")
917-
boolean eqlSamePrimitiveType(RubyArray a, RubyArray b,
915+
static boolean eqlSamePrimitiveType(RubyArray a, RubyArray b,
918916
@Bind("a.getStore()") Object aStore,
919917
@Bind("b.getStore()") Object bStore,
920918
@CachedLibrary("aStore") ArrayStoreLibrary stores,
921-
@Cached ConditionProfile sameProfile,
922-
@Cached IntValueProfile arraySizeProfile,
923-
@Cached ConditionProfile sameSizeProfile,
924-
@Cached BranchProfile trueProfile,
925-
@Cached BranchProfile falseProfile,
926-
@Cached LoopConditionProfile loopProfile) {
919+
@Cached SameOrEqlNode eqlNode,
920+
@Cached InlinedConditionProfile sameProfile,
921+
@Cached InlinedIntValueProfile arraySizeProfile,
922+
@Cached InlinedConditionProfile sameSizeProfile,
923+
@Cached InlinedBranchProfile trueProfile,
924+
@Cached InlinedBranchProfile falseProfile,
925+
@Cached InlinedLoopConditionProfile loopProfile,
926+
@Bind("$node") Node node) {
927927

928-
if (sameProfile.profile(a == b)) {
928+
if (sameProfile.profile(node, a == b)) {
929929
return true;
930930
}
931931

932-
final int size = arraySizeProfile.profile(a.size);
932+
final int size = arraySizeProfile.profile(node, a.size);
933933

934-
if (!sameSizeProfile.profile(size == b.size)) {
934+
if (!sameSizeProfile.profile(node, size == b.size)) {
935935
return false;
936936
}
937937

938938
int i = 0;
939939
try {
940-
for (; loopProfile.inject(i < size); i++) {
941-
if (!eqlNode.execute(stores.read(aStore, i), stores.read(bStore, i))) {
942-
falseProfile.enter();
940+
for (; loopProfile.inject(node, i < size); i++) {
941+
if (!eqlNode.execute(node, stores.read(aStore, i), stores.read(bStore, i))) {
942+
falseProfile.enter(node);
943943
return false;
944944
}
945-
TruffleSafepoint.poll(this);
945+
TruffleSafepoint.poll(node);
946946
}
947947
} finally {
948-
profileAndReportLoopCount(loopProfile, i);
948+
profileAndReportLoopCount(node, loopProfile, i);
949949
}
950950

951-
trueProfile.enter();
951+
trueProfile.enter(node);
952952
return true;
953953
}
954954

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

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

12+
import com.oracle.truffle.api.dsl.GenerateCached;
13+
import com.oracle.truffle.api.dsl.GenerateInline;
1214
import org.truffleruby.core.basicobject.ReferenceEqualNode;
1315
import org.truffleruby.core.kernel.KernelNodes.SameOrEqlNode;
1416
import org.truffleruby.language.RubyBaseNode;
@@ -18,14 +20,12 @@
1820
import com.oracle.truffle.api.dsl.Specialization;
1921
import com.oracle.truffle.api.nodes.Node;
2022

23+
@GenerateInline
24+
@GenerateCached(false)
2125
@GenerateUncached
2226
public abstract class CompareHashKeysNode extends RubyBaseNode {
2327

24-
public static CompareHashKeysNode getUncached() {
25-
return CompareHashKeysNodeGen.getUncached();
26-
}
27-
28-
public abstract boolean execute(boolean compareByIdentity, Object key, int hashed,
28+
public abstract boolean execute(Node node, boolean compareByIdentity, Object key, int hashed,
2929
Object otherKey, int otherHashed);
3030

3131
/** Checks if the two keys are the same object, which is used by both modes (by identity or not) of lookup. Enables
@@ -38,36 +38,35 @@ public static boolean referenceEqualKeys(Node node, ReferenceEqualNode refEqual,
3838
}
3939

4040
@Specialization(guards = "compareByIdentity")
41-
boolean refEquals(boolean compareByIdentity, Object key, int hashed, Object otherKey, int otherHashed,
41+
static boolean refEquals(
42+
Node node, boolean compareByIdentity, Object key, int hashed, Object otherKey, int otherHashed,
4243
@Cached ReferenceEqualNode refEqual) {
43-
return refEqual.execute(this, key, otherKey);
44+
return refEqual.execute(node, key, otherKey);
4445
}
4546

4647
@Specialization(guards = "!compareByIdentity")
47-
boolean same(boolean compareByIdentity, Object key, int hashed, Object otherKey, int otherHashed,
48+
static boolean same(Node node, boolean compareByIdentity, Object key, int hashed, Object otherKey, int otherHashed,
4849
@Cached SameOrEqlNode same) {
49-
return hashed == otherHashed && same.execute(key, otherKey);
50+
return hashed == otherHashed && same.execute(node, key, otherKey);
5051
}
5152

53+
@GenerateInline
54+
@GenerateCached(false)
5255
@GenerateUncached
5356
public abstract static class AssumingEqualHashes extends RubyBaseNode {
5457

55-
public static AssumingEqualHashes getUncached() {
56-
return CompareHashKeysNodeGen.AssumingEqualHashesNodeGen.getUncached();
57-
}
58-
59-
public abstract boolean execute(boolean compareByIdentity, Object key, Object otherKey);
58+
public abstract boolean execute(Node node, boolean compareByIdentity, Object key, Object otherKey);
6059

6160
@Specialization(guards = "compareByIdentity")
62-
boolean refEquals(boolean compareByIdentity, Object key, Object otherKey,
61+
static boolean refEquals(Node node, boolean compareByIdentity, Object key, Object otherKey,
6362
@Cached ReferenceEqualNode refEqual) {
64-
return refEqual.execute(this, key, otherKey);
63+
return refEqual.execute(node, key, otherKey);
6564
}
6665

6766
@Specialization(guards = "!compareByIdentity")
68-
boolean same(boolean compareByIdentity, Object key, Object otherKey,
67+
static boolean same(Node node, boolean compareByIdentity, Object key, Object otherKey,
6968
@Cached SameOrEqlNode same) {
70-
return same.execute(key, otherKey);
69+
return same.execute(node, key, otherKey);
7170
}
7271
}
7372
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,8 @@ HashLookupResult lookup(RubyHash hash, Entry[] entries, Object key,
558558
Entry previousEntry = null;
559559

560560
while (entry != null) {
561-
if (compareHashKeysNode.execute(compareByIdentity, key, hashed, entry.getKey(), entry.getHashed())) {
561+
if (compareHashKeysNode.execute(this, compareByIdentity, key, hashed, entry.getKey(),
562+
entry.getHashed())) {
562563
return new HashLookupResult(hashed, index, previousEntry, entry);
563564
}
564565

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

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import com.oracle.truffle.api.CompilerAsserts;
2020
import com.oracle.truffle.api.CompilerDirectives;
21+
import com.oracle.truffle.api.dsl.GenerateCached;
22+
import com.oracle.truffle.api.dsl.GenerateInline;
2123
import org.truffleruby.RubyContext;
2224
import org.truffleruby.RubyLanguage;
2325
import org.truffleruby.collections.PEBiFunction;
@@ -38,7 +40,6 @@
3840
import com.oracle.truffle.api.dsl.Cached;
3941
import com.oracle.truffle.api.dsl.Cached.Shared;
4042
import com.oracle.truffle.api.dsl.GenerateUncached;
41-
import com.oracle.truffle.api.dsl.ImportStatic;
4243
import com.oracle.truffle.api.dsl.Specialization;
4344
import com.oracle.truffle.api.frame.Frame;
4445
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -174,7 +175,7 @@ Object lookupOrDefault(Frame frame, RubyHash hash, Object key, PEBiFunction defa
174175
@Bind("$node") Node node) {
175176
int keyHash = hashFunction.execute(key, hash.compareByIdentity);
176177

177-
int indexPos = getIndexPosForKeyNode.execute(key, keyHash, hash.compareByIdentity, index, kvStore, false);
178+
int indexPos = getIndexPosForKeyNode.execute(node, key, keyHash, hash.compareByIdentity, index, kvStore, false);
178179
if (keyNotFound.profile(node, indexPos == KEY_NOT_FOUND)) {
179180
return defaultNode.accept(frame, hash, key);
180181
}
@@ -194,13 +195,13 @@ boolean set(RubyHash hash, Object key, Object value, boolean byIdentity,
194195
@Bind("$node") Node node) {
195196
var frozenKey = freezeKey.executeFreezeIfNeeded(node, key, byIdentity);
196197
int keyHash = hashFunction.execute(frozenKey, byIdentity);
197-
int indexPos = getIndexPosForKeyNode.execute(frozenKey, keyHash, byIdentity, index, kvStore, true);
198+
int indexPos = getIndexPosForKeyNode.execute(node, frozenKey, keyHash, byIdentity, index, kvStore, true);
198199
int keyPos = indexPosToKeyPos(index, indexPos); // can be < 0 if inserting new key
199200

200201
propagateSharingForKey.execute(node, hash, frozenKey);
201202
propagateSharingForVal.execute(node, hash, value);
202203

203-
return setKv.execute(hash, this, indexPos, keyPos, keyHash, frozenKey, value);
204+
return setKv.execute(node, hash, this, indexPos, keyPos, keyHash, frozenKey, value);
204205
}
205206

206207
@ExportMessage
@@ -210,7 +211,7 @@ Object delete(RubyHash hash, Object key,
210211
@Cached @Exclusive InlinedConditionProfile keyNotFound,
211212
@Bind("$node") Node node) {
212213
int keyHash = hashFunction.execute(key, hash.compareByIdentity);
213-
int indexPos = getIndexPosForKeyNode.execute(key, keyHash, hash.compareByIdentity, index, kvStore, false);
214+
int indexPos = getIndexPosForKeyNode.execute(node, key, keyHash, hash.compareByIdentity, index, kvStore, false);
214215
if (keyNotFound.profile(node, indexPos == KEY_NOT_FOUND)) {
215216
return null;
216217
}
@@ -235,7 +236,7 @@ Object deleteLast(RubyHash hash, Object key,
235236
}
236237

237238
int keyHash = hashFunction.execute(key, hash.compareByIdentity);
238-
int indexPos = getIndexPosFromKeyPosNode.execute(keyHash, keyPos, index);
239+
int indexPos = getIndexPosFromKeyPosNode.execute(node, keyHash, keyPos, index);
239240

240241
return deleteKvAndGetV(hash, indexPos, keyPos);
241242
}
@@ -251,7 +252,7 @@ RubyArray shift(RubyHash hash,
251252

252253
Object key = kvStore[keyPos];
253254
int keyHash = hashFunction.execute(key, hash.compareByIdentity);
254-
int indexPos = getIndexPosFromKeyPosNode.execute(keyHash, keyPos, index);
255+
int indexPos = getIndexPosFromKeyPosNode.execute(node, keyHash, keyPos, index);
255256
Object val = deleteKvAndGetV(hash, indexPos, keyPos);
256257

257258
return ArrayHelpers.createArray(RubyContext.get(node), RubyLanguage.get(node), new Object[]{ key, val });
@@ -477,27 +478,36 @@ public void getAdjacentObjects(Set<Object> reachable) {
477478

478479
/** Given a key and its hash, returns the index pos where this key's hashCode is found. If not found, returns where
479480
* it could be inserted if insert is true and KEY_NOT_FOUND otherwise. */
481+
@GenerateInline
482+
@GenerateCached(false)
480483
@GenerateUncached
481484
abstract static class GetIndexPosForKeyNode extends RubyBaseNode {
482485

483-
public abstract int execute(Object key, int hash, boolean compareByIdentity, int[] index, Object[] kvStore,
484-
boolean insert);
486+
public abstract int execute(Node node, Object key, int hash, boolean compareByIdentity, int[] index,
487+
Object[] kvStore, boolean insert);
485488

486489
@Specialization
487-
int findIndexPos(Object key, int hash, boolean compareByIdentity, int[] index, Object[] kvStore, boolean insert,
490+
static int findIndexPos(
491+
Node node,
492+
Object key,
493+
int hash,
494+
boolean compareByIdentity,
495+
int[] index,
496+
Object[] kvStore,
497+
boolean insert,
488498
@Cached CompareHashKeysNode.AssumingEqualHashes compareHashKeysNode,
489499
@Cached @Exclusive InlinedConditionProfile unused,
490-
@Cached @Exclusive InlinedConditionProfile sameHash,
491-
@Bind("$node") Node node) {
500+
@Cached @Exclusive InlinedConditionProfile sameHash) {
492501
CompilerAsserts.partialEvaluationConstant(insert);
502+
493503
int startPos = indexPosFromHashCode(hash, index.length);
494504
int indexPos = startPos;
495505
while (true) {
496506
int valuePos = indexPosToValuePos(index, indexPos);
497507
if (unused.profile(node, valuePos == INDEX_SLOT_UNUSED)) {
498508
return insert ? indexPos : KEY_NOT_FOUND;
499509
} else if (sameHash.profile(node, index[indexPos] == hash) &&
500-
compareHashKeysNode.execute(compareByIdentity, key, kvStore[valuePos - 1])) { // keyPos == valuePos - 1
510+
compareHashKeysNode.execute(node, compareByIdentity, key, kvStore[valuePos - 1])) { // keyPos == valuePos - 1
501511
return indexPos;
502512
}
503513
indexPos = incrementIndexPos(indexPos, index.length);
@@ -506,16 +516,17 @@ int findIndexPos(Object key, int hash, boolean compareByIdentity, int[] index, O
506516
}
507517
}
508518

519+
@GenerateInline
520+
@GenerateCached(false)
509521
@GenerateUncached
510522
abstract static class GetIndexPosFromKeyPosNode extends RubyBaseNode {
511523

512-
public abstract int execute(int hash, int keyPos, int[] index);
524+
public abstract int execute(Node node, int hash, int keyPos, int[] index);
513525

514526
@Specialization
515-
int findIndexPos(int hash, int keyPos, int[] index,
527+
static int findIndexPos(Node node, int hash, int keyPos, int[] index,
516528
@Cached @Exclusive InlinedConditionProfile unused,
517-
@Cached @Exclusive InlinedConditionProfile found,
518-
@Bind("$node") Node node) {
529+
@Cached @Exclusive InlinedConditionProfile found) {
519530
int valuePosToSearch = keyPos + 1;
520531
int startPos = indexPosFromHashCode(hash, index.length);
521532
int indexPos = startPos;
@@ -532,16 +543,18 @@ int findIndexPos(int hash, int keyPos, int[] index,
532543
}
533544
}
534545

546+
@GenerateInline
547+
@GenerateCached(false)
535548
@GenerateUncached
536-
@ImportStatic(CompactHashStore.class)
537549
abstract static class SetKvAtNode extends RubyBaseNode {
538550

539-
public abstract boolean execute(RubyHash hash, CompactHashStore store, int indexPos, int keyPos, int keyHash,
540-
Object key, Object value);
551+
public abstract boolean execute(Node node, RubyHash hash, CompactHashStore store, int indexPos, int keyPos,
552+
int keyHash, Object key, Object value);
541553

542554
// key already exist, very fast because there is no need to touch the index
543555
@Specialization(guards = "keyPos >= 0")
544-
boolean keyAlreadyExistsWithDifferentValue(
556+
static boolean keyAlreadyExistsWithDifferentValue(
557+
Node node,
545558
RubyHash hash,
546559
CompactHashStore store,
547560
int indexPos,
@@ -556,10 +569,16 @@ boolean keyAlreadyExistsWithDifferentValue(
556569
// setting a new key is more expensive
557570
@Specialization(guards = "keyPos < 0")
558571
static boolean keyDoesntExist(
559-
RubyHash hash, CompactHashStore store, int indexPos, int keyPos, int keyHash, Object key, Object value,
572+
Node node,
573+
RubyHash hash,
574+
CompactHashStore store,
575+
int indexPos,
576+
int keyPos,
577+
int keyHash,
578+
Object key,
579+
Object value,
560580
@Cached @Exclusive InlinedConditionProfile kvResizingIsNeeded,
561-
@Cached @Exclusive InlinedConditionProfile indexResizingIsNeeded,
562-
@Bind("$node") Node node) {
581+
@Cached @Exclusive InlinedConditionProfile indexResizingIsNeeded) {
563582
if (kvResizingIsNeeded.profile(node, store.kvStoreInsertionPos >= store.kvStore.length)) {
564583
resizeKvStore(store);
565584
}

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static boolean set(Object[] store, RubyHash hash, Object key, Object value, bool
219219
if (n < size) {
220220
final int otherHashed = getHashed(store, n);
221221
final Object otherKey = getKey(store, n);
222-
if (compareHashKeys.execute(byIdentity, key2, hashed, otherKey, otherHashed)) {
222+
if (compareHashKeys.execute(node, byIdentity, key2, hashed, otherKey, otherHashed)) {
223223
setValue(store, n, value);
224224
return false;
225225
}
@@ -248,7 +248,8 @@ static boolean set(Object[] store, RubyHash hash, Object key, Object value, bool
248248
@ExportMessage
249249
static Object delete(Object[] store, RubyHash hash, Object key,
250250
@Cached @Shared HashingNodes.ToHash hashNode,
251-
@Cached @Shared CompareHashKeysNode compareHashKeys) {
251+
@Cached @Shared CompareHashKeysNode compareHashKeys,
252+
@Bind("$node") Node node) {
252253

253254
assert verify(store, hash);
254255
final int hashed = hashNode.execute(key, hash.compareByIdentity);
@@ -259,7 +260,7 @@ static Object delete(Object[] store, RubyHash hash, Object key,
259260
final int otherHashed = getHashed(store, n);
260261
final Object otherKey = getKey(store, n);
261262

262-
if (compareHashKeys.execute(hash.compareByIdentity, key, hashed, otherKey, otherHashed)) {
263+
if (compareHashKeys.execute(node, hash.compareByIdentity, key, hashed, otherKey, otherHashed)) {
263264
final Object value = getValue(store, n);
264265
removeEntry(store, n);
265266
hash.size -= 1;
@@ -360,7 +361,8 @@ static RubyArray shift(Object[] store, RubyHash hash,
360361
@ExportMessage
361362
static void rehash(Object[] store, RubyHash hash,
362363
@Cached @Shared CompareHashKeysNode compareHashKeys,
363-
@Cached @Shared HashingNodes.ToHash hashNode) {
364+
@Cached @Shared HashingNodes.ToHash hashNode,
365+
@Bind("$node") Node node) {
364366

365367
assert verify(store, hash);
366368
int size = hash.size;
@@ -371,6 +373,7 @@ static void rehash(Object[] store, RubyHash hash,
371373

372374
for (int m = n - 1; m >= 0; m--) {
373375
if (getHashed(store, m) == newHash && compareHashKeys.execute(
376+
node,
374377
hash.compareByIdentity,
375378
key,
376379
newHash,
@@ -480,7 +483,7 @@ Object getPackedArray(Frame frame, RubyHash hash, Object key, int hashed, PEBiFu
480483
if (n < size) {
481484
final int otherHashed = getHashed(store, n);
482485
final Object otherKey = getKey(store, n);
483-
if (equalKeys(compareHashKeys, compareByIdentity, key, hashed, otherKey, otherHashed)) {
486+
if (compareHashKeys.execute(node, compareByIdentity, key, hashed, otherKey, otherHashed)) {
484487
return getValue(store, n);
485488
}
486489
}
@@ -489,11 +492,6 @@ Object getPackedArray(Frame frame, RubyHash hash, Object key, int hashed, PEBiFu
489492
notInHashProfile.enter(node);
490493
return defaultValueNode.accept(frame, hash, key);
491494
}
492-
493-
protected boolean equalKeys(CompareHashKeysNode compareHashKeys, boolean compareByIdentity, Object key,
494-
int hashed, Object otherKey, int otherHashed) {
495-
return compareHashKeys.execute(compareByIdentity, key, hashed, otherKey, otherHashed);
496-
}
497495
}
498496

499497
public abstract static class SmallHashLiteralNode extends HashLiteralNode {

0 commit comments

Comments
 (0)