aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/runtime/PropertyHashMap.java')
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyHashMap.java85
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
*/