diff options
Diffstat (limited to 'src/jdk/nashorn/internal/runtime/PropertyHashMap.java')
-rw-r--r-- | src/jdk/nashorn/internal/runtime/PropertyHashMap.java | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/src/jdk/nashorn/internal/runtime/PropertyHashMap.java b/src/jdk/nashorn/internal/runtime/PropertyHashMap.java index bfa06920..ba64af32 100644 --- a/src/jdk/nashorn/internal/runtime/PropertyHashMap.java +++ b/src/jdk/nashorn/internal/runtime/PropertyHashMap.java @@ -164,6 +164,19 @@ public final class PropertyHashMap implements Map <String, Property> { } /** + * Clone a property map, replacing a property with a new one in the same place, + * which is important for property iterations if a property changes types + * @param property old property + * @param newProperty new property + * @return new property map + */ + public PropertyHashMap immutableReplace(final Property property, final Property newProperty) { + assert property.getKey().equals(newProperty.getKey()) : "replacing properties with different keys: '" + property.getKey() + "' != '" + newProperty.getKey() + "'"; + assert findElement(property.getKey()) != null : "replacing property that doesn't exist in map: '" + property.getKey() + "'"; + return cloneMap().replaceNoClone(property.getKey(), newProperty); + } + + /** * Clone a {@link PropertyHashMap} and add a {@link Property}. * * @param property {@link Property} to add. @@ -289,7 +302,7 @@ public final class PropertyHashMap implements Map <String, Property> { * @return The bin index. */ private static int binIndex(final Element[] bins, final String key) { - return key.hashCode() & (bins.length - 1); + return key.hashCode() & bins.length - 1; } /** @@ -301,7 +314,7 @@ public final class PropertyHashMap implements Map <String, Property> { */ private static int binsNeeded(final int n) { // 50% padding - return 1 << (32 - Integer.numberOfLeadingZeros((n + (n >>> 1)) | (INITIAL_BINS - 1))); + return 1 << 32 - Integer.numberOfLeadingZeros(n + (n >>> 1) | INITIAL_BINS - 1); } /** @@ -327,8 +340,9 @@ public final class PropertyHashMap implements Map <String, Property> { final Element[] newBins = new Element[binSize]; for (Element element = list; element != null; element = element.getLink()) { final Property property = element.getProperty(); - final String key = property.getKey(); - final int binIndex = binIndex(newBins, key); + final String key = property.getKey(); + final int binIndex = binIndex(newBins, key); + newBins[binIndex] = new Element(newBins[binIndex], property); } return newBins; @@ -366,6 +380,11 @@ public final class PropertyHashMap implements Map <String, Property> { return null; } + + private PropertyHashMap cloneMap() { + return new PropertyHashMap(size, bins == null ? null : bins.clone(), list); + } + /** * Clone {@link PropertyHashMap} to accommodate new size. * @@ -385,6 +404,8 @@ public final class PropertyHashMap implements Map <String, Property> { return new PropertyHashMap(newSize, newBins, list); } + + /** * Add a {@link Property} to a temporary {@link PropertyHashMap}, that has * been already cloned. Removes duplicates if necessary. @@ -416,6 +437,18 @@ public final class PropertyHashMap implements Map <String, Property> { return new PropertyHashMap(newSize, bins, newList); } + private PropertyHashMap replaceNoClone(final String key, final Property property) { + if (bins != null) { + final int binIndex = binIndex(bins, key); + Element bin = bins[binIndex]; + bin = replaceInList(bin, key, property); + bins[binIndex] = bin; + } + Element newList = list; + newList = replaceInList(newList, key, property); + return new PropertyHashMap(size, bins, newList); + } + /** * Removes an {@link Element} from a specific list, avoiding duplication. * @@ -446,6 +479,30 @@ public final class PropertyHashMap implements Map <String, Property> { return list; } + // for element x. if x get link matches, + private static Element replaceInList(final Element list, final String key, final Property property) { + assert list != null; + final int hashCode = key.hashCode(); + + if (list.match(key, hashCode)) { + return new Element(list.getLink(), property); + } + + final Element head = new Element(null, list.getProperty()); + Element previous = head; + for (Element element = list.getLink(); element != null; element = element.getLink()) { + if (element.match(key, hashCode)) { + previous.setLink(new Element(element.getLink(), property)); + return head; + } + final Element next = new Element(null, element.getProperty()); + previous.setLink(next); + previous = next; + } + return list; + } + + /* * Map implementation */ @@ -617,6 +674,26 @@ public final class PropertyHashMap implements Map <String, Property> { throw new UnsupportedOperationException("Immutable map."); } + @Override + public String toString() { + final StringBuffer sb = new StringBuffer(); + + sb.append('['); + + Element elem = this; + do { + sb.append(elem.getValue()); + elem = elem.link; + if (elem != null) { + sb.append(" -> "); + } + } while (elem != null); + + sb.append(']'); + + return sb.toString(); + } + /* * Accessors */ |