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

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: Rebase and some algorithmic bugs fixed. 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 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 1628 matching lines...) Expand 10 before | Expand all | Expand 10 after
1639 ClassElement enclosingClass = callee.getEnclosingClass(); 1639 ClassElement enclosingClass = callee.getEnclosingClass();
1640 if (backend.classNeedsRti(enclosingClass)) { 1640 if (backend.classNeedsRti(enclosingClass)) {
1641 // If [enclosingClass] needs RTI, we have to give a value to its 1641 // If [enclosingClass] needs RTI, we have to give a value to its
1642 // type parameters. 1642 // type parameters.
1643 ClassElement currentClass = caller.getEnclosingClass(); 1643 ClassElement currentClass = caller.getEnclosingClass();
1644 // For a super constructor call, the type is the supertype of 1644 // For a super constructor call, the type is the supertype of
1645 // [currentClass]. For a redirecting constructor, the type is 1645 // [currentClass]. For a redirecting constructor, the type is
1646 // the current type. [InterfaceType.asInstanceOf] takes care 1646 // the current type. [InterfaceType.asInstanceOf] takes care
1647 // of both. 1647 // of both.
1648 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); 1648 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass);
1649 Link<DartType> typeVariables = enclosingClass.typeVariables; 1649 List<DartType> arguments = type.typeArguments;
1650 type.typeArguments.forEach((DartType argument) { 1650 List<DartType> typeVariables = enclosingClass.typeVariables;
1651 localsHandler.updateLocal( 1651 if (!type.isRaw) {
1652 typeVariables.head.element, 1652 assert(arguments.length == typeVariables.length);
1653 analyzeTypeArgument(argument)); 1653 Iterator<DartType> variables = typeVariables.iterator;
1654 typeVariables = typeVariables.tail; 1654 type.typeArguments.forEach((DartType argument) {
1655 }); 1655 variables.moveNext();
1656 // If the supertype is a raw type, we need to set to null the 1656 localsHandler.updateLocal(
1657 // type variables. 1657 variables.current.element,
1658 assert(typeVariables.isEmpty 1658 analyzeTypeArgument(argument));
1659 || enclosingClass.typeVariables == typeVariables); 1659 });
1660 while (!typeVariables.isEmpty) { 1660 } else {
1661 localsHandler.updateLocal(typeVariables.head.element, 1661 // If the supertype is a raw type, we need to set to null the
1662 graph.addConstantNull(compiler)); 1662 // type variables.
1663 typeVariables = typeVariables.tail; 1663 for (DartType variable in typeVariables) {
1664 localsHandler.updateLocal(variable.element,
1665 graph.addConstantNull(compiler));
1666 }
1664 } 1667 }
1665 } 1668 }
1666 1669
1667 // For redirecting constructors, the fields have already been 1670 // For redirecting constructors, the fields have already been
1668 // initialized by the caller. 1671 // initialized by the caller.
1669 if (callee.getEnclosingClass() != caller.getEnclosingClass()) { 1672 if (callee.getEnclosingClass() != caller.getEnclosingClass()) {
1670 inlinedFrom(callee, () { 1673 inlinedFrom(callee, () {
1671 buildFieldInitializers(callee.enclosingElement.implementation, 1674 buildFieldInitializers(callee.enclosingElement.implementation,
1672 fieldValues); 1675 fieldValues);
1673 }); 1676 });
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
1960 // would be of the form: 1963 // would be of the form:
1961 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] 1964 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)]
1962 // and k is the number of type arguments of this. If this is the case, 1965 // and k is the number of type arguments of this. If this is the case,
1963 // we can simply copy the list from this. 1966 // we can simply copy the list from this.
1964 1967
1965 // These locals are modified by [isIndexedTypeArgumentGet]. 1968 // These locals are modified by [isIndexedTypeArgumentGet].
1966 HInstruction source; // The source of the type arguments. 1969 HInstruction source; // The source of the type arguments.
1967 bool allIndexed = true; 1970 bool allIndexed = true;
1968 int expectedIndex = 0; 1971 int expectedIndex = 0;
1969 ClassElement contextClass; // The class of `this`. 1972 ClassElement contextClass; // The class of `this`.
1970 Link typeVariables; // The list of 'remaining type variables' of `this`. 1973 int remainingTypeVariables; // The number of 'remaining type variables'
1974 // of `this`.
1971 1975
1972 /// Helper to identify instructions that read a type variable without 1976 /// Helper to identify instructions that read a type variable without
1973 /// substitution (that is, directly use the index). These instructions 1977 /// substitution (that is, directly use the index). These instructions
1974 /// are of the form: 1978 /// are of the form:
1975 /// HInvokeStatic(getTypeArgumentByIndex, this, index) 1979 /// HInvokeStatic(getTypeArgumentByIndex, this, index)
1976 /// 1980 ///
1977 /// Return `true` if [instruction] is of that form and the index is the 1981 /// Return `true` if [instruction] is of that form and the index is the
1978 /// next index in the sequence (held in [expectedIndex]). 1982 /// next index in the sequence (held in [expectedIndex]).
1979 bool isIndexedTypeArgumentGet(HInstruction instruction) { 1983 bool isIndexedTypeArgumentGet(HInstruction instruction) {
1980 if (instruction is! HInvokeStatic) return false; 1984 if (instruction is! HInvokeStatic) return false;
1981 HInvokeStatic invoke = instruction; 1985 HInvokeStatic invoke = instruction;
1982 if (invoke.element != backend.getGetTypeArgumentByIndex()) { 1986 if (invoke.element != backend.getGetTypeArgumentByIndex()) {
1983 return false; 1987 return false;
1984 } 1988 }
1985 HConstant index = invoke.inputs[1]; 1989 HConstant index = invoke.inputs[1];
1986 HInstruction newSource = invoke.inputs[0]; 1990 HInstruction newSource = invoke.inputs[0];
1987 if (newSource is! HThis) { 1991 if (newSource is! HThis) {
1988 return false; 1992 return false;
1989 } 1993 }
1990 if (source == null) { 1994 if (source == null) {
1991 // This is the first match. Extract the context class for the type 1995 // This is the first match. Extract the context class for the type
1992 // variables and get the list of type variables to keep track of how 1996 // variables and get the list of type variables to keep track of how
1993 // many arguments we need to process. 1997 // many arguments we need to process.
1994 source = newSource; 1998 source = newSource;
1995 contextClass = source.sourceElement.getEnclosingClass(); 1999 contextClass = source.sourceElement.getEnclosingClass();
1996 typeVariables = contextClass.typeVariables; 2000 remainingTypeVariables = contextClass.typeVariables.length;
1997 } else { 2001 } else {
1998 assert(source == newSource); 2002 assert(source == newSource);
1999 } 2003 }
2000 // If there are no more type variables, then there are more type 2004 // If there are no more type variables, then there are more type
2001 // arguments for the new object than the source has, and it can't be 2005 // arguments for the new object than the source has, and it can't be
2002 // a copy. Otherwise remove one argument. 2006 // a copy. Otherwise remove one argument.
2003 if (typeVariables.isEmpty) return false; 2007 if (remainingTypeVariables == 0) return false;
2004 typeVariables = typeVariables.tail; 2008 remainingTypeVariables--;
2005 // Check that the index is the one we expect. 2009 // Check that the index is the one we expect.
2006 IntConstant constant = index.constant; 2010 IntConstant constant = index.constant;
2007 return constant.value == expectedIndex++; 2011 return constant.value == expectedIndex++;
2008 } 2012 }
2009 2013
2010 List<HInstruction> typeArguments = <HInstruction>[]; 2014 List<HInstruction> typeArguments = <HInstruction>[];
2011 classElement.typeVariables.forEach((TypeVariableType typeVariable) { 2015 classElement.typeVariables.forEach((TypeVariableType typeVariable) {
2012 HInstruction argument = localsHandler.readLocal(typeVariable.element); 2016 HInstruction argument = localsHandler.readLocal(typeVariable.element);
2013 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { 2017 if (allIndexed && !isIndexedTypeArgumentGet(argument)) {
2014 allIndexed = false; 2018 allIndexed = false;
2015 } 2019 }
2016 typeArguments.add(argument); 2020 typeArguments.add(argument);
2017 }); 2021 });
2018 2022
2019 if (source != null && allIndexed && typeVariables.isEmpty) { 2023 if (source != null && allIndexed && remainingTypeVariables == 0) {
2020 copyRuntimeTypeInfo(source, newObject); 2024 copyRuntimeTypeInfo(source, newObject);
2021 } else { 2025 } else {
2022 newObject = 2026 newObject =
2023 callSetRuntimeTypeInfo(classElement, typeArguments, newObject); 2027 callSetRuntimeTypeInfo(classElement, typeArguments, newObject);
2024 } 2028 }
2025 } 2029 }
2026 2030
2027 // Generate calls to the constructor bodies. 2031 // Generate calls to the constructor bodies.
2028 HInstruction interceptor = null; 2032 HInstruction interceptor = null;
2029 for (int index = constructors.length - 1; index >= 0; index--) { 2033 for (int index = constructors.length - 1; index >= 0; index--) {
(...skipping 1930 matching lines...) Expand 10 before | Expand all | Expand 10 after
3960 } 3964 }
3961 } else if (isGrowableListConstructorCall) { 3965 } else if (isGrowableListConstructorCall) {
3962 push(buildLiteralList(<HInstruction>[])); 3966 push(buildLiteralList(<HInstruction>[]));
3963 stack.last.instructionType = elementType; 3967 stack.last.instructionType = elementType;
3964 } else { 3968 } else {
3965 ClassElement cls = constructor.getEnclosingClass(); 3969 ClassElement cls = constructor.getEnclosingClass();
3966 if (cls.isAbstract && constructor.isGenerativeConstructor()) { 3970 if (cls.isAbstract && constructor.isGenerativeConstructor()) {
3967 generateAbstractClassInstantiationError(send, cls.name); 3971 generateAbstractClassInstantiationError(send, cls.name);
3968 return; 3972 return;
3969 } 3973 }
3970 if (backend.classNeedsRti(cls)) { 3974 potentiallyAddTypeArguments(inputs, cls, expectedType);
3971 Link<DartType> typeVariable = cls.typeVariables;
3972 expectedType.typeArguments.forEach((DartType argument) {
3973 inputs.add(analyzeTypeArgument(argument));
3974 typeVariable = typeVariable.tail;
3975 });
3976 assert(typeVariable.isEmpty);
3977 }
3978 3975
3979 addInlinedInstantiation(expectedType); 3976 addInlinedInstantiation(expectedType);
3980 pushInvokeStatic(node, constructor, inputs, elementType); 3977 pushInvokeStatic(node, constructor, inputs, elementType);
3981 removeInlinedInstantiation(expectedType); 3978 removeInlinedInstantiation(expectedType);
3982 } 3979 }
3983 HInstruction newInstance = stack.last; 3980 HInstruction newInstance = stack.last;
3984 if (isFixedList) { 3981 if (isFixedList) {
3985 // Overwrite the element type, in case the allocation site has 3982 // Overwrite the element type, in case the allocation site has
3986 // been inlined. 3983 // been inlined.
3987 newInstance.instructionType = elementType; 3984 newInstance.instructionType = elementType;
(...skipping 15 matching lines...) Expand all
4003 // Finally, if we called a redirecting factory constructor, check the type. 4000 // Finally, if we called a redirecting factory constructor, check the type.
4004 if (isRedirected) { 4001 if (isRedirected) {
4005 HInstruction checked = potentiallyCheckType(newInstance, type); 4002 HInstruction checked = potentiallyCheckType(newInstance, type);
4006 if (checked != newInstance) { 4003 if (checked != newInstance) {
4007 pop(); 4004 pop();
4008 stack.add(checked); 4005 stack.add(checked);
4009 } 4006 }
4010 } 4007 }
4011 } 4008 }
4012 4009
4010 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls,
4011 InterfaceType expectedType) {
4012 if (!backend.classNeedsRti(cls)) return;
4013 assert(expectedType.typeArguments.isEmpty ||
4014 cls.typeVariables.length == expectedType.typeArguments.length);
4015 expectedType.typeArguments.forEach((DartType argument) {
4016 inputs.add(analyzeTypeArgument(argument));
4017 });
4018 }
4019
4013 /// In checked mode checks the [type] of [node] to be well-bounded. The method 4020 /// In checked mode checks the [type] of [node] to be well-bounded. The method
4014 /// returns [:true:] if an error can be statically determined. 4021 /// returns [:true:] if an error can be statically determined.
4015 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { 4022 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) {
4016 if (!compiler.enableTypeAssertions) return false; 4023 if (!compiler.enableTypeAssertions) return false;
4017 4024
4018 Map<DartType, Set<DartType>> seenChecksMap = 4025 Map<DartType, Set<DartType>> seenChecksMap =
4019 new Map<DartType, Set<DartType>>(); 4026 new Map<DartType, Set<DartType>>();
4020 bool definitelyFails = false; 4027 bool definitelyFails = false;
4021 4028
4022 addTypeVariableBoundCheck(GenericType instance, 4029 addTypeVariableBoundCheck(GenericType instance,
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
4685 calleeSignature.orderedOptionalParameters; 4692 calleeSignature.orderedOptionalParameters;
4686 List<Element> callerOptionals = 4693 List<Element> callerOptionals =
4687 callerSignature.orderedOptionalParameters; 4694 callerSignature.orderedOptionalParameters;
4688 int i = 0; 4695 int i = 0;
4689 for (; i < callerOptionals.length; i++) { 4696 for (; i < callerOptionals.length; i++) {
4690 inputs.add(localsHandler.readLocal(callerOptionals[i])); 4697 inputs.add(localsHandler.readLocal(callerOptionals[i]));
4691 } 4698 }
4692 for (; i < calleeOptionals.length; i++) { 4699 for (; i < calleeOptionals.length; i++) {
4693 inputs.add(handleConstantForOptionalParameter(calleeOptionals[i])); 4700 inputs.add(handleConstantForOptionalParameter(calleeOptionals[i]));
4694 } 4701 }
4695 4702 potentiallyAddTypeArguments(inputs, element.getEnclosingClass(),
4696 if (backend.classNeedsRti(element.getEnclosingClass())) { 4703 elements.getType(node.expression));
4697 ClassElement cls = function.getEnclosingClass();
4698 Link<DartType> typeVariable = cls.typeVariables;
4699 InterfaceType type = elements.getType(node.expression);
4700 type.typeArguments.forEach((DartType argument) {
4701 inputs.add(analyzeTypeArgument(argument));
4702 typeVariable = typeVariable.tail;
4703 });
4704 assert(typeVariable.isEmpty);
4705 }
4706 pushInvokeStatic(node, element, inputs); 4704 pushInvokeStatic(node, element, inputs);
4707 value = pop(); 4705 value = pop();
4708 } else if (node.expression == null) { 4706 } else if (node.expression == null) {
4709 value = graph.addConstantNull(compiler); 4707 value = graph.addConstantNull(compiler);
4710 } else { 4708 } else {
4711 visit(node.expression); 4709 visit(node.expression);
4712 value = pop(); 4710 value = pop();
4713 value = potentiallyCheckType(value, returnType); 4711 value = potentiallyCheckType(value, returnType);
4714 } 4712 }
4715 4713
(...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after
6062 for (DartType parameter in type.parameterTypes) { 6060 for (DartType parameter in type.parameterTypes) {
6063 parameter.accept(this, builder); 6061 parameter.accept(this, builder);
6064 inputs.add(builder.pop()); 6062 inputs.add(builder.pop());
6065 } 6063 }
6066 6064
6067 for (DartType parameter in type.optionalParameterTypes) { 6065 for (DartType parameter in type.optionalParameterTypes) {
6068 parameter.accept(this, builder); 6066 parameter.accept(this, builder);
6069 inputs.add(builder.pop()); 6067 inputs.add(builder.pop());
6070 } 6068 }
6071 6069
6072 Link<DartType> namedParameterTypes = type.namedParameterTypes; 6070 List<DartType> namedParameterTypes = type.namedParameterTypes;
6073 for (String name in type.namedParameters) { 6071 List<String> names = type.namedParameters;
6074 ast.DartString dartString = new ast.DartString.literal(name); 6072 for (int index = 0; index < names.length; index++) {
6073 ast.DartString dartString = new ast.DartString.literal(names[index]);
6075 inputs.add( 6074 inputs.add(
6076 builder.graph.addConstantString(dartString, builder.compiler)); 6075 builder.graph.addConstantString(dartString, builder.compiler));
6077 namedParameterTypes.head.accept(this, builder); 6076 namedParameterTypes[index].accept(this, builder);
6078 inputs.add(builder.pop()); 6077 inputs.add(builder.pop());
6079 namedParameterTypes = namedParameterTypes.tail;
6080 } 6078 }
6081 6079
6082 ClassElement cls = builder.compiler.findHelper('RuntimeFunctionType'); 6080 ClassElement cls = builder.compiler.findHelper('RuntimeFunctionType');
6083 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls))); 6081 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls)));
6084 } 6082 }
6085 6083
6086 void visitMalformedType(MalformedType type, SsaBuilder builder) { 6084 void visitMalformedType(MalformedType type, SsaBuilder builder) {
6087 visitDynamicType(builder.compiler.types.dynamicType, builder); 6085 visitDynamicType(builder.compiler.types.dynamicType, builder);
6088 } 6086 }
6089 6087
(...skipping 24 matching lines...) Expand all
6114 DartType unaliased = type.unalias(builder.compiler); 6112 DartType unaliased = type.unalias(builder.compiler);
6115 if (unaliased is TypedefType) throw 'unable to unalias $type'; 6113 if (unaliased is TypedefType) throw 'unable to unalias $type';
6116 unaliased.accept(this, builder); 6114 unaliased.accept(this, builder);
6117 } 6115 }
6118 6116
6119 void visitDynamicType(DynamicType type, SsaBuilder builder) { 6117 void visitDynamicType(DynamicType type, SsaBuilder builder) {
6120 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); 6118 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType');
6121 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); 6119 builder.push(new HDynamicType(type, new TypeMask.exact(cls)));
6122 } 6120 }
6123 } 6121 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698