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