src/jdk/nashorn/internal/codegen/ConstantData.java

Print this page
rev 755 : 8035948: Redesign property listeners for shared classes
Reviewed-by: sundar, lagergren

@@ -23,10 +23,13 @@
  * questions.
  */
 
 package jdk.nashorn.internal.codegen;
 
+import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.PropertyMap;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;

@@ -108,10 +111,47 @@
             return hashCode;
         }
     }
 
     /**
+     * {@link PropertyMap} wrapper class that provides implementations for the {@code hashCode} and {@code equals}
+     * methods that are based on the map layout. {@code PropertyMap} itself inherits the identity based implementations
+     * from {@code java.lang.Object}.
+     */
+    private static class PropertyMapWrapper {
+        private final PropertyMap propertyMap;
+        private final int hashCode;
+
+        public PropertyMapWrapper(final PropertyMap map) {
+            int hash = 0;
+            for (final Property property : map.getProperties()) {
+                hash = hash << 7 ^ hash >> 7;
+                hash ^= property.hashCode();
+            }
+            this.hashCode = hash;
+            this.propertyMap = map;
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals(final Object other) {
+            if (!(other instanceof PropertyMapWrapper)) {
+                return false;
+            }
+
+            final Property[] ownProperties = propertyMap.getProperties();
+            final Property[] otherProperties = ((PropertyMapWrapper) other).propertyMap.getProperties();
+
+            return Arrays.equals(ownProperties, otherProperties);
+        }
+    }
+
+    /**
      * Constructor
      */
     ConstantData() {
         this.constants = new ArrayList<>();
         this.stringMap = new HashMap<>();

@@ -143,11 +183,18 @@
      *
      * @param object the string to add
      * @return the index in the constant pool that the object was given
      */
     public int add(final Object object) {
-        final Object  entry = object.getClass().isArray() ? new ArrayWrapper(object) : object;
+        final Object  entry;
+        if (object.getClass().isArray()) {
+            entry = new ArrayWrapper(object);
+        } else if (object instanceof PropertyMap) {
+            entry = new PropertyMapWrapper((PropertyMap) object);
+        } else {
+            entry = object;
+        }
         final Integer value = objectMap.get(entry);
 
         if (value != null) {
             return value.intValue();
         }