Mon, 03 Mar 2014 15:23:01 +0100
8035948: Redesign property listeners for shared classes
Reviewed-by: sundar, lagergren
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.