8068784: Halve the function object creation code size
Reviewed-by: hannesw, sundar
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Jan 12 11:29:42 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Jan 12 14:32:32 2015 +0100
@@ -38,7 +38,6 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
@@ -186,9 +185,6 @@
private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class);
- private static final String SCRIPTFUNCTION_IMPL_NAME = Type.getInternalName(ScriptFunctionImpl.class);
- private static final Type SCRIPTFUNCTION_IMPL_TYPE = Type.typeFor(ScriptFunction.class);
-
private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
"create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class,
@@ -201,6 +197,11 @@
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,
+ "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
+ private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
+ "create", ScriptFunction.class, Object[].class, int.class);
+
private static final Class<?> ITERATOR_CLASS = Iterator.class;
static {
assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
@@ -2242,7 +2243,6 @@
} else {
methodEmitter.loadConstants().load(index).arrayload();
if (object instanceof ArrayData) {
- // avoid cast to non-public ArrayData subclass
methodEmitter.checkcast(ArrayData.class);
methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
} else if (cls != Object.class) {
@@ -2251,6 +2251,10 @@
}
}
+ private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) {
+ methodEmitter.loadConstants().load(compiler.getConstantData().add(object));
+ }
+
// literal values
private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
final Object value = node.getValue();
@@ -4323,15 +4327,13 @@
final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId());
if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
- final CompileUnit fnUnit = functionNode.getCompileUnit();
- final MethodEmitter createFunction = fnUnit.getClassEmitter().method(
+ final MethodEmitter createFunction = functionNode.getCompileUnit().getClassEmitter().method(
EnumSet.of(Flag.PUBLIC, Flag.STATIC), CREATE_PROGRAM_FUNCTION.symbolName(),
ScriptFunction.class, ScriptObject.class);
createFunction.begin();
- createFunction._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
- loadConstant(data, fnUnit, createFunction);
+ loadConstantsAndIndex(data, createFunction);
createFunction.load(SCOPE_TYPE, 0);
- createFunction.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
+ createFunction.invoke(CREATE_FUNCTION_OBJECT);
createFunction._return();
createFunction.end();
}
@@ -4346,15 +4348,14 @@
return;
}
- method._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
- loadConstant(data);
+ loadConstantsAndIndex(data, method);
if (functionNode.needsParentScope()) {
method.loadCompilerConstant(SCOPE);
+ method.invoke(CREATE_FUNCTION_OBJECT);
} else {
- method.loadNull();
- }
- method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
+ method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE);
+ }
}
// calls on Global class.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Mon Jan 12 11:29:42 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Mon Jan 12 14:32:32 2015 +0100
@@ -118,13 +118,26 @@
}
/**
- * Constructor called by (compiler) generated code for {@link ScriptObject}s.
+ * Factory method called by compiler generated code for functions that need parent scope.
*
- * @param data static function data
- * @param scope scope object
+ * @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 ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope) {
- this(data, scope, Global.instance());
+ 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);
}
/**