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

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

Issue 831133004: Use closure conversion in new dart2js backend. (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 part of dart2js.ir_builder; 5 part of dart2js.ir_builder;
6 6
7 /** 7 /**
8 * This task iterates through all resolved elements and builds [ir.Node]s. The 8 * This task iterates through all resolved elements and builds [ir.Node]s. The
9 * nodes are stored in the [nodes] map and accessible through [hasIr] and 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and
10 * [getIr]. 10 * [getIr].
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 101
102 /** 102 /**
103 * A tree visitor that builds [IrNodes]. The visit methods add statements using 103 * A tree visitor that builds [IrNodes]. The visit methods add statements using
104 * to the [builder] and return the last added statement for trees that represent 104 * to the [builder] and return the last added statement for trees that represent
105 * an expression. 105 * an expression.
106 */ 106 */
107 class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive> 107 class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
108 with IrBuilderMixin<ast.Node> { 108 with IrBuilderMixin<ast.Node> {
109 final Compiler compiler; 109 final Compiler compiler;
110 final SourceFile sourceFile; 110 final SourceFile sourceFile;
111 ClosureClassMap closureMap;
111 112
112 // In SSA terms, join-point continuation parameters are the phis and the 113 // In SSA terms, join-point continuation parameters are the phis and the
113 // continuation invocation arguments are the corresponding phi inputs. To 114 // continuation invocation arguments are the corresponding phi inputs. To
114 // support name introduction and renaming for source level variables, we use 115 // support name introduction and renaming for source level variables, we use
115 // nested (delimited) visitors for constructing subparts of the IR that will 116 // nested (delimited) visitors for constructing subparts of the IR that will
116 // need renaming. Each source variable is assigned an index. 117 // need renaming. Each source variable is assigned an index.
117 // 118 //
118 // Each nested visitor maintains a list of free variable uses in the body. 119 // Each nested visitor maintains a list of free variable uses in the body.
119 // These are implemented as a list of parameters, each with their own use 120 // These are implemented as a list of parameters, each with their own use
120 // list of references. When the delimited subexpression is plugged into the 121 // list of references. When the delimited subexpression is plugged into the
121 // surrounding context, the free occurrences can be captured or become free 122 // surrounding context, the free occurrences can be captured or become free
122 // occurrences in the next outer delimited subexpression. 123 // occurrences in the next outer delimited subexpression.
123 // 124 //
124 // Each nested visitor maintains a list that maps indexes of variables 125 // Each nested visitor maintains a list that maps indexes of variables
125 // assigned in the delimited subexpression to their reaching definition --- 126 // assigned in the delimited subexpression to their reaching definition ---
126 // that is, the definition in effect at the hole in 'current'. These are 127 // that is, the definition in effect at the hole in 'current'. These are
127 // used to determine if a join-point continuation needs to be passed 128 // used to determine if a join-point continuation needs to be passed
128 // arguments, and what the arguments are. 129 // arguments, and what the arguments are.
129 130
130 /// Construct a top-level visitor. 131 /// Construct a top-level visitor.
131 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) 132 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile)
132 : super(elements); 133 : super(elements);
133 134
135 /// True if using the JavaScript backend; we use this to determine how
136 /// closures should be translated.
137 bool get isJavaScriptBackend => compiler.backend is JavaScriptBackend;
138
134 /** 139 /**
135 * Builds the [ir.ExecutableDefinition] for an executable element. In case the 140 * Builds the [ir.ExecutableDefinition] for an executable element. In case the
136 * function uses features that cannot be expressed in the IR, this element 141 * function uses features that cannot be expressed in the IR, this element
137 * returns `null`. 142 * returns `null`.
138 */ 143 */
139 ir.ExecutableDefinition buildExecutable(ExecutableElement element) { 144 ir.ExecutableDefinition buildExecutable(ExecutableElement element) {
140 return nullIfGiveup(() { 145 return nullIfGiveup(() {
141 if (element is FieldElement) { 146 if (element is FieldElement) {
142 return buildField(element); 147 return buildField(element);
143 } else if (element is FunctionElement) { 148 } else if (element is FunctionElement) {
144 return buildFunction(element); 149 return buildFunction(element);
145 } else { 150 } else {
146 compiler.internalError(element, "Unexpected element type $element"); 151 compiler.internalError(element, "Unexpected element type $element");
147 } 152 }
148 }); 153 });
149 } 154 }
150 155
156 Map mapValues(Map map, dynamic fn(dynamic)) {
157 Map result = {};
158 map.forEach((key,value) {
159 result[key] = fn(value);
160 });
161 return result;
162 }
163
164 // Converts closure.dart's CapturedVariable into a ClosureLocation.
165 // There is a 1:1 corresponce between these; we do this because the IR builder
166 // should not depend on synthetic elements.
167 ClosureLocation getLocation(CapturedVariable v) {
168 if (v is BoxFieldElement) {
169 return new ClosureLocation(v.box, v);
170 } else {
171 ClosureFieldElement field = v;
172 return new ClosureLocation(null, field);
173 }
174 }
175
176 /// If the current function is a nested function with free variables (or a
177 /// captured reference to `this`), this returns a [ClosureEnvironment]
178 /// indicating how to access these.
179 ClosureEnvironment getClosureEnvironment() {
180 if (closureMap == null) return null; // dart2dart does not use closureMap.
181 if (closureMap.closureElement == null) return null;
182 return new ClosureEnvironment(
183 closureMap.closureElement,
184 closureMap.thisLocal,
185 mapValues(closureMap.freeVariableMap, getLocation));
186 }
187
188 /// If [node] has declarations for variables that should be boxed, this
189 /// returns a [ClosureScope] naming a box to create, and enumerating the
190 /// variables that should be stored in the box.
191 ///
192 /// Also see [ClosureScope].
193 ClosureScope getClosureScope(ast.Node node) {
194 if (closureMap == null) return null; // dart2dart does not use closureMap.
195 closurelib.ClosureScope scope = closureMap.capturingScopes[node];
196 if (scope == null) return null;
197 // We translate a ClosureScope from closure.dart into IR builder's variant
198 // because the IR builder should not depend on the synthetic elements
199 // created in closure.dart.
200 return new ClosureScope(scope.boxElement,
201 mapValues(scope.capturedVariables, getLocation),
202 scope.boxedLoopVariables);
203 }
204
205 IrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) {
206 if (isJavaScriptBackend) {
207 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping(
208 element,
209 node,
210 elements);
211 return new JsIrBuilder(compiler.backend.constantSystem, element);
212 } else {
213 DetectClosureVariables closures = new DetectClosureVariables(elements);
214 if (!element.isSynthesized) {
215 closures.visit(node);
216 }
217 return new DartIrBuilder(compiler.backend.constantSystem,
218 element,
219 closures);
220 }
221 }
222
151 /// Returns a [ir.FieldDefinition] describing the initializer of [element]. 223 /// Returns a [ir.FieldDefinition] describing the initializer of [element].
152 /// Returns `null` if [element] has no initializer.
153 ir.FieldDefinition buildField(FieldElement element) { 224 ir.FieldDefinition buildField(FieldElement element) {
154 assert(invariant(element, element.isImplementation)); 225 assert(invariant(element, element.isImplementation));
155 ast.VariableDefinitions definitions = element.node; 226 ast.VariableDefinitions definitions = element.node;
156 ast.Node fieldDefinition = 227 ast.Node fieldDefinition =
157 definitions.definitions.nodes.first; 228 definitions.definitions.nodes.first;
158 if (definitions.modifiers.isConst) { 229 if (definitions.modifiers.isConst) {
159 // TODO(sigurdm): Just return const value. 230 // TODO(sigurdm): Just return const value.
160 } 231 }
161 assert(fieldDefinition != null); 232 assert(fieldDefinition != null);
162 assert(elements[fieldDefinition] != null); 233 assert(elements[fieldDefinition] != null);
163 DetectClosureVariables closureLocals =
164 new DetectClosureVariables(elements);
165 closureLocals.visit(fieldDefinition);
166 234
167 IrBuilder builder = new IrBuilder(compiler.backend.constantSystem, 235 IrBuilder builder = makeIRBuilder(fieldDefinition, element);
168 element, 236
169 closureLocals.usedFromClosure);
170 return withBuilder(builder, () { 237 return withBuilder(builder, () {
238 builder.buildFieldInitializerHeader(
239 closureScope: getClosureScope(fieldDefinition));
171 ir.Primitive initializer; 240 ir.Primitive initializer;
172 if (fieldDefinition is ast.SendSet) { 241 if (fieldDefinition is ast.SendSet) {
173 ast.SendSet sendSet = fieldDefinition; 242 ast.SendSet sendSet = fieldDefinition;
174 initializer = visit(sendSet.arguments.first); 243 initializer = visit(sendSet.arguments.first);
175 } 244 }
176 return builder.makeFieldDefinition(initializer); 245 return builder.makeFieldDefinition(initializer);
177 }); 246 });
178 } 247 }
179 248
180 ir.FunctionDefinition _makeFunctionBody(FunctionElement element, 249 ir.FunctionDefinition _makeFunctionBody(FunctionElement element,
181 ast.FunctionExpression node) { 250 ast.FunctionExpression node) {
182 FunctionSignature signature = element.functionSignature; 251 FunctionSignature signature = element.functionSignature;
183 signature.orderedForEachParameter((ParameterElement parameterElement) { 252 List<ParameterElement> parameters = [];
184 irBuilder.createFunctionParameter(parameterElement); 253 signature.orderedForEachParameter(parameters.add);
185 }); 254
255 irBuilder.buildFunctionHeader(parameters,
256 closureScope: getClosureScope(node),
257 closureEnvironment: getClosureEnvironment());
186 258
187 List<ConstantExpression> defaults = new List<ConstantExpression>(); 259 List<ConstantExpression> defaults = new List<ConstantExpression>();
188 signature.orderedOptionalParameters.forEach((ParameterElement element) { 260 signature.orderedOptionalParameters.forEach((ParameterElement element) {
189 defaults.add(getConstantForVariable(element)); 261 defaults.add(getConstantForVariable(element));
190 }); 262 });
191 263
192 List<ir.Initializer> initializers; 264 List<ir.Initializer> initializers;
193 if (element.isSynthesized) { 265 if (element.isSynthesized) {
194 assert(element is ConstructorElement); 266 assert(element is ConstructorElement);
195 return irBuilder.makeConstructorDefinition(const <ConstantExpression>[], 267 return irBuilder.makeConstructorDefinition(const <ConstantExpression>[],
196 const <ir.Initializer>[]); 268 const <ir.Initializer>[]);
197 } else if (element.isGenerativeConstructor) { 269 } else if (element.isGenerativeConstructor) {
198 initializers = buildConstructorInitializers(node, element); 270 initializers = buildConstructorInitializers(node, element);
199 visit(node.body); 271 visit(node.body);
200 return irBuilder.makeConstructorDefinition(defaults, initializers); 272 return irBuilder.makeConstructorDefinition(defaults, initializers);
201 } else { 273 } else {
202 visit(node.body); 274 visit(node.body);
203 return irBuilder.makeFunctionDefinition(defaults); 275 return irBuilder.makeFunctionDefinition(defaults);
204 } 276 }
205 } 277 }
206 278
207 List<ir.Initializer> buildConstructorInitializers( 279 List<ir.Initializer> buildConstructorInitializers(
208 ast.FunctionExpression function, ConstructorElement element) { 280 ast.FunctionExpression function, ConstructorElement element) {
209 List<ir.Initializer> result = <ir.Initializer>[]; 281 List<ir.Initializer> result = <ir.Initializer>[];
210 FunctionSignature signature = element.functionSignature; 282 FunctionSignature signature = element.functionSignature;
211 283
212 void tryAddInitializingFormal(ParameterElement parameterElement) { 284 void tryAddInitializingFormal(ParameterElement parameterElement) {
213 if (parameterElement.isInitializingFormal) { 285 if (parameterElement.isInitializingFormal) {
214 InitializingFormalElement initializingFormal = parameterElement; 286 InitializingFormalElement initializingFormal = parameterElement;
215 withBuilder(new IrBuilder.delimited(irBuilder), () { 287 withBuilder(irBuilder.makeDelimitedBuilder(), () {
216 ir.Primitive value = irBuilder.buildLocalGet(parameterElement); 288 ir.Primitive value = irBuilder.buildLocalGet(parameterElement);
217 result.add(irBuilder.makeFieldInitializer( 289 result.add(irBuilder.makeFieldInitializer(
218 initializingFormal.fieldElement, 290 initializingFormal.fieldElement,
219 irBuilder.makeRunnableBody(value))); 291 irBuilder.makeRunnableBody(value)));
220 }); 292 });
221 } 293 }
222 } 294 }
223 295
224 // TODO(sigurdm): Preserve initializing formals as initializing formals. 296 // TODO(sigurdm): Preserve initializing formals as initializing formals.
225 signature.orderedForEachParameter(tryAddInitializingFormal); 297 signature.orderedForEachParameter(tryAddInitializingFormal);
226 298
227 if (function.initializers == null) return result; 299 if (function.initializers == null) return result;
228 bool explicitSuperInitializer = false; 300 bool explicitSuperInitializer = false;
229 for(ast.Node initializer in function.initializers) { 301 for(ast.Node initializer in function.initializers) {
230 if (initializer is ast.SendSet) { 302 if (initializer is ast.SendSet) {
231 // Field initializer. 303 // Field initializer.
232 FieldElement field = elements[initializer]; 304 FieldElement field = elements[initializer];
233 withBuilder(new IrBuilder.delimited(irBuilder), () { 305 withBuilder(irBuilder.makeDelimitedBuilder(), () {
234 ir.Primitive value = visit(initializer.arguments.head); 306 ir.Primitive value = visit(initializer.arguments.head);
235 ir.RunnableBody body = irBuilder.makeRunnableBody(value); 307 ir.RunnableBody body = irBuilder.makeRunnableBody(value);
236 result.add(irBuilder.makeFieldInitializer(field, body)); 308 result.add(irBuilder.makeFieldInitializer(field, body));
237 }); 309 });
238 } else if (initializer is ast.Send) { 310 } else if (initializer is ast.Send) {
239 // Super or this initializer. 311 // Super or this initializer.
240 if (ast.Initializers.isConstructorRedirect(initializer)) { 312 if (ast.Initializers.isConstructorRedirect(initializer)) {
241 giveup(initializer, "constructor redirect (this) initializer"); 313 giveup(initializer, "constructor redirect (this) initializer");
242 } 314 }
243 ConstructorElement constructor = elements[initializer].implementation; 315 ConstructorElement constructor = elements[initializer].implementation;
244 Selector selector = elements.getSelector(initializer); 316 Selector selector = elements.getSelector(initializer);
245 List<ir.RunnableBody> arguments = 317 List<ir.RunnableBody> arguments =
246 initializer.arguments.mapToList((ast.Node argument) { 318 initializer.arguments.mapToList((ast.Node argument) {
247 return withBuilder(new IrBuilder.delimited(irBuilder), () { 319 return withBuilder(irBuilder.makeDelimitedBuilder(), () {
248 ir.Primitive value = visit(argument); 320 ir.Primitive value = visit(argument);
249 return irBuilder.makeRunnableBody(value); 321 return irBuilder.makeRunnableBody(value);
250 }); 322 });
251 }); 323 });
252 result.add(irBuilder.makeSuperInitializer(constructor, 324 result.add(irBuilder.makeSuperInitializer(constructor,
253 arguments, 325 arguments,
254 selector)); 326 selector));
255 explicitSuperInitializer = true; 327 explicitSuperInitializer = true;
256 } else { 328 } else {
257 compiler.internalError(initializer, 329 compiler.internalError(initializer,
(...skipping 23 matching lines...) Expand all
281 } 353 }
282 354
283 ir.FunctionDefinition buildFunction(FunctionElement element) { 355 ir.FunctionDefinition buildFunction(FunctionElement element) {
284 assert(invariant(element, element.isImplementation)); 356 assert(invariant(element, element.isImplementation));
285 ast.FunctionExpression node = element.node; 357 ast.FunctionExpression node = element.node;
286 358
287 Iterable<Entity> usedFromClosure; 359 Iterable<Entity> usedFromClosure;
288 if (!element.isSynthesized) { 360 if (!element.isSynthesized) {
289 assert(node != null); 361 assert(node != null);
290 assert(elements[node] != null); 362 assert(elements[node] != null);
291
292 // TODO(karlklose): this information should be provided by resolution.
293 DetectClosureVariables closureLocals =
294 new DetectClosureVariables(elements);
295 closureLocals.visit(node);
296 usedFromClosure = closureLocals.usedFromClosure;
297 } else { 363 } else {
298 SynthesizedConstructorElementX constructor = element; 364 SynthesizedConstructorElementX constructor = element;
299 if (!constructor.isDefaultConstructor) { 365 if (!constructor.isDefaultConstructor) {
300 giveup(null, 'cannot handle synthetic forwarding constructors'); 366 giveup(null, 'cannot handle synthetic forwarding constructors');
301 } 367 }
302 368
303 usedFromClosure = <Entity>[]; 369 usedFromClosure = <Entity>[];
304 } 370 }
305 371
306 IrBuilder builder = new IrBuilder(compiler.backend.constantSystem, 372 IrBuilder builder = makeIRBuilder(node, element);
307 element,
308 usedFromClosure);
309 373
310 return withBuilder(builder, () => _makeFunctionBody(element, node)); 374 return withBuilder(builder, () => _makeFunctionBody(element, node));
311 } 375 }
312 376
313 ir.Primitive visit(ast.Node node) => node.accept(this); 377 ir.Primitive visit(ast.Node node) => node.accept(this);
314 378
315 // ==== Statements ==== 379 // ==== Statements ====
316 visitBlock(ast.Block node) { 380 visitBlock(ast.Block node) {
317 irBuilder.buildBlock(node.statements.nodes, build); 381 irBuilder.buildBlock(node.statements.nodes, build);
318 } 382 }
(...skipping 20 matching lines...) Expand all
339 403
340 // Build(ExpressionStatement(e), C) = C' 404 // Build(ExpressionStatement(e), C) = C'
341 // where (C', _) = Build(e, C) 405 // where (C', _) = Build(e, C)
342 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) { 406 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) {
343 assert(irBuilder.isOpen); 407 assert(irBuilder.isOpen);
344 visit(node.expression); 408 visit(node.expression);
345 return null; 409 return null;
346 } 410 }
347 411
348 visitFor(ast.For node) { 412 visitFor(ast.For node) {
349 // TODO(kmillikin,sigurdm): Handle closure variables declared in a for-loop. 413 // TODO(asgerf): Handle closure variables declared in a for-loop.
350 if (node.initializer is ast.VariableDefinitions) { 414 if (!isJavaScriptBackend && node.initializer is ast.VariableDefinitions) {
351 ast.VariableDefinitions definitions = node.initializer; 415 ast.VariableDefinitions definitions = node.initializer;
352 for (ast.Node definition in definitions.definitions.nodes) { 416 for (ast.Node definition in definitions.definitions.nodes) {
353 Element element = elements[definition]; 417 LocalElement element = elements[definition];
354 if (irBuilder.isClosureVariable(element)) { 418 DartIrBuilder dartIrBuilder = irBuilder;
419 if (dartIrBuilder.isInClosureVariable(element)) {
355 return giveup(definition, 'Closure variable in for loop initializer'); 420 return giveup(definition, 'Closure variable in for loop initializer');
356 } 421 }
357 } 422 }
358 } 423 }
359 424
360 JumpTarget target = elements.getTargetDefinition(node); 425 JumpTarget target = elements.getTargetDefinition(node);
361 irBuilder.buildFor( 426 irBuilder.buildFor(
362 buildInitializer: subbuild(node.initializer), 427 buildInitializer: subbuild(node.initializer),
363 buildCondition: subbuild(node.condition), 428 buildCondition: subbuild(node.condition),
364 buildBody: subbuild(node.body), 429 buildBody: subbuild(node.body),
365 buildUpdate: subbuildSequence(node.update), 430 buildUpdate: subbuildSequence(node.update),
431 closureScope: getClosureScope(node),
366 target: target); 432 target: target);
367 } 433 }
368 434
369 visitIf(ast.If node) { 435 visitIf(ast.If node) {
370 irBuilder.buildIf( 436 irBuilder.buildIf(
371 build(node.condition), 437 build(node.condition),
372 subbuild(node.thenPart), 438 subbuild(node.thenPart),
373 subbuild(node.elsePart)); 439 subbuild(node.elsePart));
374 } 440 }
375 441
376 ir.Primitive visitLabeledStatement(ast.LabeledStatement node) { 442 ir.Primitive visitLabeledStatement(ast.LabeledStatement node) {
377 ast.Statement body = node.statement; 443 ast.Statement body = node.statement;
378 if (body is ast.Loop) return visit(body); 444 if (body is ast.Loop) return visit(body);
379 JumpTarget target = elements.getTargetDefinition(body); 445 JumpTarget target = elements.getTargetDefinition(body);
380 JumpCollector jumps = new JumpCollector(target); 446 JumpCollector jumps = new JumpCollector(target);
381 irBuilder.state.breakCollectors.add(jumps); 447 irBuilder.state.breakCollectors.add(jumps);
382 IrBuilder innerBuilder = new IrBuilder.delimited(irBuilder); 448 IrBuilder innerBuilder = irBuilder.makeDelimitedBuilder();
383 withBuilder(innerBuilder, () { 449 withBuilder(innerBuilder, () {
384 visit(body); 450 visit(body);
385 }); 451 });
386 irBuilder.state.breakCollectors.removeLast(); 452 irBuilder.state.breakCollectors.removeLast();
387 bool hasBreaks = !jumps.isEmpty; 453 bool hasBreaks = !jumps.isEmpty;
388 ir.Continuation joinContinuation; 454 ir.Continuation joinContinuation;
389 if (hasBreaks) { 455 if (hasBreaks) {
390 if (innerBuilder.isOpen) { 456 if (innerBuilder.isOpen) {
391 jumps.addJump(innerBuilder); 457 jumps.addJump(innerBuilder);
392 } 458 }
(...skipping 20 matching lines...) Expand all
413 irBuilder.environment = innerBuilder.environment; 479 irBuilder.environment = innerBuilder.environment;
414 } 480 }
415 } 481 }
416 return null; 482 return null;
417 } 483 }
418 484
419 visitWhile(ast.While node) { 485 visitWhile(ast.While node) {
420 irBuilder.buildWhile( 486 irBuilder.buildWhile(
421 buildCondition: subbuild(node.condition), 487 buildCondition: subbuild(node.condition),
422 buildBody: subbuild(node.body), 488 buildBody: subbuild(node.body),
423 target: elements.getTargetDefinition(node)); 489 target: elements.getTargetDefinition(node),
490 closureScope: getClosureScope(node));
424 } 491 }
425 492
426 visitForIn(ast.ForIn node) { 493 visitForIn(ast.ForIn node) {
427 // [node.declaredIdentifier] can be either an [ast.VariableDefinitions] 494 // [node.declaredIdentifier] can be either an [ast.VariableDefinitions]
428 // (defining a new local variable) or a send designating some existing 495 // (defining a new local variable) or a send designating some existing
429 // variable. 496 // variable.
430 ast.Node identifier = node.declaredIdentifier; 497 ast.Node identifier = node.declaredIdentifier;
431 ast.VariableDefinitions variableDeclaration = 498 ast.VariableDefinitions variableDeclaration =
432 identifier.asVariableDefinitions(); 499 identifier.asVariableDefinitions();
433 Element variableElement = elements.getForInVariable(node); 500 Element variableElement = elements.getForInVariable(node);
434 Selector selector = elements.getSelector(identifier); 501 Selector selector = elements.getSelector(identifier);
435 502
436 irBuilder.buildForIn( 503 irBuilder.buildForIn(
437 buildExpression: subbuild(node.expression), 504 buildExpression: subbuild(node.expression),
438 buildVariableDeclaration: subbuild(variableDeclaration), 505 buildVariableDeclaration: subbuild(variableDeclaration),
439 variableElement: variableElement, 506 variableElement: variableElement,
440 variableSelector: selector, 507 variableSelector: selector,
441 buildBody: subbuild(node.body), 508 buildBody: subbuild(node.body),
442 target: elements.getTargetDefinition(node)); 509 target: elements.getTargetDefinition(node),
510 closureScope: getClosureScope(node));
443 } 511 }
444 512
445 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { 513 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
446 assert(irBuilder.isOpen); 514 assert(irBuilder.isOpen);
447 if (node.modifiers.isConst) { 515 if (node.modifiers.isConst) {
448 for (ast.SendSet definition in node.definitions.nodes) { 516 for (ast.SendSet definition in node.definitions.nodes) {
449 assert(!definition.arguments.isEmpty); 517 assert(!definition.arguments.isEmpty);
450 assert(definition.arguments.tail.isEmpty); 518 assert(definition.arguments.tail.isEmpty);
451 VariableElement element = elements[definition]; 519 VariableElement element = elements[definition];
452 ConstantExpression value = getConstantForVariable(element); 520 ConstantExpression value = getConstantForVariable(element);
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 } 1011 }
944 1012
945 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) { 1013 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) {
946 assert(irBuilder.isOpen); 1014 assert(irBuilder.isOpen);
947 if (constant == null) { 1015 if (constant == null) {
948 constant = getConstantForNode(node); 1016 constant = getConstantForNode(node);
949 } 1017 }
950 return irBuilder.buildConstantLiteral(constant); 1018 return irBuilder.buildConstantLiteral(constant);
951 } 1019 }
952 1020
953 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { 1021 /// Returns the backend-specific representation of an inner function.
954 FunctionElement element = elements[node]; 1022 Object makeSubFunction(ast.FunctionExpression node) {
955 assert(invariant(element, element.isImplementation)); 1023 if (isJavaScriptBackend) {
1024 ClosureClassMap innerMap =
1025 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1026 ClosureClassElement closureClass = innerMap.closureClassElement;
1027 return closureClass;
1028 } else {
1029 FunctionElement element = elements[node];
1030 assert(invariant(element, element.isImplementation));
956 1031
957 IrBuilder builder = new IrBuilder.innerFunction(irBuilder, element); 1032 IrBuilder builder = irBuilder.makeInnerFunctionBuilder(element);
958 1033
959 return withBuilder(builder, () => _makeFunctionBody(element, node)); 1034 return withBuilder(builder, () => _makeFunctionBody(element, node));
1035 }
960 } 1036 }
961 1037
962 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { 1038 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
963 return irBuilder.buildFunctionExpression(makeSubFunction(node)); 1039 return irBuilder.buildFunctionExpression(makeSubFunction(node));
964 } 1040 }
965 1041
966 visitFunctionDeclaration(ast.FunctionDeclaration node) { 1042 visitFunctionDeclaration(ast.FunctionDeclaration node) {
967 LocalFunctionElement element = elements[node.function]; 1043 LocalFunctionElement element = elements[node.function];
968 ir.FunctionDefinition inner = makeSubFunction(node.function); 1044 Object inner = makeSubFunction(node.function);
969 irBuilder.declareLocalFunction(element, inner); 1045 irBuilder.declareLocalFunction(element, inner);
970 } 1046 }
971 1047
972 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; 1048 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
973 1049
974 dynamic giveup(ast.Node node, [String reason]) { 1050 dynamic giveup(ast.Node node, [String reason]) {
975 throw ABORT_IRNODE_BUILDER; 1051 throw ABORT_IRNODE_BUILDER;
976 } 1052 }
977 1053
978 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { 1054 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
979 try { 1055 try {
980 return action(); 1056 return action();
981 } catch(e, tr) { 1057 } catch(e, tr) {
982 if (e == ABORT_IRNODE_BUILDER) { 1058 if (e == ABORT_IRNODE_BUILDER) {
983 return null; 1059 return null;
984 } 1060 }
985 rethrow; 1061 rethrow;
986 } 1062 }
987 } 1063 }
988 1064
989 void internalError(String reason, {ast.Node node}) { 1065 void internalError(String reason, {ast.Node node}) {
990 giveup(node); 1066 giveup(node);
991 } 1067 }
992 } 1068 }
993 1069
994 /// Classifies local variables and local functions as 'closure variables'. 1070 /// Classifies local variables and local functions as 'closure variables'.
995 /// A closure variable is one that is accessed from an inner function nested 1071 /// A closure variable is one that is accessed from an inner function nested
996 /// one or more levels inside the one that declares it. 1072 /// one or more levels inside the one that declares it.
997 class DetectClosureVariables extends ast.Visitor { 1073 class DetectClosureVariables extends ast.Visitor
1074 implements ClosureVariableInfo {
998 final TreeElements elements; 1075 final TreeElements elements;
999 DetectClosureVariables(this.elements); 1076 DetectClosureVariables(this.elements);
1000 1077
1001 FunctionElement currentFunction; 1078 FunctionElement currentFunction;
1002 bool insideInitializer = false; 1079 bool insideInitializer = false;
1003 Set<Local> usedFromClosure = new Set<Local>(); 1080 Set<Local> capturedVariables = new Set<Local>();
1004 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>();
1005
1006 bool isClosureVariable(Entity entity) => usedFromClosure.contains(entity);
1007 1081
1008 void markAsClosureVariable(Local local) { 1082 void markAsClosureVariable(Local local) {
1009 usedFromClosure.add(local); 1083 capturedVariables.add(local);
1010 } 1084 }
1011 1085
1012 visit(ast.Node node) => node.accept(this); 1086 visit(ast.Node node) => node.accept(this);
1013 1087
1014 visitNode(ast.Node node) { 1088 visitNode(ast.Node node) {
1015 node.visitChildren(this); 1089 node.visitChildren(this);
1016 } 1090 }
1017 1091
1018 void handleSend(ast.Send node) { 1092 void handleSend(ast.Send node) {
1019 Element element = elements[node]; 1093 Element element = elements[node];
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1054 currentFunction = elements[node]; 1128 currentFunction = elements[node];
1055 if (node.initializers != null) { 1129 if (node.initializers != null) {
1056 insideInitializer = true; 1130 insideInitializer = true;
1057 visit(node.initializers); 1131 visit(node.initializers);
1058 insideInitializer = false; 1132 insideInitializer = false;
1059 } 1133 }
1060 visit(node.body); 1134 visit(node.body);
1061 currentFunction = oldFunction; 1135 currentFunction = oldFunction;
1062 } 1136 }
1063 } 1137 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698