From a2e8f3c7ce47c9f8904e6afe39cf4aa8ac340c46 Mon Sep 17 00:00:00 2001 From: Google Java Core Libraries Date: Wed, 5 Oct 2022 15:24:02 -0700 Subject: [PATCH] Optimize the memory footprint of `MapMakerInternalMap` entries by special-casing linked entries. The first entry in each bucket does not need a `next` field because it will only ever be the tail of the bucket's linked list. Because `MapMakerInternalMap` uses a load factor of 0.75, we can expect that most entries are tails, so long as the hash function is good. For the common use case of a weak interner with compressed OOPs, omitting the `next` field reduces the shallow heap of `WeakKeyDummyValueEntry` from 40 bytes to 32 bytes. RELNOTES=Memory optimizations for `Interner` and `MapMaker` PiperOrigin-RevId: 479157599 --- .../common/collect/MapMakerInternalMap.java | 295 +++++++++-------- .../common/collect/MapMakerInternalMap.java | 298 ++++++++++-------- 2 files changed, 332 insertions(+), 261 deletions(-) diff --git a/android/guava/src/com/google/common/collect/MapMakerInternalMap.java b/android/guava/src/com/google/common/collect/MapMakerInternalMap.java index 5572b94ac151..5bda50df6005 100644 --- a/android/guava/src/com/google/common/collect/MapMakerInternalMap.java +++ b/android/guava/src/com/google/common/collect/MapMakerInternalMap.java @@ -344,27 +344,26 @@ abstract static class AbstractStrongKeyEntry { final K key; final int hash; - @CheckForNull final E next; - AbstractStrongKeyEntry(K key, int hash, @CheckForNull E next) { + AbstractStrongKeyEntry(K key, int hash) { this.key = key; this.hash = hash; - this.next = next; } @Override - public K getKey() { - return this.key; + public final K getKey() { + return key; } @Override - public int getHash() { + public final int getHash() { return hash; } @Override + @CheckForNull public E getNext() { - return next; + return null; } } @@ -376,12 +375,6 @@ interface StrongValueEntry> interface WeakValueEntry> extends InternalEntry { /** Gets the weak value reference held by entry. */ WeakValueReference getValueReference(); - - /** - * Clears the weak value reference held by the entry. Should be used when the entry's value is - * overwritten. - */ - void clearValue(); } @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value @@ -391,30 +384,34 @@ WeakValueReference unsetWeakValueReference() { } /** Concrete implementation of {@link InternalEntry} for strong keys and strong values. */ - static final class StrongKeyStrongValueEntry + static class StrongKeyStrongValueEntry extends AbstractStrongKeyEntry> implements StrongValueEntry> { @CheckForNull private volatile V value = null; - StrongKeyStrongValueEntry(K key, int hash, @CheckForNull StrongKeyStrongValueEntry next) { - super(key, hash, next); + private StrongKeyStrongValueEntry(K key, int hash) { + super(key, hash); } @Override @CheckForNull - public V getValue() { + public final V getValue() { return value; } - void setValue(V value) { - this.value = value; - } + private static final class LinkedStrongKeyStrongValueEntry + extends StrongKeyStrongValueEntry { + private final StrongKeyStrongValueEntry next; + + LinkedStrongKeyStrongValueEntry(K key, int hash, StrongKeyStrongValueEntry next) { + super(key, hash); + this.next = next; + } - StrongKeyStrongValueEntry copy(StrongKeyStrongValueEntry newNext) { - StrongKeyStrongValueEntry newEntry = - new StrongKeyStrongValueEntry<>(this.key, this.hash, newNext); - newEntry.value = this.value; - return newEntry; + @Override + public StrongKeyStrongValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for strong keys and strong values. */ @@ -453,7 +450,10 @@ public StrongKeyStrongValueEntry copy( StrongKeyStrongValueSegment segment, StrongKeyStrongValueEntry entry, @CheckForNull StrongKeyStrongValueEntry newNext) { - return entry.copy(newNext); + StrongKeyStrongValueEntry newEntry = + newEntry(segment, entry.key, entry.hash, newNext); + newEntry.value = entry.value; + return newEntry; } @Override @@ -461,7 +461,7 @@ public void setValue( StrongKeyStrongValueSegment segment, StrongKeyStrongValueEntry entry, V value) { - entry.setValue(value); + entry.value = value; } @Override @@ -470,48 +470,47 @@ public StrongKeyStrongValueEntry newEntry( K key, int hash, @CheckForNull StrongKeyStrongValueEntry next) { - return new StrongKeyStrongValueEntry<>(key, hash, next); + return next == null + ? new StrongKeyStrongValueEntry<>(key, hash) + : new LinkedStrongKeyStrongValueEntry<>(key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for strong keys and weak values. */ - static final class StrongKeyWeakValueEntry + static class StrongKeyWeakValueEntry extends AbstractStrongKeyEntry> implements WeakValueEntry> { private volatile WeakValueReference> valueReference = unsetWeakValueReference(); - StrongKeyWeakValueEntry(K key, int hash, @CheckForNull StrongKeyWeakValueEntry next) { - super(key, hash, next); + private StrongKeyWeakValueEntry(K key, int hash) { + super(key, hash); } @Override - public V getValue() { + public final V getValue() { return valueReference.get(); } @Override - public void clearValue() { - valueReference.clear(); + public final WeakValueReference> getValueReference() { + return valueReference; } - void setValue(V value, ReferenceQueue queueForValues) { - WeakValueReference> previous = this.valueReference; - this.valueReference = new WeakValueReferenceImpl<>(queueForValues, value, this); - previous.clear(); - } + private static final class LinkedStrongKeyWeakValueEntry + extends StrongKeyWeakValueEntry { + private final StrongKeyWeakValueEntry next; - StrongKeyWeakValueEntry copy( - ReferenceQueue queueForValues, StrongKeyWeakValueEntry newNext) { - StrongKeyWeakValueEntry newEntry = new StrongKeyWeakValueEntry<>(key, hash, newNext); - newEntry.valueReference = valueReference.copyFor(queueForValues, newEntry); - return newEntry; - } + LinkedStrongKeyWeakValueEntry(K key, int hash, StrongKeyWeakValueEntry next) { + super(key, hash); + this.next = next; + } - @Override - public WeakValueReference> getValueReference() { - return valueReference; + @Override + public StrongKeyWeakValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for strong keys and weak values. */ @@ -545,6 +544,7 @@ public StrongKeyWeakValueSegment newSegment( } @Override + @CheckForNull public StrongKeyWeakValueEntry copy( StrongKeyWeakValueSegment segment, StrongKeyWeakValueEntry entry, @@ -552,13 +552,17 @@ public StrongKeyWeakValueEntry copy( if (Segment.isCollected(entry)) { return null; } - return entry.copy(segment.queueForValues, newNext); + StrongKeyWeakValueEntry newEntry = newEntry(segment, entry.key, entry.hash, newNext); + newEntry.valueReference = entry.valueReference.copyFor(segment.queueForValues, newEntry); + return newEntry; } @Override public void setValue( StrongKeyWeakValueSegment segment, StrongKeyWeakValueEntry entry, V value) { - entry.setValue(value, segment.queueForValues); + WeakValueReference> previous = entry.valueReference; + entry.valueReference = new WeakValueReferenceImpl<>(segment.queueForValues, value, entry); + previous.clear(); } @Override @@ -567,28 +571,40 @@ public StrongKeyWeakValueEntry newEntry( K key, int hash, @CheckForNull StrongKeyWeakValueEntry next) { - return new StrongKeyWeakValueEntry<>(key, hash, next); + return next == null + ? new StrongKeyWeakValueEntry<>(key, hash) + : new LinkedStrongKeyWeakValueEntry<>(key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for strong keys and {@link Dummy} values. */ - static final class StrongKeyDummyValueEntry + static class StrongKeyDummyValueEntry extends AbstractStrongKeyEntry> implements StrongValueEntry> { - StrongKeyDummyValueEntry(K key, int hash, @CheckForNull StrongKeyDummyValueEntry next) { - super(key, hash, next); + + private StrongKeyDummyValueEntry(K key, int hash) { + super(key, hash); } @Override - public Dummy getValue() { + public final Dummy getValue() { return Dummy.VALUE; } - void setValue(Dummy value) {} + private static final class LinkedStrongKeyDummyValueEntry + extends StrongKeyDummyValueEntry { + private final StrongKeyDummyValueEntry next; + + LinkedStrongKeyDummyValueEntry(K key, int hash, StrongKeyDummyValueEntry next) { + super(key, hash); + this.next = next; + } - StrongKeyDummyValueEntry copy(StrongKeyDummyValueEntry newNext) { - return new StrongKeyDummyValueEntry(this.key, this.hash, newNext); + @Override + public StrongKeyDummyValueEntry getNext() { + return next; + } } /** @@ -629,7 +645,7 @@ public StrongKeyDummyValueEntry copy( StrongKeyDummyValueSegment segment, StrongKeyDummyValueEntry entry, @CheckForNull StrongKeyDummyValueEntry newNext) { - return entry.copy(newNext); + return newEntry(segment, entry.key, entry.hash, newNext); } @Override @@ -642,7 +658,9 @@ public StrongKeyDummyValueEntry newEntry( K key, int hash, @CheckForNull StrongKeyDummyValueEntry next) { - return new StrongKeyDummyValueEntry(key, hash, next); + return next == null + ? new StrongKeyDummyValueEntry(key, hash) + : new LinkedStrongKeyDummyValueEntry<>(key, hash, next); } } } @@ -651,49 +669,56 @@ public StrongKeyDummyValueEntry newEntry( abstract static class AbstractWeakKeyEntry> extends WeakReference implements InternalEntry { final int hash; - @CheckForNull final E next; - AbstractWeakKeyEntry(ReferenceQueue queue, K key, int hash, @CheckForNull E next) { + AbstractWeakKeyEntry(ReferenceQueue queue, K key, int hash) { super(key, queue); this.hash = hash; - this.next = next; } @Override - public K getKey() { + public final K getKey() { return get(); } @Override - public int getHash() { + public final int getHash() { return hash; } @Override + @CheckForNull public E getNext() { - return next; + return null; } } /** Concrete implementation of {@link InternalEntry} for weak keys and {@link Dummy} values. */ - static final class WeakKeyDummyValueEntry + static class WeakKeyDummyValueEntry extends AbstractWeakKeyEntry> implements StrongValueEntry> { - WeakKeyDummyValueEntry( - ReferenceQueue queue, K key, int hash, @CheckForNull WeakKeyDummyValueEntry next) { - super(queue, key, hash, next); + + private WeakKeyDummyValueEntry(ReferenceQueue queue, K key, int hash) { + super(queue, key, hash); } @Override - public Dummy getValue() { + public final Dummy getValue() { return Dummy.VALUE; } - void setValue(Dummy value) {} + private static final class LinkedWeakKeyDummyValueEntry extends WeakKeyDummyValueEntry { + private final WeakKeyDummyValueEntry next; - WeakKeyDummyValueEntry copy( - ReferenceQueue queueForKeys, WeakKeyDummyValueEntry newNext) { - return new WeakKeyDummyValueEntry(queueForKeys, getKey(), this.hash, newNext); + private LinkedWeakKeyDummyValueEntry( + ReferenceQueue queue, K key, int hash, WeakKeyDummyValueEntry next) { + super(queue, key, hash); + this.next = next; + } + + @Override + public WeakKeyDummyValueEntry getNext() { + return next; + } } /** @@ -725,19 +750,21 @@ public WeakKeyDummyValueSegment newSegment( MapMakerInternalMap, WeakKeyDummyValueSegment> map, int initialCapacity, int maxSegmentSize) { - return new WeakKeyDummyValueSegment(map, initialCapacity, maxSegmentSize); + return new WeakKeyDummyValueSegment<>(map, initialCapacity, maxSegmentSize); } @Override + @CheckForNull public WeakKeyDummyValueEntry copy( WeakKeyDummyValueSegment segment, WeakKeyDummyValueEntry entry, @CheckForNull WeakKeyDummyValueEntry newNext) { - if (entry.getKey() == null) { + K key = entry.getKey(); + if (key == null) { // key collected return null; } - return entry.copy(segment.queueForKeys, newNext); + return newEntry(segment, key, entry.hash, newNext); } @Override @@ -750,41 +777,43 @@ public WeakKeyDummyValueEntry newEntry( K key, int hash, @CheckForNull WeakKeyDummyValueEntry next) { - return new WeakKeyDummyValueEntry(segment.queueForKeys, key, hash, next); + return next == null + ? new WeakKeyDummyValueEntry<>(segment.queueForKeys, key, hash) + : new LinkedWeakKeyDummyValueEntry<>(segment.queueForKeys, key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for weak keys and strong values. */ - static final class WeakKeyStrongValueEntry + static class WeakKeyStrongValueEntry extends AbstractWeakKeyEntry> implements StrongValueEntry> { @CheckForNull private volatile V value = null; - WeakKeyStrongValueEntry( - ReferenceQueue queue, - K key, - int hash, - @CheckForNull WeakKeyStrongValueEntry next) { - super(queue, key, hash, next); + private WeakKeyStrongValueEntry(ReferenceQueue queue, K key, int hash) { + super(queue, key, hash); } @Override @CheckForNull - public V getValue() { + public final V getValue() { return value; } - void setValue(V value) { - this.value = value; - } + private static final class LinkedWeakKeyStrongValueEntry + extends WeakKeyStrongValueEntry { + private final WeakKeyStrongValueEntry next; - WeakKeyStrongValueEntry copy( - ReferenceQueue queueForKeys, WeakKeyStrongValueEntry newNext) { - WeakKeyStrongValueEntry newEntry = - new WeakKeyStrongValueEntry<>(queueForKeys, getKey(), this.hash, newNext); - newEntry.setValue(value); - return newEntry; + private LinkedWeakKeyStrongValueEntry( + ReferenceQueue queue, K key, int hash, WeakKeyStrongValueEntry next) { + super(queue, key, hash); + this.next = next; + } + + @Override + public WeakKeyStrongValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for weak keys and strong values. */ @@ -818,21 +847,25 @@ public WeakKeyStrongValueSegment newSegment( } @Override + @CheckForNull public WeakKeyStrongValueEntry copy( WeakKeyStrongValueSegment segment, WeakKeyStrongValueEntry entry, @CheckForNull WeakKeyStrongValueEntry newNext) { - if (entry.getKey() == null) { + K key = entry.getKey(); + if (key == null) { // key collected return null; } - return entry.copy(segment.queueForKeys, newNext); + WeakKeyStrongValueEntry newEntry = newEntry(segment, key, entry.hash, newNext); + newEntry.value = entry.value; + return newEntry; } @Override public void setValue( WeakKeyStrongValueSegment segment, WeakKeyStrongValueEntry entry, V value) { - entry.setValue(value); + entry.value = value; } @Override @@ -841,52 +874,48 @@ public WeakKeyStrongValueEntry newEntry( K key, int hash, @CheckForNull WeakKeyStrongValueEntry next) { - return new WeakKeyStrongValueEntry<>(segment.queueForKeys, key, hash, next); + return next == null + ? new WeakKeyStrongValueEntry<>(segment.queueForKeys, key, hash) + : new LinkedWeakKeyStrongValueEntry<>(segment.queueForKeys, key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for weak keys and weak values. */ - static final class WeakKeyWeakValueEntry + static class WeakKeyWeakValueEntry extends AbstractWeakKeyEntry> implements WeakValueEntry> { private volatile WeakValueReference> valueReference = unsetWeakValueReference(); - WeakKeyWeakValueEntry( - ReferenceQueue queue, K key, int hash, @CheckForNull WeakKeyWeakValueEntry next) { - super(queue, key, hash, next); + WeakKeyWeakValueEntry(ReferenceQueue queue, K key, int hash) { + super(queue, key, hash); } @Override - public V getValue() { + public final V getValue() { return valueReference.get(); } - WeakKeyWeakValueEntry copy( - ReferenceQueue queueForKeys, - ReferenceQueue queueForValues, - WeakKeyWeakValueEntry newNext) { - WeakKeyWeakValueEntry newEntry = - new WeakKeyWeakValueEntry<>(queueForKeys, getKey(), this.hash, newNext); - newEntry.valueReference = valueReference.copyFor(queueForValues, newEntry); - return newEntry; - } - @Override - public void clearValue() { - valueReference.clear(); + public final WeakValueReference> getValueReference() { + return valueReference; } - void setValue(V value, ReferenceQueue queueForValues) { - WeakValueReference> previous = this.valueReference; - this.valueReference = new WeakValueReferenceImpl<>(queueForValues, value, this); - previous.clear(); - } + private static final class LinkedWeakKeyWeakValueEntry + extends WeakKeyWeakValueEntry { + private final WeakKeyWeakValueEntry next; - @Override - public WeakValueReference> getValueReference() { - return valueReference; + LinkedWeakKeyWeakValueEntry( + ReferenceQueue queue, K key, int hash, WeakKeyWeakValueEntry next) { + super(queue, key, hash); + this.next = next; + } + + @Override + public WeakKeyWeakValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for weak keys and weak values. */ @@ -919,24 +948,30 @@ public WeakKeyWeakValueSegment newSegment( } @Override + @CheckForNull public WeakKeyWeakValueEntry copy( WeakKeyWeakValueSegment segment, WeakKeyWeakValueEntry entry, @CheckForNull WeakKeyWeakValueEntry newNext) { - if (entry.getKey() == null) { + K key = entry.getKey(); + if (key == null) { // key collected return null; } if (Segment.isCollected(entry)) { return null; } - return entry.copy(segment.queueForKeys, segment.queueForValues, newNext); + WeakKeyWeakValueEntry newEntry = newEntry(segment, key, entry.hash, newNext); + newEntry.valueReference = entry.valueReference.copyFor(segment.queueForValues, newEntry); + return newEntry; } @Override public void setValue( WeakKeyWeakValueSegment segment, WeakKeyWeakValueEntry entry, V value) { - entry.setValue(value, segment.queueForValues); + WeakValueReference> previous = entry.valueReference; + entry.valueReference = new WeakValueReferenceImpl<>(segment.queueForValues, value, entry); + previous.clear(); } @Override @@ -945,7 +980,9 @@ public WeakKeyWeakValueEntry newEntry( K key, int hash, @CheckForNull WeakKeyWeakValueEntry next) { - return new WeakKeyWeakValueEntry<>(segment.queueForKeys, key, hash, next); + return next == null + ? new WeakKeyWeakValueEntry<>(segment.queueForKeys, key, hash) + : new LinkedWeakKeyWeakValueEntry<>(segment.queueForKeys, key, hash, next); } } } diff --git a/guava/src/com/google/common/collect/MapMakerInternalMap.java b/guava/src/com/google/common/collect/MapMakerInternalMap.java index e34ab170d09e..5eb763bd78c2 100644 --- a/guava/src/com/google/common/collect/MapMakerInternalMap.java +++ b/guava/src/com/google/common/collect/MapMakerInternalMap.java @@ -344,27 +344,25 @@ abstract static class AbstractStrongKeyEntry { final K key; final int hash; - final @Nullable E next; - AbstractStrongKeyEntry(K key, int hash, @Nullable E next) { + AbstractStrongKeyEntry(K key, int hash) { this.key = key; this.hash = hash; - this.next = next; } @Override - public K getKey() { - return this.key; + public final K getKey() { + return key; } @Override - public int getHash() { + public final int getHash() { return hash; } @Override - public E getNext() { - return next; + public @Nullable E getNext() { + return null; } } @@ -376,12 +374,6 @@ interface StrongValueEntry> interface WeakValueEntry> extends InternalEntry { /** Gets the weak value reference held by entry. */ WeakValueReference getValueReference(); - - /** - * Clears the weak value reference held by the entry. Should be used when the entry's value is - * overwritten. - */ - void clearValue(); } @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value @@ -391,29 +383,33 @@ WeakValueReference unsetWeakValueReference() { } /** Concrete implementation of {@link InternalEntry} for strong keys and strong values. */ - static final class StrongKeyStrongValueEntry + static class StrongKeyStrongValueEntry extends AbstractStrongKeyEntry> implements StrongValueEntry> { private volatile @Nullable V value = null; - StrongKeyStrongValueEntry(K key, int hash, @Nullable StrongKeyStrongValueEntry next) { - super(key, hash, next); + private StrongKeyStrongValueEntry(K key, int hash) { + super(key, hash); } @Override - public @Nullable V getValue() { + public final @Nullable V getValue() { return value; } - void setValue(V value) { - this.value = value; - } + private static final class LinkedStrongKeyStrongValueEntry + extends StrongKeyStrongValueEntry { + private final StrongKeyStrongValueEntry next; + + LinkedStrongKeyStrongValueEntry(K key, int hash, StrongKeyStrongValueEntry next) { + super(key, hash); + this.next = next; + } - StrongKeyStrongValueEntry copy(StrongKeyStrongValueEntry newNext) { - StrongKeyStrongValueEntry newEntry = - new StrongKeyStrongValueEntry<>(this.key, this.hash, newNext); - newEntry.value = this.value; - return newEntry; + @Override + public StrongKeyStrongValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for strong keys and strong values. */ @@ -452,7 +448,10 @@ public StrongKeyStrongValueEntry copy( StrongKeyStrongValueSegment segment, StrongKeyStrongValueEntry entry, @Nullable StrongKeyStrongValueEntry newNext) { - return entry.copy(newNext); + StrongKeyStrongValueEntry newEntry = + newEntry(segment, entry.key, entry.hash, newNext); + newEntry.value = entry.value; + return newEntry; } @Override @@ -460,7 +459,7 @@ public void setValue( StrongKeyStrongValueSegment segment, StrongKeyStrongValueEntry entry, V value) { - entry.setValue(value); + entry.value = value; } @Override @@ -469,48 +468,47 @@ public StrongKeyStrongValueEntry newEntry( K key, int hash, @Nullable StrongKeyStrongValueEntry next) { - return new StrongKeyStrongValueEntry<>(key, hash, next); + return next == null + ? new StrongKeyStrongValueEntry<>(key, hash) + : new LinkedStrongKeyStrongValueEntry<>(key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for strong keys and weak values. */ - static final class StrongKeyWeakValueEntry + static class StrongKeyWeakValueEntry extends AbstractStrongKeyEntry> implements WeakValueEntry> { private volatile WeakValueReference> valueReference = unsetWeakValueReference(); - StrongKeyWeakValueEntry(K key, int hash, @Nullable StrongKeyWeakValueEntry next) { - super(key, hash, next); + private StrongKeyWeakValueEntry(K key, int hash) { + super(key, hash); } @Override - public V getValue() { + public final V getValue() { return valueReference.get(); } @Override - public void clearValue() { - valueReference.clear(); + public final WeakValueReference> getValueReference() { + return valueReference; } - void setValue(V value, ReferenceQueue queueForValues) { - WeakValueReference> previous = this.valueReference; - this.valueReference = new WeakValueReferenceImpl<>(queueForValues, value, this); - previous.clear(); - } + private static final class LinkedStrongKeyWeakValueEntry + extends StrongKeyWeakValueEntry { + private final StrongKeyWeakValueEntry next; - StrongKeyWeakValueEntry copy( - ReferenceQueue queueForValues, StrongKeyWeakValueEntry newNext) { - StrongKeyWeakValueEntry newEntry = new StrongKeyWeakValueEntry<>(key, hash, newNext); - newEntry.valueReference = valueReference.copyFor(queueForValues, newEntry); - return newEntry; - } + LinkedStrongKeyWeakValueEntry(K key, int hash, StrongKeyWeakValueEntry next) { + super(key, hash); + this.next = next; + } - @Override - public WeakValueReference> getValueReference() { - return valueReference; + @Override + public StrongKeyWeakValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for strong keys and weak values. */ @@ -544,20 +542,24 @@ public StrongKeyWeakValueSegment newSegment( } @Override - public StrongKeyWeakValueEntry copy( + public @Nullable StrongKeyWeakValueEntry copy( StrongKeyWeakValueSegment segment, StrongKeyWeakValueEntry entry, @Nullable StrongKeyWeakValueEntry newNext) { if (Segment.isCollected(entry)) { return null; } - return entry.copy(segment.queueForValues, newNext); + StrongKeyWeakValueEntry newEntry = newEntry(segment, entry.key, entry.hash, newNext); + newEntry.valueReference = entry.valueReference.copyFor(segment.queueForValues, newEntry); + return newEntry; } @Override public void setValue( StrongKeyWeakValueSegment segment, StrongKeyWeakValueEntry entry, V value) { - entry.setValue(value, segment.queueForValues); + WeakValueReference> previous = entry.valueReference; + entry.valueReference = new WeakValueReferenceImpl<>(segment.queueForValues, value, entry); + previous.clear(); } @Override @@ -566,28 +568,40 @@ public StrongKeyWeakValueEntry newEntry( K key, int hash, @Nullable StrongKeyWeakValueEntry next) { - return new StrongKeyWeakValueEntry<>(key, hash, next); + return next == null + ? new StrongKeyWeakValueEntry<>(key, hash) + : new LinkedStrongKeyWeakValueEntry<>(key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for strong keys and {@link Dummy} values. */ - static final class StrongKeyDummyValueEntry + static class StrongKeyDummyValueEntry extends AbstractStrongKeyEntry> implements StrongValueEntry> { - StrongKeyDummyValueEntry(K key, int hash, @Nullable StrongKeyDummyValueEntry next) { - super(key, hash, next); + + private StrongKeyDummyValueEntry(K key, int hash) { + super(key, hash); } @Override - public Dummy getValue() { + public final Dummy getValue() { return Dummy.VALUE; } - void setValue(Dummy value) {} + private static final class LinkedStrongKeyDummyValueEntry + extends StrongKeyDummyValueEntry { + private final StrongKeyDummyValueEntry next; + + LinkedStrongKeyDummyValueEntry(K key, int hash, StrongKeyDummyValueEntry next) { + super(key, hash); + this.next = next; + } - StrongKeyDummyValueEntry copy(StrongKeyDummyValueEntry newNext) { - return new StrongKeyDummyValueEntry(this.key, this.hash, newNext); + @Override + public StrongKeyDummyValueEntry getNext() { + return next; + } } /** @@ -628,7 +642,7 @@ public StrongKeyDummyValueEntry copy( StrongKeyDummyValueSegment segment, StrongKeyDummyValueEntry entry, @Nullable StrongKeyDummyValueEntry newNext) { - return entry.copy(newNext); + return newEntry(segment, entry.key, entry.hash, newNext); } @Override @@ -641,7 +655,9 @@ public StrongKeyDummyValueEntry newEntry( K key, int hash, @Nullable StrongKeyDummyValueEntry next) { - return new StrongKeyDummyValueEntry(key, hash, next); + return next == null + ? new StrongKeyDummyValueEntry(key, hash) + : new LinkedStrongKeyDummyValueEntry<>(key, hash, next); } } } @@ -650,49 +666,55 @@ public StrongKeyDummyValueEntry newEntry( abstract static class AbstractWeakKeyEntry> extends WeakReference implements InternalEntry { final int hash; - final @Nullable E next; - AbstractWeakKeyEntry(ReferenceQueue queue, K key, int hash, @Nullable E next) { + AbstractWeakKeyEntry(ReferenceQueue queue, K key, int hash) { super(key, queue); this.hash = hash; - this.next = next; } @Override - public K getKey() { + public final K getKey() { return get(); } @Override - public int getHash() { + public final int getHash() { return hash; } @Override - public E getNext() { - return next; + public @Nullable E getNext() { + return null; } } /** Concrete implementation of {@link InternalEntry} for weak keys and {@link Dummy} values. */ - static final class WeakKeyDummyValueEntry + static class WeakKeyDummyValueEntry extends AbstractWeakKeyEntry> implements StrongValueEntry> { - WeakKeyDummyValueEntry( - ReferenceQueue queue, K key, int hash, @Nullable WeakKeyDummyValueEntry next) { - super(queue, key, hash, next); + + private WeakKeyDummyValueEntry(ReferenceQueue queue, K key, int hash) { + super(queue, key, hash); } @Override - public Dummy getValue() { + public final Dummy getValue() { return Dummy.VALUE; } - void setValue(Dummy value) {} + private static final class LinkedWeakKeyDummyValueEntry extends WeakKeyDummyValueEntry { + private final WeakKeyDummyValueEntry next; + + private LinkedWeakKeyDummyValueEntry( + ReferenceQueue queue, K key, int hash, WeakKeyDummyValueEntry next) { + super(queue, key, hash); + this.next = next; + } - WeakKeyDummyValueEntry copy( - ReferenceQueue queueForKeys, WeakKeyDummyValueEntry newNext) { - return new WeakKeyDummyValueEntry(queueForKeys, getKey(), this.hash, newNext); + @Override + public WeakKeyDummyValueEntry getNext() { + return next; + } } /** @@ -724,19 +746,20 @@ public WeakKeyDummyValueSegment newSegment( MapMakerInternalMap, WeakKeyDummyValueSegment> map, int initialCapacity, int maxSegmentSize) { - return new WeakKeyDummyValueSegment(map, initialCapacity, maxSegmentSize); + return new WeakKeyDummyValueSegment<>(map, initialCapacity, maxSegmentSize); } @Override - public WeakKeyDummyValueEntry copy( + public @Nullable WeakKeyDummyValueEntry copy( WeakKeyDummyValueSegment segment, WeakKeyDummyValueEntry entry, @Nullable WeakKeyDummyValueEntry newNext) { - if (entry.getKey() == null) { + K key = entry.getKey(); + if (key == null) { // key collected return null; } - return entry.copy(segment.queueForKeys, newNext); + return newEntry(segment, key, entry.hash, newNext); } @Override @@ -749,37 +772,42 @@ public WeakKeyDummyValueEntry newEntry( K key, int hash, @Nullable WeakKeyDummyValueEntry next) { - return new WeakKeyDummyValueEntry(segment.queueForKeys, key, hash, next); + return next == null + ? new WeakKeyDummyValueEntry<>(segment.queueForKeys, key, hash) + : new LinkedWeakKeyDummyValueEntry<>(segment.queueForKeys, key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for weak keys and strong values. */ - static final class WeakKeyStrongValueEntry + static class WeakKeyStrongValueEntry extends AbstractWeakKeyEntry> implements StrongValueEntry> { private volatile @Nullable V value = null; - WeakKeyStrongValueEntry( - ReferenceQueue queue, K key, int hash, @Nullable WeakKeyStrongValueEntry next) { - super(queue, key, hash, next); + private WeakKeyStrongValueEntry(ReferenceQueue queue, K key, int hash) { + super(queue, key, hash); } @Override - public @Nullable V getValue() { + public final @Nullable V getValue() { return value; } - void setValue(V value) { - this.value = value; - } + private static final class LinkedWeakKeyStrongValueEntry + extends WeakKeyStrongValueEntry { + private final WeakKeyStrongValueEntry next; + + private LinkedWeakKeyStrongValueEntry( + ReferenceQueue queue, K key, int hash, WeakKeyStrongValueEntry next) { + super(queue, key, hash); + this.next = next; + } - WeakKeyStrongValueEntry copy( - ReferenceQueue queueForKeys, WeakKeyStrongValueEntry newNext) { - WeakKeyStrongValueEntry newEntry = - new WeakKeyStrongValueEntry<>(queueForKeys, getKey(), this.hash, newNext); - newEntry.setValue(value); - return newEntry; + @Override + public WeakKeyStrongValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for weak keys and strong values. */ @@ -813,21 +841,24 @@ public WeakKeyStrongValueSegment newSegment( } @Override - public WeakKeyStrongValueEntry copy( + public @Nullable WeakKeyStrongValueEntry copy( WeakKeyStrongValueSegment segment, WeakKeyStrongValueEntry entry, @Nullable WeakKeyStrongValueEntry newNext) { - if (entry.getKey() == null) { + K key = entry.getKey(); + if (key == null) { // key collected return null; } - return entry.copy(segment.queueForKeys, newNext); + WeakKeyStrongValueEntry newEntry = newEntry(segment, key, entry.hash, newNext); + newEntry.value = entry.value; + return newEntry; } @Override public void setValue( WeakKeyStrongValueSegment segment, WeakKeyStrongValueEntry entry, V value) { - entry.setValue(value); + entry.value = value; } @Override @@ -836,52 +867,48 @@ public WeakKeyStrongValueEntry newEntry( K key, int hash, @Nullable WeakKeyStrongValueEntry next) { - return new WeakKeyStrongValueEntry<>(segment.queueForKeys, key, hash, next); + return next == null + ? new WeakKeyStrongValueEntry<>(segment.queueForKeys, key, hash) + : new LinkedWeakKeyStrongValueEntry<>(segment.queueForKeys, key, hash, next); } } } /** Concrete implementation of {@link InternalEntry} for weak keys and weak values. */ - static final class WeakKeyWeakValueEntry + static class WeakKeyWeakValueEntry extends AbstractWeakKeyEntry> implements WeakValueEntry> { private volatile WeakValueReference> valueReference = unsetWeakValueReference(); - WeakKeyWeakValueEntry( - ReferenceQueue queue, K key, int hash, @Nullable WeakKeyWeakValueEntry next) { - super(queue, key, hash, next); + WeakKeyWeakValueEntry(ReferenceQueue queue, K key, int hash) { + super(queue, key, hash); } @Override - public V getValue() { + public final V getValue() { return valueReference.get(); } - WeakKeyWeakValueEntry copy( - ReferenceQueue queueForKeys, - ReferenceQueue queueForValues, - WeakKeyWeakValueEntry newNext) { - WeakKeyWeakValueEntry newEntry = - new WeakKeyWeakValueEntry<>(queueForKeys, getKey(), this.hash, newNext); - newEntry.valueReference = valueReference.copyFor(queueForValues, newEntry); - return newEntry; - } - @Override - public void clearValue() { - valueReference.clear(); + public final WeakValueReference> getValueReference() { + return valueReference; } - void setValue(V value, ReferenceQueue queueForValues) { - WeakValueReference> previous = this.valueReference; - this.valueReference = new WeakValueReferenceImpl<>(queueForValues, value, this); - previous.clear(); - } + private static final class LinkedWeakKeyWeakValueEntry + extends WeakKeyWeakValueEntry { + private final WeakKeyWeakValueEntry next; - @Override - public WeakValueReference> getValueReference() { - return valueReference; + LinkedWeakKeyWeakValueEntry( + ReferenceQueue queue, K key, int hash, WeakKeyWeakValueEntry next) { + super(queue, key, hash); + this.next = next; + } + + @Override + public WeakKeyWeakValueEntry getNext() { + return next; + } } /** Concrete implementation of {@link InternalEntryHelper} for weak keys and weak values. */ @@ -914,24 +941,29 @@ public WeakKeyWeakValueSegment newSegment( } @Override - public WeakKeyWeakValueEntry copy( + public @Nullable WeakKeyWeakValueEntry copy( WeakKeyWeakValueSegment segment, WeakKeyWeakValueEntry entry, @Nullable WeakKeyWeakValueEntry newNext) { - if (entry.getKey() == null) { + K key = entry.getKey(); + if (key == null) { // key collected return null; } if (Segment.isCollected(entry)) { return null; } - return entry.copy(segment.queueForKeys, segment.queueForValues, newNext); + WeakKeyWeakValueEntry newEntry = newEntry(segment, key, entry.hash, newNext); + newEntry.valueReference = entry.valueReference.copyFor(segment.queueForValues, newEntry); + return newEntry; } @Override public void setValue( WeakKeyWeakValueSegment segment, WeakKeyWeakValueEntry entry, V value) { - entry.setValue(value, segment.queueForValues); + WeakValueReference> previous = entry.valueReference; + entry.valueReference = new WeakValueReferenceImpl<>(segment.queueForValues, value, entry); + previous.clear(); } @Override @@ -940,7 +972,9 @@ public WeakKeyWeakValueEntry newEntry( K key, int hash, @Nullable WeakKeyWeakValueEntry next) { - return new WeakKeyWeakValueEntry<>(segment.queueForKeys, key, hash, next); + return next == null + ? new WeakKeyWeakValueEntry<>(segment.queueForKeys, key, hash) + : new LinkedWeakKeyWeakValueEntry<>(segment.queueForKeys, key, hash, next); } } }