Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 177963002: Use List instead of Link in the type system. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698