diff options
Diffstat (limited to 'src/jdk/nashorn/internal/ir/FunctionNode.java')
-rw-r--r-- | src/jdk/nashorn/internal/ir/FunctionNode.java | 228 |
1 files changed, 155 insertions, 73 deletions
diff --git a/src/jdk/nashorn/internal/ir/FunctionNode.java b/src/jdk/nashorn/internal/ir/FunctionNode.java index 60fe64ff..2b6d19bf 100644 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java @@ -25,16 +25,12 @@ package jdk.nashorn.internal.ir; -import static jdk.nashorn.internal.codegen.CompilerConstants.LITERAL_PREFIX; -import static jdk.nashorn.internal.codegen.CompilerConstants.TEMP_PREFIX; -import static jdk.nashorn.internal.ir.Symbol.IS_CONSTANT; -import static jdk.nashorn.internal.ir.Symbol.IS_TEMP; - import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; + import jdk.nashorn.internal.codegen.CompileUnit; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.CompilerConstants; @@ -90,11 +86,17 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func /** method has been emitted to bytecode */ EMITTED } + /** Source of entity. */ + private final Source source; /** External function identifier. */ @Ignore private final IdentNode ident; + /** Parsed version of functionNode */ + @Ignore + private final FunctionNode snapshot; + /** The body of the function node */ private final Block body; @@ -127,6 +129,9 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func @Ignore private final EnumSet<CompilationState> compilationState; + @Ignore + private final Compiler.Hints hints; + /** Function flags. */ private final int flags; @@ -176,6 +181,9 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func /** Does this function have nested declarations? */ public static final int HAS_FUNCTION_DECLARATIONS = 1 << 13; + /** Can this function be specialized? */ + public static final int CAN_SPECIALIZE = 1 << 14; + /** Does this function or any nested functions contain an eval? */ private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL; @@ -196,6 +204,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func * Constructor * * @param source the source + * @param lineNumber line number * @param token token * @param finish finish * @param firstToken first token of the funtion node (including the function declaration) @@ -208,6 +217,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func */ public FunctionNode( final Source source, + final int lineNumber, final long token, final int finish, final long firstToken, @@ -217,39 +227,56 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func final List<IdentNode> parameters, final FunctionNode.Kind kind, final int flags) { - super(source, token, finish); - - this.ident = ident; - this.name = name; - this.kind = kind; - this.parameters = parameters; - this.firstToken = firstToken; - this.lastToken = token; - this.namespace = namespace; - this.compilationState = EnumSet.of(CompilationState.INITIALIZED); - this.declaredSymbols = new HashSet<>(); - this.flags = flags; - this.compileUnit = null; - this.body = null; - } - - private FunctionNode(final FunctionNode functionNode, final long lastToken, final int flags, final Type returnType, final CompileUnit compileUnit, final EnumSet<CompilationState> compilationState, final Block body) { + super(lineNumber, token, finish); + + this.source = source; + this.ident = ident; + this.name = name; + this.kind = kind; + this.parameters = parameters; + this.firstToken = firstToken; + this.lastToken = token; + this.namespace = namespace; + this.compilationState = EnumSet.of(CompilationState.INITIALIZED); + this.declaredSymbols = new HashSet<>(); + this.flags = flags; + this.compileUnit = null; + this.body = null; + this.snapshot = null; + this.hints = null; + } + + private FunctionNode( + final FunctionNode functionNode, + final long lastToken, + final int flags, + final Type returnType, + final CompileUnit compileUnit, + final EnumSet<CompilationState> compilationState, + final Block body, + final List<IdentNode> parameters, + final FunctionNode snapshot, + final Compiler.Hints hints) { super(functionNode); - this.flags = flags; - this.returnType = returnType; - this.compileUnit = compileUnit; - this.lastToken = lastToken; + + this.flags = flags; + this.returnType = returnType; + this.compileUnit = compileUnit; + this.lastToken = lastToken; this.compilationState = compilationState; - this.body = body; + this.body = body; + this.parameters = parameters; + this.snapshot = snapshot; + this.hints = hints; // the fields below never change - they are final and assigned in constructor - this.name = functionNode.name; - this.ident = functionNode.ident; - this.namespace = functionNode.namespace; + this.source = functionNode.source; + this.name = functionNode.name; + this.ident = functionNode.ident; + this.namespace = functionNode.namespace; this.declaredSymbols = functionNode.declaredSymbols; - this.kind = functionNode.kind; - this.parameters = functionNode.parameters; - this.firstToken = functionNode.firstToken; + this.kind = functionNode.kind; + this.firstToken = functionNode.firstToken; } @Override @@ -261,6 +288,61 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func } /** + * Get the source for this function + * @return the source + */ + public Source getSource() { + return source; + } + + /** + * Get the version of this function node's code as it looked upon construction + * i.e typically parsed and nothing else + * @return initial version of function node + */ + public FunctionNode getSnapshot() { + return snapshot; + } + + /** + * Throw away the snapshot, if any, to save memory. Used when heuristic + * determines that a method is not worth specializing + * + * @param lc lexical context + * @return new function node if a snapshot was present, now with snapsnot null + */ + public FunctionNode clearSnapshot(final LexicalContext lc) { + if (this.snapshot == null) { + return this; + } + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, null, hints)); + } + + /** + * Take a snapshot of this function node at a given point in time + * and store it in the function node + * @param lc lexical context + * @return function node + */ + public FunctionNode snapshot(final LexicalContext lc) { + if (this.snapshot == this) { + return this; + } + if (isProgram() || parameters.isEmpty()) { + return this; //never specialize anything that won't be recompiled + } + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, this, hints)); + } + + /** + * Can this function node be regenerated with more specific type args? + * @return true if specialization is possible + */ + public boolean canSpecialize() { + return getFlag(CAN_SPECIALIZE); + } + + /** * Get the compilation state of this function * @return the compilation state */ @@ -307,7 +389,28 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func } final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); newState.add(state); - return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, newState, body)); + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, newState, body, parameters, snapshot, hints)); + } + + /** + * Get any compiler hints that may associated with the function + * @return compiler hints + */ + public Compiler.Hints getHints() { + return this.hints == null ? Compiler.Hints.EMPTY : hints; + } + + /** + * Set compiler hints for this function + * @param lc lexical context + * @param hints compiler hints + * @return new function if hints changed + */ + public FunctionNode setHints(final LexicalContext lc, final Compiler.Hints hints) { + if (this.hints == hints) { + return this; + } + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); } /** @@ -319,20 +422,6 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func return namespace.uniqueName(base); } - /** - * Create a virtual symbol for a literal. - * - * @param literalNode Primary node to use symbol. - * - * @return Symbol used. - */ - public Symbol newLiteral(final LiteralNode<?> literalNode) { - final String uname = uniqueName(LITERAL_PREFIX.symbolName()); - final Symbol symbol = new Symbol(uname, IS_CONSTANT, literalNode.getType()); - literalNode.setSymbol(symbol); - - return symbol; - } @Override public void toString(final StringBuilder sb) { @@ -374,7 +463,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func if (this.flags == flags) { return this; } - return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body)); + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); } @Override @@ -483,7 +572,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func if(this.body == body) { return this; } - return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body)); + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); } /** @@ -551,7 +640,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func if (this.lastToken == lastToken) { return this; } - return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body)); + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); } /** @@ -599,13 +688,17 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func } /** - * Get a specialized type for an identity, if one exists - * @param node node to check specialized type for - * @return null if no specialization exists, otherwise type + * Reset the compile unit used to compile this function + * @see Compiler + * @param lc lexical context + * @param parameters the compile unit + * @return function node or a new one if state was changed */ - @SuppressWarnings("static-method") - public Type getSpecializedType(final IdentNode node) { - return null; //TODO implement specialized types later + public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) { + if (this.parameters == parameters) { + return this; + } + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); } /** @@ -674,7 +767,10 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func returnType), compileUnit, compilationState, - body)); + body, + parameters, + snapshot, + hints)); } /** @@ -705,7 +801,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func if (this.compileUnit == compileUnit) { return this; } - return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body)); + return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); } /** @@ -717,19 +813,6 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func * * @return Symbol used. */ - public Symbol ensureSymbol(final Block block, final Type type, final Node node) { - Symbol symbol = node.getSymbol(); - - // If no symbol already present. - if (symbol == null) { - final String uname = uniqueName(TEMP_PREFIX.symbolName()); - symbol = new Symbol(uname, IS_TEMP, type); - block.putSymbol(uname, symbol); - node.setSymbol(symbol); - } - - return symbol; - } /** * Get the symbol for a compiler constant, or null if not available (yet) @@ -739,5 +822,4 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func public Symbol compilerConstant(final CompilerConstants cc) { return body.getExistingSymbol(cc.symbolName()); } - } |