| 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 2568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2579 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), target, HType.UNKNOWN); | 2579 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), target, HType.UNKNOWN); |
| 2580 return pop(); | 2580 return pop(); |
| 2581 } | 2581 } |
| 2582 | 2582 |
| 2583 // TODO(karlklose): change construction of the representations to be GVN'able | 2583 // TODO(karlklose): change construction of the representations to be GVN'able |
| 2584 // (dartbug.com/7182). | 2584 // (dartbug.com/7182). |
| 2585 List<HInstruction> buildTypeArgumentRepresentations(DartType type) { | 2585 List<HInstruction> buildTypeArgumentRepresentations(DartType type) { |
| 2586 HInstruction createForeignArray(String code, inputs) { | 2586 HInstruction createForeignArray(String code, inputs) { |
| 2587 return createForeign(code, HType.READABLE_ARRAY, inputs); | 2587 return createForeign(code, HType.READABLE_ARRAY, inputs); |
| 2588 } | 2588 } |
| 2589 HInstruction typeInfo; | |
| 2590 | |
| 2591 /// Helper to create an instruction that contains the runtime value of | |
| 2592 /// the type variable [variable]. | |
| 2593 HInstruction getTypeArgument(TypeVariableType variable) { | |
| 2594 if (typeInfo == null) { | |
| 2595 typeInfo = getRuntimeTypeInfo(localsHandler.readThis()); | |
| 2596 } | |
| 2597 int intIndex = RuntimeTypeInformation.getTypeVariableIndex(variable); | |
| 2598 HInstruction index = graph.addConstantInt(intIndex, constantSystem); | |
| 2599 return createForeignArray('#[#]', <HInstruction>[typeInfo, index]); | |
| 2600 } | |
| 2601 | 2589 |
| 2602 // Compute the representation of the type arguments, including access | 2590 // Compute the representation of the type arguments, including access |
| 2603 // to the runtime type information for type variables as instructions. | 2591 // to the runtime type information for type variables as instructions. |
| 2604 HInstruction representations; | 2592 HInstruction representations; |
| 2605 if (type.element.isTypeVariable()) { | 2593 if (type.element.isTypeVariable()) { |
| 2606 return <HInstruction>[getTypeArgument(type)]; | 2594 return <HInstruction>[addTypeVariableReference(type)]; |
| 2607 } else { | 2595 } else { |
| 2608 assert(type.element.isClass()); | 2596 assert(type.element.isClass()); |
| 2609 List<HInstruction> arguments = <HInstruction>[]; | 2597 List<HInstruction> arguments = <HInstruction>[]; |
| 2610 InterfaceType interface = type; | 2598 InterfaceType interface = type; |
| 2611 for (DartType argument in interface.typeArguments) { | 2599 for (DartType argument in interface.typeArguments) { |
| 2612 List<HInstruction> inputs = <HInstruction>[]; | 2600 List<HInstruction> inputs = <HInstruction>[]; |
| 2613 String template = rti.getTypeRepresentation(argument, (variable) { | 2601 String template = rti.getTypeRepresentation(argument, (variable) { |
| 2614 HInstruction runtimeType = getTypeArgument(variable); | 2602 HInstruction runtimeType = addTypeVariableReference(variable); |
| 2615 add(runtimeType); | |
| 2616 inputs.add(runtimeType); | 2603 inputs.add(runtimeType); |
| 2617 }); | 2604 }); |
| 2618 HInstruction representation = createForeignArray(template, inputs); | 2605 HInstruction representation = createForeignArray(template, inputs); |
| 2619 add(representation); | 2606 add(representation); |
| 2620 arguments.add(representation); | 2607 arguments.add(representation); |
| 2621 } | 2608 } |
| 2622 return arguments; | 2609 return arguments; |
| 2623 } | 2610 } |
| 2624 } | 2611 } |
| 2625 | 2612 |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3144 target = new HInvokeSuper(inputs); | 3131 target = new HInvokeSuper(inputs); |
| 3145 add(target); | 3132 add(target); |
| 3146 inputs = <HInstruction>[target]; | 3133 inputs = <HInstruction>[target]; |
| 3147 addDynamicSendArgumentsToList(node, inputs); | 3134 addDynamicSendArgumentsToList(node, inputs); |
| 3148 Selector closureSelector = new Selector.callClosureFrom(selector); | 3135 Selector closureSelector = new Selector.callClosureFrom(selector); |
| 3149 push(new HInvokeClosure(closureSelector, inputs)); | 3136 push(new HInvokeClosure(closureSelector, inputs)); |
| 3150 } | 3137 } |
| 3151 } | 3138 } |
| 3152 | 3139 |
| 3153 /** | 3140 /** |
| 3141 * Helper to create an instruction that gets the value of a type variable. |
| 3142 */ |
| 3143 HInstruction addTypeVariableReference(TypeVariableType type) { |
| 3144 Element member = currentElement; |
| 3145 if (member.enclosingElement.isClosure()) { |
| 3146 ClosureClassElement closureClass = member.enclosingElement; |
| 3147 member = closureClass.methodElement; |
| 3148 member = member.getOutermostEnclosingMemberOrTopLevel(); |
| 3149 } |
| 3150 if (member.isFactoryConstructor()) { |
| 3151 // The type variable is stored in a parameter of the method. |
| 3152 return localsHandler.readLocal(type.element); |
| 3153 } else if (member.isInstanceMember() || |
| 3154 member.isGenerativeConstructor()) { |
| 3155 // The type variable is stored on the object. Generate code to extract |
| 3156 // the type arguments from the object, substitute them as an instance |
| 3157 // of the type we are testing against (if necessary), and extract the |
| 3158 // type argument by the index of the variable in the list of type |
| 3159 // variables for that class. |
| 3160 int index = RuntimeTypeInformation.getTypeVariableIndex(type); |
| 3161 HInstruction thisObject = localsHandler.readThis(); |
| 3162 String substitutionNameString = |
| 3163 backend.namer.substitutionName(member.getEnclosingClass()); |
| 3164 HInstruction substitutionName = graph.addConstantString( |
| 3165 new LiteralDartString(substitutionNameString), null, constantSystem); |
| 3166 HInstruction substitution = createForeign('#[#]', HType.UNKNOWN, |
| 3167 <HInstruction>[thisObject, substitutionName]); |
| 3168 add(substitution); |
| 3169 pushInvokeHelper3(backend.getGetRuntimeTypeArgument(), |
| 3170 thisObject, |
| 3171 substitution, |
| 3172 graph.addConstantInt(index, constantSystem), |
| 3173 HType.UNKNOWN); |
| 3174 return pop(); |
| 3175 } else { |
| 3176 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3177 // exception at runtime. |
| 3178 compiler.cancel('Unimplemented unresolved type variable', |
| 3179 element: type.element); |
| 3180 } |
| 3181 } |
| 3182 |
| 3183 /** |
| 3154 * Documentation wanted -- johnniwinther | 3184 * Documentation wanted -- johnniwinther |
| 3155 * | 3185 * |
| 3156 * Invariant: [argument] must not be malformed in checked mode. | 3186 * Invariant: [argument] must not be malformed in checked mode. |
| 3157 */ | 3187 */ |
| 3158 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { | 3188 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { |
| 3159 assert(invariant(currentNode, | 3189 assert(invariant(currentNode, |
| 3160 !compiler.enableTypeAssertions || !argument.isMalformed, | 3190 !compiler.enableTypeAssertions || !argument.isMalformed, |
| 3161 message: '$argument is malformed in checked mode')); | 3191 message: '$argument is malformed in checked mode')); |
| 3162 if (argument == compiler.types.dynamicType || argument.isMalformed) { | 3192 if (argument == compiler.types.dynamicType || argument.isMalformed) { |
| 3163 // Represent [dynamic] as [null]. | 3193 // Represent [dynamic] as [null]. |
| 3164 return graph.addConstantNull(constantSystem); | 3194 return graph.addConstantNull(constantSystem); |
| 3165 } | 3195 } |
| 3166 | 3196 |
| 3167 // The inputs are shared between invocations of the helper. | |
| 3168 List<HInstruction> inputs = <HInstruction>[]; | 3197 List<HInstruction> inputs = <HInstruction>[]; |
| 3169 | 3198 |
| 3170 /** | 3199 String template = rti.getTypeRepresentation(argument, (variable) { |
| 3171 * Helper to create an instruction that gets the value of a type variable. | 3200 inputs.add(addTypeVariableReference(variable)); |
| 3172 */ | 3201 }); |
| 3173 String addTypeVariableReference(TypeVariableType type) { | |
| 3174 Element member = currentElement; | |
| 3175 if (member.enclosingElement.isClosure()) { | |
| 3176 ClosureClassElement closureClass = member.enclosingElement; | |
| 3177 member = closureClass.methodElement; | |
| 3178 member = member.getOutermostEnclosingMemberOrTopLevel(); | |
| 3179 } | |
| 3180 if (member.isFactoryConstructor()) { | |
| 3181 // The type variable is stored in a parameter of the method. | |
| 3182 inputs.add(localsHandler.readLocal(type.element)); | |
| 3183 } else if (member.isInstanceMember() || | |
| 3184 member.isGenerativeConstructor()) { | |
| 3185 // The type variable is stored on the object. Generate code to extract | |
| 3186 // the type arguments from the object, substitute them as an instance | |
| 3187 // of the type we are testing against (if necessary), and extract the | |
| 3188 // type argument by the index of the variable in the list of type | |
| 3189 // variables for that class. | |
| 3190 int index = RuntimeTypeInformation.getTypeVariableIndex(type); | |
| 3191 HInstruction thisObject = localsHandler.readThis(); | |
| 3192 String substitutionNameString = | |
| 3193 backend.namer.substitutionName(member.getEnclosingClass()); | |
| 3194 HInstruction substitutionName = graph.addConstantString( | |
| 3195 new LiteralDartString(substitutionNameString), null, constantSystem)
; | |
| 3196 HInstruction substitution = createForeign('#[#]', HType.UNKNOWN, | |
| 3197 <HInstruction>[thisObject, substitutionName]); | |
| 3198 add(substitution); | |
| 3199 pushInvokeHelper3(backend.getGetRuntimeTypeArgument(), | |
| 3200 thisObject, | |
| 3201 substitution, | |
| 3202 graph.addConstantInt(index, constantSystem), | |
| 3203 HType.UNKNOWN); | |
| 3204 inputs.add(pop()); | |
| 3205 } else { | |
| 3206 // TODO(ngeoffray): Match the VM behavior and throw an | |
| 3207 // exception at runtime. | |
| 3208 compiler.cancel('Unimplemented unresolved type variable', | |
| 3209 node: currentNode); | |
| 3210 } | |
| 3211 } | |
| 3212 | 3202 |
| 3213 String template = rti.getTypeRepresentation(argument, | |
| 3214 addTypeVariableReference); | |
| 3215 HInstruction result = createForeign(template, HType.STRING, inputs); | 3203 HInstruction result = createForeign(template, HType.STRING, inputs); |
| 3216 add(result); | 3204 add(result); |
| 3217 return result; | 3205 return result; |
| 3218 } | 3206 } |
| 3219 | 3207 |
| 3220 void handleListConstructor(InterfaceType type, | 3208 void handleListConstructor(InterfaceType type, |
| 3221 Node currentNode, | 3209 Node currentNode, |
| 3222 HInstruction newObject) { | 3210 HInstruction newObject) { |
| 3223 if (!compiler.world.needsRti(type.element)) return; | 3211 if (!compiler.world.needsRti(type.element)) return; |
| 3224 if (!type.isRaw) { | 3212 if (!type.isRaw) { |
| (...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5062 new HSubGraphBlockInformation(elseBranch.graph)); | 5050 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5063 | 5051 |
| 5064 HBasicBlock conditionStartBlock = conditionBranch.block; | 5052 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5065 conditionStartBlock.setBlockFlow(info, joinBlock); | 5053 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5066 SubGraph conditionGraph = conditionBranch.graph; | 5054 SubGraph conditionGraph = conditionBranch.graph; |
| 5067 HIf branch = conditionGraph.end.last; | 5055 HIf branch = conditionGraph.end.last; |
| 5068 assert(branch is HIf); | 5056 assert(branch is HIf); |
| 5069 branch.blockInformation = conditionStartBlock.blockFlow; | 5057 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5070 } | 5058 } |
| 5071 } | 5059 } |
| OLD | NEW |