| 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 3054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3065 SourceString name = selector.name; | 3065 SourceString name = selector.name; |
| 3066 | 3066 |
| 3067 ClassElement cls = currentElement.getEnclosingClass(); | 3067 ClassElement cls = currentElement.getEnclosingClass(); |
| 3068 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 3068 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); |
| 3069 if (element.enclosingElement.declaration != compiler.objectClass) { | 3069 if (element.enclosingElement.declaration != compiler.objectClass) { |
| 3070 // Register the call as dynamic if [:noSuchMethod:] on the super class | 3070 // Register the call as dynamic if [:noSuchMethod:] on the super class |
| 3071 // is _not_ the default implementation from [:Object:], in case | 3071 // is _not_ the default implementation from [:Object:], in case |
| 3072 // the [:noSuchMethod:] implementation does an [:invokeOn:] on | 3072 // the [:noSuchMethod:] implementation does an [:invokeOn:] on |
| 3073 // the invocation mirror. | 3073 // the invocation mirror. |
| 3074 compiler.enqueuer.codegen.registerSelectorUse(selector); | 3074 compiler.enqueuer.codegen.registerSelectorUse(selector); |
| 3075 } | 3075 } |
| 3076 HStatic target = new HStatic(element); | 3076 HStatic target = new HStatic(element); |
| 3077 add(target); | 3077 add(target); |
| 3078 HInstruction self = localsHandler.readThis(); | 3078 HInstruction self = localsHandler.readThis(); |
| 3079 Constant nameConstant = constantSystem.createString( | 3079 Constant nameConstant = constantSystem.createString( |
| 3080 new DartString.literal(name.slowToString()), node); | 3080 new DartString.literal(name.slowToString()), node); |
| 3081 | 3081 |
| 3082 String internalName = backend.namer.invocationName(selector); | 3082 String internalName = backend.namer.invocationName(selector); |
| 3083 Constant internalNameConstant = | 3083 Constant internalNameConstant = |
| 3084 constantSystem.createString(new DartString.literal(internalName), node); | 3084 constantSystem.createString(new DartString.literal(internalName), node); |
| 3085 | 3085 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3152 HInstruction target = new HInvokeSuper(inputs); | 3152 HInstruction target = new HInvokeSuper(inputs); |
| 3153 add(target); | 3153 add(target); |
| 3154 inputs = <HInstruction>[target]; | 3154 inputs = <HInstruction>[target]; |
| 3155 addDynamicSendArgumentsToList(node, inputs); | 3155 addDynamicSendArgumentsToList(node, inputs); |
| 3156 Selector closureSelector = new Selector.callClosureFrom(selector); | 3156 Selector closureSelector = new Selector.callClosureFrom(selector); |
| 3157 push(new HInvokeClosure(closureSelector, inputs)); | 3157 push(new HInvokeClosure(closureSelector, inputs)); |
| 3158 } | 3158 } |
| 3159 } | 3159 } |
| 3160 | 3160 |
| 3161 /** | 3161 /** |
| 3162 * Generate code to extract the type arguments from the object, substitute |
| 3163 * them as an instance of the type we are testing against (if necessary), and |
| 3164 * extract the type argument by the index of the variable in the list of type |
| 3165 * variables for that class. |
| 3166 */ |
| 3167 HInstruction readTypeVariable(ClassElement cls, |
| 3168 TypeVariableElement variable) { |
| 3169 int index = RuntimeTypeInformation.getTypeVariableIndex(variable); |
| 3170 String substitutionNameString = backend.namer.substitutionName(cls); |
| 3171 HInstruction substitutionName = graph.addConstantString( |
| 3172 new LiteralDartString(substitutionNameString), null, constantSystem); |
| 3173 HInstruction target = localsHandler.readThis(); |
| 3174 HInstruction substitution = createForeign('#[#]', HType.UNKNOWN, |
| 3175 <HInstruction>[target, substitutionName]); |
| 3176 add(substitution); |
| 3177 pushInvokeHelper3(backend.getGetRuntimeTypeArgument(), |
| 3178 target, |
| 3179 substitution, |
| 3180 graph.addConstantInt(index, constantSystem), |
| 3181 HType.UNKNOWN); |
| 3182 return pop(); |
| 3183 } |
| 3184 |
| 3185 /** |
| 3162 * Helper to create an instruction that gets the value of a type variable. | 3186 * Helper to create an instruction that gets the value of a type variable. |
| 3163 */ | 3187 */ |
| 3164 HInstruction addTypeVariableReference(TypeVariableType type) { | 3188 HInstruction addTypeVariableReference(TypeVariableType type) { |
| 3165 Element member = currentElement; | 3189 Element member = currentElement; |
| 3166 if (member.enclosingElement.isClosure()) { | 3190 if (member.enclosingElement.isClosure()) { |
| 3167 ClosureClassElement closureClass = member.enclosingElement; | 3191 ClosureClassElement closureClass = member.enclosingElement; |
| 3168 member = closureClass.methodElement; | 3192 member = closureClass.methodElement; |
| 3169 member = member.getOutermostEnclosingMemberOrTopLevel(); | 3193 member = member.getOutermostEnclosingMemberOrTopLevel(); |
| 3170 } | 3194 } |
| 3171 if (member.isConstructor() | 3195 if (member.isConstructor() |
| 3172 || member.isGenerativeConstructorBody() | 3196 || member.isGenerativeConstructorBody() |
| 3173 || member.isField()) { | 3197 || member.isField()) { |
| 3174 // The type variable is stored in a parameter of the method. | 3198 // The type variable is stored in a parameter of the method. |
| 3175 return localsHandler.readLocal(type.element); | 3199 return localsHandler.readLocal(type.element); |
| 3176 } else if (member.isInstanceMember()) { | 3200 } else if (member.isInstanceMember()) { |
| 3177 // The type variable is stored on the object. Generate code to extract | 3201 // The type variable is stored on the object. |
| 3178 // the type arguments from the object, substitute them as an instance | 3202 return readTypeVariable(member.getEnclosingClass(), |
| 3179 // of the type we are testing against (if necessary), and extract the | 3203 type.element); |
| 3180 // type argument by the index of the variable in the list of type | |
| 3181 // variables for that class. | |
| 3182 int index = RuntimeTypeInformation.getTypeVariableIndex(type); | |
| 3183 HInstruction thisObject = localsHandler.readThis(); | |
| 3184 String substitutionNameString = | |
| 3185 backend.namer.substitutionName(member.getEnclosingClass()); | |
| 3186 HInstruction substitutionName = graph.addConstantString( | |
| 3187 new LiteralDartString(substitutionNameString), null, constantSystem); | |
| 3188 HInstruction substitution = createForeign('#[#]', HType.UNKNOWN, | |
| 3189 <HInstruction>[thisObject, substitutionName]); | |
| 3190 add(substitution); | |
| 3191 pushInvokeHelper3(backend.getGetRuntimeTypeArgument(), | |
| 3192 thisObject, | |
| 3193 substitution, | |
| 3194 graph.addConstantInt(index, constantSystem), | |
| 3195 HType.UNKNOWN); | |
| 3196 return pop(); | |
| 3197 } else { | 3204 } else { |
| 3198 // TODO(ngeoffray): Match the VM behavior and throw an | 3205 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3199 // exception at runtime. | 3206 // exception at runtime. |
| 3200 compiler.cancel('Unimplemented unresolved type variable', | 3207 compiler.cancel('Unimplemented unresolved type variable', |
| 3201 element: type.element); | 3208 element: type.element); |
| 3202 } | 3209 } |
| 3203 } | 3210 } |
| 3204 | 3211 |
| 3205 /** | 3212 /** |
| 3206 * Documentation wanted -- johnniwinther | 3213 * Documentation wanted -- johnniwinther |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3413 } | 3420 } |
| 3414 | 3421 |
| 3415 visitTypeReferenceSend(Send node) { | 3422 visitTypeReferenceSend(Send node) { |
| 3416 Element element = elements[node]; | 3423 Element element = elements[node]; |
| 3417 if (element.isClass() || element.isTypedef()) { | 3424 if (element.isClass() || element.isTypedef()) { |
| 3418 // TODO(karlklose): add type representation | 3425 // TODO(karlklose): add type representation |
| 3419 ConstantHandler handler = compiler.constantHandler; | 3426 ConstantHandler handler = compiler.constantHandler; |
| 3420 Constant constant = handler.compileNodeWithDefinitions(node, elements); | 3427 Constant constant = handler.compileNodeWithDefinitions(node, elements); |
| 3421 stack.add(graph.addConstant(constant)); | 3428 stack.add(graph.addConstant(constant)); |
| 3422 } else if (element.isTypeVariable()) { | 3429 } else if (element.isTypeVariable()) { |
| 3423 // TODO(6248): implement support for type variables. | 3430 HInstruction value = readTypeVariable(currentElement.getEnclosingClass(), |
| 3424 compiler.unimplemented('first class type for type variable', node: node); | 3431 element); |
| 3432 pushInvokeHelper1(backend.getRuntimeTypeToString(), |
| 3433 value, HType.STRING); |
| 3434 pushInvokeHelper1(backend.getCreateRuntimeType(), |
| 3435 pop(), HType.UNKNOWN); |
| 3425 } else { | 3436 } else { |
| 3426 internalError('unexpected element kind $element', node: node); | 3437 internalError('unexpected element kind $element', node: node); |
| 3427 } | 3438 } |
| 3428 if (node.isCall) { | 3439 if (node.isCall) { |
| 3429 // This send is of the form 'e(...)', where e is resolved to a type | 3440 // This send is of the form 'e(...)', where e is resolved to a type |
| 3430 // reference. We create a regular closure call on the result of the type | 3441 // reference. We create a regular closure call on the result of the type |
| 3431 // reference instead of creating a NoSuchMethodError to avoid pulling it | 3442 // reference instead of creating a NoSuchMethodError to avoid pulling it |
| 3432 // in if it is not used (e.g., in a try/catch). | 3443 // in if it is not used (e.g., in a try/catch). |
| 3433 HInstruction target = pop(); | 3444 HInstruction target = pop(); |
| 3434 Selector selector = elements.getSelector(node); | 3445 Selector selector = elements.getSelector(node); |
| (...skipping 1663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5098 new HSubGraphBlockInformation(elseBranch.graph)); | 5109 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5099 | 5110 |
| 5100 HBasicBlock conditionStartBlock = conditionBranch.block; | 5111 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5101 conditionStartBlock.setBlockFlow(info, joinBlock); | 5112 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5102 SubGraph conditionGraph = conditionBranch.graph; | 5113 SubGraph conditionGraph = conditionBranch.graph; |
| 5103 HIf branch = conditionGraph.end.last; | 5114 HIf branch = conditionGraph.end.last; |
| 5104 assert(branch is HIf); | 5115 assert(branch is HIf); |
| 5105 branch.blockInformation = conditionStartBlock.blockFlow; | 5116 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5106 } | 5117 } |
| 5107 } | 5118 } |
| OLD | NEW |