Mon, 12 Jan 2015 14:32:32 +0100
8068784: Halve the function object creation code size
Reviewed-by: hannesw, sundar
1.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Jan 12 11:29:42 2015 +0100 1.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Jan 12 14:32:32 2015 +0100 1.3 @@ -38,7 +38,6 @@ 1.4 import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX; 1.5 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; 1.6 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; 1.7 -import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; 1.8 import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup; 1.9 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; 1.10 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; 1.11 @@ -186,9 +185,6 @@ 1.12 1.13 private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class); 1.14 1.15 - private static final String SCRIPTFUNCTION_IMPL_NAME = Type.getInternalName(ScriptFunctionImpl.class); 1.16 - private static final Type SCRIPTFUNCTION_IMPL_TYPE = Type.typeFor(ScriptFunction.class); 1.17 - 1.18 private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class, 1.19 "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class); 1.20 private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class, 1.21 @@ -201,6 +197,11 @@ 1.22 private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, 1.23 "ensureNumber", double.class, Object.class, int.class); 1.24 1.25 + private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, 1.26 + "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class); 1.27 + private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, 1.28 + "create", ScriptFunction.class, Object[].class, int.class); 1.29 + 1.30 private static final Class<?> ITERATOR_CLASS = Iterator.class; 1.31 static { 1.32 assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type(); 1.33 @@ -2242,7 +2243,6 @@ 1.34 } else { 1.35 methodEmitter.loadConstants().load(index).arrayload(); 1.36 if (object instanceof ArrayData) { 1.37 - // avoid cast to non-public ArrayData subclass 1.38 methodEmitter.checkcast(ArrayData.class); 1.39 methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class)); 1.40 } else if (cls != Object.class) { 1.41 @@ -2251,6 +2251,10 @@ 1.42 } 1.43 } 1.44 1.45 + private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) { 1.46 + methodEmitter.loadConstants().load(compiler.getConstantData().add(object)); 1.47 + } 1.48 + 1.49 // literal values 1.50 private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) { 1.51 final Object value = node.getValue(); 1.52 @@ -4322,15 +4326,13 @@ 1.53 final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId()); 1.54 1.55 if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) { 1.56 - final CompileUnit fnUnit = functionNode.getCompileUnit(); 1.57 - final MethodEmitter createFunction = fnUnit.getClassEmitter().method( 1.58 + final MethodEmitter createFunction = functionNode.getCompileUnit().getClassEmitter().method( 1.59 EnumSet.of(Flag.PUBLIC, Flag.STATIC), CREATE_PROGRAM_FUNCTION.symbolName(), 1.60 ScriptFunction.class, ScriptObject.class); 1.61 createFunction.begin(); 1.62 - createFunction._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup(); 1.63 - loadConstant(data, fnUnit, createFunction); 1.64 + loadConstantsAndIndex(data, createFunction); 1.65 createFunction.load(SCOPE_TYPE, 0); 1.66 - createFunction.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class)); 1.67 + createFunction.invoke(CREATE_FUNCTION_OBJECT); 1.68 createFunction._return(); 1.69 createFunction.end(); 1.70 } 1.71 @@ -4345,15 +4347,14 @@ 1.72 return; 1.73 } 1.74 1.75 - method._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup(); 1.76 - loadConstant(data); 1.77 + loadConstantsAndIndex(data, method); 1.78 1.79 if (functionNode.needsParentScope()) { 1.80 method.loadCompilerConstant(SCOPE); 1.81 + method.invoke(CREATE_FUNCTION_OBJECT); 1.82 } else { 1.83 - method.loadNull(); 1.84 - } 1.85 - method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class)); 1.86 + method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE); 1.87 + } 1.88 } 1.89 1.90 // calls on Global class.
2.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Mon Jan 12 11:29:42 2015 +0100 2.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Mon Jan 12 14:32:32 2015 +0100 2.3 @@ -118,13 +118,26 @@ 2.4 } 2.5 2.6 /** 2.7 - * Constructor called by (compiler) generated code for {@link ScriptObject}s. 2.8 + * Factory method called by compiler generated code for functions that need parent scope. 2.9 * 2.10 - * @param data static function data 2.11 - * @param scope scope object 2.12 + * @param constants the generated class' constant array 2.13 + * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array. 2.14 + * @param scope the parent scope object 2.15 + * @return a newly created function object 2.16 */ 2.17 - public ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope) { 2.18 - this(data, scope, Global.instance()); 2.19 + public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) { 2.20 + return new ScriptFunctionImpl((RecompilableScriptFunctionData)constants[index], scope, Global.instance()); 2.21 + } 2.22 + 2.23 + /** 2.24 + * Factory method called by compiler generated code for functions that don't need parent scope. 2.25 + * 2.26 + * @param constants the generated class' constant array 2.27 + * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array. 2.28 + * @return a newly created function object 2.29 + */ 2.30 + public static ScriptFunction create(final Object[] constants, final int index) { 2.31 + return create(constants, index, null); 2.32 } 2.33 2.34 /**