16
16
17
17
import java .util .Set ;
18
18
19
+ import com .oracle .truffle .api .CompilerAsserts ;
19
20
import com .oracle .truffle .api .CompilerDirectives ;
20
21
import org .truffleruby .RubyContext ;
21
22
import org .truffleruby .RubyLanguage ;
@@ -173,7 +174,7 @@ Object lookupOrDefault(Frame frame, RubyHash hash, Object key, PEBiFunction defa
173
174
@ Bind ("$node" ) Node node ) {
174
175
int keyHash = hashFunction .execute (key , hash .compareByIdentity );
175
176
176
- int indexPos = getIndexPosForKeyNode .execute (key , keyHash , hash .compareByIdentity , index , kvStore );
177
+ int indexPos = getIndexPosForKeyNode .execute (key , keyHash , hash .compareByIdentity , index , kvStore , false );
177
178
if (keyNotFound .profile (node , indexPos == KEY_NOT_FOUND )) {
178
179
return defaultNode .accept (frame , hash , key );
179
180
}
@@ -185,15 +186,15 @@ Object lookupOrDefault(Frame frame, RubyHash hash, Object key, PEBiFunction defa
185
186
@ ExportMessage
186
187
boolean set (RubyHash hash , Object key , Object value , boolean byIdentity ,
187
188
@ Cached @ Shared HashingNodes .ToHash hashFunction ,
188
- @ Cached GetInsertionIndexPosForKeyNode getInsertionIndexPosForKeyNode ,
189
+ @ Cached @ Shared GetIndexPosForKeyNode getIndexPosForKeyNode ,
189
190
@ Cached FreezeHashKeyIfNeededNode freezeKey ,
190
191
@ Cached @ Exclusive PropagateSharingNode propagateSharingForKey ,
191
192
@ Cached @ Exclusive PropagateSharingNode propagateSharingForVal ,
192
193
@ Cached SetKvAtNode setKv ,
193
194
@ Bind ("$node" ) Node node ) {
194
195
var frozenKey = freezeKey .executeFreezeIfNeeded (node , key , byIdentity );
195
196
int keyHash = hashFunction .execute (frozenKey , byIdentity );
196
- int indexPos = getInsertionIndexPosForKeyNode .execute (frozenKey , keyHash , byIdentity , index , kvStore );
197
+ int indexPos = getIndexPosForKeyNode .execute (frozenKey , keyHash , byIdentity , index , kvStore , true );
197
198
int keyPos = indexPosToKeyPos (index , indexPos ); // can be < 0 if inserting new key
198
199
199
200
propagateSharingForKey .execute (node , hash , frozenKey );
@@ -209,7 +210,7 @@ Object delete(RubyHash hash, Object key,
209
210
@ Cached @ Exclusive InlinedConditionProfile keyNotFound ,
210
211
@ Bind ("$node" ) Node node ) {
211
212
int keyHash = hashFunction .execute (key , hash .compareByIdentity );
212
- int indexPos = getIndexPosForKeyNode .execute (key , keyHash , hash .compareByIdentity , index , kvStore );
213
+ int indexPos = getIndexPosForKeyNode .execute (key , keyHash , hash .compareByIdentity , index , kvStore , false );
213
214
if (keyNotFound .profile (node , indexPos == KEY_NOT_FOUND )) {
214
215
return null ;
215
216
}
@@ -470,24 +471,27 @@ public void getAdjacentObjects(Set<Object> reachable) {
470
471
}
471
472
}
472
473
473
- /** Given a key and its hash, returns the index pos for this key's hashCode, or KEY_NOT_FOUND if not found. */
474
+ /** Given a key and its hash, returns the index pos where this key's hashCode is found. If not found, returns where
475
+ * it could be inserted if insert is true and KEY_NOT_FOUND otherwise. */
474
476
@ GenerateUncached
475
477
abstract static class GetIndexPosForKeyNode extends RubyBaseNode {
476
478
477
- public abstract int execute (Object key , int hash , boolean compareByIdentity , int [] index , Object [] kvStore );
479
+ public abstract int execute (Object key , int hash , boolean compareByIdentity , int [] index , Object [] kvStore ,
480
+ boolean insert );
478
481
479
482
@ Specialization
480
- int findIndexPos (Object key , int hash , boolean compareByIdentity , int [] index , Object [] kvStore ,
483
+ int findIndexPos (Object key , int hash , boolean compareByIdentity , int [] index , Object [] kvStore , boolean insert ,
481
484
@ Cached CompareHashKeysNode .AssumingEqualHashes compareHashKeysNode ,
482
485
@ Cached @ Exclusive InlinedConditionProfile unused ,
483
486
@ Cached @ Exclusive InlinedConditionProfile sameHash ,
484
487
@ Bind ("$node" ) Node node ) {
488
+ CompilerAsserts .partialEvaluationConstant (insert );
485
489
int startPos = indexPosFromHashCode (hash , index .length );
486
490
int indexPos = startPos ;
487
491
while (true ) {
488
492
int valuePos = indexPosToValuePos (index , indexPos );
489
493
if (unused .profile (node , valuePos == INDEX_SLOT_UNUSED )) {
490
- return KEY_NOT_FOUND ;
494
+ return insert ? indexPos : KEY_NOT_FOUND ;
491
495
} else if (sameHash .profile (node , index [indexPos ] == hash ) &&
492
496
compareHashKeysNode .execute (compareByIdentity , key , kvStore [valuePos - 1 ])) { // keyPos == valuePos - 1
493
497
return indexPos ;
@@ -498,38 +502,6 @@ int findIndexPos(Object key, int hash, boolean compareByIdentity, int[] index, O
498
502
}
499
503
}
500
504
501
- /** Given a key and its hash, returns the index pos where this key's hashCode is found or where it could be
502
- * inserted. */
503
- @ GenerateUncached
504
- abstract static class GetInsertionIndexPosForKeyNode extends RubyBaseNode {
505
-
506
- public abstract int execute (Object key , int hash , boolean compareByIdentity , int [] index , Object [] kvStore );
507
-
508
- @ Specialization
509
- int findIndexPos (Object key , int hash , boolean compareByIdentity , int [] index , Object [] kvStore ,
510
- @ Cached CompareHashKeysNode .AssumingEqualHashes compareHashKeysNode ,
511
- @ Cached @ Exclusive InlinedConditionProfile unused ,
512
- @ Cached @ Exclusive InlinedConditionProfile sameHash ,
513
- @ Bind ("$node" ) Node node ) {
514
- int startPos = indexPosFromHashCode (hash , index .length );
515
- int indexPos = startPos ;
516
- while (true ) {
517
- int valuePos = indexPosToValuePos (index , indexPos );
518
- if (unused .profile (node , valuePos == INDEX_SLOT_UNUSED )) {
519
- return indexPos ;
520
- } else {
521
- int keyPos = valuePos - 1 ;
522
- if (sameHash .profile (node , index [indexPos ] == hash ) &&
523
- compareHashKeysNode .execute (compareByIdentity , key , kvStore [keyPos ])) {
524
- return indexPos ;
525
- }
526
- }
527
- indexPos = incrementIndexPos (indexPos , index .length );
528
- assert indexPos != startPos ;
529
- }
530
- }
531
- }
532
-
533
505
@ GenerateUncached
534
506
abstract static class GetHashNextPosInIndexNode extends RubyBaseNode {
535
507
0 commit comments