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