| 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 implement [TypedElement.type] because our | 9 * methods. We need to implement [TypedElement.type] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 * [directLocals] is iterated, so it is "insertion ordered" to make the | 108 * [directLocals] is iterated, so it is "insertion ordered" to make the |
| 109 * iteration order a function only of insertions and not a function of | 109 * iteration order a function only of insertions and not a function of |
| 110 * e.g. Element hash codes. I'd prefer to use a SortedMap but some elements | 110 * e.g. Element hash codes. I'd prefer to use a SortedMap but some elements |
| 111 * don't have source locations for [Elements.compareByPosition]. | 111 * don't have source locations for [Elements.compareByPosition]. |
| 112 */ | 112 */ |
| 113 Map<Element, HInstruction> directLocals; | 113 Map<Element, HInstruction> directLocals; |
| 114 Map<Element, Element> redirectionMapping; | 114 Map<Element, Element> redirectionMapping; |
| 115 SsaBuilder builder; | 115 SsaBuilder builder; |
| 116 ClosureClassMap closureData; | 116 ClosureClassMap closureData; |
| 117 | 117 |
| 118 LocalsHandler(this.builder) | 118 /// The class that defines the current type environment or null if no type |
| 119 : directLocals = new Map<Element, HInstruction>(), | 119 /// variables are in scope. |
| 120 redirectionMapping = new Map<Element, Element>(); | 120 final ClassElement contextClass; |
| 121 |
| 122 LocalsHandler(this.builder, this.contextClass) |
| 123 : redirectionMapping = new Map<Element, Element>(), |
| 124 directLocals = new Map<Element, HInstruction>(); |
| 125 |
| 126 /// Substituted type variables occurring in [type] into the context of |
| 127 /// [contextClass]. |
| 128 DartType substInContext(DartType type) { |
| 129 if (contextClass != null) { |
| 130 ClassElement typeContext = Types.getClassContext(type); |
| 131 if (typeContext != null) { |
| 132 type = type.substByContext( |
| 133 contextClass.asInstanceOf(typeContext)); |
| 134 } |
| 135 } |
| 136 return type; |
| 137 } |
| 121 | 138 |
| 122 get typesTask => builder.compiler.typesTask; | 139 get typesTask => builder.compiler.typesTask; |
| 123 | 140 |
| 124 /** | 141 /** |
| 125 * Creates a new [LocalsHandler] based on [other]. We only need to | 142 * Creates a new [LocalsHandler] based on [other]. We only need to |
| 126 * copy the [directLocals], since the other fields can be shared | 143 * copy the [directLocals], since the other fields can be shared |
| 127 * throughout the AST visit. | 144 * throughout the AST visit. |
| 128 */ | 145 */ |
| 129 LocalsHandler.from(LocalsHandler other) | 146 LocalsHandler.from(LocalsHandler other) |
| 130 : directLocals = new Map<Element, HInstruction>.from(other.directLocals), | 147 : directLocals = new Map<Element, HInstruction>.from(other.directLocals), |
| 131 redirectionMapping = other.redirectionMapping, | 148 redirectionMapping = other.redirectionMapping, |
| 149 contextClass = other.contextClass, |
| 132 builder = other.builder, | 150 builder = other.builder, |
| 133 closureData = other.closureData; | 151 closureData = other.closureData; |
| 134 | 152 |
| 135 /** | 153 /** |
| 136 * Redirects accesses from element [from] to element [to]. The [to] element | 154 * Redirects accesses from element [from] to element [to]. The [to] element |
| 137 * must be a boxed variable or a variable that is stored in a closure-field. | 155 * must be a boxed variable or a variable that is stored in a closure-field. |
| 138 */ | 156 */ |
| 139 void redirectElement(Element from, Element to) { | 157 void redirectElement(Element from, Element to) { |
| 140 assert(redirectionMapping[from] == null); | 158 assert(redirectionMapping[from] == null); |
| 141 redirectionMapping[from] = to; | 159 redirectionMapping[from] = to; |
| (...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 List<HInstruction> stack = <HInstruction>[]; | 980 List<HInstruction> stack = <HInstruction>[]; |
| 963 | 981 |
| 964 SsaBuilder(JavaScriptBackend backend, | 982 SsaBuilder(JavaScriptBackend backend, |
| 965 CodegenWorkItem work, | 983 CodegenWorkItem work, |
| 966 this.nativeEmitter) | 984 this.nativeEmitter) |
| 967 : this.backend = backend, | 985 : this.backend = backend, |
| 968 this.constantSystem = backend.constantSystem, | 986 this.constantSystem = backend.constantSystem, |
| 969 this.work = work, | 987 this.work = work, |
| 970 this.rti = backend.rti, | 988 this.rti = backend.rti, |
| 971 super(work.resolutionTree, backend.compiler) { | 989 super(work.resolutionTree, backend.compiler) { |
| 972 localsHandler = new LocalsHandler(this); | 990 localsHandler = new LocalsHandler(this, work.element.contextClass); |
| 973 sourceElementStack.add(work.element); | 991 sourceElementStack.add(work.element); |
| 974 } | 992 } |
| 975 | 993 |
| 976 Element get sourceElement => sourceElementStack.last; | 994 Element get sourceElement => sourceElementStack.last; |
| 977 | 995 |
| 978 HBasicBlock addNewBlock() { | 996 HBasicBlock addNewBlock() { |
| 979 HBasicBlock block = graph.addNewBlock(); | 997 HBasicBlock block = graph.addNewBlock(); |
| 980 // If adding a new block during building of an expression, it is due to | 998 // If adding a new block during building of an expression, it is due to |
| 981 // conditional expressions or short-circuit logical operators. | 999 // conditional expressions or short-circuit logical operators. |
| 982 return block; | 1000 return block; |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1517 * This method sets up the local state of the builder for inlining [function]. | 1535 * This method sets up the local state of the builder for inlining [function]. |
| 1518 * The arguments of the function are inserted into the [localsHandler]. | 1536 * The arguments of the function are inserted into the [localsHandler]. |
| 1519 * | 1537 * |
| 1520 * When inlining a function, [:return:] statements are not emitted as | 1538 * When inlining a function, [:return:] statements are not emitted as |
| 1521 * [HReturn] instructions. Instead, the value of a synthetic element is | 1539 * [HReturn] instructions. Instead, the value of a synthetic element is |
| 1522 * updated in the [localsHandler]. This function creates such an element and | 1540 * updated in the [localsHandler]. This function creates such an element and |
| 1523 * stores it in the [returnElement] field. | 1541 * stores it in the [returnElement] field. |
| 1524 */ | 1542 */ |
| 1525 void setupStateForInlining(FunctionElement function, | 1543 void setupStateForInlining(FunctionElement function, |
| 1526 List<HInstruction> compiledArguments) { | 1544 List<HInstruction> compiledArguments) { |
| 1527 localsHandler = new LocalsHandler(this); | 1545 localsHandler = new LocalsHandler(this, function.contextClass); |
| 1528 localsHandler.closureData = | 1546 localsHandler.closureData = |
| 1529 compiler.closureToClassMapper.computeClosureToClassMapping( | 1547 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 1530 function, function.parseNode(compiler), elements); | 1548 function, function.parseNode(compiler), elements); |
| 1531 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. | 1549 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. |
| 1532 returnElement = new VariableElementX.synthetic("result", | 1550 returnElement = new VariableElementX.synthetic("result", |
| 1533 ElementKind.VARIABLE, function); | 1551 ElementKind.VARIABLE, function); |
| 1534 localsHandler.updateLocal(returnElement, | 1552 localsHandler.updateLocal(returnElement, |
| 1535 graph.addConstantNull(compiler)); | 1553 graph.addConstantNull(compiler)); |
| 1536 | 1554 |
| 1537 inTryStatement = false; // TODO(lry): why? Document. | 1555 inTryStatement = false; // TODO(lry): why? Document. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 } | 1629 } |
| 1612 | 1630 |
| 1613 /** | 1631 /** |
| 1614 * In checked mode, generate type tests for the parameters of the inlined | 1632 * In checked mode, generate type tests for the parameters of the inlined |
| 1615 * function. | 1633 * function. |
| 1616 */ | 1634 */ |
| 1617 void potentiallyCheckInlinedParameterTypes(FunctionElement function) { | 1635 void potentiallyCheckInlinedParameterTypes(FunctionElement function) { |
| 1618 if (!compiler.enableTypeAssertions) return; | 1636 if (!compiler.enableTypeAssertions) return; |
| 1619 | 1637 |
| 1620 FunctionSignature signature = function.functionSignature; | 1638 FunctionSignature signature = function.functionSignature; |
| 1621 | |
| 1622 InterfaceType contextType; | |
| 1623 if (function.isSynthesized && function.isGenerativeConstructor()) { | |
| 1624 // Synthesized constructors reuse the parameters from the | |
| 1625 // [targetConstructor]. In face of generic types, the type variables | |
| 1626 // occurring in the parameter types must be substituted by the type | |
| 1627 // arguments of the enclosing class. | |
| 1628 FunctionElement target = function; | |
| 1629 while (target.targetConstructor != null) { | |
| 1630 target = target.targetConstructor; | |
| 1631 } | |
| 1632 if (target != function) { | |
| 1633 ClassElement functionClass = function.getEnclosingClass(); | |
| 1634 ClassElement targetClass = target.getEnclosingClass(); | |
| 1635 contextType = functionClass.thisType.asInstanceOf(targetClass); | |
| 1636 } | |
| 1637 } | |
| 1638 | |
| 1639 signature.orderedForEachParameter((ParameterElement parameter) { | 1639 signature.orderedForEachParameter((ParameterElement parameter) { |
| 1640 HInstruction argument = localsHandler.readLocal(parameter); | 1640 HInstruction argument = localsHandler.readLocal(parameter); |
| 1641 DartType parameterType = parameter.type; | 1641 potentiallyCheckType(argument, parameter.type); |
| 1642 if (contextType != null) { | |
| 1643 parameterType = parameterType.substByContext(contextType); | |
| 1644 } | |
| 1645 potentiallyCheckType(argument, parameterType); | |
| 1646 }); | 1642 }); |
| 1647 } | 1643 } |
| 1648 | 1644 |
| 1649 /** | 1645 /** |
| 1650 * Documentation wanted -- johnniwinther | 1646 * Documentation wanted -- johnniwinther |
| 1651 * | 1647 * |
| 1652 * Invariant: [constructors] must contain only implementation elements. | 1648 * Invariant: [constructors] must contain only implementation elements. |
| 1653 */ | 1649 */ |
| 1654 void inlineSuperOrRedirect(FunctionElement callee, | 1650 void inlineSuperOrRedirect(FunctionElement callee, |
| 1655 List<HInstruction> compiledArguments, | 1651 List<HInstruction> compiledArguments, |
| 1656 List<FunctionElement> constructors, | 1652 List<FunctionElement> constructors, |
| 1657 Map<Element, HInstruction> fieldValues, | 1653 Map<Element, HInstruction> fieldValues, |
| 1658 FunctionElement caller) { | 1654 FunctionElement caller) { |
| 1659 callee = callee.implementation; | 1655 callee = callee.implementation; |
| 1660 compiler.withCurrentElement(callee, () { | 1656 compiler.withCurrentElement(callee, () { |
| 1661 constructors.add(callee); | 1657 constructors.add(callee); |
| 1662 ClassElement enclosingClass = callee.getEnclosingClass(); | 1658 ClassElement enclosingClass = callee.getEnclosingClass(); |
| 1663 if (backend.classNeedsRti(enclosingClass)) { | 1659 if (backend.classNeedsRti(enclosingClass)) { |
| 1664 // If [enclosingClass] needs RTI, we have to give a value to its | 1660 // If [enclosingClass] needs RTI, we have to give a value to its |
| 1665 // type parameters. | 1661 // type parameters. |
| 1666 ClassElement currentClass = caller.getEnclosingClass(); | 1662 ClassElement currentClass = caller.getEnclosingClass(); |
| 1667 // For a super constructor call, the type is the supertype of | 1663 // For a super constructor call, the type is the supertype of |
| 1668 // [currentClass]. For a redirecting constructor, the type is | 1664 // [currentClass]. For a redirecting constructor, the type is |
| 1669 // the current type. [InterfaceType.asInstanceOf] takes care | 1665 // the current type. [InterfaceType.asInstanceOf] takes care |
| 1670 // of both. | 1666 // of both. |
| 1671 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); | 1667 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); |
| 1668 type = localsHandler.substInContext(type); |
| 1672 Link<DartType> typeVariables = enclosingClass.typeVariables; | 1669 Link<DartType> typeVariables = enclosingClass.typeVariables; |
| 1673 type.typeArguments.forEach((DartType argument) { | 1670 type.typeArguments.forEach((DartType argument) { |
| 1674 localsHandler.updateLocal( | 1671 localsHandler.updateLocal( |
| 1675 typeVariables.head.element, | 1672 typeVariables.head.element, |
| 1676 analyzeTypeArgument(argument)); | 1673 analyzeTypeArgument(argument)); |
| 1677 typeVariables = typeVariables.tail; | 1674 typeVariables = typeVariables.tail; |
| 1678 }); | 1675 }); |
| 1679 // If the supertype is a raw type, we need to set to null the | 1676 // If the supertype is a raw type, we need to set to null the |
| 1680 // type variables. | 1677 // type variables. |
| 1681 assert(typeVariables.isEmpty | 1678 assert(typeVariables.isEmpty |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1929 | 1926 |
| 1930 classElement.forEachInstanceField( | 1927 classElement.forEachInstanceField( |
| 1931 (ClassElement enclosingClass, VariableElement member) { | 1928 (ClassElement enclosingClass, VariableElement member) { |
| 1932 HInstruction value = fieldValues[member]; | 1929 HInstruction value = fieldValues[member]; |
| 1933 if (value == null) { | 1930 if (value == null) { |
| 1934 // Uninitialized native fields are pre-initialized by the native | 1931 // Uninitialized native fields are pre-initialized by the native |
| 1935 // implementation. | 1932 // implementation. |
| 1936 assert(isNativeUpgradeFactory); | 1933 assert(isNativeUpgradeFactory); |
| 1937 } else { | 1934 } else { |
| 1938 fields.add(member); | 1935 fields.add(member); |
| 1939 DartType type = member.type; | 1936 DartType type = localsHandler.substInContext(member.type); |
| 1940 if (enclosingClass.isMixinApplication) { | |
| 1941 // TODO(johnniwinther): Add a member-like abstraction for fields | |
| 1942 // that normalizes this. | |
| 1943 type = type.substByContext( | |
| 1944 enclosingClass.thisType.asInstanceOf( | |
| 1945 member.enclosingElement)); | |
| 1946 } | |
| 1947 constructorArguments.add(potentiallyCheckType(value, type)); | 1937 constructorArguments.add(potentiallyCheckType(value, type)); |
| 1948 } | 1938 } |
| 1949 }, | 1939 }, |
| 1950 includeSuperAndInjectedMembers: true); | 1940 includeSuperAndInjectedMembers: true); |
| 1951 | 1941 |
| 1952 InterfaceType type = classElement.thisType; | 1942 InterfaceType type = classElement.thisType; |
| 1953 TypeMask ssaType = new TypeMask.nonNullExact(classElement.declaration); | 1943 TypeMask ssaType = new TypeMask.nonNullExact(classElement.declaration); |
| 1954 List<DartType> instantiatedTypes; | 1944 List<DartType> instantiatedTypes; |
| 1955 addInlinedInstantiation(type); | 1945 addInlinedInstantiation(type); |
| 1956 if (!currentInlinedInstantiations.isEmpty) { | 1946 if (!currentInlinedInstantiations.isEmpty) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2079 if (!localsHandler.isBoxed(parameter)) { | 2069 if (!localsHandler.isBoxed(parameter)) { |
| 2080 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 2070 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 2081 } | 2071 } |
| 2082 }); | 2072 }); |
| 2083 | 2073 |
| 2084 ClassElement currentClass = constructor.getEnclosingClass(); | 2074 ClassElement currentClass = constructor.getEnclosingClass(); |
| 2085 if (backend.classNeedsRti(currentClass)) { | 2075 if (backend.classNeedsRti(currentClass)) { |
| 2086 // If [currentClass] needs RTI, we add the type variables as | 2076 // If [currentClass] needs RTI, we add the type variables as |
| 2087 // parameters of the generative constructor body. | 2077 // parameters of the generative constructor body. |
| 2088 currentClass.typeVariables.forEach((DartType argument) { | 2078 currentClass.typeVariables.forEach((DartType argument) { |
| 2079 // TODO(johnniwinther): Substitute [argument] with |
| 2080 // `localsHandler.substInContext(argument)`. |
| 2089 bodyCallInputs.add(localsHandler.readLocal(argument.element)); | 2081 bodyCallInputs.add(localsHandler.readLocal(argument.element)); |
| 2090 }); | 2082 }); |
| 2091 } | 2083 } |
| 2092 | 2084 |
| 2093 // If there are locals that escape (ie mutated in closures), we | 2085 // If there are locals that escape (ie mutated in closures), we |
| 2094 // pass the box to the constructor. | 2086 // pass the box to the constructor. |
| 2095 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; | 2087 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; |
| 2096 if (scopeData != null) { | 2088 if (scopeData != null) { |
| 2097 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); | 2089 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); |
| 2098 } | 2090 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2171 localsHandler.directLocals[parameterElement] = newParameter; | 2163 localsHandler.directLocals[parameterElement] = newParameter; |
| 2172 }); | 2164 }); |
| 2173 | 2165 |
| 2174 returnType = signature.type.returnType; | 2166 returnType = signature.type.returnType; |
| 2175 } else { | 2167 } else { |
| 2176 // Otherwise it is a lazy initializer which does not have parameters. | 2168 // Otherwise it is a lazy initializer which does not have parameters. |
| 2177 assert(element is VariableElement); | 2169 assert(element is VariableElement); |
| 2178 } | 2170 } |
| 2179 } | 2171 } |
| 2180 | 2172 |
| 2173 /// Check that [type] is valid in the context of `localsHandler.contextClass`. |
| 2174 /// This should only be called in assertions. |
| 2175 bool assertTypeInContext(DartType type, [Spannable spannable]) { |
| 2176 return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable, |
| 2177 () { |
| 2178 ClassElement contextClass = Types.getClassContext(type); |
| 2179 return contextClass == null || |
| 2180 contextClass == localsHandler.contextClass; |
| 2181 }, |
| 2182 message: "Type '$type' is not valid context of " |
| 2183 "${localsHandler.contextClass}."); |
| 2184 } |
| 2185 |
| 2186 /// Build a [HTypeConversion] for convertion [original] to type [type]. |
| 2187 /// |
| 2188 /// Invariant: [type] must be valid in the context. |
| 2189 /// See [LocalsHandler.substInContext]. |
| 2181 HInstruction buildTypeConversion(HInstruction original, | 2190 HInstruction buildTypeConversion(HInstruction original, |
| 2182 DartType type, | 2191 DartType type, |
| 2183 int kind) { | 2192 int kind) { |
| 2184 if (type == null) return original; | 2193 if (type == null) return original; |
| 2185 type = type.unalias(compiler); | 2194 assert(assertTypeInContext(type, original)); |
| 2186 if (type.kind == TypeKind.INTERFACE && !type.treatAsRaw) { | 2195 if (type.kind == TypeKind.INTERFACE && !type.treatAsRaw) { |
| 2187 TypeMask subtype = new TypeMask.subtype(type.element); | 2196 TypeMask subtype = new TypeMask.subtype(type.element); |
| 2188 HInstruction representations = buildTypeArgumentRepresentations(type); | 2197 HInstruction representations = buildTypeArgumentRepresentations(type); |
| 2189 add(representations); | 2198 add(representations); |
| 2190 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 2199 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
| 2191 original, representations); | 2200 original, representations); |
| 2192 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 2201 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 2193 TypeMask subtype = original.instructionType; | 2202 TypeMask subtype = original.instructionType; |
| 2194 HInstruction typeVariable = addTypeVariableReference(type); | 2203 HInstruction typeVariable = addTypeVariableReference(type); |
| 2195 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 2204 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2206 | 2215 |
| 2207 return new HTypeConversion(type, kind, original.instructionType, pop()); | 2216 return new HTypeConversion(type, kind, original.instructionType, pop()); |
| 2208 } else { | 2217 } else { |
| 2209 return original.convertType(compiler, type, kind); | 2218 return original.convertType(compiler, type, kind); |
| 2210 } | 2219 } |
| 2211 } | 2220 } |
| 2212 | 2221 |
| 2213 HInstruction potentiallyCheckType(HInstruction original, DartType type, | 2222 HInstruction potentiallyCheckType(HInstruction original, DartType type, |
| 2214 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { | 2223 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
| 2215 if (!compiler.enableTypeAssertions) return original; | 2224 if (!compiler.enableTypeAssertions) return original; |
| 2225 type = localsHandler.substInContext(type); |
| 2216 HInstruction other = buildTypeConversion(original, type, kind); | 2226 HInstruction other = buildTypeConversion(original, type, kind); |
| 2217 if (other != original) add(other); | 2227 if (other != original) add(other); |
| 2218 compiler.enqueuer.codegen.registerIsCheck(type, work.resolutionTree); | 2228 compiler.enqueuer.codegen.registerIsCheck(type, work.resolutionTree); |
| 2219 return other; | 2229 return other; |
| 2220 } | 2230 } |
| 2221 | 2231 |
| 2222 void assertIsSubtype(ast.Node node, DartType subtype, DartType supertype, | 2232 void assertIsSubtype(ast.Node node, DartType subtype, DartType supertype, |
| 2223 String message) { | 2233 String message) { |
| 2224 HInstruction subtypeInstruction = analyzeTypeArgument(subtype); | 2234 HInstruction subtypeInstruction = |
| 2225 HInstruction supertypeInstruction = analyzeTypeArgument(supertype); | 2235 analyzeTypeArgument(localsHandler.substInContext(subtype)); |
| 2236 HInstruction supertypeInstruction = |
| 2237 analyzeTypeArgument(localsHandler.substInContext(supertype)); |
| 2226 HInstruction messageInstruction = | 2238 HInstruction messageInstruction = |
| 2227 graph.addConstantString(new ast.DartString.literal(message), compiler); | 2239 graph.addConstantString(new ast.DartString.literal(message), compiler); |
| 2228 Element element = backend.getAssertIsSubtype(); | 2240 Element element = backend.getAssertIsSubtype(); |
| 2229 var inputs = <HInstruction>[subtypeInstruction, supertypeInstruction, | 2241 var inputs = <HInstruction>[subtypeInstruction, supertypeInstruction, |
| 2230 messageInstruction]; | 2242 messageInstruction]; |
| 2231 HInstruction assertIsSubtype = new HInvokeStatic( | 2243 HInstruction assertIsSubtype = new HInvokeStatic( |
| 2232 element, inputs, subtypeInstruction.instructionType); | 2244 element, inputs, subtypeInstruction.instructionType); |
| 2233 compiler.backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); | 2245 compiler.backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); |
| 2234 add(assertIsSubtype); | 2246 add(assertIsSubtype); |
| 2235 } | 2247 } |
| (...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3153 visitIsSend(node); | 3165 visitIsSend(node); |
| 3154 } else if ("as" == op.source) { | 3166 } else if ("as" == op.source) { |
| 3155 visit(node.receiver); | 3167 visit(node.receiver); |
| 3156 HInstruction expression = pop(); | 3168 HInstruction expression = pop(); |
| 3157 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | 3169 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); |
| 3158 if (type.kind == TypeKind.MALFORMED_TYPE) { | 3170 if (type.kind == TypeKind.MALFORMED_TYPE) { |
| 3159 ErroneousElement element = type.element; | 3171 ErroneousElement element = type.element; |
| 3160 generateTypeError(node, element.message); | 3172 generateTypeError(node, element.message); |
| 3161 } else { | 3173 } else { |
| 3162 HInstruction converted = buildTypeConversion( | 3174 HInstruction converted = buildTypeConversion( |
| 3163 expression, type, HTypeConversion.CAST_TYPE_CHECK); | 3175 expression, |
| 3176 localsHandler.substInContext(type), |
| 3177 HTypeConversion.CAST_TYPE_CHECK); |
| 3164 if (converted != expression) add(converted); | 3178 if (converted != expression) add(converted); |
| 3165 stack.add(converted); | 3179 stack.add(converted); |
| 3166 } | 3180 } |
| 3167 } else { | 3181 } else { |
| 3168 visit(node.receiver); | 3182 visit(node.receiver); |
| 3169 visit(node.argumentsNode); | 3183 visit(node.argumentsNode); |
| 3170 var right = pop(); | 3184 var right = pop(); |
| 3171 var left = pop(); | 3185 var left = pop(); |
| 3172 visitBinary(left, op, right, elements.getSelector(node), node); | 3186 visitBinary(left, op, right, elements.getSelector(node), node); |
| 3173 } | 3187 } |
| 3174 } | 3188 } |
| 3175 | 3189 |
| 3176 void visitIsSend(ast.Send node) { | 3190 void visitIsSend(ast.Send node) { |
| 3177 visit(node.receiver); | 3191 visit(node.receiver); |
| 3178 HInstruction expression = pop(); | 3192 HInstruction expression = pop(); |
| 3179 bool isNot = node.isIsNotCheck; | 3193 bool isNot = node.isIsNotCheck; |
| 3180 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | 3194 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); |
| 3181 type = type.unalias(compiler); | |
| 3182 HInstruction instruction = buildIsNode(node, type, expression); | 3195 HInstruction instruction = buildIsNode(node, type, expression); |
| 3183 if (isNot) { | 3196 if (isNot) { |
| 3184 add(instruction); | 3197 add(instruction); |
| 3185 instruction = new HNot(instruction, backend.boolType); | 3198 instruction = new HNot(instruction, backend.boolType); |
| 3186 } | 3199 } |
| 3187 push(instruction); | 3200 push(instruction); |
| 3188 } | 3201 } |
| 3189 | 3202 |
| 3190 HInstruction buildIsNode(ast.Node node, DartType type, HInstruction expression
) { | 3203 HInstruction buildIsNode(ast.Node node, |
| 3191 type = type.unalias(compiler); | 3204 DartType type, |
| 3205 HInstruction expression) { |
| 3206 type = localsHandler.substInContext(type).unalias(compiler); |
| 3192 if (type.kind == TypeKind.FUNCTION) { | 3207 if (type.kind == TypeKind.FUNCTION) { |
| 3193 List arguments = [buildFunctionType(type), expression]; | 3208 List arguments = [buildFunctionType(type), expression]; |
| 3194 pushInvokeDynamic( | 3209 pushInvokeDynamic( |
| 3195 node, new Selector.call('_isTest', compiler.jsHelperLibrary, 1), | 3210 node, new Selector.call('_isTest', compiler.jsHelperLibrary, 1), |
| 3196 arguments); | 3211 arguments); |
| 3197 return new HIs.compound(type, expression, pop(), backend.boolType); | 3212 return new HIs.compound(type, expression, pop(), backend.boolType); |
| 3198 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 3213 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 3199 HInstruction runtimeType = addTypeVariableReference(type); | 3214 HInstruction runtimeType = addTypeVariableReference(type); |
| 3200 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 3215 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
| 3201 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3216 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3833 // fixed. | 3848 // fixed. |
| 3834 bool hasDirectLocal(Element element) { | 3849 bool hasDirectLocal(Element element) { |
| 3835 return !localsHandler.isAccessedDirectly(element) || | 3850 return !localsHandler.isAccessedDirectly(element) || |
| 3836 localsHandler.directLocals[element] != null; | 3851 localsHandler.directLocals[element] != null; |
| 3837 } | 3852 } |
| 3838 | 3853 |
| 3839 /** | 3854 /** |
| 3840 * Helper to create an instruction that gets the value of a type variable. | 3855 * Helper to create an instruction that gets the value of a type variable. |
| 3841 */ | 3856 */ |
| 3842 HInstruction addTypeVariableReference(TypeVariableType type) { | 3857 HInstruction addTypeVariableReference(TypeVariableType type) { |
| 3858 assert(assertTypeInContext(type)); |
| 3843 Element member = sourceElement; | 3859 Element member = sourceElement; |
| 3844 bool isClosure = member.enclosingElement.isClosure(); | 3860 bool isClosure = member.enclosingElement.isClosure(); |
| 3845 if (isClosure) { | 3861 if (isClosure) { |
| 3846 ClosureClassElement closureClass = member.enclosingElement; | 3862 ClosureClassElement closureClass = member.enclosingElement; |
| 3847 member = closureClass.methodElement; | 3863 member = closureClass.methodElement; |
| 3848 member = member.getOutermostEnclosingMemberOrTopLevel(); | 3864 member = member.getOutermostEnclosingMemberOrTopLevel(); |
| 3849 } | 3865 } |
| 3850 bool isInConstructorContext = member.isConstructor() || | 3866 bool isInConstructorContext = member.isConstructor() || |
| 3851 member.isGenerativeConstructorBody(); | 3867 member.isGenerativeConstructorBody(); |
| 3852 if (isClosure) { | 3868 if (isClosure) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3884 } else { | 3900 } else { |
| 3885 // TODO(ngeoffray): Match the VM behavior and throw an | 3901 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3886 // exception at runtime. | 3902 // exception at runtime. |
| 3887 compiler.internalError(type.element, | 3903 compiler.internalError(type.element, |
| 3888 'Unimplemented unresolved type variable.'); | 3904 'Unimplemented unresolved type variable.'); |
| 3889 return null; | 3905 return null; |
| 3890 } | 3906 } |
| 3891 } | 3907 } |
| 3892 | 3908 |
| 3893 HInstruction analyzeTypeArgument(DartType argument) { | 3909 HInstruction analyzeTypeArgument(DartType argument) { |
| 3910 assert(assertTypeInContext(argument)); |
| 3894 if (argument.treatAsDynamic) { | 3911 if (argument.treatAsDynamic) { |
| 3895 // Represent [dynamic] as [null]. | 3912 // Represent [dynamic] as [null]. |
| 3896 return graph.addConstantNull(compiler); | 3913 return graph.addConstantNull(compiler); |
| 3897 } | 3914 } |
| 3898 | 3915 |
| 3899 if (argument.kind == TypeKind.TYPE_VARIABLE) { | 3916 if (argument.kind == TypeKind.TYPE_VARIABLE) { |
| 3900 return addTypeVariableReference(argument); | 3917 return addTypeVariableReference(argument); |
| 3901 } | 3918 } |
| 3902 | 3919 |
| 3903 List<HInstruction> inputs = <HInstruction>[]; | 3920 List<HInstruction> inputs = <HInstruction>[]; |
| 3904 | 3921 |
| 3905 String template = rti.getTypeRepresentationWithHashes(argument, (variable) { | 3922 String template = rti.getTypeRepresentationWithHashes(argument, (variable) { |
| 3906 inputs.add(addTypeVariableReference(variable)); | 3923 inputs.add(addTypeVariableReference(variable)); |
| 3907 }); | 3924 }); |
| 3908 | 3925 |
| 3909 js.Template code = js.js.uncachedExpressionTemplate(template); | 3926 js.Template code = js.js.uncachedExpressionTemplate(template); |
| 3910 HInstruction result = createForeign(code, backend.stringType, inputs); | 3927 HInstruction result = createForeign(code, backend.stringType, inputs); |
| 3911 add(result); | 3928 add(result); |
| 3912 return result; | 3929 return result; |
| 3913 } | 3930 } |
| 3914 | 3931 |
| 3915 HInstruction handleListConstructor(InterfaceType type, | 3932 HInstruction handleListConstructor(InterfaceType type, |
| 3916 ast.Node currentNode, | 3933 ast.Node currentNode, |
| 3917 HInstruction newObject) { | 3934 HInstruction newObject) { |
| 3918 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 3935 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
| 3919 return newObject; | 3936 return newObject; |
| 3920 } | 3937 } |
| 3921 List<HInstruction> inputs = <HInstruction>[]; | 3938 List<HInstruction> inputs = <HInstruction>[]; |
| 3939 type = localsHandler.substInContext(type); |
| 3922 type.typeArguments.forEach((DartType argument) { | 3940 type.typeArguments.forEach((DartType argument) { |
| 3923 inputs.add(analyzeTypeArgument(argument)); | 3941 inputs.add(analyzeTypeArgument(argument)); |
| 3924 }); | 3942 }); |
| 3925 // TODO(15489): Register at codegen. | 3943 // TODO(15489): Register at codegen. |
| 3926 compiler.enqueuer.codegen.registerInstantiatedType(type, elements); | 3944 compiler.enqueuer.codegen.registerInstantiatedType(type, elements); |
| 3927 return callSetRuntimeTypeInfo(type.element, inputs, newObject); | 3945 return callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| 3928 } | 3946 } |
| 3929 | 3947 |
| 3930 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { | 3948 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { |
| 3931 Element copyHelper = backend.getCopyTypeArguments(); | 3949 Element copyHelper = backend.getCopyTypeArguments(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4020 assert(invariant(send, constructor != null, | 4038 assert(invariant(send, constructor != null, |
| 4021 message: 'Constructor Symbol.validated is missing')); | 4039 message: 'Constructor Symbol.validated is missing')); |
| 4022 selector = compiler.symbolValidatedConstructorSelector; | 4040 selector = compiler.symbolValidatedConstructorSelector; |
| 4023 assert(invariant(send, selector != null, | 4041 assert(invariant(send, selector != null, |
| 4024 message: 'Constructor Symbol.validated is missing')); | 4042 message: 'Constructor Symbol.validated is missing')); |
| 4025 } | 4043 } |
| 4026 | 4044 |
| 4027 bool isRedirected = functionElement.isRedirectingFactory; | 4045 bool isRedirected = functionElement.isRedirectingFactory; |
| 4028 InterfaceType type = elements.getType(node); | 4046 InterfaceType type = elements.getType(node); |
| 4029 InterfaceType expectedType = functionElement.computeTargetType(type); | 4047 InterfaceType expectedType = functionElement.computeTargetType(type); |
| 4048 expectedType = localsHandler.substInContext(expectedType); |
| 4030 | 4049 |
| 4031 if (checkTypeVariableBounds(node, type)) return; | 4050 if (checkTypeVariableBounds(node, type)) return; |
| 4032 | 4051 |
| 4033 var inputs = <HInstruction>[]; | 4052 var inputs = <HInstruction>[]; |
| 4034 if (constructor.isGenerativeConstructor() && | 4053 if (constructor.isGenerativeConstructor() && |
| 4035 Elements.isNativeOrExtendsNative(constructor.getEnclosingClass())) { | 4054 Elements.isNativeOrExtendsNative(constructor.getEnclosingClass())) { |
| 4036 // Native class generative constructors take a pre-constructed object. | 4055 // Native class generative constructors take a pre-constructed object. |
| 4037 inputs.add(graph.addConstantNull(compiler)); | 4056 inputs.add(graph.addConstantNull(compiler)); |
| 4038 } | 4057 } |
| 4039 // TODO(5347): Try to avoid the need for calling [implementation] before | 4058 // TODO(5347): Try to avoid the need for calling [implementation] before |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4257 // TODO(karlklose): add type representation | 4276 // TODO(karlklose): add type representation |
| 4258 if (node.isCall) { | 4277 if (node.isCall) { |
| 4259 // The node itself is not a constant but we register the selector (the | 4278 // The node itself is not a constant but we register the selector (the |
| 4260 // identifier that refers to the class/typedef) as a constant. | 4279 // identifier that refers to the class/typedef) as a constant. |
| 4261 stack.add(addConstant(node.selector)); | 4280 stack.add(addConstant(node.selector)); |
| 4262 } else { | 4281 } else { |
| 4263 stack.add(addConstant(node)); | 4282 stack.add(addConstant(node)); |
| 4264 } | 4283 } |
| 4265 } else if (element.isTypeVariable()) { | 4284 } else if (element.isTypeVariable()) { |
| 4266 TypeVariableElement typeVariable = element; | 4285 TypeVariableElement typeVariable = element; |
| 4267 HInstruction value = addTypeVariableReference(typeVariable.type); | 4286 DartType type = localsHandler.substInContext(typeVariable.type); |
| 4287 HInstruction value = analyzeTypeArgument(type); |
| 4268 pushInvokeStatic(node, | 4288 pushInvokeStatic(node, |
| 4269 backend.getRuntimeTypeToString(), | 4289 backend.getRuntimeTypeToString(), |
| 4270 [value], | 4290 [value], |
| 4271 backend.stringType); | 4291 backend.stringType); |
| 4272 pushInvokeStatic(node, | 4292 pushInvokeStatic(node, |
| 4273 backend.getCreateRuntimeType(), | 4293 backend.getCreateRuntimeType(), |
| 4274 [pop()]); | 4294 [pop()]); |
| 4275 } else { | 4295 } else { |
| 4276 internalError('unexpected element kind $element', node: node); | 4296 internalError('unexpected element kind $element', node: node); |
| 4277 } | 4297 } |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4821 } | 4841 } |
| 4822 for (; i < targetOptionals.length; i++) { | 4842 for (; i < targetOptionals.length; i++) { |
| 4823 inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); | 4843 inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); |
| 4824 } | 4844 } |
| 4825 | 4845 |
| 4826 ClassElement targetClass = targetConstructor.getEnclosingClass(); | 4846 ClassElement targetClass = targetConstructor.getEnclosingClass(); |
| 4827 if (backend.classNeedsRti(targetClass)) { | 4847 if (backend.classNeedsRti(targetClass)) { |
| 4828 ClassElement cls = redirectingConstructor.getEnclosingClass(); | 4848 ClassElement cls = redirectingConstructor.getEnclosingClass(); |
| 4829 InterfaceType targetType = | 4849 InterfaceType targetType = |
| 4830 redirectingConstructor.computeTargetType(cls.thisType); | 4850 redirectingConstructor.computeTargetType(cls.thisType); |
| 4851 targetType = localsHandler.substInContext(targetType); |
| 4831 targetType.typeArguments.forEach((DartType argument) { | 4852 targetType.typeArguments.forEach((DartType argument) { |
| 4832 inputs.add(analyzeTypeArgument(argument)); | 4853 inputs.add(analyzeTypeArgument(argument)); |
| 4833 }); | 4854 }); |
| 4834 } | 4855 } |
| 4835 pushInvokeStatic(node, targetConstructor, inputs); | 4856 pushInvokeStatic(node, targetConstructor, inputs); |
| 4836 value = pop(); | 4857 value = pop(); |
| 4837 } else if (node.expression == null) { | 4858 } else if (node.expression == null) { |
| 4838 value = graph.addConstantNull(compiler); | 4859 value = graph.addConstantNull(compiler); |
| 4839 } else { | 4860 } else { |
| 4840 visit(node.expression); | 4861 visit(node.expression); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4871 localsHandler.updateLocal(elements[definition], initialValue); | 4892 localsHandler.updateLocal(elements[definition], initialValue); |
| 4872 } else { | 4893 } else { |
| 4873 assert(definition is ast.SendSet); | 4894 assert(definition is ast.SendSet); |
| 4874 visitSendSet(definition); | 4895 visitSendSet(definition); |
| 4875 pop(); // Discard value. | 4896 pop(); // Discard value. |
| 4876 } | 4897 } |
| 4877 } | 4898 } |
| 4878 } | 4899 } |
| 4879 | 4900 |
| 4880 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) { | 4901 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) { |
| 4881 InterfaceType type = elements.getType(node); | 4902 InterfaceType type = localsHandler.substInContext(elements.getType(node)); |
| 4882 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 4903 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
| 4883 return object; | 4904 return object; |
| 4884 } | 4905 } |
| 4885 List<HInstruction> arguments = <HInstruction>[]; | 4906 List<HInstruction> arguments = <HInstruction>[]; |
| 4886 for (DartType argument in type.typeArguments) { | 4907 for (DartType argument in type.typeArguments) { |
| 4887 arguments.add(analyzeTypeArgument(argument)); | 4908 arguments.add(analyzeTypeArgument(argument)); |
| 4888 } | 4909 } |
| 4889 // TODO(15489): Register at codegen. | 4910 // TODO(15489): Register at codegen. |
| 4890 compiler.enqueuer.codegen.registerInstantiatedType(type, elements); | 4911 compiler.enqueuer.codegen.registerInstantiatedType(type, elements); |
| 4891 return callSetRuntimeTypeInfo(type.element, arguments, object); | 4912 return callSetRuntimeTypeInfo(type.element, arguments, object); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5118 inputs.add(keyValuePairs); | 5139 inputs.add(keyValuePairs); |
| 5119 } | 5140 } |
| 5120 | 5141 |
| 5121 assert(constructor.isFactoryConstructor()); | 5142 assert(constructor.isFactoryConstructor()); |
| 5122 | 5143 |
| 5123 FunctionElement functionElement = constructor; | 5144 FunctionElement functionElement = constructor; |
| 5124 constructor = functionElement.redirectionTarget; | 5145 constructor = functionElement.redirectionTarget; |
| 5125 | 5146 |
| 5126 InterfaceType type = elements.getType(node); | 5147 InterfaceType type = elements.getType(node); |
| 5127 InterfaceType expectedType = functionElement.computeTargetType(type); | 5148 InterfaceType expectedType = functionElement.computeTargetType(type); |
| 5149 expectedType = localsHandler.substInContext(expectedType); |
| 5128 | 5150 |
| 5129 if (constructor.isFactoryConstructor()) { | 5151 if (constructor.isFactoryConstructor()) { |
| 5130 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); | 5152 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); |
| 5131 } | 5153 } |
| 5132 | 5154 |
| 5133 ClassElement cls = constructor.getEnclosingClass(); | 5155 ClassElement cls = constructor.getEnclosingClass(); |
| 5134 | 5156 |
| 5135 if (backend.classNeedsRti(cls)) { | 5157 if (backend.classNeedsRti(cls)) { |
| 5136 Link<DartType> typeVariable = cls.typeVariables; | 5158 Link<DartType> typeVariable = cls.typeVariables; |
| 5137 expectedType.typeArguments.forEach((DartType argument) { | 5159 expectedType.typeArguments.forEach((DartType argument) { |
| (...skipping 1178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6316 DartType unaliased = type.unalias(builder.compiler); | 6338 DartType unaliased = type.unalias(builder.compiler); |
| 6317 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6339 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6318 unaliased.accept(this, builder); | 6340 unaliased.accept(this, builder); |
| 6319 } | 6341 } |
| 6320 | 6342 |
| 6321 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6343 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6322 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); | 6344 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); |
| 6323 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); | 6345 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 6324 } | 6346 } |
| 6325 } | 6347 } |
| OLD | NEW |