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

Unified Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 2360673003: kernel->ssa: Implement for-loops and while-loops (Closed)
Patch Set: Created 4 years, 3 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 | « pkg/compiler/lib/src/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/builder.dart
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index bf008a2c8506abdd389af5c5a701b6c0c935968e..91266f3a12d44855e451896e058146a215e10708 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -40,7 +40,9 @@ import '../util/util.dart';
import '../world.dart' show ClassWorld;
import 'graph_builder.dart';
+import 'jump_handler.dart';
import 'locals_handler.dart';
+import 'loop_handler.dart';
import 'nodes.dart';
import 'optimize.dart';
import 'ssa_branch_builder.dart';
@@ -125,226 +127,6 @@ class SsaBuilderTask extends CompilerTask {
}
}
-// Represents a single break/continue instruction.
-class JumpHandlerEntry {
- final HJump jumpInstruction;
- final LocalsHandler locals;
- bool isBreak() => jumpInstruction is HBreak;
- bool isContinue() => jumpInstruction is HContinue;
- JumpHandlerEntry(this.jumpInstruction, this.locals);
-}
-
-abstract class JumpHandler {
- factory JumpHandler(SsaBuilder builder, JumpTarget target) {
- return new TargetJumpHandler(builder, target);
- }
- void generateBreak([LabelDefinition label]);
- void generateContinue([LabelDefinition label]);
- void forEachBreak(void action(HBreak instruction, LocalsHandler locals));
- void forEachContinue(
- void action(HContinue instruction, LocalsHandler locals));
- bool hasAnyContinue();
- bool hasAnyBreak();
- void close();
- final JumpTarget target;
- List<LabelDefinition> labels();
-}
-
-// Insert break handler used to avoid null checks when a target isn't
-// used as the target of a break, and therefore doesn't need a break
-// handler associated with it.
-class NullJumpHandler implements JumpHandler {
- final DiagnosticReporter reporter;
-
- NullJumpHandler(this.reporter);
-
- void generateBreak([LabelDefinition label]) {
- reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
- 'NullJumpHandler.generateBreak should not be called.');
- }
-
- void generateContinue([LabelDefinition label]) {
- reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
- 'NullJumpHandler.generateContinue should not be called.');
- }
-
- void forEachBreak(Function ignored) {}
- void forEachContinue(Function ignored) {}
- void close() {}
- bool hasAnyContinue() => false;
- bool hasAnyBreak() => false;
-
- List<LabelDefinition> labels() => const <LabelDefinition>[];
- JumpTarget get target => null;
-}
-
-// Records breaks until a target block is available.
-// Breaks are always forward jumps.
-// Continues in loops are implemented as breaks of the body.
-// Continues in switches is currently not handled.
-class TargetJumpHandler implements JumpHandler {
- final SsaBuilder builder;
- final JumpTarget target;
- final List<JumpHandlerEntry> jumps;
-
- TargetJumpHandler(SsaBuilder builder, this.target)
- : this.builder = builder,
- jumps = <JumpHandlerEntry>[] {
- assert(builder.jumpTargets[target] == null);
- builder.jumpTargets[target] = this;
- }
-
- void generateBreak([LabelDefinition label]) {
- HInstruction breakInstruction;
- if (label == null) {
- breakInstruction = new HBreak(target);
- } else {
- breakInstruction = new HBreak.toLabel(label);
- }
- LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
- builder.close(breakInstruction);
- jumps.add(new JumpHandlerEntry(breakInstruction, locals));
- }
-
- void generateContinue([LabelDefinition label]) {
- HInstruction continueInstruction;
- if (label == null) {
- continueInstruction = new HContinue(target);
- } else {
- continueInstruction = new HContinue.toLabel(label);
- // Switch case continue statements must be handled by the
- // [SwitchCaseJumpHandler].
- assert(label.target.statement is! ast.SwitchCase);
- }
- LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
- builder.close(continueInstruction);
- jumps.add(new JumpHandlerEntry(continueInstruction, locals));
- }
-
- void forEachBreak(Function action) {
- for (JumpHandlerEntry entry in jumps) {
- if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
- }
- }
-
- void forEachContinue(Function action) {
- for (JumpHandlerEntry entry in jumps) {
- if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
- }
- }
-
- bool hasAnyContinue() {
- for (JumpHandlerEntry entry in jumps) {
- if (entry.isContinue()) return true;
- }
- return false;
- }
-
- bool hasAnyBreak() {
- for (JumpHandlerEntry entry in jumps) {
- if (entry.isBreak()) return true;
- }
- return false;
- }
-
- void close() {
- // The mapping from TargetElement to JumpHandler is no longer needed.
- builder.jumpTargets.remove(target);
- }
-
- List<LabelDefinition> labels() {
- List<LabelDefinition> result = null;
- for (LabelDefinition element in target.labels) {
- if (result == null) result = <LabelDefinition>[];
- result.add(element);
- }
- return (result == null) ? const <LabelDefinition>[] : result;
- }
-}
-
-/// Special [JumpHandler] implementation used to handle continue statements
-/// targeting switch cases.
-class SwitchCaseJumpHandler extends TargetJumpHandler {
- /// Map from switch case targets to indices used to encode the flow of the
- /// switch case loop.
- final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>();
-
- SwitchCaseJumpHandler(
- SsaBuilder builder, JumpTarget target, ast.SwitchStatement node)
- : super(builder, target) {
- // The switch case indices must match those computed in
- // [SsaFromAstMixin.buildSwitchCaseConstants].
- // Switch indices are 1-based so we can bypass the synthetic loop when no
- // cases match simply by branching on the index (which defaults to null).
- int switchIndex = 1;
- for (ast.SwitchCase switchCase in node.cases) {
- for (ast.Node labelOrCase in switchCase.labelsAndCases) {
- ast.Node label = labelOrCase.asLabel();
- if (label != null) {
- LabelDefinition labelElement =
- builder.elements.getLabelDefinition(label);
- if (labelElement != null && labelElement.isContinueTarget) {
- JumpTarget continueTarget = labelElement.target;
- targetIndexMap[continueTarget] = switchIndex;
- assert(builder.jumpTargets[continueTarget] == null);
- builder.jumpTargets[continueTarget] = this;
- }
- }
- }
- switchIndex++;
- }
- }
-
- void generateBreak([LabelDefinition label]) {
- if (label == null) {
- // Creates a special break instruction for the synthetic loop generated
- // for a switch statement with continue statements. See
- // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
-
- HInstruction breakInstruction =
- new HBreak(target, breakSwitchContinueLoop: true);
- LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
- builder.close(breakInstruction);
- jumps.add(new JumpHandlerEntry(breakInstruction, locals));
- } else {
- super.generateBreak(label);
- }
- }
-
- bool isContinueToSwitchCase(LabelDefinition label) {
- return label != null && targetIndexMap.containsKey(label.target);
- }
-
- void generateContinue([LabelDefinition label]) {
- if (isContinueToSwitchCase(label)) {
- // Creates the special instructions 'label = i; continue l;' used in
- // switch statements with continue statements. See
- // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
-
- assert(label != null);
- HInstruction value = builder.graph
- .addConstantInt(targetIndexMap[label.target], builder.compiler);
- builder.localsHandler.updateLocal(target, value);
-
- assert(label.target.labels.contains(label));
- HInstruction continueInstruction = new HContinue(target);
- LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
- builder.close(continueInstruction);
- jumps.add(new JumpHandlerEntry(continueInstruction, locals));
- } else {
- super.generateContinue(label);
- }
- }
-
- void close() {
- // The mapping from TargetElement to JumpHandler is no longer needed.
- for (JumpTarget target in targetIndexMap.keys) {
- builder.jumpTargets.remove(target);
- }
- super.close();
- }
-}
-
/**
* This class builds SSA nodes for functions represented in AST.
*/
@@ -376,7 +158,6 @@ class SsaBuilder extends ast.Visitor
// used only for codegen, but currently we want to experiment using it for
// code-analysis too.
final CodegenRegistry registry;
- final Compiler compiler;
final GlobalTypeInferenceResults inferenceResults;
final JavaScriptBackend backend;
final ConstantSystem constantSystem;
@@ -397,13 +178,6 @@ class SsaBuilder extends ast.Visitor
bool inExpressionOfThrow = false;
/**
- * The loop nesting is consulted when inlining a function invocation in
- * [tryInlineMethod]. The inlining heuristics take this information into
- * account.
- */
- int loopNesting = 0;
-
- /**
* This stack contains declaration elements of the functions being built
* or inlined by this builder.
*/
@@ -411,8 +185,6 @@ class SsaBuilder extends ast.Visitor
HInstruction rethrowableException;
- Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
-
/// Returns `true` if the current element is an `async` function.
bool get isBuildingAsyncFunction {
Element element = sourceElement;
@@ -420,6 +192,9 @@ class SsaBuilder extends ast.Visitor
element.asyncMarker == AsyncMarker.ASYNC);
}
+ /// Handles the building of loops.
+ LoopHandler<ast.Node> loopHandler;
+
// TODO(sigmund): make most args optional
SsaBuilder(
this.target,
@@ -428,13 +203,13 @@ class SsaBuilder extends ast.Visitor
JavaScriptBackend backend,
this.nativeEmitter,
SourceInformationStrategy sourceInformationFactory)
- : this.compiler = backend.compiler,
- this.infoReporter = backend.compiler.dumpInfoTask,
+ : this.infoReporter = backend.compiler.dumpInfoTask,
this.backend = backend,
this.constantSystem = backend.constantSystem,
this.rti = backend.rti,
this.inferenceResults = backend.compiler.globalInference.results {
assert(target.isImplementation);
+ compiler = backend.compiler;
graph.element = target;
sourceElementStack.add(target);
sourceInformationBuilder =
@@ -442,6 +217,7 @@ class SsaBuilder extends ast.Visitor
graph.sourceInformation =
sourceInformationBuilder.buildVariableDeclaration();
localsHandler = new LocalsHandler(this, target, null, compiler);
+ loopHandler = new SsaLoopHandler(this);
}
BackendHelpers get helpers => backend.helpers;
@@ -632,7 +408,7 @@ class SsaBuilder extends ast.Visitor
FunctionElement function = element;
ResolvedAst functionResolvedAst = function.resolvedAst;
- bool insideLoop = loopNesting > 0 || graph.calledInLoop;
+ bool insideLoop = loopDepth > 0 || graph.calledInLoop;
// Bail out early if the inlining decision is in the cache and we can't
// inline (no need to check the hard constraints).
@@ -1953,275 +1729,6 @@ class SsaBuilder extends ast.Visitor
}
}
- /**
- * Creates a new loop-header block. The previous [current] block
- * is closed with an [HGoto] and replaced by the newly created block.
- * Also notifies the locals handler that we're entering a loop.
- */
- JumpHandler beginLoopHeader(ast.Node node) {
- assert(!isAborted());
- HBasicBlock previousBlock = close(new HGoto());
-
- JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true);
- HBasicBlock loopEntry =
- graph.addNewLoopHeaderBlock(jumpHandler.target, jumpHandler.labels());
- previousBlock.addSuccessor(loopEntry);
- open(loopEntry);
-
- localsHandler.beginLoopHeader(loopEntry);
- return jumpHandler;
- }
-
- /**
- * Ends the loop:
- * - creates a new block and adds it as successor to the [branchExitBlock] and
- * any blocks that end in break.
- * - opens the new block (setting as [current]).
- * - notifies the locals handler that we're exiting a loop.
- * [savedLocals] are the locals from the end of the loop condition.
- * [branchExitBlock] is the exit (branching) block of the condition. Generally
- * this is not the top of the loop, since this would lead to critical edges.
- * It is null for degenerate do-while loops that have
- * no back edge because they abort (throw/return/break in the body and have
- * no continues).
- */
- void endLoop(HBasicBlock loopEntry, HBasicBlock branchExitBlock,
- JumpHandler jumpHandler, LocalsHandler savedLocals) {
- HBasicBlock loopExitBlock = addNewBlock();
-
- List<LocalsHandler> breakHandlers = <LocalsHandler>[];
- // Collect data for the successors and the phis at each break.
- jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
- breakInstruction.block.addSuccessor(loopExitBlock);
- breakHandlers.add(locals);
- });
-
- // The exit block is a successor of the loop condition if it is reached.
- // We don't add the successor in the case of a while/for loop that aborts
- // because the caller of endLoop will be wiring up a special empty else
- // block instead.
- if (branchExitBlock != null) {
- branchExitBlock.addSuccessor(loopExitBlock);
- }
- // Update the phis at the loop entry with the current values of locals.
- localsHandler.endLoop(loopEntry);
-
- // Start generating code for the exit block.
- open(loopExitBlock);
-
- // Create a new localsHandler for the loopExitBlock with the correct phis.
- if (!breakHandlers.isEmpty) {
- if (branchExitBlock != null) {
- // Add the values of the locals at the end of the condition block to
- // the phis. These are the values that flow to the exit if the
- // condition fails.
- breakHandlers.add(savedLocals);
- }
- localsHandler = savedLocals.mergeMultiple(breakHandlers, loopExitBlock);
- } else {
- localsHandler = savedLocals;
- }
- }
-
- HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) {
- if (statements == null) return null;
- return new HSubGraphBlockInformation(statements);
- }
-
- HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
- if (expression == null) return null;
- return new HSubExpressionBlockInformation(expression);
- }
-
- // For while loops, initializer and update are null.
- // The condition function must return a boolean result.
- // None of the functions must leave anything on the stack.
- void handleLoop(ast.Node loop, void initialize(), HInstruction condition(),
- void update(), void body()) {
- // Generate:
- // <initializer>
- // loop-entry:
- // if (!<condition>) goto loop-exit;
- // <body>
- // <updates>
- // goto loop-entry;
- // loop-exit:
-
- localsHandler.startLoop(loop);
-
- // The initializer.
- SubExpression initializerGraph = null;
- HBasicBlock startBlock;
- if (initialize != null) {
- HBasicBlock initializerBlock = openNewBlock();
- startBlock = initializerBlock;
- initialize();
- assert(!isAborted());
- initializerGraph = new SubExpression(initializerBlock, current);
- }
-
- loopNesting++;
- JumpHandler jumpHandler = beginLoopHeader(loop);
- HLoopInformation loopInfo = current.loopInformation;
- HBasicBlock conditionBlock = current;
- if (startBlock == null) startBlock = conditionBlock;
-
- HInstruction conditionInstruction = condition();
- HBasicBlock conditionEndBlock =
- close(new HLoopBranch(conditionInstruction));
- SubExpression conditionExpression =
- new SubExpression(conditionBlock, conditionEndBlock);
-
- // Save the values of the local variables at the end of the condition
- // block. These are the values that will flow to the loop exit if the
- // condition fails.
- LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
-
- // The body.
- HBasicBlock beginBodyBlock = addNewBlock();
- conditionEndBlock.addSuccessor(beginBodyBlock);
- open(beginBodyBlock);
-
- localsHandler.enterLoopBody(loop);
- body();
-
- SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock);
- HBasicBlock bodyBlock = current;
- if (current != null) close(new HGoto());
-
- SubExpression updateGraph;
-
- bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null;
- if (!loopIsDegenerate) {
- // Update.
- // We create an update block, even when we are in a while loop. There the
- // update block is the jump-target for continue statements. We could avoid
- // the creation if there is no continue, but for now we always create it.
- HBasicBlock updateBlock = addNewBlock();
-
- List<LocalsHandler> continueHandlers = <LocalsHandler>[];
- jumpHandler
- .forEachContinue((HContinue instruction, LocalsHandler locals) {
- instruction.block.addSuccessor(updateBlock);
- continueHandlers.add(locals);
- });
-
- if (bodyBlock != null) {
- continueHandlers.add(localsHandler);
- bodyBlock.addSuccessor(updateBlock);
- }
-
- open(updateBlock);
- localsHandler =
- continueHandlers[0].mergeMultiple(continueHandlers, updateBlock);
-
- List<LabelDefinition> labels = jumpHandler.labels();
- JumpTarget target = elements.getTargetDefinition(loop);
- if (!labels.isEmpty) {
- beginBodyBlock.setBlockFlow(
- new HLabeledBlockInformation(
- new HSubGraphBlockInformation(bodyGraph), jumpHandler.labels(),
- isContinue: true),
- updateBlock);
- } else if (target != null && target.isContinueTarget) {
- beginBodyBlock.setBlockFlow(
- new HLabeledBlockInformation.implicit(
- new HSubGraphBlockInformation(bodyGraph), target,
- isContinue: true),
- updateBlock);
- }
-
- localsHandler.enterLoopUpdates(loop);
-
- update();
-
- HBasicBlock updateEndBlock = close(new HGoto());
- // The back-edge completing the cycle.
- updateEndBlock.addSuccessor(conditionBlock);
- updateGraph = new SubExpression(updateBlock, updateEndBlock);
-
- // Avoid a critical edge from the condition to the loop-exit body.
- HBasicBlock conditionExitBlock = addNewBlock();
- open(conditionExitBlock);
- close(new HGoto());
- conditionEndBlock.addSuccessor(conditionExitBlock);
-
- endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
-
- conditionBlock.postProcessLoopHeader();
- HLoopBlockInformation info = new HLoopBlockInformation(
- _loopKind(loop),
- wrapExpressionGraph(initializerGraph),
- wrapExpressionGraph(conditionExpression),
- wrapStatementGraph(bodyGraph),
- wrapExpressionGraph(updateGraph),
- conditionBlock.loopInformation.target,
- conditionBlock.loopInformation.labels,
- sourceInformationBuilder.buildLoop(loop));
-
- startBlock.setBlockFlow(info, current);
- loopInfo.loopBlockInformation = info;
- } else {
- // The body of the for/while loop always aborts, so there is no back edge.
- // We turn the code into:
- // if (condition) {
- // body;
- // } else {
- // // We always create an empty else block to avoid critical edges.
- // }
- //
- // If there is any break in the body, we attach a synthetic
- // label to the if.
- HBasicBlock elseBlock = addNewBlock();
- open(elseBlock);
- close(new HGoto());
- // Pass the elseBlock as the branchBlock, because that's the block we go
- // to just before leaving the 'loop'.
- endLoop(conditionBlock, elseBlock, jumpHandler, savedLocals);
-
- SubGraph elseGraph = new SubGraph(elseBlock, elseBlock);
- // Remove the loop information attached to the header.
- conditionBlock.loopInformation = null;
-
- // Remove the [HLoopBranch] instruction and replace it with
- // [HIf].
- HInstruction condition = conditionEndBlock.last.inputs[0];
- conditionEndBlock.addAtExit(new HIf(condition));
- conditionEndBlock.addSuccessor(elseBlock);
- conditionEndBlock.remove(conditionEndBlock.last);
- HIfBlockInformation info = new HIfBlockInformation(
- wrapExpressionGraph(conditionExpression),
- wrapStatementGraph(bodyGraph),
- wrapStatementGraph(elseGraph));
-
- conditionEndBlock.setBlockFlow(info, current);
- HIf ifBlock = conditionEndBlock.last;
- ifBlock.blockInformation = conditionEndBlock.blockFlow;
-
- // If the body has any break, attach a synthesized label to the
- // if block.
- if (jumpHandler.hasAnyBreak()) {
- JumpTarget target = elements.getTargetDefinition(loop);
- LabelDefinition label = target.addLabel(null, 'loop');
- label.setBreakTarget();
- SubGraph labelGraph = new SubGraph(conditionBlock, current);
- HLabeledBlockInformation labelInfo = new HLabeledBlockInformation(
- new HSubGraphBlockInformation(labelGraph),
- <LabelDefinition>[label]);
-
- conditionBlock.setBlockFlow(labelInfo, current);
-
- jumpHandler.forEachBreak((HBreak breakInstruction, _) {
- HBasicBlock block = breakInstruction.block;
- block.addAtExit(new HBreak.toLabel(label));
- block.remove(breakInstruction);
- });
- }
- }
- jumpHandler.close();
- loopNesting--;
- }
-
visitFor(ast.For node) {
assert(isReachable);
assert(node.body != null);
@@ -2256,7 +1763,8 @@ class SsaBuilder extends ast.Visitor
visit(node.body);
}
- handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
+ loopHandler.handleLoop(
+ node, buildInitializer, buildCondition, buildUpdate, buildBody);
}
visitWhile(ast.While node) {
@@ -2266,7 +1774,7 @@ class SsaBuilder extends ast.Visitor
return popBoolified();
}
- handleLoop(node, () {}, buildCondition, () {}, () {
+ loopHandler.handleLoop(node, () {}, buildCondition, () {}, () {
visit(node.body);
});
}
@@ -2275,8 +1783,8 @@ class SsaBuilder extends ast.Visitor
assert(isReachable);
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
localsHandler.startLoop(node);
- loopNesting++;
- JumpHandler jumpHandler = beginLoopHeader(node);
+ loopDepth++;
+ JumpHandler jumpHandler = loopHandler.beginLoopHeader(node);
HLoopInformation loopInfo = current.loopInformation;
HBasicBlock loopEntryBlock = current;
HBasicBlock bodyEntryBlock = current;
@@ -2363,7 +1871,8 @@ class SsaBuilder extends ast.Visitor
close(new HGoto());
conditionEndBlock.addSuccessor(conditionExitBlock);
- endLoop(loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
+ loopHandler.endLoop(
+ loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
loopEntryBlock.postProcessLoopHeader();
SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock);
@@ -2386,7 +1895,7 @@ class SsaBuilder extends ast.Visitor
if (jumpHandler.hasAnyBreak()) {
// Null branchBlock because the body of the do-while loop always aborts,
// so we never get to the condition.
- endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
+ loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
// Since the body of the loop has a break, we attach a synthesized label
// to the body.
@@ -2405,7 +1914,7 @@ class SsaBuilder extends ast.Visitor
}
}
jumpHandler.close();
- loopNesting--;
+ loopDepth--;
}
visitFunctionExpression(ast.FunctionExpression node) {
@@ -6056,7 +5565,7 @@ class SsaBuilder extends ast.Visitor
* a special "null handler" is returned.
*
* [isLoopJump] is [:true:] when the jump handler is for a loop. This is used
- * to distinguish the synthetized loop created for a switch statement with
+ * to distinguish the synthesized loop created for a switch statement with
* continue statements from simple switch statements.
*/
JumpHandler createJumpHandler(ast.Statement node, {bool isLoopJump}) {
@@ -6125,7 +5634,7 @@ class SsaBuilder extends ast.Visitor
void buildUpdate() {}
buildProtectedByFinally(() {
- handleLoop(
+ loopHandler.handleLoop(
node, buildInitializer, buildCondition, buildUpdate, buildBody);
}, () {
pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]);
@@ -6195,7 +5704,8 @@ class SsaBuilder extends ast.Visitor
visit(node.body);
}
- handleLoop(node, buildInitializer, buildCondition, () {}, buildBody);
+ loopHandler.handleLoop(
+ node, buildInitializer, buildCondition, () {}, buildBody);
}
buildAssignLoopVariable(ast.ForIn node, HInstruction value) {
@@ -6314,7 +5824,8 @@ class SsaBuilder extends ast.Visitor
localsHandler.updateLocal(indexVariable, addInstruction);
}
- handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
+ loopHandler.handleLoop(
+ node, buildInitializer, buildCondition, buildUpdate, buildBody);
}
visitLabel(ast.Label node) {
@@ -6658,7 +6169,7 @@ class SsaBuilder extends ast.Visitor
}
void buildLoop() {
- handleLoop(node, () {}, buildCondition, () {}, buildSwitch);
+ loopHandler.handleLoop(node, () {}, buildCondition, () {}, buildSwitch);
}
if (hasDefault) {
@@ -7560,19 +7071,3 @@ class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
}
}
-
-/// Determine what kind of loop [node] represents. The result is one of the
-/// kinds defined in [HLoopBlockInformation].
-int _loopKind(ast.Node node) => node.accept(const _LoopTypeVisitor());
-
-class _LoopTypeVisitor extends ast.Visitor {
- const _LoopTypeVisitor();
- int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
- int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
- int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
- int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
- int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
- int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
- int visitSwitchStatement(ast.SwitchStatement node) =>
- HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
-}
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698