Chromium Code Reviews| 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 1809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1820 ClassElement enclosingClass = callee.getEnclosingClass(); | 1820 ClassElement enclosingClass = callee.getEnclosingClass(); |
| 1821 if (backend.classNeedsRti(enclosingClass)) { | 1821 if (backend.classNeedsRti(enclosingClass)) { |
| 1822 // If [enclosingClass] needs RTI, we have to give a value to its | 1822 // If [enclosingClass] needs RTI, we have to give a value to its |
| 1823 // type parameters. | 1823 // type parameters. |
| 1824 ClassElement currentClass = caller.getEnclosingClass(); | 1824 ClassElement currentClass = caller.getEnclosingClass(); |
| 1825 // For a super constructor call, the type is the supertype of | 1825 // For a super constructor call, the type is the supertype of |
| 1826 // [currentClass]. For a redirecting constructor, the type is | 1826 // [currentClass]. For a redirecting constructor, the type is |
| 1827 // the current type. [InterfaceType.asInstanceOf] takes care | 1827 // the current type. [InterfaceType.asInstanceOf] takes care |
| 1828 // of both. | 1828 // of both. |
| 1829 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); | 1829 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); |
| 1830 Link<DartType> typeVariables = enclosingClass.typeVariables; | 1830 List<DartType> arguments = type.typeArguments; |
| 1831 type.typeArguments.forEach((DartType argument) { | 1831 List<DartType> typeVariables = enclosingClass.typeVariables; |
| 1832 localsHandler.updateLocal( | 1832 if (!type.isRaw) { |
| 1833 typeVariables.head.element, | 1833 assert(arguments.length == typeVariables.length); |
| 1834 analyzeTypeArgument(argument)); | 1834 Iterator<DartType> variables = typeVariables.iterator; |
| 1835 typeVariables = typeVariables.tail; | 1835 type.typeArguments.forEach((DartType argument) { |
| 1836 }); | 1836 variables.moveNext(); |
| 1837 // If the supertype is a raw type, we need to set to null the | 1837 localsHandler.updateLocal( |
| 1838 // type variables. | 1838 variables.current.element, |
| 1839 assert(typeVariables.isEmpty | 1839 analyzeTypeArgument(argument)); |
| 1840 || enclosingClass.typeVariables == typeVariables); | 1840 }); |
| 1841 while (!typeVariables.isEmpty) { | 1841 } else { |
| 1842 localsHandler.updateLocal(typeVariables.head.element, | 1842 // If the supertype is a raw type, we need to set to null the |
| 1843 graph.addConstantNull(compiler)); | 1843 // type variables. |
| 1844 typeVariables = typeVariables.tail; | 1844 for (DartType variable in typeVariables) { |
| 1845 localsHandler.updateLocal(variable.element, | |
| 1846 graph.addConstantNull(compiler)); | |
| 1847 } | |
| 1845 } | 1848 } |
| 1846 } | 1849 } |
| 1847 | 1850 |
| 1848 // For redirecting constructors, the fields have already been | 1851 // For redirecting constructors, the fields have already been |
| 1849 // initialized by the caller. | 1852 // initialized by the caller. |
| 1850 if (callee.getEnclosingClass() != caller.getEnclosingClass()) { | 1853 if (callee.getEnclosingClass() != caller.getEnclosingClass()) { |
| 1851 inlinedFrom(callee, () { | 1854 inlinedFrom(callee, () { |
| 1852 buildFieldInitializers(callee.enclosingElement.implementation, | 1855 buildFieldInitializers(callee.enclosingElement.implementation, |
| 1853 fieldValues); | 1856 fieldValues); |
| 1854 }); | 1857 }); |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2134 // would be of the form: | 2137 // would be of the form: |
| 2135 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] | 2138 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] |
| 2136 // and k is the number of type arguments of this. If this is the case, | 2139 // and k is the number of type arguments of this. If this is the case, |
| 2137 // we can simply copy the list from this. | 2140 // we can simply copy the list from this. |
| 2138 | 2141 |
| 2139 // These locals are modified by [isIndexedTypeArgumentGet]. | 2142 // These locals are modified by [isIndexedTypeArgumentGet]. |
| 2140 HInstruction source; // The source of the type arguments. | 2143 HInstruction source; // The source of the type arguments. |
| 2141 bool allIndexed = true; | 2144 bool allIndexed = true; |
| 2142 int expectedIndex = 0; | 2145 int expectedIndex = 0; |
| 2143 ClassElement contextClass; // The class of `this`. | 2146 ClassElement contextClass; // The class of `this`. |
| 2144 Link typeVariables; // The list of 'remaining type variables' of `this`. | 2147 int remainingTypeVariables; // The number of 'remaining type variables' |
| 2148 //of `this`. | |
|
Johnni Winther
2014/02/26 14:01:54
Add space after //
karlklose
2014/02/27 09:31:41
Done.
| |
| 2145 | 2149 |
| 2146 /// Helper to identify instructions that read a type variable without | 2150 /// Helper to identify instructions that read a type variable without |
| 2147 /// substitution (that is, directly use the index). These instructions | 2151 /// substitution (that is, directly use the index). These instructions |
| 2148 /// are of the form: | 2152 /// are of the form: |
| 2149 /// HInvokeStatic(getTypeArgumentByIndex, this, index) | 2153 /// HInvokeStatic(getTypeArgumentByIndex, this, index) |
| 2150 /// | 2154 /// |
| 2151 /// Return `true` if [instruction] is of that form and the index is the | 2155 /// Return `true` if [instruction] is of that form and the index is the |
| 2152 /// next index in the sequence (held in [expectedIndex]). | 2156 /// next index in the sequence (held in [expectedIndex]). |
| 2153 bool isIndexedTypeArgumentGet(HInstruction instruction) { | 2157 bool isIndexedTypeArgumentGet(HInstruction instruction) { |
| 2154 if (instruction is! HInvokeStatic) return false; | 2158 if (instruction is! HInvokeStatic) return false; |
| 2155 HInvokeStatic invoke = instruction; | 2159 HInvokeStatic invoke = instruction; |
| 2156 if (invoke.element != backend.getGetTypeArgumentByIndex()) { | 2160 if (invoke.element != backend.getGetTypeArgumentByIndex()) { |
| 2157 return false; | 2161 return false; |
| 2158 } | 2162 } |
| 2159 HConstant index = invoke.inputs[1]; | 2163 HConstant index = invoke.inputs[1]; |
| 2160 HInstruction newSource = invoke.inputs[0]; | 2164 HInstruction newSource = invoke.inputs[0]; |
| 2161 if (newSource is! HThis) { | 2165 if (newSource is! HThis) { |
| 2162 return false; | 2166 return false; |
| 2163 } | 2167 } |
| 2164 if (source == null) { | 2168 if (source == null) { |
| 2165 // This is the first match. Extract the context class for the type | 2169 // This is the first match. Extract the context class for the type |
| 2166 // variables and get the list of type variables to keep track of how | 2170 // variables and get the list of type variables to keep track of how |
| 2167 // many arguments we need to process. | 2171 // many arguments we need to process. |
| 2168 source = newSource; | 2172 source = newSource; |
| 2169 contextClass = source.sourceElement.getEnclosingClass(); | 2173 contextClass = source.sourceElement.getEnclosingClass(); |
| 2170 typeVariables = contextClass.typeVariables; | 2174 remainingTypeVariables = contextClass.typeVariables.length; |
| 2171 } else { | 2175 } else { |
| 2172 assert(source == newSource); | 2176 assert(source == newSource); |
| 2173 } | 2177 } |
| 2174 // If there are no more type variables, then there are more type | 2178 // If there are no more type variables, then there are more type |
| 2175 // arguments for the new object than the source has, and it can't be | 2179 // arguments for the new object than the source has, and it can't be |
| 2176 // a copy. Otherwise remove one argument. | 2180 // a copy. Otherwise remove one argument. |
| 2177 if (typeVariables.isEmpty) return false; | 2181 if (remainingTypeVariables == 0) return false; |
| 2178 typeVariables = typeVariables.tail; | 2182 remainingTypeVariables--; |
| 2179 // Check that the index is the one we expect. | 2183 // Check that the index is the one we expect. |
| 2180 IntConstant constant = index.constant; | 2184 IntConstant constant = index.constant; |
| 2181 return constant.value == expectedIndex++; | 2185 return constant.value == expectedIndex++; |
| 2182 } | 2186 } |
| 2183 | 2187 |
| 2184 List<HInstruction> typeArguments = <HInstruction>[]; | 2188 List<HInstruction> typeArguments = <HInstruction>[]; |
| 2185 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 2189 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
| 2186 HInstruction argument = localsHandler.readLocal(typeVariable.element); | 2190 HInstruction argument = localsHandler.readLocal(typeVariable.element); |
| 2187 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { | 2191 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { |
| 2188 allIndexed = false; | 2192 allIndexed = false; |
| 2189 } | 2193 } |
| 2190 typeArguments.add(argument); | 2194 typeArguments.add(argument); |
| 2191 }); | 2195 }); |
| 2192 | 2196 |
| 2193 if (source != null && allIndexed && typeVariables.isEmpty) { | 2197 if (source != null && allIndexed && remainingTypeVariables == 0) { |
| 2194 copyRuntimeTypeInfo(source, newObject); | 2198 copyRuntimeTypeInfo(source, newObject); |
| 2195 } else { | 2199 } else { |
| 2196 newObject = | 2200 newObject = |
| 2197 callSetRuntimeTypeInfo(classElement, typeArguments, newObject); | 2201 callSetRuntimeTypeInfo(classElement, typeArguments, newObject); |
| 2198 } | 2202 } |
| 2199 } | 2203 } |
| 2200 | 2204 |
| 2201 // Generate calls to the constructor bodies. | 2205 // Generate calls to the constructor bodies. |
| 2202 HInstruction interceptor = null; | 2206 HInstruction interceptor = null; |
| 2203 for (int index = constructors.length - 1; index >= 0; index--) { | 2207 for (int index = constructors.length - 1; index >= 0; index--) { |
| (...skipping 1930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4134 } | 4138 } |
| 4135 } else if (isGrowableListConstructorCall) { | 4139 } else if (isGrowableListConstructorCall) { |
| 4136 push(buildLiteralList(<HInstruction>[])); | 4140 push(buildLiteralList(<HInstruction>[])); |
| 4137 stack.last.instructionType = elementType; | 4141 stack.last.instructionType = elementType; |
| 4138 } else { | 4142 } else { |
| 4139 ClassElement cls = constructor.getEnclosingClass(); | 4143 ClassElement cls = constructor.getEnclosingClass(); |
| 4140 if (cls.isAbstract && constructor.isGenerativeConstructor()) { | 4144 if (cls.isAbstract && constructor.isGenerativeConstructor()) { |
| 4141 generateAbstractClassInstantiationError(send, cls.name); | 4145 generateAbstractClassInstantiationError(send, cls.name); |
| 4142 return; | 4146 return; |
| 4143 } | 4147 } |
| 4144 if (backend.classNeedsRti(cls)) { | 4148 potentiallyAddTypeArguments(inputs, cls, expectedType); |
| 4145 Link<DartType> typeVariable = cls.typeVariables; | |
| 4146 expectedType.typeArguments.forEach((DartType argument) { | |
| 4147 inputs.add(analyzeTypeArgument(argument)); | |
| 4148 typeVariable = typeVariable.tail; | |
| 4149 }); | |
| 4150 assert(typeVariable.isEmpty); | |
| 4151 } | |
| 4152 | 4149 |
| 4153 addInlinedInstantiation(expectedType); | 4150 addInlinedInstantiation(expectedType); |
| 4154 pushInvokeStatic(node, constructor, inputs, elementType); | 4151 pushInvokeStatic(node, constructor, inputs, elementType); |
| 4155 removeInlinedInstantiation(expectedType); | 4152 removeInlinedInstantiation(expectedType); |
| 4156 } | 4153 } |
| 4157 HInstruction newInstance = stack.last; | 4154 HInstruction newInstance = stack.last; |
| 4158 if (isFixedList) { | 4155 if (isFixedList) { |
| 4159 // Overwrite the element type, in case the allocation site has | 4156 // Overwrite the element type, in case the allocation site has |
| 4160 // been inlined. | 4157 // been inlined. |
| 4161 newInstance.instructionType = elementType; | 4158 newInstance.instructionType = elementType; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 4177 // Finally, if we called a redirecting factory constructor, check the type. | 4174 // Finally, if we called a redirecting factory constructor, check the type. |
| 4178 if (isRedirected) { | 4175 if (isRedirected) { |
| 4179 HInstruction checked = potentiallyCheckType(newInstance, type); | 4176 HInstruction checked = potentiallyCheckType(newInstance, type); |
| 4180 if (checked != newInstance) { | 4177 if (checked != newInstance) { |
| 4181 pop(); | 4178 pop(); |
| 4182 stack.add(checked); | 4179 stack.add(checked); |
| 4183 } | 4180 } |
| 4184 } | 4181 } |
| 4185 } | 4182 } |
| 4186 | 4183 |
| 4184 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls, | |
| 4185 InterfaceType expectedType) { | |
| 4186 if (!backend.classNeedsRti(cls)) return; | |
| 4187 assert(expectedType.typeArguments.isEmpty || | |
|
Johnni Winther
2014/02/26 14:01:54
`expectedType.typeArguments.isEmpty ||` should not
karlklose
2014/02/27 09:31:41
If cls is expectedType.element, this assertion is
Johnni Winther
2014/02/27 09:48:23
Shouldn't we then just assert `cls == expectedType
| |
| 4188 cls.typeVariables.length == expectedType.typeArguments.length); | |
| 4189 expectedType.typeArguments.forEach((DartType argument) { | |
| 4190 inputs.add(analyzeTypeArgument(argument)); | |
| 4191 }); | |
| 4192 } | |
| 4193 | |
| 4187 /// In checked mode checks the [type] of [node] to be well-bounded. The method | 4194 /// In checked mode checks the [type] of [node] to be well-bounded. The method |
| 4188 /// returns [:true:] if an error can be statically determined. | 4195 /// returns [:true:] if an error can be statically determined. |
| 4189 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { | 4196 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { |
| 4190 if (!compiler.enableTypeAssertions) return false; | 4197 if (!compiler.enableTypeAssertions) return false; |
| 4191 | 4198 |
| 4192 Map<DartType, Set<DartType>> seenChecksMap = | 4199 Map<DartType, Set<DartType>> seenChecksMap = |
| 4193 new Map<DartType, Set<DartType>>(); | 4200 new Map<DartType, Set<DartType>>(); |
| 4194 bool definitelyFails = false; | 4201 bool definitelyFails = false; |
| 4195 | 4202 |
| 4196 addTypeVariableBoundCheck(GenericType instance, | 4203 addTypeVariableBoundCheck(GenericType instance, |
| (...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4859 calleeSignature.orderedOptionalParameters; | 4866 calleeSignature.orderedOptionalParameters; |
| 4860 List<Element> callerOptionals = | 4867 List<Element> callerOptionals = |
| 4861 callerSignature.orderedOptionalParameters; | 4868 callerSignature.orderedOptionalParameters; |
| 4862 int i = 0; | 4869 int i = 0; |
| 4863 for (; i < callerOptionals.length; i++) { | 4870 for (; i < callerOptionals.length; i++) { |
| 4864 inputs.add(localsHandler.readLocal(callerOptionals[i])); | 4871 inputs.add(localsHandler.readLocal(callerOptionals[i])); |
| 4865 } | 4872 } |
| 4866 for (; i < calleeOptionals.length; i++) { | 4873 for (; i < calleeOptionals.length; i++) { |
| 4867 inputs.add(handleConstantForOptionalParameter(calleeOptionals[i])); | 4874 inputs.add(handleConstantForOptionalParameter(calleeOptionals[i])); |
| 4868 } | 4875 } |
| 4869 | 4876 potentiallyAddTypeArguments(inputs, element.getEnclosingClass(), |
| 4870 if (backend.classNeedsRti(element.getEnclosingClass())) { | 4877 elements.getType(node.expression)); |
| 4871 ClassElement cls = function.getEnclosingClass(); | |
| 4872 Link<DartType> typeVariable = cls.typeVariables; | |
| 4873 InterfaceType type = elements.getType(node.expression); | |
| 4874 type.typeArguments.forEach((DartType argument) { | |
| 4875 inputs.add(analyzeTypeArgument(argument)); | |
| 4876 typeVariable = typeVariable.tail; | |
| 4877 }); | |
| 4878 assert(typeVariable.isEmpty); | |
| 4879 } | |
| 4880 pushInvokeStatic(node, element, inputs); | 4878 pushInvokeStatic(node, element, inputs); |
| 4881 value = pop(); | 4879 value = pop(); |
| 4882 } else if (node.expression == null) { | 4880 } else if (node.expression == null) { |
| 4883 value = graph.addConstantNull(compiler); | 4881 value = graph.addConstantNull(compiler); |
| 4884 } else { | 4882 } else { |
| 4885 visit(node.expression); | 4883 visit(node.expression); |
| 4886 value = pop(); | 4884 value = pop(); |
| 4887 value = potentiallyCheckType(value, returnType); | 4885 value = potentiallyCheckType(value, returnType); |
| 4888 } | 4886 } |
| 4889 | 4887 |
| (...skipping 1465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6355 for (DartType parameter in type.parameterTypes) { | 6353 for (DartType parameter in type.parameterTypes) { |
| 6356 parameter.accept(this, builder); | 6354 parameter.accept(this, builder); |
| 6357 inputs.add(builder.pop()); | 6355 inputs.add(builder.pop()); |
| 6358 } | 6356 } |
| 6359 | 6357 |
| 6360 for (DartType parameter in type.optionalParameterTypes) { | 6358 for (DartType parameter in type.optionalParameterTypes) { |
| 6361 parameter.accept(this, builder); | 6359 parameter.accept(this, builder); |
| 6362 inputs.add(builder.pop()); | 6360 inputs.add(builder.pop()); |
| 6363 } | 6361 } |
| 6364 | 6362 |
| 6365 Link<DartType> namedParameterTypes = type.namedParameterTypes; | 6363 List<DartType> namedParameterTypes = type.namedParameterTypes; |
| 6366 for (String name in type.namedParameters) { | 6364 List<String> names = type.namedParameters; |
| 6367 ast.DartString dartString = new ast.DartString.literal(name); | 6365 for (int index = 0; index < names.length; index++) { |
| 6366 ast.DartString dartString = new ast.DartString.literal(names[index]); | |
| 6368 inputs.add( | 6367 inputs.add( |
| 6369 builder.graph.addConstantString(dartString, builder.compiler)); | 6368 builder.graph.addConstantString(dartString, builder.compiler)); |
| 6370 namedParameterTypes.head.accept(this, builder); | 6369 namedParameterTypes[index].accept(this, builder); |
| 6371 inputs.add(builder.pop()); | 6370 inputs.add(builder.pop()); |
| 6372 namedParameterTypes = namedParameterTypes.tail; | |
| 6373 } | 6371 } |
| 6374 | 6372 |
| 6375 ClassElement cls = builder.compiler.findHelper('RuntimeFunctionType'); | 6373 ClassElement cls = builder.compiler.findHelper('RuntimeFunctionType'); |
| 6376 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls))); | 6374 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls))); |
| 6377 } | 6375 } |
| 6378 | 6376 |
| 6379 void visitMalformedType(MalformedType type, SsaFromAstMixin builder) { | 6377 void visitMalformedType(MalformedType type, SsaFromAstMixin builder) { |
| 6380 visitDynamicType(builder.compiler.types.dynamicType, builder); | 6378 visitDynamicType(builder.compiler.types.dynamicType, builder); |
| 6381 } | 6379 } |
| 6382 | 6380 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 6407 DartType unaliased = type.unalias(builder.compiler); | 6405 DartType unaliased = type.unalias(builder.compiler); |
| 6408 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6406 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6409 unaliased.accept(this, builder); | 6407 unaliased.accept(this, builder); |
| 6410 } | 6408 } |
| 6411 | 6409 |
| 6412 void visitDynamicType(DynamicType type, SsaFromAstMixin builder) { | 6410 void visitDynamicType(DynamicType type, SsaFromAstMixin builder) { |
| 6413 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); | 6411 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); |
| 6414 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); | 6412 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 6415 } | 6413 } |
| 6416 } | 6414 } |
| OLD | NEW |