diff options
Diffstat (limited to 'src/jdk/nashorn/internal/ir/Block.java')
-rw-r--r-- | src/jdk/nashorn/internal/ir/Block.java | 363 |
1 files changed, 55 insertions, 308 deletions
diff --git a/src/jdk/nashorn/internal/ir/Block.java b/src/jdk/nashorn/internal/ir/Block.java index 9449be5b..6f138f85 100644 --- a/src/jdk/nashorn/internal/ir/Block.java +++ b/src/jdk/nashorn/internal/ir/Block.java @@ -25,41 +25,24 @@ package jdk.nashorn.internal.ir; -import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL; -import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; -import static jdk.nashorn.internal.ir.Symbol.IS_LET; -import static jdk.nashorn.internal.ir.Symbol.IS_PARAM; -import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE; -import static jdk.nashorn.internal.ir.Symbol.IS_VAR; -import static jdk.nashorn.internal.ir.Symbol.KINDMASK; - import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import jdk.nashorn.internal.codegen.Frame; import jdk.nashorn.internal.codegen.Label; -import jdk.nashorn.internal.ir.annotations.Ignore; -import jdk.nashorn.internal.ir.annotations.ParentNode; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source; /** * IR representation for a list of statements and functions. All provides the * basis for script body. - * */ public class Block extends Node { - /** Parent context */ - @ParentNode @Ignore - private Block parent; - - /** Owning function. */ - @Ignore //don't print it, it is apparent in the tree - protected FunctionNode function; - /** List of statements */ protected List<Node> statements; @@ -84,14 +67,10 @@ public class Block extends Node { * @param source source code * @param token token * @param finish finish - * @param parent reference to parent block - * @param function function node this block is in */ - public Block(final Source source, final long token, final int finish, final Block parent, final FunctionNode function) { + public Block(final Source source, final long token, final int finish) { super(source, token, finish); - this.parent = parent; - this.function = function; this.statements = new ArrayList<>(); this.symbols = new HashMap<>(); this.entryLabel = new Label("block_entry"); @@ -107,8 +86,6 @@ public class Block extends Node { protected Block(final Block block, final CopyState cs) { super(block); - this.parent = block.parent; - this.function = block.function; this.statements = new ArrayList<>(); for (final Node statement : block.getStatements()) { statements.add(cs.existingOrCopy(statement)); @@ -123,55 +100,7 @@ public class Block extends Node { @Override protected Node copy(final CopyState cs) { - return fixBlockChain(new Block(this, cs)); - } - - /** - * Whenever a clone that contains a hierarchy of blocks is created, - * this function has to be called to ensure that the parents point - * to the correct parent blocks or two different ASTs would not - * be completely separated. - * - * @return the argument - */ - static Block fixBlockChain(final Block root) { - root.accept(new NodeVisitor() { - private Block parent = root.getParent(); - private final FunctionNode function = root.getFunction(); - - @Override - public Node enter(final Block block) { - assert block.getFunction() == function; - block.setParent(parent); - parent = block; - - return block; - } - - @Override - public Node leave(final Block block) { - parent = block.getParent(); - - return block; - } - - @Override - public Node enter(final FunctionNode functionNode) { - assert functionNode.getFunction() == function; - - return enter((Block)functionNode); - } - - @Override - public Node leave(final FunctionNode functionNode) { - assert functionNode.getFunction() == function; - - return leave((Block)functionNode); - } - - }); - - return root; + return new Block(this, cs); } /** @@ -189,17 +118,12 @@ public class Block extends Node { } /** - * Prepend a statement to the statement list + * Prepend statements to the statement list * - * @param statement Statement node to add + * @param prepended statement to add */ - public void prependStatement(final Node statement) { - if (statement != null) { - final List<Node> newStatements = new ArrayList<>(); - newStatements.add(statement); - newStatements.addAll(statements); - setStatements(newStatements); - } + public void prependStatements(final List<Node> prepended) { + statements.addAll(0, prepended); } /** @@ -212,39 +136,6 @@ public class Block extends Node { } /** - * Add a new function to the function list. - * - * @param functionNode Function node to add. - */ - public void addFunction(final FunctionNode functionNode) { - assert parent != null : "Parent context missing."; - - parent.addFunction(functionNode); - } - - /** - * Add a list of functions to the function list. - * - * @param functionNodes Function nodes to add. - */ - public void addFunctions(final List<FunctionNode> functionNodes) { - assert parent != null : "Parent context missing."; - - parent.addFunctions(functionNodes); - } - - /** - * Set the function list to a new one - * - * @param functionNodes the nodes to set - */ - public void setFunctions(final List<FunctionNode> functionNodes) { - assert parent != null : "Parent context missing."; - - parent.setFunctions(functionNodes); - } - - /** * Assist in IR navigation. * * @param visitor IR navigating visitor. @@ -258,13 +149,9 @@ public class Block extends Node { try { // Ignore parent to avoid recursion. - if (visitor.enter(this) != null) { - for (int i = 0, count = statements.size(); i < count; i++) { - final Node statement = statements.get(i); - statements.set(i, statement.accept(visitor)); - } - - return visitor.leave(this); + if (visitor.enterBlock(this) != null) { + visitStatements(visitor); + return visitor.leaveBlock(this); } } finally { visitor.setCurrentBlock(saveBlock); @@ -274,51 +161,21 @@ public class Block extends Node { } /** - * Search for symbol. - * - * @param name Symbol name. - * - * @return Found symbol or null if not found. + * Get an iterator for all the symbols defined in this block + * @return symbol iterator */ - public Symbol findSymbol(final String name) { - // Search up block chain to locate symbol. - - for (Block block = this; block != null; block = block.getParent()) { - // Find name. - final Symbol symbol = block.symbols.get(name); - // If found then we are good. - if (symbol != null) { - return symbol; - } - } - return null; + public Iterator<Symbol> symbolIterator() { + return symbols.values().iterator(); } /** - * Search for symbol in current function. - * - * @param name Symbol name. - * - * @return Found symbol or null if not found. + * Retrieves an existing symbol defined in the current block. + * @param name the name of the symbol + * @return an existing symbol with the specified name defined in the current block, or null if this block doesn't + * define a symbol with this name. */ - public Symbol findLocalSymbol(final String name) { - // Search up block chain to locate symbol. - for (Block block = this; block != null; block = block.getParent()) { - // Find name. - final Symbol symbol = block.symbols.get(name); - // If found then we are good. - if (symbol != null) { - return symbol; - } - - // If searched function then we are done. - if (block == block.function) { - break; - } - } - - // Not found. - return null; + public Symbol getExistingSymbol(final String name) { + return symbols.get(name); } /** @@ -331,122 +188,6 @@ public class Block extends Node { return statements.size() == 1 && statements.get(0) instanceof CatchNode; } - /** - * Test to see if a symbol is local to the function. - * - * @param symbol Symbol to test. - * @return True if a local symbol. - */ - public boolean isLocal(final Symbol symbol) { - // some temp symbols have no block, so can be assumed local - final Block block = symbol.getBlock(); - return block == null || block.getFunction() == function; - } - - /** - * Declare the definition of a new symbol. - * - * @param name Name of symbol. - * @param symbolFlags Symbol flags. - * @param node Defining Node. - * - * @return Symbol for given name or null for redefinition. - */ - public Symbol defineSymbol(final String name, final int symbolFlags, final Node node) { - int flags = symbolFlags; - Symbol symbol = findSymbol(name); // Locate symbol. - - if ((flags & KINDMASK) == IS_GLOBAL) { - flags |= IS_SCOPE; - } - - if (symbol != null) { - // Symbol was already defined. Check if it needs to be redefined. - if ((flags & KINDMASK) == IS_PARAM) { - if (!function.isLocal(symbol)) { - // Not defined in this function. Create a new definition. - symbol = null; - } else if (symbol.isParam()) { - // Duplicate parameter. Null return will force an error. - assert false : "duplicate parameter"; - return null; - } - } else if ((flags & KINDMASK) == IS_VAR) { - if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & Symbol.IS_LET) == Symbol.IS_LET) { - assert !((flags & IS_LET) == IS_LET && symbol.getBlock() == this) : "duplicate let variable in block"; - // Always create a new definition. - symbol = null; - } else { - // Not defined in this function. Create a new definition. - if (!function.isLocal(symbol) || symbol.less(IS_VAR)) { - symbol = null; - } - } - } - } - - if (symbol == null) { - // If not found, then create a new one. - Block symbolBlock; - - // Determine where to create it. - if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { - symbolBlock = this; - } else { - symbolBlock = getFunction(); - } - - // Create and add to appropriate block. - symbol = new Symbol(name, flags, node, symbolBlock); - symbolBlock.putSymbol(name, symbol); - - if ((flags & Symbol.KINDMASK) != IS_GLOBAL) { - symbolBlock.getFrame().addSymbol(symbol); - symbol.setNeedsSlot(true); - } - } else if (symbol.less(flags)) { - symbol.setFlags(flags); - } - - if (node != null) { - node.setSymbol(symbol); - } - - return symbol; - } - - /** - * Declare the use of a symbol. - * - * @param name Name of symbol. - * @param node Using node - * - * @return Symbol for given name. - */ - public Symbol useSymbol(final String name, final Node node) { - Symbol symbol = findSymbol(name); - - if (symbol == null) { - // If not found, declare as a free var. - symbol = defineSymbol(name, IS_GLOBAL, node); - } else { - node.setSymbol(symbol); - } - - return symbol; - } - - /** - * Add parent name to the builder. - * - * @param sb String bulder. - */ - public void addParentName(final StringBuilder sb) { - if (parent != null) { - parent.addParentName(sb); - } - } - @Override public void toString(final StringBuilder sb) { for (final Node statement : statements) { @@ -505,16 +246,6 @@ public class Block extends Node { } /** - * Get the FunctionNode for this block, i.e. the function it - * belongs to - * - * @return the function node - */ - public FunctionNode getFunction() { - return function; - } - - /** * Reset the frame for this block * * @param frame the new frame @@ -524,24 +255,6 @@ public class Block extends Node { } /** - * Get the parent block - * - * @return parent block, or null if none exists - */ - public Block getParent() { - return parent; - } - - /** - * Set the parent block - * - * @param parent the new parent block - */ - public void setParent(final Block parent) { - this.parent = parent; - } - - /** * Get the list of statements in this block * * @return a list of statements @@ -551,6 +264,15 @@ public class Block extends Node { } /** + * Applies the specified visitor to all statements in the block. + * @param visitor the visitor. + */ + public void visitStatements(NodeVisitor visitor) { + for (ListIterator<Node> stmts = statements.listIterator(); stmts.hasNext();) { + stmts.set(stmts.next().accept(visitor)); + } + } + /** * Reset the statement list for this block * * @param statements new statement list @@ -585,4 +307,29 @@ public class Block extends Node { needsScope = true; } + /** + * Marks this block as using a specified scoped symbol. The block and its parent blocks up to but not + * including the block defining the symbol will be marked as needing parent scope. The block defining the symbol + * will be marked as one that needs to have its own scope. + * @param symbol the symbol being used. + * @param ancestors the iterator over block's containing lexical context + */ + public void setUsesScopeSymbol(final Symbol symbol, Iterator<Block> ancestors) { + if(symbol.getBlock() == this) { + setNeedsScope(); + } else { + setUsesParentScopeSymbol(symbol, ancestors); + } + } + + /** + * Invoked when this block uses a scope symbol defined in one of its ancestors. + * @param symbol the scope symbol being used + * @param ancestors iterator over ancestor blocks + */ + void setUsesParentScopeSymbol(final Symbol symbol, Iterator<Block> ancestors) { + if(ancestors.hasNext()) { + ancestors.next().setUsesScopeSymbol(symbol, ancestors); + } + } } |