8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
Reviewed-by: attila, jlaskey
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Thu May 23 15:51:08 2013 +0200
@@ -84,8 +84,8 @@
import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.ir.VarNode;
import jdk.nashorn.internal.ir.WithNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
@@ -111,7 +111,7 @@
* computed.
*/
-final class Attr extends NodeOperatorVisitor {
+final class Attr extends NodeOperatorVisitor<LexicalContext> {
/**
* Local definitions in current block (to discriminate from function
@@ -138,6 +138,7 @@
* Constructor.
*/
Attr(final TemporarySymbols temporarySymbols) {
+ super(new LexicalContext());
this.temporarySymbols = temporarySymbols;
this.localDefs = new ArrayDeque<>();
this.localUses = new ArrayDeque<>();
@@ -202,7 +203,7 @@
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
// This visitor will assign symbol to all declared variables, except function declarations (which are taken care
// in a separate step above) and "var" declarations in for loop initializers.
- body.accept(new NodeOperatorVisitor() {
+ body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterFunctionNode(final FunctionNode nestedFn) {
return false;
@@ -218,7 +219,7 @@
if (varNode.isFunctionDeclaration()) {
newType(symbol, FunctionNode.FUNCTION_TYPE);
}
- return varNode.setName((IdentNode)ident.setSymbol(getLexicalContext(), symbol));
+ return varNode.setName((IdentNode)ident.setSymbol(lc, symbol));
}
return varNode;
}
@@ -227,8 +228,8 @@
private void enterFunctionBody() {
- final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
- final Block body = getLexicalContext().getCurrentBlock();
+ final FunctionNode functionNode = lc.getCurrentFunction();
+ final Block body = lc.getCurrentBlock();
initFunctionWideVariables(functionNode, body);
@@ -256,7 +257,7 @@
//the symbols in the block should really be stateless
block.clearSymbols();
- if (getLexicalContext().isFunctionBody()) {
+ if (lc.isFunctionBody()) {
enterFunctionBody();
}
pushLocalsBlock();
@@ -283,7 +284,7 @@
@Override
public boolean enterCatchNode(final CatchNode catchNode) {
final IdentNode exception = catchNode.getException();
- final Block block = getLexicalContext().getCurrentBlock();
+ final Block block = lc.getCurrentBlock();
start(catchNode);
@@ -298,10 +299,10 @@
@Override
public Node leaveCatchNode(final CatchNode catchNode) {
final IdentNode exception = catchNode.getException();
- final Block block = getLexicalContext().getCurrentBlock();
+ final Block block = lc.getCurrentBlock();
final Symbol symbol = findSymbol(block, exception.getName());
assert symbol != null;
- return end(catchNode.setException((IdentNode)exception.setSymbol(getLexicalContext(), symbol)));
+ return end(catchNode.setException((IdentNode)exception.setSymbol(lc, symbol)));
}
/**
@@ -320,7 +321,7 @@
flags |= IS_SCOPE;
}
- final FunctionNode function = getLexicalContext().getFunction(block);
+ final FunctionNode function = lc.getFunction(block);
if (symbol != null) {
// Symbol was already defined. Check if it needs to be redefined.
if ((flags & KINDMASK) == IS_PARAM) {
@@ -353,12 +354,12 @@
if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
symbolBlock = block; //internal vars are always defined in the block closest to them
} else {
- symbolBlock = getLexicalContext().getFunctionBody(function);
+ symbolBlock = lc.getFunctionBody(function);
}
// Create and add to appropriate block.
symbol = new Symbol(name, flags);
- symbolBlock.putSymbol(getLexicalContext(), symbol);
+ symbolBlock.putSymbol(lc, symbol);
if ((flags & Symbol.KINDMASK) != IS_GLOBAL) {
symbol.setNeedsSlot(true);
@@ -381,7 +382,7 @@
//an outermost function in our lexical context that is not a program (runScript)
//is possible - it is a function being compiled lazily
if (functionNode.isDeclared()) {
- final Iterator<Block> blocks = getLexicalContext().getBlocks();
+ final Iterator<Block> blocks = lc.getBlocks();
if (blocks.hasNext()) {
defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR);
}
@@ -397,13 +398,11 @@
public Node leaveFunctionNode(final FunctionNode functionNode) {
FunctionNode newFunctionNode = functionNode;
- final LexicalContext lc = getLexicalContext();
-
final Block body = newFunctionNode.getBody();
//look for this function in the parent block
if (functionNode.isDeclared()) {
- final Iterator<Block> blocks = getLexicalContext().getBlocks();
+ final Iterator<Block> blocks = lc.getBlocks();
if (blocks.hasNext()) {
newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, findSymbol(blocks.next(), functionNode.getIdent().getName()));
}
@@ -411,7 +410,7 @@
final boolean anonymous = functionNode.isAnonymous();
final String name = anonymous ? null : functionNode.getIdent().getName();
if (anonymous || body.getExistingSymbol(name) != null) {
- newFunctionNode = (FunctionNode)ensureSymbol(lc, FunctionNode.FUNCTION_TYPE, newFunctionNode);
+ newFunctionNode = (FunctionNode)ensureSymbol(FunctionNode.FUNCTION_TYPE, newFunctionNode);
} else {
assert name != null;
final Symbol self = body.getExistingSymbol(name);
@@ -490,8 +489,6 @@
start(identNode);
- final LexicalContext lc = getLexicalContext();
-
if (identNode.isPropertyName()) {
// assign a pseudo symbol to property name
final Symbol pseudoSymbol = pseudoSymbol(name);
@@ -549,7 +546,7 @@
*/
private void maybeForceScope(final Symbol symbol) {
if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) {
- Symbol.setSymbolIsScope(getLexicalContext(), symbol);
+ Symbol.setSymbolIsScope(lc, symbol);
}
}
@@ -558,7 +555,7 @@
return false;
}
boolean previousWasBlock = false;
- for(final Iterator<LexicalContextNode> it = getLexicalContext().getAllNodes(); it.hasNext();) {
+ for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
final LexicalContextNode node = it.next();
if(node instanceof FunctionNode) {
// We reached the function boundary without seeing a definition for the symbol - it needs to be in
@@ -594,10 +591,8 @@
}
if (symbol.isScope()) {
- final LexicalContext lc = getLexicalContext();
-
Block scopeBlock = null;
- for (final Iterator<LexicalContextNode> contextNodeIter = getLexicalContext().getAllNodes(); contextNodeIter.hasNext(); ) {
+ for (final Iterator<LexicalContextNode> contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) {
final LexicalContextNode node = contextNodeIter.next();
if (node instanceof Block) {
if (((Block)node).getExistingSymbol(name) != null) {
@@ -610,7 +605,7 @@
}
if (scopeBlock != null) {
- assert getLexicalContext().contains(scopeBlock);
+ assert lc.contains(scopeBlock);
lc.setFlag(scopeBlock, Block.NEEDS_SCOPE);
}
}
@@ -622,8 +617,8 @@
* @see #needsParentScope()
*/
private void setUsesGlobalSymbol() {
- for (final Iterator<FunctionNode> fns = getLexicalContext().getFunctions(); fns.hasNext();) {
- getLexicalContext().setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
+ for (final Iterator<FunctionNode> fns = lc.getFunctions(); fns.hasNext();) {
+ lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
}
}
@@ -635,7 +630,7 @@
private Symbol findSymbol(final Block block, final String name) {
// Search up block chain to locate symbol.
- for (final Iterator<Block> blocks = getLexicalContext().getBlocks(block); blocks.hasNext();) {
+ for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) {
// Find name.
final Symbol symbol = blocks.next().getExistingSymbol(name);
// If found then we are good.
@@ -656,11 +651,11 @@
public Node leaveLiteralNode(final LiteralNode literalNode) {
assert !literalNode.isTokenType(TokenType.THIS) : "tokentype for " + literalNode + " is this"; //guard against old dead code case. literal nodes should never inherit tokens
assert literalNode instanceof ArrayLiteralNode || !(literalNode.getValue() instanceof Node) : "literals with Node values not supported";
- final Symbol symbol = new Symbol(getLexicalContext().getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType());
+ final Symbol symbol = new Symbol(lc.getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType());
if (literalNode instanceof ArrayLiteralNode) {
((ArrayLiteralNode)literalNode).analyze();
}
- return end(literalNode.setSymbol(getLexicalContext(), symbol));
+ return end(literalNode.setSymbol(lc, symbol));
}
@Override
@@ -676,7 +671,7 @@
@Override
public Node leavePropertyNode(final PropertyNode propertyNode) {
// assign a pseudo symbol to property name, see NASHORN-710
- return propertyNode.setSymbol(getLexicalContext(), new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT));
+ return propertyNode.setSymbol(lc, new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT));
}
@Override
@@ -734,11 +729,11 @@
type = Type.OBJECT;
}
- switchNode.setTag(newInternal(getLexicalContext().getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type));
+ switchNode.setTag(newInternal(lc.getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type));
end(switchNode);
- return switchNode.setCases(getLexicalContext(), newCases);
+ return switchNode.setCases(lc, newCases);
}
@Override
@@ -761,7 +756,7 @@
final IdentNode ident = varNode.getName();
final String name = ident.getName();
- final Symbol symbol = defineSymbol(getLexicalContext().getCurrentBlock(), name, IS_VAR);
+ final Symbol symbol = defineSymbol(lc.getCurrentBlock(), name, IS_VAR);
assert symbol != null;
// NASHORN-467 - use before definition of vars - conservative
@@ -781,7 +776,6 @@
final IdentNode ident = newVarNode.getName();
final String name = ident.getName();
- final LexicalContext lc = getLexicalContext();
final Symbol symbol = findSymbol(lc.getCurrentBlock(), ident.getName());
if (init == null) {
@@ -834,7 +828,7 @@
@Override
public Node leaveDELETE(final UnaryNode unaryNode) {
- final FunctionNode currentFunctionNode = getLexicalContext().getCurrentFunction();
+ final FunctionNode currentFunctionNode = lc.getCurrentFunction();
final boolean strictMode = currentFunctionNode.isStrict();
final Node rhs = unaryNode.rhs();
final Node strictFlagNode = LiteralNode.newInstance(unaryNode, strictMode).accept(this);
@@ -894,10 +888,10 @@
* @return true if the symbol denoted by the specified name in the current lexical context defined in the program level.
*/
private boolean isProgramLevelSymbol(final String name) {
- for(final Iterator<Block> it = getLexicalContext().getBlocks(); it.hasNext();) {
+ for(final Iterator<Block> it = lc.getBlocks(); it.hasNext();) {
final Block next = it.next();
if(next.getExistingSymbol(name) != null) {
- return next == getLexicalContext().getFunctionBody(getLexicalContext().getOutermostFunction());
+ return next == lc.getFunctionBody(lc.getOutermostFunction());
}
}
throw new AssertionError("Couldn't find symbol " + name + " in the context");
@@ -914,14 +908,14 @@
}
private IdentNode compilerConstant(CompilerConstants cc) {
- final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
+ final FunctionNode functionNode = lc.getCurrentFunction();
return (IdentNode)
new IdentNode(
functionNode.getToken(),
functionNode.getFinish(),
cc.symbolName()).
setSymbol(
- getLexicalContext(),
+ lc,
functionNode.compilerConstant(cc));
}
@@ -999,7 +993,7 @@
final Node lhs = binaryNode.lhs();
if (lhs instanceof IdentNode) {
- final Block block = getLexicalContext().getCurrentBlock();
+ final Block block = lc.getCurrentBlock();
final IdentNode ident = (IdentNode)lhs;
final String name = ident.getName();
@@ -1043,7 +1037,7 @@
}
private boolean isLocal(FunctionNode function, Symbol symbol) {
- final FunctionNode definingFn = getLexicalContext().getDefiningFunction(symbol);
+ final FunctionNode definingFn = lc.getDefiningFunction(symbol);
// Temp symbols are not assigned to a block, so their defining fn is null; those can be assumed local
return definingFn == null || definingFn == function;
}
@@ -1329,7 +1323,7 @@
@Override
public Node leaveForNode(final ForNode forNode) {
if (forNode.isForIn()) {
- forNode.setIterator(newInternal(getLexicalContext().getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.OBJECT)); //NASHORN-73
+ forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.OBJECT)); //NASHORN-73
/*
* Iterators return objects, so we need to widen the scope of the
* init variable if it, for example, has been assigned double type
@@ -1407,7 +1401,7 @@
final Symbol paramSymbol = functionNode.getBody().getExistingSymbol(param.getName());
assert paramSymbol != null;
assert paramSymbol.isParam();
- newParams.add((IdentNode)param.setSymbol(getLexicalContext(), paramSymbol));
+ newParams.add((IdentNode)param.setSymbol(lc, paramSymbol));
assert paramSymbol != null;
Type type = functionNode.getHints().getParameterType(pos);
@@ -1439,10 +1433,10 @@
FunctionNode newFunctionNode = functionNode;
if (nparams == 0 || (specialize * 2) < nparams) {
- newFunctionNode = newFunctionNode.clearSnapshot(getLexicalContext());
+ newFunctionNode = newFunctionNode.clearSnapshot(lc);
}
- return newFunctionNode.setParameters(getLexicalContext(), newParams);
+ return newFunctionNode.setParameters(lc, newParams);
}
/**
@@ -1506,7 +1500,7 @@
}
private Symbol exceptionSymbol() {
- return newInternal(getLexicalContext().getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(ECMAException.class));
+ return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(ECMAException.class));
}
/**
@@ -1520,8 +1514,8 @@
* @param assignmentDest the destination node of the assignment, e.g. lhs for binary nodes
*/
private Node ensureAssignmentSlots(final Node assignmentDest) {
- final LexicalContext attrLexicalContext = getLexicalContext();
- return assignmentDest.accept(new NodeVisitor() {
+ final LexicalContext attrLexicalContext = lc;
+ return assignmentDest.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public Node leaveIndexNode(final IndexNode indexNode) {
assert indexNode.getSymbol().isTemp();
@@ -1565,7 +1559,7 @@
FunctionNode currentFunctionNode = functionNode;
do {
changed.clear();
- final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor() {
+ final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private Node widen(final Node node, final Type to) {
if (node instanceof LiteralNode) {
@@ -1579,7 +1573,7 @@
symbol = temporarySymbols.getTypedTemporarySymbol(to);
}
newType(symbol, to);
- final Node newNode = node.setSymbol(getLexicalContext(), symbol);
+ final Node newNode = node.setSymbol(lc, symbol);
changed.add(newNode);
return newNode;
}
@@ -1622,7 +1616,7 @@
return newBinaryNode;
}
});
- getLexicalContext().replace(currentFunctionNode, newFunctionNode);
+ lc.replace(currentFunctionNode, newFunctionNode);
currentFunctionNode = newFunctionNode;
} while (!changed.isEmpty());
return currentFunctionNode;
@@ -1643,12 +1637,12 @@
}
private Node ensureSymbol(final Type type, final Node node) {
- LOG.info("New TEMPORARY added to ", getLexicalContext().getCurrentFunction().getName(), " type=", type);
- return ensureSymbol(getLexicalContext(), type, node);
+ LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type);
+ return temporarySymbols.ensureSymbol(lc, type, node);
}
private Symbol newInternal(final String name, final Type type) {
- final Symbol iter = defineSymbol(getLexicalContext().getCurrentBlock(), name, IS_VAR | IS_INTERNAL);
+ final Symbol iter = defineSymbol(lc.getCurrentBlock(), name, IS_VAR | IS_INTERNAL);
iter.setType(type); // NASHORN-73
return iter;
}
@@ -1705,10 +1699,6 @@
localUses.peek().add(name);
}
- private Node ensureSymbol(final LexicalContext lc, final Type type, final Node node) {
- return temporarySymbols.ensureSymbol(lc, type, node);
- }
-
/**
* Pessimistically promote all symbols in current function node to Object types
* This is done when the function contains unevaluated black boxes such as
@@ -1717,7 +1707,7 @@
* @param body body for the function node we are leaving
*/
private static void objectifySymbols(final Block body) {
- body.accept(new NodeVisitor() {
+ body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private void toObject(final Block block) {
for (final Symbol symbol : block.getSymbols()) {
if (!symbol.isTemp()) {
@@ -1761,7 +1751,7 @@
append("] ").
append(printNode ? node.toString() : "").
append(" in '").
- append(getLexicalContext().getCurrentFunction().getName()).
+ append(lc.getCurrentFunction().getName()).
append("'");
LOG.info(sb);
LOG.indent();
@@ -1787,7 +1777,7 @@
append("] ").
append(printNode ? node.toString() : "").
append(" in '").
- append(getLexicalContext().getCurrentFunction().getName());
+ append(lc.getCurrentFunction().getName());
if (node.getSymbol() == null) {
sb.append(" <NO SYMBOL>");
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu May 23 15:51:08 2013 +0200
@@ -52,16 +52,12 @@
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
import java.io.PrintWriter;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Deque;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.TreeMap;
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
@@ -83,11 +79,11 @@
import jdk.nashorn.internal.ir.ExecuteNode;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
-import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
@@ -150,7 +146,7 @@
* The CodeGenerator visits nodes only once, tags them as resolved and emits
* bytecode for them.
*/
-final class CodeGenerator extends NodeOperatorVisitor {
+final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> {
/** Name of the Global object, cannot be referred to as .class, @see CodeGenerator */
private static final String GLOBAL_OBJECT = Compiler.OBJECTS_PACKAGE + '/' + "Global";
@@ -168,23 +164,12 @@
/** How many regexp fields have been emitted */
private int regexFieldCount;
- /** Map of shared scope call sites */
- private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>();
-
- /** Compile unit stack - every time we start a sub method (e.g. a split) we push one */
- private final Deque<CompileUnit> compileUnits = new ArrayDeque<>();
-
- /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */
- private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>();
-
- /** The discard stack - whenever we enter a discard node we keep track of its return value status -
- * i.e. should we keep it or throw it away */
- private final Deque<Node> discard = new ArrayDeque<>();
-
- // A stack tracking the next free local variable slot in the blocks. There's one entry for every block
- // currently on the lexical context stack.
- private int[] nextFreeSlots = new int[16];
- private int nextFreeSlotsSize = 0;
+ /** Line number for last statement. If we encounter a new line number, line number bytecode information
+ * needs to be generated */
+ private int lastLineNumber = -1;
+
+ /** When should we stop caching regexp expressions in fields to limit bytecode size? */
+ private static final int MAX_REGEX_FIELDS = 2 * 1024;
/** Current method emitter */
private MethodEmitter method;
@@ -192,20 +177,16 @@
/** Current compile unit */
private CompileUnit unit;
- private int lastLineNumber = -1;
-
- /** When should we stop caching regexp expressions in fields to limit bytecode size? */
- private static final int MAX_REGEX_FIELDS = 2 * 1024;
-
private static final DebugLogger LOG = new DebugLogger("codegen", "nashorn.codegen.debug");
+
/**
* Constructor.
*
* @param compiler
*/
CodeGenerator(final Compiler compiler) {
- super(new DynamicScopeTrackingLexicalContext());
+ super(new CodeGeneratorLexicalContext());
this.compiler = compiler;
this.callSiteFlags = compiler.getEnv()._callsite_flags;
}
@@ -217,37 +198,7 @@
* @return the correct flags for a call site in the current function
*/
int getCallSiteFlags() {
- return getLexicalContext().getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags;
- }
-
- private void pushMethodEmitter(final MethodEmitter newMethod) {
- methodEmitters.push(newMethod);
- this.method = newMethod;
- }
-
- private void popMethodEmitter(final MethodEmitter oldMethod) {
- assert methodEmitters.peek() == oldMethod;
- methodEmitters.pop();
- if (!methodEmitters.isEmpty()) {
- this.method = methodEmitters.peek();
- } else {
- this.method = null;
- }
- }
-
- private void push(final CompileUnit newUnit) {
- compileUnits.push(newUnit);
- this.unit = newUnit;
- }
-
- private void pop(final CompileUnit oldUnit) {
- assert compileUnits.peek() == oldUnit;
- compileUnits.pop();
- if (!compileUnits.isEmpty()) {
- this.unit = compileUnits.peek();
- } else {
- this.unit = null;
- }
+ return lc.getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags;
}
/**
@@ -265,7 +216,7 @@
}
final String name = symbol.getName();
- final Source source = getLexicalContext().getCurrentFunction().getSource();
+ final Source source = lc.getCurrentFunction().getSource();
if (CompilerConstants.__FILE__.name().equals(name)) {
return method.load(source.getName());
@@ -291,88 +242,43 @@
}
/**
- * A lexical context that also tracks if we have any dynamic scopes in the context. Such scopes can have new
- * variables introduced into them at run time - a with block or a function directly containing an eval call.
- */
- private static class DynamicScopeTrackingLexicalContext extends LexicalContext {
- int dynamicScopeCount = 0;
-
- @Override
- public <T extends LexicalContextNode> T push(T node) {
- if(isDynamicScopeBoundary(node)) {
- ++dynamicScopeCount;
- }
- return super.push(node);
- }
-
- @Override
- public <T extends LexicalContextNode> T pop(T node) {
- final T popped = super.pop(node);
- if(isDynamicScopeBoundary(popped)) {
- --dynamicScopeCount;
- }
- return popped;
- }
-
- private boolean isDynamicScopeBoundary(LexicalContextNode node) {
- if(node instanceof Block) {
- // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture
- // processing of WithNode.expression too, but it should be unaffected.
- return !isEmpty() && peek() instanceof WithNode;
- } else if(node instanceof FunctionNode) {
- // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
- // variable into the function's scope), and it isn't strict (as evals in strict functions get an
- // isolated scope).
- return isFunctionDynamicScope((FunctionNode)node);
- }
- return false;
- }
- }
-
- boolean inDynamicScope() {
- return ((DynamicScopeTrackingLexicalContext)getLexicalContext()).dynamicScopeCount > 0;
- }
-
- static boolean isFunctionDynamicScope(FunctionNode fn) {
- return fn.hasEval() && !fn.isStrict();
- }
-
- /**
* Check if this symbol can be accessed directly with a putfield or getfield or dynamic load
*
* @param function function to check for fast scope
* @return true if fast scope
*/
private boolean isFastScope(final Symbol symbol) {
- if(!symbol.isScope()) {
+ if (!symbol.isScope()) {
return false;
}
- final LexicalContext lc = getLexicalContext();
- if(!inDynamicScope()) {
+
+ if (!lc.inDynamicScope()) {
// If there's no with or eval in context, and the symbol is marked as scoped, it is fast scoped. Such a
// symbol must either be global, or its defining block must need scope.
assert symbol.isGlobal() || lc.getDefiningBlock(symbol).needsScope() : symbol.getName();
return true;
}
- if(symbol.isGlobal()) {
+
+ if (symbol.isGlobal()) {
// Shortcut: if there's a with or eval in context, globals can't be fast scoped
return false;
}
+
// Otherwise, check if there's a dynamic scope between use of the symbol and its definition
final String name = symbol.getName();
boolean previousWasBlock = false;
for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
final LexicalContextNode node = it.next();
- if(node instanceof Block) {
+ if (node instanceof Block) {
// If this block defines the symbol, then we can fast scope the symbol.
final Block block = (Block)node;
- if(block.getExistingSymbol(name) == symbol) {
+ if (block.getExistingSymbol(name) == symbol) {
assert block.needsScope();
return true;
}
previousWasBlock = true;
} else {
- if((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && isFunctionDynamicScope((FunctionNode)node))) {
+ if ((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && CodeGeneratorLexicalContext.isFunctionDynamicScope((FunctionNode)node))) {
// If we hit a scope that can have symbols introduced into it at run time before finding the defining
// block, the symbol can't be fast scoped. A WithNode only counts if we've immediately seen a block
// before - its block. Otherwise, we are currently processing the WithNode's expression, and that's
@@ -387,16 +293,14 @@
}
private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
- method.load(isFastScope(symbol) ? getScopeProtoDepth(getLexicalContext().getCurrentBlock(), symbol) : -1);
- final SharedScopeCall scopeCall = getScopeGet(valueType, symbol, flags | CALLSITE_FAST_SCOPE);
- scopeCall.generateInvoke(method);
- return method;
+ method.load(isFastScope(symbol) ? getScopeProtoDepth(lc.getCurrentBlock(), symbol) : -1);
+ final SharedScopeCall scopeCall = lc.getScopeGet(unit, valueType, symbol, flags | CALLSITE_FAST_SCOPE);
+ return scopeCall.generateInvoke(method);
}
private MethodEmitter loadFastScopeVar(final Type valueType, final Symbol symbol, final int flags, final boolean isMethod) {
loadFastScopeProto(symbol, false);
- method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod);
- return method;
+ return method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod);
}
private MethodEmitter storeFastScopeVar(final Type valueType, final Symbol symbol, final int flags) {
@@ -408,7 +312,7 @@
private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
int depth = 0;
final String name = symbol.getName();
- for(final Iterator<Block> blocks = getLexicalContext().getBlocks(startingBlock); blocks.hasNext();) {
+ for(final Iterator<Block> blocks = lc.getBlocks(startingBlock); blocks.hasNext();) {
final Block currentBlock = blocks.next();
if (currentBlock.getExistingSymbol(name) == symbol) {
return depth;
@@ -421,7 +325,7 @@
}
private void loadFastScopeProto(final Symbol symbol, final boolean swap) {
- final int depth = getScopeProtoDepth(getLexicalContext().getCurrentBlock(), symbol);
+ final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol);
assert depth != -1;
if (depth > 0) {
if (swap) {
@@ -464,7 +368,7 @@
*/
final CodeGenerator codegen = this;
- node.accept(new NodeVisitor() {
+ node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterIdentNode(final IdentNode identNode) {
loadIdent(identNode);
@@ -538,7 +442,7 @@
final boolean isInternal = symbol.isParam() || symbol.isInternal() || symbol.isThis() || !symbol.canBeUndefined();
if (symbol.hasSlot() && !isInternal) {
- assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + getLexicalContext().getCurrentFunction();
+ assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + lc.getCurrentFunction();
if (symbol.getSymbolType().isNumber()) {
numbers.add(symbol);
} else if (symbol.getSymbolType().isObject()) {
@@ -595,7 +499,6 @@
if (block.needsScope() && !block.isTerminal()) {
popBlockScope(block);
}
- --nextFreeSlotsSize;
return block;
}
@@ -624,11 +527,11 @@
public boolean enterBreakNode(final BreakNode breakNode) {
lineNumber(breakNode);
- final BreakableNode breakFrom = getLexicalContext().getBreakable(breakNode.getLabel());
- for (int i = 0; i < getLexicalContext().getScopeNestingLevelTo(breakFrom); i++) {
+ final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabel());
+ for (int i = 0; i < lc.getScopeNestingLevelTo(breakFrom); i++) {
closeWith();
}
- method.splitAwareGoto(getLexicalContext(), breakFrom.getBreakLabel());
+ method.splitAwareGoto(lc, breakFrom.getBreakLabel());
return false;
}
@@ -672,11 +575,12 @@
final List<Node> args = callNode.getArgs();
final Node function = callNode.getFunction();
- final Block currentBlock = getLexicalContext().getCurrentBlock();
-
- function.accept(new NodeVisitor() {
-
- private void sharedScopeCall(final IdentNode identNode, final int flags) {
+ final Block currentBlock = lc.getCurrentBlock();
+ final CodeGeneratorLexicalContext codegenLexicalContext = lc;
+
+ function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+
+ private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
final Symbol symbol = identNode.getSymbol();
int scopeCallFlags = flags;
method.loadCompilerConstant(SCOPE);
@@ -688,8 +592,8 @@
}
loadArgs(args);
final Type[] paramTypes = method.getTypesFromStack(args.size());
- final SharedScopeCall scopeCall = getScopeCall(symbol, identNode.getType(), callNode.getType(), paramTypes, scopeCallFlags);
- scopeCall.generateInvoke(method);
+ final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol, identNode.getType(), callNode.getType(), paramTypes, scopeCallFlags);
+ return scopeCall.generateInvoke(method);
}
private void scopeCall(final IdentNode node, final int flags) {
@@ -756,7 +660,7 @@
evalCall(node, flags);
} else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
|| (!isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD)
- || CodeGenerator.this.inDynamicScope()) {
+ || CodeGenerator.this.lc.inDynamicScope()) {
scopeCall(node, flags);
} else {
sharedScopeCall(node, flags);
@@ -845,11 +749,11 @@
public boolean enterContinueNode(final ContinueNode continueNode) {
lineNumber(continueNode);
- final LoopNode continueTo = getLexicalContext().getContinueTo(continueNode.getLabel());
- for (int i = 0; i < getLexicalContext().getScopeNestingLevelTo(continueTo); i++) {
+ final LoopNode continueTo = lc.getContinueTo(continueNode.getLabel());
+ for (int i = 0; i < lc.getScopeNestingLevelTo(continueTo); i++) {
closeWith();
}
- method.splitAwareGoto(getLexicalContext(), continueTo.getContinueLabel());
+ method.splitAwareGoto(lc, continueTo.getContinueLabel());
return false;
}
@@ -875,90 +779,89 @@
public boolean enterForNode(final ForNode forNode) {
lineNumber(forNode);
- final Node test = forNode.getTest();
- final Block body = forNode.getBody();
- final Node modify = forNode.getModify();
-
- final Label breakLabel = forNode.getBreakLabel();
- final Label continueLabel = forNode.getContinueLabel();
- final Label loopLabel = new Label("loop");
-
- Node init = forNode.getInit();
-
if (forNode.isForIn()) {
- final Symbol iter = forNode.getIterator();
-
- // We have to evaluate the optional initializer expression
- // of the iterator variable of the for-in statement.
- if (init instanceof VarNode) {
- init.accept(this);
- init = ((VarNode)init).getName();
- }
-
- load(modify);
- assert modify.getType().isObject();
- method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
- method.store(iter);
- method._goto(continueLabel);
- method.label(loopLabel);
-
- new Store<Node>(init) {
- @Override
- protected void storeNonDiscard() {
- return;
- }
- @Override
- protected void evaluate() {
- method.load(iter);
- method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class));
- }
- }.store();
-
- body.accept(this);
-
- method.label(continueLabel);
- method.load(iter);
- method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class));
- method.ifne(loopLabel);
- method.label(breakLabel);
+ enterForIn(forNode);
} else {
- if (init != null) {
- init.accept(this);
- }
-
- final Label testLabel = new Label("test");
-
- method._goto(testLabel);
- method.label(loopLabel);
- body.accept(this);
- method.label(continueLabel);
-
- if (!body.isTerminal() && modify != null) {
- load(modify);
- }
-
- method.label(testLabel);
- if (test != null) {
- new BranchOptimizer(this, method).execute(test, loopLabel, true);
- } else {
- method._goto(loopLabel);
- }
-
- method.label(breakLabel);
+ enterFor(forNode);
}
return false;
}
- private static int assignSlots(final Block block, final int firstSlot) {
- int nextSlot = firstSlot;
- for (final Symbol symbol : block.getSymbols()) {
- if (symbol.hasSlot()) {
- symbol.setSlot(nextSlot);
- nextSlot += symbol.slotCount();
+ private void enterFor(final ForNode forNode) {
+ final Node init = forNode.getInit();
+ final Node test = forNode.getTest();
+ final Block body = forNode.getBody();
+ final Node modify = forNode.getModify();
+
+ if (init != null) {
+ init.accept(this);
+ }
+
+ final Label loopLabel = new Label("loop");
+ final Label testLabel = new Label("test");
+
+ method._goto(testLabel);
+ method.label(loopLabel);
+ body.accept(this);
+ method.label(forNode.getContinueLabel());
+
+ if (!body.isTerminal() && modify != null) {
+ load(modify);
+ }
+
+ method.label(testLabel);
+ if (test != null) {
+ new BranchOptimizer(this, method).execute(test, loopLabel, true);
+ } else {
+ method._goto(loopLabel);
+ }
+
+ method.label(forNode.getBreakLabel());
+ }
+
+ private void enterForIn(final ForNode forNode) {
+ final Block body = forNode.getBody();
+ final Node modify = forNode.getModify();
+
+ final Symbol iter = forNode.getIterator();
+ final Label loopLabel = new Label("loop");
+
+ Node init = forNode.getInit();
+
+ // We have to evaluate the optional initializer expression
+ // of the iterator variable of the for-in statement.
+ if (init instanceof VarNode) {
+ init.accept(this);
+ init = ((VarNode)init).getName();
+ }
+
+ load(modify);
+ assert modify.getType().isObject();
+ method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
+ method.store(iter);
+ method._goto(forNode.getContinueLabel());
+ method.label(loopLabel);
+
+ new Store<Node>(init) {
+ @Override
+ protected void storeNonDiscard() {
+ return;
}
- }
- return nextSlot;
+ @Override
+ protected void evaluate() {
+ method.load(iter);
+ method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class));
+ }
+ }.store();
+
+ body.accept(this);
+
+ method.label(forNode.getContinueLabel());
+ method.load(iter);
+ method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class));
+ method.ifne(loopLabel);
+ method.label(forNode.getBreakLabel());
}
/**
@@ -967,24 +870,11 @@
* @param block block with local vars.
*/
private void initLocals(final Block block) {
- final boolean isFunctionBody = getLexicalContext().isFunctionBody();
-
- final int nextFreeSlot;
- if (isFunctionBody) {
- // On entry to function, start with slot 0
- nextFreeSlot = 0;
- } else {
- // Otherwise, continue from previous block's first free slot
- nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1];
- }
- if(nextFreeSlotsSize == nextFreeSlots.length) {
- final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
- System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
- nextFreeSlots = newNextFreeSlots;
- }
- nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot);
-
- final FunctionNode function = getLexicalContext().getCurrentFunction();
+ lc.nextFreeSlot(block);
+
+ final boolean isFunctionBody = lc.isFunctionBody();
+
+ final FunctionNode function = lc.getCurrentFunction();
if (isFunctionBody) {
/* Fix the predefined slots so they have numbers >= 0, like varargs. */
if (function.needsParentScope()) {
@@ -1023,7 +913,7 @@
}
if (symbol.isVar()) {
- if(varsInScope || symbol.isScope()) {
+ if (varsInScope || symbol.isScope()) {
nameList.add(symbol.getName());
newSymbols.add(symbol);
values.add(null);
@@ -1062,7 +952,7 @@
@Override
protected void loadScope(MethodEmitter m) {
- if(function.needsParentScope()) {
+ if (function.needsParentScope()) {
m.loadCompilerConstant(SCOPE);
} else {
m.loadNull();
@@ -1096,7 +986,7 @@
private void initArguments(final FunctionNode function) {
method.loadCompilerConstant(VARARGS);
- if(function.needsCallee()) {
+ if (function.needsCallee()) {
method.loadCompilerConstant(CALLEE);
} else {
// If function is strict mode, "arguments.callee" is not populated, so we don't necessarily need the
@@ -1126,10 +1016,10 @@
LOG.info("=== BEGIN ", functionNode.getName());
assert functionNode.getCompileUnit() != null : "no compile unit for " + functionNode.getName() + " " + Debug.id(functionNode);
- push(functionNode.getCompileUnit());
- assert !compileUnits.isEmpty();
-
- pushMethodEmitter(unit.getClassEmitter().method(functionNode));
+ unit = lc.pushCompileUnit(functionNode.getCompileUnit());
+ assert lc.hasCompileUnits();
+
+ method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode));
// Mark end for variable tables.
method.begin();
@@ -1140,11 +1030,11 @@
public Node leaveFunctionNode(final FunctionNode functionNode) {
try {
method.end(); // wrap up this method
- pop(functionNode.getCompileUnit());
- popMethodEmitter(method);
+ unit = lc.popCompileUnit(functionNode.getCompileUnit());
+ method = lc.popMethodEmitter(method);
LOG.info("=== END ", functionNode.getName());
- final FunctionNode newFunctionNode = functionNode.setState(getLexicalContext(), CompilationState.EMITTED);
+ final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED);
newFunctionObject(newFunctionNode, functionNode);
return newFunctionNode;
@@ -1238,16 +1128,16 @@
final MethodEmitter savedMethod = method;
for (final ArrayUnit arrayUnit : units) {
- push(arrayUnit.getCompileUnit());
+ unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
final String className = unit.getUnitClassName();
- final String name = getLexicalContext().getCurrentFunction().uniqueName(SPLIT_PREFIX.symbolName());
+ final String name = lc.getCurrentFunction().uniqueName(SPLIT_PREFIX.symbolName());
final String signature = methodDescriptor(type, Object.class, ScriptFunction.class, ScriptObject.class, type);
final MethodEmitter me = unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature);
- pushMethodEmitter(me);
-
- method.setFunctionNode(getLexicalContext().getCurrentFunction());
+ method = lc.pushMethodEmitter(me);
+
+ method.setFunctionNode(lc.getCurrentFunction());
method.begin();
fixScopeSlot();
@@ -1260,7 +1150,7 @@
method._return();
method.end();
- popMethodEmitter(me);
+ method = lc.popMethodEmitter(me);
assert method == savedMethod;
method.loadCompilerConstant(THIS);
@@ -1271,7 +1161,7 @@
method.swap();
method.invokestatic(className, name, signature);
- pop(unit);
+ unit = lc.popCompileUnit(unit);
}
return method;
@@ -1407,7 +1297,7 @@
return loadRegexToken(regexToken);
}
// emit field
- final String regexName = getLexicalContext().getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
+ final String regexName = lc.getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
final ClassEmitter classEmitter = unit.getClassEmitter();
classEmitter.field(EnumSet.of(PRIVATE, STATIC), regexName, Object.class);
@@ -1545,7 +1435,7 @@
method.registerReturn();
- final Type returnType = getLexicalContext().getCurrentFunction().getReturnType();
+ final Type returnType = lc.getCurrentFunction().getReturnType();
final Node expression = returnNode.getExpression();
if (expression != null) {
@@ -1756,7 +1646,7 @@
final CompileUnit splitCompileUnit = splitNode.getCompileUnit();
- final FunctionNode fn = getLexicalContext().getCurrentFunction();
+ final FunctionNode fn = lc.getCurrentFunction();
final String className = splitCompileUnit.getUnitClassName();
final String name = splitNode.getName();
@@ -1767,7 +1657,7 @@
new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class};
final MethodEmitter caller = method;
- push(splitCompileUnit);
+ unit = lc.pushCompileUnit(splitCompileUnit);
final Call splitCall = staticCallNoLookup(
className,
@@ -1781,8 +1671,7 @@
rtype,
ptypes);
- pushMethodEmitter(splitEmitter);
-
+ method = lc.pushMethodEmitter(splitEmitter);
method.setFunctionNode(fn);
if (fn.needsCallee()) {
@@ -1809,7 +1698,7 @@
}
private void fixScopeSlot() {
- if (getLexicalContext().getCurrentFunction().compilerConstant(SCOPE).getSlot() != SCOPE.slot()) {
+ if (lc.getCurrentFunction().compilerConstant(SCOPE).getSlot() != SCOPE.slot()) {
// TODO hack to move the scope to the expected slot (that's needed because split methods reuse the same slots as the root method)
method.load(Type.typeFor(ScriptObject.class), SCOPE.slot());
method.storeCompilerConstant(SCOPE);
@@ -1826,15 +1715,15 @@
// Wrap up this method.
method.loadCompilerConstant(RETURN);
- method._return(getLexicalContext().getCurrentFunction().getReturnType());
+ method._return(lc.getCurrentFunction().getReturnType());
method.end();
- pop(splitNode.getCompileUnit());
- popMethodEmitter(method);
+ unit = lc.popCompileUnit(splitNode.getCompileUnit());
+ method = lc.popMethodEmitter(method);
} catch (final Throwable t) {
Context.printStackTrace(t);
- final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + getLexicalContext().getCurrentFunction().getSource().getName());
+ final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + lc.getCurrentFunction().getSource().getName());
e.initCause(t);
throw e;
}
@@ -1862,7 +1751,7 @@
//has to be zero
caller.label(new Label("split_return"));
method.loadCompilerConstant(RETURN);
- caller._return(getLexicalContext().getCurrentFunction().getReturnType());
+ caller._return(lc.getCurrentFunction().getReturnType());
caller.label(breakLabel);
} else {
assert !targets.isEmpty();
@@ -1879,14 +1768,14 @@
caller.label(labels[i - low]);
if (i == 0) {
caller.loadCompilerConstant(RETURN);
- caller._return(getLexicalContext().getCurrentFunction().getReturnType());
+ caller._return(lc.getCurrentFunction().getReturnType());
} else {
// Clear split state.
caller.loadCompilerConstant(SCOPE);
caller.checkcast(Scope.class);
caller.load(-1);
caller.invoke(Scope.SET_SPLIT_STATE);
- caller.splitAwareGoto(getLexicalContext(), targets.get(i - 1));
+ caller.splitAwareGoto(lc, targets.get(i - 1));
}
}
caller.label(breakLabel);
@@ -2037,7 +1926,7 @@
method._new(ECMAException.class).dup();
- final Source source = getLexicalContext().getCurrentFunction().getSource();
+ final Source source = lc.getCurrentFunction().getSource();
final Node expression = throwNode.getExpression();
final int position = throwNode.position();
@@ -2088,7 +1977,7 @@
//TODO this is very ugly - try not to call enter/leave methods directly
//better to use the implicit lexical context scoping given by the visitor's
//accept method.
- getLexicalContext().push(catchBlock);
+ lc.push(catchBlock);
enterBlock(catchBlock);
final CatchNode catchNode = (CatchNode)catchBlocks.get(i).getStatements().get(0);
@@ -2101,6 +1990,7 @@
protected void storeNonDiscard() {
return;
}
+
@Override
protected void evaluate() {
if (catchNode.isSyntheticRethrow()) {
@@ -2147,7 +2037,7 @@
}
leaveBlock(catchBlock);
- getLexicalContext().pop(catchBlock);
+ lc.pop(catchBlock);
}
method.label(skip);
@@ -2244,7 +2134,7 @@
final boolean hasScope = method.hasScope();
final Label tryLabel;
- if(hasScope) {
+ if (hasScope) {
tryLabel = new Label("with_try");
method.label(tryLabel);
method.loadCompilerConstant(SCOPE);
@@ -2255,7 +2145,7 @@
load(expression);
assert expression.getType().isObject() : "with expression needs to be object: " + expression;
- if(hasScope) {
+ if (hasScope) {
// Construct a WithObject if we have a scope
method.invoke(ScriptRuntime.OPEN_WITH);
method.storeCompilerConstant(SCOPE);
@@ -2397,13 +2287,13 @@
public boolean enterDISCARD(final UnaryNode unaryNode) {
final Node rhs = unaryNode.rhs();
- discard.push(rhs);
+ lc.pushDiscard(rhs);
load(rhs);
- if (discard.peek() == rhs) {
+ if (lc.getCurrentDiscard() == rhs) {
assert !rhs.isAssignment();
method.pop();
- discard.pop();
+ lc.popDiscard();
}
return false;
@@ -2455,7 +2345,7 @@
assert lhs.getType().equals(rhs.getType()) && lhs.getType().equals(type) : lhs.getType() + " != " + rhs.getType() + " != " + type + " " + new ASTWriter(lhs) + " " + new ASTWriter(rhs);
load(lhs);
load(rhs);
- method.add();
+ method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack?
method.store(symbol);
return null;
}
@@ -2999,53 +2889,12 @@
* Generate all shared scope calls generated during codegen.
*/
protected void generateScopeCalls() {
- for (final SharedScopeCall scopeAccess : scopeCalls.values()) {
+ for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
scopeAccess.generateScopeCall();
}
}
/**
- * Get a shared static method representing a dynamic scope callsite.
- *
- * @param symbol the symbol
- * @param valueType the value type of the symbol
- * @param returnType the return type
- * @param paramTypes the parameter types
- * @param flags the callsite flags
- * @return an object representing a shared scope call
- */
- private SharedScopeCall getScopeCall(final Symbol symbol, final Type valueType, final Type returnType,
- final Type[] paramTypes, final int flags) {
-
- final SharedScopeCall scopeCall = new SharedScopeCall(symbol, valueType, returnType, paramTypes, flags);
- if (scopeCalls.containsKey(scopeCall)) {
- return scopeCalls.get(scopeCall);
- }
- scopeCall.setClassAndName(unit, getLexicalContext().getCurrentFunction().uniqueName("scopeCall"));
- scopeCalls.put(scopeCall, scopeCall);
- return scopeCall;
- }
-
- /**
- * Get a shared static method representing a dynamic scope get access.
- *
- * @param type the type of the variable
- * @param symbol the symbol
- * @param flags the callsite flags
- * @return an object representing a shared scope call
- */
- private SharedScopeCall getScopeGet(final Type type, final Symbol symbol, final int flags) {
-
- final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags);
- if (scopeCalls.containsKey(scopeCall)) {
- return scopeCalls.get(scopeCall);
- }
- scopeCall.setClassAndName(unit, getLexicalContext().getCurrentFunction().uniqueName("scopeCall"));
- scopeCalls.put(scopeCall, scopeCall);
- return scopeCall;
- }
-
- /**
* Debug code used to print symbols
*
* @param block the block we are in
@@ -3139,14 +2988,14 @@
private void prologue() {
final Symbol targetSymbol = target.getSymbol();
- final Symbol scopeSymbol = getLexicalContext().getCurrentFunction().compilerConstant(SCOPE);
+ final Symbol scopeSymbol = lc.getCurrentFunction().compilerConstant(SCOPE);
/**
* This loads the parts of the target, e.g base and index. they are kept
* on the stack throughout the store and used at the end to execute it
*/
- target.accept(new NodeVisitor() {
+ target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterIdentNode(final IdentNode node) {
if (targetSymbol.isScope()) {
@@ -3213,22 +3062,21 @@
* @return the quick symbol
*/
private Symbol quickSymbol(final Type type, final String prefix) {
- final String name = getLexicalContext().getCurrentFunction().uniqueName(prefix);
+ final String name = lc.getCurrentFunction().uniqueName(prefix);
final Symbol symbol = new Symbol(name, IS_TEMP | IS_INTERNAL);
symbol.setType(type);
- final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1];
- nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount();
- symbol.setSlot(quickSlot);
+
+ symbol.setSlot(lc.quickSlot(symbol));
return symbol;
}
// store the result that "lives on" after the op, e.g. "i" in i++ postfix.
protected void storeNonDiscard() {
- if (discard.peek() == assignNode) {
+ if (lc.getCurrentDiscard() == assignNode) {
assert assignNode.isAssignment();
- discard.pop();
+ lc.popDiscard();
return;
}
@@ -3256,7 +3104,7 @@
*/
method.convert(target.getType());
- target.accept(new NodeVisitor() {
+ target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
protected boolean enterDefault(Node node) {
throw new AssertionError("Unexpected node " + node + " in store epilogue");
@@ -3318,7 +3166,6 @@
}
private void newFunctionObject(final FunctionNode functionNode, final FunctionNode originalFunctionNode) {
- final LexicalContext lc = getLexicalContext();
assert lc.peek() == functionNode;
// We don't emit a ScriptFunction on stack for:
// 1. the outermost compiled function (as there's no code being generated in its outer context that'd need it
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Thu May 23 15:51:08 2013 +0200
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LexicalContextNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.WithNode;
+
+/**
+ * A lexical context that also tracks if we have any dynamic scopes in the context. Such scopes can have new
+ * variables introduced into them at run time - a with block or a function directly containing an eval call.
+ * Furthermore, this class keeps track of current discard state, which the current method emitter being used is,
+ * the current compile unit, and local variable indexes
+ */
+final class CodeGeneratorLexicalContext extends LexicalContext {
+ private int dynamicScopeCount;
+
+ /** Map of shared scope call sites */
+ private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>();
+
+ /** Compile unit stack - every time we start a sub method (e.g. a split) we push one */
+ private final Deque<CompileUnit> compileUnits = new ArrayDeque<>();
+
+ /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */
+ private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>();
+
+ /** The discard stack - whenever we enter a discard node we keep track of its return value status -
+ * i.e. should we keep it or throw it away */
+ private final Deque<Node> discard = new ArrayDeque<>();
+
+ /** A stack tracking the next free local variable slot in the blocks. There's one entry for every block
+ * currently on the lexical context stack. */
+ private int[] nextFreeSlots = new int[16];
+
+ /** size of next free slot vector */
+ private int nextFreeSlotsSize;
+
+ @Override
+ public <T extends LexicalContextNode> T push(final T node) {
+ if (isDynamicScopeBoundary(node)) {
+ ++dynamicScopeCount;
+ }
+ return super.push(node);
+ }
+
+ @Override
+ public <T extends LexicalContextNode> T pop(final T node) {
+ final T popped = super.pop(node);
+ if (isDynamicScopeBoundary(popped)) {
+ --dynamicScopeCount;
+ }
+ if (node instanceof Block) {
+ --nextFreeSlotsSize;
+ }
+ return popped;
+ }
+
+ private boolean isDynamicScopeBoundary(final LexicalContextNode node) {
+ if (node instanceof Block) {
+ // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture
+ // processing of WithNode.expression too, but it should be unaffected.
+ return !isEmpty() && peek() instanceof WithNode;
+ } else if (node instanceof FunctionNode) {
+ // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
+ // variable into the function's scope), and it isn't strict (as evals in strict functions get an
+ // isolated scope).
+ return isFunctionDynamicScope((FunctionNode)node);
+ }
+ return false;
+ }
+
+ boolean inDynamicScope() {
+ return dynamicScopeCount > 0;
+ }
+
+ static boolean isFunctionDynamicScope(FunctionNode fn) {
+ return fn.hasEval() && !fn.isStrict();
+ }
+
+ MethodEmitter pushMethodEmitter(final MethodEmitter newMethod) {
+ methodEmitters.push(newMethod);
+ return newMethod;
+ }
+
+ MethodEmitter popMethodEmitter(final MethodEmitter oldMethod) {
+ assert methodEmitters.peek() == oldMethod;
+ methodEmitters.pop();
+ return methodEmitters.isEmpty() ? null : methodEmitters.peek();
+ }
+
+ CompileUnit pushCompileUnit(final CompileUnit newUnit) {
+ compileUnits.push(newUnit);
+ return newUnit;
+ }
+
+ CompileUnit popCompileUnit(final CompileUnit oldUnit) {
+ assert compileUnits.peek() == oldUnit;
+ compileUnits.pop();
+ return compileUnits.isEmpty() ? null : compileUnits.peek();
+ }
+
+ boolean hasCompileUnits() {
+ return !compileUnits.isEmpty();
+ }
+
+ Collection<SharedScopeCall> getScopeCalls() {
+ return Collections.unmodifiableCollection(scopeCalls.values());
+ }
+
+ /**
+ * Get a shared static method representing a dynamic scope callsite.
+ *
+ * @param unit current compile unit
+ * @param symbol the symbol
+ * @param valueType the value type of the symbol
+ * @param returnType the return type
+ * @param paramTypes the parameter types
+ * @param flags the callsite flags
+ * @return an object representing a shared scope call
+ */
+ SharedScopeCall getScopeCall(final CompileUnit unit, final Symbol symbol, final Type valueType, final Type returnType, final Type[] paramTypes, final int flags) {
+ final SharedScopeCall scopeCall = new SharedScopeCall(symbol, valueType, returnType, paramTypes, flags);
+ if (scopeCalls.containsKey(scopeCall)) {
+ return scopeCalls.get(scopeCall);
+ }
+ scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+ scopeCalls.put(scopeCall, scopeCall);
+ return scopeCall;
+ }
+
+ /**
+ * Get a shared static method representing a dynamic scope get access.
+ *
+ * @param unit current compile unit
+ * @param type the type of the variable
+ * @param symbol the symbol
+ * @param flags the callsite flags
+ * @return an object representing a shared scope call
+ */
+ SharedScopeCall getScopeGet(final CompileUnit unit, final Type type, final Symbol symbol, final int flags) {
+ final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags);
+ if (scopeCalls.containsKey(scopeCall)) {
+ return scopeCalls.get(scopeCall);
+ }
+ scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+ scopeCalls.put(scopeCall, scopeCall);
+ return scopeCall;
+ }
+
+
+ void nextFreeSlot(final Block block) {
+ final boolean isFunctionBody = isFunctionBody();
+
+ final int nextFreeSlot;
+ if (isFunctionBody) {
+ // On entry to function, start with slot 0
+ nextFreeSlot = 0;
+ } else {
+ // Otherwise, continue from previous block's first free slot
+ nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1];
+ }
+ if (nextFreeSlotsSize == nextFreeSlots.length) {
+ final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
+ System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
+ nextFreeSlots = newNextFreeSlots;
+ }
+ nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot);
+ }
+
+ private static int assignSlots(final Block block, final int firstSlot) {
+ int nextSlot = firstSlot;
+ for (final Symbol symbol : block.getSymbols()) {
+ if (symbol.hasSlot()) {
+ symbol.setSlot(nextSlot);
+ nextSlot += symbol.slotCount();
+ }
+ }
+ return nextSlot;
+ }
+
+ void pushDiscard(final Node node) {
+ discard.push(node);
+ }
+
+ Node popDiscard() {
+ return discard.pop();
+ }
+
+ Node getCurrentDiscard() {
+ return discard.peek();
+ }
+
+ int quickSlot(final Symbol symbol) {
+ final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1];
+ nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount();
+ return quickSlot;
+ }
+
+}
+
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu May 23 15:51:08 2013 +0200
@@ -24,15 +24,14 @@
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.CallNode;
import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.ReturnNode;
import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.TemporarySymbols;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.runtime.ECMAErrors;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
@@ -74,7 +73,7 @@
FunctionNode newFunctionNode = outermostFunctionNode;
- newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor() {
+ newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
// self references are done with invokestatic and thus cannot
// have trampolines - never lazy
@Override
@@ -107,10 +106,9 @@
lazy.remove(node);
}
- newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeOperatorVisitor() {
+ newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
- final LexicalContext lc = getLexicalContext();
if (lazy.contains(functionNode)) {
Compiler.LOG.fine(
"Marking ",
@@ -194,12 +192,11 @@
* @param functionNode node where to start iterating
*/
private FunctionNode enterAttr(final FunctionNode functionNode, final TemporarySymbols ts) {
- return (FunctionNode)functionNode.accept(new NodeVisitor() {
+ return (FunctionNode)functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public Node leaveFunctionNode(final FunctionNode node) {
- final LexicalContext lc = getLexicalContext();
if (node.isLazy()) {
- FunctionNode newNode = node.setReturnType(getLexicalContext(), Type.OBJECT);
+ FunctionNode newNode = node.setReturnType(lc, Type.OBJECT);
return ts.ensureSymbol(lc, Type.OBJECT, newNode);
}
//node may have a reference here that needs to be nulled if it was referred to by
@@ -230,7 +227,7 @@
FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer());
final List<ReturnNode> returns = new ArrayList<>();
- newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor() {
+ newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private final Deque<ArrayList<ReturnNode>> returnStack = new ArrayDeque<>();
@Override
@@ -249,7 +246,7 @@
}
returnType = Type.widest(returnType, ret.getExpression().getType());
}
- return functionNode.setReturnType(getLexicalContext(), returnType);
+ return functionNode.setReturnType(lc, returnType);
}
@Override
@@ -270,8 +267,8 @@
}
final Type rangeType = range.getType();
if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
- RangeAnalyzer.LOG.info("[", getLexicalContext().getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
- return node.setSymbol(getLexicalContext(), symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
+ RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
+ return node.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
}
}
return node;
--- a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Thu May 23 15:51:08 2013 +0200
@@ -31,6 +31,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.AccessNode;
import jdk.nashorn.internal.ir.Assignment;
@@ -84,13 +85,14 @@
* and frame optimizations
*/
-final class FinalizeTypes extends NodeOperatorVisitor {
+final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
private static final DebugLogger LOG = new DebugLogger("finalize");
private final TemporarySymbols temporarySymbols;
FinalizeTypes(final TemporarySymbols temporarySymbols) {
+ super(new LexicalContext());
this.temporarySymbols = temporarySymbols;
}
@@ -233,7 +235,7 @@
private boolean symbolIsInteger(Node node) {
final Symbol symbol = node.getSymbol();
- assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + getLexicalContext().getCurrentFunction().getSource();
+ assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + lc.getCurrentFunction().getSource();
return true;
}
@@ -382,12 +384,10 @@
final Node test = forNode.getTest();
final Node modify = forNode.getModify();
- final LexicalContext lc = getLexicalContext();
-
if (forNode.isForIn()) {
return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400
}
- assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + getLexicalContext().getCurrentFunction();
+ assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction();
return forNode.
setInit(lc, init == null ? null : discard(init)).
@@ -419,7 +419,7 @@
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
- return functionNode.setState(getLexicalContext(), CompilationState.FINALIZED);
+ return functionNode.setState(lc, CompilationState.FINALIZED);
}
@Override
@@ -450,7 +450,7 @@
public Node leaveReturnNode(final ReturnNode returnNode) {
final Node expr = returnNode.getExpression();
if (expr != null) {
- return returnNode.setExpression(convert(expr, getLexicalContext().getCurrentFunction().getReturnType()));
+ return returnNode.setExpression(convert(expr, lc.getCurrentFunction().getReturnType()));
}
return returnNode;
}
@@ -482,8 +482,8 @@
}
return switchNode.
- setExpression(getLexicalContext(), convert(expression, Type.OBJECT)).
- setCases(getLexicalContext(), newCases);
+ setExpression(lc, convert(expression, Type.OBJECT)).
+ setCases(lc, newCases);
}
@Override
@@ -519,14 +519,14 @@
public Node leaveWhileNode(final WhileNode whileNode) {
final Node test = whileNode.getTest();
if (test != null) {
- return whileNode.setTest(getLexicalContext(), convert(test, Type.BOOLEAN));
+ return whileNode.setTest(lc, convert(test, Type.BOOLEAN));
}
return whileNode;
}
@Override
public Node leaveWithNode(final WithNode withNode) {
- return withNode.setExpression(getLexicalContext(), convert(withNode.getExpression(), Type.OBJECT));
+ return withNode.setExpression(lc, convert(withNode.getExpression(), Type.OBJECT));
}
private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
@@ -550,7 +550,6 @@
return; // nothing to do
}
- final LexicalContext lc = getLexicalContext();
final FunctionNode functionNode = lc.getFunction(block);
final boolean allVarsInScope = functionNode.allVarsInScope();
final boolean isVarArg = functionNode.isVarArg();
@@ -652,7 +651,7 @@
private static void setCanBePrimitive(final Node node, final Type to) {
final HashSet<Node> exclude = new HashSet<>();
- node.accept(new NodeVisitor() {
+ node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private void setCanBePrimitive(final Symbol symbol) {
LOG.info("*** can be primitive symbol ", symbol, " ", Debug.id(symbol));
symbol.setCanBePrimitive(to);
@@ -762,7 +761,7 @@
}
}
LOG.info("Type override for lhs in '", node, "' => ", to);
- return ((TypeOverride<T>)node).setType(temporarySymbols, getLexicalContext(), to);
+ return ((TypeOverride<T>)node).setType(temporarySymbols, lc, to);
}
/**
@@ -785,8 +784,8 @@
private Node convert(final Node node, final Type to) {
assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass();
assert node != null : "node is null";
- assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + getLexicalContext().getCurrentFunction();
- assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + getLexicalContext().getCurrentFunction();
+ assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + lc.getCurrentFunction();
+ assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + lc.getCurrentFunction();
final Type from = node.getType();
@@ -817,7 +816,6 @@
assert !node.isTerminal();
- final LexicalContext lc = getLexicalContext();
//This is the only place in this file that can create new temporaries
//FinalizeTypes may not introduce ANY node that is not a conversion.
return temporarySymbols.ensureSymbol(lc, to, resultNode);
@@ -854,7 +852,7 @@
symbol = symbol.setTypeOverrideShared(to, temporarySymbols);
LOG.info("Type override for temporary in '", node, "' => ", to);
}
- return node.setSymbol(getLexicalContext(), symbol);
+ return node.setSymbol(lc, symbol);
}
/**
@@ -907,7 +905,7 @@
if (literalNode != null) {
//inherit literal symbol for attr.
- literalNode = (LiteralNode<?>)literalNode.setSymbol(getLexicalContext(), parent.getSymbol());
+ literalNode = (LiteralNode<?>)literalNode.setSymbol(lc, parent.getSymbol());
}
return literalNode;
--- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java Thu May 23 15:51:08 2013 +0200
@@ -33,6 +33,7 @@
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
import jdk.nashorn.internal.ir.Node;
@@ -46,11 +47,12 @@
/**
* Simple constant folding pass, executed before IR is starting to be lowered.
*/
-final class FoldConstants extends NodeVisitor {
+final class FoldConstants extends NodeVisitor<LexicalContext> {
private static final DebugLogger LOG = new DebugLogger("fold");
FoldConstants() {
+ super(new LexicalContext());
}
@Override
@@ -80,7 +82,7 @@
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
- return functionNode.setState(getLexicalContext(), CompilationState.CONSTANT_FOLDED);
+ return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED);
}
@Override
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Thu May 23 15:51:08 2013 +0200
@@ -80,7 +80,7 @@
* finalized.
*/
-final class Lower extends NodeOperatorVisitor {
+final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
private static final DebugLogger LOG = new DebugLogger("lower");
@@ -105,7 +105,7 @@
terminated = true;
}
} else {
- statement.accept(new NodeVisitor() {
+ statement.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterVarNode(final VarNode varNode) {
newStatements.add(varNode.setInit(null));
@@ -121,7 +121,6 @@
@Override
public boolean enterBlock(final Block block) {
- final LexicalContext lc = getLexicalContext();
final FunctionNode function = lc.getCurrentFunction();
if (lc.isFunctionBody() && function.isProgram() && !function.hasDeclaredFunctions()) {
new ExecuteNode(block.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this);
@@ -134,12 +133,10 @@
//now we have committed the entire statement list to the block, but we need to truncate
//whatever is after the last terminal. block append won't append past it
- final BlockLexicalContext lc = (BlockLexicalContext)getLexicalContext();
-
Statement last = lc.getLastStatement();
if (lc.isFunctionBody()) {
- final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
+ final FunctionNode currentFunction = lc.getCurrentFunction();
final boolean isProgram = currentFunction.isProgram();
final ReturnNode returnNode = new ReturnNode(
last == null ? block.getLineNumber() : last.getLineNumber(), //TODO?
@@ -191,7 +188,7 @@
final Node expr = executeNode.getExpression();
ExecuteNode node = executeNode;
- final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
+ final FunctionNode currentFunction = lc.getCurrentFunction();
if (currentFunction.isProgram()) {
if (!(expr instanceof Block) || expr instanceof FunctionNode) { // it's not a block, but can be a function
@@ -216,7 +213,7 @@
final Node test = forNode.getTest();
if (!forNode.isForIn() && conservativeAlwaysTrue(test)) {
- newForNode = forNode.setTest(getLexicalContext(), null);
+ newForNode = forNode.setTest(lc, null);
}
return addStatement(checkEscape(newForNode));
@@ -230,7 +227,7 @@
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
LOG.info("END FunctionNode: ", functionNode.getName());
- return functionNode.setState(getLexicalContext(), CompilationState.LOWERED);
+ return functionNode.setState(lc, CompilationState.LOWERED);
}
@Override
@@ -262,16 +259,16 @@
}
private static Node ensureUniqueNamesIn(final LexicalContext lc, final Node node) {
- return node.accept(new NodeVisitor() {
+ return node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
final String name = functionNode.getName();
- return functionNode.setName(getLexicalContext(), lc.getCurrentFunction().uniqueName(name));
+ return functionNode.setName(lc, lc.getCurrentFunction().uniqueName(name));
}
@Override
public Node leaveDefault(final Node labelledNode) {
- return labelledNode.ensureUniqueLabels(getLexicalContext());
+ return labelledNode.ensureUniqueLabels(lc);
}
});
}
@@ -292,10 +289,10 @@
final long token = tryNode.getToken();
final int finish = tryNode.getFinish();
- final IdentNode exception = new IdentNode(token, finish, getLexicalContext().getCurrentFunction().uniqueName("catch_all"));
+ final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName("catch_all"));
final Block catchBody = new Block(lineNumber, token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW)).
- setIsTerminal(getLexicalContext(), true); //ends with throw, so terminal
+ setIsTerminal(lc, true); //ends with throw, so terminal
final CatchNode catchAllNode = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, CatchNode.IS_SYNTHETIC_RETHROW);
final Block catchAllBlock = new Block(lineNumber, token, finish, catchAllNode);
@@ -306,7 +303,7 @@
}
private IdentNode compilerConstant(final CompilerConstants cc) {
- final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
+ final FunctionNode functionNode = lc.getCurrentFunction();
return new IdentNode(functionNode.getToken(), functionNode.getFinish(), cc.symbolName());
}
@@ -324,9 +321,8 @@
private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
assert tryNode.getFinallyBody() == null;
final int finish = tryNode.getFinish();
- final LexicalContext lc = getLexicalContext();
- final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() {
+ final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
final List<Node> insideTry = new ArrayList<>();
@Override
@@ -355,12 +351,12 @@
@Override
public Node leaveBreakNode(final BreakNode breakNode) {
- return copy(breakNode, Lower.this.getLexicalContext().getBreakable(breakNode.getLabel()));
+ return copy(breakNode, Lower.this.lc.getBreakable(breakNode.getLabel()));
}
@Override
public Node leaveContinueNode(final ContinueNode continueNode) {
- return copy(continueNode, Lower.this.getLexicalContext().getContinueTo(continueNode.getLabel()));
+ return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabel()));
}
@Override
@@ -383,7 +379,7 @@
newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
}
- return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), getLexicalContext().getCurrentBlock().getFinish(), newStatements));
+ return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), lc.getCurrentBlock().getFinish(), newStatements));
}
private Node copy(final Statement endpoint, final Node targetNode) {
@@ -442,7 +438,7 @@
final Block catchAll = catchAllBlock(tryNode);
final List<ThrowNode> rethrows = new ArrayList<>();
- catchAll.accept(new NodeVisitor() {
+ catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterThrowNode(final ThrowNode throwNode) {
rethrows.add(throwNode);
@@ -470,7 +466,7 @@
@Override
public Node leaveVarNode(final VarNode varNode) {
addStatement(varNode);
- if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && getLexicalContext().getCurrentFunction().isProgram()) {
+ if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && lc.getCurrentFunction().isProgram()) {
new ExecuteNode(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this);
}
return varNode;
@@ -484,7 +480,7 @@
if (conservativeAlwaysTrue(test)) {
//turn it into a for node without a test.
final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), null, null, body, null, ForNode.IS_FOR).accept(this);
- getLexicalContext().replace(whileNode, forNode);
+ lc.replace(whileNode, forNode);
return forNode;
}
@@ -519,7 +515,7 @@
* @return eval location
*/
private String evalLocation(final IdentNode node) {
- final Source source = getLexicalContext().getCurrentFunction().getSource();
+ final Source source = lc.getCurrentFunction().getSource();
return new StringBuilder().
append(source.getName()).
append('#').
@@ -551,10 +547,10 @@
// 'eval' call with at least one argument
if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) {
- final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
+ final FunctionNode currentFunction = lc.getCurrentFunction();
return callNode.setEvalArgs(
new CallNode.EvalArgs(
- ensureUniqueNamesIn(getLexicalContext(), args.get(0)).accept(this),
+ ensureUniqueNamesIn(lc, args.get(0)).accept(this),
compilerConstant(THIS),
evalLocation(callee),
currentFunction.isStrict()));
@@ -580,7 +576,7 @@
private static boolean controlFlowEscapes(final LexicalContext lex, final Block loopBody) {
final List<Node> escapes = new ArrayList<>();
- loopBody.accept(new NodeVisitor() {
+ loopBody.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public Node leaveBreakNode(final BreakNode node) {
escapes.add(node);
@@ -601,7 +597,6 @@
}
private LoopNode checkEscape(final LoopNode loopNode) {
- final LexicalContext lc = getLexicalContext();
final boolean escapes = controlFlowEscapes(lc, loopNode.getBody());
if (escapes) {
return loopNode.
@@ -613,7 +608,7 @@
private Node addStatement(final Statement statement) {
- ((BlockLexicalContext)getLexicalContext()).appendStatement(statement);
+ lc.appendStatement(statement);
return statement;
}
--- a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Thu May 23 15:51:08 2013 +0200
@@ -35,6 +35,7 @@
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
import jdk.nashorn.internal.ir.LoopNode;
@@ -61,7 +62,7 @@
*
* Proves that the multiplication never exceeds 24 bits and can thus be an int
*/
-final class RangeAnalyzer extends NodeOperatorVisitor {
+final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
static final DebugLogger LOG = new DebugLogger("ranges");
private static final Range.Functionality RANGE = new Range.Functionality(LOG);
@@ -69,6 +70,7 @@
private final Map<LoopNode, Symbol> loopCounters = new HashMap<>();
RangeAnalyzer() {
+ super(new LexicalContext());
}
@Override
@@ -96,7 +98,7 @@
final Range symRange = RANGE.join(symbol.getRange(), range);
//anything assigned in the loop, not being the safe loop counter(s) invalidates its entire range
- if (getLexicalContext().inLoop() && !isLoopCounter(getLexicalContext().getCurrentLoop(), symbol)) {
+ if (lc.inLoop() && !isLoopCounter(lc.getCurrentLoop(), symbol)) {
symbol.setRange(Range.createGenericRange());
return symbol;
}
@@ -399,7 +401,7 @@
final HashSet<Node> skip = new HashSet<>();
final HashSet<Node> assignmentsInLoop = new HashSet<>();
- loopNode.accept(new NodeVisitor() {
+ loopNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private boolean assigns(final Node node, final Symbol s) {
return node.isAssignment() && ((Assignment<?>)node).getAssignmentDest().getSymbol() == s;
}
--- a/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Thu May 23 15:51:08 2013 +0200
@@ -116,9 +116,10 @@
/**
* Generate the invoke instruction for this shared scope call.
* @param method the method emitter
+ * @return the method emitter
*/
- public void generateInvoke(final MethodEmitter method) {
- method.invokestatic(compileUnit.getUnitClassName(), methodName, getStaticSignature());
+ public MethodEmitter generateInvoke(final MethodEmitter method) {
+ return method.invokestatic(compileUnit.getUnitClassName(), methodName, getStaticSignature());
}
/**
--- a/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java Thu May 23 15:51:08 2013 +0200
@@ -49,12 +49,12 @@
/**
* Split the IR into smaller compile units.
*/
-final class Splitter extends NodeVisitor {
+final class Splitter extends NodeVisitor<LexicalContext> {
/** Current compiler. */
private final Compiler compiler;
/** IR to be broken down. */
- private FunctionNode outermost;
+ private final FunctionNode outermost;
/** Compile unit for the main script. */
private final CompileUnit outermostCompileUnit;
@@ -75,6 +75,7 @@
* @param outermostCompileUnit compile unit for outermost function, if non-lazy this is the script's compile unit
*/
public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) {
+ super(new LexicalContext());
this.compiler = compiler;
this.outermost = functionNode;
this.outermostCompileUnit = outermostCompileUnit;
@@ -93,8 +94,6 @@
LOG.finest("Initiating split of '", functionNode.getName(), "'");
- final LexicalContext lc = getLexicalContext();
-
long weight = WeighNodes.weigh(functionNode);
final boolean top = fn.isProgram(); //compiler.getFunctionNode() == outermost;
@@ -127,7 +126,7 @@
final Block body = functionNode.getBody();
final List<FunctionNode> dc = directChildren(functionNode);
- final Block newBody = (Block)body.accept(new NodeVisitor() {
+ final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterFunctionNode(final FunctionNode nestedFunction) {
return dc.contains(nestedFunction);
@@ -136,7 +135,7 @@
@Override
public Node leaveFunctionNode(final FunctionNode nestedFunction) {
FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction);
- getLexicalContext().replace(nestedFunction, split);
+ lc.replace(nestedFunction, split);
return split;
}
});
@@ -149,13 +148,13 @@
private static List<FunctionNode> directChildren(final FunctionNode functionNode) {
final List<FunctionNode> dc = new ArrayList<>();
- functionNode.accept(new NodeVisitor() {
+ functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterFunctionNode(final FunctionNode child) {
if (child == functionNode) {
return true;
}
- if (getLexicalContext().getParentFunction(child) == functionNode) {
+ if (lc.getParentFunction(child) == functionNode) {
dc.add(child);
}
return false;
@@ -181,7 +180,7 @@
* @return new weight for the resulting block.
*/
private Block splitBlock(final Block block, final FunctionNode function) {
- getLexicalContext().setFlag(getLexicalContext().getCurrentFunction(), FunctionNode.IS_SPLIT);
+ lc.setFlag(lc.getCurrentFunction(), FunctionNode.IS_SPLIT);
final List<Statement> splits = new ArrayList<>();
List<Statement> statements = new ArrayList<>();
@@ -210,7 +209,7 @@
splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
}
- return block.setStatements(getLexicalContext(), splits);
+ return block.setStatements(lc, splits);
}
/**
@@ -258,7 +257,7 @@
// been split already, so weigh again before splitting.
long weight = WeighNodes.weigh(block, weightCache);
if (weight >= SPLIT_THRESHOLD) {
- newBlock = splitBlock(block, getLexicalContext().getFunction(block));
+ newBlock = splitBlock(block, lc.getFunction(block));
weight = WeighNodes.weigh(newBlock, weightCache);
}
weightCache.put(newBlock, weight);
@@ -274,9 +273,9 @@
return literal;
}
- final FunctionNode functionNode = getLexicalContext().getCurrentFunction();
+ final FunctionNode functionNode = lc.getCurrentFunction();
- getLexicalContext().setFlag(functionNode, FunctionNode.IS_SPLIT);
+ lc.setFlag(functionNode, FunctionNode.IS_SPLIT);
if (literal instanceof ArrayLiteralNode) {
final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
--- a/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java Thu May 23 15:51:08 2013 +0200
@@ -27,6 +27,7 @@
import java.util.List;
import java.util.Map;
+
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.AccessNode;
import jdk.nashorn.internal.ir.BinaryNode;
@@ -41,6 +42,7 @@
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
@@ -63,7 +65,7 @@
* Computes the "byte code" weight of an AST segment. This is used
* for Splitting too large class files
*/
-final class WeighNodes extends NodeOperatorVisitor {
+final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
/*
* Weight constants.
*/
@@ -100,7 +102,7 @@
* @param weightCache cache of already calculated block weights
*/
private WeighNodes(FunctionNode topFunction, final Map<Node, Long> weightCache) {
- super();
+ super(new LexicalContext());
this.topFunction = topFunction;
this.weightCache = weightCache;
}
--- a/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java Thu May 23 15:51:08 2013 +0200
@@ -60,7 +60,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterAccessNode(this)) {
return visitor.leaveAccessNode(
setBase(base.accept(visitor)).
@@ -110,7 +110,6 @@
return new AccessNode(this, base, property, isFunction(), hasCallSiteType());
}
-
private AccessNode setProperty(final IdentNode property) {
if (this.property == property) {
return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java Thu May 23 15:51:08 2013 +0200
@@ -160,7 +160,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterBinaryNode(this)) {
return visitor.leaveBinaryNode(setLHS(lhs.accept(visitor)).setRHS(rhs.accept(visitor)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/Block.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/Block.java Thu May 23 15:51:08 2013 +0200
@@ -131,7 +131,7 @@
* @return new or same node
*/
@Override
- public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterBlock(this)) {
return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, Statement.class, statements)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java Thu May 23 15:51:08 2013 +0200
@@ -59,7 +59,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterBreakNode(this)) {
return visitor.leaveBreakNode(this);
}
--- a/nashorn/src/jdk/nashorn/internal/ir/CallNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java Thu May 23 15:51:08 2013 +0200
@@ -27,6 +27,7 @@
import java.util.Collections;
import java.util.List;
+
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -194,7 +195,7 @@
* @return node or replacement
*/
@Override
- public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterCallNode(this)) {
final CallNode newCallNode = (CallNode)visitor.leaveCallNode(
setFunction(function.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java Thu May 23 15:51:08 2013 +0200
@@ -78,7 +78,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterCaseNode(this)) {
final Node newTest = test == null ? null : test.accept(visitor);
final Block newBody = body == null ? null : (Block)body.accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java Thu May 23 15:51:08 2013 +0200
@@ -79,7 +79,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterCatchNode(this)) {
return visitor.leaveCatchNode(
setException((IdentNode)exception.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java Thu May 23 15:51:08 2013 +0200
@@ -55,7 +55,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterContinueNode(this)) {
return visitor.leaveContinueNode(this);
}
--- a/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java Thu May 23 15:51:08 2013 +0200
@@ -56,7 +56,7 @@
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterEmptyNode(this)) {
return visitor.leaveEmptyNode(this);
}
--- a/nashorn/src/jdk/nashorn/internal/ir/ExecuteNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/ExecuteNode.java Thu May 23 15:51:08 2013 +0200
@@ -62,7 +62,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterExecuteNode(this)) {
return visitor.leaveExecuteNode(setExpression(expression.accept(visitor)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/ForNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/ForNode.java Thu May 23 15:51:08 2013 +0200
@@ -86,7 +86,7 @@
}
@Override
- protected Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterForNode(this)) {
return visitor.leaveForNode(
setInit(lc, init == null ? null : init.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java Thu May 23 15:51:08 2013 +0200
@@ -281,7 +281,7 @@
}
@Override
- public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterFunctionNode(this)) {
return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java Thu May 23 15:51:08 2013 +0200
@@ -29,7 +29,6 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
-
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -119,7 +118,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterIdentNode(this)) {
return visitor.leaveIdentNode(this);
}
--- a/nashorn/src/jdk/nashorn/internal/ir/IfNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/IfNode.java Thu May 23 15:51:08 2013 +0200
@@ -72,7 +72,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterIfNode(this)) {
return visitor.leaveIfNode(
setTest(test.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java Thu May 23 15:51:08 2013 +0200
@@ -56,19 +56,12 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterIndexNode(this)) {
- final Node newBase = base.accept(visitor);
- final Node newIndex = index.accept(visitor);
- final IndexNode newNode;
- if (newBase != base || newIndex != index) {
- newNode = new IndexNode(this, newBase, newIndex, isFunction(), hasCallSiteType());
- } else {
- newNode = this;
- }
- return visitor.leaveIndexNode(newNode);
+ return visitor.leaveIndexNode(
+ setBase(base.accept(visitor)).
+ setIndex(index.accept(visitor)));
}
-
return this;
}
@@ -106,6 +99,13 @@
return index;
}
+ private IndexNode setBase(final Node base) {
+ if (this.base == base) {
+ return this;
+ }
+ return new IndexNode(this, base, index, isFunction(), hasCallSiteType());
+ }
+
/**
* Set the index expression for this node
* @param index new index expression
--- a/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java Thu May 23 15:51:08 2013 +0200
@@ -67,11 +67,11 @@
}
@Override
- public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLabelNode(this)) {
return visitor.leaveLabelNode(
- setLabel(visitor.getLexicalContext(), (IdentNode)label.accept(visitor)).
- setBody(visitor.getLexicalContext(), (Block)body.accept(visitor)));
+ setLabel(lc, (IdentNode)label.accept(visitor)).
+ setBody(lc, (Block)body.accept(visitor)));
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java Thu May 23 15:51:08 2013 +0200
@@ -60,10 +60,10 @@
*
* @return new node or same node depending on state change
*/
- protected abstract Node accept(final LexicalContext lc, final NodeVisitor visitor);
+ protected abstract Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor);
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
final LexicalContext lc = visitor.getLexicalContext();
lc.push(this);
final LexicalContextNode newNode = (LexicalContextNode)accept(lc, visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java Thu May 23 15:51:08 2013 +0200
@@ -28,6 +28,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -208,7 +209,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLiteralNode(this)) {
return visitor.leaveLiteralNode(this);
}
@@ -514,7 +515,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLiteralNode(this)) {
if (value != null) {
final Node newValue = value.accept(visitor);
@@ -840,7 +841,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLiteralNode(this)) {
final List<Node> oldValue = Arrays.asList(value);
final List<Node> newValue = Node.accept(visitor, Node.class, oldValue);
--- a/nashorn/src/jdk/nashorn/internal/ir/Node.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/Node.java Thu May 23 15:51:08 2013 +0200
@@ -27,6 +27,7 @@
import java.util.ArrayList;
import java.util.List;
+
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.Token;
@@ -175,7 +176,7 @@
* @param visitor Node visitor.
* @return node the node or its replacement after visitation, null if no further visitations are required
*/
- public abstract Node accept(NodeVisitor visitor);
+ public abstract Node accept(NodeVisitor<? extends LexicalContext> visitor);
@Override
public String toString() {
@@ -337,7 +338,7 @@
}
//on change, we have to replace the entire list, that's we can't simple do ListIterator.set
- static <T extends Node> List<T> accept(final NodeVisitor visitor, final Class<T> clazz, final List<T> list) {
+ static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final Class<T> clazz, final List<T> list) {
boolean changed = false;
final List<T> newList = new ArrayList<>();
--- a/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java Thu May 23 15:51:08 2013 +0200
@@ -58,7 +58,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterObjectNode(this)) {
return visitor.leaveObjectNode(setElements(Node.accept(visitor, Node.class, elements)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java Thu May 23 15:51:08 2013 +0200
@@ -81,7 +81,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterPropertyNode(this)) {
return visitor.leavePropertyNode(
setKey((PropertyKey)((Node)key).accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java Thu May 23 15:51:08 2013 +0200
@@ -86,7 +86,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterReturnNode(this)) {
if (expression != null) {
return visitor.leaveReturnNode(setExpression(expression.accept(visitor)));
--- a/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu May 23 15:51:08 2013 +0200
@@ -29,6 +29,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -407,7 +408,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterRuntimeNode(this)) {
final List<Node> newArgs = new ArrayList<>();
for (final Node arg : args) {
--- a/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java Thu May 23 15:51:08 2013 +0200
@@ -81,7 +81,7 @@
}
@Override
- public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterSplitNode(this)) {
return visitor.leaveSplitNode(setBody(lc, body.accept(visitor)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java Thu May 23 15:51:08 2013 +0200
@@ -100,11 +100,11 @@
}
@Override
- public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterSwitchNode(this)) {
return visitor.leaveSwitchNode(
- setExpression(visitor.getLexicalContext(), expression.accept(visitor)).
- setCases(visitor.getLexicalContext(), Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
+ setExpression(lc, expression.accept(visitor)).
+ setCases(lc, Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java Thu May 23 15:51:08 2013 +0200
@@ -63,7 +63,7 @@
}
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterTernaryNode(this)) {
final Node newLhs = lhs().accept(visitor);
final Node newRhs = rhs().accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java Thu May 23 15:51:08 2013 +0200
@@ -72,7 +72,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterThrowNode(this)) {
return visitor.leaveThrowNode(setExpression(expression.accept(visitor)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/TryNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/TryNode.java Thu May 23 15:51:08 2013 +0200
@@ -106,7 +106,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterTryNode(this)) {
// Need to do finallybody first for termination analysis. TODO still necessary?
final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java Thu May 23 15:51:08 2013 +0200
@@ -29,7 +29,6 @@
import static jdk.nashorn.internal.parser.TokenType.CONVERT;
import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
-
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -121,7 +120,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterUnaryNode(this)) {
return visitor.leaveUnaryNode(setRHS(rhs.accept(visitor)));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/VarNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/VarNode.java Thu May 23 15:51:08 2013 +0200
@@ -121,7 +121,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterVarNode(this)) {
final IdentNode newName = (IdentNode)name.accept(visitor);
final Node newInit = init == null ? null : init.accept(visitor);
--- a/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java Thu May 23 15:51:08 2013 +0200
@@ -75,7 +75,7 @@
}
@Override
- protected Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterWhileNode(this)) {
if (isDoWhile()) {
return visitor.leaveWhileNode(
--- a/nashorn/src/jdk/nashorn/internal/ir/WithNode.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/WithNode.java Thu May 23 15:51:08 2013 +0200
@@ -64,7 +64,7 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final LexicalContext lc, final NodeVisitor visitor) {
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterWithNode(this)) {
return visitor.leaveWithNode(
setExpression(lc, expression.accept(visitor)).
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Thu May 23 15:51:08 2013 +0200
@@ -45,6 +45,7 @@
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ObjectNode;
@@ -74,7 +75,8 @@
/**
* This IR writer produces a JSON string that represents AST as a JSON string.
*/
-public final class JSONWriter extends NodeVisitor {
+public final class JSONWriter extends NodeVisitor<LexicalContext> {
+
/**
* Returns AST as JSON compatible string.
*
@@ -867,7 +869,8 @@
// Internals below
private JSONWriter(final boolean includeLocation) {
- this.buf = new StringBuilder();
+ super(new LexicalContext());
+ this.buf = new StringBuilder();
this.includeLocation = includeLocation;
}
@@ -963,7 +966,7 @@
objectStart("loc");
// source name
- final Source src = getLexicalContext().getCurrentFunction().getSource();
+ final Source src = lc.getCurrentFunction().getSource();
property("source", src.getName());
comma();
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java Thu May 23 15:51:08 2013 +0200
@@ -36,6 +36,7 @@
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.SplitNode;
import jdk.nashorn.internal.ir.Statement;
@@ -53,7 +54,7 @@
*
* see the flags --print-parse and --print-lower-parse
*/
-public final class PrintVisitor extends NodeVisitor {
+public final class PrintVisitor extends NodeVisitor<LexicalContext> {
/** Tab width */
private static final int TABWIDTH = 4;
@@ -84,6 +85,7 @@
* @param printLineNumbers should line number nodes be included in the output?
*/
public PrintVisitor(final boolean printLineNumbers) {
+ super(new LexicalContext());
this.EOLN = System.lineSeparator();
this.sb = new StringBuilder();
this.printLineNumbers = printLineNumbers;
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Thu May 23 15:51:08 2013 +0200
@@ -32,21 +32,15 @@
/**
* Like NodeVisitor but navigating further into operators.
+ * @param <T> Lexical context class for this NodeOperatorVisitor
*/
-public class NodeOperatorVisitor extends NodeVisitor {
- /**
- * Constructor
- */
- public NodeOperatorVisitor() {
- super();
- }
-
+public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
/**
* Constructor
*
* @param lc a custom lexical context
*/
- public NodeOperatorVisitor(final LexicalContext lc) {
+ public NodeOperatorVisitor(final T lc) {
super(lc);
}
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Thu May 23 15:51:08 2013 +0200
@@ -60,23 +60,18 @@
/**
* Visitor used to navigate the IR.
+ * @param <T> lexical context class used by this visitor
*/
-public abstract class NodeVisitor {
- private final LexicalContext lc;
-
- /**
- * Constructor
- */
- public NodeVisitor() {
- this(new LexicalContext());
- }
+public abstract class NodeVisitor<T extends LexicalContext> {
+ /** lexical context in use */
+ protected final T lc;
/**
* Constructor
*
* @param lc a custom lexical context
*/
- public NodeVisitor(final LexicalContext lc) {
+ public NodeVisitor(final T lc) {
this.lc = lc;
}
@@ -84,7 +79,7 @@
* Get the lexical context of this node visitor
* @return lexical context
*/
- public LexicalContext getLexicalContext() {
+ public T getLexicalContext() {
return lc;
}
--- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java Thu May 23 15:51:08 2013 +0200
@@ -28,7 +28,6 @@
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
--- a/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java Thu May 23 15:51:08 2013 +0200
@@ -35,7 +35,6 @@
*/
public final class DebugLogger {
- @SuppressWarnings("NonConstantLogger")
private final Logger logger;
private final boolean isEnabled;
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu May 23 15:51:08 2013 +0200
@@ -43,6 +43,7 @@
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.SecureClassLoader;
+
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
@@ -58,6 +59,7 @@
* "class loader", it does not, in fact, extend {@code ClassLoader}, but rather uses them internally. Instances of this
* class are normally created by {@link JavaAdapterBytecodeGenerator}.
*/
+@SuppressWarnings("javadoc")
class JavaAdapterClassLoader extends JavaAdapterGeneratorBase {
private static final Type PRIVILEGED_ACTION_TYPE = Type.getType(PrivilegedAction.class);
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu May 23 15:51:08 2013 +0200
@@ -39,6 +39,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.support.LinkRequestImpl;
import jdk.nashorn.internal.objects.NativeJava;
@@ -66,6 +67,7 @@
* </p>
*/
+@SuppressWarnings("javadoc")
public final class JavaAdapterFactory {
/**
* A mapping from an original Class object to AdapterInfo representing the adapter for the class it represents.
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java Thu May 23 09:49:03 2013 -0300
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java Thu May 23 15:51:08 2013 +0200
@@ -33,6 +33,7 @@
* Base class for both {@link JavaAdapterBytecodeGenerator} and {@link JavaAdapterClassLoader}, containing those
* bytecode types, type names and method descriptor that are used by both.
*/
+@SuppressWarnings("javadoc")
abstract class JavaAdapterGeneratorBase {
static final Type CONTEXT_TYPE = Type.getType(Context.class);
static final Type OBJECT_TYPE = Type.getType(Object.class);