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 1153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 } | 1164 } |
1165 | 1165 |
1166 FunctionSignature signature = function.computeSignature(compiler); | 1166 FunctionSignature signature = function.computeSignature(compiler); |
1167 signature.orderedForEachParameter((Element parameter) { | 1167 signature.orderedForEachParameter((Element parameter) { |
1168 HInstruction argument = compiledArguments[argumentIndex++]; | 1168 HInstruction argument = compiledArguments[argumentIndex++]; |
1169 newLocalsHandler.updateLocal(parameter, argument); | 1169 newLocalsHandler.updateLocal(parameter, argument); |
1170 }); | 1170 }); |
1171 | 1171 |
1172 ClassElement enclosing = function.getEnclosingClass(); | 1172 ClassElement enclosing = function.getEnclosingClass(); |
1173 if ((function.isConstructor() || function.isGenerativeConstructorBody()) | 1173 if ((function.isConstructor() || function.isGenerativeConstructorBody()) |
1174 && backend.needsRti(enclosing)) { | 1174 && backend.classNeedsRti(enclosing)) { |
1175 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1175 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
1176 HInstruction argument = compiledArguments[argumentIndex++]; | 1176 HInstruction argument = compiledArguments[argumentIndex++]; |
1177 newLocalsHandler.updateLocal(typeVariable.element, argument); | 1177 newLocalsHandler.updateLocal(typeVariable.element, argument); |
1178 }); | 1178 }); |
1179 } | 1179 } |
1180 assert(argumentIndex == compiledArguments.length); | 1180 assert(argumentIndex == compiledArguments.length); |
1181 | 1181 |
1182 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. | 1182 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. |
1183 returnElement = new ElementX(const SourceString("result"), | 1183 returnElement = new ElementX(const SourceString("result"), |
1184 ElementKind.VARIABLE, | 1184 ElementKind.VARIABLE, |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1329 compiledArguments)); | 1329 compiledArguments)); |
1330 if (!succeeded) { | 1330 if (!succeeded) { |
1331 // Non-matching super and redirects are compile-time errors and thus | 1331 // Non-matching super and redirects are compile-time errors and thus |
1332 // checked by the resolver. | 1332 // checked by the resolver. |
1333 compiler.internalError( | 1333 compiler.internalError( |
1334 "Parameters and arguments didn't match for super/redirect call", | 1334 "Parameters and arguments didn't match for super/redirect call", |
1335 element: constructor); | 1335 element: constructor); |
1336 } | 1336 } |
1337 | 1337 |
1338 ClassElement superclass = constructor.getEnclosingClass(); | 1338 ClassElement superclass = constructor.getEnclosingClass(); |
1339 if (backend.needsRti(superclass)) { | 1339 if (backend.classNeedsRti(superclass)) { |
1340 // If [superclass] needs RTI, we have to give a value to its | 1340 // If [superclass] needs RTI, we have to give a value to its |
1341 // type parameters. Those values are in the [supertype] | 1341 // type parameters. Those values are in the [supertype] |
1342 // declaration of [subclass]. | 1342 // declaration of [subclass]. |
1343 ClassElement subclass = inlinedFromElement.getEnclosingClass(); | 1343 ClassElement subclass = inlinedFromElement.getEnclosingClass(); |
1344 InterfaceType supertype = subclass.supertype; | 1344 InterfaceType supertype = subclass.supertype; |
1345 Link<DartType> typeVariables = superclass.typeVariables; | 1345 Link<DartType> typeVariables = superclass.typeVariables; |
1346 supertype.typeArguments.forEach((DartType argument) { | 1346 supertype.typeArguments.forEach((DartType argument) { |
1347 localsHandler.updateLocal(typeVariables.head.element, | 1347 localsHandler.updateLocal(typeVariables.head.element, |
1348 analyzeTypeArgument(argument, callNode)); | 1348 analyzeTypeArgument(argument, callNode)); |
1349 typeVariables = typeVariables.tail; | 1349 typeVariables = typeVariables.tail; |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1576 includeSuperAndInjectedMembers: true); | 1576 includeSuperAndInjectedMembers: true); |
1577 | 1577 |
1578 InterfaceType type = classElement.computeType(compiler); | 1578 InterfaceType type = classElement.computeType(compiler); |
1579 HType ssaType = new HType.nonNullExact(type, compiler); | 1579 HType ssaType = new HType.nonNullExact(type, compiler); |
1580 HForeignNew newObject = new HForeignNew(classElement, | 1580 HForeignNew newObject = new HForeignNew(classElement, |
1581 ssaType, | 1581 ssaType, |
1582 constructorArguments); | 1582 constructorArguments); |
1583 add(newObject); | 1583 add(newObject); |
1584 | 1584 |
1585 // Create the runtime type information, if needed. | 1585 // Create the runtime type information, if needed. |
1586 if (backend.needsRti(classElement)) { | 1586 if (backend.classNeedsRti(classElement)) { |
1587 List<HInstruction> rtiInputs = <HInstruction>[]; | 1587 List<HInstruction> rtiInputs = <HInstruction>[]; |
1588 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1588 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
1589 rtiInputs.add(localsHandler.readLocal(typeVariable.element)); | 1589 rtiInputs.add(localsHandler.readLocal(typeVariable.element)); |
1590 }); | 1590 }); |
1591 callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); | 1591 callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); |
1592 } | 1592 } |
1593 | 1593 |
1594 // Generate calls to the constructor bodies. | 1594 // Generate calls to the constructor bodies. |
1595 for (int index = constructors.length - 1; index >= 0; index--) { | 1595 for (int index = constructors.length - 1; index >= 0; index--) { |
1596 FunctionElement constructor = constructors[index]; | 1596 FunctionElement constructor = constructors[index]; |
(...skipping 25 matching lines...) Expand all Loading... |
1622 // If [parameter] is checked, we pass the already computed | 1622 // If [parameter] is checked, we pass the already computed |
1623 // boolean to the constructor body. | 1623 // boolean to the constructor body. |
1624 if (elements.isParameterChecked(parameter)) { | 1624 if (elements.isParameterChecked(parameter)) { |
1625 Element fieldCheck = | 1625 Element fieldCheck = |
1626 parameterClosureData.parametersWithSentinel[parameter]; | 1626 parameterClosureData.parametersWithSentinel[parameter]; |
1627 bodyCallInputs.add(localsHandler.readLocal(fieldCheck)); | 1627 bodyCallInputs.add(localsHandler.readLocal(fieldCheck)); |
1628 } | 1628 } |
1629 }); | 1629 }); |
1630 | 1630 |
1631 ClassElement currentClass = constructor.getEnclosingClass(); | 1631 ClassElement currentClass = constructor.getEnclosingClass(); |
1632 if (backend.needsRti(currentClass)) { | 1632 if (backend.classNeedsRti(currentClass)) { |
1633 // If [currentClass] needs RTI, we add the type variables as | 1633 // If [currentClass] needs RTI, we add the type variables as |
1634 // parameters of the generative constructor body. | 1634 // parameters of the generative constructor body. |
1635 currentClass.typeVariables.forEach((DartType argument) { | 1635 currentClass.typeVariables.forEach((DartType argument) { |
1636 bodyCallInputs.add(localsHandler.readLocal(argument.element)); | 1636 bodyCallInputs.add(localsHandler.readLocal(argument.element)); |
1637 }); | 1637 }); |
1638 } | 1638 } |
1639 | 1639 |
1640 // If there are locals that escape (ie mutated in closures), we | 1640 // If there are locals that escape (ie mutated in closures), we |
1641 // pass the box to the constructor. | 1641 // pass the box to the constructor. |
1642 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; | 1642 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1726 localsHandler.startFunction(element, node); | 1726 localsHandler.startFunction(element, node); |
1727 close(new HGoto()).addSuccessor(block); | 1727 close(new HGoto()).addSuccessor(block); |
1728 | 1728 |
1729 open(block); | 1729 open(block); |
1730 | 1730 |
1731 // Add the type parameters of the class as parameters of this method. This | 1731 // Add the type parameters of the class as parameters of this method. This |
1732 // must be done before adding the normal parameters, because their types | 1732 // must be done before adding the normal parameters, because their types |
1733 // may contain references to type variables. | 1733 // may contain references to type variables. |
1734 var enclosing = element.enclosingElement; | 1734 var enclosing = element.enclosingElement; |
1735 if ((element.isConstructor() || element.isGenerativeConstructorBody()) | 1735 if ((element.isConstructor() || element.isGenerativeConstructorBody()) |
1736 && backend.needsRti(enclosing)) { | 1736 && backend.classNeedsRti(enclosing)) { |
1737 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1737 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
1738 HParameterValue param = addParameter(typeVariable.element); | 1738 HParameterValue param = addParameter(typeVariable.element); |
1739 localsHandler.directLocals[typeVariable.element] = param; | 1739 localsHandler.directLocals[typeVariable.element] = param; |
1740 }); | 1740 }); |
1741 } | 1741 } |
1742 | 1742 |
1743 if (element is FunctionElement) { | 1743 if (element is FunctionElement) { |
1744 FunctionElement functionElement = element; | 1744 FunctionElement functionElement = element; |
1745 FunctionSignature signature = functionElement.computeSignature(compiler); | 1745 FunctionSignature signature = functionElement.computeSignature(compiler); |
1746 signature.orderedForEachParameter((Element parameterElement) { | 1746 signature.orderedForEachParameter((Element parameterElement) { |
(...skipping 28 matching lines...) Expand all Loading... |
1775 } else { | 1775 } else { |
1776 // Otherwise it is a lazy initializer which does not have parameters. | 1776 // Otherwise it is a lazy initializer which does not have parameters. |
1777 assert(element is VariableElement); | 1777 assert(element is VariableElement); |
1778 } | 1778 } |
1779 } | 1779 } |
1780 | 1780 |
1781 HInstruction buildTypeConversion(HInstruction original, | 1781 HInstruction buildTypeConversion(HInstruction original, |
1782 DartType type, | 1782 DartType type, |
1783 int kind) { | 1783 int kind) { |
1784 if (type == null) return original; | 1784 if (type == null) return original; |
| 1785 type = type.unalias(compiler); |
1785 if (type.kind == TypeKind.INTERFACE && !type.isMalformed && !type.isRaw) { | 1786 if (type.kind == TypeKind.INTERFACE && !type.isMalformed && !type.isRaw) { |
1786 HType subtype = new HType.subtype(type, compiler); | 1787 HType subtype = new HType.subtype(type, compiler); |
1787 HInstruction representations = buildTypeArgumentRepresentations(type); | 1788 HInstruction representations = buildTypeArgumentRepresentations(type); |
1788 add(representations); | 1789 add(representations); |
1789 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 1790 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
1790 original, representations); | 1791 original, representations); |
1791 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 1792 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
1792 HType subtype = original.instructionType; | 1793 HType subtype = original.instructionType; |
1793 HInstruction typeVariable = addTypeVariableReference(type); | 1794 HInstruction typeVariable = addTypeVariableReference(type); |
1794 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 1795 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
1795 original, typeVariable); | 1796 original, typeVariable); |
| 1797 } else if (type.kind == TypeKind.FUNCTION) { |
| 1798 HType subtype = original.instructionType; |
| 1799 if (type.containsTypeVariables) { |
| 1800 bool contextIsTypeArguments = false; |
| 1801 HInstruction context; |
| 1802 if (currentElement.isInstanceMember()) { |
| 1803 context = localsHandler.readThis(); |
| 1804 } else { |
| 1805 ClassElement contextClass = Types.getClassContext(type); |
| 1806 context = buildTypeVariableList(contextClass); |
| 1807 add(context); |
| 1808 contextIsTypeArguments = true; |
| 1809 } |
| 1810 return new HTypeConversion.withContext(type, kind, subtype, |
| 1811 original, context, contextIsTypeArguments: contextIsTypeArguments); |
| 1812 } else { |
| 1813 return new HTypeConversion(type, kind, subtype, original); |
| 1814 } |
1796 } else { | 1815 } else { |
1797 return original.convertType(compiler, type, kind); | 1816 return original.convertType(compiler, type, kind); |
1798 } | 1817 } |
1799 } | 1818 } |
1800 | 1819 |
1801 HInstruction potentiallyCheckType(HInstruction original, DartType type, | 1820 HInstruction potentiallyCheckType(HInstruction original, DartType type, |
1802 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { | 1821 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
1803 if (!compiler.enableTypeAssertions) return original; | 1822 if (!compiler.enableTypeAssertions) return original; |
1804 HInstruction other = buildTypeConversion(original, type, kind); | 1823 HInstruction other = buildTypeConversion(original, type, kind); |
1805 if (other != original) add(other); | 1824 if (other != original) add(other); |
| 1825 compiler.enqueuer.codegen.registerIsCheck(type, work.resolutionTree); |
1806 return other; | 1826 return other; |
1807 } | 1827 } |
1808 | 1828 |
1809 HGraph closeFunction() { | 1829 HGraph closeFunction() { |
1810 // TODO(kasperl): Make this goto an implicit return. | 1830 // TODO(kasperl): Make this goto an implicit return. |
1811 if (!isAborted()) closeAndGotoExit(new HGoto()); | 1831 if (!isAborted()) closeAndGotoExit(new HGoto()); |
1812 graph.finalize(); | 1832 graph.finalize(); |
1813 return graph; | 1833 return graph; |
1814 } | 1834 } |
1815 | 1835 |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2441 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; | 2461 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; |
2442 assert(capturedLocal != null); | 2462 assert(capturedLocal != null); |
2443 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 2463 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
2444 } | 2464 } |
2445 }); | 2465 }); |
2446 | 2466 |
2447 HType type = new HType.nonNullExact( | 2467 HType type = new HType.nonNullExact( |
2448 compiler.functionClass.computeType(compiler), | 2468 compiler.functionClass.computeType(compiler), |
2449 compiler); | 2469 compiler); |
2450 push(new HForeignNew(closureClassElement, type, capturedVariables)); | 2470 push(new HForeignNew(closureClassElement, type, capturedVariables)); |
| 2471 |
| 2472 Element methodElement = nestedClosureData.closureElement; |
| 2473 if (compiler.backend.methodNeedsRti(methodElement)) { |
| 2474 compiler.backend.registerGenericClosure( |
| 2475 methodElement, compiler.enqueuer.codegen, work.resolutionTree); |
| 2476 } |
2451 } | 2477 } |
2452 | 2478 |
2453 visitFunctionDeclaration(FunctionDeclaration node) { | 2479 visitFunctionDeclaration(FunctionDeclaration node) { |
2454 assert(isReachable); | 2480 assert(isReachable); |
2455 visit(node.function); | 2481 visit(node.function); |
2456 localsHandler.updateLocal(elements[node], pop()); | 2482 localsHandler.updateLocal(elements[node], pop()); |
2457 } | 2483 } |
2458 | 2484 |
2459 visitIdentifier(Identifier node) { | 2485 visitIdentifier(Identifier node) { |
2460 if (node.isThis()) { | 2486 if (node.isThis()) { |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2724 inputs.add(runtimeType); | 2750 inputs.add(runtimeType); |
2725 })); | 2751 })); |
2726 } | 2752 } |
2727 String template = '[${templates.join(', ')}]'; | 2753 String template = '[${templates.join(', ')}]'; |
2728 HInstruction representation = | 2754 HInstruction representation = |
2729 createForeign(template, backend.readableArrayType, inputs); | 2755 createForeign(template, backend.readableArrayType, inputs); |
2730 return representation; | 2756 return representation; |
2731 } | 2757 } |
2732 } | 2758 } |
2733 | 2759 |
2734 visitOperatorSend(node) { | 2760 visitOperatorSend(Send node) { |
2735 Operator op = node.selector; | 2761 Operator op = node.selector; |
2736 if (const SourceString("[]") == op.source) { | 2762 if (const SourceString("[]") == op.source) { |
2737 visitDynamicSend(node); | 2763 visitDynamicSend(node); |
2738 } else if (const SourceString("&&") == op.source || | 2764 } else if (const SourceString("&&") == op.source || |
2739 const SourceString("||") == op.source) { | 2765 const SourceString("||") == op.source) { |
2740 visitLogicalAndOr(node, op); | 2766 visitLogicalAndOr(node, op); |
2741 } else if (const SourceString("!") == op.source) { | 2767 } else if (const SourceString("!") == op.source) { |
2742 visitLogicalNot(node); | 2768 visitLogicalNot(node); |
2743 } else if (node.argumentsNode is Prefix) { | 2769 } else if (node.argumentsNode is Prefix) { |
2744 visitUnary(node, op); | 2770 visitUnary(node, op); |
(...skipping 16 matching lines...) Expand all Loading... |
2761 var left = pop(); | 2787 var left = pop(); |
2762 visitBinary(left, op, right, elements.getSelector(node), node); | 2788 visitBinary(left, op, right, elements.getSelector(node), node); |
2763 } | 2789 } |
2764 } | 2790 } |
2765 | 2791 |
2766 void visitIsSend(Send node) { | 2792 void visitIsSend(Send node) { |
2767 visit(node.receiver); | 2793 visit(node.receiver); |
2768 HInstruction expression = pop(); | 2794 HInstruction expression = pop(); |
2769 bool isNot = node.isIsNotCheck; | 2795 bool isNot = node.isIsNotCheck; |
2770 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | 2796 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); |
| 2797 type = type.unalias(compiler); |
2771 if (type.isMalformed) { | 2798 if (type.isMalformed) { |
2772 String reasons = Types.fetchReasonsFromMalformedType(type); | 2799 String reasons = Types.fetchReasonsFromMalformedType(type); |
2773 if (compiler.enableTypeAssertions) { | 2800 if (compiler.enableTypeAssertions) { |
2774 generateMalformedSubtypeError(node, expression, type, reasons); | 2801 generateMalformedSubtypeError(node, expression, type, reasons); |
2775 } else { | 2802 } else { |
2776 generateRuntimeError(node, '$type is malformed: $reasons'); | 2803 generateRuntimeError(node, '$type is malformed: $reasons'); |
2777 } | 2804 } |
2778 } else { | 2805 } else { |
2779 HInstruction instruction = buildIsNode(node, type, expression); | 2806 HInstruction instruction = buildIsNode(node, type, expression); |
2780 if (isNot) { | 2807 if (isNot) { |
2781 add(instruction); | 2808 add(instruction); |
2782 instruction = new HNot(instruction); | 2809 instruction = new HNot(instruction); |
2783 } | 2810 } |
2784 push(instruction); | 2811 push(instruction); |
2785 } | 2812 } |
2786 } | 2813 } |
2787 | 2814 |
| 2815 HLiteralList buildTypeVariableList(ClassElement contextClass) { |
| 2816 List<HInstruction> inputs = <HInstruction>[]; |
| 2817 for (Link<DartType> link = contextClass.typeVariables; |
| 2818 !link.isEmpty; |
| 2819 link = link.tail) { |
| 2820 inputs.add(addTypeVariableReference(link.head)); |
| 2821 } |
| 2822 return buildLiteralList(inputs); |
| 2823 } |
| 2824 |
2788 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { | 2825 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { |
2789 if (type.kind == TypeKind.TYPE_VARIABLE) { | 2826 type = type.unalias(compiler); |
| 2827 if (type.kind == TypeKind.FUNCTION) { |
| 2828 Element checkFunctionSubtype = backend.getCheckFunctionSubtype(); |
| 2829 |
| 2830 HInstruction signatureName = graph.addConstantString( |
| 2831 new DartString.literal(backend.namer.getFunctionTypeName(type)), |
| 2832 node, compiler); |
| 2833 |
| 2834 HInstruction contextName; |
| 2835 HInstruction context; |
| 2836 HInstruction typeArguments; |
| 2837 if (type.containsTypeVariables) { |
| 2838 ClassElement contextClass = Types.getClassContext(type); |
| 2839 contextName = graph.addConstantString( |
| 2840 new DartString.literal(backend.namer.getName(contextClass)), |
| 2841 node, compiler); |
| 2842 if (currentElement.isInstanceMember()) { |
| 2843 context = localsHandler.readThis(); |
| 2844 typeArguments = graph.addConstantNull(compiler); |
| 2845 } else { |
| 2846 context = graph.addConstantNull(compiler); |
| 2847 typeArguments = buildTypeVariableList(contextClass); |
| 2848 add(typeArguments); |
| 2849 } |
| 2850 } else { |
| 2851 contextName = graph.addConstantNull(compiler); |
| 2852 context = graph.addConstantNull(compiler); |
| 2853 typeArguments = graph.addConstantNull(compiler); |
| 2854 } |
| 2855 |
| 2856 List<HInstruction> inputs = <HInstruction>[expression, |
| 2857 signatureName, |
| 2858 contextName, |
| 2859 context, |
| 2860 typeArguments]; |
| 2861 pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN); |
| 2862 HInstruction call = pop(); |
| 2863 return new HIs(type, <HInstruction>[expression, call], |
| 2864 HIs.COMPOUND_CHECK); |
| 2865 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
2790 HInstruction runtimeType = addTypeVariableReference(type); | 2866 HInstruction runtimeType = addTypeVariableReference(type); |
2791 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 2867 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
2792 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 2868 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
2793 pushInvokeStatic(null, helper, inputs, HType.BOOLEAN); | 2869 pushInvokeStatic(null, helper, inputs, HType.BOOLEAN); |
2794 HInstruction call = pop(); | 2870 HInstruction call = pop(); |
2795 return new HIs(type, <HInstruction>[expression, call], | 2871 return new HIs(type, <HInstruction>[expression, call], |
2796 HIs.VARIABLE_CHECK); | 2872 HIs.VARIABLE_CHECK); |
2797 } else if (RuntimeTypes.hasTypeArguments(type)) { | 2873 } else if (RuntimeTypes.hasTypeArguments(type)) { |
2798 ClassElement element = type.element; | 2874 ClassElement element = type.element; |
2799 Element helper = backend.getCheckSubtype(); | 2875 Element helper = backend.getCheckSubtype(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2977 Element element = compiler.isolateHelperLibrary.find( | 3053 Element element = compiler.isolateHelperLibrary.find( |
2978 const SourceString('_currentIsolate')); | 3054 const SourceString('_currentIsolate')); |
2979 if (element == null) { | 3055 if (element == null) { |
2980 compiler.cancel( | 3056 compiler.cancel( |
2981 'Isolate library and compiler mismatch', node: node); | 3057 'Isolate library and compiler mismatch', node: node); |
2982 } | 3058 } |
2983 pushInvokeStatic(null, element, [], HType.UNKNOWN); | 3059 pushInvokeStatic(null, element, [], HType.UNKNOWN); |
2984 } | 3060 } |
2985 } | 3061 } |
2986 | 3062 |
| 3063 void handleForeignJsSetupObject(Send node) { |
| 3064 if (!node.arguments.isEmpty) { |
| 3065 compiler.cancel( |
| 3066 'Too many arguments to JS_GLOBAL_OBJECT', node: node); |
| 3067 } |
| 3068 |
| 3069 String name = backend.namer.GLOBAL_OBJECT; |
| 3070 push(new HForeign(new js.LiteralString(name), |
| 3071 HType.UNKNOWN, |
| 3072 <HInstruction>[])); |
| 3073 } |
| 3074 |
2987 void handleForeignJsCallInIsolate(Send node) { | 3075 void handleForeignJsCallInIsolate(Send node) { |
2988 Link<Node> link = node.arguments; | 3076 Link<Node> link = node.arguments; |
2989 if (!compiler.hasIsolateSupport()) { | 3077 if (!compiler.hasIsolateSupport()) { |
2990 // If the isolate library is not used, we just invoke the | 3078 // If the isolate library is not used, we just invoke the |
2991 // closure. | 3079 // closure. |
2992 visit(link.tail.head); | 3080 visit(link.tail.head); |
2993 Selector selector = new Selector.callClosure(0); | 3081 Selector selector = new Selector.callClosure(0); |
2994 push(new HInvokeClosure(selector, <HInstruction>[pop()])); | 3082 push(new HInvokeClosure(selector, <HInstruction>[pop()])); |
2995 } else { | 3083 } else { |
2996 // Call a helper method from the isolate library. | 3084 // Call a helper method from the isolate library. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3088 <HInstruction>[])); | 3176 <HInstruction>[])); |
3089 } | 3177 } |
3090 | 3178 |
3091 visitForeignSend(Send node) { | 3179 visitForeignSend(Send node) { |
3092 Selector selector = elements.getSelector(node); | 3180 Selector selector = elements.getSelector(node); |
3093 SourceString name = selector.name; | 3181 SourceString name = selector.name; |
3094 if (name == const SourceString('JS')) { | 3182 if (name == const SourceString('JS')) { |
3095 handleForeignJs(node); | 3183 handleForeignJs(node); |
3096 } else if (name == const SourceString('JS_CURRENT_ISOLATE_CONTEXT')) { | 3184 } else if (name == const SourceString('JS_CURRENT_ISOLATE_CONTEXT')) { |
3097 handleForeignJsCurrentIsolateContext(node); | 3185 handleForeignJsCurrentIsolateContext(node); |
| 3186 } else if (name == const SourceString('JS_GLOBAL_OBJECT')) { |
| 3187 handleForeignJsSetupObject(node); |
3098 } else if (name == const SourceString('JS_CALL_IN_ISOLATE')) { | 3188 } else if (name == const SourceString('JS_CALL_IN_ISOLATE')) { |
3099 handleForeignJsCallInIsolate(node); | 3189 handleForeignJsCallInIsolate(node); |
3100 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { | 3190 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { |
3101 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); | 3191 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); |
3102 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { | 3192 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { |
3103 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); | 3193 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); |
3104 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { | 3194 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { |
3105 handleForeignSetCurrentIsolate(node); | 3195 handleForeignSetCurrentIsolate(node); |
3106 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { | 3196 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { |
3107 handleForeignCreateIsolate(node); | 3197 handleForeignCreateIsolate(node); |
3108 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { | 3198 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { |
3109 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); | 3199 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); |
3110 } else if (name == const SourceString('JS_OBJECT_CLASS_NAME')) { | 3200 } else if (name == const SourceString('JS_OBJECT_CLASS_NAME')) { |
3111 String name = backend.namer.getRuntimeTypeName(compiler.objectClass); | 3201 String name = backend.namer.getRuntimeTypeName(compiler.objectClass); |
3112 stack.add(addConstantString(node, name)); | 3202 stack.add(addConstantString(node, name)); |
| 3203 } else if (name == const SourceString('JS_FUNCTION_CLASS_NAME')) { |
| 3204 String name = backend.namer.getRuntimeTypeName(compiler.functionClass); |
| 3205 stack.add(addConstantString(node, name)); |
3113 } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) { | 3206 } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) { |
3114 stack.add(addConstantString(node, backend.namer.operatorAsPrefix())); | 3207 stack.add(addConstantString(node, backend.namer.operatorAsPrefix())); |
| 3208 } else if (name == const SourceString('JS_SIGNATURE_NAME')) { |
| 3209 stack.add(addConstantString(node, backend.namer.operatorSignature())); |
| 3210 } else if (name == const SourceString('JS_FUNCTION_TYPE_TAG')) { |
| 3211 stack.add(addConstantString(node, backend.namer.functionTypeTag())); |
| 3212 } else if (name == const SourceString('JS_FUNCTION_TYPE_VOID_RETURN_TAG')) { |
| 3213 stack.add(addConstantString(node, |
| 3214 backend.namer.functionTypeVoidReturnTag())); |
| 3215 } else if (name == const SourceString('JS_FUNCTION_TYPE_RETURN_TYPE_TAG')) { |
| 3216 stack.add(addConstantString(node, |
| 3217 backend.namer.functionTypeReturnTypeTag())); |
| 3218 } else if (name == |
| 3219 const SourceString('JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG')) { |
| 3220 stack.add(addConstantString(node, |
| 3221 backend.namer.functionTypeRequiredParametersTag())); |
| 3222 } else if (name == |
| 3223 const SourceString('JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG')) { |
| 3224 stack.add(addConstantString(node, |
| 3225 backend.namer.functionTypeOptionalParametersTag())); |
| 3226 } else if (name == |
| 3227 const SourceString('JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG')) { |
| 3228 stack.add(addConstantString(node, |
| 3229 backend.namer.functionTypeNamedParametersTag())); |
3115 } else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) { | 3230 } else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) { |
3116 handleForeignDartObjectJsConstructorFunction(node); | 3231 handleForeignDartObjectJsConstructorFunction(node); |
3117 } else if (name == const SourceString('JS_IS_INDEXABLE_FIELD_NAME')) { | 3232 } else if (name == const SourceString('JS_IS_INDEXABLE_FIELD_NAME')) { |
3118 Element element = compiler.findHelper( | 3233 Element element = compiler.findHelper( |
3119 const SourceString('JavaScriptIndexingBehavior')); | 3234 const SourceString('JavaScriptIndexingBehavior')); |
3120 stack.add(addConstantString(node, backend.namer.operatorIs(element))); | 3235 stack.add(addConstantString(node, backend.namer.operatorIs(element))); |
3121 } else if (name == const SourceString('JS_CURRENT_ISOLATE')) { | 3236 } else if (name == const SourceString('JS_CURRENT_ISOLATE')) { |
3122 handleForeignJsCurrentIsolate(node); | 3237 handleForeignJsCurrentIsolate(node); |
3123 } else { | 3238 } else { |
3124 throw "Unknown foreign: ${selector}"; | 3239 throw "Unknown foreign: ${selector}"; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3221 /** | 3336 /** |
3222 * Generate code to extract the type arguments from the object, substitute | 3337 * Generate code to extract the type arguments from the object, substitute |
3223 * them as an instance of the type we are testing against (if necessary), and | 3338 * them as an instance of the type we are testing against (if necessary), and |
3224 * extract the type argument by the index of the variable in the list of type | 3339 * extract the type argument by the index of the variable in the list of type |
3225 * variables for that class. | 3340 * variables for that class. |
3226 */ | 3341 */ |
3227 HInstruction readTypeVariable(ClassElement cls, | 3342 HInstruction readTypeVariable(ClassElement cls, |
3228 TypeVariableElement variable) { | 3343 TypeVariableElement variable) { |
3229 assert(currentElement.isInstanceMember()); | 3344 assert(currentElement.isInstanceMember()); |
3230 int index = RuntimeTypes.getTypeVariableIndex(variable); | 3345 int index = RuntimeTypes.getTypeVariableIndex(variable); |
3231 String substitutionNameString = backend.namer.substitutionName(cls); | 3346 String substitutionNameString = backend.namer.getName(cls); |
3232 HInstruction substitutionName = graph.addConstantString( | 3347 HInstruction substitutionName = graph.addConstantString( |
3233 new LiteralDartString(substitutionNameString), null, compiler); | 3348 new LiteralDartString(substitutionNameString), null, compiler); |
3234 HInstruction target = localsHandler.readThis(); | 3349 HInstruction target = localsHandler.readThis(); |
3235 HInstruction substitution = createForeign('#[#]', HType.UNKNOWN, | |
3236 <HInstruction>[target, substitutionName]); | |
3237 add(substitution); | |
3238 pushInvokeStatic(null, | 3350 pushInvokeStatic(null, |
3239 backend.getGetRuntimeTypeArgument(), | 3351 backend.getGetRuntimeTypeArgument(), |
3240 [target, | 3352 [target, |
3241 substitution, | 3353 substitutionName, |
3242 graph.addConstantInt(index, compiler)], | 3354 graph.addConstantInt(index, compiler)], |
3243 HType.UNKNOWN); | 3355 HType.UNKNOWN); |
3244 return pop(); | 3356 return pop(); |
3245 } | 3357 } |
3246 | 3358 |
3247 /** | 3359 /** |
3248 * Helper to create an instruction that gets the value of a type variable. | 3360 * Helper to create an instruction that gets the value of a type variable. |
3249 */ | 3361 */ |
3250 HInstruction addTypeVariableReference(TypeVariableType type) { | 3362 HInstruction addTypeVariableReference(TypeVariableType type) { |
3251 Element member = currentElement; | 3363 Element member = currentElement; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3313 }); | 3425 }); |
3314 | 3426 |
3315 HInstruction result = createForeign(template, backend.stringType, inputs); | 3427 HInstruction result = createForeign(template, backend.stringType, inputs); |
3316 add(result); | 3428 add(result); |
3317 return result; | 3429 return result; |
3318 } | 3430 } |
3319 | 3431 |
3320 void handleListConstructor(InterfaceType type, | 3432 void handleListConstructor(InterfaceType type, |
3321 Node currentNode, | 3433 Node currentNode, |
3322 HInstruction newObject) { | 3434 HInstruction newObject) { |
3323 if (!backend.needsRti(type.element)) return; | 3435 if (!backend.classNeedsRti(type.element)) return; |
3324 if (!type.isRaw) { | 3436 if (!type.isRaw) { |
3325 List<HInstruction> inputs = <HInstruction>[]; | 3437 List<HInstruction> inputs = <HInstruction>[]; |
3326 type.typeArguments.forEach((DartType argument) { | 3438 type.typeArguments.forEach((DartType argument) { |
3327 inputs.add(analyzeTypeArgument(argument, currentNode)); | 3439 inputs.add(analyzeTypeArgument(argument, currentNode)); |
3328 }); | 3440 }); |
3329 callSetRuntimeTypeInfo(type.element, inputs, newObject); | 3441 callSetRuntimeTypeInfo(type.element, inputs, newObject); |
3330 } | 3442 } |
3331 } | 3443 } |
3332 | 3444 |
3333 void callSetRuntimeTypeInfo(ClassElement element, | 3445 void callSetRuntimeTypeInfo(ClassElement element, |
3334 List<HInstruction> rtiInputs, | 3446 List<HInstruction> rtiInputs, |
3335 HInstruction newObject) { | 3447 HInstruction newObject) { |
3336 if (!backend.needsRti(element) || element.typeVariables.isEmpty) { | 3448 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { |
3337 return; | 3449 return; |
3338 } | 3450 } |
3339 | 3451 |
3340 HInstruction typeInfo = buildLiteralList(rtiInputs); | 3452 HInstruction typeInfo = buildLiteralList(rtiInputs); |
3341 add(typeInfo); | 3453 add(typeInfo); |
3342 | 3454 |
3343 // Set the runtime type information on the object. | 3455 // Set the runtime type information on the object. |
3344 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); | 3456 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); |
3345 pushInvokeStatic( | 3457 pushInvokeStatic( |
3346 null, | 3458 null, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3424 if (!succeeded) { | 3536 if (!succeeded) { |
3425 generateWrongArgumentCountError(send, constructor, send.arguments); | 3537 generateWrongArgumentCountError(send, constructor, send.arguments); |
3426 return; | 3538 return; |
3427 } | 3539 } |
3428 | 3540 |
3429 ClassElement cls = constructor.getEnclosingClass(); | 3541 ClassElement cls = constructor.getEnclosingClass(); |
3430 if (cls.isAbstract(compiler) && constructor.isGenerativeConstructor()) { | 3542 if (cls.isAbstract(compiler) && constructor.isGenerativeConstructor()) { |
3431 generateAbstractClassInstantiationError(send, cls.name.slowToString()); | 3543 generateAbstractClassInstantiationError(send, cls.name.slowToString()); |
3432 return; | 3544 return; |
3433 } | 3545 } |
3434 if (backend.needsRti(cls)) { | 3546 if (backend.classNeedsRti(cls)) { |
3435 Link<DartType> typeVariable = cls.typeVariables; | 3547 Link<DartType> typeVariable = cls.typeVariables; |
3436 type.typeArguments.forEach((DartType argument) { | 3548 type.typeArguments.forEach((DartType argument) { |
3437 inputs.add(analyzeTypeArgument(argument, send)); | 3549 inputs.add(analyzeTypeArgument(argument, send)); |
3438 typeVariable = typeVariable.tail; | 3550 typeVariable = typeVariable.tail; |
3439 }); | 3551 }); |
3440 // Also add null to non-provided type variables to call the | 3552 // Also add null to non-provided type variables to call the |
3441 // constructor with the right number of arguments. | 3553 // constructor with the right number of arguments. |
3442 while (!typeVariable.isEmpty) { | 3554 while (!typeVariable.isEmpty) { |
3443 inputs.add(graph.addConstantNull(compiler)); | 3555 inputs.add(graph.addConstantNull(compiler)); |
3444 typeVariable = typeVariable.tail; | 3556 typeVariable = typeVariable.tail; |
3445 } | 3557 } |
3446 } | 3558 } |
3447 | 3559 |
3448 if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) { | 3560 if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) { |
3449 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); | 3561 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); |
3450 } | 3562 } |
3451 HType elementType = computeType(constructor); | 3563 HType elementType = computeType(constructor); |
3452 pushInvokeStatic(node, constructor, inputs, elementType); | 3564 pushInvokeStatic(node, constructor, inputs, elementType); |
3453 HInstruction newInstance = stack.last; | 3565 HInstruction newInstance = stack.last; |
3454 | 3566 |
3455 // The List constructor forwards to a Dart static method that does | 3567 // The List constructor forwards to a Dart static method that does |
3456 // not know about the type argument. Therefore we special case | 3568 // not know about the type argument. Therefore we special case |
3457 // this constructor to have the setRuntimeTypeInfo called where | 3569 // this constructor to have the setRuntimeTypeInfo called where |
3458 // the 'new' is done. | 3570 // the 'new' is done. |
3459 if (isListConstructor && backend.needsRti(compiler.listClass)) { | 3571 if (isListConstructor && backend.classNeedsRti(compiler.listClass)) { |
3460 handleListConstructor(type, send, newInstance); | 3572 handleListConstructor(type, send, newInstance); |
3461 } | 3573 } |
3462 | 3574 |
3463 // Finally, if we called a redirecting factory constructor, check the type. | 3575 // Finally, if we called a redirecting factory constructor, check the type. |
3464 if (isRedirected) { | 3576 if (isRedirected) { |
3465 HInstruction checked = potentiallyCheckType(newInstance, expectedType); | 3577 HInstruction checked = potentiallyCheckType(newInstance, expectedType); |
3466 if (checked != newInstance) { | 3578 if (checked != newInstance) { |
3467 pop(); | 3579 pop(); |
3468 stack.add(checked); | 3580 stack.add(checked); |
3469 } | 3581 } |
(...skipping 1933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5403 new HSubGraphBlockInformation(elseBranch.graph)); | 5515 new HSubGraphBlockInformation(elseBranch.graph)); |
5404 | 5516 |
5405 HBasicBlock conditionStartBlock = conditionBranch.block; | 5517 HBasicBlock conditionStartBlock = conditionBranch.block; |
5406 conditionStartBlock.setBlockFlow(info, joinBlock); | 5518 conditionStartBlock.setBlockFlow(info, joinBlock); |
5407 SubGraph conditionGraph = conditionBranch.graph; | 5519 SubGraph conditionGraph = conditionBranch.graph; |
5408 HIf branch = conditionGraph.end.last; | 5520 HIf branch = conditionGraph.end.last; |
5409 assert(branch is HIf); | 5521 assert(branch is HIf); |
5410 branch.blockInformation = conditionStartBlock.blockFlow; | 5522 branch.blockInformation = conditionStartBlock.blockFlow; |
5411 } | 5523 } |
5412 } | 5524 } |
OLD | NEW |