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

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

Issue 846353002: Dart2dart: Support for-loop variables captured in loop body. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 /// [nodes] in its context using [build]. 172 /// [nodes] in its context using [build].
173 // TODO(johnniwinther): Type [nodes] as `Iterable<N>` when `NodeList` uses 173 // TODO(johnniwinther): Type [nodes] as `Iterable<N>` when `NodeList` uses
174 // `List` instead of `Link`. 174 // `List` instead of `Link`.
175 SubbuildFunction subbuildSequence(/*Iterable<N>*/ nodes) { 175 SubbuildFunction subbuildSequence(/*Iterable<N>*/ nodes) {
176 return (IrBuilder builder) { 176 return (IrBuilder builder) {
177 return withBuilder(builder, () => builder.buildSequence(nodes, build)); 177 return withBuilder(builder, () => builder.buildSequence(nodes, build));
178 }; 178 };
179 } 179 }
180 } 180 }
181 181
182 /// Shared state between IrBuilders of nested functions.
183 class IrBuilderClosureState {
184 /// Maps local variables to their corresponding [ClosureVariable] object.
185 final Map<Local, ir.ClosureVariable> local2closure =
186 <Local, ir.ClosureVariable>{};
187
188 /// Maps functions to the list of closure variables declared in that function.
189 final Map<ExecutableElement, List<ir.ClosureVariable>> function2closures =
190 <ExecutableElement, List<ir.ClosureVariable>>{};
191
192 /// Returns the closure variables declared in the given function.
193 List<ir.ClosureVariable> getClosureList(ExecutableElement element) {
194 return function2closures.putIfAbsent(element, () => <ir.ClosureVariable>[]);
195 }
196
197 /// Creates a closure variable for the given local.
198 void makeClosureVariable(Local local) {
199 ir.ClosureVariable variable =
200 new ir.ClosureVariable(local.executableContext, local);
201 local2closure[local] = variable;
202 getClosureList(local.executableContext).add(variable);
203 }
204 }
205
206 /// Shared state between delimited IrBuilders within the same function. 182 /// Shared state between delimited IrBuilders within the same function.
207 class IrBuilderSharedState { 183 class IrBuilderDelimitedState {
208 final ConstantSystem constantSystem; 184 final ConstantSystem constantSystem;
209 185
210 /// A stack of collectors for breaks. 186 /// A stack of collectors for breaks.
211 final List<JumpCollector> breakCollectors = <JumpCollector>[]; 187 final List<JumpCollector> breakCollectors = <JumpCollector>[];
212 188
213 /// A stack of collectors for continues. 189 /// A stack of collectors for continues.
214 final List<JumpCollector> continueCollectors = <JumpCollector>[]; 190 final List<JumpCollector> continueCollectors = <JumpCollector>[];
215 191
216 final List<ConstDeclaration> localConstants = <ConstDeclaration>[]; 192 final List<ConstDeclaration> localConstants = <ConstDeclaration>[];
217 193
218 final ExecutableElement currentElement; 194 final ExecutableElement currentElement;
219 195
220 final ir.Continuation returnContinuation = new ir.Continuation.retrn(); 196 final ir.Continuation returnContinuation = new ir.Continuation.retrn();
221 197
222 final List<ir.Definition> functionParameters = <ir.Definition>[]; 198 final List<ir.Definition> functionParameters = <ir.Definition>[];
223 199
224 /// Maps boxed locals to their location. These locals are not part of 200 IrBuilderDelimitedState(this.constantSystem, this.currentElement);
225 /// the environment.
226 final Map<Local, ClosureLocation> boxedVariables = {};
227
228 /// If non-null, this refers to the receiver (`this`) in the enclosing method.
229 ir.Primitive receiver;
230
231 IrBuilderSharedState(this.constantSystem, this.currentElement);
232 } 201 }
233 202
234 /// A factory for building the cps IR. 203 /// A factory for building the cps IR.
235 /// 204 ///
236 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured 205 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured
237 /// variables in different ways. 206 /// variables in different ways.
238 abstract class IrBuilder { 207 abstract class IrBuilder {
239 IrBuilder _makeInstance(); 208 IrBuilder _makeInstance();
240 209
241 void declareLocalVariable(LocalVariableElement element, 210 void declareLocalVariable(LocalVariableElement element,
242 {ir.Primitive initialValue}); 211 {ir.Primitive initialValue});
243 void declareLocalFunction(LocalFunctionElement element, Object function); 212 void declareLocalFunction(LocalFunctionElement element, Object function);
244 ir.Primitive buildFunctionExpression(Object function); 213 ir.Primitive buildFunctionExpression(Object function);
245 ir.Primitive buildLocalGet(LocalElement element); 214 ir.Primitive buildLocalGet(LocalElement element);
246 ir.Primitive buildLocalSet(LocalElement element, ir.Primitive value); 215 ir.Primitive buildLocalSet(LocalElement element, ir.Primitive value);
247 216
248 /// Called when entering a nested function with free variables. 217 /// Called when entering a nested function with free variables.
249 /// The free variables should subsequently be accessible using [buildLocalGet] 218 ///
219 /// The free variables must subsequently be accessible using [buildLocalGet]
250 /// and [buildLocalSet]. 220 /// and [buildLocalSet].
251 void _buildClosureEnvironmentSetup(ClosureEnvironment env); 221 void _enterClosureEnvironment(ClosureEnvironment env);
asgerf 2015/01/14 08:55:57 I reverted to the "enterXXX" naming scheme because
252 222
253 /// Enter a scope that declares boxed variables. The boxed variables must 223 /// Called when entering a function body or loop body.
254 /// subsequently be accessible using [buildLocalGet], [buildLocalSet], etc. 224 ///
255 void _buildClosureScopeSetup(ClosureScope scope); 225 /// This does not called for for-loops, which instead use the methods
sigurdm 2015/01/14 12:02:48 This 'is' not
asgerf 2015/01/14 12:08:21 Thanks.
226 /// [_enterForLoopInitializer], [_enterForLoopBody], and [_enterForLoopUpdate]
227 /// due to their special scoping rules.
228 ///
229 /// The boxed variables declared in this scope must subsequently be available
230 /// using [buildLocalGet], [buildLocalSet], etc.
231 void _enterScope(ClosureScope scope);
232
233 /// Called before building the initializer of a for-loop.
234 ///
235 /// The loop variables will subsequently be declared using
236 /// [declareLocalVariable].
237 void _enterForLoopInitializer(ClosureScope scope,
238 List<LocalElement> loopVariables);
239
240 /// Called before building the body of a for-loop.
241 void _enterForLoopBody(ClosureScope scope,
242 List<LocalElement> loopVariables);
243
244 /// Called before building the update of a for-loop.
245 void _enterForLoopUpdate(ClosureScope scope,
246 List<LocalElement> loopVariables);
256 247
257 /// Add the given function parameter to the IR, and bind it in the environment 248 /// Add the given function parameter to the IR, and bind it in the environment
258 /// or put it in its box, if necessary. 249 /// or put it in its box, if necessary.
259 void _createFunctionParameter(ParameterElement parameterElement); 250 void _createFunctionParameter(ParameterElement parameterElement);
260 251
261 /// Called before the update expression of a for-loop. A new box should be 252 /// Returns the list of closure variables declared in the given function or
262 /// created for [scope] and the values from the old box should be copied over. 253 /// field initializer.
263 void _migrateLoopVariables(ClosureScope scope); 254 List<ir.ClosureVariable> _getDeclaredClosureVariables(ExecutableElement elm);
255
256 /// Creates an access to the receiver from the current (or enclosing) method.
257 ///
258 /// If inside a closure class, [buildThis] will redirect access through
259 /// closure fields in order to access the receiver from the enclosing method.
260 ir.Primitive buildThis();
264 261
265 // TODO(johnniwinther): Make these field final and remove the default values 262 // TODO(johnniwinther): Make these field final and remove the default values
266 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin. 263 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
267 264
268 final List<ir.Parameter> _parameters = <ir.Parameter>[]; 265 final List<ir.Parameter> _parameters = <ir.Parameter>[];
269 266
270 IrBuilderSharedState state; 267 IrBuilderDelimitedState state;
271
272 IrBuilderClosureState closure;
273 268
274 /// A map from variable indexes to their values. 269 /// A map from variable indexes to their values.
275 /// 270 ///
276 /// [BoxLocal]s map to their box. [LocalElement]s that are boxed are not 271 /// [BoxLocal]s map to their box. [LocalElement]s that are boxed are not
277 /// in the map; look up their [BoxLocal] instead. 272 /// in the map; look up their [BoxLocal] instead.
278 Environment environment; 273 Environment environment;
279 274
280 // The IR builder maintains a context, which is an expression with a hole in 275 // The IR builder maintains a context, which is an expression with a hole in
281 // it. The hole represents the focus where new expressions can be added. 276 // it. The hole represents the focus where new expressions can be added.
282 // The context is implemented by 'root' which is the root of the expression 277 // The context is implemented by 'root' which is the root of the expression
(...skipping 16 matching lines...) Expand all
299 // We do not pass contexts as arguments or return them. Rather we use the 294 // We do not pass contexts as arguments or return them. Rather we use the
300 // current context (root, current) as the visitor state and mutate current. 295 // current context (root, current) as the visitor state and mutate current.
301 // Visiting a statement returns null; visiting an expression returns the 296 // Visiting a statement returns null; visiting an expression returns the
302 // primitive denoting its value. 297 // primitive denoting its value.
303 298
304 ir.Expression _root = null; 299 ir.Expression _root = null;
305 ir.Expression _current = null; 300 ir.Expression _current = null;
306 301
307 /// Initialize a new top-level IR builder. 302 /// Initialize a new top-level IR builder.
308 void _init(ConstantSystem constantSystem, ExecutableElement currentElement) { 303 void _init(ConstantSystem constantSystem, ExecutableElement currentElement) {
309 state = new IrBuilderSharedState(constantSystem, currentElement); 304 state = new IrBuilderDelimitedState(constantSystem, currentElement);
310 closure = new IrBuilderClosureState();
311 environment = new Environment.empty(); 305 environment = new Environment.empty();
312 } 306 }
313 307
314 /// Construct a delimited visitor for visiting a subtree. 308 /// Construct a delimited visitor for visiting a subtree.
315 /// 309 ///
316 /// The delimited visitor has its own compile-time environment mapping 310 /// The delimited visitor has its own compile-time environment mapping
317 /// local variables to their values, which is initially a copy of the parent 311 /// local variables to their values, which is initially a copy of the parent
318 /// environment. It has its own context for building an IR expression, so 312 /// environment. It has its own context for building an IR expression, so
319 /// the built expression is not plugged into the parent's context. 313 /// the built expression is not plugged into the parent's context.
320 IrBuilder makeDelimitedBuilder() { 314 IrBuilder makeDelimitedBuilder() {
321 return _makeInstance() 315 return _makeInstance()
322 ..state = state 316 ..state = state
323 ..closure = closure
324 ..environment = new Environment.from(environment); 317 ..environment = new Environment.from(environment);
325 } 318 }
326 319
327 /// Construct a visitor for a recursive continuation. 320 /// Construct a visitor for a recursive continuation.
328 /// 321 ///
329 /// The recursive continuation builder has fresh parameters (i.e. SSA phis) 322 /// The recursive continuation builder has fresh parameters (i.e. SSA phis)
330 /// for all the local variables in the parent, because the invocation sites 323 /// for all the local variables in the parent, because the invocation sites
331 /// of the continuation are not all known when the builder is created. The 324 /// of the continuation are not all known when the builder is created. The
332 /// recursive invocations will be passed values for all the local variables, 325 /// recursive invocations will be passed values for all the local variables,
333 /// which may be eliminated later if they are redundant---if they take on 326 /// which may be eliminated later if they are redundant---if they take on
334 /// the same value at all invocation sites. 327 /// the same value at all invocation sites.
335 IrBuilder makeRecursiveBuilder() { 328 IrBuilder makeRecursiveBuilder() {
336 IrBuilder inner = _makeInstance() 329 IrBuilder inner = _makeInstance()
337 ..state = state 330 ..state = state
338 ..closure = closure
339 ..environment = new Environment.empty(); 331 ..environment = new Environment.empty();
340 environment.index2variable.forEach(inner.createLocalParameter); 332 environment.index2variable.forEach(inner.createLocalParameter);
341 return inner; 333 return inner;
342 } 334 }
343 335
344 /// Construct a builder for an inner function. 336 /// Construct a builder for an inner function.
345 IrBuilder makeInnerFunctionBuilder(ExecutableElement currentElement) { 337 IrBuilder makeInnerFunctionBuilder(ExecutableElement currentElement) {
346 return _makeInstance() 338 return _makeInstance()
347 ..state = new IrBuilderSharedState(state.constantSystem, currentElement) 339 ..state = new IrBuilderDelimitedState(state.constantSystem, currentEleme nt)
348 ..closure = closure
349 ..environment = new Environment.empty(); 340 ..environment = new Environment.empty();
350 } 341 }
351 342
352 bool get isOpen => _root == null || _current != null; 343 bool get isOpen => _root == null || _current != null;
353 344
354 345
355 void buildFieldInitializerHeader({ClosureScope closureScope}) { 346 void buildFieldInitializerHeader({ClosureScope closureScope}) {
356 _buildClosureScopeSetup(closureScope); 347 _enterScope(closureScope);
357 } 348 }
358 349
359 void buildFunctionHeader(Iterable<ParameterElement> parameters, 350 void buildFunctionHeader(Iterable<ParameterElement> parameters,
360 {ClosureScope closureScope, 351 {ClosureScope closureScope,
361 ClosureEnvironment closureEnvironment}) { 352 ClosureEnvironment closureEnvironment}) {
362 _buildClosureEnvironmentSetup(closureEnvironment); 353 _enterClosureEnvironment(closureEnvironment);
363 _buildClosureScopeSetup(closureScope); 354 _enterScope(closureScope);
364 parameters.forEach(_createFunctionParameter); 355 parameters.forEach(_createFunctionParameter);
365 } 356 }
366 357
367 /// Creates a parameter for [local] and adds it to the current environment. 358 /// Creates a parameter for [local] and adds it to the current environment.
368 ir.Parameter createLocalParameter(Local local) { 359 ir.Parameter createLocalParameter(Local local) {
369 ir.Parameter parameter = new ir.Parameter(local); 360 ir.Parameter parameter = new ir.Parameter(local);
370 _parameters.add(parameter); 361 _parameters.add(parameter);
371 environment.extend(local, parameter); 362 environment.extend(local, parameter);
372 return parameter; 363 return parameter;
373 } 364 }
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 message: "Non-empty body for abstract method $element: $_root")); 599 message: "Non-empty body for abstract method $element: $_root"));
609 assert(invariant(element, state.localConstants.isEmpty, 600 assert(invariant(element, state.localConstants.isEmpty,
610 message: "Local constants for abstract method $element: " 601 message: "Local constants for abstract method $element: "
611 "${state.localConstants}")); 602 "${state.localConstants}"));
612 return new ir.FunctionDefinition.abstract( 603 return new ir.FunctionDefinition.abstract(
613 element, state.functionParameters, defaults); 604 element, state.functionParameters, defaults);
614 } else { 605 } else {
615 ir.RunnableBody body = makeRunnableBody(); 606 ir.RunnableBody body = makeRunnableBody();
616 return new ir.FunctionDefinition( 607 return new ir.FunctionDefinition(
617 element, state.functionParameters, body, 608 element, state.functionParameters, body,
618 state.localConstants, defaults, closure.getClosureList(element)); 609 state.localConstants, defaults,
610 _getDeclaredClosureVariables(element));
619 } 611 }
620 } 612 }
621 613
622 ir.ConstructorDefinition makeConstructorDefinition( 614 ir.ConstructorDefinition makeConstructorDefinition(
623 List<ConstantExpression> defaults, List<ir.Initializer> initializers) { 615 List<ConstantExpression> defaults, List<ir.Initializer> initializers) {
624 FunctionElement element = state.currentElement; 616 FunctionElement element = state.currentElement;
625 if (element.isExternal) { 617 if (element.isExternal) {
626 assert(invariant(element, _root == null, 618 assert(invariant(element, _root == null,
627 message: "Non-empty body for external constructor $element: $_root")); 619 message: "Non-empty body for external constructor $element: $_root"));
628 assert(invariant(element, state.localConstants.isEmpty, 620 assert(invariant(element, state.localConstants.isEmpty,
629 message: "Local constants for external constructor $element: " 621 message: "Local constants for external constructor $element: "
630 "${state.localConstants}")); 622 "${state.localConstants}"));
631 return new ir.ConstructorDefinition.abstract( 623 return new ir.ConstructorDefinition.abstract(
632 element, state.functionParameters, defaults); 624 element, state.functionParameters, defaults);
633 } 625 }
634 ir.RunnableBody body = makeRunnableBody(); 626 ir.RunnableBody body = makeRunnableBody();
635 return new ir.ConstructorDefinition( 627 return new ir.ConstructorDefinition(
636 element, state.functionParameters, body, initializers, 628 element, state.functionParameters, body, initializers,
637 state.localConstants, defaults, 629 state.localConstants, defaults,
638 closure.getClosureList(element)); 630 _getDeclaredClosureVariables(element));
639 } 631 }
640 632
641 /// Create a super invocation where the method name and the argument structure 633 /// Create a super invocation where the method name and the argument structure
642 /// are defined by [selector] and the argument values are defined by 634 /// are defined by [selector] and the argument values are defined by
643 /// [arguments]. 635 /// [arguments].
644 ir.Primitive buildSuperInvocation(Selector selector, 636 ir.Primitive buildSuperInvocation(Selector selector,
645 List<ir.Primitive> arguments) { 637 List<ir.Primitive> arguments) {
646 return _buildInvokeSuper(selector, arguments); 638 return _buildInvokeSuper(selector, arguments);
647 } 639 }
648 640
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 /// Creates a for loop in which the initializer, condition, body, update are 855 /// Creates a for loop in which the initializer, condition, body, update are
864 /// created by [buildInitializer], [buildCondition], [buildBody] and 856 /// created by [buildInitializer], [buildCondition], [buildBody] and
865 /// [buildUpdate], respectively. 857 /// [buildUpdate], respectively.
866 /// 858 ///
867 /// The jump [target] is used to identify which `break` and `continue` 859 /// The jump [target] is used to identify which `break` and `continue`
868 /// statements that have this `for` statement as their target. 860 /// statements that have this `for` statement as their target.
869 /// 861 ///
870 /// The [closureScope] identifies variables that should be boxed in this loop. 862 /// The [closureScope] identifies variables that should be boxed in this loop.
871 /// This includes variables declared inside the body of the loop as well as 863 /// This includes variables declared inside the body of the loop as well as
872 /// in the for-loop initializer. 864 /// in the for-loop initializer.
865 ///
866 /// [loopVariables] is the list of variable declared in the for-loop
sigurdm 2015/01/14 12:02:48 variable -> variables
asgerf 2015/01/14 12:08:21 Thanks again.
867 /// initializer.
873 void buildFor({SubbuildFunction buildInitializer, 868 void buildFor({SubbuildFunction buildInitializer,
874 SubbuildFunction buildCondition, 869 SubbuildFunction buildCondition,
875 SubbuildFunction buildBody, 870 SubbuildFunction buildBody,
876 SubbuildFunction buildUpdate, 871 SubbuildFunction buildUpdate,
877 JumpTarget target, 872 JumpTarget target,
878 ClosureScope closureScope}) { 873 ClosureScope closureScope,
874 List<LocalElement> loopVariables}) {
879 assert(isOpen); 875 assert(isOpen);
880 876
881 // For loops use four named continuations: the entry to the condition, 877 // For loops use four named continuations: the entry to the condition,
882 // the entry to the body, the loop exit, and the loop successor (break). 878 // the entry to the body, the loop exit, and the loop successor (break).
883 // The CPS translation of 879 // The CPS translation of
884 // [[for (initializer; condition; update) body; successor]] is: 880 // [[for (initializer; condition; update) body; successor]] is:
885 // 881 //
886 // [[initializer]]; 882 // [[initializer]];
887 // let cont loop(x, ...) = 883 // let cont loop(x, ...) =
888 // let prim cond = [[condition]] in 884 // let prim cond = [[condition]] in
889 // let cont break() = [[successor]] in 885 // let cont break() = [[successor]] in
890 // let cont exit() = break(v, ...) in 886 // let cont exit() = break(v, ...) in
891 // let cont body() = 887 // let cont body() =
892 // let cont continue(x, ...) = [[update]]; loop(v, ...) in 888 // let cont continue(x, ...) = [[update]]; loop(v, ...) in
893 // [[body]]; continue(v, ...) in 889 // [[body]]; continue(v, ...) in
894 // branch cond (body, exit) in 890 // branch cond (body, exit) in
895 // loop(v, ...) 891 // loop(v, ...)
896 // 892 //
897 // If there are no breaks in the body, the break continuation is inlined 893 // If there are no breaks in the body, the break continuation is inlined
898 // in the exit continuation (i.e., the translation of the successor 894 // in the exit continuation (i.e., the translation of the successor
899 // statement occurs in the exit continuation). If there is only one 895 // statement occurs in the exit continuation). If there is only one
900 // invocation of the continue continuation (i.e., no continues in the 896 // invocation of the continue continuation (i.e., no continues in the
901 // body), the continue continuation is inlined in the body. 897 // body), the continue continuation is inlined in the body.
902 898
903 // If the variables declared in the initializer must be boxed, we must 899 _enterForLoopInitializer(closureScope, loopVariables);
904 // create the box before entering the loop and renew the box at the end
905 // of the loop.
906 bool hasBoxedLoopVariables = closureScope != null &&
907 !closureScope.boxedLoopVariables.isEmpty;
908
909 // If a variable declared in the initializer must be boxed, we should
910 // create the box before initializing these variables.
911 // Otherwise, it is best to create the box inside the body so we don't have
912 // to create a box before the loop AND at the end of the loop.
913 if (hasBoxedLoopVariables) {
914 _buildClosureScopeSetup(closureScope);
915 }
916 900
917 buildInitializer(this); 901 buildInitializer(this);
918 902
919 IrBuilder condBuilder = makeRecursiveBuilder(); 903 IrBuilder condBuilder = makeRecursiveBuilder();
920 ir.Primitive condition = buildCondition(condBuilder); 904 ir.Primitive condition = buildCondition(condBuilder);
921 if (condition == null) { 905 if (condition == null) {
922 // If the condition is empty then the body is entered unconditionally. 906 // If the condition is empty then the body is entered unconditionally.
923 condition = condBuilder.buildBooleanLiteral(true); 907 condition = condBuilder.buildBooleanLiteral(true);
924 } 908 }
925 909
926 JumpCollector breakCollector = new JumpCollector(target); 910 JumpCollector breakCollector = new JumpCollector(target);
927 JumpCollector continueCollector = new JumpCollector(target); 911 JumpCollector continueCollector = new JumpCollector(target);
928 state.breakCollectors.add(breakCollector); 912 state.breakCollectors.add(breakCollector);
929 state.continueCollectors.add(continueCollector); 913 state.continueCollectors.add(continueCollector);
930 914
931 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); 915 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder();
932 916
933 // If we did not yet create a box for the boxed variables, we must create it 917 bodyBuilder._enterForLoopBody(closureScope, loopVariables);
934 // here. This saves us from
935 if (!hasBoxedLoopVariables) {
936 bodyBuilder._buildClosureScopeSetup(closureScope);
937 }
938 918
939 buildBody(bodyBuilder); 919 buildBody(bodyBuilder);
940 assert(state.breakCollectors.last == breakCollector); 920 assert(state.breakCollectors.last == breakCollector);
941 assert(state.continueCollectors.last == continueCollector); 921 assert(state.continueCollectors.last == continueCollector);
942 state.breakCollectors.removeLast(); 922 state.breakCollectors.removeLast();
943 state.continueCollectors.removeLast(); 923 state.continueCollectors.removeLast();
944 924
945 // The binding of the continue continuation should occur as late as 925 // The binding of the continue continuation should occur as late as
946 // possible, that is, at the nearest common ancestor of all the continue 926 // possible, that is, at the nearest common ancestor of all the continue
947 // sites in the body. However, that is difficult to compute here, so it 927 // sites in the body. However, that is difficult to compute here, so it
948 // is instead placed just outside the body of the body continuation. 928 // is instead placed just outside the body of the body continuation.
949 bool hasContinues = !continueCollector.isEmpty; 929 bool hasContinues = !continueCollector.isEmpty;
950 IrBuilder updateBuilder = hasContinues 930 IrBuilder updateBuilder = hasContinues
951 ? condBuilder.makeRecursiveBuilder() 931 ? condBuilder.makeRecursiveBuilder()
952 : bodyBuilder; 932 : bodyBuilder;
953 if (hasBoxedLoopVariables) { 933 updateBuilder._enterForLoopUpdate(closureScope, loopVariables);
954 updateBuilder._migrateLoopVariables(closureScope);
955 }
956 buildUpdate(updateBuilder); 934 buildUpdate(updateBuilder);
957 935
958 // Create body entry and loop exit continuations and a branch to them. 936 // Create body entry and loop exit continuations and a branch to them.
959 ir.Continuation bodyContinuation = new ir.Continuation([]); 937 ir.Continuation bodyContinuation = new ir.Continuation([]);
960 ir.Continuation exitContinuation = new ir.Continuation([]); 938 ir.Continuation exitContinuation = new ir.Continuation([]);
961 ir.LetCont branch = 939 ir.LetCont branch =
962 new ir.LetCont(exitContinuation, 940 new ir.LetCont(exitContinuation,
963 new ir.LetCont(bodyContinuation, 941 new ir.LetCont(bodyContinuation,
964 new ir.Branch(new ir.IsTrue(condition), 942 new ir.Branch(new ir.IsTrue(condition),
965 bodyContinuation, 943 bodyContinuation,
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1071 new ir.InvokeMethod(iterator, 1049 new ir.InvokeMethod(iterator,
1072 new Selector.call("moveNext", null, 0), 1050 new Selector.call("moveNext", null, 0),
1073 moveNextInvoked, emptyArguments))); 1051 moveNextInvoked, emptyArguments)));
1074 1052
1075 JumpCollector breakCollector = new JumpCollector(target); 1053 JumpCollector breakCollector = new JumpCollector(target);
1076 JumpCollector continueCollector = new JumpCollector(target); 1054 JumpCollector continueCollector = new JumpCollector(target);
1077 state.breakCollectors.add(breakCollector); 1055 state.breakCollectors.add(breakCollector);
1078 state.continueCollectors.add(continueCollector); 1056 state.continueCollectors.add(continueCollector);
1079 1057
1080 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); 1058 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder();
1081 bodyBuilder._buildClosureScopeSetup(closureScope); 1059 bodyBuilder._enterScope(closureScope);
1082 if (buildVariableDeclaration != null) { 1060 if (buildVariableDeclaration != null) {
1083 buildVariableDeclaration(bodyBuilder); 1061 buildVariableDeclaration(bodyBuilder);
1084 } 1062 }
1085 1063
1086 ir.Parameter currentValue = new ir.Parameter(null); 1064 ir.Parameter currentValue = new ir.Parameter(null);
1087 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); 1065 ir.Continuation currentInvoked = new ir.Continuation([currentValue]);
1088 bodyBuilder.add(new ir.LetCont(currentInvoked, 1066 bodyBuilder.add(new ir.LetCont(currentInvoked,
1089 new ir.InvokeMethod(iterator, new Selector.getter("current", null), 1067 new ir.InvokeMethod(iterator, new Selector.getter("current", null),
1090 currentInvoked, emptyArguments))); 1068 currentInvoked, emptyArguments)));
1091 if (Elements.isLocal(variableElement)) { 1069 if (Elements.isLocal(variableElement)) {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 // The condition and body are delimited. 1154 // The condition and body are delimited.
1177 IrBuilder condBuilder = makeRecursiveBuilder(); 1155 IrBuilder condBuilder = makeRecursiveBuilder();
1178 ir.Primitive condition = buildCondition(condBuilder); 1156 ir.Primitive condition = buildCondition(condBuilder);
1179 1157
1180 JumpCollector breakCollector = new JumpCollector(target); 1158 JumpCollector breakCollector = new JumpCollector(target);
1181 JumpCollector continueCollector = new JumpCollector(target); 1159 JumpCollector continueCollector = new JumpCollector(target);
1182 state.breakCollectors.add(breakCollector); 1160 state.breakCollectors.add(breakCollector);
1183 state.continueCollectors.add(continueCollector); 1161 state.continueCollectors.add(continueCollector);
1184 1162
1185 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder(); 1163 IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder();
1186 bodyBuilder._buildClosureScopeSetup(closureScope); 1164 bodyBuilder._enterScope(closureScope);
1187 buildBody(bodyBuilder); 1165 buildBody(bodyBuilder);
1188 assert(state.breakCollectors.last == breakCollector); 1166 assert(state.breakCollectors.last == breakCollector);
1189 assert(state.continueCollectors.last == continueCollector); 1167 assert(state.continueCollectors.last == continueCollector);
1190 state.breakCollectors.removeLast(); 1168 state.breakCollectors.removeLast();
1191 state.continueCollectors.removeLast(); 1169 state.continueCollectors.removeLast();
1192 1170
1193 // Create body entry and loop exit continuations and a branch to them. 1171 // Create body entry and loop exit continuations and a branch to them.
1194 ir.Continuation bodyContinuation = new ir.Continuation([]); 1172 ir.Continuation bodyContinuation = new ir.Continuation([]);
1195 ir.Continuation exitContinuation = new ir.Continuation([]); 1173 ir.Continuation exitContinuation = new ir.Continuation([]);
1196 ir.LetCont branch = 1174 ir.LetCont branch =
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
1427 new ir.LetCont(leftTrueContinuation, 1405 new ir.LetCont(leftTrueContinuation,
1428 new ir.LetCont(leftFalseContinuation, 1406 new ir.LetCont(leftFalseContinuation,
1429 new ir.Branch(new ir.IsTrue(leftValue), 1407 new ir.Branch(new ir.IsTrue(leftValue),
1430 leftTrueContinuation, 1408 leftTrueContinuation,
1431 leftFalseContinuation))))); 1409 leftFalseContinuation)))));
1432 // There is always a join parameter for the result value, because it 1410 // There is always a join parameter for the result value, because it
1433 // is different on at least two paths. 1411 // is different on at least two paths.
1434 return joinContinuation.parameters.last; 1412 return joinContinuation.parameters.last;
1435 } 1413 }
1436 1414
1437 /// Creates an access to the receiver from the current (or enclosing) method.
1438 ///
1439 /// If inside a closure class, [buildThis] will redirect access through
1440 /// closure fields in order to access the receiver from the enclosing method.
1441 ir.Primitive buildThis() {
1442 if (state.receiver != null) return state.receiver;
1443 ir.Primitive thisPrim = new ir.This();
1444 add(new ir.LetPrim(thisPrim));
1445 return thisPrim;
1446 }
asgerf 2015/01/14 08:55:57 Moved to subclass because 'this' capture is JS-spe
1447
1448 /// Create a non-recursive join-point continuation. 1415 /// Create a non-recursive join-point continuation.
1449 /// 1416 ///
1450 /// Given the environment length at the join point and a list of 1417 /// Given the environment length at the join point and a list of
1451 /// jumps that should reach the join point, create a join-point 1418 /// jumps that should reach the join point, create a join-point
1452 /// continuation. The join-point continuation has a parameter for each 1419 /// continuation. The join-point continuation has a parameter for each
1453 /// variable that has different values reaching on different paths. 1420 /// variable that has different values reaching on different paths.
1454 /// 1421 ///
1455 /// The jumps are uninitialized [ir.InvokeContinuation] expressions. 1422 /// The jumps are uninitialized [ir.InvokeContinuation] expressions.
1456 /// They are filled in with the target continuation and appropriate 1423 /// They are filled in with the target continuation and appropriate
1457 /// arguments. 1424 /// arguments.
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 for (int i = 0; i < environment.length; ++i) { 1511 for (int i = 0; i < environment.length; ++i) {
1545 if (common[i] == null) { 1512 if (common[i] == null) {
1546 environment.index2value[i] = parameters[index++]; 1513 environment.index2value[i] = parameters[index++];
1547 } 1514 }
1548 } 1515 }
1549 1516
1550 return join; 1517 return join;
1551 } 1518 }
1552 } 1519 }
1553 1520
1521 /// Shared state between DartIrBuilders within the same method.
1522 class DartIrBuilderSharedState {
1523 /// Maps local variables to their corresponding [ClosureVariable] object.
1524 final Map<Local, ir.ClosureVariable> local2closure =
1525 <Local, ir.ClosureVariable>{};
1526
1527 /// Maps functions to the list of closure variables declared in that function.
1528 final Map<ExecutableElement, List<ir.ClosureVariable>> function2closures =
1529 <ExecutableElement, List<ir.ClosureVariable>>{};
1530
1531 final ClosureVariableInfo closureVariables;
1532
1533 /// Returns the closure variables declared in the given function.
1534 List<ir.ClosureVariable> getClosureList(ExecutableElement element) {
1535 return function2closures.putIfAbsent(element, () => <ir.ClosureVariable>[]);
1536 }
1537
1538 /// Creates a closure variable for the given local.
1539 void makeClosureVariable(Local local) {
1540 ir.ClosureVariable variable =
1541 new ir.ClosureVariable(local.executableContext, local);
1542 local2closure[local] = variable;
1543 getClosureList(local.executableContext).add(variable);
1544 }
1545
1546 /// Closure variables that should temporarily be treated as registers.
1547 final Set<Local> registerizedClosureVariables = new Set<Local>();
1548
1549 DartIrBuilderSharedState(this.closureVariables) {
1550 closureVariables.capturedVariables.forEach(makeClosureVariable);
1551 }
1552 }
1553
1554 /// Dart-specific subclass of [IrBuilder]. 1554 /// Dart-specific subclass of [IrBuilder].
1555 /// 1555 ///
1556 /// Inner functions are represented by a [FunctionDefinition] with the 1556 /// Inner functions are represented by a [FunctionDefinition] with the
1557 /// IR for the inner function nested inside. 1557 /// IR for the inner function nested inside.
1558 /// 1558 ///
1559 /// Captured variables are translated to ref cells (see [ClosureVariable]) 1559 /// Captured variables are translated to ref cells (see [ClosureVariable])
1560 /// using [GetClosureVariable] and [SetClosureVariable]. 1560 /// using [GetClosureVariable] and [SetClosureVariable].
1561 class DartIrBuilder extends IrBuilder { 1561 class DartIrBuilder extends IrBuilder {
1562 ClosureVariableInfo closureVariables; 1562 final DartIrBuilderSharedState dartState;
1563 1563
1564 IrBuilder _makeInstance() => new DartIrBuilder._blank(closureVariables); 1564 IrBuilder _makeInstance() => new DartIrBuilder._blank(dartState);
1565 DartIrBuilder._blank(this.closureVariables); 1565 DartIrBuilder._blank(this.dartState);
1566 1566
1567 DartIrBuilder(ConstantSystem constantSystem, 1567 DartIrBuilder(ConstantSystem constantSystem,
1568 ExecutableElement currentElement, 1568 ExecutableElement currentElement,
1569 this.closureVariables) { 1569 ClosureVariableInfo closureVariables)
1570 : dartState = new DartIrBuilderSharedState(closureVariables) {
1570 _init(constantSystem, currentElement); 1571 _init(constantSystem, currentElement);
1571 closureVariables.capturedVariables.forEach(closure.makeClosureVariable);
1572 } 1572 }
1573 1573
1574 /// True if [local] is stored in a [ClosureVariable]. 1574 /// True if [local] should currently be accessed from a [ClosureVariable].
1575 bool isInClosureVariable(Local local) { 1575 bool isInClosureVariable(Local local) {
1576 return closure.local2closure.containsKey(local); 1576 return dartState.local2closure.containsKey(local) &&
1577 !dartState.registerizedClosureVariables.contains(local);
1577 } 1578 }
1578 1579
1579 /// Gets the [ClosureVariable] containing the value of [local]. 1580 /// Gets the [ClosureVariable] containing the value of [local].
1580 ir.ClosureVariable getClosureVariable(Local local) { 1581 ir.ClosureVariable getClosureVariable(Local local) {
1581 return closure.local2closure[local]; 1582 return dartState.local2closure[local];
1582 } 1583 }
1583 1584
1584 void _buildClosureScopeSetup(ClosureScope scope) { 1585 void _enterScope(ClosureScope scope) {
1585 assert(scope == null); 1586 assert(scope == null);
1586 } 1587 }
1587 1588
1588 void _buildClosureEnvironmentSetup(ClosureEnvironment env) { 1589 void _enterClosureEnvironment(ClosureEnvironment env) {
1589 assert(env == null); 1590 assert(env == null);
1590 } 1591 }
1591 1592
1592 void _migrateLoopVariables(ClosureScope scope) { 1593 void _enterForLoopInitializer(ClosureScope scope,
1594 List<LocalElement> loopVariables) {
1593 assert(scope == null); 1595 assert(scope == null);
1596 for (LocalElement loopVariable in loopVariables) {
1597 if (dartState.local2closure.containsKey(loopVariable)) {
1598 // Temporarily keep the loop variable in a primitive.
1599 // The loop variable will be added to environment when
1600 // [declareLocalVariable] is called.
1601 dartState.registerizedClosureVariables.add(loopVariable);
1602 }
1603 }
1604 }
1605
1606 void _enterForLoopBody(ClosureScope scope,
1607 List<LocalElement> loopVariables) {
1608 assert(scope == null);
1609 for (LocalElement loopVariable in loopVariables) {
1610 if (dartState.local2closure.containsKey(loopVariable)) {
1611 // Move from primitive into ClosureVariable.
1612 dartState.registerizedClosureVariables.remove(loopVariable);
1613 add(new ir.SetClosureVariable(getClosureVariable(loopVariable),
1614 environment.lookup(loopVariable),
1615 isDeclaration: true));
1616 }
1617 }
1618 }
1619
1620 void _enterForLoopUpdate(ClosureScope scope,
1621 List<LocalElement> loopVariables) {
1622 assert(scope == null);
1623 // Move captured loop variables back into the local environment.
1624 // The update expression will use the values we put in the environment,
1625 // and then the environments for the initializer and update will be
1626 // joined at the head of the body.
1627 for (LocalElement loopVariable in loopVariables) {
1628 if (isInClosureVariable(loopVariable)) {
1629 ir.ClosureVariable closureVariable = getClosureVariable(loopVariable);
1630 ir.Primitive get = new ir.GetClosureVariable(closureVariable);
1631 add(new ir.LetPrim(get));
1632 environment.update(loopVariable, get);
1633 dartState.registerizedClosureVariables.add(loopVariable);
1634 }
1635 }
1594 } 1636 }
1595 1637
1596 void _createFunctionParameter(ParameterElement parameterElement) { 1638 void _createFunctionParameter(ParameterElement parameterElement) {
1597 ir.Parameter parameter = new ir.Parameter(parameterElement); 1639 ir.Parameter parameter = new ir.Parameter(parameterElement);
1598 _parameters.add(parameter); 1640 _parameters.add(parameter);
1599 if (isInClosureVariable(parameterElement)) { 1641 if (isInClosureVariable(parameterElement)) {
1600 state.functionParameters.add(getClosureVariable(parameterElement)); 1642 state.functionParameters.add(getClosureVariable(parameterElement));
1601 } else { 1643 } else {
1602 state.functionParameters.add(parameter); 1644 state.functionParameters.add(parameter);
1603 environment.extend(parameterElement, parameter); 1645 environment.extend(parameterElement, parameter);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1660 assert(isOpen); 1702 assert(isOpen);
1661 if (isInClosureVariable(local)) { 1703 if (isInClosureVariable(local)) {
1662 add(new ir.SetClosureVariable(getClosureVariable(local), value)); 1704 add(new ir.SetClosureVariable(getClosureVariable(local), value));
1663 } else { 1705 } else {
1664 value.useElementAsHint(local); 1706 value.useElementAsHint(local);
1665 environment.update(local, value); 1707 environment.update(local, value);
1666 } 1708 }
1667 return value; 1709 return value;
1668 } 1710 }
1669 1711
1712 List<ir.ClosureVariable> _getDeclaredClosureVariables(
1713 ExecutableElement element) {
1714 return dartState.getClosureList(element);
1715 }
1716
1717 ir.Primitive buildThis() {
1718 ir.Primitive thisPrim = new ir.This();
1719 add(new ir.LetPrim(thisPrim));
1720 return thisPrim;
1721 }
1670 1722
1671 } 1723 }
1672 1724
1725 /// State shared between JsIrBuilders within the same function.
1726 ///
1727 /// Note that this is not shared between builders of nested functions.
1728 class JsIrBuilderSharedState {
1729 /// Maps boxed locals to their location. These locals are not part of
1730 /// the environment.
1731 final Map<Local, ClosureLocation> boxedVariables = {};
1732
1733 /// If non-null, this refers to the receiver (`this`) in the enclosing method.
1734 ir.Primitive receiver;
1735 }
1736
1673 /// JS-specific subclass of [IrBuilder]. 1737 /// JS-specific subclass of [IrBuilder].
1674 /// 1738 ///
1675 /// Inner functions are represented by a [ClosureClassElement], and captured 1739 /// Inner functions are represented by a [ClosureClassElement], and captured
1676 /// variables are boxed as necessary using [CreateBox], [GetField], [SetField]. 1740 /// variables are boxed as necessary using [CreateBox], [GetField], [SetField].
1677 class JsIrBuilder extends IrBuilder { 1741 class JsIrBuilder extends IrBuilder {
1678 IrBuilder _makeInstance() => new JsIrBuilder._blank(); 1742 final JsIrBuilderSharedState jsState;
1679 JsIrBuilder._blank();
1680 1743
1681 JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement) { 1744 IrBuilder _makeInstance() => new JsIrBuilder._blank(jsState);
1745 JsIrBuilder._blank(this.jsState);
1746
1747 JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement)
1748 : jsState = new JsIrBuilderSharedState() {
1682 _init(constantSystem, currentElement); 1749 _init(constantSystem, currentElement);
1683 } 1750 }
1684 1751
1685 void _buildClosureEnvironmentSetup(ClosureEnvironment env) { 1752 void _enterClosureEnvironment(ClosureEnvironment env) {
1686 if (env == null) return; 1753 if (env == null) return;
1687 1754
1688 // Obtain a reference to the function object (this). 1755 // Obtain a reference to the function object (this).
1689 ir.Primitive thisPrim = new ir.This(); 1756 ir.Primitive thisPrim = new ir.This();
1690 add(new ir.LetPrim(thisPrim)); 1757 add(new ir.LetPrim(thisPrim));
1691 1758
1692 // Obtain access to the free variables. 1759 // Obtain access to the free variables.
1693 env.freeVariables.forEach((Local local, ClosureLocation location) { 1760 env.freeVariables.forEach((Local local, ClosureLocation location) {
1694 if (location.isBox) { 1761 if (location.isBox) {
1695 // Boxed variables are loaded from their box on-demand. 1762 // Boxed variables are loaded from their box on-demand.
1696 state.boxedVariables[local] = location; 1763 jsState.boxedVariables[local] = location;
1697 } else { 1764 } else {
1698 // Unboxed variables are loaded from the function object immediately. 1765 // Unboxed variables are loaded from the function object immediately.
1699 // This includes BoxLocals which are themselves unboxed variables. 1766 // This includes BoxLocals which are themselves unboxed variables.
1700 ir.Primitive load = new ir.GetField(thisPrim, location.field); 1767 ir.Primitive load = new ir.GetField(thisPrim, location.field);
1701 add(new ir.LetPrim(load)); 1768 add(new ir.LetPrim(load));
1702 environment.extend(local, load); 1769 environment.extend(local, load);
1703 } 1770 }
1704 }); 1771 });
1705 1772
1706 // If the function captures a reference to the receiver from the 1773 // If the function captures a reference to the receiver from the
1707 // enclosing method, remember which primitive refers to the receiver object. 1774 // enclosing method, remember which primitive refers to the receiver object.
1708 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) { 1775 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) {
1709 state.receiver = environment.lookup(env.thisLocal); 1776 jsState.receiver = environment.lookup(env.thisLocal);
1710 } 1777 }
1711 1778
1712 // If the function has a self-reference, use the value of `this`. 1779 // If the function has a self-reference, use the value of `this`.
1713 if (env.selfReference != null) { 1780 if (env.selfReference != null) {
1714 environment.extend(env.selfReference, thisPrim); 1781 environment.extend(env.selfReference, thisPrim);
1715 } 1782 }
1716 } 1783 }
1717 1784
1718 void _buildClosureScopeSetup(ClosureScope scope) { 1785 void _enterScope(ClosureScope scope) {
1719 if (scope == null) return; 1786 if (scope == null) return;
1720 ir.CreateBox boxPrim = new ir.CreateBox(); 1787 ir.CreateBox boxPrim = new ir.CreateBox();
1721 add(new ir.LetPrim(boxPrim)); 1788 add(new ir.LetPrim(boxPrim));
1722 environment.extend(scope.box, boxPrim); 1789 environment.extend(scope.box, boxPrim);
1723 boxPrim.useElementAsHint(scope.box); 1790 boxPrim.useElementAsHint(scope.box);
1724 scope.capturedVariables.forEach((Local local, ClosureLocation location) { 1791 scope.capturedVariables.forEach((Local local, ClosureLocation location) {
1725 assert(!state.boxedVariables.containsKey(local)); 1792 assert(!jsState.boxedVariables.containsKey(local));
1726 if (location.isBox) { 1793 if (location.isBox) {
1727 state.boxedVariables[local] = location; 1794 jsState.boxedVariables[local] = location;
1728 } 1795 }
1729 }); 1796 });
1730 } 1797 }
1731 1798
1732 void _createFunctionParameter(ParameterElement parameterElement) { 1799 void _createFunctionParameter(ParameterElement parameterElement) {
1733 ir.Parameter parameter = new ir.Parameter(parameterElement); 1800 ir.Parameter parameter = new ir.Parameter(parameterElement);
1734 _parameters.add(parameter); 1801 _parameters.add(parameter);
1735 state.functionParameters.add(parameter); 1802 state.functionParameters.add(parameter);
1736 ClosureLocation location = state.boxedVariables[parameterElement]; 1803 ClosureLocation location = jsState.boxedVariables[parameterElement];
1737 if (location != null) { 1804 if (location != null) {
1738 add(new ir.SetField(environment.lookup(location.box), 1805 add(new ir.SetField(environment.lookup(location.box),
1739 location.field, 1806 location.field,
1740 parameter)); 1807 parameter));
1741 } else { 1808 } else {
1742 environment.extend(parameterElement, parameter); 1809 environment.extend(parameterElement, parameter);
1743 } 1810 }
1744 } 1811 }
1745 1812
1746 void declareLocalVariable(LocalElement variableElement, 1813 void declareLocalVariable(LocalElement variableElement,
1747 {ir.Primitive initialValue}) { 1814 {ir.Primitive initialValue}) {
1748 assert(isOpen); 1815 assert(isOpen);
1749 if (initialValue == null) { 1816 if (initialValue == null) {
1750 initialValue = buildNullLiteral(); 1817 initialValue = buildNullLiteral();
1751 } 1818 }
1752 ClosureLocation location = state.boxedVariables[variableElement]; 1819 ClosureLocation location = jsState.boxedVariables[variableElement];
1753 if (location != null) { 1820 if (location != null) {
1754 add(new ir.SetField(environment.lookup(location.box), 1821 add(new ir.SetField(environment.lookup(location.box),
1755 location.field, 1822 location.field,
1756 initialValue)); 1823 initialValue));
1757 } else { 1824 } else {
1758 initialValue.useElementAsHint(variableElement); 1825 initialValue.useElementAsHint(variableElement);
1759 environment.extend(variableElement, initialValue); 1826 environment.extend(variableElement, initialValue);
1760 } 1827 }
1761 } 1828 }
1762 1829
(...skipping 10 matching lines...) Expand all
1773 arguments.add(environment.lookup(field.local)); 1840 arguments.add(environment.lookup(field.local));
1774 } 1841 }
1775 ir.Primitive closure = new ir.CreateClosureClass(classElement, arguments); 1842 ir.Primitive closure = new ir.CreateClosureClass(classElement, arguments);
1776 add(new ir.LetPrim(closure)); 1843 add(new ir.LetPrim(closure));
1777 return closure; 1844 return closure;
1778 } 1845 }
1779 1846
1780 /// Create a read access of [local]. 1847 /// Create a read access of [local].
1781 ir.Primitive buildLocalGet(LocalElement local) { 1848 ir.Primitive buildLocalGet(LocalElement local) {
1782 assert(isOpen); 1849 assert(isOpen);
1783 ClosureLocation location = state.boxedVariables[local]; 1850 ClosureLocation location = jsState.boxedVariables[local];
1784 if (location != null) { 1851 if (location != null) {
1785 ir.Primitive result = new ir.GetField(environment.lookup(location.box), 1852 ir.Primitive result = new ir.GetField(environment.lookup(location.box),
1786 location.field); 1853 location.field);
1787 result.useElementAsHint(local); 1854 result.useElementAsHint(local);
1788 add(new ir.LetPrim(result)); 1855 add(new ir.LetPrim(result));
1789 return result; 1856 return result;
1790 } else { 1857 } else {
1791 return environment.lookup(local); 1858 return environment.lookup(local);
1792 } 1859 }
1793 } 1860 }
1794 1861
1795 /// Create a write access to [local] with the provided [value]. 1862 /// Create a write access to [local] with the provided [value].
1796 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { 1863 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) {
1797 assert(isOpen); 1864 assert(isOpen);
1798 ClosureLocation location = state.boxedVariables[local]; 1865 ClosureLocation location = jsState.boxedVariables[local];
1799 if (location != null) { 1866 if (location != null) {
1800 add(new ir.SetField(environment.lookup(location.box), 1867 add(new ir.SetField(environment.lookup(location.box),
1801 location.field, 1868 location.field,
1802 value)); 1869 value));
1803 } else { 1870 } else {
1804 value.useElementAsHint(local); 1871 value.useElementAsHint(local);
1805 environment.update(local, value); 1872 environment.update(local, value);
1806 } 1873 }
1807 return value; 1874 return value;
1808 } 1875 }
1809 1876
1810 void _migrateLoopVariables(ClosureScope scope) { 1877 void _enterForLoopInitializer(ClosureScope scope,
1878 List<LocalElement> loopVariables) {
1811 if (scope == null) return; 1879 if (scope == null) return;
1880 // If there are no boxed loop variables, don't create the box here, let
1881 // it be created inside the body instead.
1882 if (scope.boxedLoopVariables.isEmpty) return;
1883 _enterScope(scope);
1884 }
1885
1886 void _enterForLoopBody(ClosureScope scope,
1887 List<LocalElement> loopVariables) {
1888 if (scope == null) return;
1889 // If there are boxed loop variables, the box has already been created
1890 // at the initializer.
1891 if (!scope.boxedLoopVariables.isEmpty) return;
1892 _enterScope(scope);
1893 }
1894
1895 void _enterForLoopUpdate(ClosureScope scope,
1896 List<LocalElement> loopVariables) {
1897 if (scope == null) return;
1898 // If there are no boxed loop variables, then the box is created inside the
1899 // body, so there is no need to explicitly renew it.
1900 if (scope.boxedLoopVariables.isEmpty) return;
1812 ir.Primitive box = environment.lookup(scope.box); 1901 ir.Primitive box = environment.lookup(scope.box);
1813 ir.Primitive newBox = new ir.CreateBox(); 1902 ir.Primitive newBox = new ir.CreateBox();
1814 newBox.useElementAsHint(scope.box); 1903 newBox.useElementAsHint(scope.box);
1815 add(new ir.LetPrim(newBox)); 1904 add(new ir.LetPrim(newBox));
1816 for (VariableElement loopVar in scope.boxedLoopVariables) { 1905 for (VariableElement loopVar in scope.boxedLoopVariables) {
1817 ClosureLocation location = scope.capturedVariables[loopVar]; 1906 ClosureLocation location = scope.capturedVariables[loopVar];
1818 ir.Primitive get = new ir.GetField(box, location.field); 1907 ir.Primitive get = new ir.GetField(box, location.field);
1819 add(new ir.LetPrim(get)); 1908 add(new ir.LetPrim(get));
1820 add(new ir.SetField(newBox, location.field, get)); 1909 add(new ir.SetField(newBox, location.field, get));
1821 } 1910 }
1822 environment.update(scope.box, newBox); 1911 environment.update(scope.box, newBox);
1823 } 1912 }
1824 1913
1914 List<ir.ClosureVariable> _getDeclaredClosureVariables(
1915 ExecutableElement element) {
1916 return <ir.ClosureVariable>[];
1917 }
1918
1919 ir.Primitive buildThis() {
1920 if (jsState.receiver != null) return jsState.receiver;
1921 ir.Primitive thisPrim = new ir.This();
1922 add(new ir.LetPrim(thisPrim));
1923 return thisPrim;
1924 }
1825 } 1925 }
1826 1926
1827 1927
1828 /// Location of a variable relative to a given closure. 1928 /// Location of a variable relative to a given closure.
1829 class ClosureLocation { 1929 class ClosureLocation {
1830 /// If not `null`, this location is [box].[field]. 1930 /// If not `null`, this location is [box].[field].
1831 /// The location of [box] can be obtained separately from an 1931 /// The location of [box] can be obtained separately from an
1832 /// enclosing [ClosureEnvironment] or [ClosureScope]. 1932 /// enclosing [ClosureEnvironment] or [ClosureScope].
1833 /// If `null`, then the location is [field] on the enclosing function object. 1933 /// If `null`, then the location is [field] on the enclosing function object.
1834 final BoxLocal box; 1934 final BoxLocal box;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 /// to find the captured value of `this`. 1971 /// to find the captured value of `this`.
1872 final ThisLocal thisLocal; 1972 final ThisLocal thisLocal;
1873 1973
1874 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location. 1974 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location.
1875 final Map<Local, ClosureLocation> freeVariables; 1975 final Map<Local, ClosureLocation> freeVariables;
1876 1976
1877 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); 1977 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables);
1878 } 1978 }
1879 1979
1880 /// Information about which variables are captured in a closure. 1980 /// Information about which variables are captured in a closure.
1981 ///
1881 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and 1982 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and
1882 /// [ClosureEnvironment]. 1983 /// [ClosureEnvironment].
1883 abstract class ClosureVariableInfo { 1984 abstract class ClosureVariableInfo {
1884 Iterable<Local> get capturedVariables; 1985 Iterable<Local> get capturedVariables;
1885 } 1986 }
OLDNEW
« no previous file with comments | « pkg/analyzer2dart/lib/src/cps_generator.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698