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

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

Issue 25675002: Generative constructor factories for native objects (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months 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 /** 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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698