Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 1585503002: dart2js: CPS translation of switches with continue to their labels. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index 9777a243b92204a0657e1e6bc27c671829134800..4974de815f4dbd02632ef49f88de9fff71559418 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -166,6 +166,11 @@ abstract class JumpCollector {
JumpCollector.retrn(this._continuation)
: _continuationEnvironment = null, target = null;
+ /// Construct a collector for collecting goto jumps.
+ ///
+ /// There is no continuation or environment at the destination.
+ JumpCollector.goto(this.target) : _continuationEnvironment = null;
+
/// True if the collector has not recorded any jumps to its continuation.
bool get isEmpty;
@@ -421,6 +426,31 @@ class ReturnJumpCollector extends JumpCollector {
}
}
+/// Collect 'goto' jumps, continue to a labeled case from within a switch.
+///
+/// These jumps are unrestricted within the switch. They can be forward or
+/// backward. They are implemented by assigning to a state variable.
+class GotoJumpCollector extends JumpCollector {
+ bool isEmpty = true;
+ final ir.Continuation continuation = null;
+ final Environment environment = null;
+
+ int _stateVariableIndex;
+ int _stateValue;
+ JumpCollector _breakJoin;
+
+ GotoJumpCollector(JumpTarget target, this._stateVariableIndex,
+ this._stateValue, this._breakJoin) : super.goto(target);
+
+ void addJump(IrBuilder builder,
+ [ir.Primitive value, SourceInformation sourceInformation]) {
+ isEmpty = false;
+ ir.Primitive constant = builder.buildIntegerConstant(_stateValue);
+ builder.environment.index2value[_stateVariableIndex] = constant;
+ builder.jumpTo(_breakJoin);
+ }
+}
+
/// Function for building a node in the context of the current builder.
typedef ir.Node BuildFunction(node);
@@ -532,7 +562,7 @@ class ThisParameterLocal implements Local {
///
/// The IR fragment is an expression with a hole in it. The hole represents
/// the focus where new expressions can be added. The fragment is implemented
-/// by [_root] which is the root of the expression and [_current] which is the
+/// by [root] which is the root of the expression and [_current] which is the
/// expression that immediately contains the hole. Not all expressions have a
/// hole (e.g., invocations, which always occur in tail position, do not have a
/// hole). Expressions with a hole have a plug method.
@@ -559,7 +589,7 @@ class IrBuilder {
/// side effects.
Map<Local, ir.MutableVariable> mutableVariables;
- ir.Expression _root = null;
+ ir.Expression root = null;
ir.Expression _current = null;
GlobalProgramInformation get program => state.program;
@@ -613,7 +643,7 @@ class IrBuilder {
return mutableVariables[local];
}
- bool get isOpen => _root == null || _current != null;
+ bool get isOpen => root == null || _current != null;
List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
{ClosureScope closureScope,
@@ -640,8 +670,8 @@ class IrBuilder {
/// new value of current.
void add(ir.Expression expr) {
assert(isOpen);
- if (_root == null) {
- _root = _current = expr;
+ if (root == null) {
+ root = _current = expr;
} else {
_current = _current.plug(expr);
}
@@ -789,8 +819,8 @@ class IrBuilder {
// if condition (then, else)
ir.Continuation thenContinuation = new ir.Continuation([]);
ir.Continuation elseContinuation = new ir.Continuation([]);
- thenContinuation.body = thenBuilder._root;
- elseContinuation.body = elseBuilder._root;
+ thenContinuation.body = thenBuilder.root;
+ elseContinuation.body = elseBuilder.root;
add(new ir.LetCont(join.continuation,
new ir.LetCont.two(thenContinuation, elseContinuation,
new ir.Branch.strict(condition,
@@ -812,7 +842,7 @@ class IrBuilder {
_current = null;
}
- /// Create a [ir.FunctionDefinition] using [_root] as the body.
+ /// Create a [ir.FunctionDefinition] using [root] as the body.
///
/// The protocol for building a function is:
/// 1. Call [buildFunctionHeader].
@@ -825,7 +855,7 @@ class IrBuilder {
state.thisParameter,
state.functionParameters,
state.returnContinuation,
- _root);
+ root);
}
/// Create a invocation of the [method] on the super class where the call
@@ -1107,17 +1137,17 @@ class IrBuilder {
// case that one of them is null, it must be the only one that is open
// and thus contains the new hole in the context. This case is handled
// after the branch is plugged into the current hole.
- thenContinuation.body = thenBuilder._root;
- elseContinuation.body = elseBuilder._root;
+ thenContinuation.body = thenBuilder.root;
+ elseContinuation.body = elseBuilder.root;
add(result);
if (join == null) {
// At least one subexpression is closed.
if (thenBuilder.isOpen) {
- if (thenBuilder._root != null) _current = thenBuilder._current;
+ if (thenBuilder.root != null) _current = thenBuilder._current;
environment = thenBuilder.environment;
} else if (elseBuilder.isOpen) {
- if (elseBuilder._root != null) _current = elseBuilder._current;
+ if (elseBuilder.root != null) _current = elseBuilder._current;
environment = elseBuilder.environment;
} else {
_current = null;
@@ -1243,16 +1273,16 @@ class IrBuilder {
// it is guaranteed that the updateBuilder has a non-empty term.
if (hasContinues) {
outerBodyBuilder.add(new ir.LetCont(continueCollector.continuation,
- innerBodyBuilder._root));
- continueCollector.continuation.body = updateBuilder._root;
+ innerBodyBuilder.root));
+ continueCollector.continuation.body = updateBuilder.root;
} else {
- outerBodyBuilder.add(innerBodyBuilder._root);
+ outerBodyBuilder.add(innerBodyBuilder.root);
}
// Create loop exit and body entry continuations and a branch to them.
ir.Continuation exitContinuation = new ir.Continuation([]);
ir.Continuation bodyContinuation = new ir.Continuation([]);
- bodyContinuation.body = outerBodyBuilder._root;
+ bodyContinuation.body = outerBodyBuilder.root;
// Note the order of continuations: the first one is the one that will
// be filled by LetCont.plug.
ir.LetCont branch =
@@ -1268,7 +1298,7 @@ class IrBuilder {
if (hasBreaks) {
IrBuilder exitBuilder = makeDelimitedBuilder();
exitBuilder.jumpTo(breakCollector);
- exitContinuation.body = exitBuilder._root;
+ exitContinuation.body = exitBuilder.root;
letBreak = new ir.LetCont(breakCollector.continuation, branch);
add(letBreak);
environment = breakCollector.environment;
@@ -1411,7 +1441,7 @@ class IrBuilder {
// in branch condition (body, exit)
ir.Continuation exitContinuation = new ir.Continuation([]);
ir.Continuation bodyContinuation = new ir.Continuation([]);
- bodyContinuation.body = bodyBuilder._root;
+ bodyContinuation.body = bodyBuilder.root;
// Note the order of continuations: the first one is the one that will
// be filled by LetCont.plug.
ir.LetCont branch =
@@ -1427,7 +1457,7 @@ class IrBuilder {
if (hasBreaks) {
IrBuilder exitBuilder = makeDelimitedBuilder();
exitBuilder.jumpTo(breakCollector);
- exitContinuation.body = exitBuilder._root;
+ exitContinuation.body = exitBuilder.root;
letBreak = new ir.LetCont(breakCollector.continuation, branch);
add(letBreak);
environment = breakCollector.environment;
@@ -1486,7 +1516,7 @@ class IrBuilder {
// Create body entry and loop exit continuations and a branch to them.
ir.Continuation exitContinuation = new ir.Continuation([]);
ir.Continuation bodyContinuation = new ir.Continuation([]);
- bodyContinuation.body = bodyBuilder._root;
+ bodyContinuation.body = bodyBuilder.root;
// Note the order of continuations: the first one is the one that will
// be filled by LetCont.plug.
ir.LetCont branch =
@@ -1502,7 +1532,7 @@ class IrBuilder {
if (hasBreaks) {
IrBuilder exitBuilder = makeDelimitedBuilder();
exitBuilder.jumpTo(breakCollector);
- exitContinuation.body = exitBuilder._root;
+ exitContinuation.body = exitBuilder.root;
letBreak = new ir.LetCont(breakCollector.continuation, branch);
add(letBreak);
environment = breakCollector.environment;
@@ -1569,18 +1599,18 @@ class IrBuilder {
ir.Continuation exitContinuation = new ir.Continuation([]);
IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder();
exitBuilder.jumpTo(breakCollector);
- exitContinuation.body = exitBuilder._root;
+ exitContinuation.body = exitBuilder.root;
ir.Continuation repeatContinuation = new ir.Continuation([]);
IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder();
repeatBuilder.jumpTo(loop);
- repeatContinuation.body = repeatBuilder._root;
+ repeatContinuation.body = repeatBuilder.root;
continueBuilder.add(
new ir.LetCont.two(exitContinuation, repeatContinuation,
new ir.Branch.strict(condition,
repeatContinuation,
exitContinuation)));
- continueCollector.continuation.body = continueBuilder._root;
+ continueCollector.continuation.body = continueBuilder.root;
// Construct the loop continuation (i.e., the body and condition).
// <Loop> =
@@ -1589,56 +1619,25 @@ class IrBuilder {
// in [[body]]; continue(v, ...)
loopBuilder.add(
new ir.LetCont(continueCollector.continuation,
- bodyBuilder._root));
+ bodyBuilder.root));
// And tie it all together.
- add(new ir.LetCont(breakCollector.continuation, loopBuilder._root));
+ add(new ir.LetCont(breakCollector.continuation, loopBuilder.root));
environment = breakCollector.environment;
}
- void buildSimpleSwitch(JumpTarget target,
- ir.Primitive value,
+ void buildSimpleSwitch(JumpCollector join,
List<SwitchCaseInfo> cases,
- SwitchCaseInfo defaultCase,
- Element error,
- SourceInformation sourceInformation) {
- assert(isOpen);
- JumpCollector join = new ForwardJumpCollector(environment, target: target);
-
+ SubbuildFunction buildDefaultBody) {
IrBuilder casesBuilder = makeDelimitedBuilder();
- casesBuilder.state.breakCollectors.add(join);
for (SwitchCaseInfo caseInfo in cases) {
- buildConditionsFrom(int index) => (IrBuilder builder) {
- ir.Primitive comparison = builder.buildIdentical(
- value, caseInfo.constants[index]);
- return (index == caseInfo.constants.length - 1)
- ? comparison
- : builder.buildLogicalOperator(
- comparison, buildConditionsFrom(index + 1), isLazyOr: true);
- };
-
- ir.Primitive condition = buildConditionsFrom(0)(casesBuilder);
+ ir.Primitive condition = caseInfo.buildCondition(casesBuilder);
IrBuilder thenBuilder = makeDelimitedBuilder();
caseInfo.buildBody(thenBuilder);
- if (thenBuilder.isOpen) {
- // It is a runtime error to reach the end of a switch case, unless
- // it is the last case.
- if (caseInfo == cases.last && defaultCase == null) {
- thenBuilder.jumpTo(join);
- } else {
- ir.Primitive exception = thenBuilder.buildInvokeStatic(
- error,
- new Selector.fromElement(error),
- <ir.Primitive>[],
- sourceInformation);
- thenBuilder.buildThrow(exception);
- }
- }
-
ir.Continuation thenContinuation = new ir.Continuation([]);
- thenContinuation.body = thenBuilder._root;
+ thenContinuation.body = thenBuilder.root;
ir.Continuation elseContinuation = new ir.Continuation([]);
- // A LetCont.many term has a hole as the body of the first listed
+ // A LetCont.two term has a hole as the body of the first listed
// continuation, to be plugged by the translation. Therefore put the
// else continuation first.
casesBuilder.add(
@@ -1648,18 +1647,17 @@ class IrBuilder {
elseContinuation)));
}
- if (defaultCase != null) {
- defaultCase.buildBody(casesBuilder);
+ if (buildDefaultBody == null) {
+ casesBuilder.jumpTo(join);
+ } else {
+ buildDefaultBody(casesBuilder);
}
- if (casesBuilder.isOpen) casesBuilder.jumpTo(join);
-
- casesBuilder.state.breakCollectors.removeLast();
if (!join.isEmpty) {
- add(new ir.LetCont(join.continuation, casesBuilder._root));
+ add(new ir.LetCont(join.continuation, casesBuilder.root));
environment = join.environment;
- } else if (casesBuilder._root != null) {
- add(casesBuilder._root);
+ } else if (casesBuilder.root != null) {
+ add(casesBuilder.root);
_current = casesBuilder._current;
environment = casesBuilder.environment;
} else {
@@ -1721,11 +1719,11 @@ class IrBuilder {
List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join);
ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
- catchContinuation.body = catchBuilder._root;
+ catchContinuation.body = catchBuilder.root;
tryCatchBuilder.add(
- new ir.LetHandler(catchContinuation, tryBuilder._root));
+ new ir.LetHandler(catchContinuation, tryBuilder.root));
- leaveTryCatch(this, join, tryCatchBuilder._root);
+ leaveTryCatch(this, join, tryCatchBuilder.root);
}
/// Translates a try/catch.
@@ -1829,7 +1827,7 @@ class IrBuilder {
}
clause.buildCatchBlock(clauseBuilder);
if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
- return clauseBuilder._root;
+ return clauseBuilder.root;
}
// Expand multiple catch clauses into an explicit if/then/else. Iterate
@@ -1855,7 +1853,7 @@ class IrBuilder {
new ir.Branch.strict(typeMatches,
thenContinuation,
elseContinuation)));
- catchBody = checkBuilder._root;
+ catchBody = checkBuilder.root;
}
builder.add(catchBody);
@@ -1960,7 +1958,7 @@ class IrBuilder {
IrBuilder builder = makeDelimitedBuilder(newCollector.environment);
buildFinallyBlock(builder);
if (builder.isOpen) builder.jumpTo(originalCollector);
- newCollector.continuation.body = builder._root;
+ newCollector.continuation.body = builder.root;
exits.add(newCollector.continuation);
}
for (int i = 0; i < newBreaks.length; ++i) {
@@ -1974,7 +1972,7 @@ class IrBuilder {
ir.Primitive value = builder.environment.discard(1);
buildFinallyBlock(builder);
if (builder.isOpen) builder.buildReturn(value: value);
- newReturn.continuation.body = builder._root;
+ newReturn.continuation.body = builder.root;
exits.add(newReturn.continuation);
}
builder.add(new ir.LetCont.many(exits, body));
@@ -2101,10 +2099,10 @@ class IrBuilder {
bool hasBreaks = !join.isEmpty;
if (hasBreaks) {
if (innerBuilder.isOpen) innerBuilder.jumpTo(join);
- add(new ir.LetCont(join.continuation, innerBuilder._root));
+ add(new ir.LetCont(join.continuation, innerBuilder.root));
environment = join.environment;
- } else if (innerBuilder._root != null) {
- add(innerBuilder._root);
+ } else if (innerBuilder.root != null) {
+ add(innerBuilder.root);
_current = innerBuilder._current;
environment = innerBuilder.environment;
} else {
@@ -2240,8 +2238,8 @@ class IrBuilder {
ir.Continuation leftFalseContinuation = new ir.Continuation([]);
ir.Continuation rightTrueContinuation = new ir.Continuation([]);
ir.Continuation rightFalseContinuation = new ir.Continuation([]);
- rightTrueContinuation.body = rightTrueBuilder._root;
- rightFalseContinuation.body = rightFalseBuilder._root;
+ rightTrueContinuation.body = rightTrueBuilder.root;
+ rightFalseContinuation.body = rightFalseBuilder.root;
// The right subexpression has two continuations.
rightBuilder.add(
new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation,
@@ -2252,11 +2250,11 @@ class IrBuilder {
// either the right subexpression or an invocation of the join-point
// continuation.
if (isLazyOr) {
- leftTrueContinuation.body = emptyBuilder._root;
- leftFalseContinuation.body = rightBuilder._root;
+ leftTrueContinuation.body = emptyBuilder.root;
+ leftFalseContinuation.body = rightBuilder.root;
} else {
- leftTrueContinuation.body = rightBuilder._root;
- leftFalseContinuation.body = emptyBuilder._root;
+ leftTrueContinuation.body = rightBuilder.root;
+ leftFalseContinuation.body = emptyBuilder.root;
}
add(new ir.LetCont(join.continuation,
@@ -2838,10 +2836,8 @@ class CatchClauseInfo {
}
class SwitchCaseInfo {
- final List<ir.Primitive> constants = <ir.Primitive>[];
+ final SubbuildFunction buildCondition;
final SubbuildFunction buildBody;
- SwitchCaseInfo(this.buildBody);
-
- void addConstant(ir.Primitive constant) => constants.add(constant);
+ SwitchCaseInfo(this.buildCondition, this.buildBody);
}
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698