mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 14:51:30 +00:00
Handle for-loop with simple break in compile_from_dill_test
R=sigmund@google.com Review-Url: https://codereview.chromium.org/2950303002 .
This commit is contained in:
parent
f7f4d6133b
commit
14dda16482
|
@ -12,7 +12,8 @@ abstract class LabelDefinition<T> extends Entity {
|
|||
String get labelName;
|
||||
JumpTarget<T> get target;
|
||||
|
||||
bool get isTarget;
|
||||
bool get isTarget => isBreakTarget || isContinueTarget;
|
||||
|
||||
bool get isBreakTarget;
|
||||
bool get isContinueTarget;
|
||||
}
|
||||
|
@ -20,11 +21,14 @@ abstract class LabelDefinition<T> extends Entity {
|
|||
/// A jump target is the reference point of a statement or switch-case,
|
||||
/// either by label or as the default target of a break or continue.
|
||||
abstract class JumpTarget<T> extends Local {
|
||||
String get name => 'target';
|
||||
|
||||
bool get isTarget => isBreakTarget || isContinueTarget;
|
||||
|
||||
T get statement;
|
||||
int get nestingLevel;
|
||||
List<LabelDefinition<T>> get labels;
|
||||
|
||||
bool get isTarget;
|
||||
bool get isBreakTarget;
|
||||
bool get isContinueTarget;
|
||||
bool get isSwitch;
|
||||
|
|
|
@ -3337,7 +3337,7 @@ class UnnamedMixinApplicationElementX extends MixinApplicationElementX {
|
|||
bool get isAbstract => true;
|
||||
}
|
||||
|
||||
class LabelDefinitionX implements LabelDefinition<Node> {
|
||||
class LabelDefinitionX extends LabelDefinition<Node> {
|
||||
final Label label;
|
||||
final String labelName;
|
||||
final JumpTargetX target;
|
||||
|
@ -3362,12 +3362,10 @@ class LabelDefinitionX implements LabelDefinition<Node> {
|
|||
target.isContinueTarget = true;
|
||||
}
|
||||
|
||||
bool get isTarget => isBreakTarget || isContinueTarget;
|
||||
|
||||
String toString() => 'Label:${name}';
|
||||
}
|
||||
|
||||
class JumpTargetX implements JumpTarget<Node> {
|
||||
class JumpTargetX extends JumpTarget<Node> {
|
||||
final ExecutableElement executableContext;
|
||||
final Node statement;
|
||||
final int nestingLevel;
|
||||
|
@ -3382,10 +3380,6 @@ class JumpTargetX implements JumpTarget<Node> {
|
|||
@override
|
||||
MemberElement get memberContext => executableContext.memberContext;
|
||||
|
||||
String get name => "target";
|
||||
|
||||
bool get isTarget => isBreakTarget || isContinueTarget;
|
||||
|
||||
LabelDefinition<Node> addLabel(Label label, String labelName,
|
||||
{bool isBreakTarget: false}) {
|
||||
LabelDefinitionX result = new LabelDefinitionX(label, labelName, this);
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:kernel/ast.dart' as ir;
|
|||
|
||||
import '../backend_strategy.dart';
|
||||
import '../closure.dart';
|
||||
import '../common.dart';
|
||||
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
|
||||
import '../common/tasks.dart';
|
||||
import '../compiler.dart';
|
||||
|
@ -279,9 +280,25 @@ class GlobalLocalsMap {
|
|||
class KernelToLocalsMapImpl implements KernelToLocalsMap {
|
||||
final List<MemberEntity> _members = <MemberEntity>[];
|
||||
Map<ir.VariableDeclaration, KLocal> _map = <ir.VariableDeclaration, KLocal>{};
|
||||
Map<ir.LabeledStatement, KJumpTarget> _jumpTargetMap;
|
||||
|
||||
MemberEntity get currentMember => _members.last;
|
||||
|
||||
// TODO(johnniwinther): Compute this eagerly from the root of the member.
|
||||
void _ensureJumpMap(ir.TreeNode node) {
|
||||
if (_jumpTargetMap == null) {
|
||||
JumpVisitor visitor = new JumpVisitor(currentMember);
|
||||
|
||||
// Find the root node for the current member.
|
||||
while (node is! ir.Member) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
node.accept(visitor);
|
||||
_jumpTargetMap = visitor.jumpTargetMap;
|
||||
}
|
||||
}
|
||||
|
||||
KernelToLocalsMapImpl(MemberEntity member) {
|
||||
_members.add(member);
|
||||
}
|
||||
|
@ -299,54 +316,63 @@ class KernelToLocalsMapImpl implements KernelToLocalsMap {
|
|||
|
||||
@override
|
||||
JumpTarget getJumpTargetForBreak(ir.BreakStatement node) {
|
||||
throw new UnimplementedError('KernelToLocalsMapImpl.getJumpTargetForBreak');
|
||||
_ensureJumpMap(node.target);
|
||||
JumpTarget target = _jumpTargetMap[node.target];
|
||||
assert(target != null, failedAt(currentMember, 'No target for $node.'));
|
||||
return target;
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForContinueSwitch(ir.ContinueSwitchStatement node) {
|
||||
_ensureJumpMap(node.target);
|
||||
throw new UnimplementedError(
|
||||
'KernelToLocalsMapImpl.getJumpTargetForContinueSwitch');
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForSwitchCase(ir.SwitchCase node) {
|
||||
_ensureJumpMap(node);
|
||||
throw new UnimplementedError(
|
||||
'KernelToLocalsMapImpl.getJumpTargetForSwitchCase');
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForDo(ir.DoStatement node) {
|
||||
// TODO(redemption): Support do statement as jump target.
|
||||
return null;
|
||||
_ensureJumpMap(node);
|
||||
return _jumpTargetMap[node.parent];
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForLabel(ir.LabeledStatement node) {
|
||||
throw new UnimplementedError('KernelToLocalsMapImpl.getJumpTargetForLabel');
|
||||
_ensureJumpMap(node);
|
||||
JumpTarget target = _jumpTargetMap[node];
|
||||
assert(target != null, failedAt(currentMember, 'No target for $node.'));
|
||||
return target;
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node) {
|
||||
_ensureJumpMap(node);
|
||||
throw new UnimplementedError(
|
||||
'KernelToLocalsMapImpl.getJumpTargetForSwitch');
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForFor(ir.ForStatement node) {
|
||||
// TODO(redemption): Support for statement as jump target.
|
||||
return null;
|
||||
_ensureJumpMap(node);
|
||||
return _jumpTargetMap[node.parent];
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForForIn(ir.ForInStatement node) {
|
||||
// TODO(redemption): Support for-in statement as jump target.
|
||||
return null;
|
||||
_ensureJumpMap(node);
|
||||
return _jumpTargetMap[node.parent];
|
||||
}
|
||||
|
||||
@override
|
||||
JumpTarget getJumpTargetForWhile(ir.WhileStatement node) {
|
||||
// TODO(redemption): Support while statement as jump target.
|
||||
return null;
|
||||
_ensureJumpMap(node);
|
||||
return _jumpTargetMap[node.parent];
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -363,6 +389,60 @@ class KernelToLocalsMapImpl implements KernelToLocalsMap {
|
|||
}
|
||||
}
|
||||
|
||||
class JumpVisitor extends ir.Visitor {
|
||||
final MemberEntity member;
|
||||
final Map<ir.LabeledStatement, KJumpTarget> jumpTargetMap =
|
||||
<ir.LabeledStatement, KJumpTarget>{};
|
||||
|
||||
JumpVisitor(this.member);
|
||||
|
||||
KJumpTarget _getJumpTarget(ir.LabeledStatement node) {
|
||||
return jumpTargetMap.putIfAbsent(node, () {
|
||||
return new KJumpTarget(member, jumpTargetMap.length);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
defaultNode(ir.Node node) => node.visitChildren(this);
|
||||
|
||||
@override
|
||||
visitBreakStatement(ir.BreakStatement node) {
|
||||
KJumpTarget target = _getJumpTarget(node.target);
|
||||
target.isBreakTarget = true;
|
||||
super.visitBreakStatement(node);
|
||||
}
|
||||
}
|
||||
|
||||
class KJumpTarget extends JumpTarget<ir.Node> {
|
||||
final MemberEntity memberContext;
|
||||
final int nestingLevel;
|
||||
|
||||
KJumpTarget(this.memberContext, this.nestingLevel);
|
||||
|
||||
bool isBreakTarget = false;
|
||||
bool isContinueTarget = false;
|
||||
bool isSwitch = false;
|
||||
|
||||
@override
|
||||
Entity get executableContext => memberContext;
|
||||
|
||||
@override
|
||||
LabelDefinition<ir.Node> addLabel(ir.Node label, String labelName,
|
||||
{bool isBreakTarget: false}) {
|
||||
throw new UnimplementedError('KJumpTarget.addLabel');
|
||||
}
|
||||
|
||||
@override
|
||||
List<LabelDefinition<ir.Node>> get labels {
|
||||
return const <LabelDefinition<ir.Node>>[];
|
||||
}
|
||||
|
||||
@override
|
||||
ir.Node get statement {
|
||||
throw new UnimplementedError('KJumpTarget.statement');
|
||||
}
|
||||
}
|
||||
|
||||
class KLocal implements Local {
|
||||
final String name;
|
||||
final MemberEntity memberContext;
|
||||
|
|
|
@ -48,6 +48,10 @@ main() {
|
|||
new Class('');
|
||||
Class.staticField;
|
||||
var x = null;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
x = i;
|
||||
if (i == 5) break;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
'''
|
||||
|
|
Loading…
Reference in a new issue