mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 15:50:01 +00:00
[dart2js] Migrate ssa/loop_handler.dart to null safety.
Change-Id: I0391fe611d55d63a18540ea5e3410da585a377ed Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277080 Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
ce741bb017
commit
76cb3cc372
|
@ -116,6 +116,7 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
///
|
||||
/// The loop nesting is consulted when inlining a function invocation. The
|
||||
/// inlining heuristics take this information into account.
|
||||
@override
|
||||
int loopDepth = 0;
|
||||
|
||||
/// A mapping from jump targets to their handlers.
|
||||
|
@ -260,6 +261,7 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
|
||||
/// The current block to add instructions to. Might be null, if we are
|
||||
/// visiting dead code, but see [_isReachable].
|
||||
@override
|
||||
HBasicBlock get current => _current;
|
||||
|
||||
void set current(c) {
|
||||
|
@ -270,6 +272,7 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
/// The most recently opened block. Has the same value as [current] while
|
||||
/// the block is open, but unlike [current], it isn't cleared when the
|
||||
/// current block is closed.
|
||||
@override
|
||||
HBasicBlock lastOpenedBlock;
|
||||
|
||||
/// Indicates whether the current block is dead (because it has a throw or a
|
||||
|
@ -286,6 +289,7 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
Map<Local, HInstruction> parameters = {};
|
||||
Set<Local> elidedParameters;
|
||||
|
||||
@override
|
||||
HBasicBlock addNewBlock() {
|
||||
HBasicBlock block = graph.addNewBlock();
|
||||
// If adding a new block during building of an expression, it is due to
|
||||
|
@ -293,6 +297,7 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
return block;
|
||||
}
|
||||
|
||||
@override
|
||||
void open(HBasicBlock block) {
|
||||
block.open();
|
||||
current = block;
|
||||
|
@ -320,12 +325,14 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
from.addSuccessor(to);
|
||||
}
|
||||
|
||||
@override
|
||||
bool isAborted() {
|
||||
return current == null;
|
||||
}
|
||||
|
||||
/// Creates a new block, transitions to it from any current block, and
|
||||
/// opens the new block.
|
||||
@override
|
||||
HBasicBlock openNewBlock() {
|
||||
HBasicBlock newBlock = addNewBlock();
|
||||
if (!isAborted()) goto(current, newBlock);
|
||||
|
@ -353,11 +360,13 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) {
|
||||
if (statements == null) return null;
|
||||
return HSubGraphBlockInformation(statements);
|
||||
}
|
||||
|
||||
@override
|
||||
HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
|
||||
if (expression == null) return null;
|
||||
return HSubExpressionBlockInformation(expression);
|
||||
|
@ -2661,7 +2670,8 @@ class KernelSsaGraphBuilder extends ir.Visitor<void>
|
|||
/// [isLoopJump] is true when the jump handler is for a loop. This is used
|
||||
/// to distinguish the synthesized loop created for a switch statement with
|
||||
/// continue statements from simple switch statements.
|
||||
JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget target,
|
||||
@override
|
||||
JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget /*?*/ target,
|
||||
{bool isLoopJump = false}) {
|
||||
if (target == null) {
|
||||
// No breaks or continues to this node.
|
||||
|
|
|
@ -28,6 +28,7 @@ abstract class KernelSsaGraphBuilder extends ir.Visitor<void> {
|
|||
Map<JumpTarget, JumpHandler> get jumpTargets;
|
||||
|
||||
LocalsHandler get localsHandler;
|
||||
set localsHandler(LocalsHandler handler);
|
||||
|
||||
CodegenRegistry get registry;
|
||||
|
||||
|
@ -42,6 +43,13 @@ abstract class KernelSsaGraphBuilder extends ir.Visitor<void> {
|
|||
HLocalValue? get lastAddedParameter;
|
||||
set lastAddedParameter(HLocalValue? parameter);
|
||||
|
||||
HBasicBlock? get current;
|
||||
|
||||
int get loopDepth;
|
||||
set loopDepth(int depth);
|
||||
|
||||
HBasicBlock get lastOpenedBlock;
|
||||
|
||||
set elidedParameters(Set<Local> elidedParameters);
|
||||
|
||||
void add(HInstruction box);
|
||||
|
@ -52,4 +60,19 @@ abstract class KernelSsaGraphBuilder extends ir.Visitor<void> {
|
|||
HBasicBlock close(HControlFlow end);
|
||||
|
||||
HInstruction pop();
|
||||
|
||||
HBasicBlock openNewBlock();
|
||||
|
||||
bool isAborted();
|
||||
|
||||
HBasicBlock addNewBlock();
|
||||
|
||||
void open(HBasicBlock beginBodyBlock);
|
||||
|
||||
HExpressionInformation wrapExpressionGraph(SubExpression initializerGraph);
|
||||
|
||||
HStatementInformation wrapStatementGraph(SubGraph bodyGraph);
|
||||
|
||||
JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget? jumpTarget,
|
||||
{required bool isLoopJump});
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
import 'package:kernel/ast.dart' as ir;
|
||||
|
||||
import '../closure.dart' show CapturedLoopScope;
|
||||
|
@ -11,7 +9,7 @@ import '../elements/jumps.dart';
|
|||
import '../inferrer/abstract_value_domain.dart';
|
||||
import '../io/source_information.dart';
|
||||
|
||||
import 'builder.dart';
|
||||
import 'builder_interfaces.dart';
|
||||
import 'jump_handler.dart';
|
||||
import 'locals_handler.dart';
|
||||
import 'nodes.dart';
|
||||
|
@ -27,13 +25,12 @@ abstract class LoopHandler {
|
|||
|
||||
/// Builds a graph for the given [loop] node.
|
||||
///
|
||||
/// For while loops, [initialize] and [update] are null.
|
||||
/// The [condition] function must return a boolean result.
|
||||
/// None of the functions must leave anything on the stack.
|
||||
void handleLoop(
|
||||
ir.Node loop,
|
||||
ir.TreeNode loop,
|
||||
CapturedLoopScope loopClosureInfo,
|
||||
JumpTarget jumpTarget,
|
||||
JumpTarget? jumpTarget,
|
||||
void initialize(),
|
||||
HInstruction condition(),
|
||||
void update(),
|
||||
|
@ -51,21 +48,16 @@ abstract class LoopHandler {
|
|||
builder.localsHandler.startLoop(loopClosureInfo, sourceInformation);
|
||||
|
||||
// The initializer.
|
||||
SubExpression initializerGraph = null;
|
||||
HBasicBlock startBlock;
|
||||
if (initialize != null) {
|
||||
HBasicBlock initializerBlock = builder.openNewBlock();
|
||||
startBlock = initializerBlock;
|
||||
initialize();
|
||||
assert(!builder.isAborted());
|
||||
initializerGraph = SubExpression(initializerBlock, builder.current);
|
||||
}
|
||||
SubExpression? initializerGraph;
|
||||
HBasicBlock startBlock = builder.openNewBlock();
|
||||
initialize();
|
||||
assert(!builder.isAborted());
|
||||
initializerGraph = SubExpression(startBlock, builder.current!);
|
||||
|
||||
builder.loopDepth++;
|
||||
JumpHandler jumpHandler = beginLoopHeader(loop, jumpTarget);
|
||||
HLoopInformation loopInfo = builder.current.loopInformation;
|
||||
HBasicBlock conditionBlock = builder.current;
|
||||
if (startBlock == null) startBlock = conditionBlock;
|
||||
final conditionBlock = builder.current!;
|
||||
final loopInfo = conditionBlock.loopInformation!;
|
||||
|
||||
HInstruction conditionInstruction = condition();
|
||||
HBasicBlock conditionEndBlock =
|
||||
|
@ -87,8 +79,8 @@ abstract class LoopHandler {
|
|||
body();
|
||||
|
||||
SubGraph bodyGraph = SubGraph(beginBodyBlock, builder.lastOpenedBlock);
|
||||
HBasicBlock bodyBlock = builder.current;
|
||||
if (builder.current != null) builder.close(HGoto(_abstractValueDomain));
|
||||
final bodyBlock = builder.current;
|
||||
if (bodyBlock != null) builder.close(HGoto(_abstractValueDomain));
|
||||
|
||||
SubExpression updateGraph;
|
||||
|
||||
|
@ -103,7 +95,7 @@ abstract class LoopHandler {
|
|||
List<LocalsHandler> continueHandlers = <LocalsHandler>[];
|
||||
jumpHandler
|
||||
.forEachContinue((HContinue instruction, LocalsHandler locals) {
|
||||
instruction.block.addSuccessor(updateBlock);
|
||||
instruction.block!.addSuccessor(updateBlock);
|
||||
continueHandlers.add(locals);
|
||||
});
|
||||
|
||||
|
@ -156,8 +148,8 @@ abstract class LoopHandler {
|
|||
builder.wrapExpressionGraph(conditionExpression),
|
||||
builder.wrapStatementGraph(bodyGraph),
|
||||
builder.wrapExpressionGraph(updateGraph),
|
||||
conditionBlock.loopInformation.target,
|
||||
conditionBlock.loopInformation.labels,
|
||||
loopInfo.target,
|
||||
loopInfo.labels,
|
||||
sourceInformation);
|
||||
|
||||
startBlock.setBlockFlow(info, builder.current);
|
||||
|
@ -186,32 +178,32 @@ abstract class LoopHandler {
|
|||
|
||||
// Remove the [HLoopBranch] instruction and replace it with
|
||||
// [HIf].
|
||||
HInstruction condition = conditionEndBlock.last.inputs[0];
|
||||
HInstruction condition = conditionEndBlock.last!.inputs[0];
|
||||
conditionEndBlock.addAtExit(HIf(_abstractValueDomain, condition));
|
||||
conditionEndBlock.addSuccessor(elseBlock);
|
||||
conditionEndBlock.remove(conditionEndBlock.last);
|
||||
conditionEndBlock.remove(conditionEndBlock.last!);
|
||||
HIfBlockInformation info = HIfBlockInformation(
|
||||
builder.wrapExpressionGraph(conditionExpression),
|
||||
builder.wrapStatementGraph(bodyGraph),
|
||||
builder.wrapStatementGraph(elseGraph));
|
||||
|
||||
conditionEndBlock.setBlockFlow(info, builder.current);
|
||||
HIf ifBlock = conditionEndBlock.last;
|
||||
final ifBlock = conditionEndBlock.last as HIf;
|
||||
ifBlock.blockInformation = conditionEndBlock.blockFlow;
|
||||
|
||||
// If the body has any break, attach a synthesized label to the
|
||||
// if block.
|
||||
if (jumpHandler.hasAnyBreak()) {
|
||||
LabelDefinition label =
|
||||
jumpTarget.addLabel('loop', isBreakTarget: true);
|
||||
SubGraph labelGraph = SubGraph(conditionBlock, builder.current);
|
||||
jumpTarget!.addLabel('loop', isBreakTarget: true);
|
||||
SubGraph labelGraph = SubGraph(conditionBlock, builder.current!);
|
||||
HLabeledBlockInformation labelInfo = HLabeledBlockInformation(
|
||||
HSubGraphBlockInformation(labelGraph), <LabelDefinition>[label]);
|
||||
|
||||
conditionBlock.setBlockFlow(labelInfo, builder.current);
|
||||
|
||||
jumpHandler.forEachBreak((HBreak breakInstruction, _) {
|
||||
HBasicBlock block = breakInstruction.block;
|
||||
final block = breakInstruction.block!;
|
||||
block.addAtExit(
|
||||
HBreak.toLabel(_abstractValueDomain, label, sourceInformation));
|
||||
block.remove(breakInstruction);
|
||||
|
@ -225,7 +217,7 @@ abstract class LoopHandler {
|
|||
/// 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(ir.TreeNode node, JumpTarget jumpTarget) {
|
||||
JumpHandler beginLoopHeader(ir.TreeNode node, JumpTarget? jumpTarget) {
|
||||
assert(!builder.isAborted());
|
||||
HBasicBlock previousBlock = builder.close(HGoto(_abstractValueDomain));
|
||||
|
||||
|
@ -255,14 +247,14 @@ abstract class LoopHandler {
|
|||
/// 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,
|
||||
void endLoop(HBasicBlock loopEntry, HBasicBlock? branchExitBlock,
|
||||
JumpHandler jumpHandler, LocalsHandler savedLocals) {
|
||||
HBasicBlock loopExitBlock = builder.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);
|
||||
breakInstruction.block!.addSuccessor(loopExitBlock);
|
||||
breakHandlers.add(locals);
|
||||
});
|
||||
|
||||
|
@ -306,23 +298,18 @@ abstract class LoopHandler {
|
|||
/// [isLoopJump] is [:true:] when the jump handler is for a loop. This is used
|
||||
/// to distinguish the synthesized loop created for a switch statement with
|
||||
/// continue statements from simple switch statements.
|
||||
JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget jumpTarget,
|
||||
{bool isLoopJump});
|
||||
JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget? jumpTarget,
|
||||
{required bool isLoopJump});
|
||||
}
|
||||
|
||||
// TODO(het): Since kernel simplifies loop breaks and continues, we should
|
||||
// rewrite the loop handler from scratch to account for the simplified structure
|
||||
class KernelLoopHandler extends LoopHandler {
|
||||
@override
|
||||
final KernelSsaGraphBuilder builder;
|
||||
|
||||
KernelLoopHandler(KernelSsaGraphBuilder builder)
|
||||
: this.builder = builder,
|
||||
super(builder);
|
||||
KernelLoopHandler(super.builder);
|
||||
|
||||
@override
|
||||
JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget jumpTarget,
|
||||
{bool isLoopJump}) =>
|
||||
JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget? jumpTarget,
|
||||
{required bool isLoopJump}) =>
|
||||
builder.createJumpHandler(node, jumpTarget, isLoopJump: isLoopJump);
|
||||
|
||||
@override
|
||||
|
|
Loading…
Reference in a new issue