Index: modules/luni/src/main/java/java/util/IdentityHashMap.java =================================================================== --- modules/luni/src/main/java/java/util/IdentityHashMap.java (revision 646000) +++ modules/luni/src/main/java/java/util/IdentityHashMap.java (working copy) @@ -52,6 +52,9 @@ /* Actual number of key-value pairs. */ int size; + int lengthMask; + int lengthMask2; + /* * maximum number of elements that can be put in this map before having to * rehash. @@ -253,6 +256,8 @@ this.size = 0; threshold = getThreshold(maxSize); elementData = newElementArray(computeElementArraySize()); + lengthMask = computeMask(elementData.length); + lengthMask2 = lengthMask >> 1; } else { throw new IllegalArgumentException(); } @@ -326,7 +331,7 @@ key = NULL_OBJECT; } - int index = findIndex(key, elementData); + int index = findIndex(key, elementData, elementData.length, lengthMask, lengthMask2); return elementData[index] == key; } @@ -366,7 +371,7 @@ key = NULL_OBJECT; } - int index = findIndex(key, elementData); + int index = findIndex(key, elementData, elementData.length, lengthMask, lengthMask2); if (elementData[index] == key) { Object result = elementData[index + 1]; @@ -381,7 +386,7 @@ key = NULL_OBJECT; } - int index = findIndex(key, elementData); + int index = findIndex(key, elementData, elementData.length, lengthMask, lengthMask2); if (elementData[index] == key) { return getEntry(index); } @@ -412,10 +417,9 @@ * Returns the index where the key is found at, or the index of the next * empty spot if the key is not found in this table. */ - private int findIndex(Object key, Object[] array) { - int length = array.length; - int index = getModuloHash(key, length); - int last = (index + length - 2) % length; + private int findIndex(Object key, Object[] array, int length, int lengthMask, int lengthMask2) { + int index = getModuloHash(key, lengthMask2); + int last = (index + length - 2) & lengthMask; while (index != last) { if (array[index] == key || (array[index] == null)) { /* @@ -424,13 +428,14 @@ */ break; } - index = (index + 2) % length; + index = (index + 2) & lengthMask; } return index; } - private int getModuloHash(Object key, int length) { - return ((System.identityHashCode(key) & 0x7FFFFFFF) % (length / 2)) * 2; + private int getModuloHash(Object key, int lengthMask2) { + //return ((System.identityHashCode(key) & 0x7FFFFFFF) & (lengthMask >> 1)) << 1; + return (System.identityHashCode(key) & lengthMask2) << 1; } /** @@ -455,14 +460,14 @@ _value = NULL_OBJECT; } - int index = findIndex(_key, elementData); + int index = findIndex(_key, elementData, elementData.length, lengthMask, lengthMask2); // if the key doesn't exist in the table if (elementData[index] != _key) { modCount++; if (++size > threshold) { rehash(); - index = findIndex(_key, elementData); + index = findIndex(_key, elementData, elementData.length, lengthMask, lengthMask2); } // insert the key and assign the value to null initially @@ -492,27 +497,43 @@ putAllImpl(map); } + private int computeMask(int length) { + // TODO: check for 2^n first + + // computing mask + int lengthMask = 1; + while ( (length >> 1) == 0 ) { + lengthMask = (lengthMask << 1) + 1; + length = length >> 1; + } + return lengthMask; + } + private void rehash() { int newlength = elementData.length << 1; if (newlength == 0) { newlength = 1; } Object[] newData = newElementArray(newlength); + int newLengthMask = computeMask(newlength); + int newLengthMask2 = newLengthMask >> 1; for (int i = 0; i < elementData.length; i = i + 2) { Object key = elementData[i]; if (key != null) { // if not empty - int index = findIndex(key, newData); + int index = findIndex(key, newData, newlength, newLengthMask, newLengthMask2); newData[index] = key; newData[index + 1] = elementData[i + 1]; } } elementData = newData; + lengthMask = newLengthMask; + lengthMask2 = newLengthMask2; computeMaxSize(); } private void computeMaxSize() { - threshold = (int) ((long) (elementData.length / 2) * loadFactor / 10000); + threshold = (int) ((long) (elementData.length >> 1) * loadFactor / 10000); } /** @@ -532,7 +553,7 @@ boolean hashedOk; int index, next, hash; Object result, object; - index = next = findIndex(key, elementData); + index = next = findIndex(key, elementData, elementData.length, lengthMask, lengthMask2); if (elementData[index] != key) { return null; @@ -545,13 +566,13 @@ // until we reach an empty spot int length = elementData.length; while (true) { - next = (next + 2) % length; + next = (next + 2) & lengthMask; object = elementData[next]; if (object == null) { break; } - hash = getModuloHash(object, length); + hash = getModuloHash(object, lengthMask2); hashedOk = hash > index; if (next < index) { hashedOk = hashedOk || (hash <= next); @@ -784,6 +805,8 @@ int savedSize = stream.readInt(); threshold = getThreshold(DEFAULT_MAX_SIZE); elementData = newElementArray(computeElementArraySize()); + lengthMask = computeMask(elementData.length); + lengthMask2 = lengthMask >> 1; for (int i = savedSize; --i >= 0;) { K key = (K) stream.readObject(); put(key, (V) stream.readObject()); @@ -796,4 +819,7 @@ super.putAll(map); } } + + + }