diff options
Diffstat (limited to 'src/jdk/nashorn/internal/ir/Block.java')
-rw-r--r-- | src/jdk/nashorn/internal/ir/Block.java | 126 |
1 files changed, 83 insertions, 43 deletions
diff --git a/src/jdk/nashorn/internal/ir/Block.java b/src/jdk/nashorn/internal/ir/Block.java index f262d8d1..12e4fcd8 100644 --- a/src/jdk/nashorn/internal/ir/Block.java +++ b/src/jdk/nashorn/internal/ir/Block.java @@ -33,19 +33,17 @@ import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; - import jdk.nashorn.internal.codegen.Label; -import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; import jdk.nashorn.internal.ir.visitor.NodeVisitor; -import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN; - /** * IR representation for a list of statements. */ @Immutable -public class Block extends Node implements BreakableNode, Flags<Block> { +public class Block extends Node implements BreakableNode, Terminal, Flags<Block> { + private static final long serialVersionUID = 1L; + /** List of statements */ protected final List<Statement> statements; @@ -53,7 +51,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> { protected final Map<String, Symbol> symbols; /** Entry label. */ - protected final Label entryLabel; + private final Label entryLabel; /** Break label. */ private final Label breakLabel; @@ -61,17 +59,13 @@ public class Block extends Node implements BreakableNode, Flags<Block> { /** Does the block/function need a new scope? */ protected final int flags; - /** Flag indicating that this block needs scope */ - public static final int NEEDS_SCOPE = 1 << 0; - /** - * Flag indicating whether this block needs - * self symbol assignment at the start. This is used only for - * blocks that are the bodies of function nodes who refer to themselves - * by name. It causes codegen to insert a var [fn_name] = __callee__ - * at the start of the body + * @see JoinPredecessor */ - public static final int NEEDS_SELF_SYMBOL = 1 << 1; + private final LocalVariableConversion conversion; + + /** Flag indicating that this block needs scope */ + public static final int NEEDS_SCOPE = 1 << 0; /** * Is this block tagged as terminal based on its contents @@ -80,6 +74,12 @@ public class Block extends Node implements BreakableNode, Flags<Block> { public static final int IS_TERMINAL = 1 << 2; /** + * Is this block the eager global scope - i.e. the original program. This isn't true for the + * outermost level of recompiles + */ + public static final int IS_GLOBAL_SCOPE = 1 << 3; + + /** * Constructor * * @param token token @@ -94,7 +94,8 @@ public class Block extends Node implements BreakableNode, Flags<Block> { this.entryLabel = new Label("block_entry"); this.breakLabel = new Label("block_break"); final int len = statements.length; - this.flags = (len > 0 && statements[len - 1].hasTerminalFlags()) ? IS_TERMINAL : 0; + this.flags = len > 0 && statements[len - 1].hasTerminalFlags() ? IS_TERMINAL : 0; + this.conversion = null; } /** @@ -108,7 +109,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> { this(token, finish, statements.toArray(new Statement[statements.size()])); } - private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols) { + private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols, final LocalVariableConversion conversion) { super(block); this.statements = statements; this.flags = flags; @@ -116,11 +117,21 @@ public class Block extends Node implements BreakableNode, Flags<Block> { this.entryLabel = new Label(block.entryLabel); this.breakLabel = new Label(block.breakLabel); this.finish = finish; + this.conversion = conversion; + } + + /** + * Is this block the outermost eager global scope - i.e. the primordial program? + * Used for global anchor point for scope depth computation for recompilation code + * @return true if outermost eager global scope + */ + public boolean isGlobalScope() { + return getFlag(IS_GLOBAL_SCOPE); } /** - * Clear the symbols in a block - * TODO: make this immutable + * Clear the symbols in the block. + * TODO: make this immutable. */ public void clearSymbols() { symbols.clear(); @@ -128,7 +139,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> { @Override public Node ensureUniqueLabels(final LexicalContext lc) { - return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols)); + return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion)); } /** @@ -140,14 +151,14 @@ public class Block extends Node implements BreakableNode, Flags<Block> { @Override 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))); + return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, statements))); } return this; } /** - * Get an iterator for all the symbols defined in this block + * Get a copy of the list for all the symbols defined in this block * @return symbol iterator */ public List<Symbol> getSymbols() { @@ -175,9 +186,9 @@ public class Block extends Node implements BreakableNode, Flags<Block> { } @Override - public void toString(final StringBuilder sb) { + public void toString(final StringBuilder sb, final boolean printType) { for (final Node statement : statements) { - statement.toString(sb); + statement.toString(sb, printType); sb.append(';'); } } @@ -217,19 +228,16 @@ public class Block extends Node implements BreakableNode, Flags<Block> { return isTerminal ? setFlag(lc, IS_TERMINAL) : clearFlag(lc, IS_TERMINAL); } - /** - * Set the type of the return symbol in this block if present. - * @param returnType the new type - * @return this block - */ - public Block setReturnType(final Type returnType) { - final Symbol symbol = getExistingSymbol(RETURN.symbolName()); - if (symbol != null) { - symbol.setTypeOverride(returnType); - } - return this; + @Override + public int getFlags() { + return flags; } + /** + * Is this a terminal block, i.e. does it end control flow like ending with a throw or return? + * + * @return true if this node statement is terminal + */ @Override public boolean isTerminal() { return getFlag(IS_TERMINAL); @@ -248,6 +256,19 @@ public class Block extends Node implements BreakableNode, Flags<Block> { return breakLabel; } + @Override + public Block setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) { + if(this.conversion == conversion) { + return this; + } + return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion)); + } + + @Override + public LocalVariableConversion getLocalVariableConversion() { + return conversion; + } + /** * Get the list of statements in this block * @@ -258,6 +279,25 @@ public class Block extends Node implements BreakableNode, Flags<Block> { } /** + * Returns the number of statements in the block. + * @return the number of statements in the block. + */ + public int getStatementCount() { + return statements.size(); + } + + /** + * Returns the line number of the first statement in the block. + * @return the line number of the first statement in the block, or -1 if the block has no statements. + */ + public int getFirstStatementLineNumber() { + if(statements == null || statements.isEmpty()) { + return -1; + } + return statements.get(0).getLineNumber(); + } + + /** * Reset the statement list for this block * * @param lc lexical context @@ -272,7 +312,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> { if (!statements.isEmpty()) { lastFinish = statements.get(statements.size() - 1).getFinish(); } - return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols)); + return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols, conversion)); } /** @@ -295,20 +335,20 @@ public class Block extends Node implements BreakableNode, Flags<Block> { } @Override - public Block setFlags(final LexicalContext lc, int flags) { + public Block setFlags(final LexicalContext lc, final int flags) { if (this.flags == flags) { return this; } - return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols)); + return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion)); } @Override - public Block clearFlag(final LexicalContext lc, int flag) { + public Block clearFlag(final LexicalContext lc, final int flag) { return setFlags(lc, flags & ~flag); } @Override - public Block setFlag(final LexicalContext lc, int flag) { + public Block setFlag(final LexicalContext lc, final int flag) { return setFlags(lc, flags | flag); } @@ -327,7 +367,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> { return this; } - return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags | NEEDS_SCOPE, symbols)); + return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags | NEEDS_SCOPE, symbols, conversion)); } /** @@ -353,11 +393,11 @@ public class Block extends Node implements BreakableNode, Flags<Block> { @Override public List<Label> getLabels() { - return Collections.singletonList(breakLabel); + return Collections.unmodifiableList(Arrays.asList(entryLabel, breakLabel)); } @Override - public Node accept(NodeVisitor<? extends LexicalContext> visitor) { + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { return Acceptor.accept(this, visitor); } } |