| 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 2569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2580 } else { | 2580 } else { |
| 2581 assert(type.element.isClass()); | 2581 assert(type.element.isClass()); |
| 2582 List<HInstruction> arguments = <HInstruction>[]; | 2582 List<HInstruction> arguments = <HInstruction>[]; |
| 2583 InterfaceType interface = type; | 2583 InterfaceType interface = type; |
| 2584 for (DartType argument in interface.typeArguments) { | 2584 for (DartType argument in interface.typeArguments) { |
| 2585 List<HInstruction> inputs = <HInstruction>[]; | 2585 List<HInstruction> inputs = <HInstruction>[]; |
| 2586 String template = rti.getTypeRepresentation(argument, (variable) { | 2586 String template = rti.getTypeRepresentation(argument, (variable) { |
| 2587 HInstruction runtimeType = getTypeArgument(variable); | 2587 HInstruction runtimeType = getTypeArgument(variable); |
| 2588 add(runtimeType); | 2588 add(runtimeType); |
| 2589 inputs.add(runtimeType); | 2589 inputs.add(runtimeType); |
| 2590 return '#'; | |
| 2591 }); | 2590 }); |
| 2592 HInstruction representation = createForeignArray(template, inputs); | 2591 HInstruction representation = createForeignArray(template, inputs); |
| 2593 add(representation); | 2592 add(representation); |
| 2594 arguments.add(representation); | 2593 arguments.add(representation); |
| 2595 } | 2594 } |
| 2596 return arguments; | 2595 return arguments; |
| 2597 } | 2596 } |
| 2598 } | 2597 } |
| 2599 | 2598 |
| 2600 visitOperatorSend(node) { | 2599 visitOperatorSend(node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2634 // TODO(karlklose): remove this check when the backend can deal with | 2633 // TODO(karlklose): remove this check when the backend can deal with |
| 2635 // checks of the form [:o is T:] where [:T:] is a type variable. | 2634 // checks of the form [:o is T:] where [:T:] is a type variable. |
| 2636 stack.add(graph.addConstantBool(true, constantSystem)); | 2635 stack.add(graph.addConstantBool(true, constantSystem)); |
| 2637 return; | 2636 return; |
| 2638 } | 2637 } |
| 2639 | 2638 |
| 2640 HInstruction instruction; | 2639 HInstruction instruction; |
| 2641 if (type.element.isTypeVariable() || | 2640 if (type.element.isTypeVariable() || |
| 2642 RuntimeTypeInformation.hasTypeArguments(type)) { | 2641 RuntimeTypeInformation.hasTypeArguments(type)) { |
| 2643 HInstruction typeInfo = getRuntimeTypeInfo(expression); | 2642 HInstruction typeInfo = getRuntimeTypeInfo(expression); |
| 2644 Element helper = | 2643 // TODO(karlklose): make isSubtype a HInstruction to enable |
| 2645 compiler.findHelper(const SourceString('checkArguments')); | 2644 // optimizations? |
| 2646 HInstruction helperCall = new HStatic(helper); | 2645 Element helper = compiler.findHelper(const SourceString('isSubtype')); |
| 2647 add(helperCall); | 2646 HInstruction isSubtype = new HStatic(helper); |
| 2647 add(isSubtype); |
| 2648 // Build a list of representations for the type arguments. |
| 2648 List<HInstruction> representations = | 2649 List<HInstruction> representations = |
| 2649 buildTypeArgumentRepresentations(type); | 2650 buildTypeArgumentRepresentations(type); |
| 2650 String substitution = backend.namer.substitutionName(type.element); | 2651 // For each type argument, build a call to isSubtype, with the type |
| 2651 HInstruction fieldGet = | 2652 // argument as first and the representation of the tested type as |
| 2652 createForeign('#.$substitution', HType.UNKNOWN, [expression]); | 2653 // second argument. |
| 2653 HInstruction representationList = new HLiteralList(representations); | 2654 List<HInstruction> checks = <HInstruction>[]; |
| 2654 add(fieldGet); | 2655 int index = 0; |
| 2655 add(representationList); | 2656 representations.forEach((HInstruction representation) { |
| 2656 List<HInstruction> inputs = <HInstruction>[helperCall, | 2657 HInstruction position = graph.addConstantInt(index, constantSystem); |
| 2657 fieldGet, | 2658 // Get the index'th type argument from the runtime type information. |
| 2658 typeInfo, | 2659 HInstruction typeArgument = |
| 2659 representationList]; | 2660 createForeign('#[#]', HType.UNKNOWN, [typeInfo, position]); |
| 2660 HInstruction check = new HInvokeStatic(inputs); | 2661 add(typeArgument); |
| 2661 add(check); | 2662 // Create the call to isSubtype. |
| 2662 instruction = new HIs(type, <HInstruction>[expression, check]); | 2663 List<HInstruction> inputs = |
| 2664 <HInstruction>[isSubtype, typeArgument, representation]; |
| 2665 HInstruction call = new HInvokeStatic(inputs); |
| 2666 add(call); |
| 2667 checks.add(call); |
| 2668 index++; |
| 2669 }); |
| 2670 instruction = new HIs(type, <HInstruction>[expression]..addAll(checks)); |
| 2663 } else { | 2671 } else { |
| 2664 instruction = new HIs(type, <HInstruction>[expression]); | 2672 instruction = new HIs(type, <HInstruction>[expression]); |
| 2665 } | 2673 } |
| 2666 if (isNot) { | 2674 if (isNot) { |
| 2667 add(instruction); | 2675 add(instruction); |
| 2668 instruction = new HNot(instruction); | 2676 instruction = new HNot(instruction); |
| 2669 } | 2677 } |
| 2670 push(instruction); | 2678 push(instruction); |
| 2671 } else if (const SourceString("as") == op.source) { | 2679 } else if (const SourceString("as") == op.source) { |
| 2672 visit(node.receiver); | 2680 visit(node.receiver); |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2998 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { | 3006 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { |
| 2999 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); | 3007 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); |
| 3000 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { | 3008 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { |
| 3001 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); | 3009 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); |
| 3002 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { | 3010 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { |
| 3003 handleForeignSetCurrentIsolate(node); | 3011 handleForeignSetCurrentIsolate(node); |
| 3004 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { | 3012 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { |
| 3005 handleForeignCreateIsolate(node); | 3013 handleForeignCreateIsolate(node); |
| 3006 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { | 3014 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { |
| 3007 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); | 3015 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); |
| 3008 } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) { | |
| 3009 stack.add(addConstantString(node, backend.namer.operatorAsPrefix())); | |
| 3010 } else { | 3016 } else { |
| 3011 throw "Unknown foreign: ${selector}"; | 3017 throw "Unknown foreign: ${selector}"; |
| 3012 } | 3018 } |
| 3013 } | 3019 } |
| 3014 | 3020 |
| 3015 generateSuperNoSuchMethodSend(Send node) { | 3021 generateSuperNoSuchMethodSend(Send node) { |
| 3016 Selector selector = elements.getSelector(node); | 3022 Selector selector = elements.getSelector(node); |
| 3017 SourceString name = selector.name; | 3023 SourceString name = selector.name; |
| 3018 | 3024 |
| 3019 ClassElement cls = currentElement.getEnclosingClass(); | 3025 ClassElement cls = currentElement.getEnclosingClass(); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3118 */ | 3124 */ |
| 3119 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { | 3125 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { |
| 3120 assert(invariant(currentNode, | 3126 assert(invariant(currentNode, |
| 3121 !compiler.enableTypeAssertions || !argument.isMalformed, | 3127 !compiler.enableTypeAssertions || !argument.isMalformed, |
| 3122 message: '$argument is malformed in checked mode')); | 3128 message: '$argument is malformed in checked mode')); |
| 3123 if (argument == compiler.types.dynamicType || argument.isMalformed) { | 3129 if (argument == compiler.types.dynamicType || argument.isMalformed) { |
| 3124 // Represent [dynamic] as [null]. | 3130 // Represent [dynamic] as [null]. |
| 3125 return graph.addConstantNull(constantSystem); | 3131 return graph.addConstantNull(constantSystem); |
| 3126 } | 3132 } |
| 3127 | 3133 |
| 3128 // The inputs are shared between invocations of the helper. | 3134 // These variables are shared between invocations of the helper. |
| 3135 HInstruction typeInfo; |
| 3129 List<HInstruction> inputs = <HInstruction>[]; | 3136 List<HInstruction> inputs = <HInstruction>[]; |
| 3130 | 3137 |
| 3131 /** | 3138 /** |
| 3132 * Helper to create an instruction that gets the value of a type variable. | 3139 * Helper to create an instruction that gets the value of a type variable. |
| 3133 */ | 3140 */ |
| 3134 String addTypeVariableReference(TypeVariableType type) { | 3141 void addTypeVariableReference(TypeVariableType type) { |
| 3135 Element member = currentElement; | 3142 Element member = currentElement; |
| 3136 if (member.enclosingElement.isClosure()) { | 3143 if (member.enclosingElement.isClosure()) { |
| 3137 ClosureClassElement closureClass = member.enclosingElement; | 3144 ClosureClassElement closureClass = member.enclosingElement; |
| 3138 member = closureClass.methodElement; | 3145 member = closureClass.methodElement; |
| 3139 member = member.getOutermostEnclosingMemberOrTopLevel(); | 3146 member = member.getOutermostEnclosingMemberOrTopLevel(); |
| 3140 } | 3147 } |
| 3141 if (member.isFactoryConstructor()) { | 3148 if (member.isFactoryConstructor()) { |
| 3142 // The type variable is stored in a parameter of the method. | 3149 // The type variable is stored in a parameter of the factory. |
| 3143 inputs.add(localsHandler.readLocal(type.element)); | 3150 inputs.add(localsHandler.readLocal(type.element)); |
| 3144 } else if (member.isInstanceMember() || | 3151 } else if (member.isInstanceMember() |
| 3145 member.isGenerativeConstructor()) { | 3152 || member.isGenerativeConstructor()) { |
| 3146 // The type variable is stored in [this]. | 3153 // The type variable is stored in [this]. |
| 3154 if (typeInfo == null) { |
| 3155 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), |
| 3156 localsHandler.readThis()); |
| 3157 typeInfo = pop(); |
| 3158 } |
| 3147 int index = RuntimeTypeInformation.getTypeVariableIndex(type); | 3159 int index = RuntimeTypeInformation.getTypeVariableIndex(type); |
| 3148 pushInvokeHelper2(backend.getGetRuntimeTypeArgument(), | 3160 HInstruction foreign = createForeign('#[$index]', HType.STRING, |
| 3149 localsHandler.readThis(), | 3161 <HInstruction>[typeInfo]); |
| 3150 graph.addConstantInt(index, constantSystem)); | 3162 add(foreign); |
| 3151 inputs.add(pop()); | 3163 inputs.add(foreign); |
| 3152 } else { | 3164 } else { |
| 3153 // TODO(ngeoffray): Match the VM behavior and throw an | 3165 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3154 // exception at runtime. | 3166 // exception at runtime. |
| 3155 compiler.cancel('Unimplemented unresolved type variable', | 3167 compiler.cancel('Unimplemented unresolved type variable', |
| 3156 node: currentNode); | 3168 node: currentNode); |
| 3157 } | 3169 } |
| 3158 return '#'; | |
| 3159 } | 3170 } |
| 3160 | 3171 |
| 3161 String template = rti.getTypeRepresentation(argument, | 3172 String template = rti.getTypeRepresentation(argument, |
| 3162 addTypeVariableReference); | 3173 addTypeVariableReference); |
| 3163 HInstruction result = createForeign(template, HType.STRING, inputs); | 3174 HInstruction result = createForeign(template, HType.STRING, inputs); |
| 3164 add(result); | 3175 add(result); |
| 3165 return result; | 3176 return result; |
| 3166 } | 3177 } |
| 3167 | 3178 |
| 3168 void handleListConstructor(InterfaceType type, | 3179 void handleListConstructor(InterfaceType type, |
| 3169 Node currentNode, | 3180 Node currentNode, |
| 3170 HInstruction newObject) { | 3181 HInstruction newObject) { |
| 3171 if (!compiler.world.needsRti(type.element)) return; | 3182 if (!compiler.world.needsRti(type.element)) return; |
| 3183 List<HInstruction> inputs = <HInstruction>[]; |
| 3172 if (!type.isRaw) { | 3184 if (!type.isRaw) { |
| 3173 List<HInstruction> inputs = <HInstruction>[]; | |
| 3174 type.typeArguments.forEach((DartType argument) { | 3185 type.typeArguments.forEach((DartType argument) { |
| 3175 inputs.add(analyzeTypeArgument(argument, currentNode)); | 3186 inputs.add(analyzeTypeArgument(argument, currentNode)); |
| 3176 }); | 3187 }); |
| 3177 callSetRuntimeTypeInfo(type.element, inputs, newObject); | |
| 3178 } | 3188 } |
| 3189 callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| 3179 } | 3190 } |
| 3180 | 3191 |
| 3181 void callSetRuntimeTypeInfo(ClassElement element, | 3192 void callSetRuntimeTypeInfo(ClassElement element, |
| 3182 List<HInstruction> rtiInputs, | 3193 List<HInstruction> rtiInputs, |
| 3183 HInstruction newObject) { | 3194 HInstruction newObject) { |
| 3184 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) { | 3195 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) { |
| 3185 return; | 3196 return; |
| 3186 } | 3197 } |
| 3187 | 3198 |
| 3188 HInstruction typeInfo = new HLiteralList(rtiInputs); | 3199 HInstruction typeInfo = new HLiteralList(rtiInputs); |
| (...skipping 1800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4989 new HSubGraphBlockInformation(elseBranch.graph)); | 5000 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4990 | 5001 |
| 4991 HBasicBlock conditionStartBlock = conditionBranch.block; | 5002 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4992 conditionStartBlock.setBlockFlow(info, joinBlock); | 5003 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4993 SubGraph conditionGraph = conditionBranch.graph; | 5004 SubGraph conditionGraph = conditionBranch.graph; |
| 4994 HIf branch = conditionGraph.end.last; | 5005 HIf branch = conditionGraph.end.last; |
| 4995 assert(branch is HIf); | 5006 assert(branch is HIf); |
| 4996 branch.blockInformation = conditionStartBlock.blockFlow; | 5007 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4997 } | 5008 } |
| 4998 } | 5009 } |
| OLD | NEW |