| 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 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 } | 354 } |
| 355 | 355 |
| 356 /** | 356 /** |
| 357 * Returns an [HInstruction] for the given element. If the element is | 357 * Returns an [HInstruction] for the given element. If the element is |
| 358 * boxed or stored in a closure then the method generates code to retrieve | 358 * boxed or stored in a closure then the method generates code to retrieve |
| 359 * the value. | 359 * the value. |
| 360 */ | 360 */ |
| 361 HInstruction readLocal(Element element) { | 361 HInstruction readLocal(Element element) { |
| 362 if (isAccessedDirectly(element)) { | 362 if (isAccessedDirectly(element)) { |
| 363 if (directLocals[element] == null) { | 363 if (directLocals[element] == null) { |
| 364 builder.compiler.internalError("Cannot find value $element", | 364 if (element.isTypeVariable()) { |
| 365 element: element); | 365 builder.compiler.internalError( |
| 366 "Runtime type information not available for $element", |
| 367 element: builder.compiler.currentElement); |
| 368 } else { |
| 369 builder.compiler.internalError( |
| 370 "Cannot find value $element", |
| 371 element: element); |
| 372 } |
| 366 } | 373 } |
| 367 return directLocals[element]; | 374 return directLocals[element]; |
| 368 } else if (isStoredInClosureField(element)) { | 375 } else if (isStoredInClosureField(element)) { |
| 369 Element redirect = redirectionMapping[element]; | 376 Element redirect = redirectionMapping[element]; |
| 370 HInstruction receiver = readLocal(closureData.closureElement); | 377 HInstruction receiver = readLocal(closureData.closureElement); |
| 371 HInstruction fieldGet = new HFieldGet(redirect, receiver); | 378 HInstruction fieldGet = new HFieldGet(redirect, receiver); |
| 372 fieldGet.instructionType = builder.getTypeOfCapturedVariable(element); | 379 fieldGet.instructionType = builder.getTypeOfCapturedVariable(element); |
| 373 builder.add(fieldGet); | 380 builder.add(fieldGet); |
| 374 return fieldGet; | 381 return fieldGet; |
| 375 } else if (isBoxed(element)) { | 382 } else if (isBoxed(element)) { |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 LocalsHandler newLocalsHandler = new LocalsHandler.from(localsHandler); | 1097 LocalsHandler newLocalsHandler = new LocalsHandler.from(localsHandler); |
| 1091 newLocalsHandler.closureData = | 1098 newLocalsHandler.closureData = |
| 1092 compiler.closureToClassMapper.computeClosureToClassMapping( | 1099 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 1093 function, function.parseNode(compiler), elements); | 1100 function, function.parseNode(compiler), elements); |
| 1094 int argumentIndex = 0; | 1101 int argumentIndex = 0; |
| 1095 if (isInstanceMember) { | 1102 if (isInstanceMember) { |
| 1096 newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, | 1103 newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, |
| 1097 compiledArguments[argumentIndex++]); | 1104 compiledArguments[argumentIndex++]); |
| 1098 } | 1105 } |
| 1099 | 1106 |
| 1100 FunctionSignature signature = function.computeSignature(compiler); | |
| 1101 signature.orderedForEachParameter((Element parameter) { | |
| 1102 HInstruction argument = compiledArguments[argumentIndex++]; | |
| 1103 newLocalsHandler.updateLocal(parameter, argument); | |
| 1104 potentiallyCheckType(argument, parameter.computeType(compiler)); | |
| 1105 }); | |
| 1106 | |
| 1107 if (function.isConstructor()) { | 1107 if (function.isConstructor()) { |
| 1108 ClassElement enclosing = function.getEnclosingClass(); | 1108 ClassElement enclosing = function.getEnclosingClass(); |
| 1109 if (backend.needsRti(enclosing)) { | 1109 if (backend.needsRti(enclosing)) { |
| 1110 assert(currentNode is NewExpression); | 1110 assert(currentNode is NewExpression); |
| 1111 InterfaceType type = elements.getType(currentNode); | 1111 InterfaceType type = elements.getType(currentNode); |
| 1112 Link<DartType> typeVariable = enclosing.typeVariables; | 1112 Link<DartType> typeVariable = enclosing.typeVariables; |
| 1113 type.typeArguments.forEach((DartType argument) { | 1113 type.typeArguments.forEach((DartType argument) { |
| 1114 HInstruction instruction = | 1114 HInstruction instruction = |
| 1115 analyzeTypeArgument(argument, currentNode); | 1115 analyzeTypeArgument(argument, currentNode); |
| 1116 newLocalsHandler.updateLocal(typeVariable.head.element, instruction); | 1116 newLocalsHandler.updateLocal(typeVariable.head.element, instruction); |
| 1117 typeVariable = typeVariable.tail; | 1117 typeVariable = typeVariable.tail; |
| 1118 }); | 1118 }); |
| 1119 while (!typeVariable.isEmpty) { | 1119 while (!typeVariable.isEmpty) { |
| 1120 newLocalsHandler.updateLocal(typeVariable.head.element, | 1120 newLocalsHandler.updateLocal(typeVariable.head.element, |
| 1121 graph.addConstantNull(constantSystem)); | 1121 graph.addConstantNull(constantSystem)); |
| 1122 typeVariable = typeVariable.tail; | 1122 typeVariable = typeVariable.tail; |
| 1123 } | 1123 } |
| 1124 } | 1124 } |
| 1125 } | 1125 } |
| 1126 | 1126 |
| 1127 // Check the type of the arguments. This must be done after setting up the |
| 1128 // type variables in the [localsHandler] because the checked types may |
| 1129 // contain type variables. |
| 1130 FunctionSignature signature = function.computeSignature(compiler); |
| 1131 signature.orderedForEachParameter((Element parameter) { |
| 1132 HInstruction argument = compiledArguments[argumentIndex++]; |
| 1133 newLocalsHandler.updateLocal(parameter, argument); |
| 1134 potentiallyCheckType(argument, parameter.computeType(compiler)); |
| 1135 }); |
| 1136 |
| 1127 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. | 1137 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. |
| 1128 returnElement = new ElementX(const SourceString("result"), | 1138 returnElement = new ElementX(const SourceString("result"), |
| 1129 ElementKind.VARIABLE, | 1139 ElementKind.VARIABLE, |
| 1130 function); | 1140 function); |
| 1131 newLocalsHandler.updateLocal(returnElement, | 1141 newLocalsHandler.updateLocal(returnElement, |
| 1132 graph.addConstantNull(constantSystem)); | 1142 graph.addConstantNull(constantSystem)); |
| 1133 elements = compiler.enqueuer.resolution.getCachedElements(function); | 1143 elements = compiler.enqueuer.resolution.getCachedElements(function); |
| 1134 assert(elements != null); | 1144 assert(elements != null); |
| 1135 returnType = signature.returnType; | 1145 returnType = signature.returnType; |
| 1136 stack = <HInstruction>[]; | 1146 stack = <HInstruction>[]; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 if (newElements == null) { | 1217 if (newElements == null) { |
| 1208 compiler.internalError("Element not resolved: $function"); | 1218 compiler.internalError("Element not resolved: $function"); |
| 1209 } | 1219 } |
| 1210 | 1220 |
| 1211 if (canBeInlined == null) { | 1221 if (canBeInlined == null) { |
| 1212 canBeInlined = InlineWeeder.canBeInlined(functionExpression, newElements); | 1222 canBeInlined = InlineWeeder.canBeInlined(functionExpression, newElements); |
| 1213 backend.canBeInlined[function] = canBeInlined; | 1223 backend.canBeInlined[function] = canBeInlined; |
| 1214 if (!canBeInlined) return false; | 1224 if (!canBeInlined) return false; |
| 1215 } | 1225 } |
| 1216 | 1226 |
| 1227 // We cannot inline methods with type variables in the signature in checked |
| 1228 // mode, because we currently do not have access to the type variables |
| 1229 // through the locals. |
| 1230 // TODO(karlklose): remove this and enable inlining of these methods. |
| 1231 if (compiler.enableTypeAssertions && |
| 1232 element.computeType(compiler).containsTypeVariables) { |
| 1233 return false; |
| 1234 } |
| 1235 |
| 1217 assert(canBeInlined); | 1236 assert(canBeInlined); |
| 1218 InliningState state = enterInlinedMethod( | 1237 InliningState state = enterInlinedMethod( |
| 1219 function, selector, argumentsNodes, providedArguments, currentNode); | 1238 function, selector, argumentsNodes, providedArguments, currentNode); |
| 1220 // Add an explicit null check on the receiver. We use [element] | 1239 // Add an explicit null check on the receiver. We use [element] |
| 1221 // to get the same name in the NoSuchMethodError message as if we had | 1240 // to get the same name in the NoSuchMethodError message as if we had |
| 1222 // called it. | 1241 // called it. |
| 1223 if (element.isInstanceMember() | 1242 if (element.isInstanceMember() |
| 1224 && (selector.mask == null || selector.mask.isNullable)) { | 1243 && (selector.mask == null || selector.mask.isNullable)) { |
| 1225 addWithPosition( | 1244 addWithPosition( |
| 1226 new HFieldGet(element, providedArguments[0]), currentNode); | 1245 new HFieldGet(element, providedArguments[0]), currentNode); |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1669 void openFunction(Element element, Expression node) { | 1688 void openFunction(Element element, Expression node) { |
| 1670 assert(invariant(element, element.isImplementation)); | 1689 assert(invariant(element, element.isImplementation)); |
| 1671 HBasicBlock block = graph.addNewBlock(); | 1690 HBasicBlock block = graph.addNewBlock(); |
| 1672 open(graph.entry); | 1691 open(graph.entry); |
| 1673 | 1692 |
| 1674 localsHandler.startFunction(element, node); | 1693 localsHandler.startFunction(element, node); |
| 1675 close(new HGoto()).addSuccessor(block); | 1694 close(new HGoto()).addSuccessor(block); |
| 1676 | 1695 |
| 1677 open(block); | 1696 open(block); |
| 1678 | 1697 |
| 1698 // Add the type parameters of the class as parameters of this method. This |
| 1699 // must be done before adding the normal parameters, because their types |
| 1700 // may contain references to type variables. |
| 1701 var enclosing = element.enclosingElement; |
| 1702 if ((element.isConstructor() || element.isGenerativeConstructorBody()) |
| 1703 && backend.needsRti(enclosing)) { |
| 1704 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1705 HParameterValue param = addParameter(typeVariable.element); |
| 1706 localsHandler.directLocals[typeVariable.element] = param; |
| 1707 }); |
| 1708 } |
| 1709 |
| 1679 if (element is FunctionElement) { | 1710 if (element is FunctionElement) { |
| 1680 FunctionElement functionElement = element; | 1711 FunctionElement functionElement = element; |
| 1681 FunctionSignature signature = functionElement.computeSignature(compiler); | 1712 FunctionSignature signature = functionElement.computeSignature(compiler); |
| 1682 signature.orderedForEachParameter((Element parameterElement) { | 1713 signature.orderedForEachParameter((Element parameterElement) { |
| 1683 if (elements.isParameterChecked(parameterElement)) { | 1714 if (elements.isParameterChecked(parameterElement)) { |
| 1684 addParameterCheckInstruction(parameterElement); | 1715 addParameterCheckInstruction(parameterElement); |
| 1685 } | 1716 } |
| 1686 }); | 1717 }); |
| 1687 | 1718 |
| 1688 // Put the type checks in the first successor of the entry, | 1719 // Put the type checks in the first successor of the entry, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1705 localsHandler.directLocals[parameterElement], | 1736 localsHandler.directLocals[parameterElement], |
| 1706 parameterElement.computeType(compiler)); | 1737 parameterElement.computeType(compiler)); |
| 1707 localsHandler.directLocals[parameterElement] = newParameter; | 1738 localsHandler.directLocals[parameterElement] = newParameter; |
| 1708 }); | 1739 }); |
| 1709 | 1740 |
| 1710 returnType = signature.returnType; | 1741 returnType = signature.returnType; |
| 1711 } else { | 1742 } else { |
| 1712 // Otherwise it is a lazy initializer which does not have parameters. | 1743 // Otherwise it is a lazy initializer which does not have parameters. |
| 1713 assert(element is VariableElement); | 1744 assert(element is VariableElement); |
| 1714 } | 1745 } |
| 1746 } |
| 1715 | 1747 |
| 1716 // Add the type parameters of the class as parameters of this | 1748 HInstruction buildTypeConversion(Compiler compiler, HInstruction original, |
| 1717 // method. | 1749 DartType type, int kind) { |
| 1718 var enclosing = element.enclosingElement; | 1750 if (type == null) return original; |
| 1719 if ((element.isConstructor() || element.isGenerativeConstructorBody()) | 1751 if (type.kind == TypeKind.INTERFACE && !type.isMalformed && !type.isRaw) { |
| 1720 && backend.needsRti(enclosing)) { | 1752 HType subtype = new HType.subtype(type, compiler); |
| 1721 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1753 if (type.isRaw) { |
| 1722 HParameterValue param = addParameter(typeVariable.element); | 1754 return new HTypeConversion(type, kind, subtype, original); |
| 1723 localsHandler.directLocals[typeVariable.element] = param; | 1755 } |
| 1724 }); | 1756 HInstruction representations = buildTypeArgumentRepresentations(type); |
| 1757 add(representations); |
| 1758 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
| 1759 original, representations); |
| 1760 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 1761 HType subtype = original.instructionType; |
| 1762 HInstruction typeVariable = addTypeVariableReference(type); |
| 1763 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
| 1764 original, typeVariable); |
| 1765 } else { |
| 1766 return original.convertType(compiler, type, kind); |
| 1725 } | 1767 } |
| 1726 } | 1768 } |
| 1727 | 1769 |
| 1728 HInstruction potentiallyCheckType( | 1770 HInstruction potentiallyCheckType(HInstruction original, DartType type, |
| 1729 HInstruction original, DartType type, | |
| 1730 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { | 1771 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
| 1731 if (!compiler.enableTypeAssertions) return original; | 1772 if (!compiler.enableTypeAssertions) return original; |
| 1732 HInstruction other = original.convertType(compiler, type, kind); | 1773 HInstruction other = |
| 1774 buildTypeConversion(compiler, original, type, kind); |
| 1733 if (other != original) add(other); | 1775 if (other != original) add(other); |
| 1734 return other; | 1776 return other; |
| 1735 } | 1777 } |
| 1736 | 1778 |
| 1737 HGraph closeFunction() { | 1779 HGraph closeFunction() { |
| 1738 // TODO(kasperl): Make this goto an implicit return. | 1780 // TODO(kasperl): Make this goto an implicit return. |
| 1739 if (!isAborted()) closeAndGotoExit(new HGoto()); | 1781 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 1740 graph.finalize(); | 1782 graph.finalize(); |
| 1741 return graph; | 1783 return graph; |
| 1742 } | 1784 } |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2586 if (location == null) { | 2628 if (location == null) { |
| 2587 assert(send != null); | 2629 assert(send != null); |
| 2588 location = send; | 2630 location = send; |
| 2589 } | 2631 } |
| 2590 if (Elements.isStaticOrTopLevelField(element)) { | 2632 if (Elements.isStaticOrTopLevelField(element)) { |
| 2591 if (element.isSetter()) { | 2633 if (element.isSetter()) { |
| 2592 var instruction = buildInvokeStatic(element, | 2634 var instruction = buildInvokeStatic(element, |
| 2593 <HInstruction>[value], HType.UNKNOWN); | 2635 <HInstruction>[value], HType.UNKNOWN); |
| 2594 addWithPosition(instruction, location); | 2636 addWithPosition(instruction, location); |
| 2595 } else { | 2637 } else { |
| 2596 value = potentiallyCheckType(value, element.computeType(compiler)); | 2638 value = |
| 2639 potentiallyCheckType(value, element.computeType(compiler)); |
| 2597 addWithPosition(new HStaticStore(element, value), location); | 2640 addWithPosition(new HStaticStore(element, value), location); |
| 2598 } | 2641 } |
| 2599 stack.add(value); | 2642 stack.add(value); |
| 2600 } else if (Elements.isErroneousElement(element)) { | 2643 } else if (Elements.isErroneousElement(element)) { |
| 2601 // An erroneous element indicates an unresolved static setter. | 2644 // An erroneous element indicates an unresolved static setter. |
| 2602 generateThrowNoSuchMethod( | 2645 generateThrowNoSuchMethod( |
| 2603 location, | 2646 location, |
| 2604 getTargetName(element, 'set'), | 2647 getTargetName(element, 'set'), |
| 2605 argumentNodes: (send == null ? const Link<Node>() : send.arguments)); | 2648 argumentNodes: (send == null ? const Link<Node>() : send.arguments)); |
| 2606 } else { | 2649 } else { |
| 2607 stack.add(value); | 2650 stack.add(value); |
| 2608 // If the value does not already have a name, give it here. | 2651 // If the value does not already have a name, give it here. |
| 2609 if (value.sourceElement == null) { | 2652 if (value.sourceElement == null) { |
| 2610 value.sourceElement = element; | 2653 value.sourceElement = element; |
| 2611 } | 2654 } |
| 2612 HInstruction checked = potentiallyCheckType( | 2655 HInstruction checked = |
| 2613 value, element.computeType(compiler)); | 2656 potentiallyCheckType(value, element.computeType(compiler)); |
| 2614 if (!identical(checked, value)) { | 2657 if (!identical(checked, value)) { |
| 2615 pop(); | 2658 pop(); |
| 2616 stack.add(checked); | 2659 stack.add(checked); |
| 2617 } | 2660 } |
| 2618 localsHandler.updateLocal(element, checked); | 2661 localsHandler.updateLocal(element, checked); |
| 2619 } | 2662 } |
| 2620 } | 2663 } |
| 2621 | 2664 |
| 2622 HInstruction invokeInterceptor(Set<ClassElement> intercepted, | 2665 HInstruction invokeInterceptor(Set<ClassElement> intercepted, |
| 2623 HInstruction receiver) { | 2666 HInstruction receiver) { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2756 isNot = true; | 2799 isNot = true; |
| 2757 } | 2800 } |
| 2758 DartType type = elements.getType(typeAnnotation); | 2801 DartType type = elements.getType(typeAnnotation); |
| 2759 if (type.isMalformed) { | 2802 if (type.isMalformed) { |
| 2760 String reasons = Types.fetchReasonsFromMalformedType(type); | 2803 String reasons = Types.fetchReasonsFromMalformedType(type); |
| 2761 if (compiler.enableTypeAssertions) { | 2804 if (compiler.enableTypeAssertions) { |
| 2762 generateMalformedSubtypeError(node, expression, type, reasons); | 2805 generateMalformedSubtypeError(node, expression, type, reasons); |
| 2763 } else { | 2806 } else { |
| 2764 generateRuntimeError(node, '$type is malformed: $reasons'); | 2807 generateRuntimeError(node, '$type is malformed: $reasons'); |
| 2765 } | 2808 } |
| 2766 return; | 2809 } else { |
| 2810 HInstruction instruction = buildIsNode(node, type, expression); |
| 2811 if (isNot) { |
| 2812 add(instruction); |
| 2813 instruction = new HNot(instruction); |
| 2814 } |
| 2815 push(instruction); |
| 2767 } | 2816 } |
| 2817 } |
| 2768 | 2818 |
| 2769 HInstruction instruction; | 2819 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { |
| 2770 if (type.kind == TypeKind.TYPE_VARIABLE) { | 2820 if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 2771 HInstruction runtimeType = addTypeVariableReference(type); | 2821 HInstruction runtimeType = addTypeVariableReference(type); |
| 2772 Element helper = backend.getGetObjectIsSubtype(); | 2822 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
| 2773 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 2823 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| 2774 HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN); | 2824 HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN); |
| 2775 add(call); | 2825 add(call); |
| 2776 instruction = new HIs(type, <HInstruction>[expression, call], | 2826 return new HIs(type, <HInstruction>[expression, call], |
| 2777 HIs.VARIABLE_CHECK); | 2827 HIs.VARIABLE_CHECK); |
| 2778 } else if (RuntimeTypes.hasTypeArguments(type)) { | 2828 } else if (RuntimeTypes.hasTypeArguments(type)) { |
| 2779 Element element = type.element; | 2829 Element element = type.element; |
| 2780 Element helper = backend.getCheckSubtype(); | 2830 Element helper = backend.getCheckSubtype(); |
| 2781 HInstruction representations = | 2831 HInstruction representations = |
| 2782 buildTypeArgumentRepresentations(type); | 2832 buildTypeArgumentRepresentations(type); |
| 2783 add(representations); | 2833 add(representations); |
| 2784 String operator = | 2834 String operator = |
| 2785 backend.namer.operatorIs(backend.getImplementationClass(element)); | 2835 backend.namer.operatorIs(backend.getImplementationClass(element)); |
| 2786 HInstruction isFieldName = addConstantString(node, operator); | 2836 HInstruction isFieldName = addConstantString(node, operator); |
| 2787 // TODO(karlklose): use [:null:] for [asField] if [element] does not | 2837 // TODO(karlklose): use [:null:] for [asField] if [element] does not |
| 2788 // have a subclass. | 2838 // have a subclass. |
| 2789 HInstruction asFieldName = | 2839 HInstruction asFieldName = |
| 2790 addConstantString(node, backend.namer.substitutionName(element)); | 2840 addConstantString(node, backend.namer.substitutionName(element)); |
| 2791 List<HInstruction> inputs = <HInstruction>[expression, | 2841 List<HInstruction> inputs = <HInstruction>[expression, |
| 2792 isFieldName, | 2842 isFieldName, |
| 2793 representations, | 2843 representations, |
| 2794 asFieldName]; | 2844 asFieldName]; |
| 2795 HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN); | 2845 HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN); |
| 2796 add(call); | 2846 add(call); |
| 2797 instruction = new HIs(type, <HInstruction>[expression, call], | 2847 return |
| 2798 HIs.COMPOUND_CHECK); | 2848 new HIs(type, <HInstruction>[expression, call], HIs.COMPOUND_CHECK); |
| 2799 } else { | 2849 } else { |
| 2800 instruction = new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK); | 2850 return new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK); |
| 2801 } | 2851 } |
| 2802 if (isNot) { | |
| 2803 add(instruction); | |
| 2804 instruction = new HNot(instruction); | |
| 2805 } | |
| 2806 push(instruction); | |
| 2807 } | 2852 } |
| 2808 | 2853 |
| 2809 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { | 2854 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { |
| 2810 Selector selector = elements.getSelector(node); | 2855 Selector selector = elements.getSelector(node); |
| 2811 if (selector.namedArgumentCount == 0) { | 2856 if (selector.namedArgumentCount == 0) { |
| 2812 addGenericSendArgumentsToList(node.arguments, list); | 2857 addGenericSendArgumentsToList(node.arguments, list); |
| 2813 } else { | 2858 } else { |
| 2814 // Visit positional arguments and add them to the list. | 2859 // Visit positional arguments and add them to the list. |
| 2815 Link<Node> arguments = node.arguments; | 2860 Link<Node> arguments = node.arguments; |
| 2816 int positionalArgumentCount = selector.positionalArgumentCount; | 2861 int positionalArgumentCount = selector.positionalArgumentCount; |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3209 graph.addConstantInt(index, constantSystem), | 3254 graph.addConstantInt(index, constantSystem), |
| 3210 HType.UNKNOWN); | 3255 HType.UNKNOWN); |
| 3211 return pop(); | 3256 return pop(); |
| 3212 } | 3257 } |
| 3213 | 3258 |
| 3214 /** | 3259 /** |
| 3215 * Helper to create an instruction that gets the value of a type variable. | 3260 * Helper to create an instruction that gets the value of a type variable. |
| 3216 */ | 3261 */ |
| 3217 HInstruction addTypeVariableReference(TypeVariableType type) { | 3262 HInstruction addTypeVariableReference(TypeVariableType type) { |
| 3218 Element member = currentElement; | 3263 Element member = currentElement; |
| 3219 if (member.enclosingElement.isClosure()) { | 3264 bool isClosure = member.enclosingElement.isClosure(); |
| 3265 if (isClosure) { |
| 3220 ClosureClassElement closureClass = member.enclosingElement; | 3266 ClosureClassElement closureClass = member.enclosingElement; |
| 3221 member = closureClass.methodElement; | 3267 member = closureClass.methodElement; |
| 3222 member = member.getOutermostEnclosingMemberOrTopLevel(); | 3268 member = member.getOutermostEnclosingMemberOrTopLevel(); |
| 3223 } | 3269 } |
| 3224 if (member.isConstructor() | 3270 if (isClosure && member.isFactoryConstructor()) { |
| 3225 || member.isGenerativeConstructorBody() | 3271 // The type variable is used from a closure in a factory constructor. The |
| 3226 || member.isField()) { | 3272 // value of the type argument is stored as a local on the closure itself. |
| 3273 return localsHandler.readLocal(type.element); |
| 3274 } else if (member.isConstructor() || |
| 3275 member.isGenerativeConstructorBody() || |
| 3276 member.isField()) { |
| 3227 // The type variable is stored in a parameter of the method. | 3277 // The type variable is stored in a parameter of the method. |
| 3228 return localsHandler.readLocal(type.element); | 3278 return localsHandler.readLocal(type.element); |
| 3229 } else if (member.isInstanceMember()) { | 3279 } else if (member.isInstanceMember()) { |
| 3230 // The type variable is stored on the object. | 3280 // The type variable is stored on the object. |
| 3231 return readTypeVariable(member.getEnclosingClass(), | 3281 return readTypeVariable(member.getEnclosingClass(), |
| 3232 type.element); | 3282 type.element); |
| 3233 } else { | 3283 } else { |
| 3234 // TODO(ngeoffray): Match the VM behavior and throw an | 3284 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3235 // exception at runtime. | 3285 // exception at runtime. |
| 3236 compiler.cancel('Unimplemented unresolved type variable', | 3286 compiler.cancel('Unimplemented unresolved type variable', |
| (...skipping 1472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4709 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 4759 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
| 4710 // "if" condition above and this "else" branch should be deleted as | 4760 // "if" condition above and this "else" branch should be deleted as |
| 4711 // type of declared variable won't matter for the catch | 4761 // type of declared variable won't matter for the catch |
| 4712 // condition. | 4762 // condition. |
| 4713 DartType type = elements.getType(declaration.type); | 4763 DartType type = elements.getType(declaration.type); |
| 4714 if (type == null) { | 4764 if (type == null) { |
| 4715 compiler.cancel('Catch with unresolved type', node: catchBlock); | 4765 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 4716 } | 4766 } |
| 4717 // TODO(karlkose): support type arguments here. | 4767 // TODO(karlkose): support type arguments here. |
| 4718 condition = new HIs(type, <HInstruction>[unwrappedException], | 4768 condition = new HIs(type, <HInstruction>[unwrappedException], |
| 4719 HIs.RAW_CHECK, nullOk: true); | 4769 HIs.RAW_CHECK); |
| 4720 push(condition); | 4770 push(condition); |
| 4721 } | 4771 } |
| 4722 } | 4772 } |
| 4723 } | 4773 } |
| 4724 | 4774 |
| 4725 void visitThen() { | 4775 void visitThen() { |
| 4726 CatchBlock catchBlock = link.head; | 4776 CatchBlock catchBlock = link.head; |
| 4727 link = link.tail; | 4777 link = link.tail; |
| 4728 | 4778 |
| 4729 if (compiler.enableTypeAssertions) { | 4779 if (compiler.enableTypeAssertions) { |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5277 new HSubGraphBlockInformation(elseBranch.graph)); | 5327 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5278 | 5328 |
| 5279 HBasicBlock conditionStartBlock = conditionBranch.block; | 5329 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5280 conditionStartBlock.setBlockFlow(info, joinBlock); | 5330 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5281 SubGraph conditionGraph = conditionBranch.graph; | 5331 SubGraph conditionGraph = conditionBranch.graph; |
| 5282 HIf branch = conditionGraph.end.last; | 5332 HIf branch = conditionGraph.end.last; |
| 5283 assert(branch is HIf); | 5333 assert(branch is HIf); |
| 5284 branch.blockInformation = conditionStartBlock.blockFlow; | 5334 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5285 } | 5335 } |
| 5286 } | 5336 } |
| OLD | NEW |