diff options
Diffstat (limited to 'src/jdk/nashorn/internal/ir/ForNode.java')
-rw-r--r-- | src/jdk/nashorn/internal/ir/ForNode.java | 103 |
1 files changed, 60 insertions, 43 deletions
diff --git a/src/jdk/nashorn/internal/ir/ForNode.java b/src/jdk/nashorn/internal/ir/ForNode.java index 8130e23b..ef6f11db 100644 --- a/src/jdk/nashorn/internal/ir/ForNode.java +++ b/src/jdk/nashorn/internal/ir/ForNode.java @@ -33,23 +33,26 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor; */ @Immutable public final class ForNode extends LoopNode { - /** Initialize expression. */ + private static final long serialVersionUID = 1L; + + /** Initialize expression for an ordinary for statement, or the LHS expression receiving iterated-over values in a + * for-in statement. */ private final Expression init; - /** Test expression. */ - private final Expression modify; + /** Modify expression for an ordinary statement, or the source of the iterator in the for-in statement. */ + private final JoinPredecessorExpression modify; /** Iterator symbol. */ private Symbol iterator; - /** Is this a normal for loop? */ - public static final int IS_FOR = 1 << 0; - /** Is this a normal for in loop? */ - public static final int IS_FOR_IN = 1 << 1; + public static final int IS_FOR_IN = 1 << 0; /** Is this a normal for each in loop? */ - public static final int IS_FOR_EACH = 1 << 2; + public static final int IS_FOR_EACH = 1 << 1; + + /** Does this loop need a per-iteration scope because its init contain a LET declaration? */ + public static final int PER_ITERATION_SCOPE = 1 << 2; private final int flags; @@ -59,30 +62,30 @@ public final class ForNode extends LoopNode { * @param lineNumber line number * @param token token * @param finish finish - * @param init initialization expression - * @param test test * @param body body - * @param modify modify * @param flags flags */ - public ForNode(final int lineNumber, final long token, final int finish, final Expression init, final Expression test, final Block body, final Expression modify, final int flags) { - super(lineNumber, token, finish, test, body, false); - this.init = init; - this.modify = modify; + public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags) { + super(lineNumber, token, finish, body, false); this.flags = flags; + this.init = null; + this.modify = null; } - private ForNode(final ForNode forNode, final Expression init, final Expression test, final Block body, final Expression modify, final int flags, final boolean controlFlowEscapes) { - super(forNode, test, body, controlFlowEscapes); + private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test, + final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, final LocalVariableConversion conversion) { + super(forNode, test, body, controlFlowEscapes, conversion); this.init = init; this.modify = modify; this.flags = flags; - this.iterator = forNode.iterator; //TODO is this acceptable? symbols are never cloned, just copied as references + // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally + // is executed. + this.iterator = forNode.iterator; } @Override - public Node ensureUniqueLabels(LexicalContext lc) { - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes)); + public Node ensureUniqueLabels(final LexicalContext lc) { + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); } @Override @@ -90,8 +93,8 @@ public final class ForNode extends LoopNode { if (visitor.enterForNode(this)) { return visitor.leaveForNode( setInit(lc, init == null ? null : (Expression)init.accept(visitor)). - setTest(lc, test == null ? null : (Expression)test.accept(visitor)). - setModify(lc, modify == null ? null : (Expression)modify.accept(visitor)). + setTest(lc, test == null ? null : (JoinPredecessorExpression)test.accept(visitor)). + setModify(lc, modify == null ? null : (JoinPredecessorExpression)modify.accept(visitor)). setBody(lc, (Block)body.accept(visitor))); } @@ -99,24 +102,25 @@ public final class ForNode extends LoopNode { } @Override - public void toString(final StringBuilder sb) { - sb.append("for ("); + public void toString(final StringBuilder sb, final boolean printTypes) { + sb.append("for"); + LocalVariableConversion.toString(conversion, sb).append(' '); if (isForIn()) { - init.toString(sb); + init.toString(sb, printTypes); sb.append(" in "); - modify.toString(sb); + modify.toString(sb, printTypes); } else { if (init != null) { - init.toString(sb); + init.toString(sb, printTypes); } sb.append("; "); if (test != null) { - test.toString(sb); + test.toString(sb, printTypes); } sb.append("; "); if (modify != null) { - modify.toString(sb); + modify.toString(sb, printTypes); } } @@ -154,7 +158,7 @@ public final class ForNode extends LoopNode { if (this.init == init) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); } /** @@ -212,7 +216,7 @@ public final class ForNode extends LoopNode { * Get the modification expression for this ForNode * @return the modification expression */ - public Expression getModify() { + public JoinPredecessorExpression getModify() { return modify; } @@ -222,24 +226,19 @@ public final class ForNode extends LoopNode { * @param modify new modification expression * @return new for node if changed or existing if not */ - public ForNode setModify(final LexicalContext lc, final Expression modify) { + public ForNode setModify(final LexicalContext lc, final JoinPredecessorExpression modify) { if (this.modify == modify) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); } @Override - public Expression getTest() { - return test; - } - - @Override - public ForNode setTest(final LexicalContext lc, final Expression test) { + public ForNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) { if (this.test == test) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); } @Override @@ -252,7 +251,7 @@ public final class ForNode extends LoopNode { if (this.body == body) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); } @Override @@ -260,14 +259,32 @@ public final class ForNode extends LoopNode { if (this.controlFlowEscapes == controlFlowEscapes) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); } private ForNode setFlags(final LexicalContext lc, final int flags) { if (this.flags == flags) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + } + + @Override + JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) { + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + } + + @Override + public boolean hasPerIterationScope() { + return (flags & PER_ITERATION_SCOPE) != 0; } + /** + * Set the per-iteration-scope flag on this node. + * @param lc lexical context + * @return the node with flag set + */ + public ForNode setPerIterationScope(final LexicalContext lc) { + return setFlags(lc, flags | PER_ITERATION_SCOPE); + } } |