Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |