8035948: Redesign property listeners for shared classes

Mon, 03 Mar 2014 15:23:01 +0100

author
hannesw
date
Mon, 03 Mar 2014 15:23:01 +0100
changeset 766
06ee95f094b4
parent 765
316ee513df62
child 767
f6f637d883bd

8035948: Redesign property listeners for shared classes
Reviewed-by: sundar, lagergren

buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/ConstantData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ArrayBufferView.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/Global.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeArguments.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeArray.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeArrayBuffer.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeBoolean.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeDate.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeDebug.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeError.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeEvalError.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJSAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJavaImporter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeNumber.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeRangeError.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeReferenceError.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeRegExp.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeStrictArguments.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeString.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeSyntaxError.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeTypeError.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeURIError.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/PrototypeObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/PropertyListener.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/PropertyListenerManager.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/PropertyListeners.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/PropertyMap.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptFunction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/SetMethodCreator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/WithObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornGuards.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/scripts/JO.java file | annotate | diff | comparison | revisions
     1.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java	Tue Feb 25 18:56:10 2014 +0530
     1.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java	Mon Mar 03 15:23:01 2014 +0100
     1.3 @@ -50,8 +50,6 @@
     1.4  import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
     1.5  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
     1.6  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
     1.7 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED;
     1.8 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED_DESC;
     1.9  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP;
    1.10  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC;
    1.11  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
    1.12 @@ -191,8 +189,6 @@
    1.13          // stack: Collection
    1.14          // pmap = PropertyMap.newMap(Collection<Property>);
    1.15          mi.invokeStatic(PROPERTYMAP_TYPE, PROPERTYMAP_NEWMAP, PROPERTYMAP_NEWMAP_DESC);
    1.16 -        // pmap.setIsShared();
    1.17 -        mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_SETISSHARED, PROPERTYMAP_SETISSHARED_DESC);
    1.18          // $nasgenmap$ = pmap;
    1.19          mi.putStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
    1.20          mi.returnVoid();
     2.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java	Tue Feb 25 18:56:10 2014 +0530
     2.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java	Mon Mar 03 15:23:01 2014 +0100
     2.3 @@ -33,10 +33,7 @@
     2.4  import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
     2.5  import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
     2.6  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
     2.7 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
     2.8 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
     2.9  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
    2.10 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
    2.11  import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
    2.12  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR;
    2.13  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC;
    2.14 @@ -171,9 +168,6 @@
    2.15      private void loadMap(final MethodGenerator mi) {
    2.16          if (memberCount > 0) {
    2.17              mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
    2.18 -            // make sure we use duplicated PropertyMap so that original map
    2.19 -            // stays intact and so can be used for many globals.
    2.20 -            mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
    2.21          }
    2.22      }
    2.23  
     3.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java	Tue Feb 25 18:56:10 2014 +0530
     3.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java	Mon Mar 03 15:23:01 2014 +0100
     3.3 @@ -32,10 +32,7 @@
     3.4  import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
     3.5  import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
     3.6  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
     3.7 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
     3.8 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
     3.9  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
    3.10 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
    3.11  import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
    3.12  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
    3.13  import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX;
    3.14 @@ -129,7 +126,6 @@
    3.15              mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
    3.16              // make sure we use duplicated PropertyMap so that original map
    3.17              // stays intact and so can be used for many global.
    3.18 -            mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
    3.19              mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC);
    3.20              // initialize Function type fields
    3.21              initFunctionFields(mi);
     4.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Tue Feb 25 18:56:10 2014 +0530
     4.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Mon Mar 03 15:23:01 2014 +0100
     4.3 @@ -45,11 +45,9 @@
     4.4  @SuppressWarnings("javadoc")
     4.5  public interface StringConstants {
     4.6      // standard jdk types, methods
     4.7 -    static final Type TYPE_METHOD             = Type.getType(Method.class);
     4.8      static final Type TYPE_METHODHANDLE       = Type.getType(MethodHandle.class);
     4.9      static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class);
    4.10      static final Type TYPE_OBJECT             = Type.getType(Object.class);
    4.11 -    static final Type TYPE_CLASS              = Type.getType(Class.class);
    4.12      static final Type TYPE_STRING             = Type.getType(String.class);
    4.13      static final Type TYPE_COLLECTION         = Type.getType(Collection.class);
    4.14      static final Type TYPE_COLLECTIONS        = Type.getType(Collections.class);
    4.15 @@ -104,10 +102,6 @@
    4.16      static final String PROPERTYMAP_DESC = TYPE_PROPERTYMAP.getDescriptor();
    4.17      static final String PROPERTYMAP_NEWMAP = "newMap";
    4.18      static final String PROPERTYMAP_NEWMAP_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_COLLECTION);
    4.19 -    static final String PROPERTYMAP_DUPLICATE = "duplicate";
    4.20 -    static final String PROPERTYMAP_DUPLICATE_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
    4.21 -    static final String PROPERTYMAP_SETISSHARED = "setIsShared";
    4.22 -    static final String PROPERTYMAP_SETISSHARED_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
    4.23  
    4.24      // PrototypeObject
    4.25      static final String PROTOTYPEOBJECT_TYPE = TYPE_PROTOTYPEOBJECT.getInternalName();
     5.1 --- a/src/jdk/nashorn/internal/codegen/ConstantData.java	Tue Feb 25 18:56:10 2014 +0530
     5.2 +++ b/src/jdk/nashorn/internal/codegen/ConstantData.java	Mon Mar 03 15:23:01 2014 +0100
     5.3 @@ -25,6 +25,9 @@
     5.4  
     5.5  package jdk.nashorn.internal.codegen;
     5.6  
     5.7 +import jdk.nashorn.internal.runtime.Property;
     5.8 +import jdk.nashorn.internal.runtime.PropertyMap;
     5.9 +
    5.10  import java.util.ArrayList;
    5.11  import java.util.Arrays;
    5.12  import java.util.HashMap;
    5.13 @@ -110,6 +113,43 @@
    5.14      }
    5.15  
    5.16      /**
    5.17 +     * {@link PropertyMap} wrapper class that provides implementations for the {@code hashCode} and {@code equals}
    5.18 +     * methods that are based on the map layout. {@code PropertyMap} itself inherits the identity based implementations
    5.19 +     * from {@code java.lang.Object}.
    5.20 +     */
    5.21 +    private static class PropertyMapWrapper {
    5.22 +        private final PropertyMap propertyMap;
    5.23 +        private final int hashCode;
    5.24 +
    5.25 +        public PropertyMapWrapper(final PropertyMap map) {
    5.26 +            int hash = 0;
    5.27 +            for (final Property property : map.getProperties()) {
    5.28 +                hash = hash << 7 ^ hash >> 7;
    5.29 +                hash ^= property.hashCode();
    5.30 +            }
    5.31 +            this.hashCode = hash;
    5.32 +            this.propertyMap = map;
    5.33 +        }
    5.34 +
    5.35 +        @Override
    5.36 +        public int hashCode() {
    5.37 +            return hashCode;
    5.38 +        }
    5.39 +
    5.40 +        @Override
    5.41 +        public boolean equals(final Object other) {
    5.42 +            if (!(other instanceof PropertyMapWrapper)) {
    5.43 +                return false;
    5.44 +            }
    5.45 +
    5.46 +            final Property[] ownProperties = propertyMap.getProperties();
    5.47 +            final Property[] otherProperties = ((PropertyMapWrapper) other).propertyMap.getProperties();
    5.48 +
    5.49 +            return Arrays.equals(ownProperties, otherProperties);
    5.50 +        }
    5.51 +    }
    5.52 +
    5.53 +    /**
    5.54       * Constructor
    5.55       */
    5.56      ConstantData() {
    5.57 @@ -145,7 +185,14 @@
    5.58       * @return the index in the constant pool that the object was given
    5.59       */
    5.60      public int add(final Object object) {
    5.61 -        final Object  entry = object.getClass().isArray() ? new ArrayWrapper(object) : object;
    5.62 +        final Object  entry;
    5.63 +        if (object.getClass().isArray()) {
    5.64 +            entry = new ArrayWrapper(object);
    5.65 +        } else if (object instanceof PropertyMap) {
    5.66 +            entry = new PropertyMapWrapper((PropertyMap) object);
    5.67 +        } else {
    5.68 +            entry = object;
    5.69 +        }
    5.70          final Integer value = objectMap.get(entry);
    5.71  
    5.72          if (value != null) {
     6.1 --- a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java	Tue Feb 25 18:56:10 2014 +0530
     6.2 +++ b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java	Mon Mar 03 15:23:01 2014 +0100
     6.3 @@ -72,7 +72,7 @@
     6.4      }
     6.5  
     6.6      AccessorPropertyDescriptor(final boolean configurable, final boolean enumerable, final Object get, final Object set, final Global global) {
     6.7 -        super(global.getObjectPrototype(), global.getAccessorPropertyDescriptorMap());
     6.8 +        super(global.getObjectPrototype(), getInitialMap());
     6.9          this.configurable = configurable;
    6.10          this.enumerable   = enumerable;
    6.11          this.get          = get;
     7.1 --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Tue Feb 25 18:56:10 2014 +0530
     7.2 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Mon Mar 03 15:23:01 2014 +0100
     7.3 @@ -47,7 +47,7 @@
     7.4      }
     7.5  
     7.6      private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) {
     7.7 -        super(global.getArrayBufferViewMap());
     7.8 +        super(getInitialMap());
     7.9          checkConstructorArgs(buffer, byteOffset, elementLength);
    7.10          this.setProto(getPrototype(global));
    7.11          this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
     8.1 --- a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java	Tue Feb 25 18:56:10 2014 +0530
     8.2 +++ b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java	Mon Mar 03 15:23:01 2014 +0100
     8.3 @@ -69,7 +69,7 @@
     8.4      }
     8.5  
     8.6      DataPropertyDescriptor(final boolean configurable, final boolean enumerable, final boolean writable, final Object value, final Global global) {
     8.7 -        super(global.getObjectPrototype(), global.getDataPropertyDescriptorMap());
     8.8 +        super(global.getObjectPrototype(), getInitialMap());
     8.9          this.configurable = configurable;
    8.10          this.enumerable   = enumerable;
    8.11          this.writable     = writable;
     9.1 --- a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java	Tue Feb 25 18:56:10 2014 +0530
     9.2 +++ b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java	Mon Mar 03 15:23:01 2014 +0100
     9.3 @@ -60,7 +60,7 @@
     9.4      }
     9.5  
     9.6      GenericPropertyDescriptor(final boolean configurable, final boolean enumerable, final Global global) {
     9.7 -        super(global.getObjectPrototype(), global.getGenericPropertyDescriptorMap());
     9.8 +        super(global.getObjectPrototype(), getInitialMap());
     9.9          this.configurable = configurable;
    9.10          this.enumerable   = enumerable;
    9.11      }
    10.1 --- a/src/jdk/nashorn/internal/objects/Global.java	Tue Feb 25 18:56:10 2014 +0530
    10.2 +++ b/src/jdk/nashorn/internal/objects/Global.java	Mon Mar 03 15:23:01 2014 +0100
    10.3 @@ -370,36 +370,6 @@
    10.4       */
    10.5      private ScriptFunction typeErrorThrower;
    10.6  
    10.7 -    private PropertyMap    accessorPropertyDescriptorMap;
    10.8 -    private PropertyMap    arrayBufferViewMap;
    10.9 -    private PropertyMap    dataPropertyDescriptorMap;
   10.10 -    private PropertyMap    genericPropertyDescriptorMap;
   10.11 -    private PropertyMap    nativeArgumentsMap;
   10.12 -    private PropertyMap    nativeArrayMap;
   10.13 -    private PropertyMap    nativeArrayBufferMap;
   10.14 -    private PropertyMap    nativeBooleanMap;
   10.15 -    private PropertyMap    nativeDateMap;
   10.16 -    private PropertyMap    nativeErrorMap;
   10.17 -    private PropertyMap    nativeEvalErrorMap;
   10.18 -    private PropertyMap    nativeJSAdapterMap;
   10.19 -    private PropertyMap    nativeJavaImporterMap;
   10.20 -    private PropertyMap    nativeNumberMap;
   10.21 -    private PropertyMap    nativeRangeErrorMap;
   10.22 -    private PropertyMap    nativeReferenceErrorMap;
   10.23 -    private PropertyMap    nativeRegExpMap;
   10.24 -    private PropertyMap    nativeRegExpExecResultMap;
   10.25 -    private PropertyMap    nativeStrictArgumentsMap;
   10.26 -    private PropertyMap    nativeStringMap;
   10.27 -    private PropertyMap    nativeSyntaxErrorMap;
   10.28 -    private PropertyMap    nativeTypeErrorMap;
   10.29 -    private PropertyMap    nativeURIErrorMap;
   10.30 -    private PropertyMap    prototypeObjectMap;
   10.31 -    private PropertyMap    objectMap;
   10.32 -    private PropertyMap    functionMap;
   10.33 -    private PropertyMap    anonymousFunctionMap;
   10.34 -    private PropertyMap    strictFunctionMap;
   10.35 -    private PropertyMap    boundFunctionMap;
   10.36 -
   10.37      // Flag to indicate that a split method issued a return statement
   10.38      private int splitState = -1;
   10.39  
   10.40 @@ -557,7 +527,7 @@
   10.41  
   10.42      @Override
   10.43      public ScriptObject newObject() {
   10.44 -        return new JO(getObjectPrototype(), getObjectMap());
   10.45 +        return new JO(getObjectPrototype(), JO.getInitialMap());
   10.46      }
   10.47  
   10.48      @Override
   10.49 @@ -999,123 +969,6 @@
   10.50          return ScriptFunction.getPrototype(builtinFloat64Array);
   10.51      }
   10.52  
   10.53 -    // Builtin PropertyMap accessors
   10.54 -    PropertyMap getAccessorPropertyDescriptorMap() {
   10.55 -        return accessorPropertyDescriptorMap;
   10.56 -    }
   10.57 -
   10.58 -    PropertyMap getArrayBufferViewMap() {
   10.59 -        return arrayBufferViewMap;
   10.60 -    }
   10.61 -
   10.62 -    PropertyMap getDataPropertyDescriptorMap() {
   10.63 -        return dataPropertyDescriptorMap;
   10.64 -    }
   10.65 -
   10.66 -    PropertyMap getGenericPropertyDescriptorMap() {
   10.67 -        return genericPropertyDescriptorMap;
   10.68 -    }
   10.69 -
   10.70 -    PropertyMap getArgumentsMap() {
   10.71 -        return nativeArgumentsMap;
   10.72 -    }
   10.73 -
   10.74 -    PropertyMap getArrayMap() {
   10.75 -        return nativeArrayMap;
   10.76 -    }
   10.77 -
   10.78 -    PropertyMap getArrayBufferMap() {
   10.79 -        return nativeArrayBufferMap;
   10.80 -    }
   10.81 -
   10.82 -    PropertyMap getBooleanMap() {
   10.83 -        return nativeBooleanMap;
   10.84 -    }
   10.85 -
   10.86 -    PropertyMap getDateMap() {
   10.87 -        return nativeDateMap;
   10.88 -    }
   10.89 -
   10.90 -    PropertyMap getErrorMap() {
   10.91 -        return nativeErrorMap;
   10.92 -    }
   10.93 -
   10.94 -    PropertyMap getEvalErrorMap() {
   10.95 -        return nativeEvalErrorMap;
   10.96 -    }
   10.97 -
   10.98 -    PropertyMap getJSAdapterMap() {
   10.99 -        return nativeJSAdapterMap;
  10.100 -    }
  10.101 -
  10.102 -    PropertyMap getJavaImporterMap() {
  10.103 -        return nativeJavaImporterMap;
  10.104 -    }
  10.105 -
  10.106 -    PropertyMap getNumberMap() {
  10.107 -        return nativeNumberMap;
  10.108 -    }
  10.109 -
  10.110 -    PropertyMap getRangeErrorMap() {
  10.111 -        return nativeRangeErrorMap;
  10.112 -    }
  10.113 -
  10.114 -    PropertyMap getReferenceErrorMap() {
  10.115 -        return nativeReferenceErrorMap;
  10.116 -    }
  10.117 -
  10.118 -    PropertyMap getRegExpMap() {
  10.119 -        return nativeRegExpMap;
  10.120 -    }
  10.121 -
  10.122 -    PropertyMap getRegExpExecResultMap() {
  10.123 -        return nativeRegExpExecResultMap;
  10.124 -    }
  10.125 -
  10.126 -    PropertyMap getStrictArgumentsMap() {
  10.127 -        return nativeStrictArgumentsMap;
  10.128 -    }
  10.129 -
  10.130 -    PropertyMap getStringMap() {
  10.131 -        return nativeStringMap;
  10.132 -    }
  10.133 -
  10.134 -    PropertyMap getSyntaxErrorMap() {
  10.135 -        return nativeSyntaxErrorMap;
  10.136 -    }
  10.137 -
  10.138 -    PropertyMap getTypeErrorMap() {
  10.139 -        return nativeTypeErrorMap;
  10.140 -    }
  10.141 -
  10.142 -    PropertyMap getURIErrorMap() {
  10.143 -        return nativeURIErrorMap;
  10.144 -    }
  10.145 -
  10.146 -    PropertyMap getPrototypeObjectMap() {
  10.147 -        return prototypeObjectMap;
  10.148 -    }
  10.149 -
  10.150 -    PropertyMap getObjectMap() {
  10.151 -        return objectMap;
  10.152 -    }
  10.153 -
  10.154 -    PropertyMap getFunctionMap() {
  10.155 -        return functionMap;
  10.156 -    }
  10.157 -
  10.158 -    PropertyMap getAnonymousFunctionMap() {
  10.159 -        return anonymousFunctionMap;
  10.160 -    }
  10.161 -
  10.162 -    PropertyMap getStrictFunctionMap() {
  10.163 -        return strictFunctionMap;
  10.164 -    }
  10.165 -
  10.166 -    PropertyMap getBoundFunctionMap() {
  10.167 -        return boundFunctionMap;
  10.168 -    }
  10.169 -
  10.170      private ScriptFunction getBuiltinArray() {
  10.171          return builtinArray;
  10.172      }
  10.173 @@ -1631,14 +1484,11 @@
  10.174  
  10.175          final ScriptEnvironment env = getContext().getEnv();
  10.176  
  10.177 -        // duplicate PropertyMaps of Native* classes
  10.178 -        copyInitialMaps(env);
  10.179 -
  10.180          // initialize Function and Object constructor
  10.181          initFunctionAndObject();
  10.182  
  10.183          // Now fix Global's own proto.
  10.184 -        this.setProto(getObjectPrototype());
  10.185 +        this.setInitialProto(getObjectPrototype());
  10.186  
  10.187          // initialize global function properties
  10.188          this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
  10.189 @@ -1783,7 +1633,7 @@
  10.190          final ScriptObject prototype = ScriptFunction.getPrototype(cons);
  10.191          prototype.set(NativeError.NAME, name, false);
  10.192          prototype.set(NativeError.MESSAGE, "", false);
  10.193 -        prototype.setProto(errorProto);
  10.194 +        prototype.setInitialProto(errorProto);
  10.195          return (ScriptFunction)cons;
  10.196      }
  10.197  
  10.198 @@ -1955,7 +1805,7 @@
  10.199              }
  10.200  
  10.201              if (res.getProto() == null) {
  10.202 -                res.setProto(getObjectPrototype());
  10.203 +                res.setInitialProto(getObjectPrototype());
  10.204              }
  10.205  
  10.206              return res;
  10.207 @@ -1965,46 +1815,6 @@
  10.208          }
  10.209      }
  10.210  
  10.211 -    private void copyInitialMaps(final ScriptEnvironment env) {
  10.212 -        this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
  10.213 -        this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
  10.214 -        this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
  10.215 -        this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
  10.216 -        this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
  10.217 -        this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
  10.218 -        this.nativeDateMap = NativeDate.getInitialMap().duplicate();
  10.219 -        this.nativeErrorMap = NativeError.getInitialMap().duplicate();
  10.220 -        this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
  10.221 -        this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
  10.222 -        this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
  10.223 -        this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
  10.224 -        this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
  10.225 -        this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate();
  10.226 -        this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate();
  10.227 -        this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate();
  10.228 -        this.nativeStringMap = NativeString.getInitialMap().duplicate();
  10.229 -        this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate();
  10.230 -        this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate();
  10.231 -        this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
  10.232 -        this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
  10.233 -        this.objectMap = JO.getInitialMap().duplicate();
  10.234 -        this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
  10.235 -        this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
  10.236 -        this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
  10.237 -        this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
  10.238 -
  10.239 -        // java
  10.240 -        if (! env._no_java) {
  10.241 -            this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
  10.242 -        }
  10.243 -
  10.244 -        // typed arrays
  10.245 -        if (! env._no_typed_arrays) {
  10.246 -            this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
  10.247 -            this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
  10.248 -        }
  10.249 -    }
  10.250 -
  10.251      // Function and Object constructors are inter-dependent. Also,
  10.252      // Function.prototype
  10.253      // functions are not properly initialized. We fix the references here.
  10.254 @@ -2022,7 +1832,7 @@
  10.255  
  10.256          // Function.prototype === Object.getPrototypeOf(Function) ===
  10.257          // <anon-function>
  10.258 -        builtinFunction.setProto(anon);
  10.259 +        builtinFunction.setInitialProto(anon);
  10.260          builtinFunction.setPrototype(anon);
  10.261          anon.set("constructor", builtinFunction, false);
  10.262          anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
  10.263 @@ -2038,7 +1848,7 @@
  10.264          this.builtinObject = (ScriptFunction)initConstructor("Object");
  10.265          final ScriptObject ObjectPrototype = getObjectPrototype();
  10.266          // Object.getPrototypeOf(Function.prototype) === Object.prototype
  10.267 -        anon.setProto(ObjectPrototype);
  10.268 +        anon.setInitialProto(ObjectPrototype);
  10.269  
  10.270          // Function valued properties of Function.prototype were not properly
  10.271          // initialized. Because, these were created before global.function and
  10.272 @@ -2050,10 +1860,10 @@
  10.273  
  10.274              if (value instanceof ScriptFunction && value != anon) {
  10.275                  final ScriptFunction func = (ScriptFunction)value;
  10.276 -                func.setProto(getFunctionPrototype());
  10.277 +                func.setInitialProto(getFunctionPrototype());
  10.278                  final ScriptObject prototype = ScriptFunction.getPrototype(func);
  10.279                  if (prototype != null) {
  10.280 -                    prototype.setProto(ObjectPrototype);
  10.281 +                    prototype.setInitialProto(ObjectPrototype);
  10.282                  }
  10.283              }
  10.284          }
  10.285 @@ -2068,7 +1878,7 @@
  10.286                  final ScriptFunction func = (ScriptFunction)value;
  10.287                  final ScriptObject prototype = ScriptFunction.getPrototype(func);
  10.288                  if (prototype != null) {
  10.289 -                    prototype.setProto(ObjectPrototype);
  10.290 +                    prototype.setInitialProto(ObjectPrototype);
  10.291                  }
  10.292              }
  10.293          }
  10.294 @@ -2086,7 +1896,7 @@
  10.295                  final ScriptFunction func = (ScriptFunction)value;
  10.296                  final ScriptObject prototype = ScriptFunction.getPrototype(func);
  10.297                  if (prototype != null) {
  10.298 -                    prototype.setProto(ObjectPrototype);
  10.299 +                    prototype.setInitialProto(ObjectPrototype);
  10.300                  }
  10.301              }
  10.302          }
    11.1 --- a/src/jdk/nashorn/internal/objects/NativeArguments.java	Tue Feb 25 18:56:10 2014 +0530
    11.2 +++ b/src/jdk/nashorn/internal/objects/NativeArguments.java	Mon Mar 03 15:23:01 2014 +0100
    11.3 @@ -68,7 +68,7 @@
    11.4          final ArrayList<Property> properties = new ArrayList<>(2);
    11.5          properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH));
    11.6          properties.add(AccessorProperty.create("callee", Property.NOT_ENUMERABLE, G$CALLEE, S$CALLEE));
    11.7 -        map$ = PropertyMap.newMap(properties).setIsShared();
    11.8 +        map$ = PropertyMap.newMap(properties);
    11.9      }
   11.10  
   11.11      static PropertyMap getInitialMap() {
   11.12 @@ -267,9 +267,9 @@
   11.13          final Global global = Global.instance();
   11.14          final ScriptObject proto = global.getObjectPrototype();
   11.15          if (isStrict) {
   11.16 -            return new NativeStrictArguments(arguments, numParams, proto, global.getStrictArgumentsMap());
   11.17 +            return new NativeStrictArguments(arguments, numParams, proto, NativeStrictArguments.getInitialMap());
   11.18          }
   11.19 -        return new NativeArguments(arguments, callee, numParams, proto, global.getArgumentsMap());
   11.20 +        return new NativeArguments(arguments, callee, numParams, proto, NativeArguments.getInitialMap());
   11.21      }
   11.22  
   11.23      /**
    12.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java	Tue Feb 25 18:56:10 2014 +0530
    12.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java	Mon Mar 03 15:23:01 2014 +0100
    12.3 @@ -208,7 +208,7 @@
    12.4      }
    12.5  
    12.6      NativeArray(final ArrayData arrayData, final Global global) {
    12.7 -        super(global.getArrayPrototype(), global.getArrayMap());
    12.8 +        super(global.getArrayPrototype(), getInitialMap());
    12.9          this.setArray(arrayData);
   12.10          this.setIsArray();
   12.11      }
    13.1 --- a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java	Tue Feb 25 18:56:10 2014 +0530
    13.2 +++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java	Mon Mar 03 15:23:01 2014 +0100
    13.3 @@ -57,7 +57,7 @@
    13.4      }
    13.5  
    13.6      protected NativeArrayBuffer(final byte[] byteArray, final Global global) {
    13.7 -        super(global.getArrayBufferPrototype(), global.getArrayBufferMap());
    13.8 +        super(global.getArrayBufferPrototype(), getInitialMap());
    13.9          this.buffer = byteArray;
   13.10      }
   13.11  
    14.1 --- a/src/jdk/nashorn/internal/objects/NativeBoolean.java	Tue Feb 25 18:56:10 2014 +0530
    14.2 +++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java	Mon Mar 03 15:23:01 2014 +0100
    14.3 @@ -65,7 +65,7 @@
    14.4      }
    14.5  
    14.6      NativeBoolean(final boolean flag, final Global global) {
    14.7 -        this(flag, global.getBooleanPrototype(), global.getBooleanMap());
    14.8 +        this(flag, global.getBooleanPrototype(), getInitialMap());
    14.9      }
   14.10  
   14.11      NativeBoolean(final boolean flag) {
    15.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java	Tue Feb 25 18:56:10 2014 +0530
    15.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java	Mon Mar 03 15:23:01 2014 +0100
    15.3 @@ -127,7 +127,7 @@
    15.4      }
    15.5  
    15.6      NativeDate(final double time, final Global global) {
    15.7 -        this(time, global.getDatePrototype(), global.getDateMap());
    15.8 +        this(time, global.getDatePrototype(), getInitialMap());
    15.9      }
   15.10  
   15.11      private NativeDate (final double time) {
    16.1 --- a/src/jdk/nashorn/internal/objects/NativeDebug.java	Tue Feb 25 18:56:10 2014 +0530
    16.2 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java	Mon Mar 03 15:23:01 2014 +0100
    16.3 @@ -34,7 +34,7 @@
    16.4  import jdk.nashorn.internal.objects.annotations.ScriptClass;
    16.5  import jdk.nashorn.internal.objects.annotations.Where;
    16.6  import jdk.nashorn.internal.runtime.Context;
    16.7 -import jdk.nashorn.internal.runtime.PropertyListenerManager;
    16.8 +import jdk.nashorn.internal.runtime.PropertyListeners;
    16.9  import jdk.nashorn.internal.runtime.PropertyMap;
   16.10  import jdk.nashorn.internal.runtime.ScriptFunction;
   16.11  import jdk.nashorn.internal.runtime.ScriptObject;
   16.12 @@ -186,7 +186,7 @@
   16.13       */
   16.14      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
   16.15      public static Object getListenerCount(final Object self, final Object obj) {
   16.16 -        return (obj instanceof ScriptObject)? ((ScriptObject)obj).getListenerCount() : 0;
   16.17 +        return (obj instanceof ScriptObject) ? PropertyListeners.getListenerCount((ScriptObject) obj) : 0;
   16.18      }
   16.19  
   16.20      /**
   16.21 @@ -203,14 +203,13 @@
   16.22  
   16.23          out.println("ScriptObject count " + ScriptObject.getCount());
   16.24          out.println("Scope count " + ScriptObject.getScopeCount());
   16.25 -        out.println("ScriptObject listeners added " + PropertyListenerManager.getListenersAdded());
   16.26 -        out.println("ScriptObject listeners removed " + PropertyListenerManager.getListenersRemoved());
   16.27 +        out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded());
   16.28 +        out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved());
   16.29          out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount());
   16.30          out.println("ScriptFunction invokes " + ScriptFunction.getInvokes());
   16.31          out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
   16.32          out.println("PropertyMap count " + PropertyMap.getCount());
   16.33          out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
   16.34 -        out.println("PropertyMap shared " + PropertyMap.getSharedCount());
   16.35          out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
   16.36          out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
   16.37          out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
    17.1 --- a/src/jdk/nashorn/internal/objects/NativeError.java	Tue Feb 25 18:56:10 2014 +0530
    17.2 +++ b/src/jdk/nashorn/internal/objects/NativeError.java	Mon Mar 03 15:23:01 2014 +0100
    17.3 @@ -108,7 +108,7 @@
    17.4      }
    17.5  
    17.6      NativeError(final Object msg, final Global global) {
    17.7 -        this(msg, global.getErrorPrototype(), global.getErrorMap());
    17.8 +        this(msg, global.getErrorPrototype(), getInitialMap());
    17.9      }
   17.10  
   17.11      private NativeError(final Object msg) {
    18.1 --- a/src/jdk/nashorn/internal/objects/NativeEvalError.java	Tue Feb 25 18:56:10 2014 +0530
    18.2 +++ b/src/jdk/nashorn/internal/objects/NativeEvalError.java	Mon Mar 03 15:23:01 2014 +0100
    18.3 @@ -78,7 +78,7 @@
    18.4      }
    18.5  
    18.6      NativeEvalError(final Object msg, final Global global) {
    18.7 -        this(msg, global.getEvalErrorPrototype(), global.getEvalErrorMap());
    18.8 +        this(msg, global.getEvalErrorPrototype(), getInitialMap());
    18.9      }
   18.10  
   18.11      private NativeEvalError(final Object msg) {
    19.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Tue Feb 25 18:56:10 2014 +0530
    19.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Mon Mar 03 15:23:01 2014 +0100
    19.3 @@ -163,7 +163,7 @@
    19.4      }
    19.5  
    19.6      private static ScriptObject wrapAdaptee(final ScriptObject adaptee) {
    19.7 -        return new JO(adaptee, Global.instance().getObjectMap());
    19.8 +        return new JO(adaptee, JO.getInitialMap());
    19.9      }
   19.10  
   19.11      @Override
   19.12 @@ -577,7 +577,7 @@
   19.13              proto = global.getJSAdapterPrototype();
   19.14          }
   19.15  
   19.16 -        return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, global.getJSAdapterMap());
   19.17 +        return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, getInitialMap());
   19.18      }
   19.19  
   19.20      @Override
   19.21 @@ -629,7 +629,7 @@
   19.22                      // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
   19.23                      return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
   19.24                              func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
   19.25 -                            adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__),
   19.26 +                            adaptee.getProtoSwitchPoint(__call__, find.getOwner()),
   19.27                              testJSAdaptor(adaptee, null, null, null));
   19.28                  }
   19.29              }
   19.30 @@ -700,7 +700,7 @@
   19.31                  if (methodHandle != null) {
   19.32                      return new GuardedInvocation(
   19.33                              methodHandle,
   19.34 -                            adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
   19.35 +                            adaptee.getProtoSwitchPoint(hook, findData.getOwner()),
   19.36                              testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
   19.37                  }
   19.38               }
   19.39 @@ -713,7 +713,7 @@
   19.40              final MethodHandle methodHandle = hook.equals(__put__) ?
   19.41              MH.asType(Lookup.EMPTY_SETTER, type) :
   19.42              Lookup.emptyGetter(type.returnType());
   19.43 -            return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), testJSAdaptor(adaptee, null, null, null));
   19.44 +            return new GuardedInvocation(methodHandle, adaptee.getProtoSwitchPoint(hook, null), testJSAdaptor(adaptee, null, null, null));
   19.45          }
   19.46      }
   19.47  
    20.1 --- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Tue Feb 25 18:56:10 2014 +0530
    20.2 +++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Mon Mar 03 15:23:01 2014 +0100
    20.3 @@ -70,7 +70,7 @@
    20.4      }
    20.5  
    20.6      private NativeJavaImporter(final Object[] args, final Global global) {
    20.7 -        this(args, global.getJavaImporterPrototype(), global.getJavaImporterMap());
    20.8 +        this(args, global.getJavaImporterPrototype(), getInitialMap());
    20.9      }
   20.10  
   20.11      private NativeJavaImporter(final Object[] args) {
    21.1 --- a/src/jdk/nashorn/internal/objects/NativeNumber.java	Tue Feb 25 18:56:10 2014 +0530
    21.2 +++ b/src/jdk/nashorn/internal/objects/NativeNumber.java	Mon Mar 03 15:23:01 2014 +0100
    21.3 @@ -98,7 +98,7 @@
    21.4      }
    21.5  
    21.6      NativeNumber(final double value, final Global global) {
    21.7 -        this(value, global.getNumberPrototype(), global.getNumberMap());
    21.8 +        this(value, global.getNumberPrototype(), getInitialMap());
    21.9      }
   21.10  
   21.11      private NativeNumber(final double value) {
    22.1 --- a/src/jdk/nashorn/internal/objects/NativeRangeError.java	Tue Feb 25 18:56:10 2014 +0530
    22.2 +++ b/src/jdk/nashorn/internal/objects/NativeRangeError.java	Mon Mar 03 15:23:01 2014 +0100
    22.3 @@ -78,7 +78,7 @@
    22.4      }
    22.5  
    22.6      NativeRangeError(final Object msg, final Global global) {
    22.7 -        this(msg, global.getRangeErrorPrototype(), global.getRangeErrorMap());
    22.8 +        this(msg, global.getRangeErrorPrototype(), getInitialMap());
    22.9      }
   22.10  
   22.11      private NativeRangeError(final Object msg) {
    23.1 --- a/src/jdk/nashorn/internal/objects/NativeReferenceError.java	Tue Feb 25 18:56:10 2014 +0530
    23.2 +++ b/src/jdk/nashorn/internal/objects/NativeReferenceError.java	Mon Mar 03 15:23:01 2014 +0100
    23.3 @@ -78,7 +78,7 @@
    23.4      }
    23.5  
    23.6      NativeReferenceError(final Object msg, final Global global) {
    23.7 -        this(msg, global.getReferenceErrorPrototype(), global.getReferenceErrorMap());
    23.8 +        this(msg, global.getReferenceErrorPrototype(), getInitialMap());
    23.9      }
   23.10  
   23.11      private NativeReferenceError(final Object msg) {
    24.1 --- a/src/jdk/nashorn/internal/objects/NativeRegExp.java	Tue Feb 25 18:56:10 2014 +0530
    24.2 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java	Mon Mar 03 15:23:01 2014 +0100
    24.3 @@ -75,7 +75,7 @@
    24.4      }
    24.5  
    24.6      private NativeRegExp(final Global global) {
    24.7 -        super(global.getRegExpPrototype(), global.getRegExpMap());
    24.8 +        super(global.getRegExpPrototype(), getInitialMap());
    24.9          this.globalObject = global;
   24.10      }
   24.11  
    25.1 --- a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java	Tue Feb 25 18:56:10 2014 +0530
    25.2 +++ b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java	Mon Mar 03 15:23:01 2014 +0100
    25.3 @@ -58,7 +58,7 @@
    25.4      }
    25.5  
    25.6      NativeRegExpExecResult(final RegExpResult result, final Global global) {
    25.7 -        super(global.getArrayPrototype(), global.getRegExpExecResultMap());
    25.8 +        super(global.getArrayPrototype(), getInitialMap());
    25.9          setIsArray();
   25.10          this.setArray(ArrayData.allocate(result.getGroups().clone()));
   25.11          this.index = result.getIndex();
    26.1 --- a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java	Tue Feb 25 18:56:10 2014 +0530
    26.2 +++ b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java	Mon Mar 03 15:23:01 2014 +0100
    26.3 @@ -60,9 +60,9 @@
    26.4          // In strict mode, the caller and callee properties should throw TypeError
    26.5          // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
    26.6          final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
    26.7 -        map = map.addProperty(map.newUserAccessors("caller", flags));
    26.8 -        map = map.addProperty(map.newUserAccessors("callee", flags));
    26.9 -        map$ = map.setIsShared();
   26.10 +        map = map.addPropertyNoHistory(map.newUserAccessors("caller", flags));
   26.11 +        map = map.addPropertyNoHistory(map.newUserAccessors("callee", flags));
   26.12 +        map$ = map;
   26.13      }
   26.14  
   26.15      static PropertyMap getInitialMap() {
    27.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java	Tue Feb 25 18:56:10 2014 +0530
    27.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java	Mon Mar 03 15:23:01 2014 +0100
    27.3 @@ -83,7 +83,7 @@
    27.4      }
    27.5  
    27.6      NativeString(final CharSequence value, final Global global) {
    27.7 -        this(value, global.getStringPrototype(), global.getStringMap());
    27.8 +        this(value, global.getStringPrototype(), getInitialMap());
    27.9      }
   27.10  
   27.11      private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) {
    28.1 --- a/src/jdk/nashorn/internal/objects/NativeSyntaxError.java	Tue Feb 25 18:56:10 2014 +0530
    28.2 +++ b/src/jdk/nashorn/internal/objects/NativeSyntaxError.java	Mon Mar 03 15:23:01 2014 +0100
    28.3 @@ -68,7 +68,7 @@
    28.4  
    28.5      @SuppressWarnings("LeakingThisInConstructor")
    28.6      NativeSyntaxError(final Object msg, final Global global) {
    28.7 -        super(global.getSyntaxErrorPrototype(), global.getSyntaxErrorMap());
    28.8 +        super(global.getSyntaxErrorPrototype(), getInitialMap());
    28.9          if (msg != UNDEFINED) {
   28.10              this.instMessage = JSType.toString(msg);
   28.11          } else {
    29.1 --- a/src/jdk/nashorn/internal/objects/NativeTypeError.java	Tue Feb 25 18:56:10 2014 +0530
    29.2 +++ b/src/jdk/nashorn/internal/objects/NativeTypeError.java	Mon Mar 03 15:23:01 2014 +0100
    29.3 @@ -68,7 +68,7 @@
    29.4  
    29.5      @SuppressWarnings("LeakingThisInConstructor")
    29.6      NativeTypeError(final Object msg, final Global global) {
    29.7 -        super(global.getTypeErrorPrototype(), global.getTypeErrorMap());
    29.8 +        super(global.getTypeErrorPrototype(), getInitialMap());
    29.9          if (msg != UNDEFINED) {
   29.10              this.instMessage = JSType.toString(msg);
   29.11          } else {
    30.1 --- a/src/jdk/nashorn/internal/objects/NativeURIError.java	Tue Feb 25 18:56:10 2014 +0530
    30.2 +++ b/src/jdk/nashorn/internal/objects/NativeURIError.java	Mon Mar 03 15:23:01 2014 +0100
    30.3 @@ -67,7 +67,7 @@
    30.4  
    30.5      @SuppressWarnings("LeakingThisInConstructor")
    30.6      NativeURIError(final Object msg, final Global global) {
    30.7 -        super(global.getURIErrorPrototype(), global.getURIErrorMap());
    30.8 +        super(global.getURIErrorPrototype(), getInitialMap());
    30.9          if (msg != UNDEFINED) {
   30.10              this.instMessage = JSType.toString(msg);
   30.11          } else {
    31.1 --- a/src/jdk/nashorn/internal/objects/PrototypeObject.java	Tue Feb 25 18:56:10 2014 +0530
    31.2 +++ b/src/jdk/nashorn/internal/objects/PrototypeObject.java	Mon Mar 03 15:23:01 2014 +0100
    31.3 @@ -54,7 +54,7 @@
    31.4      static {
    31.5          final ArrayList<Property> properties = new ArrayList<>(1);
    31.6          properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR));
    31.7 -        map$ = PropertyMap.newMap(properties).setIsShared();
    31.8 +        map$ = PropertyMap.newMap(properties);
    31.9      }
   31.10  
   31.11      static PropertyMap getInitialMap() {
   31.12 @@ -62,8 +62,7 @@
   31.13      }
   31.14  
   31.15      private PrototypeObject(final Global global, final PropertyMap map) {
   31.16 -        super(map != map$? map.addAll(global.getPrototypeObjectMap()) : global.getPrototypeObjectMap());
   31.17 -        setProto(global.getObjectPrototype());
   31.18 +        super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$);
   31.19      }
   31.20  
   31.21      PrototypeObject() {
    32.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Tue Feb 25 18:56:10 2014 +0530
    32.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Mon Mar 03 15:23:01 2014 +0100
    32.3 @@ -37,7 +37,6 @@
    32.4  import jdk.nashorn.internal.runtime.ScriptFunction;
    32.5  import jdk.nashorn.internal.runtime.ScriptFunctionData;
    32.6  import jdk.nashorn.internal.runtime.ScriptObject;
    32.7 -import jdk.nashorn.internal.lookup.Lookup;
    32.8  import jdk.nashorn.internal.runtime.AccessorProperty;
    32.9  
   32.10  /**
   32.11 @@ -76,7 +75,7 @@
   32.12      private static final Object LAZY_PROTOTYPE = new Object();
   32.13  
   32.14      private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) {
   32.15 -        super(name, invokeHandle, global.getFunctionMap(), null, specs, false, true, true);
   32.16 +        super(name, invokeHandle, getInitialMap(), null, specs, false, true, true);
   32.17          init(global);
   32.18      }
   32.19  
   32.20 @@ -93,7 +92,7 @@
   32.21      }
   32.22  
   32.23      private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) {
   32.24 -        super(name, invokeHandle, map.addAll(global.getFunctionMap()), null, specs, false, true, true);
   32.25 +        super(name, invokeHandle, map.addAll(getInitialMap()), null, specs, false, true, true);
   32.26          init(global);
   32.27      }
   32.28  
   32.29 @@ -151,7 +150,7 @@
   32.30       * @param global the global object
   32.31       */
   32.32      ScriptFunctionImpl(final ScriptFunctionData data, final Global global) {
   32.33 -        super(data, global.getBoundFunctionMap(), null);
   32.34 +        super(data, getInitialBoundMap(), null);
   32.35          init(global);
   32.36      }
   32.37  
   32.38 @@ -163,25 +162,20 @@
   32.39          map$ = PropertyMap.newMap(properties);
   32.40          strictmodemap$ = createStrictModeMap(map$);
   32.41          boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
   32.42 -        // There are order dependencies between normal map, struct map and bound map
   32.43 -        // We can make these 'shared' only after initialization of all three.
   32.44 -        map$.setIsShared();
   32.45 -        strictmodemap$.setIsShared();
   32.46 -        boundfunctionmap$.setIsShared();
   32.47      }
   32.48  
   32.49      private static PropertyMap createStrictModeMap(final PropertyMap map) {
   32.50          final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
   32.51          PropertyMap newMap = map;
   32.52          // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
   32.53 -        newMap = newMap.addProperty(map.newUserAccessors("arguments", flags));
   32.54 -        newMap = newMap.addProperty(map.newUserAccessors("caller", flags));
   32.55 +        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
   32.56 +        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
   32.57          return newMap;
   32.58      }
   32.59  
   32.60      // Choose the map based on strict mode!
   32.61      private static PropertyMap getMap(final Global global, final boolean strict) {
   32.62 -        return strict ? global.getStrictFunctionMap() : global.getFunctionMap();
   32.63 +        return strict ? getInitialStrictMap() : getInitialMap();
   32.64      }
   32.65  
   32.66      private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) {
   32.67 @@ -193,14 +187,14 @@
   32.68      // Instance of this class is used as global anonymous function which
   32.69      // serves as Function.prototype object.
   32.70      private static class AnonymousFunction extends ScriptFunctionImpl {
   32.71 -        private static final PropertyMap anonmap$ = PropertyMap.newMap().setIsShared();
   32.72 +        private static final PropertyMap anonmap$ = PropertyMap.newMap();
   32.73  
   32.74          static PropertyMap getInitialMap() {
   32.75              return anonmap$;
   32.76          }
   32.77  
   32.78          AnonymousFunction(final Global global) {
   32.79 -            super("", GlobalFunctions.ANONYMOUS, global.getAnonymousFunctionMap(), null);
   32.80 +            super("", GlobalFunctions.ANONYMOUS, getInitialAnonymousMap(), null);
   32.81          }
   32.82      }
   32.83  
   32.84 @@ -281,13 +275,17 @@
   32.85      }
   32.86  
   32.87      @Override
   32.88 -    public final void setPrototype(final Object prototype) {
   32.89 -        this.prototype = prototype;
   32.90 +    public final void setPrototype(final Object newProto) {
   32.91 +        if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) {
   32.92 +            // Replace our current allocator map with one that is associated with the new prototype.
   32.93 +            allocatorMap = allocatorMap.changeProto((ScriptObject)newProto);
   32.94 +        }
   32.95 +        this.prototype = newProto;
   32.96      }
   32.97  
   32.98      // Internals below..
   32.99      private void init(final Global global) {
  32.100 -        this.setProto(global.getFunctionPrototype());
  32.101 +        this.setInitialProto(global.getFunctionPrototype());
  32.102          this.prototype = LAZY_PROTOTYPE;
  32.103  
  32.104          // We have to fill user accessor functions late as these are stored
    33.1 --- a/src/jdk/nashorn/internal/runtime/PropertyListener.java	Tue Feb 25 18:56:10 2014 +0530
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,66 +0,0 @@
    33.4 -/*
    33.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    33.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 - *
    33.8 - * This code is free software; you can redistribute it and/or modify it
    33.9 - * under the terms of the GNU General Public License version 2 only, as
   33.10 - * published by the Free Software Foundation.  Oracle designates this
   33.11 - * particular file as subject to the "Classpath" exception as provided
   33.12 - * by Oracle in the LICENSE file that accompanied this code.
   33.13 - *
   33.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   33.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.17 - * version 2 for more details (a copy is included in the LICENSE file that
   33.18 - * accompanied this code).
   33.19 - *
   33.20 - * You should have received a copy of the GNU General Public License version
   33.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   33.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.23 - *
   33.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.25 - * or visit www.oracle.com if you need additional information or have any
   33.26 - * questions.
   33.27 - */
   33.28 -
   33.29 -package jdk.nashorn.internal.runtime;
   33.30 -
   33.31 -/**
   33.32 - * Property change listener gets notified whenever properties are added/deleted/modified.
   33.33 - */
   33.34 -public interface PropertyListener {
   33.35 -    /**
   33.36 -     * A new property is being added.
   33.37 -     *
   33.38 -     * @param object The ScriptObject to which property was added.
   33.39 -     * @param prop The new Property added.
   33.40 -     */
   33.41 -    public void propertyAdded(ScriptObject object, Property prop);
   33.42 -
   33.43 -    /**
   33.44 -     * An existing property is being deleted.
   33.45 -     *
   33.46 -     * @param object The ScriptObject whose property is being deleted.
   33.47 -     * @param prop The property being deleted.
   33.48 -     */
   33.49 -    public void propertyDeleted(ScriptObject object, Property prop);
   33.50 -
   33.51 -    /**
   33.52 -     * An existing Property is being replaced with a new Property.
   33.53 -     *
   33.54 -     * @param object The ScriptObject whose property is being modified.
   33.55 -     * @param oldProp The old property that is being replaced.
   33.56 -     * @param newProp The new property that replaces the old property.
   33.57 -     *
   33.58 -     */
   33.59 -    public void propertyModified(ScriptObject object, Property oldProp, Property newProp);
   33.60 -
   33.61 -    /**
   33.62 -     * Given object's __proto__ has changed.
   33.63 -     *
   33.64 -     * @param object object whose __proto__ has changed.
   33.65 -     * @param oldProto old __proto__
   33.66 -     * @param newProto new __proto__
   33.67 -     */
   33.68 -    public void protoChanged(ScriptObject object, ScriptObject oldProto, ScriptObject newProto);
   33.69 -}
    34.1 --- a/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java	Tue Feb 25 18:56:10 2014 +0530
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,179 +0,0 @@
    34.4 -/*
    34.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    34.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 - *
    34.8 - * This code is free software; you can redistribute it and/or modify it
    34.9 - * under the terms of the GNU General Public License version 2 only, as
   34.10 - * published by the Free Software Foundation.  Oracle designates this
   34.11 - * particular file as subject to the "Classpath" exception as provided
   34.12 - * by Oracle in the LICENSE file that accompanied this code.
   34.13 - *
   34.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   34.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   34.17 - * version 2 for more details (a copy is included in the LICENSE file that
   34.18 - * accompanied this code).
   34.19 - *
   34.20 - * You should have received a copy of the GNU General Public License version
   34.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   34.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.23 - *
   34.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   34.25 - * or visit www.oracle.com if you need additional information or have any
   34.26 - * questions.
   34.27 - */
   34.28 -
   34.29 -package jdk.nashorn.internal.runtime;
   34.30 -
   34.31 -import java.util.Map;
   34.32 -import java.util.WeakHashMap;
   34.33 -
   34.34 -/**
   34.35 - * Helper class to manage property listeners and notification.
   34.36 - */
   34.37 -public class PropertyListenerManager implements PropertyListener {
   34.38 -    PropertyListenerManager() {}
   34.39 -
   34.40 -    /** property listeners for this object. */
   34.41 -    private Map<PropertyListener,Boolean> listeners;
   34.42 -
   34.43 -    // These counters are updated in debug mode
   34.44 -    private static int listenersAdded;
   34.45 -    private static int listenersRemoved;
   34.46 -
   34.47 -    /**
   34.48 -     * Return aggregate listeners added to all PropertyListenerManagers
   34.49 -     * @return the listenersAdded
   34.50 -     */
   34.51 -    public static int getListenersAdded() {
   34.52 -        return listenersAdded;
   34.53 -    }
   34.54 -
   34.55 -    /**
   34.56 -     * Return aggregate listeners removed from all PropertyListenerManagers
   34.57 -     * @return the listenersRemoved
   34.58 -     */
   34.59 -    public static int getListenersRemoved() {
   34.60 -        return listenersRemoved;
   34.61 -    }
   34.62 -
   34.63 -    /**
   34.64 -     * Return listeners added to this PropertyListenerManager.
   34.65 -     * @return the listener count
   34.66 -     */
   34.67 -    public final int getListenerCount() {
   34.68 -        return listeners != null? listeners.size() : 0;
   34.69 -    }
   34.70 -
   34.71 -    // Property listener management methods
   34.72 -
   34.73 -    /**
   34.74 -     * Add a property listener to this object.
   34.75 -     *
   34.76 -     * @param listener The property listener that is added.
   34.77 -     */
   34.78 -    public synchronized final void addPropertyListener(final PropertyListener listener) {
   34.79 -        if (listeners == null) {
   34.80 -            listeners = new WeakHashMap<>();
   34.81 -        }
   34.82 -
   34.83 -        if (Context.DEBUG) {
   34.84 -            listenersAdded++;
   34.85 -        }
   34.86 -        listeners.put(listener, Boolean.TRUE);
   34.87 -    }
   34.88 -
   34.89 -    /**
   34.90 -     * Remove a property listener from this object.
   34.91 -     *
   34.92 -     * @param listener The property listener that is removed.
   34.93 -     */
   34.94 -    public synchronized final void removePropertyListener(final PropertyListener listener) {
   34.95 -        if (listeners != null) {
   34.96 -            if (Context.DEBUG) {
   34.97 -                listenersRemoved++;
   34.98 -            }
   34.99 -            listeners.remove(listener);
  34.100 -        }
  34.101 -    }
  34.102 -
  34.103 -    /**
  34.104 -     * This method can be called to notify property addition to this object's listeners.
  34.105 -     *
  34.106 -     * @param object The ScriptObject to which property was added.
  34.107 -     * @param prop The property being added.
  34.108 -     */
  34.109 -    protected synchronized final void notifyPropertyAdded(final ScriptObject object, final Property prop) {
  34.110 -        if (listeners != null) {
  34.111 -            for (PropertyListener listener : listeners.keySet()) {
  34.112 -                listener.propertyAdded(object, prop);
  34.113 -            }
  34.114 -        }
  34.115 -    }
  34.116 -
  34.117 -    /**
  34.118 -     * This method can be called to notify property deletion to this object's listeners.
  34.119 -     *
  34.120 -     * @param object The ScriptObject from which property was deleted.
  34.121 -     * @param prop The property being deleted.
  34.122 -     */
  34.123 -    protected synchronized final void notifyPropertyDeleted(final ScriptObject object, final Property prop) {
  34.124 -        if (listeners != null) {
  34.125 -            for (PropertyListener listener : listeners.keySet()) {
  34.126 -                listener.propertyDeleted(object, prop);
  34.127 -            }
  34.128 -        }
  34.129 -    }
  34.130 -
  34.131 -    /**
  34.132 -     * This method can be called to notify property modification to this object's listeners.
  34.133 -     *
  34.134 -     * @param object The ScriptObject to which property was modified.
  34.135 -     * @param oldProp The old property being replaced.
  34.136 -     * @param newProp The new property that replaces the old property.
  34.137 -     */
  34.138 -    protected synchronized final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
  34.139 -        if (listeners != null) {
  34.140 -            for (PropertyListener listener : listeners.keySet()) {
  34.141 -                listener.propertyModified(object, oldProp, newProp);
  34.142 -            }
  34.143 -        }
  34.144 -    }
  34.145 -
  34.146 -    /**
  34.147 -     * This method can be called to notify __proto__ modification to this object's listeners.
  34.148 -     *
  34.149 -     * @param object The ScriptObject whose __proto__ was changed.
  34.150 -     * @param oldProto old __proto__
  34.151 -     * @param newProto new __proto__
  34.152 -     */
  34.153 -    protected synchronized final void notifyProtoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
  34.154 -        if (listeners != null) {
  34.155 -            for (PropertyListener listener : listeners.keySet()) {
  34.156 -                listener.protoChanged(object, oldProto, newProto);
  34.157 -            }
  34.158 -        }
  34.159 -    }
  34.160 -
  34.161 -    // PropertyListener methods
  34.162 -
  34.163 -    @Override
  34.164 -    public final void propertyAdded(final ScriptObject object, final Property prop) {
  34.165 -        notifyPropertyAdded(object, prop);
  34.166 -    }
  34.167 -
  34.168 -    @Override
  34.169 -    public final void propertyDeleted(final ScriptObject object, final Property prop) {
  34.170 -        notifyPropertyDeleted(object, prop);
  34.171 -    }
  34.172 -
  34.173 -    @Override
  34.174 -    public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
  34.175 -        notifyPropertyModified(object, oldProp, newProp);
  34.176 -    }
  34.177 -
  34.178 -    @Override
  34.179 -    public final void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
  34.180 -        notifyProtoChanged(object, oldProto, newProto);
  34.181 -    }
  34.182 -}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyListeners.java	Mon Mar 03 15:23:01 2014 +0100
    35.3 @@ -0,0 +1,222 @@
    35.4 +/*
    35.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + *
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.  Oracle designates this
   35.11 + * particular file as subject to the "Classpath" exception as provided
   35.12 + * by Oracle in the LICENSE file that accompanied this code.
   35.13 + *
   35.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.17 + * version 2 for more details (a copy is included in the LICENSE file that
   35.18 + * accompanied this code).
   35.19 + *
   35.20 + * You should have received a copy of the GNU General Public License version
   35.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.23 + *
   35.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.25 + * or visit www.oracle.com if you need additional information or have any
   35.26 + * questions.
   35.27 + */
   35.28 +
   35.29 +package jdk.nashorn.internal.runtime;
   35.30 +
   35.31 +import java.util.Map;
   35.32 +import java.util.Set;
   35.33 +import java.util.WeakHashMap;
   35.34 +
   35.35 +/**
   35.36 + * Helper class to manage property listeners and notification.
   35.37 + */
   35.38 +public class PropertyListeners {
   35.39 +
   35.40 +    private Map<String, WeakPropertyMapSet> listeners;
   35.41 +
   35.42 +    // These counters are updated in debug mode
   35.43 +    private static int listenersAdded;
   35.44 +    private static int listenersRemoved;
   35.45 +
   35.46 +    /**
   35.47 +     * Copy constructor
   35.48 +     * @param listener listener to copy
   35.49 +     */
   35.50 +    PropertyListeners(final PropertyListeners listener) {
   35.51 +        if (listener != null && listener.listeners != null) {
   35.52 +            this.listeners = new WeakHashMap<>(listener.listeners);
   35.53 +        }
   35.54 +    }
   35.55 +
   35.56 +    /**
   35.57 +     * Return aggregate listeners added to all PropertyListenerManagers
   35.58 +     * @return the listenersAdded
   35.59 +     */
   35.60 +    public static int getListenersAdded() {
   35.61 +        return listenersAdded;
   35.62 +    }
   35.63 +
   35.64 +    /**
   35.65 +     * Return aggregate listeners removed from all PropertyListenerManagers
   35.66 +     * @return the listenersRemoved
   35.67 +     */
   35.68 +    public static int getListenersRemoved() {
   35.69 +        return listenersRemoved;
   35.70 +    }
   35.71 +
   35.72 +    /**
   35.73 +     * Return listeners added to this ScriptObject.
   35.74 +     * @param obj the object
   35.75 +     * @return the listener count
   35.76 +     */
   35.77 +    public static int getListenerCount(final ScriptObject obj) {
   35.78 +        final PropertyListeners propertyListeners = obj.getMap().getListeners();
   35.79 +        if (propertyListeners != null) {
   35.80 +            return propertyListeners.listeners == null ? 0 : propertyListeners.listeners.size();
   35.81 +        }
   35.82 +        return 0;
   35.83 +    }
   35.84 +
   35.85 +    // Property listener management methods
   35.86 +
   35.87 +    /**
   35.88 +     * Add {@code propertyMap} as property listener to {@code listeners} using key {@code key} by
   35.89 +     * creating and returning a new {@code PropertyListeners} instance.
   35.90 +     *
   35.91 +     * @param listeners the original property listeners instance, may be null
   35.92 +     * @param key the property key
   35.93 +     * @param propertyMap the property map
   35.94 +     * @return the new property map
   35.95 +     */
   35.96 +    public static PropertyListeners addListener(final PropertyListeners listeners, final String key, final PropertyMap propertyMap) {
   35.97 +        final PropertyListeners newListeners;
   35.98 +        if (listeners == null || !listeners.containsListener(key, propertyMap)) {
   35.99 +            newListeners = new PropertyListeners(listeners);
  35.100 +            newListeners.addListener(key, propertyMap);
  35.101 +            return newListeners;
  35.102 +        }
  35.103 +        return listeners;
  35.104 +    }
  35.105 +
  35.106 +    /**
  35.107 +     * Checks whether {@code propertyMap} is registered as listener with {@code key}.
  35.108 +     *
  35.109 +     * @param key the property key
  35.110 +     * @param propertyMap the property map
  35.111 +     * @return true if property map is registered with property key
  35.112 +     */
  35.113 +    synchronized boolean containsListener(final String key, final PropertyMap propertyMap) {
  35.114 +        if (listeners == null) {
  35.115 +            return false;
  35.116 +        }
  35.117 +        WeakPropertyMapSet set = listeners.get(key);
  35.118 +        return set != null && set.contains(propertyMap);
  35.119 +    }
  35.120 +
  35.121 +    /**
  35.122 +     * Add a property listener to this object.
  35.123 +     *
  35.124 +     * @param propertyMap The property listener that is added.
  35.125 +     */
  35.126 +    synchronized final void addListener(final String key, final PropertyMap propertyMap) {
  35.127 +        if (Context.DEBUG) {
  35.128 +            listenersAdded++;
  35.129 +        }
  35.130 +        if (listeners == null) {
  35.131 +            listeners = new WeakHashMap<>();
  35.132 +        }
  35.133 +
  35.134 +        WeakPropertyMapSet set = listeners.get(key);
  35.135 +        if (set == null) {
  35.136 +            set = new WeakPropertyMapSet();
  35.137 +            listeners.put(key, set);
  35.138 +        }
  35.139 +        if (!set.contains(propertyMap)) {
  35.140 +            set.add(propertyMap);
  35.141 +        }
  35.142 +    }
  35.143 +
  35.144 +    /**
  35.145 +     * A new property is being added.
  35.146 +     *
  35.147 +     * @param prop The new Property added.
  35.148 +     */
  35.149 +    public synchronized void propertyAdded(final Property prop) {
  35.150 +        if (listeners != null) {
  35.151 +            WeakPropertyMapSet set = listeners.get(prop.getKey());
  35.152 +            if (set != null) {
  35.153 +                for (PropertyMap propertyMap : set.elements()) {
  35.154 +                    propertyMap.propertyAdded(prop);
  35.155 +                }
  35.156 +                listeners.remove(prop.getKey());
  35.157 +            }
  35.158 +        }
  35.159 +    }
  35.160 +
  35.161 +    /**
  35.162 +     * An existing property is being deleted.
  35.163 +     *
  35.164 +     * @param prop The property being deleted.
  35.165 +     */
  35.166 +    public synchronized void propertyDeleted(final Property prop) {
  35.167 +        if (listeners != null) {
  35.168 +            WeakPropertyMapSet set = listeners.get(prop.getKey());
  35.169 +            if (set != null) {
  35.170 +                for (PropertyMap propertyMap : set.elements()) {
  35.171 +                    propertyMap.propertyDeleted(prop);
  35.172 +                }
  35.173 +                listeners.remove(prop.getKey());
  35.174 +            }
  35.175 +        }
  35.176 +    }
  35.177 +
  35.178 +    /**
  35.179 +     * An existing Property is being replaced with a new Property.
  35.180 +     *
  35.181 +     * @param oldProp The old property that is being replaced.
  35.182 +     * @param newProp The new property that replaces the old property.
  35.183 +     *
  35.184 +     */
  35.185 +    public synchronized void propertyModified(final Property oldProp, final Property newProp) {
  35.186 +        if (listeners != null) {
  35.187 +            WeakPropertyMapSet set = listeners.get(oldProp.getKey());
  35.188 +            if (set != null) {
  35.189 +                for (PropertyMap propertyMap : set.elements()) {
  35.190 +                    propertyMap.propertyModified(oldProp, newProp);
  35.191 +                }
  35.192 +                listeners.remove(oldProp.getKey());
  35.193 +            }
  35.194 +        }
  35.195 +    }
  35.196 +
  35.197 +    public synchronized void protoChanged() {
  35.198 +        if (listeners != null) {
  35.199 +            for (WeakPropertyMapSet set : listeners.values()) {
  35.200 +                for (PropertyMap propertyMap : set.elements()) {
  35.201 +                    propertyMap.protoChanged();
  35.202 +                }
  35.203 +            }
  35.204 +            listeners.clear();
  35.205 +        }
  35.206 +    }
  35.207 +
  35.208 +    private static class WeakPropertyMapSet {
  35.209 +
  35.210 +        private WeakHashMap<PropertyMap, Boolean> map = new WeakHashMap<>();
  35.211 +
  35.212 +        void add(final PropertyMap propertyMap) {
  35.213 +            map.put(propertyMap, Boolean.TRUE);
  35.214 +        }
  35.215 +
  35.216 +        boolean contains(final PropertyMap propertyMap) {
  35.217 +            return map.containsKey(propertyMap);
  35.218 +        }
  35.219 +
  35.220 +        Set<PropertyMap> elements() {
  35.221 +            return map.keySet();
  35.222 +        }
  35.223 +
  35.224 +    }
  35.225 +}
    36.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Tue Feb 25 18:56:10 2014 +0530
    36.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Mon Mar 03 15:23:01 2014 +0100
    36.3 @@ -30,13 +30,11 @@
    36.4  import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
    36.5  
    36.6  import java.lang.invoke.SwitchPoint;
    36.7 -import java.lang.ref.WeakReference;
    36.8 +import java.lang.ref.SoftReference;
    36.9  import java.util.Arrays;
   36.10  import java.util.Collection;
   36.11  import java.util.HashMap;
   36.12  import java.util.Iterator;
   36.13 -import java.util.LinkedHashMap;
   36.14 -import java.util.Map;
   36.15  import java.util.NoSuchElementException;
   36.16  import java.util.WeakHashMap;
   36.17  
   36.18 @@ -49,17 +47,11 @@
   36.19   * All property maps are immutable. If a property is added, modified or removed, the mutator
   36.20   * will return a new map.
   36.21   */
   36.22 -public final class PropertyMap implements Iterable<Object>, PropertyListener {
   36.23 +public final class PropertyMap implements Iterable<Object> {
   36.24      /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
   36.25      public static final int NOT_EXTENSIBLE        = 0b0000_0001;
   36.26      /** Does this map contain valid array keys? */
   36.27      public static final int CONTAINS_ARRAY_KEYS   = 0b0000_0010;
   36.28 -    /** This mask is used to preserve certain flags when cloning the PropertyMap. Others should not be copied */
   36.29 -    private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111;
   36.30 -    /** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */
   36.31 -    public static final int IS_LISTENER_ADDED     = 0b0001_0000;
   36.32 -    /** Is this process wide "shared" map?. This flag is not copied when cloning a map */
   36.33 -    public static final int IS_SHARED             = 0b0010_0000;
   36.34  
   36.35      /** Map status flags. */
   36.36      private int flags;
   36.37 @@ -77,16 +69,16 @@
   36.38      private int spillLength;
   36.39  
   36.40      /** {@link SwitchPoint}s for gets on inherited properties. */
   36.41 -    private Map<String, SwitchPoint> protoGetSwitches;
   36.42 +    private HashMap<String, SwitchPoint> protoGetSwitches;
   36.43  
   36.44      /** History of maps, used to limit map duplication. */
   36.45 -    private HashMap<Property, PropertyMap> history;
   36.46 +    private WeakHashMap<Property, SoftReference<PropertyMap>> history;
   36.47  
   36.48      /** History of prototypes, used to limit map duplication. */
   36.49 -    private WeakHashMap<ScriptObject, WeakReference<PropertyMap>> protoHistory;
   36.50 +    private WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
   36.51  
   36.52 -    /** Cache for hashCode */
   36.53 -    private int hashCode;
   36.54 +    /** property listeners */
   36.55 +    private PropertyListeners listeners;
   36.56  
   36.57      /**
   36.58       * Constructor.
   36.59 @@ -119,10 +111,12 @@
   36.60       */
   36.61      private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
   36.62          this.properties   = properties;
   36.63 -        this.flags        = propertyMap.getClonedFlags();
   36.64 +        this.flags        = propertyMap.flags;
   36.65          this.spillLength  = propertyMap.spillLength;
   36.66          this.fieldCount   = propertyMap.fieldCount;
   36.67          this.fieldMaximum = propertyMap.fieldMaximum;
   36.68 +        // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
   36.69 +        this.listeners    = propertyMap.listeners;
   36.70  
   36.71          if (Context.DEBUG) {
   36.72              count++;
   36.73 @@ -203,35 +197,92 @@
   36.74      }
   36.75  
   36.76      /**
   36.77 +     * Get the listeners of this map, or null if none exists
   36.78 +     *
   36.79 +     * @return the listeners
   36.80 +     */
   36.81 +    public PropertyListeners getListeners() {
   36.82 +        return listeners;
   36.83 +    }
   36.84 +
   36.85 +    /**
   36.86 +     * Add {@code listenerMap} as a listener to this property map for the given {@code key}.
   36.87 +     *
   36.88 +     * @param key the property name
   36.89 +     * @param listenerMap the listener map
   36.90 +     */
   36.91 +    public void addListener(final String key, final PropertyMap listenerMap) {
   36.92 +        if (listenerMap != this) {
   36.93 +            // We need to clone listener instance when adding a new listener since we share
   36.94 +            // the listeners instance with our parent maps that don't need to see the new listener.
   36.95 +            listeners = PropertyListeners.addListener(listeners, key, listenerMap);
   36.96 +        }
   36.97 +    }
   36.98 +
   36.99 +    /**
  36.100 +     * A new property is being added.
  36.101 +     *
  36.102 +     * @param property The new Property added.
  36.103 +     */
  36.104 +    public void propertyAdded(final Property property) {
  36.105 +        invalidateProtoGetSwitchPoint(property);
  36.106 +        if (listeners != null) {
  36.107 +            listeners.propertyAdded(property);
  36.108 +        }
  36.109 +    }
  36.110 +
  36.111 +    /**
  36.112 +     * An existing property is being deleted.
  36.113 +     *
  36.114 +     * @param property The property being deleted.
  36.115 +     */
  36.116 +    public void propertyDeleted(final Property property) {
  36.117 +        invalidateProtoGetSwitchPoint(property);
  36.118 +        if (listeners != null) {
  36.119 +            listeners.propertyDeleted(property);
  36.120 +        }
  36.121 +    }
  36.122 +
  36.123 +    /**
  36.124 +     * An existing property is being redefined.
  36.125 +     *
  36.126 +     * @param oldProperty The old property
  36.127 +     * @param newProperty The new property
  36.128 +     */
  36.129 +    public void propertyModified(final Property oldProperty, final Property newProperty) {
  36.130 +        invalidateProtoGetSwitchPoint(oldProperty);
  36.131 +        if (listeners != null) {
  36.132 +            listeners.propertyModified(oldProperty, newProperty);
  36.133 +        }
  36.134 +    }
  36.135 +
  36.136 +    /**
  36.137 +     * The prototype of an object associated with this {@link PropertyMap} is changed.
  36.138 +     */
  36.139 +    public void protoChanged() {
  36.140 +        invalidateAllProtoGetSwitchPoints();
  36.141 +        if (listeners != null) {
  36.142 +            listeners.protoChanged();
  36.143 +        }
  36.144 +    }
  36.145 +
  36.146 +    /**
  36.147       * Return a SwitchPoint used to track changes of a property in a prototype.
  36.148       *
  36.149 -     * @param proto  Object prototype.
  36.150 -     * @param key    {@link Property} key.
  36.151 -     *
  36.152 +     * @param key Property key.
  36.153       * @return A shared {@link SwitchPoint} for the property.
  36.154       */
  36.155 -    public SwitchPoint getProtoGetSwitchPoint(final ScriptObject proto, final String key) {
  36.156 -        assert !isShared() : "proto SwitchPoint from a shared PropertyMap";
  36.157 -
  36.158 -        if (proto == null) {
  36.159 -            return null;
  36.160 +    public synchronized SwitchPoint getSwitchPoint(final String key) {
  36.161 +        if (protoGetSwitches == null) {
  36.162 +            protoGetSwitches = new HashMap<>();
  36.163          }
  36.164  
  36.165 -        if (protoGetSwitches == null) {
  36.166 -            protoGetSwitches = new HashMap<>();
  36.167 -            if (! isListenerAdded()) {
  36.168 -                proto.addPropertyListener(this);
  36.169 -                setIsListenerAdded();
  36.170 -            }
  36.171 +        SwitchPoint switchPoint = protoGetSwitches.get(key);
  36.172 +        if (switchPoint == null) {
  36.173 +            switchPoint = new SwitchPoint();
  36.174 +            protoGetSwitches.put(key, switchPoint);
  36.175          }
  36.176  
  36.177 -        if (protoGetSwitches.containsKey(key)) {
  36.178 -            return protoGetSwitches.get(key);
  36.179 -        }
  36.180 -
  36.181 -        final SwitchPoint switchPoint = new SwitchPoint();
  36.182 -        protoGetSwitches.put(key, switchPoint);
  36.183 -
  36.184          return switchPoint;
  36.185      }
  36.186  
  36.187 @@ -240,14 +291,13 @@
  36.188       *
  36.189       * @param property {@link Property} to invalidate.
  36.190       */
  36.191 -    private void invalidateProtoGetSwitchPoint(final Property property) {
  36.192 -        assert !isShared() : "proto invalidation on a shared PropertyMap";
  36.193 +    synchronized void invalidateProtoGetSwitchPoint(final Property property) {
  36.194 +        if (protoGetSwitches != null) {
  36.195  
  36.196 -        if (protoGetSwitches != null) {
  36.197              final String key = property.getKey();
  36.198              final SwitchPoint sp = protoGetSwitches.get(key);
  36.199              if (sp != null) {
  36.200 -                protoGetSwitches.put(key, new SwitchPoint());
  36.201 +                protoGetSwitches.remove(key);
  36.202                  if (Context.DEBUG) {
  36.203                      protoInvalidations++;
  36.204                  }
  36.205 @@ -257,14 +307,15 @@
  36.206      }
  36.207  
  36.208      /**
  36.209 -     * Indicate that proto itself has changed in hierachy somewhere.
  36.210 +     * Indicate that proto itself has changed in hierarchy somewhere.
  36.211       */
  36.212 -    private void invalidateAllProtoGetSwitchPoints() {
  36.213 -        assert !isShared() : "proto invalidation on a shared PropertyMap";
  36.214 -
  36.215 -        if (protoGetSwitches != null) {
  36.216 -            final Collection<SwitchPoint> sws = protoGetSwitches.values();
  36.217 -            SwitchPoint.invalidateAll(sws.toArray(new SwitchPoint[sws.size()]));
  36.218 +    synchronized void invalidateAllProtoGetSwitchPoints() {
  36.219 +        if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) {
  36.220 +            if (Context.DEBUG) {
  36.221 +                protoInvalidations += protoGetSwitches.size();
  36.222 +            }
  36.223 +            SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()]));
  36.224 +            protoGetSwitches.clear();
  36.225          }
  36.226      }
  36.227  
  36.228 @@ -279,7 +330,33 @@
  36.229       * @return New {@link PropertyMap} with {@link Property} added.
  36.230       */
  36.231      PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
  36.232 -        return addProperty(new AccessorProperty(property, bindTo));
  36.233 +        // No need to store bound property in the history as bound properties can't be reused.
  36.234 +        return addPropertyNoHistory(new AccessorProperty(property, bindTo));
  36.235 +    }
  36.236 +
  36.237 +    /**
  36.238 +     * Add a property to the map without adding it to the history. This should be used for properties that
  36.239 +     * can't be shared such as bound properties, or properties that are expected to be added only once.
  36.240 +     *
  36.241 +     * @param property {@link Property} being added.
  36.242 +     * @return New {@link PropertyMap} with {@link Property} added.
  36.243 +     */
  36.244 +    public PropertyMap addPropertyNoHistory(final Property property) {
  36.245 +        if (listeners != null) {
  36.246 +            listeners.propertyAdded(property);
  36.247 +        }
  36.248 +        final PropertyHashMap newProperties = properties.immutableAdd(property);
  36.249 +        final PropertyMap newMap = new PropertyMap(this, newProperties);
  36.250 +
  36.251 +        if(!property.isSpill()) {
  36.252 +            newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
  36.253 +        }
  36.254 +        if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
  36.255 +            newMap.setContainsArrayKeys();
  36.256 +        }
  36.257 +
  36.258 +        newMap.spillLength += property.getSpillCount();
  36.259 +        return newMap;
  36.260      }
  36.261  
  36.262      /**
  36.263 @@ -290,6 +367,9 @@
  36.264       * @return New {@link PropertyMap} with {@link Property} added.
  36.265       */
  36.266      public PropertyMap addProperty(final Property property) {
  36.267 +        if (listeners != null) {
  36.268 +            listeners.propertyAdded(property);
  36.269 +        }
  36.270          PropertyMap newMap = checkHistory(property);
  36.271  
  36.272          if (newMap == null) {
  36.273 @@ -318,6 +398,9 @@
  36.274       * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
  36.275       */
  36.276      public PropertyMap deleteProperty(final Property property) {
  36.277 +        if (listeners != null) {
  36.278 +            listeners.propertyDeleted(property);
  36.279 +        }
  36.280          PropertyMap newMap = checkHistory(property);
  36.281          final String key = property.getKey();
  36.282  
  36.283 @@ -339,6 +422,9 @@
  36.284       * @return New {@link PropertyMap} with {@link Property} replaced.
  36.285       */
  36.286      PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
  36.287 +        if (listeners != null) {
  36.288 +            listeners.propertyModified(oldProperty, newProperty);
  36.289 +        }
  36.290          // Add replaces existing property.
  36.291          final PropertyHashMap newProperties = properties.immutableAdd(newProperty);
  36.292          final PropertyMap newMap = new PropertyMap(this, newProperties);
  36.293 @@ -363,7 +449,7 @@
  36.294                  (oldProperty instanceof AccessorProperty &&
  36.295                  newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted";
  36.296  
  36.297 -        newMap.flags = getClonedFlags();
  36.298 +        newMap.flags = flags;
  36.299  
  36.300          /*
  36.301           * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
  36.302 @@ -491,28 +577,6 @@
  36.303      }
  36.304  
  36.305      /**
  36.306 -     * Make this property map 'shared' one. Shared property map instances are
  36.307 -     * process wide singleton objects. A shaped map should never be added as a listener
  36.308 -     * to a proto object. Nor it should have history or proto history. A shared map
  36.309 -     * is just a template that is meant to be duplicated before use. All nasgen initialized
  36.310 -     * property maps are shared.
  36.311 -     *
  36.312 -     * @return this map after making it as shared
  36.313 -     */
  36.314 -    public PropertyMap setIsShared() {
  36.315 -        assert !isListenerAdded() : "making PropertyMap shared after listener added";
  36.316 -        assert protoHistory == null : "making PropertyMap shared after associating a proto with it";
  36.317 -        if (Context.DEBUG) {
  36.318 -            sharedCount++;
  36.319 -        }
  36.320 -
  36.321 -        flags |= IS_SHARED;
  36.322 -        // clear any history on this PropertyMap, won't be used.
  36.323 -        history = null;
  36.324 -        return this;
  36.325 -    }
  36.326 -
  36.327 -    /**
  36.328       * Check for any configurable properties.
  36.329       *
  36.330       * @return {@code true} if any configurable.
  36.331 @@ -551,14 +615,14 @@
  36.332      /**
  36.333       * Check prototype history for an existing property map with specified prototype.
  36.334       *
  36.335 -     * @param newProto New prototype object.
  36.336 +     * @param parentMap New prototype object.
  36.337       *
  36.338       * @return Existing {@link PropertyMap} or {@code null} if not found.
  36.339       */
  36.340 -    private PropertyMap checkProtoHistory(final ScriptObject newProto) {
  36.341 +    private PropertyMap checkProtoHistory(final PropertyMap parentMap) {
  36.342          final PropertyMap cachedMap;
  36.343          if (protoHistory != null) {
  36.344 -            final WeakReference<PropertyMap> weakMap = protoHistory.get(newProto);
  36.345 +            final SoftReference<PropertyMap> weakMap = protoHistory.get(parentMap);
  36.346              cachedMap = (weakMap != null ? weakMap.get() : null);
  36.347          } else {
  36.348              cachedMap = null;
  36.349 @@ -574,17 +638,15 @@
  36.350      /**
  36.351       * Add a map to the prototype history.
  36.352       *
  36.353 -     * @param newProto Prototype to add (key.)
  36.354 +     * @param parentMap Prototype to add (key.)
  36.355       * @param newMap   {@link PropertyMap} associated with prototype.
  36.356       */
  36.357 -    private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
  36.358 -        assert !isShared() : "proto history modified on a shared PropertyMap";
  36.359 -
  36.360 +    private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) {
  36.361          if (protoHistory == null) {
  36.362              protoHistory = new WeakHashMap<>();
  36.363          }
  36.364  
  36.365 -        protoHistory.put(newProto, new WeakReference<>(newMap));
  36.366 +        protoHistory.put(parentMap, new SoftReference<>(newMap));
  36.367      }
  36.368  
  36.369      /**
  36.370 @@ -594,14 +656,12 @@
  36.371       * @param newMap   Modified {@link PropertyMap}.
  36.372       */
  36.373      private void addToHistory(final Property property, final PropertyMap newMap) {
  36.374 -        assert !isShared() : "history modified on a shared PropertyMap";
  36.375 -
  36.376          if (!properties.isEmpty()) {
  36.377              if (history == null) {
  36.378 -                history = new LinkedHashMap<>();
  36.379 +                history = new WeakHashMap<>();
  36.380              }
  36.381  
  36.382 -            history.put(property, newMap);
  36.383 +            history.put(property, new SoftReference<>(newMap));
  36.384          }
  36.385      }
  36.386  
  36.387 @@ -613,8 +673,10 @@
  36.388       * @return Existing map or {@code null} if not found.
  36.389       */
  36.390      private PropertyMap checkHistory(final Property property) {
  36.391 +
  36.392          if (history != null) {
  36.393 -            PropertyMap historicMap = history.get(property);
  36.394 +            SoftReference<PropertyMap> ref = history.get(property);
  36.395 +            final PropertyMap historicMap = ref == null ? null : ref.get();
  36.396  
  36.397              if (historicMap != null) {
  36.398                  if (Context.DEBUG) {
  36.399 @@ -628,54 +690,6 @@
  36.400          return null;
  36.401      }
  36.402  
  36.403 -    /**
  36.404 -     * Calculate the hash code for the map.
  36.405 -     *
  36.406 -     * @return Computed hash code.
  36.407 -     */
  36.408 -    private int computeHashCode() {
  36.409 -        int hash = 0;
  36.410 -
  36.411 -        for (final Property property : getProperties()) {
  36.412 -            hash = hash << 7 ^ hash >> 7;
  36.413 -            hash ^= property.hashCode();
  36.414 -        }
  36.415 -
  36.416 -        return hash;
  36.417 -    }
  36.418 -
  36.419 -    @Override
  36.420 -    public int hashCode() {
  36.421 -        if (hashCode == 0 && !properties.isEmpty()) {
  36.422 -            hashCode = computeHashCode();
  36.423 -        }
  36.424 -        return hashCode;
  36.425 -    }
  36.426 -
  36.427 -    @Override
  36.428 -    public boolean equals(final Object other) {
  36.429 -        if (!(other instanceof PropertyMap)) {
  36.430 -            return false;
  36.431 -        }
  36.432 -
  36.433 -        final PropertyMap otherMap = (PropertyMap)other;
  36.434 -
  36.435 -        if (properties.size() != otherMap.properties.size()) {
  36.436 -            return false;
  36.437 -        }
  36.438 -
  36.439 -        final Iterator<Property> iter      = properties.values().iterator();
  36.440 -        final Iterator<Property> otherIter = otherMap.properties.values().iterator();
  36.441 -
  36.442 -        while (iter.hasNext() && otherIter.hasNext()) {
  36.443 -            if (!iter.next().equals(otherIter.next())) {
  36.444 -                return false;
  36.445 -            }
  36.446 -        }
  36.447 -
  36.448 -        return true;
  36.449 -    }
  36.450 -
  36.451      @Override
  36.452      public String toString() {
  36.453          final StringBuilder sb = new StringBuilder();
  36.454 @@ -728,24 +742,6 @@
  36.455      }
  36.456  
  36.457      /**
  36.458 -     * Check whether a {@link PropertyListener} has been added to this map.
  36.459 -     *
  36.460 -     * @return {@code true} if {@link PropertyListener} exists
  36.461 -     */
  36.462 -    public boolean isListenerAdded() {
  36.463 -        return (flags & IS_LISTENER_ADDED) != 0;
  36.464 -    }
  36.465 -
  36.466 -    /**
  36.467 -     * Check if this map shared or not.
  36.468 -     *
  36.469 -     * @return true if this map is shared.
  36.470 -     */
  36.471 -    public boolean isShared() {
  36.472 -        return (flags & IS_SHARED) != 0;
  36.473 -    }
  36.474 -
  36.475 -    /**
  36.476       * Test to see if {@link PropertyMap} is extensible.
  36.477       *
  36.478       * @return {@code true} if {@link PropertyMap} can be added to.
  36.479 @@ -800,50 +796,29 @@
  36.480      }
  36.481  
  36.482      /**
  36.483 -     * Change the prototype of objects associated with this {@link PropertyMap}.
  36.484 +     * Return a property map with the same layout that is associated with the new prototype object.
  36.485       *
  36.486 -     * @param oldProto Current prototype object.
  36.487       * @param newProto New prototype object to replace oldProto.
  36.488 -     *
  36.489       * @return New {@link PropertyMap} with prototype changed.
  36.490       */
  36.491 -    PropertyMap changeProto(final ScriptObject oldProto, final ScriptObject newProto) {
  36.492 -        assert !isShared() : "proto associated with a shared PropertyMap";
  36.493 +    public PropertyMap changeProto(final ScriptObject newProto) {
  36.494  
  36.495 -        if (oldProto == newProto) {
  36.496 -            return this;
  36.497 -        }
  36.498 -
  36.499 -        final PropertyMap nextMap = checkProtoHistory(newProto);
  36.500 +        final PropertyMap parentMap = newProto == null ? null : newProto.getMap();
  36.501 +        final PropertyMap nextMap = checkProtoHistory(parentMap);
  36.502          if (nextMap != null) {
  36.503              return nextMap;
  36.504          }
  36.505  
  36.506          if (Context.DEBUG) {
  36.507 -            incrementSetProtoNewMapCount();
  36.508 +            setProtoNewMapCount++;
  36.509          }
  36.510  
  36.511          final PropertyMap newMap = new PropertyMap(this);
  36.512 -        addToProtoHistory(newProto, newMap);
  36.513 +        addToProtoHistory(parentMap, newMap);
  36.514  
  36.515          return newMap;
  36.516      }
  36.517  
  36.518 -    /**
  36.519 -     * Indicate that the map has listeners.
  36.520 -     */
  36.521 -    private void setIsListenerAdded() {
  36.522 -        flags |= IS_LISTENER_ADDED;
  36.523 -    }
  36.524 -
  36.525 -    /**
  36.526 -     * Return only the flags that should be copied during cloning.
  36.527 -     *
  36.528 -     * @return Subset of flags that should be copied.
  36.529 -     */
  36.530 -    private int getClonedFlags() {
  36.531 -        return flags & CLONEABLE_FLAGS_MASK;
  36.532 -    }
  36.533  
  36.534      /**
  36.535       * {@link PropertyMap} iterator.
  36.536 @@ -900,41 +875,12 @@
  36.537      }
  36.538  
  36.539      /*
  36.540 -     * PropertyListener implementation.
  36.541 -     */
  36.542 -
  36.543 -    @Override
  36.544 -    public void propertyAdded(final ScriptObject object, final Property prop) {
  36.545 -        invalidateProtoGetSwitchPoint(prop);
  36.546 -    }
  36.547 -
  36.548 -    @Override
  36.549 -    public void propertyDeleted(final ScriptObject object, final Property prop) {
  36.550 -        invalidateProtoGetSwitchPoint(prop);
  36.551 -    }
  36.552 -
  36.553 -    @Override
  36.554 -    public void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
  36.555 -        invalidateProtoGetSwitchPoint(oldProp);
  36.556 -    }
  36.557 -
  36.558 -    @Override
  36.559 -    public void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
  36.560 -        // We may walk and invalidate SwitchPoints for properties inherited
  36.561 -        // from 'object' or it's old proto chain. But, it may not be worth it.
  36.562 -        // For example, a new proto may have a user defined getter/setter for
  36.563 -        // a data property down the chain. So, invalidating all is better.
  36.564 -        invalidateAllProtoGetSwitchPoints();
  36.565 -    }
  36.566 -
  36.567 -    /*
  36.568       * Debugging and statistics.
  36.569       */
  36.570  
  36.571      // counters updated only in debug mode
  36.572      private static int count;
  36.573      private static int clonedCount;
  36.574 -    private static int sharedCount;
  36.575      private static int duplicatedCount;
  36.576      private static int historyHit;
  36.577      private static int protoInvalidations;
  36.578 @@ -956,13 +902,6 @@
  36.579      }
  36.580  
  36.581      /**
  36.582 -     * @return The number of maps that are shared.
  36.583 -     */
  36.584 -    public static int getSharedCount() {
  36.585 -        return sharedCount;
  36.586 -    }
  36.587 -
  36.588 -    /**
  36.589       * @return The number of maps that are duplicated.
  36.590       */
  36.591      public static int getDuplicatedCount() {
  36.592 @@ -997,10 +936,4 @@
  36.593          return setProtoNewMapCount;
  36.594      }
  36.595  
  36.596 -    /**
  36.597 -     * Increment the prototype set count.
  36.598 -     */
  36.599 -    private static void incrementSetProtoNewMapCount() {
  36.600 -        setProtoNewMapCount++;
  36.601 -    }
  36.602  }
    37.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Tue Feb 25 18:56:10 2014 +0530
    37.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Mon Mar 03 15:23:01 2014 +0100
    37.3 @@ -160,10 +160,10 @@
    37.4      }
    37.5  
    37.6      @Override
    37.7 -    ScriptObject allocate() {
    37.8 +    ScriptObject allocate(final PropertyMap map) {
    37.9          try {
   37.10              ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
   37.11 -            return allocator == null ? null : (ScriptObject)allocator.invokeExact(allocatorMap);
   37.12 +            return allocator == null ? null : (ScriptObject)allocator.invokeExact(map);
   37.13          } catch (final RuntimeException | Error e) {
   37.14              throw e;
   37.15          } catch (final Throwable t) {
   37.16 @@ -178,6 +178,11 @@
   37.17      }
   37.18  
   37.19      @Override
   37.20 +    PropertyMap getAllocatorMap() {
   37.21 +        return allocatorMap;
   37.22 +    }
   37.23 +
   37.24 +    @Override
   37.25      protected synchronized void ensureCodeGenerated() {
   37.26           if (!code.isEmpty()) {
   37.27               return; // nothing to do, we have code, at least some.
    38.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Tue Feb 25 18:56:10 2014 +0530
    38.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Mon Mar 03 15:23:01 2014 +0100
    38.3 @@ -80,6 +80,9 @@
    38.4  
    38.5      private final ScriptFunctionData data;
    38.6  
    38.7 +    /** The property map used for newly allocated object when function is used as constructor. */
    38.8 +    protected PropertyMap allocatorMap;
    38.9 +
   38.10      /**
   38.11       * Constructor
   38.12       *
   38.13 @@ -125,6 +128,7 @@
   38.14  
   38.15          this.data  = data;
   38.16          this.scope = scope;
   38.17 +        this.allocatorMap = data.getAllocatorMap();
   38.18      }
   38.19  
   38.20      @Override
   38.21 @@ -229,16 +233,16 @@
   38.22          }
   38.23          assert !isBoundFunction(); // allocate never invoked on bound functions
   38.24  
   38.25 -        final ScriptObject object = data.allocate();
   38.26 +        final ScriptObject object = data.allocate(allocatorMap);
   38.27  
   38.28          if (object != null) {
   38.29              Object prototype = getPrototype();
   38.30              if (prototype instanceof ScriptObject) {
   38.31 -                object.setProto((ScriptObject)prototype);
   38.32 +                object.setInitialProto((ScriptObject)prototype);
   38.33              }
   38.34  
   38.35              if (object.getProto() == null) {
   38.36 -                object.setProto(getObjectPrototype());
   38.37 +                object.setInitialProto(getObjectPrototype());
   38.38              }
   38.39          }
   38.40  
    39.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Tue Feb 25 18:56:10 2014 +0530
    39.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Mon Mar 03 15:23:01 2014 +0100
    39.3 @@ -229,9 +229,20 @@
    39.4  
    39.5      /**
    39.6       * Allocates an object using this function's allocator.
    39.7 +     *
    39.8 +     * @param map the property map for the allocated object.
    39.9       * @return the object allocated using this function's allocator, or null if the function doesn't have an allocator.
   39.10       */
   39.11 -    ScriptObject allocate() {
   39.12 +    ScriptObject allocate(final PropertyMap map) {
   39.13 +        return null;
   39.14 +    }
   39.15 +
   39.16 +    /**
   39.17 +     * Get the property map to use for objects allocated by this function.
   39.18 +     *
   39.19 +     * @return the property map for allocated objects.
   39.20 +     */
   39.21 +    PropertyMap getAllocatorMap() {
   39.22          return null;
   39.23      }
   39.24  
    40.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Feb 25 18:56:10 2014 +0530
    40.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Mar 03 15:23:01 2014 +0100
    40.3 @@ -43,6 +43,7 @@
    40.4  import java.lang.invoke.MethodHandle;
    40.5  import java.lang.invoke.MethodHandles;
    40.6  import java.lang.invoke.MethodType;
    40.7 +import java.lang.invoke.SwitchPoint;
    40.8  import java.util.AbstractMap;
    40.9  import java.util.ArrayList;
   40.10  import java.util.Arrays;
   40.11 @@ -88,7 +89,7 @@
   40.12   * </ul>
   40.13   */
   40.14  
   40.15 -public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess {
   40.16 +public abstract class ScriptObject implements PropertyAccess {
   40.17      /** __proto__ special property name */
   40.18      public static final String PROTO_PROPERTY_NAME   = "__proto__";
   40.19  
   40.20 @@ -107,9 +108,6 @@
   40.21      /** Per ScriptObject flag - is this an arguments object? */
   40.22      public static final int IS_ARGUMENTS   = 0b0000_0100;
   40.23  
   40.24 -    /** Is this a prototype PropertyMap? */
   40.25 -    public static final int IS_PROTOTYPE   = 0b0000_1000;
   40.26 -
   40.27      /** Is length property not-writable? */
   40.28      public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000;
   40.29  
   40.30 @@ -155,7 +153,7 @@
   40.31      public static final Call GET_PROTO          = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
   40.32  
   40.33      /** Method handle for setting the proto of a ScriptObject */
   40.34 -    public static final Call SET_PROTO          = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class);
   40.35 +    public static final Call SET_PROTO          = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
   40.36  
   40.37      /** Method handle for setting the proto of a ScriptObject after checking argument */
   40.38      public static final Call SET_PROTO_CHECK    = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class);
   40.39 @@ -201,10 +199,6 @@
   40.40          this.arrayData = ArrayData.EMPTY_ARRAY;
   40.41          this.setMap(map == null ? PropertyMap.newMap() : map);
   40.42          this.proto = proto;
   40.43 -
   40.44 -        if (proto != null) {
   40.45 -            proto.setIsPrototype();
   40.46 -        }
   40.47      }
   40.48  
   40.49      /**
   40.50 @@ -232,7 +226,7 @@
   40.51              if (oldProp == null) {
   40.52                  if (property instanceof UserAccessorProperty) {
   40.53                      final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
   40.54 -                    newMap = newMap.addProperty(prop);
   40.55 +                    newMap = newMap.addPropertyNoHistory(prop);
   40.56                  } else {
   40.57                      newMap = newMap.addPropertyBind((AccessorProperty)property, source);
   40.58                  }
   40.59 @@ -875,8 +869,6 @@
   40.60              newProperty = newUserAccessors(oldProperty.getKey(), propertyFlags, getter, setter);
   40.61          }
   40.62  
   40.63 -        notifyPropertyModified(this, oldProperty, newProperty);
   40.64 -
   40.65          return modifyOwnProperty(oldProperty, newProperty);
   40.66      }
   40.67  
   40.68 @@ -1120,26 +1112,30 @@
   40.69       */
   40.70      public synchronized final void setProto(final ScriptObject newProto) {
   40.71          final ScriptObject oldProto = proto;
   40.72 -        map = map.changeProto(oldProto, newProto);
   40.73 -
   40.74 -        if (newProto != null) {
   40.75 -            newProto.setIsPrototype();
   40.76 +
   40.77 +        if (oldProto != newProto) {
   40.78 +            proto = newProto;
   40.79 +
   40.80 +            // Let current listeners know that the protototype has changed and set our map
   40.81 +            final PropertyListeners listeners = getMap().getListeners();
   40.82 +            if (listeners != null) {
   40.83 +                listeners.protoChanged();
   40.84 +            }
   40.85 +            // Replace our current allocator map with one that is associated with the new prototype.
   40.86 +            setMap(getMap().changeProto(newProto));
   40.87          }
   40.88 -
   40.89 -        proto = newProto;
   40.90 -
   40.91 -        if (isPrototype()) {
   40.92 -            // tell listeners that my __proto__ has been changed
   40.93 -            notifyProtoChanged(this, oldProto, newProto);
   40.94 -
   40.95 -            if (oldProto != null) {
   40.96 -                oldProto.removePropertyListener(this);
   40.97 -            }
   40.98 -
   40.99 -            if (newProto != null) {
  40.100 -                newProto.addPropertyListener(this);
  40.101 -            }
  40.102 -        }
  40.103 +    }
  40.104 +
  40.105 +    /**
  40.106 +     * Set the initial __proto__ of this object. This should be used instead of
  40.107 +     * {@link #setProto} if it is known that the current property map will not be
  40.108 +     * used on a new object with any other parent property map, so we can pass over
  40.109 +     * property map invalidation/evolution.
  40.110 +     *
  40.111 +     * @param initialProto the initial __proto__ to set.
  40.112 +     */
  40.113 +    public void setInitialProto(final ScriptObject initialProto) {
  40.114 +        this.proto = initialProto;
  40.115      }
  40.116  
  40.117      /**
  40.118 @@ -1332,25 +1328,6 @@
  40.119      }
  40.120  
  40.121      /**
  40.122 -     * Check if this object is a prototype
  40.123 -     *
  40.124 -     * @return {@code true} if is prototype
  40.125 -     */
  40.126 -    public final boolean isPrototype() {
  40.127 -        return (flags & IS_PROTOTYPE) != 0;
  40.128 -    }
  40.129 -
  40.130 -    /**
  40.131 -     * Flag this object as having a prototype.
  40.132 -     */
  40.133 -    public final void setIsPrototype() {
  40.134 -        if (proto != null && !isPrototype()) {
  40.135 -            proto.addPropertyListener(this);
  40.136 -        }
  40.137 -        flags |= IS_PROTOTYPE;
  40.138 -    }
  40.139 -
  40.140 -    /**
  40.141       * Check if this object has non-writable length property
  40.142       *
  40.143       * @return {@code true} if 'length' property is non-writable
  40.144 @@ -1791,6 +1768,7 @@
  40.145          final boolean noGuard = ObjectClassGenerator.OBJECT_FIELDS_ONLY && NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType();
  40.146          // getMap() is fine as we have the prototype switchpoint depending on where the property was found
  40.147          final MethodHandle guard = noGuard ? null : NashornGuards.getMapGuard(getMap());
  40.148 +        final ScriptObject owner = find.getOwner();
  40.149  
  40.150          if (methodHandle != null) {
  40.151              assert methodHandle.type().returnType().equals(returnType);
  40.152 @@ -1798,18 +1776,18 @@
  40.153                  return new GuardedInvocation(methodHandle, guard);
  40.154              }
  40.155  
  40.156 -            if (!property.hasGetterFunction(find.getOwner())) {
  40.157 +            if (!property.hasGetterFunction(owner)) {
  40.158                  // If not a scope bind to actual prototype as changing prototype will change the property map.
  40.159                  // For scopes we install a filter that replaces the self object with the prototype owning the property.
  40.160                  methodHandle = isScope() ?
  40.161                          addProtoFilter(methodHandle, find.getProtoChainLength()) :
  40.162 -                        bindTo(methodHandle, find.getOwner());
  40.163 +                        bindTo(methodHandle, owner);
  40.164              }
  40.165 -            return new GuardedInvocation(methodHandle, noGuard ? null : getMap().getProtoGetSwitchPoint(proto, name), guard);
  40.166 +            return new GuardedInvocation(methodHandle, noGuard ? null : getProtoSwitchPoint(name, owner), guard);
  40.167          }
  40.168  
  40.169          assert !NashornCallSiteDescriptor.isFastScope(desc);
  40.170 -        return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard);
  40.171 +        return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
  40.172      }
  40.173  
  40.174      private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
  40.175 @@ -1866,6 +1844,28 @@
  40.176      }
  40.177  
  40.178      /**
  40.179 +     * Get a switch point for a property with the given {@code name} that will be invalidated when
  40.180 +     * the property definition is changed in this object's prototype chain. Returns {@code null} if
  40.181 +     * the property is defined in this object itself.
  40.182 +     *
  40.183 +     * @param name the property name
  40.184 +     * @param owner the property owner, null if property is not defined
  40.185 +     * @return a SwitchPoint or null
  40.186 +     */
  40.187 +    public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) {
  40.188 +        if (owner == this || getProto() == null) {
  40.189 +            return null;
  40.190 +        }
  40.191 +
  40.192 +        for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
  40.193 +            ScriptObject parent = obj.getProto();
  40.194 +            parent.getMap().addListener(name, obj.getMap());
  40.195 +        }
  40.196 +
  40.197 +        return getMap().getSwitchPoint(name);
  40.198 +    }
  40.199 +
  40.200 +    /**
  40.201       * Find the appropriate SET method for an invoke dynamic call.
  40.202       *
  40.203       * @param desc    the call site descriptor
  40.204 @@ -1921,8 +1921,7 @@
  40.205                 throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString((this)));
  40.206             }
  40.207             assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
  40.208 -           final PropertyMap myMap = getMap();
  40.209 -           return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(myMap));
  40.210 +           return new GuardedInvocation(Lookup.EMPTY_SETTER, getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
  40.211      }
  40.212  
  40.213      @SuppressWarnings("unused")
  40.214 @@ -2082,7 +2081,7 @@
  40.215                      methodHandle = bindTo(methodHandle, UNDEFINED);
  40.216                  }
  40.217                  return new GuardedInvocation(methodHandle,
  40.218 -                        find.isInherited()? getMap().getProtoGetSwitchPoint(proto, NO_SUCH_PROPERTY_NAME) : null,
  40.219 +                        getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
  40.220                          getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func));
  40.221              }
  40.222          }
  40.223 @@ -2134,7 +2133,8 @@
  40.224      }
  40.225  
  40.226      private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
  40.227 -        return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap()));
  40.228 +        return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
  40.229 +                getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
  40.230      }
  40.231  
  40.232      private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
  40.233 @@ -2215,12 +2215,10 @@
  40.234  
  40.235          if (fieldCount < fieldMaximum) {
  40.236              property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount);
  40.237 -            notifyPropertyAdded(this, property);
  40.238              property = addOwnProperty(property);
  40.239          } else {
  40.240              int i = getMap().getSpillLength();
  40.241              property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i);
  40.242 -            notifyPropertyAdded(this, property);
  40.243              property = addOwnProperty(property);
  40.244              i = property.getSlot();
  40.245  
  40.246 @@ -3274,7 +3272,6 @@
  40.247          }
  40.248  
  40.249          final Property prop = find.getProperty();
  40.250 -        notifyPropertyDeleted(this, prop);
  40.251          deleteOwnProperty(prop);
  40.252  
  40.253          return true;
    41.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Tue Feb 25 18:56:10 2014 +0530
    41.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Mon Mar 03 15:23:01 2014 +0100
    41.3 @@ -80,7 +80,7 @@
    41.4      }
    41.5  
    41.6      /**
    41.7 -     * This class encapsulates the results of looking up a setter method; it's basically a triple of a method hanle,
    41.8 +     * This class encapsulates the results of looking up a setter method; it's basically a triple of a method handle,
    41.9       * a Property object, and flags for invocation.
   41.10       *
   41.11       */
   41.12 @@ -170,7 +170,10 @@
   41.13  
   41.14      private SetMethod createNewPropertySetter() {
   41.15          final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter();
   41.16 -        sobj.notifyPropertyAdded(sobj, sm.property);
   41.17 +        final PropertyListeners listeners = map.getListeners();
   41.18 +        if (listeners != null) {
   41.19 +            listeners.propertyAdded(sm.property);
   41.20 +        }
   41.21          return sm;
   41.22      }
   41.23  
    42.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java	Tue Feb 25 18:56:10 2014 +0530
    42.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java	Mon Mar 03 15:23:01 2014 +0100
    42.3 @@ -36,6 +36,7 @@
    42.4  import jdk.internal.dynalink.linker.LinkRequest;
    42.5  import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
    42.6  import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
    42.7 +import jdk.nashorn.internal.runtime.linker.NashornGuards;
    42.8  
    42.9  /**
   42.10   * This class supports the handling of scope in a with body.
   42.11 @@ -123,7 +124,7 @@
   42.12          }
   42.13  
   42.14          if (find != null) {
   42.15 -            return fixScopeCallSite(scope.lookup(desc, request), name);
   42.16 +            return fixScopeCallSite(scope.lookup(desc, request), name, find.getOwner());
   42.17          }
   42.18  
   42.19          // the property is not found - now check for
   42.20 @@ -175,7 +176,7 @@
   42.21          link = scope.lookup(desc, request);
   42.22  
   42.23          if (link != null) {
   42.24 -            return fixScopeCallSite(link, name);
   42.25 +            return fixScopeCallSite(link, name, null);
   42.26          }
   42.27  
   42.28          return null;
   42.29 @@ -252,13 +253,10 @@
   42.30                  filterGuard(link, WITHEXPRESSIONFILTER));
   42.31      }
   42.32  
   42.33 -    private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name) {
   42.34 +    private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) {
   42.35          final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER);
   42.36          return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER),
   42.37 -            MH.guardWithTest(
   42.38 -                expressionGuard(name),
   42.39 -                filterGuard(newLink, WITHSCOPEFILTER),
   42.40 -                MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class)));
   42.41 +                NashornGuards.combineGuards(expressionGuard(name, owner), filterGuard(newLink, WITHSCOPEFILTER)));
   42.42      }
   42.43  
   42.44      private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) {
   42.45 @@ -288,9 +286,9 @@
   42.46          return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]);
   42.47      }
   42.48  
   42.49 -    private MethodHandle expressionGuard(final String name) {
   42.50 +    private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
   42.51          final PropertyMap map = expression.getMap();
   42.52 -        final SwitchPoint sp = map.getProtoGetSwitchPoint(expression.getProto(), name);
   42.53 +        final SwitchPoint sp = expression.getProtoSwitchPoint(name, owner);
   42.54          return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp);
   42.55      }
   42.56  
    43.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java	Tue Feb 25 18:56:10 2014 +0530
    43.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java	Mon Mar 03 15:23:01 2014 +0100
    43.3 @@ -37,10 +37,10 @@
    43.4   * Constructor of method handles used to guard call sites.
    43.5   */
    43.6  public final class NashornGuards {
    43.7 -    private static final MethodHandle IS_SCRIPTOBJECT          = findOwnMH("isScriptObject", boolean.class, Object.class);
    43.8 -    private static final MethodHandle IS_SCRIPTFUNCTION        = findOwnMH("isScriptFunction", boolean.class, Object.class);
    43.9 -    private static final MethodHandle IS_MAP                   = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
   43.10 -    private static final MethodHandle IS_INSTANCEOF_2          = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
   43.11 +    private static final MethodHandle IS_SCRIPTOBJECT   = findOwnMH("isScriptObject", boolean.class, Object.class);
   43.12 +    private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
   43.13 +    private static final MethodHandle IS_MAP            = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
   43.14 +    private static final MethodHandle IS_INSTANCEOF_2   = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
   43.15  
   43.16      // don't create me!
   43.17      private NashornGuards() {
   43.18 @@ -85,6 +85,17 @@
   43.19          return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2);
   43.20      }
   43.21  
   43.22 +    /**
   43.23 +     * Combine two method handles of type {@code (Object)boolean} using logical AND.
   43.24 +     *
   43.25 +     * @param guard1 the first guard
   43.26 +     * @param guard2 the second guard, only invoked if guard1 returns true
   43.27 +     * @return true if both guard1 and guard2 returned true
   43.28 +     */
   43.29 +    public static MethodHandle combineGuards(final MethodHandle guard1, final MethodHandle guard2) {
   43.30 +        return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class));
   43.31 +    }
   43.32 +
   43.33      @SuppressWarnings("unused")
   43.34      private static boolean isScriptObject(final Object self) {
   43.35          return self instanceof ScriptObject;
    44.1 --- a/src/jdk/nashorn/internal/scripts/JO.java	Tue Feb 25 18:56:10 2014 +0530
    44.2 +++ b/src/jdk/nashorn/internal/scripts/JO.java	Mon Mar 03 15:23:01 2014 +0100
    44.3 @@ -33,7 +33,7 @@
    44.4   */
    44.5  public class JO extends ScriptObject {
    44.6  
    44.7 -    private static final PropertyMap map$ = PropertyMap.newMap().setIsShared();
    44.8 +    private static final PropertyMap map$ = PropertyMap.newMap();
    44.9  
   44.10      /**
   44.11       * Returns the initial property map to be used.

mercurial