8199443: Nashorn multithread bottleneck with "use strict"
Reviewed-by: jlaskey, sundar
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/lookup/Lookup.java Fri Mar 16 13:02:42 2018 +0000
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/lookup/Lookup.java Fri Mar 16 14:56:54 2018 +0100
@@ -56,11 +56,8 @@
/** Method handle to the empty setter */
public static final MethodHandle EMPTY_SETTER = findOwnMH("emptySetter", void.class, Object.class, Object.class);
- /** Method handle to a getter that only throws type error */
- public static final MethodHandle TYPE_ERROR_THROWER_GETTER = findOwnMH("typeErrorThrowerGetter", Object.class, Object.class);
-
- /** Method handle to a setter that only throws type error */
- public static final MethodHandle TYPE_ERROR_THROWER_SETTER = findOwnMH("typeErrorThrowerSetter", void.class, Object.class, Object.class);
+ /** Method handle to a getter or setter that only throws type error */
+ public static final MethodHandle TYPE_ERROR_THROWER = findOwnMH("typeErrorThrower", Object.class, Object.class);
/** Method handle to the most generic of getters, the one that returns an Object */
public static final MethodType GET_OBJECT_TYPE = MH.type(Object.class, Object.class);
@@ -114,17 +111,7 @@
* @param self self reference
* @return undefined (but throws error before return point)
*/
- public static Object typeErrorThrowerGetter(final Object self) {
- throw typeError("strict.getter.setter.poison", ScriptRuntime.safeToString(self));
- }
-
- /**
- * Getter function that always throws type error
- *
- * @param self self reference
- * @param value (ignored)
- */
- public static void typeErrorThrowerSetter(final Object self, final Object value) {
+ public static Object typeErrorThrower(final Object self) {
throw typeError("strict.getter.setter.poison", ScriptRuntime.safeToString(self));
}
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Fri Mar 16 13:02:42 2018 +0000
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Fri Mar 16 14:56:54 2018 +0100
@@ -2978,7 +2978,7 @@
anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
// use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
- this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER);
+ this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER);
typeErrorThrower.preventExtensions();
// now initialize Object
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeStrictArguments.java Fri Mar 16 13:02:42 2018 +0000
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeStrictArguments.java Fri Mar 16 14:56:54 2018 +0100
@@ -79,9 +79,8 @@
final ScriptFunction func = Global.instance().getTypeErrorThrower();
// We have to fill user accessor functions late as these are stored
// in this object rather than in the PropertyMap of this object.
- final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
- initUserAccessors("caller", flags, func, func);
- initUserAccessors("callee", flags, func, func);
+ initUserAccessors("caller", func, func);
+ initUserAccessors("callee", func, func);
setArray(ArrayData.allocate(values));
this.length = values.length;
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Fri Mar 16 13:02:42 2018 +0000
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Fri Mar 16 14:56:54 2018 +0100
@@ -137,8 +137,8 @@
final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
PropertyMap newMap = map;
// Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
- newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
- newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
+ newMap = newMap.addPropertyNoHistory(newMap.newUserAccessors("arguments", flags));
+ newMap = newMap.addPropertyNoHistory(newMap.newUserAccessors("caller", flags));
return newMap;
}
@@ -215,8 +215,8 @@
assert objectSpill == null;
if (isStrict() || isBoundFunction()) {
final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
- initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
- initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+ initUserAccessors("arguments", typeErrorThrower, typeErrorThrower);
+ initUserAccessors("caller", typeErrorThrower, typeErrorThrower);
}
}
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Fri Mar 16 13:02:42 2018 +0000
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Fri Mar 16 14:56:54 2018 +0100
@@ -962,24 +962,19 @@
/**
* Fast initialization functions for ScriptFunctions that are strict, to avoid
* creating setters that probably aren't used. Inject directly into the spill pool
- * the defaults for "arguments" and "caller"
+ * the defaults for "arguments" and "caller", asserting the property is already
+ * defined in the map.
*
- * @param key property key
- * @param propertyFlags flags
- * @param getter getter for {@link UserAccessorProperty}, null if not present or N/A
- * @param setter setter for {@link UserAccessorProperty}, null if not present or N/A
+ * @param key property key
+ * @param getter getter for {@link UserAccessorProperty}
+ * @param setter setter for {@link UserAccessorProperty}
*/
- protected final void initUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
- final PropertyMap oldMap = getMap();
- final int slot = oldMap.getFreeSpillSlot();
- ensureSpillSize(slot);
- objectSpill[slot] = new UserAccessorProperty.Accessors(getter, setter);
- Property newProperty;
- PropertyMap newMap;
- do {
- newProperty = new UserAccessorProperty(key, propertyFlags, slot);
- newMap = oldMap.addProperty(newProperty);
- } while (!compareAndSetMap(oldMap, newMap));
+ protected final void initUserAccessors(final String key, final ScriptFunction getter, final ScriptFunction setter) {
+ final PropertyMap map = getMap();
+ final Property property = map.findProperty(key);
+ assert property instanceof UserAccessorProperty;
+ ensureSpillSize(property.getSlot());
+ objectSpill[property.getSlot()] = new UserAccessorProperty.Accessors(getter, setter);
}
/**