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