8068784: Halve the function object creation code size

Reviewed-by: hannesw, sundar
This commit is contained in:
Attila Szegedi 2015-01-12 14:32:32 +01:00
parent faf445e144
commit fb821c2f75
2 changed files with 33 additions and 19 deletions

View File

@ -38,7 +38,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
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 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
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 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
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 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
} 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 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
}
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 class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
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 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
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(CREATE_FUNCTION_OBJECT_NO_SCOPE);
}
method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
}
// calls on Global class.

View File

@ -118,13 +118,26 @@ public class ScriptFunctionImpl extends ScriptFunction {
}
/**
* 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);
}
/**