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

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 box = createBox();
339 }
334 // Add the box to the known locals. 340 // Add the box to the known locals.
335 directLocals[scopeData.boxElement] = box; 341 directLocals[scopeData.boxElement] = box;
336 // Make sure that accesses to the boxed locals go into the box. We also 342 // 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. 343 // need to make sure that parameters are copied into the box if necessary.
338 scopeData.capturedVariableMapping.forEach((Element from, Element to) { 344 scopeData.capturedVariableMapping.forEach((Element from, Element to) {
339 // The [from] can only be a parameter for function-scopes and not 345 // The [from] can only be a parameter for function-scopes and not
340 // loop scopes. 346 // loop scopes.
341 if (from.isParameter()) { 347 if (from.isParameter()) {
342 // Store the captured parameter in the box. Get the current value 348 // Store the captured parameter in the box. Get the current value
343 // before we put the redirection in place. 349 // 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); 397 HInstruction parameter = new HParameterValue(parameterElement);
392 builder.add(parameter); 398 builder.add(parameter);
393 builder.parameters[parameterElement] = parameter; 399 builder.parameters[parameterElement] = parameter;
394 directLocals[parameterElement] = parameter; 400 directLocals[parameterElement] = parameter;
395 parameter.guaranteedType = 401 parameter.guaranteedType =
396 builder.mapInferredType( 402 builder.mapInferredType(
397 typesTask.getGuaranteedTypeOfElement(parameterElement)); 403 typesTask.getGuaranteedTypeOfElement(parameterElement));
398 }); 404 });
399 } 405 }
400 406
401 enterScope(node); 407 enterScope(node, element);
402 408
403 // If the freeVariableMapping is not empty, then this function was a 409 // If the freeVariableMapping is not empty, then this function was a
404 // nested closure that captures variables. Redirect the captured 410 // nested closure that captures variables. Redirect the captured
405 // variables to fields in the closure. 411 // variables to fields in the closure.
406 closureData.freeVariableMapping.forEach((Element from, Element to) { 412 closureData.freeVariableMapping.forEach((Element from, Element to) {
407 redirectElement(from, to); 413 redirectElement(from, to);
408 }); 414 });
409 if (closureData.isClosure()) { 415 if (closureData.isClosure()) {
410 // Inside closure redirect references to itself to [:this:]. 416 // Inside closure redirect references to itself to [:this:].
411 HInstruction thisInstruction = new HThis(); 417 HInstruction thisInstruction = new HThis();
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 * loop-exit: 609 * loop-exit:
604 */ 610 */
605 void startLoop(Node node) { 611 void startLoop(Node node) {
606 ClosureScope scopeData = closureData.capturingScopes[node]; 612 ClosureScope scopeData = closureData.capturingScopes[node];
607 if (scopeData == null) return; 613 if (scopeData == null) return;
608 if (scopeData.hasBoxedLoopVariables()) { 614 if (scopeData.hasBoxedLoopVariables()) {
609 // If there are boxed loop variables then we set up the box and 615 // If there are boxed loop variables then we set up the box and
610 // redirections already now. This way the initializer can write its 616 // redirections already now. This way the initializer can write its
611 // values into the box. 617 // values into the box.
612 // For other loops the box will be created when entering the body. 618 // For other loops the box will be created when entering the body.
613 enterScope(node); 619 enterScope(node, null);
614 } 620 }
615 } 621 }
616 622
617 void beginLoopHeader(Node node, HBasicBlock loopEntry) { 623 void beginLoopHeader(Node node, HBasicBlock loopEntry) {
618 // Create a copy because we modify the map while iterating over 624 // Create a copy because we modify the map while iterating over
619 // it. 625 // it.
620 Map<Element, HInstruction> saved = 626 Map<Element, HInstruction> saved =
621 new Map<Element, HInstruction>.from(directLocals); 627 new Map<Element, HInstruction>.from(directLocals);
622 628
623 // Create phis for all elements in the definitions environment. 629 // Create phis for all elements in the definitions environment.
(...skipping 10 matching lines...) Expand all
634 } 640 }
635 }); 641 });
636 } 642 }
637 643
638 void enterLoopBody(Node node) { 644 void enterLoopBody(Node node) {
639 ClosureScope scopeData = closureData.capturingScopes[node]; 645 ClosureScope scopeData = closureData.capturingScopes[node];
640 if (scopeData == null) return; 646 if (scopeData == null) return;
641 // If there are no declared boxed loop variables then we did not create the 647 // 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. 648 // box before the initializer and we have to create the box now.
643 if (!scopeData.hasBoxedLoopVariables()) { 649 if (!scopeData.hasBoxedLoopVariables()) {
644 enterScope(node); 650 enterScope(node, null);
645 } 651 }
646 } 652 }
647 653
648 void enterLoopUpdates(Loop node) { 654 void enterLoopUpdates(Loop node) {
649 // If there are declared boxed loop variables then the updates might have 655 // 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 656 // access to the box and we must switch to a new box before executing the
651 // updates. 657 // updates.
652 // In all other cases a new box will be created when entering the body of 658 // In all other cases a new box will be created when entering the body of
653 // the next iteration. 659 // the next iteration.
654 ClosureScope scopeData = closureData.capturingScopes[node]; 660 ClosureScope scopeData = closureData.capturingScopes[node];
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 fieldValues[fieldParameterElement.fieldElement] = argument; 1169 fieldValues[fieldParameterElement.fieldElement] = argument;
1164 } 1170 }
1165 }); 1171 });
1166 1172
1167 // Build the initializers in the context of the new constructor. 1173 // Build the initializers in the context of the new constructor.
1168 TreeElements oldElements = elements; 1174 TreeElements oldElements = elements;
1169 elements = 1175 elements =
1170 compiler.enqueuer.resolution.getCachedElements(constructor); 1176 compiler.enqueuer.resolution.getCachedElements(constructor);
1171 1177
1172 ClosureClassMap oldClosureData = localsHandler.closureData; 1178 ClosureClassMap oldClosureData = localsHandler.closureData;
1179 Node node = constructor.parseNode(compiler);
1173 localsHandler.closureData = 1180 localsHandler.closureData =
1174 compiler.closureToClassMapper.computeClosureToClassMapping( 1181 compiler.closureToClassMapper.computeClosureToClassMapping(
1175 constructor, constructor.parseNode(compiler), elements); 1182 constructor, node, elements);
1176 1183
1177 params.orderedForEachParameter((Element parameterElement) { 1184 params.orderedForEachParameter((Element parameterElement) {
1178 if (elements.isParameterChecked(parameterElement)) { 1185 if (elements.isParameterChecked(parameterElement)) {
1179 addParameterCheckInstruction(parameterElement); 1186 addParameterCheckInstruction(parameterElement);
1180 } 1187 }
1181 }); 1188 });
1182 1189 localsHandler.enterScope(node, constructor);
1183 buildInitializers(constructor, constructors, fieldValues); 1190 buildInitializers(constructor, constructors, fieldValues);
1184 localsHandler.closureData = oldClosureData; 1191 localsHandler.closureData = oldClosureData;
1185 elements = oldElements; 1192 elements = oldElements;
1186 }); 1193 });
1187 } 1194 }
1188 1195
1189 /** 1196 /**
1190 * Run through the initializers and inline all field initializers. Recursively 1197 * Run through the initializers and inline all field initializers. Recursively
1191 * inlines super initializers. 1198 * inlines super initializers.
1192 * 1199 *
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 for (int index = constructors.length - 1; index >= 0; index--) { 1369 for (int index = constructors.length - 1; index >= 0; index--) {
1363 FunctionElement constructor = constructors[index]; 1370 FunctionElement constructor = constructors[index];
1364 assert(invariant(functionElement, constructor.isImplementation)); 1371 assert(invariant(functionElement, constructor.isImplementation));
1365 ConstructorBodyElement body = getConstructorBody(constructor); 1372 ConstructorBodyElement body = getConstructorBody(constructor);
1366 if (body == null) continue; 1373 if (body == null) continue;
1367 List bodyCallInputs = <HInstruction>[]; 1374 List bodyCallInputs = <HInstruction>[];
1368 bodyCallInputs.add(newObject); 1375 bodyCallInputs.add(newObject);
1369 FunctionSignature functionSignature = body.computeSignature(compiler); 1376 FunctionSignature functionSignature = body.computeSignature(compiler);
1370 int arity = functionSignature.parameterCount; 1377 int arity = functionSignature.parameterCount;
1371 functionSignature.orderedForEachParameter((parameter) { 1378 functionSignature.orderedForEachParameter((parameter) {
1379 // TODO(ngeoffray): No need to pass the parameters that are
1380 // captured and stored in a box. Because this information is
1381 // not trivial to get in codegen.dart, we just pass the
1382 // parameters anyway. We need to update both codegen.dart and
1383 // builder.dart on how parameters are being passed.
1372 bodyCallInputs.add(localsHandler.readLocal(parameter)); 1384 bodyCallInputs.add(localsHandler.readLocal(parameter));
1373 }); 1385 });
1374 1386
1375 // If parameters are checked, we pass the already computed 1387 // If parameters are checked, we pass the already computed
1376 // boolean to the constructor body. 1388 // boolean to the constructor body.
1377 TreeElements elements = 1389 TreeElements elements =
1378 compiler.enqueuer.resolution.getCachedElements(constructor); 1390 compiler.enqueuer.resolution.getCachedElements(constructor);
1379 Node node = constructor.parseNode(compiler); 1391 Node node = constructor.parseNode(compiler);
1380 ClosureClassMap parameterClosureData = 1392 ClosureClassMap parameterClosureData =
1381 compiler.closureToClassMapper.getMappingForNestedFunction(node); 1393 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1382 functionSignature.orderedForEachParameter((parameter) { 1394 functionSignature.orderedForEachParameter((parameter) {
1383 if (elements.isParameterChecked(parameter)) { 1395 if (elements.isParameterChecked(parameter)) {
1384 Element fieldCheck = 1396 Element fieldCheck =
1385 parameterClosureData.parametersWithSentinel[parameter]; 1397 parameterClosureData.parametersWithSentinel[parameter];
1386 bodyCallInputs.add(localsHandler.readLocal(fieldCheck)); 1398 bodyCallInputs.add(localsHandler.readLocal(fieldCheck));
1387 } 1399 }
1388 }); 1400 });
1389 1401
1402 // If there are locals that escape (ie used in closures), we
1403 // pass the box to the constructor.
1404 ClosureScope scopeData = parameterClosureData.capturingScopes[node];
1405 if (scopeData != null) {
1406 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement));
1407 }
1408
1390 // TODO(ahe): The constructor name is statically resolved. See 1409 // TODO(ahe): The constructor name is statically resolved. See
1391 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner 1410 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner
1392 // way to do this? 1411 // way to do this?
1393 SourceString name = 1412 SourceString name =
1394 new SourceString(backend.namer.getName(body.declaration)); 1413 new SourceString(backend.namer.getName(body.declaration));
1395 // TODO(kasperl): This seems fishy. We shouldn't be inventing all 1414 // TODO(kasperl): This seems fishy. We shouldn't be inventing all
1396 // these selectors. Maybe the resolver can do more of the work 1415 // these selectors. Maybe the resolver can do more of the work
1397 // for us here? 1416 // for us here?
1398 LibraryElement library = body.getLibrary(); 1417 LibraryElement library = body.getLibrary();
1399 Selector selector = new Selector.call(name, library, arity); 1418 Selector selector = new Selector.call(name, library, arity);
(...skipping 3184 matching lines...) Expand 10 before | Expand all | Expand 10 after
4584 new HSubGraphBlockInformation(elseBranch.graph)); 4603 new HSubGraphBlockInformation(elseBranch.graph));
4585 4604
4586 HBasicBlock conditionStartBlock = conditionBranch.block; 4605 HBasicBlock conditionStartBlock = conditionBranch.block;
4587 conditionStartBlock.setBlockFlow(info, joinBlock); 4606 conditionStartBlock.setBlockFlow(info, joinBlock);
4588 SubGraph conditionGraph = conditionBranch.graph; 4607 SubGraph conditionGraph = conditionBranch.graph;
4589 HIf branch = conditionGraph.end.last; 4608 HIf branch = conditionGraph.end.last;
4590 assert(branch is HIf); 4609 assert(branch is HIf);
4591 branch.blockInformation = conditionStartBlock.blockFlow; 4610 branch.blockInformation = conditionStartBlock.blockFlow;
4592 } 4611 }
4593 } 4612 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698