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

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 11273121: Support closures inside initializers. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 ssa; 5 part of ssa;
6 6
7 class Interceptors { 7 class Interceptors {
8 Compiler compiler; 8 Compiler compiler;
9 Interceptors(Compiler this.compiler); 9 Interceptors(Compiler this.compiler);
10 10
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 const LiteralDartString('Object'), 315 const LiteralDartString('Object'),
316 <HInstruction>[]); 316 <HInstruction>[]);
317 builder.add(box); 317 builder.add(box);
318 return box; 318 return box;
319 } 319 }
320 320
321 /** 321 /**
322 * If the scope (function or loop) [node] has captured variables then this 322 * If the scope (function or loop) [node] has captured variables then this
323 * method creates a box and sets up the redirections. 323 * method creates a box and sets up the redirections.
324 */ 324 */
325 void enterScope(Node node) { 325 void enterScope(Node node, Element element) {
326 // See if any variable in the top-scope of the function is captured. If yes 326 // See if any variable in the top-scope of the function is captured. If yes
327 // we need to create a box-object. 327 // we need to create a box-object.
328 ClosureScope scopeData = closureData.capturingScopes[node]; 328 ClosureScope scopeData = closureData.capturingScopes[node];
329 if (scopeData != null) { 329 if (scopeData != null) {
330 // The scope has captured variables. Create a box. 330 HInstruction box;
331 // TODO(floitsch): Clean up this hack. Should we create a box-object by 331 // The scope has captured variables.
332 // just creating an empty object literal? 332 if (element != null && element.isGenerativeConstructorBody()) {
333 HInstruction box = createBox(); 333 // The box is passed as a parameter to a generative
334 // constructor body.
335 box = new HParameterValue(scopeData.boxElement);
336 builder.add(box);
337 } else {
338 // Create a box.
kasperl 2012/10/31 08:25:46 Remove this comment. It's obvious from the code.
ngeoffray 2012/10/31 09:04:28 Done.
339 // TODO(floitsch): Clean up this hack. Should we create a box-object by
floitsch 2012/10/31 10:14:50 please remove this comment.
ngeoffray 2012/10/31 11:28:39 Done.
340 // just creating an empty object literal?
341 box = createBox();
342 }
334 // Add the box to the known locals. 343 // Add the box to the known locals.
335 directLocals[scopeData.boxElement] = box; 344 directLocals[scopeData.boxElement] = box;
336 // Make sure that accesses to the boxed locals go into the box. We also 345 // Make sure that accesses to the boxed locals go into the box. We also
337 // need to make sure that parameters are copied into the box if necessary. 346 // need to make sure that parameters are copied into the box if necessary.
338 scopeData.capturedVariableMapping.forEach((Element from, Element to) { 347 scopeData.capturedVariableMapping.forEach((Element from, Element to) {
339 // The [from] can only be a parameter for function-scopes and not 348 // The [from] can only be a parameter for function-scopes and not
340 // loop scopes. 349 // loop scopes.
341 if (from.isParameter()) { 350 if (from.isParameter()) {
342 // Store the captured parameter in the box. Get the current value 351 // Store the captured parameter in the box. Get the current value
343 // before we put the redirection in place. 352 // before we put the redirection in place.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 HInstruction parameter = new HParameterValue(parameterElement); 400 HInstruction parameter = new HParameterValue(parameterElement);
392 builder.add(parameter); 401 builder.add(parameter);
393 builder.parameters[parameterElement] = parameter; 402 builder.parameters[parameterElement] = parameter;
394 directLocals[parameterElement] = parameter; 403 directLocals[parameterElement] = parameter;
395 parameter.guaranteedType = 404 parameter.guaranteedType =
396 builder.mapInferredType( 405 builder.mapInferredType(
397 typesTask.getGuaranteedTypeOfElement(parameterElement)); 406 typesTask.getGuaranteedTypeOfElement(parameterElement));
398 }); 407 });
399 } 408 }
400 409
401 enterScope(node); 410 enterScope(node, element);
402 411
403 // If the freeVariableMapping is not empty, then this function was a 412 // If the freeVariableMapping is not empty, then this function was a
404 // nested closure that captures variables. Redirect the captured 413 // nested closure that captures variables. Redirect the captured
405 // variables to fields in the closure. 414 // variables to fields in the closure.
406 closureData.freeVariableMapping.forEach((Element from, Element to) { 415 closureData.freeVariableMapping.forEach((Element from, Element to) {
407 redirectElement(from, to); 416 redirectElement(from, to);
408 }); 417 });
409 if (closureData.isClosure()) { 418 if (closureData.isClosure()) {
410 // Inside closure redirect references to itself to [:this:]. 419 // Inside closure redirect references to itself to [:this:].
411 HInstruction thisInstruction = new HThis(); 420 HInstruction thisInstruction = new HThis();
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 * loop-exit: 612 * loop-exit:
604 */ 613 */
605 void startLoop(Node node) { 614 void startLoop(Node node) {
606 ClosureScope scopeData = closureData.capturingScopes[node]; 615 ClosureScope scopeData = closureData.capturingScopes[node];
607 if (scopeData == null) return; 616 if (scopeData == null) return;
608 if (scopeData.hasBoxedLoopVariables()) { 617 if (scopeData.hasBoxedLoopVariables()) {
609 // If there are boxed loop variables then we set up the box and 618 // If there are boxed loop variables then we set up the box and
610 // redirections already now. This way the initializer can write its 619 // redirections already now. This way the initializer can write its
611 // values into the box. 620 // values into the box.
612 // For other loops the box will be created when entering the body. 621 // For other loops the box will be created when entering the body.
613 enterScope(node); 622 enterScope(node, null);
614 } 623 }
615 } 624 }
616 625
617 void beginLoopHeader(Node node, HBasicBlock loopEntry) { 626 void beginLoopHeader(Node node, HBasicBlock loopEntry) {
618 // Create a copy because we modify the map while iterating over 627 // Create a copy because we modify the map while iterating over
619 // it. 628 // it.
620 Map<Element, HInstruction> saved = 629 Map<Element, HInstruction> saved =
621 new Map<Element, HInstruction>.from(directLocals); 630 new Map<Element, HInstruction>.from(directLocals);
622 631
623 // Create phis for all elements in the definitions environment. 632 // Create phis for all elements in the definitions environment.
(...skipping 10 matching lines...) Expand all
634 } 643 }
635 }); 644 });
636 } 645 }
637 646
638 void enterLoopBody(Node node) { 647 void enterLoopBody(Node node) {
639 ClosureScope scopeData = closureData.capturingScopes[node]; 648 ClosureScope scopeData = closureData.capturingScopes[node];
640 if (scopeData == null) return; 649 if (scopeData == null) return;
641 // If there are no declared boxed loop variables then we did not create the 650 // If there are no declared boxed loop variables then we did not create the
642 // box before the initializer and we have to create the box now. 651 // box before the initializer and we have to create the box now.
643 if (!scopeData.hasBoxedLoopVariables()) { 652 if (!scopeData.hasBoxedLoopVariables()) {
644 enterScope(node); 653 enterScope(node, null);
645 } 654 }
646 } 655 }
647 656
648 void enterLoopUpdates(Loop node) { 657 void enterLoopUpdates(Loop node) {
649 // If there are declared boxed loop variables then the updates might have 658 // If there are declared boxed loop variables then the updates might have
650 // access to the box and we must switch to a new box before executing the 659 // access to the box and we must switch to a new box before executing the
651 // updates. 660 // updates.
652 // In all other cases a new box will be created when entering the body of 661 // In all other cases a new box will be created when entering the body of
653 // the next iteration. 662 // the next iteration.
654 ClosureScope scopeData = closureData.capturingScopes[node]; 663 ClosureScope scopeData = closureData.capturingScopes[node];
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 fieldValues[fieldParameterElement.fieldElement] = argument; 1174 fieldValues[fieldParameterElement.fieldElement] = argument;
1166 } 1175 }
1167 }); 1176 });
1168 1177
1169 // Build the initializers in the context of the new constructor. 1178 // Build the initializers in the context of the new constructor.
1170 TreeElements oldElements = elements; 1179 TreeElements oldElements = elements;
1171 elements = 1180 elements =
1172 compiler.enqueuer.resolution.getCachedElements(constructor); 1181 compiler.enqueuer.resolution.getCachedElements(constructor);
1173 1182
1174 ClosureClassMap oldClosureData = localsHandler.closureData; 1183 ClosureClassMap oldClosureData = localsHandler.closureData;
1184 Node node = constructor.parseNode(compiler);
1175 localsHandler.closureData = 1185 localsHandler.closureData =
1176 compiler.closureToClassMapper.computeClosureToClassMapping( 1186 compiler.closureToClassMapper.computeClosureToClassMapping(
1177 constructor, constructor.parseNode(compiler), elements); 1187 constructor, node, elements);
1178 1188
1179 params.orderedForEachParameter((Element parameterElement) { 1189 params.orderedForEachParameter((Element parameterElement) {
1180 if (elements.isParameterChecked(parameterElement)) { 1190 if (elements.isParameterChecked(parameterElement)) {
1181 addParameterCheckInstruction(parameterElement); 1191 addParameterCheckInstruction(parameterElement);
1182 } 1192 }
1183 }); 1193 });
1184 1194 localsHandler.enterScope(node, constructor);
1185 buildInitializers(constructor, constructors, fieldValues); 1195 buildInitializers(constructor, constructors, fieldValues);
1186 localsHandler.closureData = oldClosureData; 1196 localsHandler.closureData = oldClosureData;
1187 elements = oldElements; 1197 elements = oldElements;
1188 }); 1198 });
1189 } 1199 }
1190 1200
1191 /** 1201 /**
1192 * Run through the initializers and inline all field initializers. Recursively 1202 * Run through the initializers and inline all field initializers. Recursively
1193 * inlines super initializers. 1203 * inlines super initializers.
1194 * 1204 *
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 for (int index = constructors.length - 1; index >= 0; index--) { 1374 for (int index = constructors.length - 1; index >= 0; index--) {
1365 FunctionElement constructor = constructors[index]; 1375 FunctionElement constructor = constructors[index];
1366 assert(invariant(functionElement, constructor.isImplementation)); 1376 assert(invariant(functionElement, constructor.isImplementation));
1367 ConstructorBodyElement body = getConstructorBody(constructor); 1377 ConstructorBodyElement body = getConstructorBody(constructor);
1368 if (body == null) continue; 1378 if (body == null) continue;
1369 List bodyCallInputs = <HInstruction>[]; 1379 List bodyCallInputs = <HInstruction>[];
1370 bodyCallInputs.add(newObject); 1380 bodyCallInputs.add(newObject);
1371 FunctionSignature functionSignature = body.computeSignature(compiler); 1381 FunctionSignature functionSignature = body.computeSignature(compiler);
1372 int arity = functionSignature.parameterCount; 1382 int arity = functionSignature.parameterCount;
1373 functionSignature.orderedForEachParameter((parameter) { 1383 functionSignature.orderedForEachParameter((parameter) {
1384 // TODO(ngeoffray): No need to pass the parameters that are
1385 // captured and stored in a box. Because this information is
1386 // not trivial to get in codegen.dart, we just pass the
1387 // parameters anyway. We need to update both codegen.dart and
1388 // builder.dart on how parameters are being passed.
1374 bodyCallInputs.add(localsHandler.readLocal(parameter)); 1389 bodyCallInputs.add(localsHandler.readLocal(parameter));
1375 }); 1390 });
1376 1391
1377 // If parameters are checked, we pass the already computed 1392 // If parameters are checked, we pass the already computed
1378 // boolean to the constructor body. 1393 // boolean to the constructor body.
1379 TreeElements elements = 1394 TreeElements elements =
1380 compiler.enqueuer.resolution.getCachedElements(constructor); 1395 compiler.enqueuer.resolution.getCachedElements(constructor);
1381 Node node = constructor.parseNode(compiler); 1396 Node node = constructor.parseNode(compiler);
1382 ClosureClassMap parameterClosureData = 1397 ClosureClassMap parameterClosureData =
1383 compiler.closureToClassMapper.getMappingForNestedFunction(node); 1398 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1384 functionSignature.orderedForEachParameter((parameter) { 1399 functionSignature.orderedForEachParameter((parameter) {
1385 if (elements.isParameterChecked(parameter)) { 1400 if (elements.isParameterChecked(parameter)) {
1386 Element fieldCheck = 1401 Element fieldCheck =
1387 parameterClosureData.parametersWithSentinel[parameter]; 1402 parameterClosureData.parametersWithSentinel[parameter];
1388 bodyCallInputs.add(localsHandler.readLocal(fieldCheck)); 1403 bodyCallInputs.add(localsHandler.readLocal(fieldCheck));
1389 } 1404 }
1390 }); 1405 });
1391 1406
1407 // If there are locals that escape (ie used in closures), we
1408 // pass the box to the constructor.
1409 ClosureScope scopeData = parameterClosureData.capturingScopes[node];
1410 if (scopeData != null) {
1411 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement));
1412 }
1413
1392 // TODO(ahe): The constructor name is statically resolved. See 1414 // TODO(ahe): The constructor name is statically resolved. See
1393 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner 1415 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner
1394 // way to do this? 1416 // way to do this?
1395 SourceString name = 1417 SourceString name =
1396 new SourceString(backend.namer.getName(body.declaration)); 1418 new SourceString(backend.namer.getName(body.declaration));
1397 // TODO(kasperl): This seems fishy. We shouldn't be inventing all 1419 // TODO(kasperl): This seems fishy. We shouldn't be inventing all
1398 // these selectors. Maybe the resolver can do more of the work 1420 // these selectors. Maybe the resolver can do more of the work
1399 // for us here? 1421 // for us here?
1400 LibraryElement library = body.getLibrary(); 1422 LibraryElement library = body.getLibrary();
1401 Selector selector = new Selector.call(name, library, arity); 1423 Selector selector = new Selector.call(name, library, arity);
(...skipping 3184 matching lines...) Expand 10 before | Expand all | Expand 10 after
4586 new HSubGraphBlockInformation(elseBranch.graph)); 4608 new HSubGraphBlockInformation(elseBranch.graph));
4587 4609
4588 HBasicBlock conditionStartBlock = conditionBranch.block; 4610 HBasicBlock conditionStartBlock = conditionBranch.block;
4589 conditionStartBlock.setBlockFlow(info, joinBlock); 4611 conditionStartBlock.setBlockFlow(info, joinBlock);
4590 SubGraph conditionGraph = conditionBranch.graph; 4612 SubGraph conditionGraph = conditionBranch.graph;
4591 HIf branch = conditionGraph.end.last; 4613 HIf branch = conditionGraph.end.last;
4592 assert(branch is HIf); 4614 assert(branch is HIf);
4593 branch.blockInformation = conditionStartBlock.blockFlow; 4615 branch.blockInformation = conditionStartBlock.blockFlow;
4594 } 4616 }
4595 } 4617 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698