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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 923013002: dart2dart: Implementation of simple try/catch. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixed break/continue, incorporated comments. Created 5 years, 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import '../constants/expressions.dart'; 7 import '../constants/expressions.dart';
8 import '../constants/values.dart' show PrimitiveConstantValue; 8 import '../constants/values.dart' show PrimitiveConstantValue;
9 import '../dart_types.dart'; 9 import '../dart_types.dart';
10 import '../dart2jslib.dart'; 10 import '../dart2jslib.dart';
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 /// continues are collected by a JumpCollector and processed later, on demand. 104 /// continues are collected by a JumpCollector and processed later, on demand.
105 /// The site of the break or continue is represented by a continuation 105 /// The site of the break or continue is represented by a continuation
106 /// invocation that will have its target and arguments filled in later. 106 /// invocation that will have its target and arguments filled in later.
107 /// 107 ///
108 /// The environment of the builder at that point is captured and should not 108 /// The environment of the builder at that point is captured and should not
109 /// be subsequently mutated until the jump is resolved. 109 /// be subsequently mutated until the jump is resolved.
110 class JumpCollector { 110 class JumpCollector {
111 final JumpTarget target; 111 final JumpTarget target;
112 final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[]; 112 final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[];
113 final List<Environment> _environments = <Environment>[]; 113 final List<Environment> _environments = <Environment>[];
114 final List<Iterable<LocalVariableElement>> boxedTryVariables =
115 <Iterable<LocalVariableElement>>[];
114 116
115 JumpCollector(this.target); 117 JumpCollector(this.target);
116 118
117 bool get isEmpty => _invocations.isEmpty; 119 bool get isEmpty => _invocations.isEmpty;
118 int get length => _invocations.length; 120 int get length => _invocations.length;
119 List<ir.InvokeContinuation> get invocations => _invocations; 121 List<ir.InvokeContinuation> get invocations => _invocations;
120 List<Environment> get environments => _environments; 122 List<Environment> get environments => _environments;
121 123
122 void addJump(IrBuilder builder) { 124 void addJump(IrBuilder builder) {
125 // Unbox all variables that were boxed on entry to try blocks between the
126 // jump and the target.
127 for (Iterable<LocalVariableElement> boxedOnEntry in boxedTryVariables) {
128 for (LocalVariableElement variable in boxedOnEntry) {
129 assert(builder.isInMutableVariable(variable));
130 ir.Primitive value = builder.buildLocalGet(variable);
131 builder.environment.update(variable, value);
132 }
133 }
123 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized(); 134 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized();
124 builder.add(invoke); 135 builder.add(invoke);
125 _invocations.add(invoke); 136 _invocations.add(invoke);
126 _environments.add(builder.environment); 137 _environments.add(builder.environment);
127 builder._current = null; 138 builder._current = null;
128 // TODO(kmillikin): Can we set builder.environment to null to make it 139 // TODO(kmillikin): Can we set builder.environment to null to make it
129 // less likely to mutate it? 140 // less likely to mutate it?
130 } 141 }
142
143 /// Add a set of variables that were boxed on entry to a try block.
144 ///
145 /// Jumps from a try block to targets outside have to unbox the variables
146 /// that were boxed on entry before invoking the target continuation. Call
147 /// this function before translating a try block and call [leaveTry] after
148 /// translating it.
149 void enterTry(Iterable<LocalVariableElement> boxedOnEntry) {
150 // The boxed variables are maintained as a stack to make leaving easy.
151 boxedTryVariables.add(boxedOnEntry);
152 }
153
154 /// Remove the most recently added set of variables boxed on entry to a try
155 /// block.
156 ///
157 /// Call [enterTry] before translating a try block and call this function
158 /// after translating it.
159 void leaveTry() {
160 boxedTryVariables.removeLast();
161 }
131 } 162 }
132 163
133 /// Function for building a node in the context of the current builder. 164 /// Function for building a node in the context of the current builder.
134 typedef ir.Node BuildFunction(node); 165 typedef ir.Node BuildFunction(node);
135 166
136 /// Function for building nodes in the context of the provided [builder]. 167 /// Function for building nodes in the context of the provided [builder].
137 typedef ir.Node SubbuildFunction(IrBuilder builder); 168 typedef ir.Node SubbuildFunction(IrBuilder builder);
138 169
139 /// Mixin that provides encapsulated access to nested builders. 170 /// Mixin that provides encapsulated access to nested builders.
140 abstract class IrBuilderMixin<N> { 171 abstract class IrBuilderMixin<N> {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 IrBuilderDelimitedState(this.constantSystem, this.currentElement); 232 IrBuilderDelimitedState(this.constantSystem, this.currentElement);
202 } 233 }
203 234
204 /// A factory for building the cps IR. 235 /// A factory for building the cps IR.
205 /// 236 ///
206 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured 237 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured
207 /// variables in different ways. 238 /// variables in different ways.
208 abstract class IrBuilder { 239 abstract class IrBuilder {
209 IrBuilder _makeInstance(); 240 IrBuilder _makeInstance();
210 241
242 /// A map from TryStatements in the AST to their analysis information.
243 ///
244 /// This includes which variables should be copied into [ir.MutableVariable]s
245 /// on entry to the try and copied out on exit.
246 Map<ast.TryStatement, TryStatementInfo> get tryStatements;
247
248 /// The set of local variables that will spend their lifetime as
249 /// [ir.MutableVariable]s due to being captured by a nested function.
250 Set<Local> get mutableCapturedVariables;
251
252 /// True if [local] should currently be accessed from a [ir.MutableVariable].
253 bool isInMutableVariable(Local local);
254
255 /// Creates a [ir.MutableVariable] for the given local.
256 void makeMutableVariable(Local local);
257
258 /// Remove an [ir.MutableVariable] for a local.
259 ///
260 /// Subsequent access to the local will be direct rather than through the
261 /// mutable variable. This is used for variables that do not spend their
262 /// entire lifetime as mutable variables (e.g., variables that are boxed
263 /// in mutable variables for a try block).
264 void removeMutableVariable(Local local);
265
211 void declareLocalVariable(LocalVariableElement element, 266 void declareLocalVariable(LocalVariableElement element,
212 {ir.Primitive initialValue}); 267 {ir.Primitive initialValue});
213 ir.Primitive buildLocalGet(LocalElement element); 268 ir.Primitive buildLocalGet(LocalElement element);
214 ir.Primitive buildLocalSet(LocalElement element, ir.Primitive value); 269 ir.Primitive buildLocalSet(LocalElement element, ir.Primitive value);
215 270
216 /// Called when entering a nested function with free variables. 271 /// Called when entering a nested function with free variables.
217 /// 272 ///
218 /// The free variables must subsequently be accessible using [buildLocalGet] 273 /// The free variables must subsequently be accessible using [buildLocalGet]
219 /// and [buildLocalSet]. 274 /// and [buildLocalSet].
220 void _enterClosureEnvironment(ClosureEnvironment env); 275 void _enterClosureEnvironment(ClosureEnvironment env);
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 environment = thenBuilder.environment; 864 environment = thenBuilder.environment;
810 } else if (elseBuilder.isOpen) { 865 } else if (elseBuilder.isOpen) {
811 if (elseBuilder._root != null) _current = elseBuilder._current; 866 if (elseBuilder._root != null) _current = elseBuilder._current;
812 environment = elseBuilder.environment; 867 environment = elseBuilder.environment;
813 } else { 868 } else {
814 _current = null; 869 _current = null;
815 } 870 }
816 } 871 }
817 } 872 }
818 873
874 void jumpTo(ir.Continuation continuation) {
875 assert(isOpen);
876 assert(environment.length >= continuation.parameters.length);
877 ir.InvokeContinuation jump = new ir.InvokeContinuation.uninitialized();
878 jump.continuation = new ir.Reference(continuation);
879 jump.arguments = new List<ir.Reference>.generate(
880 continuation.parameters.length, (i) {
881 return new ir.Reference(environment[i]);
882 });
883 add(jump);
884 _current = null;
885 }
886
819 /// Invoke a join-point continuation that contains arguments for all local 887 /// Invoke a join-point continuation that contains arguments for all local
820 /// variables. 888 /// variables.
821 /// 889 ///
822 /// Given the continuation and a list of uninitialized invocations, fill 890 /// Given the continuation and a list of uninitialized invocations, fill
823 /// in each invocation with the continuation and appropriate arguments. 891 /// in each invocation with the continuation and appropriate arguments.
824 void invokeFullJoin(ir.Continuation join, 892 void invokeFullJoin(ir.Continuation join,
825 JumpCollector jumps, 893 JumpCollector jumps,
826 {recursive: false}) { 894 {recursive: false}) {
895 // TODO(kmillikin): If the JumpCollector collected open IrBuilders instead
896 // of pairs of invocations and environments, we could use IrBuilder.jumpTo
897 // here --- the code is almost the same.
827 join.isRecursive = recursive; 898 join.isRecursive = recursive;
828 for (int i = 0; i < jumps.length; ++i) { 899 for (int i = 0; i < jumps.length; ++i) {
829 Environment currentEnvironment = jumps.environments[i]; 900 Environment currentEnvironment = jumps.environments[i];
830 ir.InvokeContinuation invoke = jumps.invocations[i]; 901 ir.InvokeContinuation invoke = jumps.invocations[i];
831 invoke.continuation = new ir.Reference(join); 902 invoke.continuation = new ir.Reference(join);
832 invoke.arguments = new List<ir.Reference>.generate( 903 invoke.arguments = new List<ir.Reference>.generate(
833 join.parameters.length, 904 join.parameters.length,
834 (i) => new ir.Reference(currentEnvironment[i])); 905 (i) => new ir.Reference(currentEnvironment[i]));
835 invoke.isRecursive = recursive; 906 invoke.isRecursive = recursive;
836 } 907 }
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 return join; 1582 return join;
1512 } 1583 }
1513 } 1584 }
1514 1585
1515 /// Shared state between DartIrBuilders within the same method. 1586 /// Shared state between DartIrBuilders within the same method.
1516 class DartIrBuilderSharedState { 1587 class DartIrBuilderSharedState {
1517 /// Maps local variables to their corresponding [MutableVariable] object. 1588 /// Maps local variables to their corresponding [MutableVariable] object.
1518 final Map<Local, ir.MutableVariable> local2mutable = 1589 final Map<Local, ir.MutableVariable> local2mutable =
1519 <Local, ir.MutableVariable>{}; 1590 <Local, ir.MutableVariable>{};
1520 1591
1521 final DartCapturedVariableInfo capturedVariables; 1592 final DartCapturedVariables capturedVariables;
1522 1593
1523 /// Creates a [MutableVariable] for the given local. 1594 /// Creates a [MutableVariable] for the given local.
1524 void makeMutableVariable(Local local) { 1595 void makeMutableVariable(Local local) {
1525 ir.MutableVariable variable = 1596 ir.MutableVariable variable =
1526 new ir.MutableVariable(local.executableContext, local); 1597 new ir.MutableVariable(local.executableContext, local);
1527 local2mutable[local] = variable; 1598 local2mutable[local] = variable;
1528 } 1599 }
1529 1600
1530 /// [MutableVariable]s that should temporarily be treated as registers. 1601 /// [MutableVariable]s that should temporarily be treated as registers.
1531 final Set<Local> registerizedMutableVariables = new Set<Local>(); 1602 final Set<Local> registerizedMutableVariables = new Set<Local>();
(...skipping 11 matching lines...) Expand all
1543 /// Captured variables are translated to ref cells (see [MutableVariable]) 1614 /// Captured variables are translated to ref cells (see [MutableVariable])
1544 /// using [GetMutableVariable] and [SetMutableVariable]. 1615 /// using [GetMutableVariable] and [SetMutableVariable].
1545 class DartIrBuilder extends IrBuilder { 1616 class DartIrBuilder extends IrBuilder {
1546 final DartIrBuilderSharedState dartState; 1617 final DartIrBuilderSharedState dartState;
1547 1618
1548 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState); 1619 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState);
1549 DartIrBuilder._blank(this.dartState); 1620 DartIrBuilder._blank(this.dartState);
1550 1621
1551 DartIrBuilder(ConstantSystem constantSystem, 1622 DartIrBuilder(ConstantSystem constantSystem,
1552 ExecutableElement currentElement, 1623 ExecutableElement currentElement,
1553 DartCapturedVariableInfo capturedVariables) 1624 DartCapturedVariables capturedVariables)
1554 : dartState = new DartIrBuilderSharedState(capturedVariables) { 1625 : dartState = new DartIrBuilderSharedState(capturedVariables) {
1555 _init(constantSystem, currentElement); 1626 _init(constantSystem, currentElement);
1556 } 1627 }
1557 1628
1558 /// True if [local] should currently be accessed from a [MutableVariable]. 1629 Map<ast.TryStatement, TryStatementInfo> get tryStatements {
1630 return dartState.capturedVariables.tryStatements;
1631 }
1632
1633 Set<Local> get mutableCapturedVariables {
1634 return dartState.capturedVariables.capturedVariables;
1635 }
1636
1559 bool isInMutableVariable(Local local) { 1637 bool isInMutableVariable(Local local) {
1560 return dartState.local2mutable.containsKey(local) && 1638 return dartState.local2mutable.containsKey(local) &&
1561 !dartState.registerizedMutableVariables.contains(local); 1639 !dartState.registerizedMutableVariables.contains(local);
1562 } 1640 }
1563 1641
1642 void makeMutableVariable(Local local) {
1643 dartState.makeMutableVariable(local);
1644 }
1645
1646 void removeMutableVariable(Local local) {
1647 dartState.local2mutable.remove(local);
1648 }
1649
1564 /// Gets the [MutableVariable] containing the value of [local]. 1650 /// Gets the [MutableVariable] containing the value of [local].
1565 ir.MutableVariable getMutableVariable(Local local) { 1651 ir.MutableVariable getMutableVariable(Local local) {
1566 return dartState.local2mutable[local]; 1652 return dartState.local2mutable[local];
1567 } 1653 }
1568 1654
1569 void _enterScope(ClosureScope scope) { 1655 void _enterScope(ClosureScope scope) {
1570 assert(scope == null); 1656 assert(scope == null);
1571 } 1657 }
1572 1658
1573 void _enterClosureEnvironment(ClosureEnvironment env) { 1659 void _enterClosureEnvironment(ClosureEnvironment env) {
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1727 final JsIrBuilderSharedState jsState; 1813 final JsIrBuilderSharedState jsState;
1728 1814
1729 IrBuilder _makeInstance() => new JsIrBuilder._blank(jsState); 1815 IrBuilder _makeInstance() => new JsIrBuilder._blank(jsState);
1730 JsIrBuilder._blank(this.jsState); 1816 JsIrBuilder._blank(this.jsState);
1731 1817
1732 JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement) 1818 JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement)
1733 : jsState = new JsIrBuilderSharedState() { 1819 : jsState = new JsIrBuilderSharedState() {
1734 _init(constantSystem, currentElement); 1820 _init(constantSystem, currentElement);
1735 } 1821 }
1736 1822
1823 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null;
1824 Set<Local> get mutableCapturedVariables => null;
1825 bool isInMutableVariable(Local local) => false;
1826 void makeMutableVariable(Local local) {}
1827 void removeMutableVariable(Local local) {}
1828
1737 void _enterClosureEnvironment(ClosureEnvironment env) { 1829 void _enterClosureEnvironment(ClosureEnvironment env) {
1738 if (env == null) return; 1830 if (env == null) return;
1739 1831
1740 // Obtain a reference to the function object (this). 1832 // Obtain a reference to the function object (this).
1741 ir.Primitive thisPrim = new ir.This(); 1833 ir.Primitive thisPrim = new ir.This();
1742 add(new ir.LetPrim(thisPrim)); 1834 add(new ir.LetPrim(thisPrim));
1743 1835
1744 // Obtain access to the free variables. 1836 // Obtain access to the free variables.
1745 env.freeVariables.forEach((Local local, ClosureLocation location) { 1837 env.freeVariables.forEach((Local local, ClosureLocation location) {
1746 if (location.isBox) { 1838 if (location.isBox) {
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
2005 /// If non-null, [thisLocal] has an entry in [freeVariables] describing where 2097 /// If non-null, [thisLocal] has an entry in [freeVariables] describing where
2006 /// to find the captured value of `this`. 2098 /// to find the captured value of `this`.
2007 final ThisLocal thisLocal; 2099 final ThisLocal thisLocal;
2008 2100
2009 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location. 2101 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location.
2010 final Map<Local, ClosureLocation> freeVariables; 2102 final Map<Local, ClosureLocation> freeVariables;
2011 2103
2012 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); 2104 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables);
2013 } 2105 }
2014 2106
2015 /// Information about which variables are captured by a nested function. 2107 class TryStatementInfo {
2016 /// 2108 final Set<LocalVariableElement> declared = new Set<LocalVariableElement>();
2017 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and 2109 final Set<LocalVariableElement> boxedOnEntry =
2018 /// [ClosureEnvironment]. 2110 new Set<LocalVariableElement>();
2019 abstract class DartCapturedVariableInfo {
2020 Iterable<Local> get capturedVariables;
2021 } 2111 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698