| Index: pkg/compiler/lib/src/js_model/locals.dart
|
| diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
|
| index f89bf5c1da2d3473095f2e558b105718956560a1..0ce0ee21bc0ed5f9a3381d886a430be1b43c84e6 100644
|
| --- a/pkg/compiler/lib/src/js_model/locals.dart
|
| +++ b/pkg/compiler/lib/src/js_model/locals.dart
|
| @@ -171,7 +171,8 @@ class KernelToLocalsMapImpl implements KernelToLocalsMap {
|
| }
|
|
|
| class JumpVisitor extends ir.Visitor {
|
| - int index = 0;
|
| + int jumpIndex = 0;
|
| + int labelIndex = 0;
|
| final MemberEntity member;
|
| final Map<ir.TreeNode, JJumpTarget> jumpTargetMap =
|
| <ir.TreeNode, JJumpTarget>{};
|
| @@ -181,7 +182,7 @@ class JumpVisitor extends ir.Visitor {
|
|
|
| JJumpTarget _getJumpTarget(ir.TreeNode node) {
|
| return jumpTargetMap.putIfAbsent(node, () {
|
| - return new JJumpTarget(member, index++);
|
| + return new JJumpTarget(member, jumpIndex++);
|
| });
|
| }
|
|
|
| @@ -221,6 +222,19 @@ class JumpVisitor extends ir.Visitor {
|
| // and can therefore use the for loop as the break target.
|
| target = _getJumpTarget(body);
|
| target.isBreakTarget = true;
|
| + ir.TreeNode search = node;
|
| + bool needsLabel = false;
|
| + while (search != node.target) {
|
| + if (_canBeBreakTarget(search)) {
|
| + needsLabel = search != body;
|
| + break;
|
| + }
|
| + search = search.parent;
|
| + }
|
| + if (needsLabel) {
|
| + target.addLabel(node.target, 'label${labelIndex++}',
|
| + isBreakTarget: true);
|
| + }
|
| } else if (_canBeContinueTarget(parent)) {
|
| // We have code like
|
| //
|
| @@ -244,6 +258,7 @@ class JumpVisitor extends ir.Visitor {
|
| class JJumpTarget extends JumpTarget<ir.Node> {
|
| final MemberEntity memberContext;
|
| final int nestingLevel;
|
| + List<LabelDefinition<ir.Node>> _labels;
|
|
|
| JJumpTarget(this.memberContext, this.nestingLevel);
|
|
|
| @@ -257,22 +272,27 @@ class JJumpTarget extends JumpTarget<ir.Node> {
|
| @override
|
| LabelDefinition<ir.Node> addLabel(ir.Node label, String labelName,
|
| {bool isBreakTarget: false}) {
|
| - throw new UnimplementedError('KJumpTarget.addLabel');
|
| + _labels ??= <LabelDefinition<ir.Node>>[];
|
| + LabelDefinition<ir.Node> labelDefinition = new JLabelDefinition(
|
| + this, label, labelName,
|
| + isBreakTarget: isBreakTarget);
|
| + _labels.add(labelDefinition);
|
| + return labelDefinition;
|
| }
|
|
|
| @override
|
| List<LabelDefinition<ir.Node>> get labels {
|
| - return const <LabelDefinition<ir.Node>>[];
|
| + return _labels ?? const <LabelDefinition<ir.Node>>[];
|
| }
|
|
|
| @override
|
| ir.Node get statement {
|
| - throw new UnimplementedError('KJumpTarget.statement');
|
| + throw new UnimplementedError('JJumpTarget.statement');
|
| }
|
|
|
| String toString() {
|
| StringBuffer sb = new StringBuffer();
|
| - sb.write('KJumpTarget[');
|
| + sb.write('JJumpTarget(');
|
| sb.write('memberContext=');
|
| sb.write(memberContext);
|
| sb.write(',nestingLevel=');
|
| @@ -281,7 +301,39 @@ class JJumpTarget extends JumpTarget<ir.Node> {
|
| sb.write(isBreakTarget);
|
| sb.write(',isContinueTarget=');
|
| sb.write(isContinueTarget);
|
| - sb.write(']');
|
| + if (_labels != null) {
|
| + sb.write(',labels=');
|
| + sb.write(_labels);
|
| + }
|
| + sb.write(')');
|
| + return sb.toString();
|
| + }
|
| +}
|
| +
|
| +class JLabelDefinition extends LabelDefinition<ir.Node> {
|
| + final JumpTarget<ir.Node> target;
|
| + final ir.Node label;
|
| + final String labelName;
|
| + final bool isBreakTarget;
|
| + final bool isContinueTarget;
|
| +
|
| + JLabelDefinition(this.target, this.label, this.labelName,
|
| + {this.isBreakTarget: false, this.isContinueTarget: false});
|
| +
|
| + @override
|
| + String get name => labelName;
|
| + String toString() {
|
| + StringBuffer sb = new StringBuffer();
|
| + sb.write('JLabelDefinition(');
|
| + sb.write('label=');
|
| + sb.write(label);
|
| + sb.write(',labelName=');
|
| + sb.write(labelName);
|
| + sb.write(',isBreakTarget=');
|
| + sb.write(isBreakTarget);
|
| + sb.write(',isContinueTarget=');
|
| + sb.write(isContinueTarget);
|
| + sb.write(')');
|
| return sb.toString();
|
| }
|
| }
|
|
|