@@ -3286,7 +3286,7 @@ && areIdentical(buffer, MAX_KEYS, sourceNode, count, count + 1))
32863286 * was constructed from for the contents of {@code buffer}.
32873287 * <p>
32883288 * For {@link FastBuilder} these are mostly the same, so they are fetched from a global cache and
3289- * resized accordingly, but for {@link AbstractUpdater } we maintain a buffer of sizes.
3289+ * resized accordingly, but for {@link Updater } we maintain a buffer of sizes.
32903290 */
32913291 int setDrainSizeMap (Object [] original , int keysInOriginal , Object [] branch , int keysInBranch )
32923292 {
@@ -3315,7 +3315,7 @@ int setDrainSizeMap(Object[] original, int keysInOriginal, Object[] branch, int
33153315 * was constructed from for the contents of {@code savedBuffer}.
33163316 * <p>
33173317 * For {@link FastBuilder} these are always the same size, so they are fetched from a global cache,
3318- * but for {@link AbstractUpdater } we maintain a buffer of sizes.
3318+ * but for {@link Updater } we maintain a buffer of sizes.
33193319 *
33203320 * @return the size of {@code branch}
33213321 */
@@ -3346,7 +3346,7 @@ int setOverflowSizeMap(Object[] branch, int keys)
33463346 * was constructed from the contents of both {@code savedBuffer} and {@code buffer}
33473347 * <p>
33483348 * For {@link FastBuilder} these are mostly the same size, so they are fetched from a global cache
3349- * and only the last items updated, but for {@link AbstractUpdater } we maintain a buffer of sizes.
3349+ * and only the last items updated, but for {@link Updater } we maintain a buffer of sizes.
33503350 */
33513351 void setRedistributedSizeMap (Object [] branch , int steal )
33523352 {
@@ -3485,11 +3485,60 @@ final LeafBuilder leaf()
34853485
34863486 /**
34873487 * Clear any references we might still retain, to avoid holding onto memory.
3488- * <p>
3489- * While this method is not strictly necessary, it exists to
3490- * ensure the implementing classes are aware they must handle it.
34913488 */
3492- abstract void reset ();
3489+ void reset ()
3490+ {
3491+ leaf ().count = 0 ;
3492+ clearLeafBuffer (leaf ().buffer );
3493+ if (leaf ().savedBuffer != null )
3494+ clearLeafBuffer (leaf ().savedBuffer );
3495+ leaf ().savedNextKey = null ;
3496+ BranchBuilder branch = leaf ().parent ;
3497+ while (branch != null && branch .inUse )
3498+ {
3499+ branch .count = 0 ;
3500+ branch .hasRightChild = false ;
3501+ clearBranchBuffer (branch .buffer );
3502+ if (branch .savedBuffer != null )
3503+ clearBranchBuffer (branch .savedBuffer );
3504+ branch .savedNextKey = null ;
3505+ branch .clearSourceNode ();
3506+ branch .inUse = false ;
3507+ branch = branch .parent ;
3508+ }
3509+ Invariants .require (branch == null || (branch .count == 0 && !branch .hasRightChild ));
3510+ }
3511+
3512+ /**
3513+ * Clear the contents of a leaf buffer, aborting once we encounter a null entry
3514+ * to save time on small trees
3515+ */
3516+ private void clearLeafBuffer (Object [] array )
3517+ {
3518+ if (array [0 ] == null )
3519+ return ;
3520+ // find first null entry; loop from beginning, to amortise cost over size of working set
3521+ int i = 1 ;
3522+ while (i < array .length && array [i ] != null )
3523+ ++i ;
3524+ Arrays .fill (array , 0 , i , null );
3525+ }
3526+
3527+ /**
3528+ * Clear the contents of a branch buffer, aborting once we encounter a null entry
3529+ * to save time on small trees
3530+ */
3531+ private void clearBranchBuffer (Object [] array )
3532+ {
3533+ if (array [0 ] == null && array [MAX_KEYS ] == null )
3534+ return ;
3535+ // find first null entry; loop from beginning, to amortise cost over size of working set
3536+ int i = 1 ;
3537+ while (i < MAX_KEYS && array [i ] != null )
3538+ ++i ;
3539+ Arrays .fill (array , 0 , i , null );
3540+ Arrays .fill (array , MAX_KEYS , MAX_KEYS + i + 1 , null );
3541+ }
34933542 }
34943543
34953544 /**
@@ -3544,14 +3593,7 @@ public void close()
35443593 @ Override
35453594 public void reset ()
35463595 {
3547- Arrays .fill (leaf ().buffer , null );
3548- leaf ().count = 0 ;
3549- BranchBuilder branch = leaf ().parent ;
3550- while (branch != null && branch .inUse )
3551- {
3552- branch .reset ();
3553- branch = branch .parent ;
3554- }
3596+ super .reset ();
35553597 }
35563598
35573599 public boolean validateEmpty ()
@@ -3580,62 +3622,6 @@ private static boolean hasOnlyNulls(Object[] buffer)
35803622 }
35813623 }
35823624
3583- private static abstract class AbstractUpdater extends AbstractFastBuilder implements AutoCloseable
3584- {
3585- void reset ()
3586- {
3587- assert leaf ().count == 0 ;
3588- clearLeafBuffer (leaf ().buffer );
3589- if (leaf ().savedBuffer != null )
3590- Arrays .fill (leaf ().savedBuffer , null );
3591-
3592- BranchBuilder branch = leaf ().parent ;
3593- while (branch != null && branch .inUse )
3594- {
3595- branch .count = 0 ;
3596- branch .hasRightChild = false ;
3597- clearBranchBuffer (branch .buffer );
3598- if (branch .savedBuffer != null && branch .savedBuffer [0 ] != null )
3599- Arrays .fill (branch .savedBuffer , null ); // by definition full, if non-empty
3600- branch .inUse = false ;
3601- branch = branch .parent ;
3602- }
3603- Invariants .require (branch == null || (branch .count == 0 && !branch .hasRightChild ));
3604- }
3605-
3606- /**
3607- * Clear the contents of a branch buffer, aborting once we encounter a null entry
3608- * to save time on small trees
3609- */
3610- private void clearLeafBuffer (Object [] array )
3611- {
3612- if (array [0 ] == null )
3613- return ;
3614- // find first null entry; loop from beginning, to amortise cost over size of working set
3615- int i = 1 ;
3616- while (i < array .length && array [i ] != null )
3617- ++i ;
3618- Arrays .fill (array , 0 , i , null );
3619- }
3620-
3621- /**
3622- * Clear the contents of a branch buffer, aborting once we encounter a null entry
3623- * to save time on small trees
3624- */
3625- private void clearBranchBuffer (Object [] array )
3626- {
3627- if (array [0 ] == null )
3628- return ;
3629-
3630- // find first null entry; loop from beginning, to amortise cost over size of working set
3631- int i = 1 ;
3632- while (i < MAX_KEYS && array [i ] != null )
3633- ++i ;
3634- Arrays .fill (array , 0 , i , null );
3635- Arrays .fill (array , MAX_KEYS , MAX_KEYS + i + 1 , null );
3636- }
3637- }
3638-
36393625 /**
36403626 * A pooled object for modifying an existing tree with a new (typically smaller) tree.
36413627 * <p>
@@ -3650,7 +3636,7 @@ private void clearBranchBuffer(Object[] array)
36503636 * Searches within both trees to accelerate the process of modification, instead of performing a simple
36513637 * iteration over the new tree.
36523638 */
3653- static class Updater <Compare , Existing extends Compare , Insert extends Compare > extends AbstractUpdater implements AutoCloseable
3639+ static class Updater <Compare , Existing extends Compare , Insert extends Compare > extends AbstractFastBuilder implements AutoCloseable
36543640 {
36553641 static final TinyThreadLocalPool <Updater > POOL = new TinyThreadLocalPool <>();
36563642 TinyThreadLocalPool .TinyPool pool ;
@@ -3869,7 +3855,7 @@ static int searchResultToComparison(int searchResult)
38693855 * <p>
38703856 * The approach taken here hopefully balances simplicity, garbage generation and execution time.
38713857 */
3872- static abstract class AbstractSeekingTransformer <I , O > extends AbstractUpdater implements AutoCloseable
3858+ static abstract class AbstractSeekingTransformer <I , O > extends AbstractFastBuilder implements AutoCloseable
38733859 {
38743860 /**
38753861 * An iterator over the tree we are updating
0 commit comments