| 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 2554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2565 stack.add(checked); | 2565 stack.add(checked); |
| 2566 } | 2566 } |
| 2567 localsHandler.updateLocal(element, checked); | 2567 localsHandler.updateLocal(element, checked); |
| 2568 } | 2568 } |
| 2569 } | 2569 } |
| 2570 | 2570 |
| 2571 void pushInvokeInterceptor(Element element, HInstruction receiver) { | 2571 void pushInvokeInterceptor(Element element, HInstruction receiver) { |
| 2572 HInstruction interceptor = new HStatic(element); | 2572 HInstruction interceptor = new HStatic(element); |
| 2573 add(interceptor); | 2573 add(interceptor); |
| 2574 List<HInstruction> inputs = <HInstruction>[interceptor, receiver]; | 2574 List<HInstruction> inputs = <HInstruction>[interceptor, receiver]; |
| 2575 HInstruction result = new HInvokeStatic(inputs); | 2575 HInvokeStatic result = new HInvokeStatic(inputs); |
| 2576 result.isSideEffectFree = true; | 2576 result.isSideEffectFree = true; |
| 2577 push(result); | 2577 push(result); |
| 2578 } | 2578 } |
| 2579 | 2579 |
| 2580 void pushInvokeHelper0(Element helper) { | 2580 void pushInvokeHelper0(Element helper) { |
| 2581 HInstruction reference = new HStatic(helper); | 2581 HInstruction reference = new HStatic(helper); |
| 2582 add(reference); | 2582 add(reference); |
| 2583 List<HInstruction> inputs = <HInstruction>[reference]; | 2583 List<HInstruction> inputs = <HInstruction>[reference]; |
| 2584 HInstruction result = new HInvokeStatic(inputs); | 2584 HInstruction result = new HInvokeStatic(inputs); |
| 2585 push(result); | 2585 push(result); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2650 bool isNot = false; | 2650 bool isNot = false; |
| 2651 // TODO(ngeoffray): Duplicating pattern in resolver. We should | 2651 // TODO(ngeoffray): Duplicating pattern in resolver. We should |
| 2652 // add a new kind of node. | 2652 // add a new kind of node. |
| 2653 if (typeAnnotation == null) { | 2653 if (typeAnnotation == null) { |
| 2654 typeAnnotation = argument.asSend().receiver; | 2654 typeAnnotation = argument.asSend().receiver; |
| 2655 isNot = true; | 2655 isNot = true; |
| 2656 } | 2656 } |
| 2657 | 2657 |
| 2658 DartType type = elements.getType(typeAnnotation); | 2658 DartType type = elements.getType(typeAnnotation); |
| 2659 HInstruction typeInfo = null; | 2659 HInstruction typeInfo = null; |
| 2660 if (rti.hasTypeArguments(type)) { | 2660 if (RuntimeTypeInformation.hasTypeArguments(type)) { |
| 2661 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); | 2661 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); |
| 2662 typeInfo = pop(); | 2662 typeInfo = pop(); |
| 2663 } | 2663 } |
| 2664 if (type.element.isTypeVariable()) { | 2664 if (type.element.isTypeVariable()) { |
| 2665 // TODO(karlklose): We currently answer true to any is check | 2665 // TODO(karlklose): We currently answer true to any is check |
| 2666 // involving a type variable -- both is T and is !T -- until | 2666 // involving a type variable -- both is T and is !T -- until |
| 2667 // we have a proper implementation of reified generics. | 2667 // we have a proper implementation of reified generics. |
| 2668 stack.add(graph.addConstantBool(true, constantSystem)); | 2668 stack.add(graph.addConstantBool(true, constantSystem)); |
| 2669 } else { | 2669 } else { |
| 2670 HInstruction instruction; | 2670 HInstruction instruction; |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3104 // The type variable is stored in a parameter of the factory. | 3104 // The type variable is stored in a parameter of the factory. |
| 3105 inputs.add(localsHandler.readLocal(type.element)); | 3105 inputs.add(localsHandler.readLocal(type.element)); |
| 3106 } else if (member.isInstanceMember() | 3106 } else if (member.isInstanceMember() |
| 3107 || member.isGenerativeConstructor()) { | 3107 || member.isGenerativeConstructor()) { |
| 3108 // The type variable is stored in [this]. | 3108 // The type variable is stored in [this]. |
| 3109 if (typeInfo == null) { | 3109 if (typeInfo == null) { |
| 3110 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), | 3110 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), |
| 3111 localsHandler.readThis()); | 3111 localsHandler.readThis()); |
| 3112 typeInfo = pop(); | 3112 typeInfo = pop(); |
| 3113 } | 3113 } |
| 3114 int index = RuntimeTypeInformation.getTypeVariableIndex(type); |
| 3114 HInstruction foreign = new HForeign( | 3115 HInstruction foreign = new HForeign( |
| 3115 new LiteralDartString('#.${type.name.slowToString()}'), | 3116 new LiteralDartString('#[$index]'), |
| 3116 new LiteralDartString('String'), | 3117 new LiteralDartString('String'), |
| 3117 <HInstruction>[typeInfo]); | 3118 <HInstruction>[typeInfo]); |
| 3118 add(foreign); | 3119 add(foreign); |
| 3119 inputs.add(foreign); | 3120 inputs.add(foreign); |
| 3120 } else { | 3121 } else { |
| 3121 // TODO(ngeoffray): Match the VM behavior and throw an | 3122 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3122 // exception at runtime. | 3123 // exception at runtime. |
| 3123 compiler.cancel('Unimplemented unresolved type variable', | 3124 compiler.cancel('Unimplemented unresolved type variable', |
| 3124 node: currentNode); | 3125 node: currentNode); |
| 3125 } | 3126 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3138 */ | 3139 */ |
| 3139 void buildTypeString(DartType type, {isInQuotes: false}) { | 3140 void buildTypeString(DartType type, {isInQuotes: false}) { |
| 3140 if (type is TypeVariableType) { | 3141 if (type is TypeVariableType) { |
| 3141 addTypeVariableReference(type); | 3142 addTypeVariableReference(type); |
| 3142 template.add(isInQuotes ? "' + # +'" : "#"); | 3143 template.add(isInQuotes ? "' + # +'" : "#"); |
| 3143 } else if (type is InterfaceType) { | 3144 } else if (type is InterfaceType) { |
| 3144 bool isFirstVariable = true; | 3145 bool isFirstVariable = true; |
| 3145 InterfaceType interfaceType = type; | 3146 InterfaceType interfaceType = type; |
| 3146 bool hasTypeArguments = !interfaceType.arguments.isEmpty; | 3147 bool hasTypeArguments = !interfaceType.arguments.isEmpty; |
| 3147 if (!isInQuotes) template.add("'"); | 3148 if (!isInQuotes) template.add("'"); |
| 3148 template.add(rti.getName(type.element)); | 3149 template.add(backend.namer.getName(type.element)); |
| 3149 if (hasTypeArguments) { | 3150 if (hasTypeArguments) { |
| 3150 template.add("<"); | 3151 template.add("<"); |
| 3151 for (DartType argument in interfaceType.arguments) { | 3152 for (DartType argument in interfaceType.arguments) { |
| 3152 if (!isFirstVariable) { | 3153 if (!isFirstVariable) { |
| 3153 template.add(", "); | 3154 template.add(", "); |
| 3154 } else { | 3155 } else { |
| 3155 isFirstVariable = false; | 3156 isFirstVariable = false; |
| 3156 } | 3157 } |
| 3157 buildTypeString(argument, isInQuotes: true); | 3158 buildTypeString(argument, isInQuotes: true); |
| 3158 } | 3159 } |
| 3159 template.add(">"); | 3160 template.add(">"); |
| 3160 } | 3161 } |
| 3161 if (!isInQuotes) template.add("'"); | 3162 if (!isInQuotes) template.add("'"); |
| 3162 } else { | 3163 } else { |
| 3163 assert(type is TypedefType); | 3164 assert(type is TypedefType); |
| 3164 if (!isInQuotes) template.add("'"); | 3165 if (!isInQuotes) template.add("'"); |
| 3165 template.add(rti.getName(argument.element)); | 3166 template.add(backend.namer.getName(argument.element)); |
| 3166 if (!isInQuotes) template.add("'"); | 3167 if (!isInQuotes) template.add("'"); |
| 3167 } | 3168 } |
| 3168 } | 3169 } |
| 3169 | 3170 |
| 3170 buildTypeString(argument, isInQuotes: false); | 3171 buildTypeString(argument, isInQuotes: false); |
| 3171 HInstruction result = | 3172 HInstruction result = |
| 3172 new HForeign(new LiteralDartString("$template"), | 3173 new HForeign(new LiteralDartString("$template"), |
| 3173 new LiteralDartString('String'), | 3174 new LiteralDartString('String'), |
| 3174 inputs); | 3175 inputs); |
| 3175 add(result); | 3176 add(result); |
| 3176 return result; | 3177 return result; |
| 3177 } | 3178 } |
| 3178 | 3179 |
| 3179 void handleListConstructor(InterfaceType type, | 3180 void handleListConstructor(InterfaceType type, |
| 3180 Node currentNode, | 3181 Node currentNode, |
| 3181 HInstruction newObject) { | 3182 HInstruction newObject) { |
| 3182 if (!compiler.world.needsRti(type.element)) return; | 3183 if (!compiler.world.needsRti(type.element)) return; |
| 3183 List<HInstruction> inputs = <HInstruction>[]; | 3184 List<HInstruction> inputs = <HInstruction>[]; |
| 3184 type.arguments.forEach((DartType argument) { | 3185 type.arguments.forEach((DartType argument) { |
| 3185 inputs.add(analyzeTypeArgument(argument, currentNode)); | 3186 inputs.add(analyzeTypeArgument(argument, currentNode)); |
| 3186 }); | 3187 }); |
| 3187 callSetRuntimeTypeInfo(type.element, inputs, newObject); | 3188 callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| 3188 } | 3189 } |
| 3189 | 3190 |
| 3190 void callSetRuntimeTypeInfo(ClassElement element, | 3191 void callSetRuntimeTypeInfo(ClassElement element, |
| 3191 List<HInstruction> rtiInputs, | 3192 List<HInstruction> rtiInputs, |
| 3192 HInstruction newObject) { | 3193 HInstruction newObject) { |
| 3193 bool needsRti = compiler.world.needsRti(element) && !rtiInputs.isEmpty; | 3194 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) { |
| 3194 bool runtimeTypeIsUsed = compiler.enabledRuntimeType; | 3195 return; |
| 3195 if (!needsRti && !runtimeTypeIsUsed) return; | |
| 3196 | |
| 3197 HInstruction createForeign(String template, | |
| 3198 List<HInstruction> arguments, | |
| 3199 [String type = 'String']) { | |
| 3200 return new HForeign(new LiteralDartString(template), | |
| 3201 new LiteralDartString(type), | |
| 3202 arguments); | |
| 3203 } | 3196 } |
| 3204 | 3197 |
| 3205 // Construct the runtime type information. | 3198 HInstruction typeInfo = new HLiteralList(rtiInputs); |
| 3206 StringBuffer runtimeCode = new StringBuffer(); | 3199 add(typeInfo); |
| 3207 List<HInstruction> runtimeCodeInputs = <HInstruction>[]; | |
| 3208 if (runtimeTypeIsUsed) { | |
| 3209 String runtimeTypeString = | |
| 3210 rti.generateRuntimeTypeString(element, rtiInputs.length); | |
| 3211 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs); | |
| 3212 add(runtimeType); | |
| 3213 runtimeCodeInputs.add(runtimeType); | |
| 3214 runtimeCode.add("runtimeType: '#'"); | |
| 3215 } | |
| 3216 if (needsRti) { | |
| 3217 if (runtimeTypeIsUsed) runtimeCode.add(', '); | |
| 3218 String typeVariablesString = | |
| 3219 RuntimeTypeInformation.generateTypeVariableString(element, | |
| 3220 rtiInputs.length); | |
| 3221 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs); | |
| 3222 add(typeInfo); | |
| 3223 runtimeCodeInputs.add(typeInfo); | |
| 3224 runtimeCode.add('#'); | |
| 3225 } | |
| 3226 HInstruction runtimeInfo = | |
| 3227 createForeign("{$runtimeCode}", runtimeCodeInputs, 'Object'); | |
| 3228 add(runtimeInfo); | |
| 3229 | 3200 |
| 3230 // Set the runtime type information on the object. | 3201 // Set the runtime type information on the object. |
| 3231 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo(); | 3202 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo(); |
| 3232 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement); | 3203 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement); |
| 3233 add(typeInfoSetter); | 3204 add(typeInfoSetter); |
| 3234 add(new HInvokeStatic( | 3205 add(new HInvokeStatic( |
| 3235 <HInstruction>[typeInfoSetter, newObject, runtimeInfo])); | 3206 <HInstruction>[typeInfoSetter, newObject, typeInfo])); |
| 3236 } | 3207 } |
| 3237 | 3208 |
| 3238 visitNewSend(Send node, InterfaceType type) { | 3209 visitNewSend(Send node, InterfaceType type) { |
| 3239 bool isListConstructor = false; | 3210 bool isListConstructor = false; |
| 3240 computeType(element) { | 3211 computeType(element) { |
| 3241 Element originalElement = elements[node]; | 3212 Element originalElement = elements[node]; |
| 3242 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) { | 3213 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) { |
| 3243 isListConstructor = true; | 3214 isListConstructor = true; |
| 3244 if (node.arguments.isEmpty) { | 3215 if (node.arguments.isEmpty) { |
| 3245 return HType.EXTENDABLE_ARRAY; | 3216 return HType.EXTENDABLE_ARRAY; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3280 if (constructor.getEnclosingClass().isAbstract(compiler) && | 3251 if (constructor.getEnclosingClass().isAbstract(compiler) && |
| 3281 constructor.isGenerativeConstructor()) { | 3252 constructor.isGenerativeConstructor()) { |
| 3282 generateAbstractClassInstantiationError(node, type.name.slowToString()); | 3253 generateAbstractClassInstantiationError(node, type.name.slowToString()); |
| 3283 return; | 3254 return; |
| 3284 } | 3255 } |
| 3285 if (compiler.world.needsRti(constructor.enclosingElement)) { | 3256 if (compiler.world.needsRti(constructor.enclosingElement)) { |
| 3286 if (!type.arguments.isEmpty) { | 3257 if (!type.arguments.isEmpty) { |
| 3287 type.arguments.forEach((DartType argument) { | 3258 type.arguments.forEach((DartType argument) { |
| 3288 inputs.add(analyzeTypeArgument(argument, node)); | 3259 inputs.add(analyzeTypeArgument(argument, node)); |
| 3289 }); | 3260 }); |
| 3290 } else if (compiler.enabledRuntimeType) { | |
| 3291 Link<DartType> variables = | |
| 3292 constructor.getEnclosingClass().typeVariables; | |
| 3293 if (!variables.isEmpty) { | |
| 3294 // If the class has type variables but no type arguments have been | |
| 3295 // provided, add [:dynamic:] as argument for all type variables. | |
| 3296 DartString stringDynamic = new DartString.literal('dynamic'); | |
| 3297 HInstruction input = graph.addConstantString(stringDynamic, | |
| 3298 node, | |
| 3299 constantSystem); | |
| 3300 variables.forEach((_) => inputs.add(input)); | |
| 3301 } | |
| 3302 } | 3261 } |
| 3303 } | 3262 } |
| 3304 | 3263 |
| 3305 HType elementType = computeType(constructor); | 3264 HType elementType = computeType(constructor); |
| 3306 HInstruction newInstance = new HInvokeStatic(inputs, elementType); | 3265 HInstruction newInstance = new HInvokeStatic(inputs, elementType); |
| 3307 pushWithPosition(newInstance, node); | 3266 pushWithPosition(newInstance, node); |
| 3308 | 3267 |
| 3309 // The List constructor forwards to a Dart static method that does | 3268 // The List constructor forwards to a Dart static method that does |
| 3310 // not know about the type argument. Therefore we special case | 3269 // not know about the type argument. Therefore we special case |
| 3311 // this constructor to have the setRuntimeTypeInfo called where | 3270 // this constructor to have the setRuntimeTypeInfo called where |
| (...skipping 1647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4959 new HSubGraphBlockInformation(elseBranch.graph)); | 4918 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4960 | 4919 |
| 4961 HBasicBlock conditionStartBlock = conditionBranch.block; | 4920 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4962 conditionStartBlock.setBlockFlow(info, joinBlock); | 4921 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4963 SubGraph conditionGraph = conditionBranch.graph; | 4922 SubGraph conditionGraph = conditionBranch.graph; |
| 4964 HIf branch = conditionGraph.end.last; | 4923 HIf branch = conditionGraph.end.last; |
| 4965 assert(branch is HIf); | 4924 assert(branch is HIf); |
| 4966 branch.blockInformation = conditionStartBlock.blockFlow; | 4925 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4967 } | 4926 } |
| 4968 } | 4927 } |
| OLD | NEW |