# HG changeset patch # User hannesw # Date 1521208614 -3600 # Node ID 82f763a9cc2229ed3f75c70e9f92e101adbf499f # Parent ca2780cd20567dabb3512c8c426b0cf3450dd6ed 8199443: Nashorn multithread bottleneck with "use strict" Reviewed-by: jlaskey, sundar diff -r ca2780cd2056 -r 82f763a9cc22 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/lookup/Lookup.java --- 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)); } diff -r ca2780cd2056 -r 82f763a9cc22 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java --- 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 diff -r ca2780cd2056 -r 82f763a9cc22 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeStrictArguments.java --- 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; diff -r ca2780cd2056 -r 82f763a9cc22 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java --- 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); } } diff -r ca2780cd2056 -r 82f763a9cc22 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java --- 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); } /**