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 |