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

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: Address comments. Created 6 years, 5 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 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 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after
1661 if (backend.classNeedsRti(enclosingClass)) { 1661 if (backend.classNeedsRti(enclosingClass)) {
1662 // If [enclosingClass] needs RTI, we have to give a value to its 1662 // If [enclosingClass] needs RTI, we have to give a value to its
1663 // type parameters. 1663 // type parameters.
1664 ClassElement currentClass = caller.enclosingClass; 1664 ClassElement currentClass = caller.enclosingClass;
1665 // For a super constructor call, the type is the supertype of 1665 // For a super constructor call, the type is the supertype of
1666 // [currentClass]. For a redirecting constructor, the type is 1666 // [currentClass]. For a redirecting constructor, the type is
1667 // the current type. [InterfaceType.asInstanceOf] takes care 1667 // the current type. [InterfaceType.asInstanceOf] takes care
1668 // of both. 1668 // of both.
1669 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); 1669 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass);
1670 type = localsHandler.substInContext(type); 1670 type = localsHandler.substInContext(type);
1671 Link<DartType> typeVariables = enclosingClass.typeVariables; 1671 List<DartType> arguments = type.typeArguments;
1672 type.typeArguments.forEach((DartType argument) { 1672 List<DartType> typeVariables = enclosingClass.typeVariables;
1673 localsHandler.updateLocal( 1673 if (!type.isRaw) {
1674 typeVariables.head.element, 1674 assert(arguments.length == typeVariables.length);
1675 analyzeTypeArgument(argument)); 1675 Iterator<DartType> variables = typeVariables.iterator;
1676 typeVariables = typeVariables.tail; 1676 type.typeArguments.forEach((DartType argument) {
1677 }); 1677 variables.moveNext();
1678 // If the supertype is a raw type, we need to set to null the 1678 localsHandler.updateLocal(
1679 // type variables. 1679 variables.current.element,
1680 assert(typeVariables.isEmpty 1680 analyzeTypeArgument(argument));
1681 || enclosingClass.typeVariables == typeVariables); 1681 });
1682 while (!typeVariables.isEmpty) { 1682 } else {
1683 localsHandler.updateLocal(typeVariables.head.element, 1683 // If the supertype is a raw type, we need to set to null the
1684 graph.addConstantNull(compiler)); 1684 // type variables.
1685 typeVariables = typeVariables.tail; 1685 for (DartType variable in typeVariables) {
1686 localsHandler.updateLocal(variable.element,
1687 graph.addConstantNull(compiler));
1688 }
1686 } 1689 }
1687 } 1690 }
1688 1691
1689 // For redirecting constructors, the fields have already been 1692 // For redirecting constructors, the fields have already been
1690 // initialized by the caller. 1693 // initialized by the caller.
1691 if (callee.enclosingClass != caller.enclosingClass) { 1694 if (callee.enclosingClass != caller.enclosingClass) {
1692 inlinedFrom(callee, () { 1695 inlinedFrom(callee, () {
1693 buildFieldInitializers(callee.enclosingElement.implementation, 1696 buildFieldInitializers(callee.enclosingElement.implementation,
1694 fieldValues); 1697 fieldValues);
1695 }); 1698 });
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1977 // would be of the form: 1980 // would be of the form:
1978 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] 1981 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)]
1979 // and k is the number of type arguments of this. If this is the case, 1982 // and k is the number of type arguments of this. If this is the case,
1980 // we can simply copy the list from this. 1983 // we can simply copy the list from this.
1981 1984
1982 // These locals are modified by [isIndexedTypeArgumentGet]. 1985 // These locals are modified by [isIndexedTypeArgumentGet].
1983 HInstruction source; // The source of the type arguments. 1986 HInstruction source; // The source of the type arguments.
1984 bool allIndexed = true; 1987 bool allIndexed = true;
1985 int expectedIndex = 0; 1988 int expectedIndex = 0;
1986 ClassElement contextClass; // The class of `this`. 1989 ClassElement contextClass; // The class of `this`.
1987 Link typeVariables; // The list of 'remaining type variables' of `this`. 1990 int remainingTypeVariables; // The number of 'remaining type variables'
1991 // of `this`.
1988 1992
1989 /// Helper to identify instructions that read a type variable without 1993 /// Helper to identify instructions that read a type variable without
1990 /// substitution (that is, directly use the index). These instructions 1994 /// substitution (that is, directly use the index). These instructions
1991 /// are of the form: 1995 /// are of the form:
1992 /// HInvokeStatic(getTypeArgumentByIndex, this, index) 1996 /// HInvokeStatic(getTypeArgumentByIndex, this, index)
1993 /// 1997 ///
1994 /// Return `true` if [instruction] is of that form and the index is the 1998 /// Return `true` if [instruction] is of that form and the index is the
1995 /// next index in the sequence (held in [expectedIndex]). 1999 /// next index in the sequence (held in [expectedIndex]).
1996 bool isIndexedTypeArgumentGet(HInstruction instruction) { 2000 bool isIndexedTypeArgumentGet(HInstruction instruction) {
1997 if (instruction is! HInvokeStatic) return false; 2001 if (instruction is! HInvokeStatic) return false;
1998 HInvokeStatic invoke = instruction; 2002 HInvokeStatic invoke = instruction;
1999 if (invoke.element != backend.getGetTypeArgumentByIndex()) { 2003 if (invoke.element != backend.getGetTypeArgumentByIndex()) {
2000 return false; 2004 return false;
2001 } 2005 }
2002 HConstant index = invoke.inputs[1]; 2006 HConstant index = invoke.inputs[1];
2003 HInstruction newSource = invoke.inputs[0]; 2007 HInstruction newSource = invoke.inputs[0];
2004 if (newSource is! HThis) { 2008 if (newSource is! HThis) {
2005 return false; 2009 return false;
2006 } 2010 }
2007 if (source == null) { 2011 if (source == null) {
2008 // This is the first match. Extract the context class for the type 2012 // This is the first match. Extract the context class for the type
2009 // variables and get the list of type variables to keep track of how 2013 // variables and get the list of type variables to keep track of how
2010 // many arguments we need to process. 2014 // many arguments we need to process.
2011 source = newSource; 2015 source = newSource;
2012 contextClass = source.sourceElement.enclosingClass; 2016 contextClass = source.sourceElement.enclosingClass;
2013 typeVariables = contextClass.typeVariables; 2017 remainingTypeVariables = contextClass.typeVariables.length;
2014 } else { 2018 } else {
2015 assert(source == newSource); 2019 assert(source == newSource);
2016 } 2020 }
2017 // If there are no more type variables, then there are more type 2021 // If there are no more type variables, then there are more type
2018 // arguments for the new object than the source has, and it can't be 2022 // arguments for the new object than the source has, and it can't be
2019 // a copy. Otherwise remove one argument. 2023 // a copy. Otherwise remove one argument.
2020 if (typeVariables.isEmpty) return false; 2024 if (remainingTypeVariables == 0) return false;
2021 typeVariables = typeVariables.tail; 2025 remainingTypeVariables--;
2022 // Check that the index is the one we expect. 2026 // Check that the index is the one we expect.
2023 IntConstant constant = index.constant; 2027 IntConstant constant = index.constant;
2024 return constant.value == expectedIndex++; 2028 return constant.value == expectedIndex++;
2025 } 2029 }
2026 2030
2027 List<HInstruction> typeArguments = <HInstruction>[]; 2031 List<HInstruction> typeArguments = <HInstruction>[];
2028 classElement.typeVariables.forEach((TypeVariableType typeVariable) { 2032 classElement.typeVariables.forEach((TypeVariableType typeVariable) {
2029 HInstruction argument = localsHandler.readLocal(typeVariable.element); 2033 HInstruction argument = localsHandler.readLocal(typeVariable.element);
2030 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { 2034 if (allIndexed && !isIndexedTypeArgumentGet(argument)) {
2031 allIndexed = false; 2035 allIndexed = false;
2032 } 2036 }
2033 typeArguments.add(argument); 2037 typeArguments.add(argument);
2034 }); 2038 });
2035 2039
2036 if (source != null && allIndexed && typeVariables.isEmpty) { 2040 if (source != null && allIndexed && remainingTypeVariables == 0) {
2037 copyRuntimeTypeInfo(source, newObject); 2041 copyRuntimeTypeInfo(source, newObject);
2038 } else { 2042 } else {
2039 newObject = 2043 newObject =
2040 callSetRuntimeTypeInfo(classElement, typeArguments, newObject); 2044 callSetRuntimeTypeInfo(classElement, typeArguments, newObject);
2041 } 2045 }
2042 } 2046 }
2043 2047
2044 // Generate calls to the constructor bodies. 2048 // Generate calls to the constructor bodies.
2045 HInstruction interceptor = null; 2049 HInstruction interceptor = null;
2046 for (int index = constructors.length - 1; index >= 0; index--) { 2050 for (int index = constructors.length - 1; index >= 0; index--) {
(...skipping 2095 matching lines...) Expand 10 before | Expand all | Expand 10 after
4142 } 4146 }
4143 } else if (isGrowableListConstructorCall) { 4147 } else if (isGrowableListConstructorCall) {
4144 push(buildLiteralList(<HInstruction>[])); 4148 push(buildLiteralList(<HInstruction>[]));
4145 stack.last.instructionType = elementType; 4149 stack.last.instructionType = elementType;
4146 } else { 4150 } else {
4147 ClassElement cls = constructor.enclosingClass; 4151 ClassElement cls = constructor.enclosingClass;
4148 if (cls.isAbstract && constructor.isGenerativeConstructor) { 4152 if (cls.isAbstract && constructor.isGenerativeConstructor) {
4149 generateAbstractClassInstantiationError(send, cls.name); 4153 generateAbstractClassInstantiationError(send, cls.name);
4150 return; 4154 return;
4151 } 4155 }
4152 if (backend.classNeedsRti(cls)) { 4156 potentiallyAddTypeArguments(inputs, cls, expectedType);
4153 Link<DartType> typeVariable = cls.typeVariables;
4154 expectedType.typeArguments.forEach((DartType argument) {
4155 inputs.add(analyzeTypeArgument(argument));
4156 typeVariable = typeVariable.tail;
4157 });
4158 assert(typeVariable.isEmpty);
4159 }
4160 4157
4161 addInlinedInstantiation(expectedType); 4158 addInlinedInstantiation(expectedType);
4162 pushInvokeStatic(node, constructor, inputs, elementType); 4159 pushInvokeStatic(node, constructor, inputs, elementType);
4163 removeInlinedInstantiation(expectedType); 4160 removeInlinedInstantiation(expectedType);
4164 } 4161 }
4165 HInstruction newInstance = stack.last; 4162 HInstruction newInstance = stack.last;
4166 if (isFixedList) { 4163 if (isFixedList) {
4167 // Overwrite the element type, in case the allocation site has 4164 // Overwrite the element type, in case the allocation site has
4168 // been inlined. 4165 // been inlined.
4169 newInstance.instructionType = elementType; 4166 newInstance.instructionType = elementType;
(...skipping 15 matching lines...) Expand all
4185 // Finally, if we called a redirecting factory constructor, check the type. 4182 // Finally, if we called a redirecting factory constructor, check the type.
4186 if (isRedirected) { 4183 if (isRedirected) {
4187 HInstruction checked = potentiallyCheckType(newInstance, type); 4184 HInstruction checked = potentiallyCheckType(newInstance, type);
4188 if (checked != newInstance) { 4185 if (checked != newInstance) {
4189 pop(); 4186 pop();
4190 stack.add(checked); 4187 stack.add(checked);
4191 } 4188 }
4192 } 4189 }
4193 } 4190 }
4194 4191
4192 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls,
4193 InterfaceType expectedType) {
4194 if (!backend.classNeedsRti(cls)) return;
4195 assert(expectedType.typeArguments.isEmpty ||
4196 cls.typeVariables.length == expectedType.typeArguments.length);
4197 expectedType.typeArguments.forEach((DartType argument) {
4198 inputs.add(analyzeTypeArgument(argument));
4199 });
4200 }
4201
4195 /// In checked mode checks the [type] of [node] to be well-bounded. The method 4202 /// In checked mode checks the [type] of [node] to be well-bounded. The method
4196 /// returns [:true:] if an error can be statically determined. 4203 /// returns [:true:] if an error can be statically determined.
4197 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { 4204 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) {
4198 if (!compiler.enableTypeAssertions) return false; 4205 if (!compiler.enableTypeAssertions) return false;
4199 4206
4200 Map<DartType, Set<DartType>> seenChecksMap = 4207 Map<DartType, Set<DartType>> seenChecksMap =
4201 new Map<DartType, Set<DartType>>(); 4208 new Map<DartType, Set<DartType>>();
4202 bool definitelyFails = false; 4209 bool definitelyFails = false;
4203 4210
4204 addTypeVariableBoundCheck(GenericType instance, 4211 addTypeVariableBoundCheck(GenericType instance,
(...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after
4881 targetSignature.orderedOptionalParameters; 4888 targetSignature.orderedOptionalParameters;
4882 List<Element> redirectingOptionals = 4889 List<Element> redirectingOptionals =
4883 redirectingSignature.orderedOptionalParameters; 4890 redirectingSignature.orderedOptionalParameters;
4884 int i = 0; 4891 int i = 0;
4885 for (; i < redirectingOptionals.length; i++) { 4892 for (; i < redirectingOptionals.length; i++) {
4886 inputs.add(localsHandler.readLocal(redirectingOptionals[i])); 4893 inputs.add(localsHandler.readLocal(redirectingOptionals[i]));
4887 } 4894 }
4888 for (; i < targetOptionals.length; i++) { 4895 for (; i < targetOptionals.length; i++) {
4889 inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); 4896 inputs.add(handleConstantForOptionalParameter(targetOptionals[i]));
4890 } 4897 }
4891
4892 ClassElement targetClass = targetConstructor.enclosingClass; 4898 ClassElement targetClass = targetConstructor.enclosingClass;
4893 if (backend.classNeedsRti(targetClass)) { 4899 if (backend.classNeedsRti(targetClass)) {
4894 ClassElement cls = redirectingConstructor.enclosingClass; 4900 ClassElement cls = redirectingConstructor.enclosingClass;
4895 InterfaceType targetType = 4901 InterfaceType targetType =
4896 redirectingConstructor.computeEffectiveTargetType(cls.thisType); 4902 redirectingConstructor.computeEffectiveTargetType(cls.thisType);
4897 targetType = localsHandler.substInContext(targetType); 4903 targetType = localsHandler.substInContext(targetType);
4898 targetType.typeArguments.forEach((DartType argument) { 4904 targetType.typeArguments.forEach((DartType argument) {
4899 inputs.add(analyzeTypeArgument(argument)); 4905 inputs.add(analyzeTypeArgument(argument));
4900 }); 4906 });
4901 } 4907 }
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
5195 functionElement.computeEffectiveTargetType(type); 5201 functionElement.computeEffectiveTargetType(type);
5196 expectedType = localsHandler.substInContext(expectedType); 5202 expectedType = localsHandler.substInContext(expectedType);
5197 5203
5198 if (constructor.isFactoryConstructor) { 5204 if (constructor.isFactoryConstructor) {
5199 registry.registerFactoryWithTypeArguments(); 5205 registry.registerFactoryWithTypeArguments();
5200 } 5206 }
5201 5207
5202 ClassElement cls = constructor.enclosingClass; 5208 ClassElement cls = constructor.enclosingClass;
5203 5209
5204 if (backend.classNeedsRti(cls)) { 5210 if (backend.classNeedsRti(cls)) {
5205 Link<DartType> typeVariable = cls.typeVariables; 5211 List<DartType> typeVariable = cls.typeVariables;
5206 expectedType.typeArguments.forEach((DartType argument) { 5212 expectedType.typeArguments.forEach((DartType argument) {
5207 inputs.add(analyzeTypeArgument(argument)); 5213 inputs.add(analyzeTypeArgument(argument));
5208 typeVariable = typeVariable.tail;
5209 }); 5214 });
5210 assert(typeVariable.isEmpty); 5215 assert(typeVariable.isEmpty);
5211 } 5216 }
5212 5217
5213 // The instruction type will always be a subtype of the mapLiteralClass, but 5218 // The instruction type will always be a subtype of the mapLiteralClass, but
5214 // type inference might discover a more specific type, or find nothing (in 5219 // type inference might discover a more specific type, or find nothing (in
5215 // dart2js unit tests). 5220 // dart2js unit tests).
5216 TypeMask mapType = new TypeMask.nonNullSubtype(backend.mapLiteralClass); 5221 TypeMask mapType = new TypeMask.nonNullSubtype(backend.mapLiteralClass);
5217 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( 5222 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement(
5218 constructor, compiler); 5223 constructor, compiler);
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after
6333 for (DartType parameter in type.parameterTypes) { 6338 for (DartType parameter in type.parameterTypes) {
6334 parameter.accept(this, builder); 6339 parameter.accept(this, builder);
6335 inputs.add(builder.pop()); 6340 inputs.add(builder.pop());
6336 } 6341 }
6337 6342
6338 for (DartType parameter in type.optionalParameterTypes) { 6343 for (DartType parameter in type.optionalParameterTypes) {
6339 parameter.accept(this, builder); 6344 parameter.accept(this, builder);
6340 inputs.add(builder.pop()); 6345 inputs.add(builder.pop());
6341 } 6346 }
6342 6347
6343 Link<DartType> namedParameterTypes = type.namedParameterTypes; 6348 List<DartType> namedParameterTypes = type.namedParameterTypes;
6344 for (String name in type.namedParameters) { 6349 List<String> names = type.namedParameters;
6345 ast.DartString dartString = new ast.DartString.literal(name); 6350 for (int index = 0; index < names.length; index++) {
6351 ast.DartString dartString = new ast.DartString.literal(names[index]);
6346 inputs.add( 6352 inputs.add(
6347 builder.graph.addConstantString(dartString, builder.compiler)); 6353 builder.graph.addConstantString(dartString, builder.compiler));
6348 namedParameterTypes.head.accept(this, builder); 6354 namedParameterTypes[index].accept(this, builder);
6349 inputs.add(builder.pop()); 6355 inputs.add(builder.pop());
6350 namedParameterTypes = namedParameterTypes.tail;
6351 } 6356 }
6352 6357
6353 ClassElement cls = builder.backend.findHelper('RuntimeFunctionType'); 6358 ClassElement cls = builder.backend.findHelper('RuntimeFunctionType');
6354 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls))); 6359 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls)));
6355 } 6360 }
6356 6361
6357 void visitMalformedType(MalformedType type, SsaBuilder builder) { 6362 void visitMalformedType(MalformedType type, SsaBuilder builder) {
6358 visitDynamicType(const DynamicType(), builder); 6363 visitDynamicType(const DynamicType(), builder);
6359 } 6364 }
6360 6365
(...skipping 25 matching lines...) Expand all
6386 if (unaliased is TypedefType) throw 'unable to unalias $type'; 6391 if (unaliased is TypedefType) throw 'unable to unalias $type';
6387 unaliased.accept(this, builder); 6392 unaliased.accept(this, builder);
6388 } 6393 }
6389 6394
6390 void visitDynamicType(DynamicType type, SsaBuilder builder) { 6395 void visitDynamicType(DynamicType type, SsaBuilder builder) {
6391 JavaScriptBackend backend = builder.compiler.backend; 6396 JavaScriptBackend backend = builder.compiler.backend;
6392 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 6397 ClassElement cls = backend.findHelper('DynamicRuntimeType');
6393 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); 6398 builder.push(new HDynamicType(type, new TypeMask.exact(cls)));
6394 } 6399 }
6395 } 6400 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698