RFR: [6904367]: (coll) IdentityHashMap is resized before exceeding the expected maximum size

Peter Levart peter.levart at gmail.com
Tue Jul 8 12:30:51 UTC 2014


On 07/08/2014 02:20 PM, Peter Levart wrote:
> That's right. Not in put(). But in putAll() it can overflow, since the 
> argument Map can be of any size that fits in int... So here's my 3rd 
> variation of Martin's latest version:
>
> http://cr.openjdk.java.net/~plevart/jdk9-dev/IdentityHashMap/webrev.03/
>
Another bug in my part 8-( I should've used the null-masked 'k' instead 
of 'key' in the index re-compute block:

http://cr.openjdk.java.net/~plevart/jdk9-dev/IdentityHashMap/webrev.04/

And diff to Martin's patch:

*** src/share/classes/java/util/IdentityHashMap.java.mb 2014-07-08 
12:37:57.267916926 +0200
--- src/share/classes/java/util/IdentityHashMap.java    2014-07-08 
14:23:25.141249319 +0200
***************
*** 437,449 ****

           if (size == MAXIMUM_CAPACITY - 1)
               throw new IllegalStateException("Capacity exhausted.");
           modCount++;
           tab[i] = k;
           tab[i + 1] = value;
           size++;
-         int x = size + (size << 1); // Optimized form of 3 * size
-         if (x > len)
-             resize(len); // len == 2 * current capacity.
           return null;
       }

--- 437,455 ----

           if (size == MAXIMUM_CAPACITY - 1)
               throw new IllegalStateException("Capacity exhausted.");
+
+         int x = size + (size << 1) + 3; // Optimized form of 3 * (size 
+ 1)
+         if (x > len && resize(len)) { // len == 2 * current capacity.
+             tab = table;
+             len = tab.length;
+             i = hash(k, len);
+             while (tab[i] != null)
+                 i = nextKeyIndex(i, len);
+         }
           modCount++;
           tab[i] = k;
           tab[i + 1] = value;
           size++;
           return null;
       }

***************
*** 452,468 ****
        *
        * @param newCapacity the new capacity, must be a power of two.
        */
!     private void resize(int newCapacity) {
           // assert (newCapacity & -newCapacity) == newCapacity; // 
power of 2
-         int newLength = newCapacity * 2;

           Object[] oldTable = table;
           int oldLength = oldTable.length;
           if (oldLength == 2 * MAXIMUM_CAPACITY) { // can't expand any 
further
!             return;
           }
           if (oldLength >= newLength)
!             return;

           Object[] newTable = new Object[newLength];

--- 458,474 ----
        *
        * @param newCapacity the new capacity, must be a power of two.
        */
!     private boolean resize(int newCapacity) {
           // assert (newCapacity & -newCapacity) == newCapacity; // 
power of 2

           Object[] oldTable = table;
           int oldLength = oldTable.length;
           if (oldLength == 2 * MAXIMUM_CAPACITY) { // can't expand any 
further
!             return false;
           }
+         int newLength = newCapacity * 2;
           if (oldLength >= newLength)
!             return false;

           Object[] newTable = new Object[newLength];

***************
*** 480,485 ****
--- 486,492 ----
               }
           }
           table = newTable;
+         return true;
       }

       /**
***************
*** 494,500 ****
           int n = m.size();
           if (n == 0)
               return;
!         if (n + (n << 1) > table.length) // conservatively pre-expand
               resize(capacity(n));

           for (Entry<? extends K, ? extends V> e : m.entrySet())
--- 501,507 ----
           int n = m.size();
           if (n == 0)
               return;
!         if (n > table.length / 3) // conservatively pre-expand
               resize(capacity(n));

           for (Entry<? extends K, ? extends V> e : m.entrySet())


Regards, Peter




More information about the core-libs-dev mailing list