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 /** | 7 /** |
8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 builder.graph.thisInstruction = thisInstruction; | 268 builder.graph.thisInstruction = thisInstruction; |
269 builder.graph.entry.addAtEntry(thisInstruction); | 269 builder.graph.entry.addAtEntry(thisInstruction); |
270 directLocals[closureData.thisElement] = thisInstruction; | 270 directLocals[closureData.thisElement] = thisInstruction; |
271 } | 271 } |
272 | 272 |
273 // If this method is an intercepted method, add the extra | 273 // If this method is an intercepted method, add the extra |
274 // parameter to it, that is the actual receiver for intercepted | 274 // parameter to it, that is the actual receiver for intercepted |
275 // classes, or the same as [:this:] for non-intercepted classes. | 275 // classes, or the same as [:this:] for non-intercepted classes. |
276 ClassElement cls = element.getEnclosingClass(); | 276 ClassElement cls = element.getEnclosingClass(); |
277 JavaScriptBackend backend = compiler.backend; | 277 JavaScriptBackend backend = compiler.backend; |
| 278 bool isNativeUpgradeFactory = element.isGenerativeConstructor() |
| 279 && Elements.isNativeOrExtendsNative(cls); |
278 if (backend.isInterceptedMethod(element)) { | 280 if (backend.isInterceptedMethod(element)) { |
279 bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); | 281 bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); |
280 SourceString name = isInterceptorClass | 282 SourceString name = isInterceptorClass |
281 ? const SourceString('receiver') | 283 ? const SourceString('receiver') |
282 : const SourceString('_'); | 284 : const SourceString('_'); |
283 Element parameter = new InterceptedElement( | 285 Element parameter = new InterceptedElement( |
284 cls.computeType(compiler), name, element); | 286 cls.computeType(compiler), name, element); |
285 HParameterValue value = new HParameterValue(parameter); | 287 HParameterValue value = new HParameterValue(parameter); |
286 builder.graph.explicitReceiverParameter = value; | 288 builder.graph.explicitReceiverParameter = value; |
287 builder.graph.entry.addAfter( | 289 builder.graph.entry.addAfter( |
288 directLocals[closureData.thisElement], value); | 290 directLocals[closureData.thisElement], value); |
289 if (isInterceptorClass) { | 291 if (isInterceptorClass) { |
290 // Only use the extra parameter in intercepted classes. | 292 // Only use the extra parameter in intercepted classes. |
291 directLocals[closureData.thisElement] = value; | 293 directLocals[closureData.thisElement] = value; |
292 } | 294 } |
293 value.instructionType = builder.getTypeOfThis(); | 295 value.instructionType = builder.getTypeOfThis(); |
| 296 } else if (isNativeUpgradeFactory) { |
| 297 bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); |
| 298 Element parameter = new InterceptedElement( |
| 299 cls.computeType(compiler), const SourceString('receiver'), element); |
| 300 HParameterValue value = new HParameterValue(parameter); |
| 301 builder.graph.explicitReceiverParameter = value; |
| 302 builder.graph.entry.addAtEntry(value); |
| 303 value.instructionType = builder.getTypeOfThis(); |
294 } | 304 } |
295 } | 305 } |
296 | 306 |
297 bool hasValueForDirectLocal(Element element) { | 307 bool hasValueForDirectLocal(Element element) { |
298 assert(element != null); | 308 assert(element != null); |
299 assert(isAccessedDirectly(element)); | 309 assert(isAccessedDirectly(element)); |
300 return directLocals[element] != null; | 310 return directLocals[element] != null; |
301 } | 311 } |
302 | 312 |
303 /** | 313 /** |
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1260 } | 1270 } |
1261 | 1271 |
1262 // Don't inline operator== methods if the parameter can be null. | 1272 // Don't inline operator== methods if the parameter can be null. |
1263 if (element.name == const SourceString('==')) { | 1273 if (element.name == const SourceString('==')) { |
1264 if (element.getEnclosingClass() != compiler.objectClass | 1274 if (element.getEnclosingClass() != compiler.objectClass |
1265 && providedArguments[1].canBeNull()) { | 1275 && providedArguments[1].canBeNull()) { |
1266 return false; | 1276 return false; |
1267 } | 1277 } |
1268 } | 1278 } |
1269 | 1279 |
| 1280 if (element.isGenerativeConstructor()) { |
| 1281 if (Elements.isNativeOrExtendsNative(element.getEnclosingClass())) { |
| 1282 return false; |
| 1283 } |
| 1284 } |
1270 // A generative constructor body is not seen by global analysis, | 1285 // A generative constructor body is not seen by global analysis, |
1271 // so we should not query for its type. | 1286 // so we should not query for its type. |
1272 if (!element.isGenerativeConstructorBody()) { | 1287 if (!element.isGenerativeConstructorBody()) { |
1273 // Don't inline if the return type was inferred to be non-null empty. | 1288 // Don't inline if the return type was inferred to be non-null empty. |
1274 // This means that the function always throws an exception. | 1289 // This means that the function always throws an exception. |
1275 TypeMask returnType = | 1290 TypeMask returnType = |
1276 compiler.typesTask.getGuaranteedReturnTypeOfElement(element); | 1291 compiler.typesTask.getGuaranteedReturnTypeOfElement(element); |
1277 if (returnType != null | 1292 if (returnType != null |
1278 && returnType.isEmpty | 1293 && returnType.isEmpty |
1279 && !returnType.isNullable) { | 1294 && !returnType.isNullable) { |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1579 */ | 1594 */ |
1580 void buildFieldInitializers(ClassElement classElement, | 1595 void buildFieldInitializers(ClassElement classElement, |
1581 Map<Element, HInstruction> fieldValues) { | 1596 Map<Element, HInstruction> fieldValues) { |
1582 assert(invariant(classElement, classElement.isImplementation)); | 1597 assert(invariant(classElement, classElement.isImplementation)); |
1583 classElement.forEachInstanceField( | 1598 classElement.forEachInstanceField( |
1584 (ClassElement enclosingClass, Element member) { | 1599 (ClassElement enclosingClass, Element member) { |
1585 compiler.withCurrentElement(member, () { | 1600 compiler.withCurrentElement(member, () { |
1586 TreeElements definitions = compiler.analyzeElement(member); | 1601 TreeElements definitions = compiler.analyzeElement(member); |
1587 Node node = member.parseNode(compiler); | 1602 Node node = member.parseNode(compiler); |
1588 SendSet assignment = node.asSendSet(); | 1603 SendSet assignment = node.asSendSet(); |
1589 HInstruction value; | |
1590 if (assignment == null) { | 1604 if (assignment == null) { |
1591 value = graph.addConstantNull(compiler); | 1605 // Unassigned fields of native classes are not initialized to |
| 1606 // prevent overwriting pre-initialized native properties. |
| 1607 if (!Elements.isNativeOrExtendsNative(classElement)) { |
| 1608 HInstruction value = graph.addConstantNull(compiler); |
| 1609 fieldValues[member] = value; |
| 1610 } |
1592 } else { | 1611 } else { |
1593 Node right = assignment.arguments.head; | 1612 Node right = assignment.arguments.head; |
1594 TreeElements savedElements = elements; | 1613 TreeElements savedElements = elements; |
1595 elements = definitions; | 1614 elements = definitions; |
1596 // In case the field initializer uses closures, run the | 1615 // In case the field initializer uses closures, run the |
1597 // closure to class mapper. | 1616 // closure to class mapper. |
1598 compiler.closureToClassMapper.computeClosureToClassMapping( | 1617 compiler.closureToClassMapper.computeClosureToClassMapping( |
1599 member, node, elements); | 1618 member, node, elements); |
1600 inlinedFrom(member, () => right.accept(this)); | 1619 inlinedFrom(member, () => right.accept(this)); |
1601 elements = savedElements; | 1620 elements = savedElements; |
1602 value = pop(); | 1621 HInstruction value = pop(); |
| 1622 fieldValues[member] = value; |
1603 } | 1623 } |
1604 fieldValues[member] = value; | |
1605 }); | 1624 }); |
1606 }); | 1625 }); |
1607 } | 1626 } |
1608 | 1627 |
1609 /** | 1628 /** |
1610 * Build the factory function corresponding to the constructor | 1629 * Build the factory function corresponding to the constructor |
1611 * [functionElement]: | 1630 * [functionElement]: |
1612 * - Initialize fields with the values of the field initializers of the | 1631 * - Initialize fields with the values of the field initializers of the |
1613 * current constructor and super constructors or constructors redirected | 1632 * current constructor and super constructors or constructors redirected |
1614 * to, starting from the current constructor. | 1633 * to, starting from the current constructor. |
1615 * - Call the constructor bodies, starting from the constructor(s) in the | 1634 * - Call the constructor bodies, starting from the constructor(s) in the |
1616 * super class(es). | 1635 * super class(es). |
1617 */ | 1636 */ |
1618 HGraph buildFactory(FunctionElement functionElement) { | 1637 HGraph buildFactory(FunctionElement functionElement) { |
1619 functionElement = functionElement.implementation; | 1638 functionElement = functionElement.implementation; |
1620 ClassElement classElement = | 1639 ClassElement classElement = |
1621 functionElement.getEnclosingClass().implementation; | 1640 functionElement.getEnclosingClass().implementation; |
| 1641 bool isNativeUpgradeFactory = |
| 1642 Elements.isNativeOrExtendsNative(classElement); |
1622 FunctionExpression function = functionElement.parseNode(compiler); | 1643 FunctionExpression function = functionElement.parseNode(compiler); |
1623 // Note that constructors (like any other static function) do not need | 1644 // Note that constructors (like any other static function) do not need |
1624 // to deal with optional arguments. It is the callers job to provide all | 1645 // to deal with optional arguments. It is the callers job to provide all |
1625 // arguments as if they were positional. | 1646 // arguments as if they were positional. |
1626 | 1647 |
1627 if (inliningStack.isEmpty) { | 1648 if (inliningStack.isEmpty) { |
1628 // The initializer list could contain closures. | 1649 // The initializer list could contain closures. |
1629 openFunction(functionElement, function); | 1650 openFunction(functionElement, function); |
1630 } | 1651 } |
1631 | 1652 |
(...skipping 15 matching lines...) Expand all Loading... |
1647 } | 1668 } |
1648 }); | 1669 }); |
1649 | 1670 |
1650 // Analyze the constructor and all referenced constructors and collect | 1671 // Analyze the constructor and all referenced constructors and collect |
1651 // initializers and constructor bodies. | 1672 // initializers and constructor bodies. |
1652 List<FunctionElement> constructors = <FunctionElement>[functionElement]; | 1673 List<FunctionElement> constructors = <FunctionElement>[functionElement]; |
1653 buildInitializers(functionElement, constructors, fieldValues); | 1674 buildInitializers(functionElement, constructors, fieldValues); |
1654 | 1675 |
1655 // Call the JavaScript constructor with the fields as argument. | 1676 // Call the JavaScript constructor with the fields as argument. |
1656 List<HInstruction> constructorArguments = <HInstruction>[]; | 1677 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 1678 List<FieldElement> fields = <FieldElement>[]; |
| 1679 |
1657 classElement.forEachInstanceField( | 1680 classElement.forEachInstanceField( |
1658 (ClassElement enclosingClass, Element member) { | 1681 (ClassElement enclosingClass, Element member) { |
1659 constructorArguments.add(potentiallyCheckType( | 1682 HInstruction value = fieldValues[member]; |
1660 fieldValues[member], member.computeType(compiler))); | 1683 if (value == null) { |
| 1684 // Uninitialized native fields are pre-initialized by the native |
| 1685 // implementation. |
| 1686 assert(isNativeUpgradeFactory); |
| 1687 } else { |
| 1688 fields.add(member); |
| 1689 constructorArguments.add( |
| 1690 potentiallyCheckType(value, member.computeType(compiler))); |
| 1691 } |
1661 }, | 1692 }, |
1662 includeSuperAndInjectedMembers: true); | 1693 includeSuperAndInjectedMembers: true); |
1663 | 1694 |
1664 InterfaceType type = classElement.computeType(compiler); | 1695 InterfaceType type = classElement.computeType(compiler); |
1665 HType ssaType = new HType.nonNullExact(classElement, compiler); | 1696 HType ssaType = new HType.nonNullExact(classElement, compiler); |
1666 List<DartType> instantiatedTypes; | 1697 List<DartType> instantiatedTypes; |
1667 addInlinedInstantiation(type); | 1698 addInlinedInstantiation(type); |
1668 if (!currentInlinedInstantiations.isEmpty) { | 1699 if (!currentInlinedInstantiations.isEmpty) { |
1669 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); | 1700 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); |
1670 } | 1701 } |
1671 HForeignNew newObject = new HForeignNew(classElement, | 1702 |
1672 ssaType, | 1703 HInstruction newObject; |
1673 constructorArguments, | 1704 if (!isNativeUpgradeFactory) { |
1674 instantiatedTypes); | 1705 newObject = new HForeignNew(classElement, |
1675 add(newObject); | 1706 ssaType, |
| 1707 constructorArguments, |
| 1708 instantiatedTypes); |
| 1709 add(newObject); |
| 1710 } else { |
| 1711 // Bulk assign to the initialized fields. |
| 1712 newObject = graph.explicitReceiverParameter; |
| 1713 for (int i = 0; i < fields.length; i++) { |
| 1714 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); |
| 1715 } |
| 1716 } |
1676 removeInlinedInstantiation(type); | 1717 removeInlinedInstantiation(type); |
1677 // Create the runtime type information, if needed. | 1718 // Create the runtime type information, if needed. |
1678 if (backend.classNeedsRti(classElement)) { | 1719 if (backend.classNeedsRti(classElement)) { |
1679 List<HInstruction> rtiInputs = <HInstruction>[]; | 1720 List<HInstruction> rtiInputs = <HInstruction>[]; |
1680 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1721 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
1681 rtiInputs.add(localsHandler.readLocal(typeVariable.element)); | 1722 rtiInputs.add(localsHandler.readLocal(typeVariable.element)); |
1682 }); | 1723 }); |
1683 callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); | 1724 callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); |
1684 } | 1725 } |
1685 | 1726 |
1686 // Generate calls to the constructor bodies. | 1727 // Generate calls to the constructor bodies. |
| 1728 HInstruction interceptor = null; |
1687 for (int index = constructors.length - 1; index >= 0; index--) { | 1729 for (int index = constructors.length - 1; index >= 0; index--) { |
1688 FunctionElement constructor = constructors[index]; | 1730 FunctionElement constructor = constructors[index]; |
1689 assert(invariant(functionElement, constructor.isImplementation)); | 1731 assert(invariant(functionElement, constructor.isImplementation)); |
1690 ConstructorBodyElement body = getConstructorBody(constructor); | 1732 ConstructorBodyElement body = getConstructorBody(constructor); |
1691 if (body == null) continue; | 1733 if (body == null) continue; |
| 1734 |
1692 List bodyCallInputs = <HInstruction>[]; | 1735 List bodyCallInputs = <HInstruction>[]; |
| 1736 if (isNativeUpgradeFactory) { |
| 1737 if (interceptor == null) { |
| 1738 Constant constant = new InterceptorConstant( |
| 1739 classElement.computeType(compiler)); |
| 1740 interceptor = graph.addConstant(constant, compiler); |
| 1741 } |
| 1742 bodyCallInputs.add(interceptor); |
| 1743 } |
1693 bodyCallInputs.add(newObject); | 1744 bodyCallInputs.add(newObject); |
1694 TreeElements elements = | 1745 TreeElements elements = |
1695 compiler.enqueuer.resolution.getCachedElements(constructor); | 1746 compiler.enqueuer.resolution.getCachedElements(constructor); |
1696 Node node = constructor.parseNode(compiler); | 1747 Node node = constructor.parseNode(compiler); |
1697 ClosureClassMap parameterClosureData = | 1748 ClosureClassMap parameterClosureData = |
1698 compiler.closureToClassMapper.getMappingForNestedFunction(node); | 1749 compiler.closureToClassMapper.getMappingForNestedFunction(node); |
1699 | 1750 |
1700 | |
1701 FunctionSignature functionSignature = body.computeSignature(compiler); | 1751 FunctionSignature functionSignature = body.computeSignature(compiler); |
1702 // Provide the parameters to the generative constructor body. | 1752 // Provide the parameters to the generative constructor body. |
1703 functionSignature.orderedForEachParameter((parameter) { | 1753 functionSignature.orderedForEachParameter((parameter) { |
1704 // If [parameter] is boxed, it will be a field in the box passed as the | 1754 // If [parameter] is boxed, it will be a field in the box passed as the |
1705 // last parameter. So no need to directly pass it. | 1755 // last parameter. So no need to directly pass it. |
1706 if (!localsHandler.isBoxed(parameter)) { | 1756 if (!localsHandler.isBoxed(parameter)) { |
1707 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 1757 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
1708 } | 1758 } |
1709 }); | 1759 }); |
1710 | 1760 |
1711 ClassElement currentClass = constructor.getEnclosingClass(); | 1761 ClassElement currentClass = constructor.getEnclosingClass(); |
1712 if (backend.classNeedsRti(currentClass)) { | 1762 if (backend.classNeedsRti(currentClass)) { |
1713 // If [currentClass] needs RTI, we add the type variables as | 1763 // If [currentClass] needs RTI, we add the type variables as |
1714 // parameters of the generative constructor body. | 1764 // parameters of the generative constructor body. |
1715 currentClass.typeVariables.forEach((DartType argument) { | 1765 currentClass.typeVariables.forEach((DartType argument) { |
1716 bodyCallInputs.add(localsHandler.readLocal(argument.element)); | 1766 bodyCallInputs.add(localsHandler.readLocal(argument.element)); |
1717 }); | 1767 }); |
1718 } | 1768 } |
1719 | 1769 |
1720 // If there are locals that escape (ie mutated in closures), we | 1770 // If there are locals that escape (ie mutated in closures), we |
1721 // pass the box to the constructor. | 1771 // pass the box to the constructor. |
1722 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; | 1772 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; |
1723 if (scopeData != null) { | 1773 if (scopeData != null) { |
1724 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); | 1774 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); |
1725 } | 1775 } |
1726 | 1776 |
1727 if (tryInlineMethod(body, null, bodyCallInputs, function)) { | 1777 if (!isNativeUpgradeFactory && // TODO(sra): Fix inlining. |
| 1778 tryInlineMethod(body, null, bodyCallInputs, function)) { |
1728 pop(); | 1779 pop(); |
1729 } else { | 1780 } else { |
1730 HInvokeConstructorBody invoke = | 1781 HInvokeConstructorBody invoke = |
1731 new HInvokeConstructorBody(body.declaration, bodyCallInputs); | 1782 new HInvokeConstructorBody(body.declaration, bodyCallInputs); |
1732 invoke.sideEffects = | 1783 invoke.sideEffects = |
1733 compiler.world.getSideEffectsOfElement(constructor); | 1784 compiler.world.getSideEffectsOfElement(constructor); |
1734 add(invoke); | 1785 add(invoke); |
1735 } | 1786 } |
1736 } | 1787 } |
1737 if (inliningStack.isEmpty) { | 1788 if (inliningStack.isEmpty) { |
(...skipping 3817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5555 new HSubGraphBlockInformation(elseBranch.graph)); | 5606 new HSubGraphBlockInformation(elseBranch.graph)); |
5556 | 5607 |
5557 HBasicBlock conditionStartBlock = conditionBranch.block; | 5608 HBasicBlock conditionStartBlock = conditionBranch.block; |
5558 conditionStartBlock.setBlockFlow(info, joinBlock); | 5609 conditionStartBlock.setBlockFlow(info, joinBlock); |
5559 SubGraph conditionGraph = conditionBranch.graph; | 5610 SubGraph conditionGraph = conditionBranch.graph; |
5560 HIf branch = conditionGraph.end.last; | 5611 HIf branch = conditionGraph.end.last; |
5561 assert(branch is HIf); | 5612 assert(branch is HIf); |
5562 branch.blockInformation = conditionStartBlock.blockFlow; | 5613 branch.blockInformation = conditionStartBlock.blockFlow; |
5563 } | 5614 } |
5564 } | 5615 } |
OLD | NEW |