@@ -702,63 +702,78 @@ private boolean needsCompaction() {
702
702
return dummyCnt > quarterOfUsable ;
703
703
}
704
704
705
- public void remove (VirtualFrame frame , Object key , long keyHash , RemoveProfiles profiles ) {
706
- assert checkInternalState ();
707
- if (CompilerDirectives .injectBranchProbability (SLOWPATH_PROBABILITY , needsCompaction ())) {
708
- profiles .compactProfile .enter ();
709
- compact ();
710
- }
711
- // Note: CPython is not shrinking the capacity of the hash table on delete, we do the same
712
- int compactIndex = getIndex (keyHash );
713
- int index = indices [compactIndex ];
714
- if (profiles .foundNullKey .profile (index == EMPTY_INDEX )) {
715
- return ; // not found
705
+
706
+ @ GenerateUncached
707
+ public abstract static class RemoveNode extends Node {
708
+ public final void remove (ThreadState state , ObjectHashMap map , DictKey key ) {
709
+ execute (state , map , key .getValue (), key .getPythonHash ());
716
710
}
717
711
718
- int unwrappedIndex = unwrapIndex (index );
719
- if (profiles .foundEqKey .profile (index != DUMMY_INDEX && keysEqual (frame , unwrappedIndex , key , keyHash , profiles ))) {
720
- indices [compactIndex ] = DUMMY_INDEX ;
721
- setValue (unwrappedIndex , null );
722
- setKey (unwrappedIndex , null );
723
- size --;
724
- return ;
712
+ public final void remove (ThreadState state , ObjectHashMap map , Object key , long keyHash ) {
713
+ execute (state , map , key , keyHash );
725
714
}
726
715
727
- // collision: intentionally counted loop
728
- long perturb = keyHash ;
729
- int searchLimit = getBucketsCount () + PERTURB_SHIFTS_COUT ;
730
- int i = 0 ;
731
- try {
732
- for (; CompilerDirectives .injectBranchProbability (0 , i < searchLimit ); i ++) {
733
- perturb >>>= PERTURB_SHIFT ;
734
- compactIndex = nextIndex (compactIndex , perturb );
735
- index = indices [compactIndex ];
736
- if (profiles .collisionFoundNoValue .profile (index == EMPTY_INDEX )) {
737
- return ; // not found
738
- }
739
- unwrappedIndex = unwrapIndex (index );
740
- if (profiles .collisionFoundEqKey .profile (index != DUMMY_INDEX && keysEqual (frame , unwrappedIndex , key , keyHash , profiles ))) {
741
- indices [compactIndex ] = DUMMY_INDEX ;
742
- setValue (unwrappedIndex , null );
743
- setKey (unwrappedIndex , null );
744
- size --;
745
- return ;
746
- }
716
+ abstract void execute (ThreadState state , ObjectHashMap map , Object key , long keyHash );
717
+
718
+ // "public" for testing...
719
+ @ Specialization
720
+ public static void doRemove (ThreadState state , ObjectHashMap map , Object key , long keyHash ,
721
+ @ Cached ("createCountingProfile()" ) ConditionProfile foundNullKey ,
722
+ @ Cached ("createCountingProfile()" ) ConditionProfile foundEqKey ,
723
+ @ Cached ("createCountingProfile()" ) ConditionProfile collisionFoundNoValue ,
724
+ @ Cached ("createCountingProfile()" ) ConditionProfile collisionFoundEqKey ,
725
+ @ Cached BranchProfile compactProfile ,
726
+ @ Cached ConditionProfile hasState ,
727
+ @ Cached PyObjectRichCompareBool .EqNode eqNode ) {
728
+ assert map .checkInternalState ();
729
+ if (CompilerDirectives .injectBranchProbability (SLOWPATH_PROBABILITY , map .needsCompaction ())) {
730
+ compactProfile .enter ();
731
+ map .compact ();
732
+ }
733
+ // Note: CPython is not shrinking the capacity of the hash table on delete, we do the same
734
+ int compactIndex = map .getIndex (keyHash );
735
+ int index = map .indices [compactIndex ];
736
+ if (foundNullKey .profile (index == EMPTY_INDEX )) {
737
+ return ; // not found
747
738
}
748
- } finally {
749
- LoopNode .reportLoopCount (profiles , i );
750
- }
751
- // all values are dummies? Not possible, since we should have compacted the
752
- // hashes/keysAndValues arrays at the top
753
- throw CompilerDirectives .shouldNotReachHere ();
754
- }
755
739
756
- private boolean keysEqual (Frame frame , int index , Object key , long keyHash , GetProfiles profiles ) {
757
- return hashes [index ] == keyHash && profiles .eqNode .execute (frame , getKey (index ), key );
758
- }
740
+ int unwrappedIndex = unwrapIndex (index );
741
+ if (foundEqKey .profile (index != DUMMY_INDEX && map .keysEqual (state , unwrappedIndex , key , keyHash , eqNode , hasState ))) {
742
+ map .indices [compactIndex ] = DUMMY_INDEX ;
743
+ map .setValue (unwrappedIndex , null );
744
+ map .setKey (unwrappedIndex , null );
745
+ map .size --;
746
+ return ;
747
+ }
759
748
760
- private boolean keysEqual (Frame frame , int index , Object key , long keyHash , PyObjectRichCompareBool .EqNode eqNode ) {
761
- return hashes [index ] == keyHash && eqNode .execute (frame , getKey (index ), key );
749
+ // collision: intentionally counted loop
750
+ long perturb = keyHash ;
751
+ int searchLimit = map .getBucketsCount () + PERTURB_SHIFTS_COUT ;
752
+ int i = 0 ;
753
+ try {
754
+ for (; CompilerDirectives .injectBranchProbability (0 , i < searchLimit ); i ++) {
755
+ perturb >>>= PERTURB_SHIFT ;
756
+ compactIndex = map .nextIndex (compactIndex , perturb );
757
+ index = map .indices [compactIndex ];
758
+ if (collisionFoundNoValue .profile (index == EMPTY_INDEX )) {
759
+ return ; // not found
760
+ }
761
+ unwrappedIndex = unwrapIndex (index );
762
+ if (collisionFoundEqKey .profile (index != DUMMY_INDEX && map .keysEqual (state , unwrappedIndex , key , keyHash , eqNode , hasState ))) {
763
+ map .indices [compactIndex ] = DUMMY_INDEX ;
764
+ map .setValue (unwrappedIndex , null );
765
+ map .setKey (unwrappedIndex , null );
766
+ map .size --;
767
+ return ;
768
+ }
769
+ }
770
+ } finally {
771
+ LoopNode .reportLoopCount (eqNode , i );
772
+ }
773
+ // all values are dummies? Not possible, since we should have compacted the
774
+ // hashes/keysAndValues arrays at the top
775
+ throw CompilerDirectives .shouldNotReachHere ();
776
+ }
762
777
}
763
778
764
779
private boolean keysEqual (ThreadState state , int index , Object key , long keyHash , PyObjectRichCompareBool .EqNode eqNode , ConditionProfile hasState ) {
0 commit comments