aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/ir/FunctionNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/ir/FunctionNode.java')
-rw-r--r--src/jdk/nashorn/internal/ir/FunctionNode.java228
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());
}
-
}