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

Unified Diff: pkg/compiler/lib/src/js_model/locals.dart

Issue 2960153002: Move locals and closure classes from kernel/ to js_model/ (Closed)
Patch Set: Created 3 years, 6 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/js_model/js_strategy.dart ('k') | pkg/compiler/lib/src/kernel/closure.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
new file mode 100644
index 0000000000000000000000000000000000000000..a79037a6dafd542530dc1c04c95a039af44e85f7
--- /dev/null
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -0,0 +1,278 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library dart2js.js_model.locals;
+
+import 'package:kernel/ast.dart' as ir;
+
+import '../closure.dart';
+import '../common.dart';
+import '../elements/entities.dart';
+import '../elements/jumps.dart';
+import '../kernel/element_map.dart';
+
+class GlobalLocalsMap {
+ Map<MemberEntity, KernelToLocalsMap> _localsMaps =
+ <MemberEntity, KernelToLocalsMap>{};
+
+ KernelToLocalsMap getLocalsMap(MemberEntity member) {
+ return _localsMaps.putIfAbsent(
+ member, () => new KernelToLocalsMapImpl(member));
+ }
+}
+
+class KernelToLocalsMapImpl implements KernelToLocalsMap {
+ final List<MemberEntity> _members = <MemberEntity>[];
+ Map<ir.VariableDeclaration, JLocal> _map = <ir.VariableDeclaration, JLocal>{};
+ Map<ir.TreeNode, JJumpTarget> _jumpTargetMap;
+ Set<ir.BreakStatement> _breaksAsContinue;
+
+ 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;
+ _breaksAsContinue = visitor.breaksAsContinue;
+ }
+ }
+
+ KernelToLocalsMapImpl(MemberEntity member) {
+ _members.add(member);
+ }
+
+ @override
+ void enterInlinedMember(MemberEntity member) {
+ _members.add(member);
+ }
+
+ @override
+ void leaveInlinedMember(MemberEntity member) {
+ assert(member == currentMember);
+ _members.removeLast();
+ }
+
+ @override
+ JumpTarget getJumpTargetForBreak(ir.BreakStatement node) {
+ _ensureJumpMap(node.target);
+ JumpTarget target = _jumpTargetMap[node];
+ assert(target != null, failedAt(currentMember, 'No target for $node.'));
+ return target;
+ }
+
+ @override
+ bool generateContinueForBreak(ir.BreakStatement node) {
+ return _breaksAsContinue.contains(node);
+ }
+
+ @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) {
+ _ensureJumpMap(node);
+ return _jumpTargetMap[node.parent];
+ }
+
+ @override
+ JumpTarget getJumpTargetForLabel(ir.LabeledStatement node) {
+ _ensureJumpMap(node);
+ return _jumpTargetMap[node];
+ }
+
+ @override
+ JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node) {
+ _ensureJumpMap(node);
+ throw new UnimplementedError(
+ 'KernelToLocalsMapImpl.getJumpTargetForSwitch');
+ }
+
+ @override
+ JumpTarget getJumpTargetForFor(ir.ForStatement node) {
+ _ensureJumpMap(node);
+ return _jumpTargetMap[node];
+ }
+
+ @override
+ JumpTarget getJumpTargetForForIn(ir.ForInStatement node) {
+ _ensureJumpMap(node);
+ return _jumpTargetMap[node];
+ }
+
+ @override
+ JumpTarget getJumpTargetForWhile(ir.WhileStatement node) {
+ _ensureJumpMap(node);
+ return _jumpTargetMap[node];
+ }
+
+ @override
+ Local getLocal(ir.VariableDeclaration node) {
+ return _map.putIfAbsent(node, () {
+ return new JLocal(node.name, currentMember);
+ });
+ }
+
+ @override
+ LoopClosureScope getLoopClosureScope(
+ ClosureDataLookup closureLookup, ir.TreeNode node) {
+ return closureLookup.getLoopClosureScope(node);
+ }
+}
+
+class JumpVisitor extends ir.Visitor {
+ int index = 0;
+ final MemberEntity member;
+ final Map<ir.TreeNode, JJumpTarget> jumpTargetMap =
+ <ir.TreeNode, JJumpTarget>{};
+ final Set<ir.BreakStatement> breaksAsContinue = new Set<ir.BreakStatement>();
+
+ JumpVisitor(this.member);
+
+ JJumpTarget _getJumpTarget(ir.TreeNode node) {
+ return jumpTargetMap.putIfAbsent(node, () {
+ return new JJumpTarget(member, index++);
+ });
+ }
+
+ @override
+ defaultNode(ir.Node node) => node.visitChildren(this);
+
+ bool _canBeBreakTarget(ir.TreeNode node) {
+ // TODO(johnniwinther): Add more.
+ return node is ir.ForStatement ||
+ node is ir.ForInStatement ||
+ node is ir.WhileStatement;
+ }
+
+ bool _canBeContinueTarget(ir.TreeNode node) {
+ // TODO(johnniwinther): Add more.
+ return node is ir.ForStatement ||
+ node is ir.ForInStatement ||
+ node is ir.WhileStatement;
+ }
+
+ @override
+ visitBreakStatement(ir.BreakStatement node) {
+ // TODO(johnniwinther): Add labels if the enclosing loop is not the implicit
+ // break target.
+ JJumpTarget target;
+ ir.TreeNode body = node.target.body;
+ ir.TreeNode parent = node.target.parent;
+ if (_canBeBreakTarget(body)) {
+ // We have code like
+ //
+ // l1: for (int i = 0; i < 10; i++) {
+ // break l1:
+ // }
+ //
+ // and can therefore use the for loop as the break target.
+ target = _getJumpTarget(body);
+ target.isBreakTarget = true;
+ } else if (_canBeContinueTarget(parent)) {
+ // We have code like
+ //
+ // for (int i = 0; i < 10; i++) l1: {
+ // break l1:
+ // }
+ //
+ // and can therefore use the for loop as a continue target.
+ target = _getJumpTarget(parent);
+ target.isContinueTarget = true;
+ breaksAsContinue.add(node);
+ } else {
+ target = _getJumpTarget(node.target);
+ target.isBreakTarget = true;
+ }
+ jumpTargetMap[node] = target;
+ super.visitBreakStatement(node);
+ }
+}
+
+class JJumpTarget extends JumpTarget<ir.Node> {
+ final MemberEntity memberContext;
+ final int nestingLevel;
+
+ JJumpTarget(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');
+ }
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('KJumpTarget[');
+ sb.write('memberContext=');
+ sb.write(memberContext);
+ sb.write(',nestingLevel=');
+ sb.write(nestingLevel);
+ sb.write(',isBreakTarget=');
+ sb.write(isBreakTarget);
+ sb.write(',isContinueTarget=');
+ sb.write(isContinueTarget);
+ sb.write(']');
+ return sb.toString();
+ }
+}
+
+class JLocal implements Local {
+ final String name;
+ final MemberEntity memberContext;
+
+ JLocal(this.name, this.memberContext);
+
+ @override
+ Entity get executableContext => memberContext;
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('local(');
+ if (memberContext.enclosingClass != null) {
+ sb.write(memberContext.enclosingClass.name);
+ sb.write('.');
+ }
+ sb.write(memberContext.name);
+ sb.write('#');
+ sb.write(name);
+ sb.write(')');
+ return sb.toString();
+ }
+}
« no previous file with comments | « pkg/compiler/lib/src/js_model/js_strategy.dart ('k') | pkg/compiler/lib/src/kernel/closure.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698