Skip to content

Commit 35c1350

Browse files
committed
[Truffle] Make the bucket chain singly linked.
1 parent 18593e6 commit 35c1350

File tree

5 files changed

+29
-42
lines changed

5 files changed

+29
-42
lines changed

core/src/main/java/org/jruby/truffle/nodes/core/HashNodes.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -467,14 +467,10 @@ public Object delete(VirtualFrame frame, RubyHash hash, Object key) {
467467

468468
// Remove from the lookup chain
469469

470-
if (bucket.getPreviousInLookup() == null) {
470+
if (bucketSearchResult.getPreviousBucket() == null) {
471471
((Bucket[]) hash.getStore())[bucketSearchResult.getIndex()] = bucket.getNextInLookup();
472472
} else {
473-
bucket.getPreviousInLookup().setNextInLookup(bucket.getNextInLookup());
474-
}
475-
476-
if (bucket.getNextInLookup() != null) {
477-
bucket.getNextInLookup().setPreviousInLookup(bucket.getPreviousInLookup());
473+
bucketSearchResult.getPreviousBucket().setNextInLookup(bucket.getNextInLookup());
478474
}
479475

480476
hash.setSize(hash.getSize() - 1);

core/src/main/java/org/jruby/truffle/nodes/hash/FindBucketNode.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ public BucketSearchResult search(VirtualFrame frame, RubyHash hash, Object key)
4848
final int bucketIndex = (hashed & HashOperations.SIGN_BIT_MASK) % buckets.length;
4949
Bucket bucket = buckets[bucketIndex];
5050

51-
Bucket endOfLookupChain = null;
51+
Bucket previousBucket = null;
5252

5353
while (bucket != null) {
5454
if (eqlNode.call(frame, key, "eql?", null, bucket.getKey())) {
55-
return new BucketSearchResult(bucketIndex, bucket, bucket);
55+
return new BucketSearchResult(bucketIndex, previousBucket, bucket);
5656
}
5757

58-
endOfLookupChain = bucket;
58+
previousBucket = bucket;
5959
bucket = bucket.getNextInLookup();
6060
}
6161

62-
return new BucketSearchResult(bucketIndex, endOfLookupChain, null);
62+
return new BucketSearchResult(bucketIndex, previousBucket, null);
6363
}
6464

6565
@Override

core/src/main/java/org/jruby/truffle/runtime/hash/Bucket.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ public class Bucket {
1919
private Object key;
2020
private Object value;
2121

22-
private Bucket previousInLookup;
2322
private Bucket nextInLookup;
2423

2524
private Bucket previousInSequence;
@@ -46,14 +45,6 @@ public void setValue(Object value) {
4645
this.value = value;
4746
}
4847

49-
public Bucket getPreviousInLookup() {
50-
return previousInLookup;
51-
}
52-
53-
public void setPreviousInLookup(Bucket previousInLookup) {
54-
this.previousInLookup = previousInLookup;
55-
}
56-
5748
public Bucket getNextInLookup() {
5849
return nextInLookup;
5950
}

core/src/main/java/org/jruby/truffle/runtime/hash/BucketSearchResult.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,37 @@
1010
package org.jruby.truffle.runtime.hash;
1111

1212
/**
13-
* The result of looking for a bucket (a {@link Bucket}) in a Ruby hash. We get the last bucket in the lookup chain for
14-
* this index, the bucket that was found, and the index that was used. There are three possible outcomes for a search.
13+
* The result of looking for a bucket (a {@link Bucket}) in a Ruby hash. We get the previous bucket in the lookup chain
14+
* for this index until the bucket was found, the bucket that was found, and the index that was used. There are three
15+
* possible outcomes for a search.
1516
* <ul>
1617
* <li>There is nothing at that index, in which case the bucket and last bucket in the chain will be
1718
* {@code null}</li>
18-
* <li>There were buckets at that index, but none for our key, in which case the bucket will be null, but the last
19-
* bucket will the last bucket in the chain at that index, presumably where we will want to insert your new
20-
* bucket</li>
21-
* <li>A bucket was found for our key, in which case the bucket and the last bucket in the chain will be the
22-
* same</li>
19+
* <li>There were buckets at that index, but none for our key, in which case the bucket will be null, but the
20+
* previous bucket will be the last bucket in the chain at that index, presumably where we will want to insert our
21+
* new bucket</li>
22+
* <li>A bucket was found for our key, in which case the bucket will be the one correspond to the key, and the
23+
* previous bucket will be the one in the bucket chain before that one</li>
2324
* </ul>
2425
*/
2526
public class BucketSearchResult {
2627

27-
private final Bucket endOfLookupChain;
28+
private final Bucket previousBucket;
2829
private final Bucket bucket;
2930
private final int index;
3031

31-
public BucketSearchResult(int index, Bucket endOfLookupChain, Bucket bucket) {
32+
public BucketSearchResult(int index, Bucket previousBucket, Bucket bucket) {
3233
this.index = index;
33-
this.endOfLookupChain = endOfLookupChain;
34+
this.previousBucket = previousBucket;
3435
this.bucket = bucket;
3536
}
3637

3738
public int getIndex() {
3839
return index;
3940
}
4041

41-
public Bucket getEndOfLookupChain() {
42-
return endOfLookupChain;
42+
public Bucket getPreviousBucket() {
43+
return previousBucket;
4344
}
4445

4546
public Bucket getBucket() {

core/src/main/java/org/jruby/truffle/runtime/hash/HashOperations.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,26 +139,32 @@ public static BucketSearchResult verySlowFindBucket(RubyHash hash, Object key) {
139139
final int bucketIndex = (hashed & SIGN_BIT_MASK) % buckets.length;
140140
Bucket bucket = buckets[bucketIndex];
141141

142-
Bucket endOfLookupChain = null;
142+
Bucket previousBucket = null;
143143

144144
while (bucket != null) {
145145
// TODO: cast
146146

147147
if ((boolean) DebugOperations.send(hash.getContext(), key, "eql?", null, bucket.getKey())) {
148-
return new BucketSearchResult(bucketIndex, bucket, bucket);
148+
return new BucketSearchResult(bucketIndex, previousBucket, bucket);
149149
}
150150

151-
endOfLookupChain = bucket;
151+
previousBucket = bucket;
152152
bucket = bucket.getNextInLookup();
153153
}
154154

155-
return new BucketSearchResult(bucketIndex, endOfLookupChain, null);
155+
return new BucketSearchResult(bucketIndex, previousBucket, null);
156156
}
157157

158158
public static void setAtBucket(RubyHash hash, BucketSearchResult bucketSearchResult, Object key, Object value) {
159159
if (bucketSearchResult.getBucket() == null) {
160160
final Bucket bucket = new Bucket(key, value);
161161

162+
if (bucketSearchResult.getPreviousBucket() == null) {
163+
((Bucket[]) hash.getStore())[bucketSearchResult.getIndex()] = bucket;
164+
} else {
165+
bucketSearchResult.getPreviousBucket().setNextInLookup(bucket);
166+
}
167+
162168
if (hash.getFirstInSequence() == null) {
163169
hash.setFirstInSequence(bucket);
164170
hash.setLastInSequence(bucket);
@@ -167,13 +173,6 @@ public static void setAtBucket(RubyHash hash, BucketSearchResult bucketSearchRes
167173
bucket.setPreviousInSequence(hash.getLastInSequence());
168174
hash.setLastInSequence(bucket);
169175
}
170-
171-
if (bucketSearchResult.getEndOfLookupChain() == null) {
172-
((Bucket[]) hash.getStore())[bucketSearchResult.getIndex()] = bucket;
173-
} else {
174-
bucketSearchResult.getEndOfLookupChain().setNextInLookup(bucket);
175-
bucket.setPreviousInLookup(bucketSearchResult.getEndOfLookupChain());
176-
}
177176
} else {
178177
final Bucket bucket = bucketSearchResult.getBucket();
179178

0 commit comments

Comments
 (0)