Index: pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart |
diff --git a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart |
index a6b8d6e57becafa4b090b269a55abdc077caed00..59254091d6b33bc6b9c27f3d6cb3afeb948ac846 100644 |
--- a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart |
+++ b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart |
@@ -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. |
Siggi Cherem (dart-lang)
2017/06/23 19:34:00
I know this will go away when you do it eagerly, b
Johnni Winther
2017/06/26 09:04:18
Your guess is right.
|
+ 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(johnniwinther): 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(johnniwinther): Support for statement as jump target. |
- return null; |
+ _ensureJumpMap(node); |
+ return _jumpTargetMap[node.parent]; |
} |
@override |
JumpTarget getJumpTargetForForIn(ir.ForInStatement node) { |
- // TODO(johnniwinther): Support for-in statement as jump target. |
- return null; |
+ _ensureJumpMap(node); |
+ return _jumpTargetMap[node.parent]; |
} |
@override |
JumpTarget getJumpTargetForWhile(ir.WhileStatement node) { |
- // TODO(johnniwinther): 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; |