| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 2060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2071 HInstruction representations = buildTypeArgumentRepresentations(type); | 2071 HInstruction representations = buildTypeArgumentRepresentations(type); |
| 2072 add(representations); | 2072 add(representations); |
| 2073 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 2073 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
| 2074 original, representations); | 2074 original, representations); |
| 2075 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 2075 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 2076 TypeMask subtype = original.instructionType; | 2076 TypeMask subtype = original.instructionType; |
| 2077 HInstruction typeVariable = addTypeVariableReference(type); | 2077 HInstruction typeVariable = addTypeVariableReference(type); |
| 2078 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 2078 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
| 2079 original, typeVariable); | 2079 original, typeVariable); |
| 2080 } else if (type.kind == TypeKind.FUNCTION) { | 2080 } else if (type.kind == TypeKind.FUNCTION) { |
| 2081 if (backend.rti.isSimpleFunctionType(type)) { | 2081 String name = kind == HTypeConversion.CAST_TYPE_CHECK |
| 2082 return original.convertType(compiler, type, kind); | 2082 ? '_asCheck' : '_assertCheck'; |
| 2083 } | 2083 |
| 2084 TypeMask subtype = original.instructionType; | 2084 List arguments = [buildFunctionType(type), original]; |
| 2085 if (type.containsTypeVariables) { | 2085 pushInvokeDynamic( |
| 2086 bool contextIsTypeArguments = false; | 2086 null, |
| 2087 HInstruction context; | 2087 new Selector.call(name, compiler.jsHelperLibrary, 1), |
| 2088 if (!currentElement.enclosingElement.isClosure() | 2088 arguments); |
| 2089 && currentElement.isInstanceMember()) { | 2089 |
| 2090 context = localsHandler.readThis(); | 2090 return new HTypeConversion(type, kind, original.instructionType, pop()); |
| 2091 } else { | |
| 2092 ClassElement contextClass = Types.getClassContext(type); | |
| 2093 context = buildTypeVariableList(contextClass); | |
| 2094 add(context); | |
| 2095 contextIsTypeArguments = true; | |
| 2096 } | |
| 2097 return new HTypeConversion.withContext(type, kind, subtype, | |
| 2098 original, context, contextIsTypeArguments: contextIsTypeArguments); | |
| 2099 } else { | |
| 2100 return new HTypeConversion(type, kind, subtype, original); | |
| 2101 } | |
| 2102 } else { | 2091 } else { |
| 2103 return original.convertType(compiler, type, kind); | 2092 return original.convertType(compiler, type, kind); |
| 2104 } | 2093 } |
| 2105 } | 2094 } |
| 2106 | 2095 |
| 2107 HInstruction potentiallyCheckType(HInstruction original, DartType type, | 2096 HInstruction potentiallyCheckType(HInstruction original, DartType type, |
| 2108 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { | 2097 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
| 2109 if (!compiler.enableTypeAssertions) return original; | 2098 if (!compiler.enableTypeAssertions) return original; |
| 2110 HInstruction other = buildTypeConversion(original, type, kind); | 2099 HInstruction other = buildTypeConversion(original, type, kind); |
| 2111 if (other != original) add(other); | 2100 if (other != original) add(other); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 value, | 2154 value, |
| 2166 compiler.boolClass.computeType(compiler), | 2155 compiler.boolClass.computeType(compiler), |
| 2167 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 2156 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
| 2168 } | 2157 } |
| 2169 HInstruction result = new HBoolify(value, backend.boolType); | 2158 HInstruction result = new HBoolify(value, backend.boolType); |
| 2170 add(result); | 2159 add(result); |
| 2171 return result; | 2160 return result; |
| 2172 } | 2161 } |
| 2173 | 2162 |
| 2174 HInstruction attachPosition(HInstruction target, Node node) { | 2163 HInstruction attachPosition(HInstruction target, Node node) { |
| 2175 target.sourcePosition = sourceFileLocationForBeginToken(node); | 2164 if (node != null) { |
| 2165 target.sourcePosition = sourceFileLocationForBeginToken(node); |
| 2166 } |
| 2176 return target; | 2167 return target; |
| 2177 } | 2168 } |
| 2178 | 2169 |
| 2179 SourceFileLocation sourceFileLocationForBeginToken(Node node) => | 2170 SourceFileLocation sourceFileLocationForBeginToken(Node node) => |
| 2180 sourceFileLocationForToken(node, node.getBeginToken()); | 2171 sourceFileLocationForToken(node, node.getBeginToken()); |
| 2181 | 2172 |
| 2182 SourceFileLocation sourceFileLocationForEndToken(Node node) => | 2173 SourceFileLocation sourceFileLocationForEndToken(Node node) => |
| 2183 sourceFileLocationForToken(node, node.getEndToken()); | 2174 sourceFileLocationForToken(node, node.getEndToken()); |
| 2184 | 2175 |
| 2185 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { | 2176 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { |
| (...skipping 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3076 !link.isEmpty; | 3067 !link.isEmpty; |
| 3077 link = link.tail) { | 3068 link = link.tail) { |
| 3078 inputs.add(addTypeVariableReference(link.head)); | 3069 inputs.add(addTypeVariableReference(link.head)); |
| 3079 } | 3070 } |
| 3080 return buildLiteralList(inputs); | 3071 return buildLiteralList(inputs); |
| 3081 } | 3072 } |
| 3082 | 3073 |
| 3083 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { | 3074 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { |
| 3084 type = type.unalias(compiler); | 3075 type = type.unalias(compiler); |
| 3085 if (type.kind == TypeKind.FUNCTION) { | 3076 if (type.kind == TypeKind.FUNCTION) { |
| 3086 if (backend.rti.isSimpleFunctionType(type)) { | 3077 List arguments = [buildFunctionType(type), expression]; |
| 3087 // TODO(johnniwinther): Avoid interceptor if unneeded. | 3078 pushInvokeDynamic( |
| 3088 return new HIs.raw( | 3079 node, new Selector.call('_isTest', compiler.jsHelperLibrary, 1), |
| 3089 type, expression, invokeInterceptor(expression), backend.boolType); | 3080 arguments); |
| 3090 } | 3081 return new HIs.compound(type, expression, pop(), backend.boolType); |
| 3091 Element checkFunctionSubtype = backend.getCheckFunctionSubtype(); | |
| 3092 | |
| 3093 HInstruction signatureName = graph.addConstantString( | |
| 3094 new DartString.literal(backend.namer.getFunctionTypeName(type)), | |
| 3095 compiler); | |
| 3096 | |
| 3097 HInstruction contextName; | |
| 3098 HInstruction context; | |
| 3099 HInstruction typeArguments; | |
| 3100 if (type.containsTypeVariables) { | |
| 3101 ClassElement contextClass = Types.getClassContext(type); | |
| 3102 contextName = graph.addConstantString( | |
| 3103 new DartString.literal(backend.namer.getNameOfClass(contextClass)), | |
| 3104 compiler); | |
| 3105 if (!currentElement.enclosingElement.isClosure() | |
| 3106 && currentElement.isInstanceMember()) { | |
| 3107 context = localsHandler.readThis(); | |
| 3108 typeArguments = graph.addConstantNull(compiler); | |
| 3109 } else { | |
| 3110 context = graph.addConstantNull(compiler); | |
| 3111 typeArguments = buildTypeVariableList(contextClass); | |
| 3112 add(typeArguments); | |
| 3113 } | |
| 3114 } else { | |
| 3115 contextName = graph.addConstantNull(compiler); | |
| 3116 context = graph.addConstantNull(compiler); | |
| 3117 typeArguments = graph.addConstantNull(compiler); | |
| 3118 } | |
| 3119 | |
| 3120 List<HInstruction> inputs = <HInstruction>[expression, | |
| 3121 signatureName, | |
| 3122 contextName, | |
| 3123 context, | |
| 3124 typeArguments]; | |
| 3125 pushInvokeStatic(node, checkFunctionSubtype, inputs, backend.boolType); | |
| 3126 HInstruction call = pop(); | |
| 3127 return new HIs.compound(type, expression, call, backend.boolType); | |
| 3128 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 3082 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 3129 HInstruction runtimeType = addTypeVariableReference(type); | 3083 HInstruction runtimeType = addTypeVariableReference(type); |
| 3130 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 3084 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
| 3131 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3085 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| 3132 pushInvokeStatic(null, helper, inputs, backend.boolType); | 3086 pushInvokeStatic(null, helper, inputs, backend.boolType); |
| 3133 HInstruction call = pop(); | 3087 HInstruction call = pop(); |
| 3134 return new HIs.variable(type, expression, call, backend.boolType); | 3088 return new HIs.variable(type, expression, call, backend.boolType); |
| 3135 } else if (RuntimeTypes.hasTypeArguments(type)) { | 3089 } else if (RuntimeTypes.hasTypeArguments(type)) { |
| 3136 ClassElement element = type.element; | 3090 ClassElement element = type.element; |
| 3137 Element helper = backend.getCheckSubtype(); | 3091 Element helper = backend.getCheckSubtype(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3159 } else { | 3113 } else { |
| 3160 if (backend.hasDirectCheckFor(type)) { | 3114 if (backend.hasDirectCheckFor(type)) { |
| 3161 return new HIs.direct(type, expression, backend.boolType); | 3115 return new HIs.direct(type, expression, backend.boolType); |
| 3162 } | 3116 } |
| 3163 // TODO(johnniwinther): Avoid interceptor if unneeded. | 3117 // TODO(johnniwinther): Avoid interceptor if unneeded. |
| 3164 return new HIs.raw( | 3118 return new HIs.raw( |
| 3165 type, expression, invokeInterceptor(expression), backend.boolType); | 3119 type, expression, invokeInterceptor(expression), backend.boolType); |
| 3166 } | 3120 } |
| 3167 } | 3121 } |
| 3168 | 3122 |
| 3123 HInstruction buildFunctionType(FunctionType type) { |
| 3124 type.accept(new TypeBuilder(), this); |
| 3125 return pop(); |
| 3126 } |
| 3127 |
| 3169 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { | 3128 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { |
| 3170 Selector selector = elements.getSelector(node); | 3129 Selector selector = elements.getSelector(node); |
| 3171 if (selector.namedArgumentCount == 0) { | 3130 if (selector.namedArgumentCount == 0) { |
| 3172 addGenericSendArgumentsToList(node.arguments, list); | 3131 addGenericSendArgumentsToList(node.arguments, list); |
| 3173 } else { | 3132 } else { |
| 3174 // Visit positional arguments and add them to the list. | 3133 // Visit positional arguments and add them to the list. |
| 3175 Link<Node> arguments = node.arguments; | 3134 Link<Node> arguments = node.arguments; |
| 3176 int positionalArgumentCount = selector.positionalArgumentCount; | 3135 int positionalArgumentCount = selector.positionalArgumentCount; |
| 3177 for (int i = 0; | 3136 for (int i = 0; |
| 3178 i < positionalArgumentCount; | 3137 i < positionalArgumentCount; |
| (...skipping 2775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5954 new HSubGraphBlockInformation(elseBranch.graph)); | 5913 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5955 | 5914 |
| 5956 HBasicBlock conditionStartBlock = conditionBranch.block; | 5915 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5957 conditionStartBlock.setBlockFlow(info, joinBlock); | 5916 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5958 SubGraph conditionGraph = conditionBranch.graph; | 5917 SubGraph conditionGraph = conditionBranch.graph; |
| 5959 HIf branch = conditionGraph.end.last; | 5918 HIf branch = conditionGraph.end.last; |
| 5960 assert(branch is HIf); | 5919 assert(branch is HIf); |
| 5961 branch.blockInformation = conditionStartBlock.blockFlow; | 5920 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5962 } | 5921 } |
| 5963 } | 5922 } |
| 5923 |
| 5924 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> { |
| 5925 void visitType(DartType type, _) { |
| 5926 throw 'Internal error $type'; |
| 5927 } |
| 5928 |
| 5929 void visitVoidType(VoidType type, SsaBuilder builder) { |
| 5930 ClassElement cls = builder.compiler.findHelper('VoidRuntimeType'); |
| 5931 builder.push(new HVoidType(type, new TypeMask.exact(cls))); |
| 5932 } |
| 5933 |
| 5934 void visitTypeVariableType(TypeVariableType type, |
| 5935 SsaBuilder builder) { |
| 5936 ClassElement cls = builder.compiler.findHelper('RuntimeType'); |
| 5937 TypeMask instructionType = new TypeMask.subclass(cls); |
| 5938 if (!builder.currentElement.enclosingElement.isClosure() && |
| 5939 builder.currentElement.isInstanceMember()) { |
| 5940 HInstruction receiver = builder.localsHandler.readThis(); |
| 5941 builder.push(new HReadTypeVariable(type, receiver, instructionType)); |
| 5942 } else { |
| 5943 builder.push( |
| 5944 new HReadTypeVariable.noReceiver( |
| 5945 type, builder.addTypeVariableReference(type), instructionType)); |
| 5946 } |
| 5947 } |
| 5948 |
| 5949 void visitFunctionType(FunctionType type, SsaBuilder builder) { |
| 5950 type.returnType.accept(this, builder); |
| 5951 HInstruction returnType = builder.pop(); |
| 5952 List<HInstruction> inputs = <HInstruction>[returnType]; |
| 5953 |
| 5954 for (DartType parameter in type.parameterTypes) { |
| 5955 parameter.accept(this, builder); |
| 5956 inputs.add(builder.pop()); |
| 5957 } |
| 5958 |
| 5959 for (DartType parameter in type.optionalParameterTypes) { |
| 5960 parameter.accept(this, builder); |
| 5961 inputs.add(builder.pop()); |
| 5962 } |
| 5963 |
| 5964 Link<DartType> namedParameterTypes = type.namedParameterTypes; |
| 5965 for (String name in type.namedParameters) { |
| 5966 DartString dartString = new DartString.literal(name); |
| 5967 inputs.add( |
| 5968 builder.graph.addConstantString(dartString, builder.compiler)); |
| 5969 namedParameterTypes.head.accept(this, builder); |
| 5970 inputs.add(builder.pop()); |
| 5971 namedParameterTypes = namedParameterTypes.tail; |
| 5972 } |
| 5973 |
| 5974 ClassElement cls = builder.compiler.findHelper('RuntimeFunctionType'); |
| 5975 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls))); |
| 5976 } |
| 5977 |
| 5978 void visitMalformedType(MalformedType type, SsaBuilder builder) { |
| 5979 visitDynamicType(builder.compiler.types.dynamicType, builder); |
| 5980 } |
| 5981 |
| 5982 void visitStatementType(StatementType type, SsaBuilder builder) { |
| 5983 throw 'not implemented visitStatementType($type)'; |
| 5984 } |
| 5985 |
| 5986 void visitGenericType(GenericType type, SsaBuilder builder) { |
| 5987 throw 'not implemented visitGenericType($type)'; |
| 5988 } |
| 5989 |
| 5990 void visitInterfaceType(InterfaceType type, SsaBuilder builder) { |
| 5991 List<HInstruction> inputs = <HInstruction>[]; |
| 5992 for (DartType typeArgument in type.typeArguments) { |
| 5993 typeArgument.accept(this, builder); |
| 5994 inputs.add(builder.pop()); |
| 5995 } |
| 5996 ClassElement cls; |
| 5997 if (type.typeArguments.isEmpty) { |
| 5998 cls = builder.compiler.findHelper('RuntimeTypePlain'); |
| 5999 } else { |
| 6000 cls = builder.compiler.findHelper('RuntimeTypeGeneric'); |
| 6001 } |
| 6002 builder.push(new HInterfaceType(inputs, type, new TypeMask.exact(cls))); |
| 6003 } |
| 6004 |
| 6005 void visitTypedefType(TypedefType type, SsaBuilder builder) { |
| 6006 DartType unaliased = type.unalias(builder.compiler); |
| 6007 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6008 unaliased.accept(this, builder); |
| 6009 } |
| 6010 |
| 6011 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6012 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); |
| 6013 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 6014 } |
| 6015 } |
| OLD | NEW |