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 2055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2066 HInstruction representations = buildTypeArgumentRepresentations(type); | 2066 HInstruction representations = buildTypeArgumentRepresentations(type); |
2067 add(representations); | 2067 add(representations); |
2068 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 2068 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
2069 original, representations); | 2069 original, representations); |
2070 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 2070 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
2071 TypeMask subtype = original.instructionType; | 2071 TypeMask subtype = original.instructionType; |
2072 HInstruction typeVariable = addTypeVariableReference(type); | 2072 HInstruction typeVariable = addTypeVariableReference(type); |
2073 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, | 2073 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, |
2074 original, typeVariable); | 2074 original, typeVariable); |
2075 } else if (type.kind == TypeKind.FUNCTION) { | 2075 } else if (type.kind == TypeKind.FUNCTION) { |
2076 if (backend.rti.isSimpleFunctionType(type)) { | 2076 String name = kind == HTypeConversion.CAST_TYPE_CHECK |
2077 return original.convertType(compiler, type, kind); | 2077 ? '_asCheck' : '_assertCheck'; |
2078 } | 2078 |
2079 TypeMask subtype = original.instructionType; | 2079 List arguments = [buildFunctionType(type), original]; |
2080 if (type.containsTypeVariables) { | 2080 pushInvokeDynamic( |
2081 bool contextIsTypeArguments = false; | 2081 null, |
2082 HInstruction context; | 2082 new Selector.call(name, compiler.jsHelperLibrary, 1), |
2083 if (!currentElement.enclosingElement.isClosure() | 2083 arguments); |
2084 && currentElement.isInstanceMember()) { | 2084 |
2085 context = localsHandler.readThis(); | 2085 return new HTypeConversion(type, kind, original.instructionType, pop()); |
2086 } else { | |
2087 ClassElement contextClass = Types.getClassContext(type); | |
2088 context = buildTypeVariableList(contextClass); | |
2089 add(context); | |
2090 contextIsTypeArguments = true; | |
2091 } | |
2092 return new HTypeConversion.withContext(type, kind, subtype, | |
2093 original, context, contextIsTypeArguments: contextIsTypeArguments); | |
2094 } else { | |
2095 return new HTypeConversion(type, kind, subtype, original); | |
2096 } | |
2097 } else { | 2086 } else { |
2098 return original.convertType(compiler, type, kind); | 2087 return original.convertType(compiler, type, kind); |
2099 } | 2088 } |
2100 } | 2089 } |
2101 | 2090 |
2102 HInstruction potentiallyCheckType(HInstruction original, DartType type, | 2091 HInstruction potentiallyCheckType(HInstruction original, DartType type, |
2103 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { | 2092 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
2104 if (!compiler.enableTypeAssertions) return original; | 2093 if (!compiler.enableTypeAssertions) return original; |
2105 HInstruction other = buildTypeConversion(original, type, kind); | 2094 HInstruction other = buildTypeConversion(original, type, kind); |
2106 if (other != original) add(other); | 2095 if (other != original) add(other); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2158 value, | 2147 value, |
2159 compiler.boolClass.computeType(compiler), | 2148 compiler.boolClass.computeType(compiler), |
2160 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 2149 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
2161 } | 2150 } |
2162 HInstruction result = new HBoolify(value, backend.boolType); | 2151 HInstruction result = new HBoolify(value, backend.boolType); |
2163 add(result); | 2152 add(result); |
2164 return result; | 2153 return result; |
2165 } | 2154 } |
2166 | 2155 |
2167 HInstruction attachPosition(HInstruction target, Node node) { | 2156 HInstruction attachPosition(HInstruction target, Node node) { |
2168 target.sourcePosition = sourceFileLocationForBeginToken(node); | 2157 if (node != null) { |
| 2158 target.sourcePosition = sourceFileLocationForBeginToken(node); |
| 2159 } |
2169 return target; | 2160 return target; |
2170 } | 2161 } |
2171 | 2162 |
2172 SourceFileLocation sourceFileLocationForBeginToken(Node node) => | 2163 SourceFileLocation sourceFileLocationForBeginToken(Node node) => |
2173 sourceFileLocationForToken(node, node.getBeginToken()); | 2164 sourceFileLocationForToken(node, node.getBeginToken()); |
2174 | 2165 |
2175 SourceFileLocation sourceFileLocationForEndToken(Node node) => | 2166 SourceFileLocation sourceFileLocationForEndToken(Node node) => |
2176 sourceFileLocationForToken(node, node.getEndToken()); | 2167 sourceFileLocationForToken(node, node.getEndToken()); |
2177 | 2168 |
2178 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { | 2169 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { |
(...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3051 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | 3042 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); |
3052 type = type.unalias(compiler); | 3043 type = type.unalias(compiler); |
3053 HInstruction instruction = buildIsNode(node, type, expression); | 3044 HInstruction instruction = buildIsNode(node, type, expression); |
3054 if (isNot) { | 3045 if (isNot) { |
3055 add(instruction); | 3046 add(instruction); |
3056 instruction = new HNot(instruction, backend.boolType); | 3047 instruction = new HNot(instruction, backend.boolType); |
3057 } | 3048 } |
3058 push(instruction); | 3049 push(instruction); |
3059 } | 3050 } |
3060 | 3051 |
3061 HLiteralList buildTypeVariableList(ClassElement contextClass) { | |
3062 List<HInstruction> inputs = <HInstruction>[]; | |
3063 for (Link<DartType> link = contextClass.typeVariables; | |
3064 !link.isEmpty; | |
3065 link = link.tail) { | |
3066 inputs.add(addTypeVariableReference(link.head)); | |
3067 } | |
3068 return buildLiteralList(inputs); | |
3069 } | |
3070 | |
3071 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { | 3052 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { |
3072 type = type.unalias(compiler); | 3053 type = type.unalias(compiler); |
3073 if (type.kind == TypeKind.FUNCTION) { | 3054 if (type.kind == TypeKind.FUNCTION) { |
3074 if (backend.rti.isSimpleFunctionType(type)) { | 3055 List arguments = [buildFunctionType(type), expression]; |
3075 // TODO(johnniwinther): Avoid interceptor if unneeded. | 3056 pushInvokeDynamic( |
3076 return new HIs.raw( | 3057 node, new Selector.call('_isTest', compiler.jsHelperLibrary, 1), |
3077 type, expression, invokeInterceptor(expression), backend.boolType); | 3058 arguments); |
3078 } | 3059 return new HIs.compound(type, expression, pop(), backend.boolType); |
3079 Element checkFunctionSubtype = backend.getCheckFunctionSubtype(); | |
3080 | |
3081 HInstruction signatureName = graph.addConstantString( | |
3082 new DartString.literal(backend.namer.getFunctionTypeName(type)), | |
3083 compiler); | |
3084 | |
3085 HInstruction contextName; | |
3086 HInstruction context; | |
3087 HInstruction typeArguments; | |
3088 if (type.containsTypeVariables) { | |
3089 ClassElement contextClass = Types.getClassContext(type); | |
3090 contextName = graph.addConstantString( | |
3091 new DartString.literal(backend.namer.getNameOfClass(contextClass)), | |
3092 compiler); | |
3093 if (!currentElement.enclosingElement.isClosure() | |
3094 && currentElement.isInstanceMember()) { | |
3095 context = localsHandler.readThis(); | |
3096 typeArguments = graph.addConstantNull(compiler); | |
3097 } else { | |
3098 context = graph.addConstantNull(compiler); | |
3099 typeArguments = buildTypeVariableList(contextClass); | |
3100 add(typeArguments); | |
3101 } | |
3102 } else { | |
3103 contextName = graph.addConstantNull(compiler); | |
3104 context = graph.addConstantNull(compiler); | |
3105 typeArguments = graph.addConstantNull(compiler); | |
3106 } | |
3107 | |
3108 List<HInstruction> inputs = <HInstruction>[expression, | |
3109 signatureName, | |
3110 contextName, | |
3111 context, | |
3112 typeArguments]; | |
3113 pushInvokeStatic(node, checkFunctionSubtype, inputs, backend.boolType); | |
3114 HInstruction call = pop(); | |
3115 return new HIs.compound(type, expression, call, backend.boolType); | |
3116 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 3060 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
3117 HInstruction runtimeType = addTypeVariableReference(type); | 3061 HInstruction runtimeType = addTypeVariableReference(type); |
3118 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 3062 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
3119 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3063 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
3120 pushInvokeStatic(null, helper, inputs, backend.boolType); | 3064 pushInvokeStatic(null, helper, inputs, backend.boolType); |
3121 HInstruction call = pop(); | 3065 HInstruction call = pop(); |
3122 return new HIs.variable(type, expression, call, backend.boolType); | 3066 return new HIs.variable(type, expression, call, backend.boolType); |
3123 } else if (RuntimeTypes.hasTypeArguments(type)) { | 3067 } else if (RuntimeTypes.hasTypeArguments(type)) { |
3124 ClassElement element = type.element; | 3068 ClassElement element = type.element; |
3125 Element helper = backend.getCheckSubtype(); | 3069 Element helper = backend.getCheckSubtype(); |
(...skipping 21 matching lines...) Expand all Loading... |
3147 } else { | 3091 } else { |
3148 if (backend.hasDirectCheckFor(type)) { | 3092 if (backend.hasDirectCheckFor(type)) { |
3149 return new HIs.direct(type, expression, backend.boolType); | 3093 return new HIs.direct(type, expression, backend.boolType); |
3150 } | 3094 } |
3151 // TODO(johnniwinther): Avoid interceptor if unneeded. | 3095 // TODO(johnniwinther): Avoid interceptor if unneeded. |
3152 return new HIs.raw( | 3096 return new HIs.raw( |
3153 type, expression, invokeInterceptor(expression), backend.boolType); | 3097 type, expression, invokeInterceptor(expression), backend.boolType); |
3154 } | 3098 } |
3155 } | 3099 } |
3156 | 3100 |
| 3101 HInstruction buildFunctionType(FunctionType type) { |
| 3102 type.accept(new TypeBuilder(), this); |
| 3103 return pop(); |
| 3104 } |
| 3105 |
3157 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { | 3106 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { |
3158 Selector selector = elements.getSelector(node); | 3107 Selector selector = elements.getSelector(node); |
3159 if (selector.namedArgumentCount == 0) { | 3108 if (selector.namedArgumentCount == 0) { |
3160 addGenericSendArgumentsToList(node.arguments, list); | 3109 addGenericSendArgumentsToList(node.arguments, list); |
3161 } else { | 3110 } else { |
3162 // Visit positional arguments and add them to the list. | 3111 // Visit positional arguments and add them to the list. |
3163 Link<Node> arguments = node.arguments; | 3112 Link<Node> arguments = node.arguments; |
3164 int positionalArgumentCount = selector.positionalArgumentCount; | 3113 int positionalArgumentCount = selector.positionalArgumentCount; |
3165 for (int i = 0; | 3114 for (int i = 0; |
3166 i < positionalArgumentCount; | 3115 i < positionalArgumentCount; |
(...skipping 2780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5947 new HSubGraphBlockInformation(elseBranch.graph)); | 5896 new HSubGraphBlockInformation(elseBranch.graph)); |
5948 | 5897 |
5949 HBasicBlock conditionStartBlock = conditionBranch.block; | 5898 HBasicBlock conditionStartBlock = conditionBranch.block; |
5950 conditionStartBlock.setBlockFlow(info, joinBlock); | 5899 conditionStartBlock.setBlockFlow(info, joinBlock); |
5951 SubGraph conditionGraph = conditionBranch.graph; | 5900 SubGraph conditionGraph = conditionBranch.graph; |
5952 HIf branch = conditionGraph.end.last; | 5901 HIf branch = conditionGraph.end.last; |
5953 assert(branch is HIf); | 5902 assert(branch is HIf); |
5954 branch.blockInformation = conditionStartBlock.blockFlow; | 5903 branch.blockInformation = conditionStartBlock.blockFlow; |
5955 } | 5904 } |
5956 } | 5905 } |
| 5906 |
| 5907 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> { |
| 5908 void visitType(DartType type, _) { |
| 5909 throw 'Internal error $type'; |
| 5910 } |
| 5911 |
| 5912 void visitVoidType(VoidType type, SsaBuilder builder) { |
| 5913 ClassElement cls = builder.compiler.findHelper('VoidRuntimeType'); |
| 5914 builder.push(new HVoidType(type, new TypeMask.exact(cls))); |
| 5915 } |
| 5916 |
| 5917 void visitTypeVariableType(TypeVariableType type, |
| 5918 SsaBuilder builder) { |
| 5919 ClassElement cls = builder.compiler.findHelper('RuntimeType'); |
| 5920 TypeMask instructionType = new TypeMask.subclass(cls); |
| 5921 if (!builder.currentElement.enclosingElement.isClosure() && |
| 5922 builder.currentElement.isInstanceMember()) { |
| 5923 HInstruction receiver = builder.localsHandler.readThis(); |
| 5924 builder.push(new HReadTypeVariable(type, receiver, instructionType)); |
| 5925 } else { |
| 5926 builder.push( |
| 5927 new HReadTypeVariable.noReceiver( |
| 5928 type, builder.addTypeVariableReference(type), instructionType)); |
| 5929 } |
| 5930 } |
| 5931 |
| 5932 void visitFunctionType(FunctionType type, SsaBuilder builder) { |
| 5933 type.returnType.accept(this, builder); |
| 5934 HInstruction returnType = builder.pop(); |
| 5935 List<HInstruction> inputs = <HInstruction>[returnType]; |
| 5936 |
| 5937 for (DartType parameter in type.parameterTypes) { |
| 5938 parameter.accept(this, builder); |
| 5939 inputs.add(builder.pop()); |
| 5940 } |
| 5941 |
| 5942 for (DartType parameter in type.optionalParameterTypes) { |
| 5943 parameter.accept(this, builder); |
| 5944 inputs.add(builder.pop()); |
| 5945 } |
| 5946 |
| 5947 Link<DartType> namedParameterTypes = type.namedParameterTypes; |
| 5948 for (String name in type.namedParameters) { |
| 5949 DartString dartString = new DartString.literal(name); |
| 5950 inputs.add( |
| 5951 builder.graph.addConstantString(dartString, builder.compiler)); |
| 5952 namedParameterTypes.head.accept(this, builder); |
| 5953 inputs.add(builder.pop()); |
| 5954 namedParameterTypes = namedParameterTypes.tail; |
| 5955 } |
| 5956 |
| 5957 ClassElement cls = builder.compiler.findHelper('RuntimeFunctionType'); |
| 5958 builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls))); |
| 5959 } |
| 5960 |
| 5961 void visitMalformedType(MalformedType type, SsaBuilder builder) { |
| 5962 visitDynamicType(builder.compiler.types.dynamicType, builder); |
| 5963 } |
| 5964 |
| 5965 void visitStatementType(StatementType type, SsaBuilder builder) { |
| 5966 throw 'not implemented visitStatementType($type)'; |
| 5967 } |
| 5968 |
| 5969 void visitGenericType(GenericType type, SsaBuilder builder) { |
| 5970 throw 'not implemented visitGenericType($type)'; |
| 5971 } |
| 5972 |
| 5973 void visitInterfaceType(InterfaceType type, SsaBuilder builder) { |
| 5974 List<HInstruction> inputs = <HInstruction>[]; |
| 5975 for (DartType typeArgument in type.typeArguments) { |
| 5976 typeArgument.accept(this, builder); |
| 5977 inputs.add(builder.pop()); |
| 5978 } |
| 5979 ClassElement cls; |
| 5980 if (type.typeArguments.isEmpty) { |
| 5981 cls = builder.compiler.findHelper('RuntimeTypePlain'); |
| 5982 } else { |
| 5983 cls = builder.compiler.findHelper('RuntimeTypeGeneric'); |
| 5984 } |
| 5985 builder.push(new HInterfaceType(inputs, type, new TypeMask.exact(cls))); |
| 5986 } |
| 5987 |
| 5988 void visitTypedefType(TypedefType type, SsaBuilder builder) { |
| 5989 DartType unaliased = type.unalias(builder.compiler); |
| 5990 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 5991 unaliased.accept(this, builder); |
| 5992 } |
| 5993 |
| 5994 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 5995 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); |
| 5996 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 5997 } |
| 5998 } |
OLD | NEW |