Index: working_classlib/modules/luni/src/main/java/java/util/IdentityHashMap.java =================================================================== --- working_classlib/modules/luni/src/main/java/java/util/IdentityHashMap.java (revision 649000) +++ working_classlib/modules/luni/src/main/java/java/util/IdentityHashMap.java (working copy) @@ -47,7 +47,7 @@ * The internal data structure to hold key value pairs This array holds keys * and values in an alternating fashion. */ - transient Object[] elementData; + transient Object[] keys, values; /* Actual number of key-value pairs. */ int size; @@ -136,10 +136,10 @@ } public boolean hasNext() { - while (position < associatedMap.elementData.length) { + while (position < associatedMap.keys.length) { // if this is an empty spot, go to the next one - if (associatedMap.elementData[position] == null) { - position += 2; + if (associatedMap.keys[position] == null) { + position ++; } else { return true; } @@ -162,7 +162,7 @@ IdentityHashMapEntry result = associatedMap .getEntry(position); lastPosition = position; - position += 2; + position++; canRemove = true; return type.get(result); @@ -175,7 +175,7 @@ } canRemove = false; - associatedMap.remove(associatedMap.elementData[lastPosition]); + associatedMap.remove(associatedMap.keys[lastPosition]); position = lastPosition; expectedModCount++; } @@ -234,6 +234,15 @@ } } + private int roundTo2K(int s) { + s |= (s >> 1); + s |= (s >> 2); + s |= (s >> 4); + s |= (s >> 8); + s |= (s >> 16); + return s + 1; + } + /** * Create an IdentityHashMap with default maximum size */ @@ -252,7 +261,9 @@ if (maxSize >= 0) { this.size = 0; threshold = getThreshold(maxSize); - elementData = newElementArray(computeElementArraySize()); + int eaSize = roundTo2K(maxSize); + keys = newElementArray(eaSize); + values = newElementArray(eaSize); } else { throw new IllegalArgumentException(); } @@ -264,10 +275,6 @@ return maxSize > 3 ? maxSize : 3; } - private int computeElementArraySize() { - return (int) (((long) threshold * 10000) / loadFactor) * 2; - } - /** * Create a new element array * @@ -286,7 +293,7 @@ * A map of (key,value) pairs to copy into the IdentityHashMap */ public IdentityHashMap(Map map) { - this(map.size() < 6 ? 11 : map.size() * 2); + this(map.size() < 6 ? 11 : map.size()); putAllImpl(map); } @@ -307,8 +314,9 @@ @Override public void clear() { size = 0; - for (int i = 0; i < elementData.length; i++) { - elementData[i] = null; + for (int i = 0; i < keys.length; i++) { + keys[i] = null; + values[i] = null; } modCount++; } @@ -326,8 +334,8 @@ key = NULL_OBJECT; } - int index = findIndex(key, elementData); - return elementData[index] == key; + int index = findIndex(key, keys); + return keys[index] == key; } /** @@ -345,8 +353,8 @@ value = NULL_OBJECT; } - for (int i = 1; i < elementData.length; i = i + 2) { - if (elementData[i] == value) { + for (int i = 0; i < values.length; i++) { + if (values[i] == value) { return true; } } @@ -366,10 +374,10 @@ key = NULL_OBJECT; } - int index = findIndex(key, elementData); + int index = findIndex(key, keys); - if (elementData[index] == key) { - Object result = elementData[index + 1]; + if (keys[index] == key) { + Object result = values[index]; return massageValue(result); } @@ -381,8 +389,8 @@ key = NULL_OBJECT; } - int index = findIndex(key, elementData); - if (elementData[index] == key) { + int index = findIndex(key, keys); + if (keys[index] == key) { return getEntry(index); } @@ -395,8 +403,8 @@ */ @SuppressWarnings("unchecked") private IdentityHashMapEntry getEntry(int index) { - Object key = elementData[index]; - Object value = elementData[index + 1]; + Object key = keys[index]; + Object value = values[index]; if (key == NULL_OBJECT) { key = null; @@ -415,7 +423,7 @@ private int findIndex(Object key, Object[] array) { int length = array.length; int index = getModuloHash(key, length); - int last = (index + length - 2) % length; + int last = (index + length - 1) & (length - 1); while (index != last) { if (array[index] == key || (array[index] == null)) { /* @@ -424,13 +432,13 @@ */ break; } - index = (index + 2) % length; + index = (index + 1) & (length - 1); } return index; } private int getModuloHash(Object key, int length) { - return ((System.identityHashCode(key) & 0x7FFFFFFF) % (length / 2)) * 2; + return (System.identityHashCode(key) & (length - 1)); } /** @@ -455,24 +463,23 @@ _value = NULL_OBJECT; } - int index = findIndex(_key, elementData); + int index = findIndex(_key, keys); // if the key doesn't exist in the table - if (elementData[index] != _key) { + if (keys[index] != _key) { modCount++; if (++size > threshold) { rehash(); - index = findIndex(_key, elementData); + index = findIndex(_key, keys); } - // insert the key and assign the value to null initially - elementData[index] = _key; - elementData[index + 1] = null; + // insert the key + keys[index] = _key; } // insert value to where it needs to go, return the old value - Object result = elementData[index + 1]; - elementData[index + 1] = _value; + Object result = values[index]; + values[index] = _value; return massageValue(result); } @@ -493,26 +500,28 @@ } private void rehash() { - int newlength = elementData.length << 1; + int newlength = keys.length << 1; if (newlength == 0) { newlength = 1; } - Object[] newData = newElementArray(newlength); - for (int i = 0; i < elementData.length; i = i + 2) { - Object key = elementData[i]; + Object[] newKeys = newElementArray(newlength); + Object[] newValues = newElementArray(newlength); + for (int i = 0; i < keys.length; i++) { + Object key = keys[i]; if (key != null) { // if not empty - int index = findIndex(key, newData); - newData[index] = key; - newData[index + 1] = elementData[i + 1]; + int index = findIndex(key, newKeys); + newKeys[index] = key; + newValues[index] = values[i]; } } - elementData = newData; + keys = newKeys; + values = newValues; computeMaxSize(); } private void computeMaxSize() { - threshold = (int) ((long) (elementData.length / 2) * loadFactor / 10000); + threshold = (int) ((long) (keys.length) * loadFactor / 10000); } /** @@ -532,21 +541,21 @@ boolean hashedOk; int index, next, hash; Object result, object; - index = next = findIndex(key, elementData); + index = next = findIndex(key, keys); - if (elementData[index] != key) { + if (keys[index] != key) { return null; } // store the value for this key - result = elementData[index + 1]; + result = values[index]; // shift the following elements up if needed // until we reach an empty spot - int length = elementData.length; + int length = keys.length; while (true) { - next = (next + 2) % length; - object = elementData[next]; + next = (next + 1) & (length - 1); + object = keys[next]; if (object == null) { break; } @@ -559,8 +568,8 @@ hashedOk = hashedOk && (hash <= next); } if (!hashedOk) { - elementData[index] = object; - elementData[index + 1] = elementData[next + 1]; + keys[index] = object; + values[index] = values[next]; index = next; } } @@ -569,8 +578,8 @@ modCount++; // clear both the key and the value - elementData[index] = null; - elementData[index + 1] = null; + keys[index] = null; + values[index] = null; return massageValue(result); } @@ -782,8 +791,10 @@ ClassNotFoundException { stream.defaultReadObject(); int savedSize = stream.readInt(); - threshold = getThreshold(DEFAULT_MAX_SIZE); - elementData = newElementArray(computeElementArraySize()); + int newSize = roundTo2K(DEFAULT_MAX_SIZE); + threshold = getThreshold(newSize); + keys = newElementArray(newSize); + values = newElementArray(newSize); for (int i = savedSize; --i >= 0;) { K key = (K) stream.readObject(); put(key, (V) stream.readObject());