Wed, 26 Jun 2013 08:36:53 -0300
8008458: Strict functions dont share property map
Reviewed-by: sundar, hannesw
Contributed-by: james.laskey@oracle.com
1.1 --- a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java Wed Jun 26 16:36:13 2013 +0530 1.2 +++ b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java Wed Jun 26 08:36:53 2013 -0300 1.3 @@ -57,8 +57,10 @@ 1.4 PropertyMap map = PropertyMap.newMap(NativeStrictArguments.class); 1.5 map = Lookup.newProperty(map, "length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH); 1.6 // In strict mode, the caller and callee properties should throw TypeError 1.7 - map = ScriptFunctionImpl.newThrowerProperty(map, "caller"); 1.8 - map = ScriptFunctionImpl.newThrowerProperty(map, "callee"); 1.9 + // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. 1.10 + final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; 1.11 + map = map.addProperty(map.newUserAccessors("caller", flags)); 1.12 + map = map.addProperty(map.newUserAccessors("callee", flags)); 1.13 nasgenmap$ = map; 1.14 } 1.15
2.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Jun 26 16:36:13 2013 +0530 2.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Jun 26 08:36:53 2013 -0300 2.3 @@ -155,8 +155,12 @@ 2.4 Lookup.TYPE_ERROR_THROWER_GETTER, Lookup.TYPE_ERROR_THROWER_SETTER); 2.5 } 2.6 2.7 - private static PropertyMap createStrictModeMap(final PropertyMap functionMap) { 2.8 - return newThrowerProperty(newThrowerProperty(functionMap, "arguments"), "caller"); 2.9 + private static PropertyMap createStrictModeMap(PropertyMap map) { 2.10 + final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; 2.11 + // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. 2.12 + map = map.addProperty(map.newUserAccessors("arguments", flags)); 2.13 + map = map.addProperty(map.newUserAccessors("caller", flags)); 2.14 + return map; 2.15 } 2.16 2.17 // Choose the map based on strict mode! 2.18 @@ -260,12 +264,15 @@ 2.19 this.setProto(Global.instance().getFunctionPrototype()); 2.20 this.prototype = LAZY_PROTOTYPE; 2.21 2.22 - if (isStrict()) { 2.23 - final ScriptFunction func = getTypeErrorThrower(); 2.24 - // We have to fill user accessor functions late as these are stored 2.25 - // in this object rather than in the PropertyMap of this object. 2.26 - setUserAccessors("arguments", func, func); 2.27 - setUserAccessors("caller", func, func); 2.28 + // We have to fill user accessor functions late as these are stored 2.29 + // in this object rather than in the PropertyMap of this object. 2.30 + 2.31 + if (findProperty("arguments", true) != null) { 2.32 + setUserAccessors("arguments", getTypeErrorThrower(), getTypeErrorThrower()); 2.33 + } 2.34 + 2.35 + if (findProperty("caller", true) != null) { 2.36 + setUserAccessors("caller", getTypeErrorThrower(), getTypeErrorThrower()); 2.37 } 2.38 } 2.39 }
3.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java Wed Jun 26 16:36:13 2013 +0530 3.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java Wed Jun 26 08:36:53 2013 -0300 3.3 @@ -89,7 +89,7 @@ 3.4 MethodHandle setter = property.getSetter(type, getOwner().getMap()); 3.5 if (property instanceof UserAccessorProperty) { 3.6 final UserAccessorProperty uc = (UserAccessorProperty) property; 3.7 - setter = MH.insertArguments(setter, 0, (isInherited() ? getOwner() : null), 3.8 + setter = MH.insertArguments(setter, 0, isInherited() ? getOwner() : null, 3.9 uc.getSetterSlot(), strict? property.getKey() : null); 3.10 } 3.11 3.12 @@ -109,7 +109,7 @@ 3.13 * @return appropriate receiver 3.14 */ 3.15 public ScriptObject getGetterReceiver() { 3.16 - return property != null && property.hasGetterFunction() ? self : prototype; 3.17 + return property != null && property.hasGetterFunction(prototype) ? self : prototype; 3.18 } 3.19 3.20 /** 3.21 @@ -117,7 +117,7 @@ 3.22 * @return appropriate receiver 3.23 */ 3.24 public ScriptObject getSetterReceiver() { 3.25 - return property != null && property.hasSetterFunction() ? self : prototype; 3.26 + return property != null && property.hasSetterFunction(prototype) ? self : prototype; 3.27 } 3.28 3.29 /**
4.1 --- a/src/jdk/nashorn/internal/runtime/Property.java Wed Jun 26 16:36:13 2013 +0530 4.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java Wed Jun 26 08:36:53 2013 -0300 4.3 @@ -180,17 +180,19 @@ 4.4 4.5 /** 4.6 * Check whether this property has a user defined getter function. See {@link UserAccessorProperty} 4.7 + * @param obj object containing getter 4.8 * @return true if getter function exists, false is default 4.9 */ 4.10 - public boolean hasGetterFunction() { 4.11 + public boolean hasGetterFunction(final ScriptObject obj) { 4.12 return false; 4.13 } 4.14 4.15 /** 4.16 * Check whether this property has a user defined setter function. See {@link UserAccessorProperty} 4.17 + * @param obj object containing setter 4.18 * @return true if getter function exists, false is default 4.19 */ 4.20 - public boolean hasSetterFunction() { 4.21 + public boolean hasSetterFunction(final ScriptObject obj) { 4.22 return false; 4.23 } 4.24
5.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java Wed Jun 26 16:36:13 2013 +0530 5.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Wed Jun 26 08:36:53 2013 -0300 5.3 @@ -302,7 +302,7 @@ 5.4 * 5.5 * @return New {@link PropertyMap} with {@link Property} added. 5.6 */ 5.7 - PropertyMap addProperty(final Property property) { 5.8 + public PropertyMap addProperty(final Property property) { 5.9 PropertyMap newMap = checkHistory(property); 5.10 5.11 if (newMap == null) { 5.12 @@ -383,6 +383,21 @@ 5.13 return newMap; 5.14 } 5.15 5.16 + /* 5.17 + * Make a new UserAccessorProperty property. getter and setter functions are stored in 5.18 + * this ScriptObject and slot values are used in property object. Note that slots 5.19 + * are assigned speculatively and should be added to map before adding other 5.20 + * properties. 5.21 + */ 5.22 + public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) { 5.23 + int oldSpillLength = spillLength; 5.24 + 5.25 + final int getterSlot = oldSpillLength++; 5.26 + final int setterSlot = oldSpillLength++; 5.27 + 5.28 + return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot); 5.29 + } 5.30 + 5.31 /** 5.32 * Find a property in the map. 5.33 *
6.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jun 26 16:36:13 2013 +0530 6.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jun 26 08:36:53 2013 -0300 6.3 @@ -777,30 +777,18 @@ 6.4 public final Property modifyOwnProperty(final Property oldProperty, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { 6.5 Property newProperty; 6.6 if (oldProperty instanceof UserAccessorProperty) { 6.7 - // re-use the slots of the old user accessor property. 6.8 final UserAccessorProperty uc = (UserAccessorProperty) oldProperty; 6.9 - 6.10 - int getterSlot = uc.getGetterSlot(); 6.11 - // clear the old getter and set the new getter 6.12 + final int getterSlot = uc.getGetterSlot(); 6.13 + final int setterSlot = uc.getSetterSlot(); 6.14 setSpill(getterSlot, getter); 6.15 - // if getter function is null, flag the slot to be negative (less by 1) 6.16 - if (getter == null) { 6.17 - getterSlot = -getterSlot - 1; 6.18 - } 6.19 - 6.20 - int setterSlot = uc.getSetterSlot(); 6.21 - // clear the old setter and set the new setter 6.22 setSpill(setterSlot, setter); 6.23 - // if setter function is null, flag the slot to be negative (less by 1) 6.24 - if (setter == null) { 6.25 - setterSlot = -setterSlot - 1; 6.26 - } 6.27 - 6.28 - newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot); 6.29 + 6.30 // if just flipping getter and setter with new functions, no need to change property or map 6.31 - if (oldProperty.equals(newProperty)) { 6.32 + if (uc.flags == propertyFlags) { 6.33 return oldProperty; 6.34 } 6.35 + 6.36 + newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot); 6.37 } else { 6.38 // erase old property value and create new user accessor property 6.39 erasePropertyValue(oldProperty); 6.40 @@ -862,12 +850,12 @@ 6.41 */ 6.42 public final void setUserAccessors(final String key, final ScriptFunction getter, final ScriptFunction setter) { 6.43 final Property oldProperty = getMap().findProperty(key); 6.44 - if (oldProperty != null) { 6.45 - final UserAccessorProperty newProperty = newUserAccessors(oldProperty.getKey(), oldProperty.getFlags(), getter, setter); 6.46 - modifyOwnProperty(oldProperty, newProperty); 6.47 + if (oldProperty instanceof UserAccessorProperty) { 6.48 + final UserAccessorProperty ua = (UserAccessorProperty)oldProperty; 6.49 + setSpill(ua.getGetterSlot(), getter); 6.50 + setSpill(ua.getSetterSlot(), setter); 6.51 } else { 6.52 - final UserAccessorProperty newProperty = newUserAccessors(key, 0, getter, setter); 6.53 - addOwnProperty(newProperty); 6.54 + addOwnProperty(newUserAccessors(key, oldProperty != null ? oldProperty.getFlags() : 0, getter, setter)); 6.55 } 6.56 } 6.57 6.58 @@ -1712,7 +1700,7 @@ 6.59 6.60 final ScriptObject prototype = find.getOwner(); 6.61 6.62 - if (!property.hasGetterFunction()) { 6.63 + if (!property.hasGetterFunction(prototype)) { 6.64 methodHandle = bindTo(methodHandle, prototype); 6.65 } 6.66 return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard); 6.67 @@ -3144,49 +3132,30 @@ 6.68 * Make a new UserAccessorProperty property. getter and setter functions are stored in 6.69 * this ScriptObject and slot values are used in property object. 6.70 */ 6.71 - private UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { 6.72 - int oldSpillLength = getMap().getSpillLength(); 6.73 - 6.74 - int getterSlot = oldSpillLength++; 6.75 - setSpill(getterSlot, getter); 6.76 - // if getter function is null, flag the slot to be negative (less by 1) 6.77 - if (getter == null) { 6.78 - getterSlot = -getterSlot - 1; 6.79 + protected final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { 6.80 + final UserAccessorProperty property = getMap().newUserAccessors(key, propertyFlags); 6.81 + setSpill(property.getGetterSlot(), getter); 6.82 + setSpill(property.getSetterSlot(), setter); 6.83 + 6.84 + return property; 6.85 + } 6.86 + 6.87 + protected final void setSpill(final int slot, final Object value) { 6.88 + if (spill == null) { 6.89 + // create new spill. 6.90 + spill = new Object[Math.max(slot + 1, SPILL_RATE)]; 6.91 + } else if (slot >= spill.length) { 6.92 + // grow spill as needed 6.93 + final Object[] newSpill = new Object[slot + 1]; 6.94 + System.arraycopy(spill, 0, newSpill, 0, spill.length); 6.95 + spill = newSpill; 6.96 } 6.97 6.98 - int setterSlot = oldSpillLength++; 6.99 - 6.100 - setSpill(setterSlot, setter); 6.101 - // if setter function is null, flag the slot to be negative (less by 1) 6.102 - if (setter == null) { 6.103 - setterSlot = -setterSlot - 1; 6.104 - } 6.105 - 6.106 - return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot); 6.107 + spill[slot] = value; 6.108 } 6.109 6.110 - private void setSpill(final int slot, final Object value) { 6.111 - if (slot >= 0) { 6.112 - final int index = slot; 6.113 - if (spill == null) { 6.114 - // create new spill. 6.115 - spill = new Object[Math.max(index + 1, SPILL_RATE)]; 6.116 - } else if (index >= spill.length) { 6.117 - // grow spill as needed 6.118 - final Object[] newSpill = new Object[index + 1]; 6.119 - System.arraycopy(spill, 0, newSpill, 0, spill.length); 6.120 - spill = newSpill; 6.121 - } 6.122 - 6.123 - spill[index] = value; 6.124 - } 6.125 - } 6.126 - 6.127 - // user accessors are either stored in spill array slots 6.128 - // get the accessor value using slot number. Note that slot is spill array index. 6.129 - Object getSpill(final int slot) { 6.130 - final int index = slot; 6.131 - return (index < 0 || (index >= spill.length)) ? null : spill[index]; 6.132 + protected Object getSpill(final int slot) { 6.133 + return spill != null && slot < spill.length ? spill[slot] : null; 6.134 } 6.135 6.136 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
7.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Jun 26 16:36:13 2013 +0530 7.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Jun 26 08:36:53 2013 -0300 7.3 @@ -151,9 +151,10 @@ 7.4 assert methodHandle != null; 7.5 assert property != null; 7.6 7.7 + final ScriptObject prototype = find.getOwner(); 7.8 final MethodHandle boundHandle; 7.9 - if (!property.hasSetterFunction() && find.isInherited()) { 7.10 - boundHandle = ScriptObject.bindTo(methodHandle, find.getOwner()); 7.11 + if (!property.hasSetterFunction(prototype) && find.isInherited()) { 7.12 + boundHandle = ScriptObject.bindTo(methodHandle, prototype); 7.13 } else { 7.14 boundHandle = methodHandle; 7.15 }
8.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Jun 26 16:36:13 2013 +0530 8.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Jun 26 08:36:53 2013 -0300 8.3 @@ -96,19 +96,19 @@ 8.4 } 8.5 8.6 /** 8.7 - * Return getter slot for this UserAccessorProperty. Slots start with first embed field. 8.8 + * Return getter spill slot for this UserAccessorProperty. 8.9 * @return getter slot 8.10 */ 8.11 public int getGetterSlot() { 8.12 - return getterSlot < 0 ? -getterSlot - 1 : getterSlot; 8.13 + return getterSlot; 8.14 } 8.15 8.16 /** 8.17 - * Return setter slot for this UserAccessorProperty. Slots start with first embed field. 8.18 + * Return setter spill slot for this UserAccessorProperty. 8.19 * @return setter slot 8.20 */ 8.21 public int getSetterSlot() { 8.22 - return setterSlot < 0 ? -setterSlot - 1 : setterSlot; 8.23 + return setterSlot; 8.24 } 8.25 8.26 @Override 8.27 @@ -124,7 +124,7 @@ 8.28 8.29 final UserAccessorProperty uc = (UserAccessorProperty) other; 8.30 return getterSlot == uc.getterSlot && setterSlot == uc.setterSlot; 8.31 - } 8.32 + } 8.33 8.34 @Override 8.35 public int hashCode() { 8.36 @@ -136,25 +136,17 @@ 8.37 */ 8.38 @Override 8.39 public int getSpillCount() { 8.40 - // calculate how many spill array slots used by this propery. 8.41 - int count = 0; 8.42 - if (getGetterSlot() >= 0) { 8.43 - count++; 8.44 - } 8.45 - if (getSetterSlot() >= 0) { 8.46 - count++; 8.47 - } 8.48 - return count; 8.49 + return 2; 8.50 } 8.51 8.52 @Override 8.53 - public boolean hasGetterFunction() { 8.54 - return getterSlot > -1; 8.55 + public boolean hasGetterFunction(final ScriptObject obj) { 8.56 + return obj.getSpill(getterSlot) != null; 8.57 } 8.58 8.59 @Override 8.60 - public boolean hasSetterFunction() { 8.61 - return setterSlot > -1; 8.62 + public boolean hasSetterFunction(final ScriptObject obj) { 8.63 + return obj.getSpill(setterSlot) != null; 8.64 } 8.65 8.66 @Override