8011095: PropertyHashMap.rehash() does not grow enough

Reviewed-by: hannesw, lagergren
This commit is contained in:
James Laskey 2013-03-31 08:19:11 -03:00 committed by Jim Laskey
parent db89cafb53
commit 1cfc0cae65
2 changed files with 20 additions and 28 deletions

View File

@ -104,10 +104,10 @@ import java.util.Set;
*/ */
public final class PropertyHashMap implements Map <String, Property> { public final class PropertyHashMap implements Map <String, Property> {
/** Number of initial bins. Power of 2. */ /** Number of initial bins. Power of 2. */
private static final int INITIAL_BINS = 16; private static final int INITIAL_BINS = 32;
/** Threshold before using bins. */ /** Threshold before using bins. */
private static final int LIST_THRESHOLD = 4; private static final int LIST_THRESHOLD = 8;
/** Initial map. */ /** Initial map. */
public static final PropertyHashMap EMPTY_MAP = new PropertyHashMap(); public static final PropertyHashMap EMPTY_MAP = new PropertyHashMap();
@ -300,8 +300,8 @@ public final class PropertyHashMap implements Map <String, Property> {
* @return Number of bins required. * @return Number of bins required.
*/ */
private static int binsNeeded(final int n) { private static int binsNeeded(final int n) {
// Allow for 25% padding. // 50% padding
return 1 << (32 - Integer.numberOfLeadingZeros((n + oneQuarter(n)) | (INITIAL_BINS - 1))); return 1 << (32 - Integer.numberOfLeadingZeros((n + (n >>> 1)) | (INITIAL_BINS - 1)));
} }
/** /**
@ -315,28 +315,16 @@ public final class PropertyHashMap implements Map <String, Property> {
return (n >>> 1) + (n >>> 2); return (n >>> 1) + (n >>> 2);
} }
/**
* Used to calculate the current capacity of the bins.
*
* @param n Number of bin slots.
*
* @return 25% of n.
*/
private static int oneQuarter(final int n) {
return n >>> 2;
}
/** /**
* Regenerate the bin table after changing the number of bins. * Regenerate the bin table after changing the number of bins.
* *
* @param list // List of all properties. * @param list // List of all properties.
* @param newSize // New size of {@link PropertyHashMap}. * @param binSize // New size of bins.
* *
* @return Populated bins. * @return Populated bins.
*/ */
private static Element[] rehash(final Element list, final int newSize) { private static Element[] rehash(final Element list, final int binSize) {
final int binsNeeded = binsNeeded(newSize); final Element[] newBins = new Element[binSize];
final Element[] newBins = new Element[binsNeeded];
for (Element element = list; element != null; element = element.getLink()) { for (Element element = list; element != null; element = element.getLink()) {
final Property property = element.getProperty(); final Property property = element.getProperty();
final String key = property.getKey(); final String key = property.getKey();
@ -390,7 +378,7 @@ public final class PropertyHashMap implements Map <String, Property> {
if (bins == null && newSize <= LIST_THRESHOLD) { if (bins == null && newSize <= LIST_THRESHOLD) {
newBins = null; newBins = null;
} else if (newSize > threshold) { } else if (newSize > threshold) {
newBins = rehash(list, newSize); newBins = rehash(list, binsNeeded(newSize));
} else { } else {
newBins = bins.clone(); newBins = bins.clone();
} }

View File

@ -526,11 +526,13 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @param newMap {@link PropertyMap} associated with prototype. * @param newMap {@link PropertyMap} associated with prototype.
*/ */
private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) { private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
if (protoHistory == null) { if (!properties.isEmpty()) {
protoHistory = new WeakHashMap<>(); if (protoHistory == null) {
} protoHistory = new WeakHashMap<>();
}
protoHistory.put(newProto, new WeakReference<>(newMap)); protoHistory.put(newProto, new WeakReference<>(newMap));
}
} }
/** /**
@ -540,11 +542,13 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @param newMap Modified {@link PropertyMap}. * @param newMap Modified {@link PropertyMap}.
*/ */
private void addToHistory(final Property property, final PropertyMap newMap) { private void addToHistory(final Property property, final PropertyMap newMap) {
if (history == null) { if (!properties.isEmpty()) {
history = new LinkedHashMap<>(); if (history == null) {
} history = new LinkedHashMap<>();
}
history.put(property, newMap); history.put(property, newMap);
}
} }
/** /**