# HG changeset patch # User sundar # Date 1441799386 -19800 # Node ID a750a66640e0ac3fd58c643ff3e030d83a3ace1a # Parent 330ddba6ffc4b00ea933ca72009dd8130a73bc01 8027137: Merge ScriptFunction and ScriptFunctionImpl Reviewed-by: attila, hannesw, mhaupt diff -r 330ddba6ffc4 -r a750a66640e0 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Wed Sep 09 09:36:48 2015 +0200 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Wed Sep 09 17:19:46 2015 +0530 @@ -54,10 +54,9 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE; @@ -282,9 +281,9 @@ assert specs != null; if (!specs.isEmpty()) { mi.memberInfoArray(className, specs); - mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC); + mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC); } else { - mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC); + mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_DESC); } if (arityFound) { diff -r 330ddba6ffc4 -r a750a66640e0 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Wed Sep 09 09:36:48 2015 +0200 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Wed Sep 09 17:19:46 2015 +0530 @@ -38,9 +38,8 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC3; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC4; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC3; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC4; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE; @@ -76,7 +75,7 @@ byte[] getClassBytes() { // new class extending from ScriptObject - final String superClass = (constructor != null)? SCRIPTFUNCTIONIMPL_TYPE : SCRIPTOBJECT_TYPE; + final String superClass = (constructor != null)? SCRIPTFUNCTION_TYPE : SCRIPTOBJECT_TYPE; cw.visit(V1_7, ACC_FINAL, className, null, superClass, null); if (memberCount > 0) { // add fields @@ -182,8 +181,8 @@ loadMap(mi); } else { // call Function. - superClass = SCRIPTFUNCTIONIMPL_TYPE; - superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3; + superClass = SCRIPTFUNCTION_TYPE; + superDesc = (memberCount > 0) ? SCRIPTFUNCTION_INIT_DESC4 : SCRIPTFUNCTION_INIT_DESC3; mi.loadLiteral(constructor.getName()); mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc())); loadMap(mi); diff -r 330ddba6ffc4 -r a750a66640e0 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed Sep 09 09:36:48 2015 +0200 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed Sep 09 17:19:46 2015 +0530 @@ -31,10 +31,9 @@ import java.util.Collections; import java.util.List; import jdk.internal.org.objectweb.asm.Type; -import jdk.nashorn.internal.objects.PrototypeObject; -import jdk.nashorn.internal.objects.ScriptFunctionImpl; import jdk.nashorn.internal.runtime.AccessorProperty; import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.PrototypeObject; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Specialization; @@ -88,7 +87,6 @@ static final Type TYPE_PROPERTYMAP = Type.getType(PropertyMap.class); static final Type TYPE_PROTOTYPEOBJECT = Type.getType(PrototypeObject.class); static final Type TYPE_SCRIPTFUNCTION = Type.getType(ScriptFunction.class); - static final Type TYPE_SCRIPTFUNCTIONIMPL = Type.getType(ScriptFunctionImpl.class); static final Type TYPE_SCRIPTOBJECT = Type.getType(ScriptObject.class); static final String PROTOTYPE_SUFFIX = "$Prototype"; @@ -122,17 +120,14 @@ static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE); static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype"; static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT); - - // ScriptFunctionImpl - static final String SCRIPTFUNCTIONIMPL_TYPE = TYPE_SCRIPTFUNCTIONIMPL.getInternalName(); - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION = "makeFunction"; - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC = + static final String SCRIPTFUNCTION_CREATEBUILTIN = "createBuiltin"; + static final String SCRIPTFUNCTION_CREATEBUILTIN_DESC = Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE); - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC = + static final String SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC = Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); - static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 = + static final String SCRIPTFUNCTION_INIT_DESC3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); - static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 = + static final String SCRIPTFUNCTION_INIT_DESC4 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY); // ScriptObject diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Wed Sep 09 17:19:46 2015 +0530 @@ -77,7 +77,7 @@ * @return a synchronizing wrapper function */ public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) { - return func.makeSynchronizedFunction(unwrap(sync)); + return func.createSynchronized(unwrap(sync)); } /** diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Sep 09 17:19:46 2015 +0530 @@ -132,7 +132,6 @@ import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.objects.Global; -import jdk.nashorn.internal.objects.ScriptFunctionImpl; import jdk.nashorn.internal.parser.Lexer.RegexToken; import jdk.nashorn.internal.parser.TokenType; import jdk.nashorn.internal.runtime.Context; @@ -195,9 +194,9 @@ private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, "ensureNumber", double.class, Object.class, int.class); - private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, + private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class, "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class); - private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, + private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunction.class, "create", ScriptFunction.class, Object[].class, int.class); private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class, diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java Wed Sep 09 09:36:48 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.objects; - -import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptFunctionData; -import jdk.nashorn.internal.runtime.ScriptObject; -import jdk.nashorn.internal.runtime.ScriptRuntime; - -/** - * A {@code ScriptFunctionImpl} subclass for functions created using {@code Function.prototype.bind}. Such functions - * must track their {@code [[TargetFunction]]} property for purposes of correctly implementing {@code [[HasInstance]]}; - * see {@link ScriptFunction#isInstance(ScriptObject)}. - */ -final class BoundScriptFunctionImpl extends ScriptFunctionImpl { - private final ScriptFunction targetFunction; - - BoundScriptFunctionImpl(final ScriptFunctionData data, final ScriptFunction targetFunction) { - super(data, Global.instance()); - setPrototype(ScriptRuntime.UNDEFINED); - this.targetFunction = targetFunction; - } - - @Override - protected ScriptFunction getTargetFunction() { - return targetFunction; - } -} diff -r 330ddba6ffc4 -r a750a66640e0 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 Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Sep 09 17:19:46 2015 +0530 @@ -1583,7 +1583,11 @@ return ScriptFunction.getPrototype(builtinObject); } - ScriptObject getFunctionPrototype() { + /** + * Get the builtin Function prototype. + * @return the Function.prototype. + */ + public ScriptObject getFunctionPrototype() { return ScriptFunction.getPrototype(builtinFunction); } @@ -1768,7 +1772,12 @@ return ScriptFunction.getPrototype(getBuiltinFloat64Array()); } - ScriptFunction getTypeErrorThrower() { + /** + * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties. + * + * @return the TypeError throwing function + */ + public ScriptFunction getTypeErrorThrower() { return typeErrorThrower; } @@ -2202,10 +2211,10 @@ * Adds jjs shell interactive mode builtin functions to global scope. */ public void addShellBuiltins() { - Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT); + Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT); addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); - value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT); + value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT); addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); } @@ -2251,35 +2260,35 @@ this.setInitialProto(getObjectPrototype()); // initialize global function properties - this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); - - this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, + this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL); + + this.parseInt = ScriptFunction.createBuiltin("parseInt", GlobalFunctions.PARSEINT, new Specialization[] { new Specialization(GlobalFunctions.PARSEINT_Z), new Specialization(GlobalFunctions.PARSEINT_I), new Specialization(GlobalFunctions.PARSEINT_J), new Specialization(GlobalFunctions.PARSEINT_OI), new Specialization(GlobalFunctions.PARSEINT_O) }); - this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); - this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN, + this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); + this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN, new Specialization[] { new Specialization(GlobalFunctions.IS_NAN_I), new Specialization(GlobalFunctions.IS_NAN_J), new Specialization(GlobalFunctions.IS_NAN_D) }); - this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); - this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN); - this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE); - this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI); - this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); - this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI); - this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); - this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE); - this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE); - this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN); - this.load = ScriptFunctionImpl.makeFunction("load", LOAD); - this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); - this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT); - this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT); + this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); + this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN); + this.isFinite = ScriptFunction.createBuiltin("isFinite", GlobalFunctions.IS_FINITE); + this.encodeURI = ScriptFunction.createBuiltin("encodeURI", GlobalFunctions.ENCODE_URI); + this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); + this.decodeURI = ScriptFunction.createBuiltin("decodeURI", GlobalFunctions.DECODE_URI); + this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); + this.escape = ScriptFunction.createBuiltin("escape", GlobalFunctions.ESCAPE); + this.unescape = ScriptFunction.createBuiltin("unescape", GlobalFunctions.UNESCAPE); + this.print = ScriptFunction.createBuiltin("print", env._print_no_newline ? PRINT : PRINTLN); + this.load = ScriptFunction.createBuiltin("load", LOAD); + this.loadWithNewGlobal = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); + this.exit = ScriptFunction.createBuiltin("exit", EXIT); + this.quit = ScriptFunction.createBuiltin("quit", EXIT); // built-in constructors this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); @@ -2359,7 +2368,7 @@ // default file name addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); // __noSuchProperty__ hook for ScriptContext search of missing variables - final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); + final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp); } } @@ -2370,17 +2379,17 @@ final ScriptObject errorProto = getErrorPrototype(); // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName - final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK); - final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK); + final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK); + final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK); errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); - final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER); - final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER); + final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER); + final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER); errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); - final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER); - final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER); + final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER); + final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER); errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); - final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME); - final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME); + final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME); + final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME); errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); // ECMA 15.11.4.2 Error.prototype.name @@ -2420,14 +2429,14 @@ private void initScripting(final ScriptEnvironment scriptEnv) { ScriptObject value; - value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE); + value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE); addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); - value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY); + value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY); addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); final String execName = ScriptingFunctions.EXEC_NAME; - value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC); + value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC); value.addOwnProperty(ScriptingFunctions.THROW_ON_ERROR_NAME, Attribute.NOT_ENUMERABLE, false); addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); @@ -2610,7 +2619,7 @@ this.builtinFunction = initConstructor("Function", ScriptFunction.class); // create global anonymous function - final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(); + final ScriptFunction anon = ScriptFunction.createAnonymous(); // need to copy over members of Function.prototype to anon function anon.addBoundProperties(getFunctionPrototype()); @@ -2622,10 +2631,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 = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0); - typeErrorThrower.setPrototype(UNDEFINED); - // Non-constructor built-in functions do not have "prototype" property - typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype")); + this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER); typeErrorThrower.preventExtensions(); // now initialize Object @@ -2636,8 +2642,8 @@ // ES6 draft compliant __proto__ property of Object.prototype // accessors on Object.prototype for "__proto__" - final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__); - final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__); + final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__); + final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__); ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); // Function valued properties of Function.prototype were not properly diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeError.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeError.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeError.java Wed Sep 09 17:19:46 2015 +0530 @@ -148,8 +148,8 @@ initException(sobj); sobj.delete(STACK, false); if (! sobj.has("stack")) { - final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK); - final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK); + final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", GET_STACK); + final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", SET_STACK); sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); } return UNDEFINED; diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Sep 09 17:19:46 2015 +0530 @@ -621,11 +621,11 @@ if (find != null) { final Object value = find.getObjectValue(); if (value instanceof ScriptFunction) { - final ScriptFunctionImpl func = (ScriptFunctionImpl)value; + final ScriptFunction func = (ScriptFunction)value; // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice. return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class, - func.makeBoundFunction(this, new Object[] { name })), 0, Object.class), + func.createBound(this, new Object[] { name })), 0, Object.class), testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoint(__call__, find.getOwner())); } diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java Wed Sep 09 17:19:46 2015 +0530 @@ -96,7 +96,7 @@ @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object synchronizedFunc(final Object self, final Object func, final Object obj) { if (func instanceof ScriptFunction) { - return ((ScriptFunction)func).makeSynchronizedFunction(obj); + return ((ScriptFunction)func).createSynchronized(obj); } throw typeError("not.a.function", ScriptRuntime.safeToString(func)); diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/PrototypeObject.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/PrototypeObject.java Wed Sep 09 09:36:48 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.objects; - -import static jdk.nashorn.internal.lookup.Lookup.MH; -import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.ArrayList; -import jdk.nashorn.internal.runtime.AccessorProperty; -import jdk.nashorn.internal.runtime.Property; -import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; - -/** - * Instances of this class serve as "prototype" object for script functions. - * The purpose is to expose "constructor" property from "prototype". Also, nasgen - * generated prototype classes extend from this class. - * - */ -public class PrototypeObject extends ScriptObject { - private static final PropertyMap map$; - - private Object constructor; - - private static final MethodHandle GET_CONSTRUCTOR = findOwnMH("getConstructor", Object.class, Object.class); - private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class); - - static { - final ArrayList properties = new ArrayList<>(1); - properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR)); - map$ = PropertyMap.newMap(properties); - } - - private PrototypeObject(final Global global, final PropertyMap map) { - super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$); - } - - PrototypeObject() { - this(Global.instance(), map$); - } - - /** - * PropertyObject constructor - * - * @param map property map - */ - PrototypeObject(final PropertyMap map) { - this(Global.instance(), map); - } - - PrototypeObject(final ScriptFunction func) { - this(Global.instance(), map$); - this.constructor = func; - } - - /** - * Get the constructor for this {@code PrototypeObject} - * @param self self reference - * @return constructor, probably, but not necessarily, a {@link ScriptFunction} - */ - static Object getConstructor(final Object self) { - return (self instanceof PrototypeObject) ? - ((PrototypeObject)self).getConstructor() : - UNDEFINED; - } - - /** - * Reset the constructor for this {@code PrototypeObject} - * @param self self reference - * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction} - */ - static void setConstructor(final Object self, final Object constructor) { - if (self instanceof PrototypeObject) { - ((PrototypeObject)self).setConstructor(constructor); - } - } - - private Object getConstructor() { - return constructor; - } - - private void setConstructor(final Object constructor) { - this.constructor = constructor; - } - - private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { - return MH.findStatic(MethodHandles.lookup(), PrototypeObject.class, name, MH.type(rtype, types)); - } -} diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Sep 09 09:36:48 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.objects; - -import static jdk.nashorn.internal.lookup.Lookup.MH; -import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; - -import java.lang.invoke.MethodHandle; -import java.util.ArrayList; -import jdk.nashorn.internal.runtime.AccessorProperty; -import jdk.nashorn.internal.runtime.GlobalFunctions; -import jdk.nashorn.internal.runtime.Property; -import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; -import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptFunctionData; -import jdk.nashorn.internal.runtime.ScriptObject; -import jdk.nashorn.internal.runtime.Specialization; - -/** - * Concrete implementation of ScriptFunction. This sets correct map for the - * function objects -- to expose properties like "prototype", "length" etc. - */ -public class ScriptFunctionImpl extends ScriptFunction { - - /** Reference to constructor prototype. */ - private Object prototype; - - // property map for strict mode functions - private static final PropertyMap strictmodemap$; - // property map for bound functions - private static final PropertyMap boundfunctionmap$; - // property map for non-strict, non-bound functions. - private static final PropertyMap map$; - - // Marker object for lazily initialized prototype object - private static final Object LAZY_PROTOTYPE = new Object(); - - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs, final Global global) { - super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); - init(global); - } - - /** - * Constructor called by Nasgen generated code, no membercount, use the default map. - * Creates builtin functions only. - * - * @param name name of function - * @param invokeHandle handle for invocation - * @param specs specialized versions of this method, if available, null otherwise - */ - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs) { - this(name, invokeHandle, specs, Global.instance()); - } - - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs, final Global global) { - super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); - init(global); - } - - /** - * Constructor called by Nasgen generated code, no membercount, use the map passed as argument. - * Creates builtin functions only. - * - * @param name name of function - * @param invokeHandle handle for invocation - * @param map initial property map - * @param specs specialized versions of this method, if available, null otherwise - */ - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) { - this(name, invokeHandle, map, specs, Global.instance()); - } - - private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags, final Global global) { - super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags); - init(global); - } - - /** - * Constructor called by Global.newScriptFunction (runtime). - * - * @param name name of function - * @param methodHandle handle for invocation - * @param scope scope object - * @param specs specialized versions of this method, if available, null otherwise - * @param flags {@link ScriptFunctionData} flags - */ - ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags) { - this(name, methodHandle, scope, specs, flags, Global.instance()); - } - - private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) { - super(data, getMap(data.isStrict()), scope); - init(global); - } - - /** - * Factory method called by compiler generated code for functions that need parent scope. - * - * @param constants the generated class' constant array - * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array. - * @param scope the parent scope object - * @return a newly created function object - */ - public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) { - return new ScriptFunctionImpl((RecompilableScriptFunctionData)constants[index], scope, Global.instance()); - } - - /** - * Factory method called by compiler generated code for functions that don't need parent scope. - * - * @param constants the generated class' constant array - * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array. - * @return a newly created function object - */ - public static ScriptFunction create(final Object[] constants, final int index) { - return create(constants, index, null); - } - - /** - * Only invoked internally from {@link BoundScriptFunctionImpl} constructor. - * @param data the script function data for the bound function. - * @param global the global object - */ - ScriptFunctionImpl(final ScriptFunctionData data, final Global global) { - super(data, boundfunctionmap$, null); - init(global); - } - - static { - final ArrayList properties = new ArrayList<>(3); - properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE)); - properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null)); - properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null)); - map$ = PropertyMap.newMap(properties); - strictmodemap$ = createStrictModeMap(map$); - boundfunctionmap$ = createBoundFunctionMap(strictmodemap$); - } - - private static PropertyMap createStrictModeMap(final PropertyMap map) { - 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)); - return newMap; - } - - private static boolean isStrict(final int flags) { - return (flags & ScriptFunctionData.IS_STRICT) != 0; - } - - // Choose the map based on strict mode! - private static PropertyMap getMap(final boolean strict) { - return strict ? strictmodemap$ : map$; - } - - private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) { - // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see - // ECMAScript 5.1 section 15.3.4.5 - return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype")); - } - - // Instance of this class is used as global anonymous function which - // serves as Function.prototype object. - private static class AnonymousFunction extends ScriptFunctionImpl { - private static final PropertyMap anonmap$ = PropertyMap.newMap(); - - AnonymousFunction() { - super("", GlobalFunctions.ANONYMOUS, anonmap$, null); - } - } - - static ScriptFunctionImpl newAnonymousFunction() { - return new AnonymousFunction(); - } - - private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) { - final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags); - func.setPrototype(UNDEFINED); - // Non-constructor built-in functions do not have "prototype" property - func.deleteOwnProperty(func.getMap().findProperty("prototype")); - - return func; - } - - /** - * Factory method for non-constructor built-in functions - * - * @param name function name - * @param methodHandle handle for invocation - * @param specs specialized versions of function if available, null otherwise - * @return new ScriptFunction - */ - static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs) { - return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN); - } - - /** - * Factory method for non-constructor built-in, strict functions - * - * @param name function name - * @param methodHandle handle for invocation - * @return new ScriptFunction - */ - static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) { - return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT ); - } - - /** - * Factory method for non-constructor built-in functions - * - * @param name function name - * @param methodHandle handle for invocation - * @return new ScriptFunction - */ - static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle) { - return makeFunction(name, methodHandle, null); - } - - @Override - public ScriptFunction makeSynchronizedFunction(final Object sync) { - final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync); - return makeFunction(getName(), mh); - } - - /** - * Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we - * can expose it. - * @param self the self to bind to this function. Can be null (in which case, null is bound as this). - * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments. - * @return a function with the specified self and parameters bound. - */ - @Override - public ScriptFunction makeBoundFunction(final Object self, final Object[] args) { - return super.makeBoundFunction(self, args); - } - - /** - * This method is used to create a bound function based on this function. - * - * @param data the {@code ScriptFunctionData} specifying the functions immutable portion. - * @return a function initialized from the specified data. Its parent scope will be set to null, therefore the - * passed in data should not expect a callee. - */ - @Override - protected ScriptFunction makeBoundFunction(final ScriptFunctionData data) { - return new BoundScriptFunctionImpl(data, getTargetFunction()); - } - - // return Object.prototype - used by "allocate" - @Override - protected final ScriptObject getObjectPrototype() { - return Global.objectPrototype(); - } - - @Override - public final Object getPrototype() { - if (prototype == LAZY_PROTOTYPE) { - prototype = new PrototypeObject(this); - } - return prototype; - } - - @Override - public final void setPrototype(final Object newProto) { - if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) { - // Replace our current allocator map with one that is associated with the new prototype. - allocatorMap = allocatorMap.changeProto((ScriptObject)newProto); - } - this.prototype = newProto; - } - - // Internals below.. - private void init(final Global global) { - this.setInitialProto(global.getFunctionPrototype()); - this.prototype = LAZY_PROTOTYPE; - - // We have to fill user accessor functions late as these are stored - // in this object rather than in the PropertyMap of this object. - assert objectSpill == null; - final ScriptFunction typeErrorThrower = global.getTypeErrorThrower(); - if (findProperty("arguments", true) != null) { - initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); - } - if (findProperty("caller", true) != null) { - initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); - } - } -} diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyListeners.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyListeners.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyListeners.java Wed Sep 09 17:19:46 2015 +0530 @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import java.util.concurrent.atomic.LongAdder; /** * Helper class to manage property listeners and notification. @@ -37,8 +38,15 @@ private Map listeners; // These counters are updated in debug mode - private static int listenersAdded; - private static int listenersRemoved; + private static LongAdder listenersAdded; + private static LongAdder listenersRemoved; + + static { + if (Context.DEBUG) { + listenersAdded = new LongAdder(); + listenersRemoved = new LongAdder(); + } + } /** * Copy constructor @@ -54,16 +62,16 @@ * Return aggregate listeners added to all PropertyListenerManagers * @return the listenersAdded */ - public static int getListenersAdded() { - return listenersAdded; + public static long getListenersAdded() { + return listenersAdded.longValue(); } /** * Return aggregate listeners removed from all PropertyListenerManagers * @return the listenersRemoved */ - public static int getListenersRemoved() { - return listenersRemoved; + public static long getListenersRemoved() { + return listenersRemoved.longValue(); } /** @@ -122,7 +130,7 @@ */ synchronized final void addListener(final String key, final PropertyMap propertyMap) { if (Context.DEBUG) { - listenersAdded++; + listenersAdded.increment(); } if (listeners == null) { listeners = new WeakHashMap<>(); @@ -151,6 +159,9 @@ propertyMap.propertyAdded(prop); } listeners.remove(prop.getKey()); + if (Context.DEBUG) { + listenersRemoved.increment(); + } } } } @@ -168,6 +179,9 @@ propertyMap.propertyDeleted(prop); } listeners.remove(prop.getKey()); + if (Context.DEBUG) { + listenersRemoved.increment(); + } } } } @@ -187,6 +201,9 @@ propertyMap.propertyModified(oldProp, newProp); } listeners.remove(oldProp.getKey()); + if (Context.DEBUG) { + listenersRemoved.increment(); + } } } } diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Wed Sep 09 17:19:46 2015 +0530 @@ -42,6 +42,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.WeakHashMap; +import java.util.concurrent.atomic.LongAdder; import jdk.nashorn.internal.scripts.JO; /** @@ -114,7 +115,7 @@ } if (Context.DEBUG) { - count++; + count.increment(); } } @@ -135,8 +136,8 @@ this.freeSlots = propertyMap.freeSlots; if (Context.DEBUG) { - count++; - clonedCount++; + count.increment(); + clonedCount.increment(); } } @@ -328,7 +329,7 @@ if (sp != null) { protoGetSwitches.remove(key); if (Context.DEBUG) { - protoInvalidations++; + protoInvalidations.increment(); } SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); } @@ -343,7 +344,7 @@ final int size = protoGetSwitches.size(); if (size > 0) { if (Context.DEBUG) { - protoInvalidations += size; + protoInvalidations.add(size); } SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[size])); protoGetSwitches.clear(); @@ -713,7 +714,7 @@ } if (Context.DEBUG && cachedMap != null) { - protoHistoryHit++; + protoHistoryHit.increment(); } return cachedMap; @@ -762,7 +763,7 @@ if (historicMap != null) { if (Context.DEBUG) { - historyHit++; + historyHit.increment(); } return historicMap; @@ -910,7 +911,7 @@ } if (Context.DEBUG) { - setProtoNewMapCount++; + setProtoNewMapCount.increment(); } final PropertyMap newMap = new PropertyMap(this); @@ -1030,52 +1031,62 @@ } // counters updated only in debug mode - private static int count; - private static int clonedCount; - private static int historyHit; - private static int protoInvalidations; - private static int protoHistoryHit; - private static int setProtoNewMapCount; + private static LongAdder count; + private static LongAdder clonedCount; + private static LongAdder historyHit; + private static LongAdder protoInvalidations; + private static LongAdder protoHistoryHit; + private static LongAdder setProtoNewMapCount; + static { + if (Context.DEBUG) { + count = new LongAdder(); + clonedCount = new LongAdder(); + historyHit = new LongAdder(); + protoInvalidations = new LongAdder(); + protoHistoryHit = new LongAdder(); + setProtoNewMapCount = new LongAdder(); + } + } /** * @return Total number of maps. */ - public static int getCount() { - return count; + public static long getCount() { + return count.longValue(); } /** * @return The number of maps that were cloned. */ - public static int getClonedCount() { - return clonedCount; + public static long getClonedCount() { + return clonedCount.longValue(); } /** * @return The number of times history was successfully used. */ - public static int getHistoryHit() { - return historyHit; + public static long getHistoryHit() { + return historyHit.longValue(); } /** * @return The number of times prototype changes caused invalidation. */ - public static int getProtoInvalidations() { - return protoInvalidations; + public static long getProtoInvalidations() { + return protoInvalidations.longValue(); } /** * @return The number of times proto history was successfully used. */ - public static int getProtoHistoryHit() { - return protoHistoryHit; + public static long getProtoHistoryHit() { + return protoHistoryHit.longValue(); } /** * @return The number of times prototypes were modified. */ - public static int getSetProtoNewMapCount() { - return setProtoNewMapCount; + public static long getSetProtoNewMapCount() { + return setProtoNewMapCount.longValue(); } } diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PrototypeObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PrototypeObject.java Wed Sep 09 17:19:46 2015 +0530 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.runtime; + +import static jdk.nashorn.internal.lookup.Lookup.MH; +import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import jdk.nashorn.internal.objects.Global; + +/** + * Instances of this class serve as "prototype" object for script functions. + * The purpose is to expose "constructor" property from "prototype". Also, nasgen + * generated prototype classes extend from this class. + */ +public class PrototypeObject extends ScriptObject { + private static final PropertyMap map$; + + private Object constructor; + + private static final MethodHandle GET_CONSTRUCTOR = findOwnMH("getConstructor", Object.class, Object.class); + private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class); + + static { + final ArrayList properties = new ArrayList<>(1); + properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR)); + map$ = PropertyMap.newMap(properties); + } + + private PrototypeObject(final Global global, final PropertyMap map) { + super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$); + } + + /** + * Prototype constructor + */ + protected PrototypeObject() { + this(Global.instance(), map$); + } + + /** + * PropertyObject constructor + * + * @param map property map + */ + protected PrototypeObject(final PropertyMap map) { + this(Global.instance(), map); + } + + /** + * PropertyObject constructor + * + * @param func constructor function + */ + protected PrototypeObject(final ScriptFunction func) { + this(Global.instance(), map$); + this.constructor = func; + } + + /** + * Get the constructor for this {@code PrototypeObject} + * @param self self reference + * @return constructor, probably, but not necessarily, a {@link ScriptFunction} + */ + public static Object getConstructor(final Object self) { + return (self instanceof PrototypeObject) ? + ((PrototypeObject)self).getConstructor() : + UNDEFINED; + } + + /** + * Reset the constructor for this {@code PrototypeObject} + * @param self self reference + * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction} + */ + public static void setConstructor(final Object self, final Object constructor) { + if (self instanceof PrototypeObject) { + ((PrototypeObject)self).setConstructor(constructor); + } + } + + private Object getConstructor() { + return constructor; + } + + private void setConstructor(final Object constructor) { + this.constructor = constructor; + } + + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { + return MH.findStatic(MethodHandles.lookup(), PrototypeObject.class, name, MH.type(rtype, types)); + } +} diff -r 330ddba6ffc4 -r a750a66640e0 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 Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Sep 09 17:19:46 2015 +0530 @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; @@ -40,6 +39,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.concurrent.atomic.LongAdder; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; @@ -55,38 +55,54 @@ import jdk.nashorn.internal.runtime.logging.DebugLogger; /** - * Runtime representation of a JavaScript function. + * Runtime representation of a JavaScript function. This class has only private + * and protected constructors. There are no *public* constructors - but only + * factory methods that follow the naming pattern "createXYZ". */ -public abstract class ScriptFunction extends ScriptObject { +public class ScriptFunction extends ScriptObject { - /** Method handle for prototype getter for this ScriptFunction */ + /** + * Method handle for prototype getter for this ScriptFunction + */ public static final MethodHandle G$PROTOTYPE = findOwnMH_S("G$prototype", Object.class, Object.class); - /** Method handle for prototype setter for this ScriptFunction */ + /** + * Method handle for prototype setter for this ScriptFunction + */ public static final MethodHandle S$PROTOTYPE = findOwnMH_S("S$prototype", void.class, Object.class, Object.class); - /** Method handle for length getter for this ScriptFunction */ + /** + * Method handle for length getter for this ScriptFunction + */ public static final MethodHandle G$LENGTH = findOwnMH_S("G$length", int.class, Object.class); - /** Method handle for name getter for this ScriptFunction */ + /** + * Method handle for name getter for this ScriptFunction + */ public static final MethodHandle G$NAME = findOwnMH_S("G$name", Object.class, Object.class); - /** Method handle used for implementing sync() in mozilla_compat */ + /** + * Method handle used for implementing sync() in mozilla_compat + */ public static final MethodHandle INVOKE_SYNC = findOwnMH_S("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class); - /** Method handle for allocate function for this ScriptFunction */ + /** + * Method handle for allocate function for this ScriptFunction + */ static final MethodHandle ALLOCATE = findOwnMH_V("allocate", Object.class); private static final MethodHandle WRAPFILTER = findOwnMH_S("wrapFilter", Object.class, Object.class); private static final MethodHandle SCRIPTFUNCTION_GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class); - /** method handle to scope getter for this ScriptFunction */ + /** + * method handle to scope getter for this ScriptFunction + */ public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class); - private static final MethodHandle IS_FUNCTION_MH = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class); + private static final MethodHandle IS_FUNCTION_MH = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class); - private static final MethodHandle IS_APPLY_FUNCTION = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class); + private static final MethodHandle IS_APPLY_FUNCTION = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class); private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH_S("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class); @@ -94,55 +110,301 @@ private static final MethodHandle WRAP_THIS = MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, "wrapThis", MH.type(Object.class, Object.class)); - /** The parent scope. */ + // various property maps used for different kinds of functions + // property map for anonymous function that serves as Function.prototype + private static final PropertyMap anonmap$; + // property map for strict mode functions + private static final PropertyMap strictmodemap$; + // property map for bound functions + private static final PropertyMap boundfunctionmap$; + // property map for non-strict, non-bound functions. + private static final PropertyMap map$; + + // Marker object for lazily initialized prototype object + private static final Object LAZY_PROTOTYPE = new Object(); + + private static PropertyMap createStrictModeMap(final PropertyMap map) { + 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)); + return newMap; + } + + private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) { + // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see + // ECMAScript 5.1 section 15.3.4.5 + return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype")); + } + + static { + anonmap$ = PropertyMap.newMap(); + final ArrayList properties = new ArrayList<>(3); + properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE)); + properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null)); + properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null)); + map$ = PropertyMap.newMap(properties); + strictmodemap$ = createStrictModeMap(map$); + boundfunctionmap$ = createBoundFunctionMap(strictmodemap$); + } + + private static boolean isStrict(final int flags) { + return (flags & ScriptFunctionData.IS_STRICT) != 0; + } + + // Choose the map based on strict mode! + private static PropertyMap getMap(final boolean strict) { + return strict ? strictmodemap$ : map$; + } + + /** + * The parent scope. + */ private final ScriptObject scope; private final ScriptFunctionData data; - /** The property map used for newly allocated object when function is used as constructor. */ + /** + * The property map used for newly allocated object when function is used as + * constructor. + */ protected PropertyMap allocatorMap; /** + * Reference to constructor prototype. + */ + protected Object prototype; + + /** * Constructor * - * @param name function name - * @param methodHandle method handle to function (if specializations are present, assumed to be most generic) - * @param map property map - * @param scope scope - * @param specs specialized version of this function - other method handles - * @param flags {@link ScriptFunctionData} flags + * @param data static function data + * @param map property map + * @param scope scope */ - protected ScriptFunction( + private ScriptFunction( + final ScriptFunctionData data, + final PropertyMap map, + final ScriptObject scope, + final Global global) { + + super(map); + + if (Context.DEBUG) { + constructorCount.increment(); + } + + this.data = data; + this.scope = scope; + this.setInitialProto(global.getFunctionPrototype()); + this.prototype = LAZY_PROTOTYPE; + + // We have to fill user accessor functions late as these are stored + // in this object rather than in the PropertyMap of this object. + assert objectSpill == null; + final ScriptFunction typeErrorThrower = global.getTypeErrorThrower(); + if (findProperty("arguments", true) != null) { + initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); + } + + if (findProperty("caller", true) != null) { + initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); + } + } + + /** + * Constructor + * + * @param name function name + * @param methodHandle method handle to function (if specializations are + * present, assumed to be most generic) + * @param map property map + * @param scope scope + * @param specs specialized version of this function - other method handles + * @param flags {@link ScriptFunctionData} flags + */ + private ScriptFunction( final String name, final MethodHandle methodHandle, final PropertyMap map, final ScriptObject scope, final Specialization[] specs, - final int flags) { - - this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope); + final int flags, + final Global global) { + this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope, global); } /** * Constructor * - * @param data static function data - * @param map property map - * @param scope scope + * @param name name of function + * @param methodHandle handle for invocation + * @param scope scope object + * @param specs specialized versions of this method, if available, null + * otherwise + * @param flags {@link ScriptFunctionData} flags + */ + private ScriptFunction( + final String name, + final MethodHandle methodHandle, + final ScriptObject scope, + final Specialization[] specs, + final int flags) { + this(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags, Global.instance()); + } + + /** + * Constructor called by Nasgen generated code, zero added members, use the + * default map. Creates builtin functions only. + * + * @param name name of function + * @param invokeHandle handle for invocation + * @param specs specialized versions of this method, if available, null + * otherwise + */ + protected ScriptFunction(final String name, final MethodHandle invokeHandle, final Specialization[] specs) { + this(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance()); + } + + /** + * Constructor called by Nasgen generated code, non zero member count, use + * the map passed as argument. Creates builtin functions only. + * + * @param name name of function + * @param invokeHandle handle for invocation + * @param map initial property map + * @param specs specialized versions of this method, if available, null + * otherwise + */ + protected ScriptFunction(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) { + this(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance()); + } + + // Factory methods to create various functions + /** + * Factory method called by compiler generated code for functions that need + * parent scope. + * + * @param constants the generated class' constant array + * @param index the index of the {@code RecompilableScriptFunctionData} + * object in the constants array. + * @param scope the parent scope object + * @return a newly created function object */ - protected ScriptFunction( - final ScriptFunctionData data, - final PropertyMap map, - final ScriptObject scope) { + public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) { + final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constants[index]; + return new ScriptFunction(data, getMap(data.isStrict()), scope, Global.instance()); + } + + /** + * Factory method called by compiler generated code for functions that don't + * need parent scope. + * + * @param constants the generated class' constant array + * @param index the index of the {@code RecompilableScriptFunctionData} + * object in the constants array. + * @return a newly created function object + */ + public static ScriptFunction create(final Object[] constants, final int index) { + return create(constants, index, null); + } + + /** + * Create anonymous function that serves as Function.prototype + * + * @return anonymous function object + */ + public static ScriptFunction createAnonymous() { + return new ScriptFunction("", GlobalFunctions.ANONYMOUS, anonmap$, null); + } + + // builtin function create helper factory + private static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) { + final ScriptFunction func = new ScriptFunction(name, methodHandle, null, specs, flags); + func.setPrototype(UNDEFINED); + // Non-constructor built-in functions do not have "prototype" property + func.deleteOwnProperty(func.getMap().findProperty("prototype")); + + return func; + } - super(map); + /** + * Factory method for non-constructor built-in functions + * + * @param name function name + * @param methodHandle handle for invocation + * @param specs specialized versions of function if available, null + * otherwise + * @return new ScriptFunction + */ + public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs) { + return ScriptFunction.createBuiltin(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN); + } - if (Context.DEBUG) { - constructorCount++; + /** + * Factory method for non-constructor built-in functions + * + * @param name function name + * @param methodHandle handle for invocation + * @return new ScriptFunction + */ + public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle) { + return ScriptFunction.createBuiltin(name, methodHandle, null); + } + + /** + * Factory method for non-constructor built-in, strict functions + * + * @param name function name + * @param methodHandle handle for invocation + * @return new ScriptFunction + */ + public static ScriptFunction createStrictBuiltin(final String name, final MethodHandle methodHandle) { + return ScriptFunction.createBuiltin(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT); + } + + // Subclass to represent bound functions + private static class Bound extends ScriptFunction { + private final ScriptFunction target; + + Bound(final ScriptFunctionData boundData, final ScriptFunction target) { + super(boundData, boundfunctionmap$, null, Global.instance()); + setPrototype(ScriptRuntime.UNDEFINED); + this.target = target; } - this.data = data; - this.scope = scope; + @Override + protected ScriptFunction getTargetFunction() { + return target; + } + } + + /** + * Creates a version of this function bound to a specific "self" and other + * arguments, as per {@code Function.prototype.bind} functionality in + * ECMAScript 5.1 section 15.3.4.5. + * + * @param self the self to bind to this function. Can be null (in which + * case, null is bound as this). + * @param args additional arguments to bind to this function. Can be null or + * empty to not bind additional arguments. + * @return a function with the specified self and parameters bound. + */ + public final ScriptFunction createBound(final Object self, final Object[] args) { + return new Bound(data.makeBoundFunctionData(this, self, args), getTargetFunction()); + } + + /** + * Create a function that invokes this function synchronized on {@code sync} + * or the self object of the invocation. + * + * @param sync the Object to synchronize on, or undefined + * @return synchronized function + */ + public final ScriptFunction createSynchronized(final Object sync) { + final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync); + return createBuiltin(getName(), mh); } @Override @@ -151,8 +413,8 @@ } /** - * ECMA 15.3.5.3 [[HasInstance]] (V) - * Step 3 if "prototype" value is not an Object, throw TypeError + * ECMA 15.3.5.3 [[HasInstance]] (V) Step 3 if "prototype" value is not an + * Object, throw TypeError */ @Override public boolean isInstance(final ScriptObject instance) { @@ -171,22 +433,25 @@ } /** - * Returns the target function for this function. If the function was not created using - * {@link #makeBoundFunction(Object, Object[])}, its target function is itself. If it is bound, its target function - * is the target function of the function it was made from (therefore, the target function is always the final, - * unbound recipient of the calls). + * Returns the target function for this function. If the function was not + * created using {@link #createBound(Object, Object[])}, its target + * function is itself. If it is bound, its target function is the target + * function of the function it was made from (therefore, the target function + * is always the final, unbound recipient of the calls). + * * @return the target function for this function. */ protected ScriptFunction getTargetFunction() { return this; } - boolean isBoundFunction() { + final boolean isBoundFunction() { return getTargetFunction() != this; } /** * Set the arity of this ScriptFunction + * * @param arity arity */ public final void setArity(final int arity) { @@ -195,59 +460,66 @@ /** * Is this a ECMAScript 'use strict' function? + * * @return true if function is in strict mode */ - public boolean isStrict() { + public final boolean isStrict() { return data.isStrict(); } /** - * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument - * according to ECMA 10.4.3. + * Returns true if this is a non-strict, non-built-in function that requires + * non-primitive this argument according to ECMA 10.4.3. + * * @return true if this argument must be an object */ - public boolean needsWrappedThis() { + public final boolean needsWrappedThis() { return data.needsWrappedThis(); } private static boolean needsWrappedThis(final Object fn) { - return fn instanceof ScriptFunction ? ((ScriptFunction)fn).needsWrappedThis() : false; + return fn instanceof ScriptFunction ? ((ScriptFunction) fn).needsWrappedThis() : false; } /** * Execute this script function. - * @param self Target object. - * @param arguments Call arguments. + * + * @param self Target object. + * @param arguments Call arguments. * @return ScriptFunction result. - * @throws Throwable if there is an exception/error with the invocation or thrown from it + * @throws Throwable if there is an exception/error with the invocation or + * thrown from it */ - Object invoke(final Object self, final Object... arguments) throws Throwable { + final Object invoke(final Object self, final Object... arguments) throws Throwable { if (Context.DEBUG) { - invokes++; + invokes.increment(); } return data.invoke(this, self, arguments); } /** * Execute this script function as a constructor. - * @param arguments Call arguments. + * + * @param arguments Call arguments. * @return Newly constructed result. - * @throws Throwable if there is an exception/error with the invocation or thrown from it + * @throws Throwable if there is an exception/error with the invocation or + * thrown from it */ - Object construct(final Object... arguments) throws Throwable { + final Object construct(final Object... arguments) throws Throwable { return data.construct(this, arguments); } /** - * Allocate function. Called from generated {@link ScriptObject} code - * for allocation as a factory method + * Allocate function. Called from generated {@link ScriptObject} code for + * allocation as a factory method * - * @return a new instance of the {@link ScriptObject} whose allocator this is + * @return a new instance of the {@link ScriptObject} whose allocator this + * is */ @SuppressWarnings("unused") private Object allocate() { if (Context.DEBUG) { - allocations++; + allocations.increment(); } assert !isBoundFunction(); // allocate never invoked on bound functions @@ -257,7 +529,7 @@ if (object != null) { final Object prototype = getPrototype(); if (prototype instanceof ScriptObject) { - object.setInitialProto((ScriptObject)prototype); + object.setInitialProto((ScriptObject) prototype); } if (object.getProto() == null) { @@ -277,43 +549,28 @@ /** * Return Object.prototype - used by "allocate" + * * @return Object.prototype */ - protected abstract ScriptObject getObjectPrototype(); - - /** - * Creates a version of this function bound to a specific "self" and other arguments, as per - * {@code Function.prototype.bind} functionality in ECMAScript 5.1 section 15.3.4.5. - * @param self the self to bind to this function. Can be null (in which case, null is bound as this). - * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments. - * @return a function with the specified self and parameters bound. - */ - protected ScriptFunction makeBoundFunction(final Object self, final Object[] args) { - return makeBoundFunction(data.makeBoundFunctionData(this, self, args)); + protected final ScriptObject getObjectPrototype() { + return Global.objectPrototype(); } - /** - * Create a version of this function as in {@link ScriptFunction#makeBoundFunction(Object, Object[])}, - * but using a {@link ScriptFunctionData} for the bound data. - * - * @param boundData ScriptFuntionData for the bound function - * @return a function with the bindings performed according to the given data - */ - protected abstract ScriptFunction makeBoundFunction(ScriptFunctionData boundData); - @Override public final String safeToString() { return toSource(); } @Override - public String toString() { + public final String toString() { return data.toString(); } /** - * Get this function as a String containing its source code. If no source code - * exists in this ScriptFunction, its contents will be displayed as {@code [native code]} + * Get this function as a String containing its source code. If no source + * code exists in this ScriptFunction, its contents will be displayed as + * {@code [native code]} + * * @return string representation of this function's source */ public final String toSource() { @@ -322,27 +579,32 @@ /** * Get the prototype object for this function + * * @return prototype */ - public abstract Object getPrototype(); + public final Object getPrototype() { + if (prototype == LAZY_PROTOTYPE) { + prototype = new PrototypeObject(this); + } + return prototype; + } /** * Set the prototype object for this function - * @param prototype new prototype object + * + * @param newPrototype new prototype object */ - public abstract void setPrototype(Object prototype); + public final void setPrototype(Object newPrototype) { + if (newPrototype instanceof ScriptObject && newPrototype != this.prototype && allocatorMap != null) { + // Replace our current allocator map with one that is associated with the new prototype. + allocatorMap = allocatorMap.changeProto((ScriptObject) newPrototype); + } + this.prototype = newPrototype; + } /** - * Create a function that invokes this function synchronized on {@code sync} or the self object - * of the invocation. - * @param sync the Object to synchronize on, or undefined - * @return synchronized function - */ - public abstract ScriptFunction makeSynchronizedFunction(Object sync); - - /** - * Return the invoke handle bound to a given ScriptObject self reference. - * If callee parameter is required result is rebound to this. + * Return the invoke handle bound to a given ScriptObject self reference. If + * callee parameter is required result is rebound to this. * * @param self self reference * @return bound invoke handle @@ -352,9 +614,12 @@ } /** - * Bind the method handle to this {@code ScriptFunction} instance if it needs a callee parameter. If this function's - * method handles don't have a callee parameter, the handle is returned unchanged. - * @param methodHandle the method handle to potentially bind to this function instance. + * Bind the method handle to this {@code ScriptFunction} instance if it + * needs a callee parameter. If this function's method handles don't have a + * callee parameter, the handle is returned unchanged. + * + * @param methodHandle the method handle to potentially bind to this + * function instance. * @return the potentially bound method handle */ private MethodHandle bindToCalleeIfNeeded(final MethodHandle methodHandle) { @@ -364,15 +629,16 @@ /** * Get the name for this function + * * @return the name */ public final String getName() { return data.getName(); } - /** * Get the scope for this function + * * @return the scope */ public final ScriptObject getScope() { @@ -383,36 +649,37 @@ * Prototype getter for this ScriptFunction - follows the naming convention * used by Nasgen and the code generator * - * @param self self reference + * @param self self reference * @return self's prototype */ public static Object G$prototype(final Object self) { - return self instanceof ScriptFunction ? - ((ScriptFunction)self).getPrototype() : - UNDEFINED; + return self instanceof ScriptFunction + ? ((ScriptFunction) self).getPrototype() + : UNDEFINED; } /** * Prototype setter for this ScriptFunction - follows the naming convention * used by Nasgen and the code generator * - * @param self self reference + * @param self self reference * @param prototype prototype to set */ public static void S$prototype(final Object self, final Object prototype) { if (self instanceof ScriptFunction) { - ((ScriptFunction)self).setPrototype(prototype); + ((ScriptFunction) self).setPrototype(prototype); } } /** * Length getter - ECMA 15.3.3.2: Function.length + * * @param self self reference * @return length */ public static int G$length(final Object self) { if (self instanceof ScriptFunction) { - return ((ScriptFunction)self).data.getArity(); + return ((ScriptFunction) self).data.getArity(); } return 0; @@ -420,12 +687,13 @@ /** * Name getter - ECMA Function.name + * * @param self self refence * @return the name, or undefined if none */ public static Object G$name(final Object self) { if (self instanceof ScriptFunction) { - return ((ScriptFunction)self).getName(); + return ((ScriptFunction) self).getName(); } return UNDEFINED; @@ -433,6 +701,7 @@ /** * Get the prototype for this ScriptFunction + * * @param constructor constructor * @return prototype, or null if given constructor is not a ScriptFunction */ @@ -440,7 +709,7 @@ if (constructor != null) { final Object proto = constructor.getPrototype(); if (proto instanceof ScriptObject) { - return (ScriptObject)proto; + return (ScriptObject) proto; } } @@ -448,29 +717,37 @@ } // These counters are updated only in debug mode. - private static int constructorCount; - private static int invokes; - private static int allocations; + private static LongAdder constructorCount; + private static LongAdder invokes; + private static LongAdder allocations; + + static { + if (Context.DEBUG) { + constructorCount = new LongAdder(); + invokes = new LongAdder(); + allocations = new LongAdder(); + } + } /** * @return the constructorCount */ - public static int getConstructorCount() { - return constructorCount; + public static long getConstructorCount() { + return constructorCount.longValue(); } /** * @return the invokes */ - public static int getInvokes() { - return invokes; + public static long getInvokes() { + return invokes.longValue(); } /** * @return the allocations */ - public static int getAllocations() { - return allocations; + public static long getAllocations() { + return allocations.longValue(); } @Override @@ -490,7 +767,6 @@ return Context.getGlobal().wrapAsObject(obj); } - @SuppressWarnings("unused") private static Object globalFilter(final Object object) { // replace whatever we get with the current global object @@ -498,14 +774,16 @@ } /** - * Some receivers are primitive, in that case, according to the Spec we create a new - * native object per callsite with the wrap filter. We can only apply optimistic builtins - * if there is no per instance state saved for these wrapped objects (e.g. currently NativeStrings), - * otherwise we can't create optimistic versions + * Some receivers are primitive, in that case, according to the Spec we + * create a new native object per callsite with the wrap filter. We can only + * apply optimistic builtins if there is no per instance state saved for + * these wrapped objects (e.g. currently NativeStrings), otherwise we can't + * create optimistic versions * - * @param self receiver - * @param linkLogicClass linkLogicClass, or null if no link logic exists - * @return link logic instance, or null if one could not be constructed for this receiver + * @param self receiver + * @param linkLogicClass linkLogicClass, or null if no link logic exists + * @return link logic instance, or null if one could not be constructed for + * this receiver */ private static LinkLogic getLinkLogic(final Object self, final Class linkLogicClass) { if (linkLogicClass == null) { @@ -518,25 +796,25 @@ final Object wrappedSelf = wrapFilter(self); if (wrappedSelf instanceof OptimisticBuiltins) { - if (wrappedSelf != self && ((OptimisticBuiltins)wrappedSelf).hasPerInstanceAssumptions()) { + if (wrappedSelf != self && ((OptimisticBuiltins) wrappedSelf).hasPerInstanceAssumptions()) { return null; //pessimistic - we created a wrapped object different from the primitive, but the assumptions have instance state } - return ((OptimisticBuiltins)wrappedSelf).getLinkLogic(linkLogicClass); + return ((OptimisticBuiltins) wrappedSelf).getLinkLogic(linkLogicClass); } return null; } /** - * dyn:call call site signature: (callee, thiz, [args...]) - * generated method signature: (callee, thiz, [args...]) + * dyn:call call site signature: (callee, thiz, [args...]) generated method + * signature: (callee, thiz, [args...]) * * cases: * (a) method has callee parameter - * (1) for local/scope calls, we just bind thiz and drop the second argument. - * (2) for normal this-calls, we have to swap thiz and callee to get matching signatures. + * (1) for local/scope calls, we just bind thiz and drop the second argument. + * (2) for normal this-calls, we have to swap thiz and callee to get matching signatures. * (b) method doesn't have callee parameter (builtin functions) - * (3) for local/scope calls, bind thiz and drop both callee and thiz. - * (4) for normal this-calls, drop callee. + * (3) for local/scope calls, bind thiz and drop both callee and thiz. + * (4) for normal this-calls, drop callee. * * @return guarded invocation for call */ @@ -544,11 +822,11 @@ protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) { final MethodType type = desc.getMethodType(); - final String name = getName(); + final String name = getName(); final boolean isUnstable = request.isCallSiteUnstable(); - final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc); - final boolean isCall = !scopeCall && data.isBuiltin() && "call".equals(name); - final boolean isApply = !scopeCall && data.isBuiltin() && "apply".equals(name); + final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc); + final boolean isCall = !scopeCall && data.isBuiltin() && "call".equals(name); + final boolean isApply = !scopeCall && data.isBuiltin() && "apply".equals(name); final boolean isApplyOrCall = isCall | isApply; @@ -569,7 +847,7 @@ return new GuardedInvocation( handle, null, - (SwitchPoint)null, + (SwitchPoint) null, ClassCastException.class); } @@ -672,14 +950,14 @@ this, cf.getFlags()) : guard, - spsArray, + spsArray, exceptionGuard); } private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) { final MethodType descType = desc.getMethodType(); final int paramCount = descType.parameterCount(); - if(descType.parameterType(paramCount - 1).isArray()) { + if (descType.parameterType(paramCount - 1).isArray()) { // This is vararg invocation of apply or call. This can normally only happen when we do a recursive // invocation of createApplyOrCallCall (because we're doing apply-of-apply). In this case, create delegate // linkage by unpacking the vararg invocation and use pairArguments to introduce the necessary spreader. @@ -786,7 +1064,7 @@ inv = MH.filterArguments(inv, 2, NativeFunction.TO_APPLY_ARGS); } else { // If the original call site doesn't pass argArray, pass in an empty array - inv = MH.insertArguments(inv, 2, (Object)ScriptRuntime.EMPTY_ARRAY); + inv = MH.insertArguments(inv, 2, (Object) ScriptRuntime.EMPTY_ARRAY); } } @@ -851,7 +1129,7 @@ final LinkRequest request, final Object[] args) { final MethodType descType = desc.getMethodType(); final int paramCount = descType.parameterCount(); - final Object[] varArgs = (Object[])args[paramCount - 1]; + final Object[] varArgs = (Object[]) args[paramCount - 1]; // -1 'cause we're not passing the vararg array itself final int copiedArgCount = args.length - 1; final int varArgCount = varArgs.length; @@ -893,7 +1171,7 @@ // If the last parameter type of the guard is an array, then it is already itself a guard for a vararg apply // invocation. We must filter the last argument with toApplyArgs otherwise deeper levels of nesting will fail // with ClassCastException of NativeArray to Object[]. - if(guardType.parameterType(guardParamCount - 1).isArray()) { + if (guardType.parameterType(guardParamCount - 1).isArray()) { arrayConvertingGuard = MH.filterArguments(guard, guardParamCount - 1, NativeFunction.TO_APPLY_ARGS); } else { arrayConvertingGuard = guard; @@ -903,19 +1181,20 @@ } private static MethodHandle bindImplicitThis(final Object fn, final MethodHandle mh) { - final MethodHandle bound; - if(fn instanceof ScriptFunction && ((ScriptFunction)fn).needsWrappedThis()) { - bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER); - } else { - bound = mh; - } - return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED); - } + final MethodHandle bound; + if (fn instanceof ScriptFunction && ((ScriptFunction) fn).needsWrappedThis()) { + bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER); + } else { + bound = mh; + } + return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED); + } /** * Used for noSuchMethod/noSuchProperty and JSAdapter hooks. * - * These don't want a callee parameter, so bind that. Name binding is optional. + * These don't want a callee parameter, so bind that. Name binding is + * optional. */ MethodHandle getCallMethodHandle(final MethodType type, final String bindName) { return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(data.getGenericInvoker(scope)), bindName), type); @@ -939,10 +1218,11 @@ } /** - * Get the guard that checks if a {@link ScriptFunction} is equal to - * a known ScriptFunction, using reference comparison + * Get the guard that checks if a {@link ScriptFunction} is equal to a known + * ScriptFunction, using reference comparison * - * @param function The ScriptFunction to check against. This will be bound to the guard method handle + * @param function The ScriptFunction to check against. This will be bound + * to the guard method handle * * @return method handle for guard */ @@ -957,11 +1237,12 @@ } /** - * Get a guard that checks if a {@link ScriptFunction} is equal to - * a known ScriptFunction using reference comparison, and whether the type of - * the second argument (this-object) is not a JavaScript primitive type. + * Get a guard that checks if a {@link ScriptFunction} is equal to a known + * ScriptFunction using reference comparison, and whether the type of the + * second argument (this-object) is not a JavaScript primitive type. * - * @param function The ScriptFunction to check against. This will be bound to the guard method handle + * @param function The ScriptFunction to check against. This will be bound + * to the guard method handle * * @return method handle for guard */ @@ -972,12 +1253,12 @@ @SuppressWarnings("unused") private static boolean isFunctionMH(final Object self, final ScriptFunctionData data) { - return self instanceof ScriptFunction && ((ScriptFunction)self).data == data; + return self instanceof ScriptFunction && ((ScriptFunction) self).data == data; } @SuppressWarnings("unused") private static boolean isNonStrictFunction(final Object self, final Object arg, final ScriptFunctionData data) { - return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject; + return self instanceof ScriptFunction && ((ScriptFunction) self).data == data && arg instanceof ScriptObject; } //TODO this can probably be removed given that we have builtin switchpoints in the context @@ -990,7 +1271,7 @@ @SuppressWarnings("unused") private static Object[] addZerothElement(final Object[] args, final Object value) { // extends input array with by adding new zeroth element - final Object[] src = args == null? ScriptRuntime.EMPTY_ARRAY : args; + final Object[] src = args == null ? ScriptRuntime.EMPTY_ARRAY : args; final Object[] result = new Object[src.length + 1]; System.arraycopy(src, 0, result, 1, src.length); result[0] = value; @@ -1014,4 +1295,3 @@ return MH.findVirtual(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types)); } } - diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Sep 09 17:19:46 2015 +0530 @@ -397,7 +397,7 @@ /** * This method is used to create the immutable portion of a bound function. - * See {@link ScriptFunction#makeBoundFunction(Object, Object[])} + * See {@link ScriptFunction#createBound(Object, Object[])} * * @param fn the original function being bound * @param self this reference to bind. Can be null. diff -r 330ddba6ffc4 -r a750a66640e0 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 Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Wed Sep 09 17:19:46 2015 +0530 @@ -64,6 +64,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.LongAdder; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; @@ -211,7 +212,7 @@ */ public ScriptObject(final PropertyMap map) { if (Context.DEBUG) { - ScriptObject.count++; + ScriptObject.count.increment(); } this.arrayData = ArrayData.EMPTY_ARRAY; this.setMap(map == null ? PropertyMap.newMap() : map); @@ -2316,7 +2317,7 @@ MH.dropArguments( MH.constant( ScriptFunction.class, - func.makeBoundFunction(thiz, new Object[] { name })), + func.createBound(thiz, new Object[] { name })), 0, Object.class), NashornGuards.combineGuards( @@ -2422,7 +2423,7 @@ return UNDEFINED; } - return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name}); + return ((ScriptFunction)value).createBound(this, new Object[] {name}); } private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) { @@ -3811,15 +3812,20 @@ } /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */ - private static int count; - + private static LongAdder count; + + static { + if (Context.DEBUG) { + count = new LongAdder(); + } + } /** * Get number of {@code ScriptObject} instances created. If not running in debug * mode this is always 0 * * @return number of ScriptObjects created */ - public static int getCount() { - return count; + public static long getCount() { + return count.longValue(); } } diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java Wed Sep 09 17:19:46 2015 +0530 @@ -352,7 +352,7 @@ } private static Object bindToExpression(final ScriptFunction fn, final Object receiver) { - return fn.makeBoundFunction(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY); + return fn.createBound(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY); } private MethodHandle expressionGuard(final String name, final ScriptObject owner) { diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Sep 09 17:19:46 2015 +0530 @@ -49,7 +49,6 @@ import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; -import jdk.nashorn.internal.objects.ScriptFunctionImpl; import jdk.nashorn.internal.runtime.ECMAException; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.OptimisticReturnFilters; @@ -396,8 +395,8 @@ * @throws ECMAException with {@code TypeError} if the object is not a callable. */ public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) { - if (callable instanceof ScriptFunctionImpl) { - return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs); + if (callable instanceof ScriptFunction) { + return ((ScriptFunction)callable).createBound(boundThis, boundArgs); } else if (callable instanceof BoundCallable) { return ((BoundCallable)callable).bind(boundArgs); } else if (isCallable(callable)) { diff -r 330ddba6ffc4 -r a750a66640e0 src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Wed Sep 09 09:36:48 2015 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Wed Sep 09 17:19:46 2015 +0530 @@ -43,6 +43,7 @@ import java.util.Random; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.LongAdder; import jdk.internal.dynalink.ChainedCallSite; import jdk.internal.dynalink.DynamicLinker; import jdk.internal.dynalink.linker.GuardedInvocation; @@ -70,7 +71,7 @@ LinkerCallSite(final NashornCallSiteDescriptor descriptor) { super(descriptor); if (Context.DEBUG) { - LinkerCallSite.count++; + LinkerCallSite.count.increment(); } } @@ -173,7 +174,7 @@ * @return self reference */ public static Object increaseMissCount(final String desc, final Object self) { - ++missCount; + missCount.increment(); if (r.nextInt(100) < missSamplingPercentage) { final AtomicInteger i = missCounts.get(desc); if (i == null) { @@ -509,12 +510,19 @@ } // counters updated in debug mode - private static int count; + private static LongAdder count; private static final HashMap missCounts = new HashMap<>(); - private static int missCount; + private static LongAdder missCount; private static final Random r = new Random(); private static final int missSamplingPercentage = Options.getIntProperty("nashorn.tcs.miss.samplePercent", 1); + static { + if (Context.DEBUG) { + count = new LongAdder(); + missCount = new LongAdder(); + } + } + @Override protected int getMaxChainLength() { return 8; @@ -524,16 +532,16 @@ * Get the callsite count * @return the count */ - public static int getCount() { - return count; + public static long getCount() { + return count.longValue(); } /** * Get the callsite miss count * @return the missCount */ - public static int getMissCount() { - return missCount; + public static long getMissCount() { + return missCount.longValue(); } /**