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

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: Rebase 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);
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 is not called for for-loops, which instead use the methods
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 variables declared in the for-loop
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 }
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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 assert(isOpen); 1704 assert(isOpen);
1663 if (isInClosureVariable(local)) { 1705 if (isInClosureVariable(local)) {
1664 add(new ir.SetClosureVariable(getClosureVariable(local), value)); 1706 add(new ir.SetClosureVariable(getClosureVariable(local), value));
1665 } else { 1707 } else {
1666 value.useElementAsHint(local); 1708 value.useElementAsHint(local);
1667 environment.update(local, value); 1709 environment.update(local, value);
1668 } 1710 }
1669 return value; 1711 return value;
1670 } 1712 }
1671 1713
1714 List<ir.ClosureVariable> _getDeclaredClosureVariables(
1715 ExecutableElement element) {
1716 return dartState.getClosureList(element);
1717 }
1718
1719 ir.Primitive buildThis() {
1720 ir.Primitive thisPrim = new ir.This();
1721 add(new ir.LetPrim(thisPrim));
1722 return thisPrim;
1723 }
1672 1724
1673 } 1725 }
1674 1726
1727 /// State shared between JsIrBuilders within the same function.
1728 ///
1729 /// Note that this is not shared between builders of nested functions.
1730 class JsIrBuilderSharedState {
1731 /// Maps boxed locals to their location. These locals are not part of
1732 /// the environment.
1733 final Map<Local, ClosureLocation> boxedVariables = {};
1734
1735 /// If non-null, this refers to the receiver (`this`) in the enclosing method.
1736 ir.Primitive receiver;
1737 }
1738
1675 /// JS-specific subclass of [IrBuilder]. 1739 /// JS-specific subclass of [IrBuilder].
1676 /// 1740 ///
1677 /// Inner functions are represented by a [ClosureClassElement], and captured 1741 /// Inner functions are represented by a [ClosureClassElement], and captured
1678 /// variables are boxed as necessary using [CreateBox], [GetField], [SetField]. 1742 /// variables are boxed as necessary using [CreateBox], [GetField], [SetField].
1679 class JsIrBuilder extends IrBuilder { 1743 class JsIrBuilder extends IrBuilder {
1680 IrBuilder _makeInstance() => new JsIrBuilder._blank(); 1744 final JsIrBuilderSharedState jsState;
1681 JsIrBuilder._blank();
1682 1745
1683 JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement) { 1746 IrBuilder _makeInstance() => new JsIrBuilder._blank(jsState);
1747 JsIrBuilder._blank(this.jsState);
1748
1749 JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement)
1750 : jsState = new JsIrBuilderSharedState() {
1684 _init(constantSystem, currentElement); 1751 _init(constantSystem, currentElement);
1685 } 1752 }
1686 1753
1687 void _buildClosureEnvironmentSetup(ClosureEnvironment env) { 1754 void _enterClosureEnvironment(ClosureEnvironment env) {
1688 if (env == null) return; 1755 if (env == null) return;
1689 1756
1690 // Obtain a reference to the function object (this). 1757 // Obtain a reference to the function object (this).
1691 ir.Primitive thisPrim = new ir.This(); 1758 ir.Primitive thisPrim = new ir.This();
1692 add(new ir.LetPrim(thisPrim)); 1759 add(new ir.LetPrim(thisPrim));
1693 1760
1694 // Obtain access to the free variables. 1761 // Obtain access to the free variables.
1695 env.freeVariables.forEach((Local local, ClosureLocation location) { 1762 env.freeVariables.forEach((Local local, ClosureLocation location) {
1696 if (location.isBox) { 1763 if (location.isBox) {
1697 // Boxed variables are loaded from their box on-demand. 1764 // Boxed variables are loaded from their box on-demand.
1698 state.boxedVariables[local] = location; 1765 jsState.boxedVariables[local] = location;
1699 } else { 1766 } else {
1700 // Unboxed variables are loaded from the function object immediately. 1767 // Unboxed variables are loaded from the function object immediately.
1701 // This includes BoxLocals which are themselves unboxed variables. 1768 // This includes BoxLocals which are themselves unboxed variables.
1702 ir.Primitive load = new ir.GetField(thisPrim, location.field); 1769 ir.Primitive load = new ir.GetField(thisPrim, location.field);
1703 add(new ir.LetPrim(load)); 1770 add(new ir.LetPrim(load));
1704 environment.extend(local, load); 1771 environment.extend(local, load);
1705 } 1772 }
1706 }); 1773 });
1707 1774
1708 // If the function captures a reference to the receiver from the 1775 // If the function captures a reference to the receiver from the
1709 // enclosing method, remember which primitive refers to the receiver object. 1776 // enclosing method, remember which primitive refers to the receiver object.
1710 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) { 1777 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) {
1711 state.receiver = environment.lookup(env.thisLocal); 1778 jsState.receiver = environment.lookup(env.thisLocal);
1712 } 1779 }
1713 1780
1714 // If the function has a self-reference, use the value of `this`. 1781 // If the function has a self-reference, use the value of `this`.
1715 if (env.selfReference != null) { 1782 if (env.selfReference != null) {
1716 environment.extend(env.selfReference, thisPrim); 1783 environment.extend(env.selfReference, thisPrim);
1717 } 1784 }
1718 } 1785 }
1719 1786
1720 void _buildClosureScopeSetup(ClosureScope scope) { 1787 void _enterScope(ClosureScope scope) {
1721 if (scope == null) return; 1788 if (scope == null) return;
1722 ir.CreateBox boxPrim = new ir.CreateBox(); 1789 ir.CreateBox boxPrim = new ir.CreateBox();
1723 add(new ir.LetPrim(boxPrim)); 1790 add(new ir.LetPrim(boxPrim));
1724 environment.extend(scope.box, boxPrim); 1791 environment.extend(scope.box, boxPrim);
1725 boxPrim.useElementAsHint(scope.box); 1792 boxPrim.useElementAsHint(scope.box);
1726 scope.capturedVariables.forEach((Local local, ClosureLocation location) { 1793 scope.capturedVariables.forEach((Local local, ClosureLocation location) {
1727 assert(!state.boxedVariables.containsKey(local)); 1794 assert(!jsState.boxedVariables.containsKey(local));
1728 if (location.isBox) { 1795 if (location.isBox) {
1729 state.boxedVariables[local] = location; 1796 jsState.boxedVariables[local] = location;
1730 } 1797 }
1731 }); 1798 });
1732 } 1799 }
1733 1800
1734 void _createFunctionParameter(ParameterElement parameterElement) { 1801 void _createFunctionParameter(ParameterElement parameterElement) {
1735 ir.Parameter parameter = new ir.Parameter(parameterElement); 1802 ir.Parameter parameter = new ir.Parameter(parameterElement);
1736 _parameters.add(parameter); 1803 _parameters.add(parameter);
1737 state.functionParameters.add(parameter); 1804 state.functionParameters.add(parameter);
1738 ClosureLocation location = state.boxedVariables[parameterElement]; 1805 ClosureLocation location = jsState.boxedVariables[parameterElement];
1739 if (location != null) { 1806 if (location != null) {
1740 add(new ir.SetField(environment.lookup(location.box), 1807 add(new ir.SetField(environment.lookup(location.box),
1741 location.field, 1808 location.field,
1742 parameter)); 1809 parameter));
1743 } else { 1810 } else {
1744 environment.extend(parameterElement, parameter); 1811 environment.extend(parameterElement, parameter);
1745 } 1812 }
1746 } 1813 }
1747 1814
1748 void declareLocalVariable(LocalElement variableElement, 1815 void declareLocalVariable(LocalElement variableElement,
1749 {ir.Primitive initialValue}) { 1816 {ir.Primitive initialValue}) {
1750 assert(isOpen); 1817 assert(isOpen);
1751 if (initialValue == null) { 1818 if (initialValue == null) {
1752 initialValue = buildNullLiteral(); 1819 initialValue = buildNullLiteral();
1753 } 1820 }
1754 ClosureLocation location = state.boxedVariables[variableElement]; 1821 ClosureLocation location = jsState.boxedVariables[variableElement];
1755 if (location != null) { 1822 if (location != null) {
1756 add(new ir.SetField(environment.lookup(location.box), 1823 add(new ir.SetField(environment.lookup(location.box),
1757 location.field, 1824 location.field,
1758 initialValue)); 1825 initialValue));
1759 } else { 1826 } else {
1760 initialValue.useElementAsHint(variableElement); 1827 initialValue.useElementAsHint(variableElement);
1761 environment.extend(variableElement, initialValue); 1828 environment.extend(variableElement, initialValue);
1762 } 1829 }
1763 } 1830 }
1764 1831
(...skipping 10 matching lines...) Expand all
1775 arguments.add(environment.lookup(field.local)); 1842 arguments.add(environment.lookup(field.local));
1776 } 1843 }
1777 ir.Primitive closure = new ir.CreateClosureClass(classElement, arguments); 1844 ir.Primitive closure = new ir.CreateClosureClass(classElement, arguments);
1778 add(new ir.LetPrim(closure)); 1845 add(new ir.LetPrim(closure));
1779 return closure; 1846 return closure;
1780 } 1847 }
1781 1848
1782 /// Create a read access of [local]. 1849 /// Create a read access of [local].
1783 ir.Primitive buildLocalGet(LocalElement local) { 1850 ir.Primitive buildLocalGet(LocalElement local) {
1784 assert(isOpen); 1851 assert(isOpen);
1785 ClosureLocation location = state.boxedVariables[local]; 1852 ClosureLocation location = jsState.boxedVariables[local];
1786 if (location != null) { 1853 if (location != null) {
1787 ir.Primitive result = new ir.GetField(environment.lookup(location.box), 1854 ir.Primitive result = new ir.GetField(environment.lookup(location.box),
1788 location.field); 1855 location.field);
1789 result.useElementAsHint(local); 1856 result.useElementAsHint(local);
1790 add(new ir.LetPrim(result)); 1857 add(new ir.LetPrim(result));
1791 return result; 1858 return result;
1792 } else { 1859 } else {
1793 return environment.lookup(local); 1860 return environment.lookup(local);
1794 } 1861 }
1795 } 1862 }
1796 1863
1797 /// Create a write access to [local] with the provided [value]. 1864 /// Create a write access to [local] with the provided [value].
1798 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { 1865 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) {
1799 assert(isOpen); 1866 assert(isOpen);
1800 ClosureLocation location = state.boxedVariables[local]; 1867 ClosureLocation location = jsState.boxedVariables[local];
1801 if (location != null) { 1868 if (location != null) {
1802 add(new ir.SetField(environment.lookup(location.box), 1869 add(new ir.SetField(environment.lookup(location.box),
1803 location.field, 1870 location.field,
1804 value)); 1871 value));
1805 } else { 1872 } else {
1806 value.useElementAsHint(local); 1873 value.useElementAsHint(local);
1807 environment.update(local, value); 1874 environment.update(local, value);
1808 } 1875 }
1809 return value; 1876 return value;
1810 } 1877 }
1811 1878
1812 void _migrateLoopVariables(ClosureScope scope) { 1879 void _enterForLoopInitializer(ClosureScope scope,
1880 List<LocalElement> loopVariables) {
1813 if (scope == null) return; 1881 if (scope == null) return;
1882 // If there are no boxed loop variables, don't create the box here, let
1883 // it be created inside the body instead.
1884 if (scope.boxedLoopVariables.isEmpty) return;
1885 _enterScope(scope);
1886 }
1887
1888 void _enterForLoopBody(ClosureScope scope,
1889 List<LocalElement> loopVariables) {
1890 if (scope == null) return;
1891 // If there are boxed loop variables, the box has already been created
1892 // at the initializer.
1893 if (!scope.boxedLoopVariables.isEmpty) return;
1894 _enterScope(scope);
1895 }
1896
1897 void _enterForLoopUpdate(ClosureScope scope,
1898 List<LocalElement> loopVariables) {
1899 if (scope == null) return;
1900 // If there are no boxed loop variables, then the box is created inside the
1901 // body, so there is no need to explicitly renew it.
1902 if (scope.boxedLoopVariables.isEmpty) return;
1814 ir.Primitive box = environment.lookup(scope.box); 1903 ir.Primitive box = environment.lookup(scope.box);
1815 ir.Primitive newBox = new ir.CreateBox(); 1904 ir.Primitive newBox = new ir.CreateBox();
1816 newBox.useElementAsHint(scope.box); 1905 newBox.useElementAsHint(scope.box);
1817 add(new ir.LetPrim(newBox)); 1906 add(new ir.LetPrim(newBox));
1818 for (VariableElement loopVar in scope.boxedLoopVariables) { 1907 for (VariableElement loopVar in scope.boxedLoopVariables) {
1819 ClosureLocation location = scope.capturedVariables[loopVar]; 1908 ClosureLocation location = scope.capturedVariables[loopVar];
1820 ir.Primitive get = new ir.GetField(box, location.field); 1909 ir.Primitive get = new ir.GetField(box, location.field);
1821 add(new ir.LetPrim(get)); 1910 add(new ir.LetPrim(get));
1822 add(new ir.SetField(newBox, location.field, get)); 1911 add(new ir.SetField(newBox, location.field, get));
1823 } 1912 }
1824 environment.update(scope.box, newBox); 1913 environment.update(scope.box, newBox);
1825 } 1914 }
1826 1915
1916 List<ir.ClosureVariable> _getDeclaredClosureVariables(
1917 ExecutableElement element) {
1918 return <ir.ClosureVariable>[];
1919 }
1920
1921 ir.Primitive buildThis() {
1922 if (jsState.receiver != null) return jsState.receiver;
1923 ir.Primitive thisPrim = new ir.This();
1924 add(new ir.LetPrim(thisPrim));
1925 return thisPrim;
1926 }
1827 } 1927 }
1828 1928
1829 1929
1830 /// Location of a variable relative to a given closure. 1930 /// Location of a variable relative to a given closure.
1831 class ClosureLocation { 1931 class ClosureLocation {
1832 /// If not `null`, this location is [box].[field]. 1932 /// If not `null`, this location is [box].[field].
1833 /// The location of [box] can be obtained separately from an 1933 /// The location of [box] can be obtained separately from an
1834 /// enclosing [ClosureEnvironment] or [ClosureScope]. 1934 /// enclosing [ClosureEnvironment] or [ClosureScope].
1835 /// If `null`, then the location is [field] on the enclosing function object. 1935 /// If `null`, then the location is [field] on the enclosing function object.
1836 final BoxLocal box; 1936 final BoxLocal box;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1873 /// to find the captured value of `this`. 1973 /// to find the captured value of `this`.
1874 final ThisLocal thisLocal; 1974 final ThisLocal thisLocal;
1875 1975
1876 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location. 1976 /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location.
1877 final Map<Local, ClosureLocation> freeVariables; 1977 final Map<Local, ClosureLocation> freeVariables;
1878 1978
1879 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); 1979 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables);
1880 } 1980 }
1881 1981
1882 /// Information about which variables are captured in a closure. 1982 /// Information about which variables are captured in a closure.
1983 ///
1883 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and 1984 /// This is used by the [DartIrBuilder] instead of [ClosureScope] and
1884 /// [ClosureEnvironment]. 1985 /// [ClosureEnvironment].
1885 abstract class ClosureVariableInfo { 1986 abstract class ClosureVariableInfo {
1886 Iterable<Local> get capturedVariables; 1987 Iterable<Local> get capturedVariables;
1887 } 1988 }
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