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

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

Issue 267153002: Support general handling of type variables by substituting types into the current context. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698