Chromium Code Reviews| 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 2170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2181 } | 2181 } |
| 2182 | 2182 |
| 2183 void visitLogicalAndOr(Send node, Operator op) { | 2183 void visitLogicalAndOr(Send node, Operator op) { |
| 2184 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); | 2184 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); |
| 2185 branchBuilder.handleLogicalAndOrWithLeftNode( | 2185 branchBuilder.handleLogicalAndOrWithLeftNode( |
| 2186 node.receiver, | 2186 node.receiver, |
| 2187 () { visit(node.argumentsNode); }, | 2187 () { visit(node.argumentsNode); }, |
| 2188 isAnd: (const SourceString("&&") == op.source)); | 2188 isAnd: (const SourceString("&&") == op.source)); |
| 2189 } | 2189 } |
| 2190 | 2190 |
| 2191 | |
| 2192 void visitLogicalNot(Send node) { | 2191 void visitLogicalNot(Send node) { |
| 2193 assert(node.argumentsNode is Prefix); | 2192 assert(node.argumentsNode is Prefix); |
| 2194 visit(node.receiver); | 2193 visit(node.receiver); |
| 2195 HNot not = new HNot(popBoolified()); | 2194 HNot not = new HNot(popBoolified()); |
| 2196 pushWithPosition(not, node); | 2195 pushWithPosition(not, node); |
| 2197 } | 2196 } |
| 2198 | 2197 |
| 2199 void visitUnary(Send node, Operator op) { | 2198 void visitUnary(Send node, Operator op) { |
| 2200 if (node.isParameterCheck) { | 2199 if (node.isParameterCheck) { |
| 2201 Element element = elements[node.receiver]; | 2200 Element element = elements[node.receiver]; |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2649 if (type.element.isTypeVariable()) { | 2648 if (type.element.isTypeVariable()) { |
| 2650 // TODO(karlklose): remove this check when the backend can deal with | 2649 // TODO(karlklose): remove this check when the backend can deal with |
| 2651 // checks of the form [:o is T:] where [:T:] is a type variable. | 2650 // checks of the form [:o is T:] where [:T:] is a type variable. |
| 2652 stack.add(graph.addConstantBool(true, constantSystem)); | 2651 stack.add(graph.addConstantBool(true, constantSystem)); |
| 2653 return; | 2652 return; |
| 2654 } | 2653 } |
| 2655 | 2654 |
| 2656 HInstruction instruction; | 2655 HInstruction instruction; |
| 2657 if (type.element.isTypeVariable() || | 2656 if (type.element.isTypeVariable() || |
| 2658 RuntimeTypeInformation.hasTypeArguments(type)) { | 2657 RuntimeTypeInformation.hasTypeArguments(type)) { |
| 2659 HInstruction typeInfo = getRuntimeTypeInfo(expression); | 2658 |
| 2660 // TODO(karlklose): make isSubtype a HInstruction to enable | 2659 void argumentsCheck() { |
|
karlklose
2013/02/08 14:51:46
@Nicolas: this is the main change to the previous
| |
| 2661 // optimizations? | 2660 HInstruction typeInfo = getRuntimeTypeInfo(expression); |
| 2662 Element helper = compiler.findHelper(const SourceString('isSubtype')); | 2661 Element helper = |
| 2663 HInstruction isSubtype = new HStatic(helper); | 2662 compiler.findHelper(const SourceString('checkArguments')); |
| 2664 add(isSubtype); | 2663 HInstruction helperCall = new HStatic(helper); |
| 2665 // Build a list of representations for the type arguments. | 2664 add(helperCall); |
| 2666 List<HInstruction> representations = | 2665 List<HInstruction> representations = |
| 2667 buildTypeArgumentRepresentations(type); | 2666 buildTypeArgumentRepresentations(type); |
| 2668 // For each type argument, build a call to isSubtype, with the type | 2667 Element element = type.element; |
| 2669 // argument as first and the representation of the tested type as | 2668 String substitution = backend.namer.substitutionName(element); |
| 2670 // second argument. | 2669 if (backend.emitter.nativeEmitter.requiresNativeIsCheck(element)) { |
| 2671 List<HInstruction> checks = <HInstruction>[]; | 2670 substitution = '$substitution()'; |
| 2672 int index = 0; | 2671 } |
| 2673 representations.forEach((HInstruction representation) { | 2672 HInstruction fieldGet = |
| 2674 HInstruction position = graph.addConstantInt(index, constantSystem); | 2673 createForeign('#.$substitution', HType.UNKNOWN, [expression]); |
| 2675 // Get the index'th type argument from the runtime type information. | 2674 HInstruction representationList = new HLiteralList(representations); |
| 2676 HInstruction typeArgument = | 2675 add(fieldGet); |
| 2677 createForeign('#[#]', HType.UNKNOWN, [typeInfo, position]); | 2676 add(representationList); |
| 2678 add(typeArgument); | 2677 List<HInstruction> inputs = <HInstruction>[helperCall, |
| 2679 // Create the call to isSubtype. | 2678 fieldGet, |
| 2680 List<HInstruction> inputs = | 2679 typeInfo, |
| 2681 <HInstruction>[isSubtype, typeArgument, representation]; | 2680 representationList]; |
| 2682 HInstruction call = new HInvokeStatic(inputs, HType.BOOLEAN); | 2681 push(new HInvokeStatic(inputs, HType.UNKNOWN)); |
| 2683 add(call); | 2682 } |
| 2684 checks.add(call); | 2683 |
| 2685 index++; | 2684 void classCheck() { push(new HIs(type, <HInstruction>[expression])); } |
| 2686 }); | 2685 |
| 2687 instruction = new HIs(type, <HInstruction>[expression]..addAll(checks)); | 2686 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); |
| 2687 branchBuilder.handleLogicalAndOr(classCheck, argumentsCheck, isAnd: true ); | |
| 2688 instruction = pop(); | |
| 2688 } else { | 2689 } else { |
| 2689 instruction = new HIs(type, <HInstruction>[expression]); | 2690 instruction = new HIs(type, <HInstruction>[expression]); |
| 2691 add(instruction); | |
| 2690 } | 2692 } |
| 2691 if (isNot) { | 2693 if (isNot) { |
| 2694 instruction = new HNot(instruction); | |
| 2692 add(instruction); | 2695 add(instruction); |
| 2693 instruction = new HNot(instruction); | |
| 2694 } | 2696 } |
| 2695 push(instruction); | 2697 stack.add(instruction); |
| 2696 } else if (const SourceString("as") == op.source) { | 2698 } else if (const SourceString("as") == op.source) { |
| 2697 visit(node.receiver); | 2699 visit(node.receiver); |
| 2698 HInstruction expression = pop(); | 2700 HInstruction expression = pop(); |
| 2699 Node argument = node.arguments.head; | 2701 Node argument = node.arguments.head; |
| 2700 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); | 2702 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); |
| 2701 DartType type = elements.getType(typeAnnotation); | 2703 DartType type = elements.getType(typeAnnotation); |
| 2702 HInstruction converted = expression.convertType( | 2704 HInstruction converted = expression.convertType( |
| 2703 compiler, type, HTypeConversion.CAST_TYPE_CHECK); | 2705 compiler, type, HTypeConversion.CAST_TYPE_CHECK); |
| 2704 if (converted != expression) add(converted); | 2706 if (converted != expression) add(converted); |
| 2705 stack.add(converted); | 2707 stack.add(converted); |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3023 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { | 3025 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { |
| 3024 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); | 3026 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); |
| 3025 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { | 3027 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { |
| 3026 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); | 3028 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); |
| 3027 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { | 3029 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { |
| 3028 handleForeignSetCurrentIsolate(node); | 3030 handleForeignSetCurrentIsolate(node); |
| 3029 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { | 3031 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { |
| 3030 handleForeignCreateIsolate(node); | 3032 handleForeignCreateIsolate(node); |
| 3031 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { | 3033 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { |
| 3032 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); | 3034 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); |
| 3035 } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) { | |
| 3036 stack.add(addConstantString(node, backend.namer.operatorAsPrefix())); | |
| 3033 } else { | 3037 } else { |
| 3034 throw "Unknown foreign: ${selector}"; | 3038 throw "Unknown foreign: ${selector}"; |
| 3035 } | 3039 } |
| 3036 } | 3040 } |
| 3037 | 3041 |
| 3038 generateSuperNoSuchMethodSend(Send node) { | 3042 generateSuperNoSuchMethodSend(Send node) { |
| 3039 Selector selector = elements.getSelector(node); | 3043 Selector selector = elements.getSelector(node); |
| 3040 SourceString name = selector.name; | 3044 SourceString name = selector.name; |
| 3041 | 3045 |
| 3042 ClassElement cls = currentElement.getEnclosingClass(); | 3046 ClassElement cls = currentElement.getEnclosingClass(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3142 */ | 3146 */ |
| 3143 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { | 3147 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { |
| 3144 assert(invariant(currentNode, | 3148 assert(invariant(currentNode, |
| 3145 !compiler.enableTypeAssertions || !argument.isMalformed, | 3149 !compiler.enableTypeAssertions || !argument.isMalformed, |
| 3146 message: '$argument is malformed in checked mode')); | 3150 message: '$argument is malformed in checked mode')); |
| 3147 if (argument == compiler.types.dynamicType || argument.isMalformed) { | 3151 if (argument == compiler.types.dynamicType || argument.isMalformed) { |
| 3148 // Represent [dynamic] as [null]. | 3152 // Represent [dynamic] as [null]. |
| 3149 return graph.addConstantNull(constantSystem); | 3153 return graph.addConstantNull(constantSystem); |
| 3150 } | 3154 } |
| 3151 | 3155 |
| 3152 // These variables are shared between invocations of the helper. | 3156 // The inputs are shared between invocations of the helper. |
| 3153 HInstruction typeInfo; | |
| 3154 List<HInstruction> inputs = <HInstruction>[]; | 3157 List<HInstruction> inputs = <HInstruction>[]; |
| 3155 | 3158 |
| 3156 /** | 3159 /** |
| 3157 * Helper to create an instruction that gets the value of a type variable. | 3160 * Helper to create an instruction that gets the value of a type variable. |
| 3158 */ | 3161 */ |
| 3159 void addTypeVariableReference(TypeVariableType type) { | 3162 String addTypeVariableReference(TypeVariableType type) { |
| 3160 Element member = currentElement; | 3163 Element member = currentElement; |
| 3161 if (member.enclosingElement.isClosure()) { | 3164 if (member.enclosingElement.isClosure()) { |
| 3162 ClosureClassElement closureClass = member.enclosingElement; | 3165 ClosureClassElement closureClass = member.enclosingElement; |
| 3163 member = closureClass.methodElement; | 3166 member = closureClass.methodElement; |
| 3164 member = member.getOutermostEnclosingMemberOrTopLevel(); | 3167 member = member.getOutermostEnclosingMemberOrTopLevel(); |
| 3165 } | 3168 } |
| 3166 if (member.isFactoryConstructor()) { | 3169 if (member.isFactoryConstructor()) { |
| 3167 // The type variable is stored in a parameter of the factory. | 3170 // The type variable is stored in a parameter of the method. |
| 3168 inputs.add(localsHandler.readLocal(type.element)); | 3171 inputs.add(localsHandler.readLocal(type.element)); |
| 3169 } else if (member.isInstanceMember() | 3172 } else if (member.isInstanceMember() || |
| 3170 || member.isGenerativeConstructor()) { | 3173 member.isGenerativeConstructor()) { |
| 3171 // The type variable is stored in [this]. | 3174 // The type variable is stored in [this]. |
| 3172 if (typeInfo == null) { | |
| 3173 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), | |
| 3174 localsHandler.readThis(), | |
| 3175 HType.UNKNOWN); | |
| 3176 typeInfo = pop(); | |
| 3177 } | |
| 3178 int index = RuntimeTypeInformation.getTypeVariableIndex(type); | 3175 int index = RuntimeTypeInformation.getTypeVariableIndex(type); |
| 3179 HInstruction foreign = createForeign('#[$index]', HType.STRING, | 3176 pushInvokeHelper2(backend.getGetRuntimeTypeArgument(), |
| 3180 <HInstruction>[typeInfo]); | 3177 localsHandler.readThis(), |
| 3181 add(foreign); | 3178 graph.addConstantInt(index, constantSystem), |
| 3182 inputs.add(foreign); | 3179 HType.UNKNOWN); |
| 3180 inputs.add(pop()); | |
| 3183 } else { | 3181 } else { |
| 3184 // TODO(ngeoffray): Match the VM behavior and throw an | 3182 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3185 // exception at runtime. | 3183 // exception at runtime. |
| 3186 compiler.cancel('Unimplemented unresolved type variable', | 3184 compiler.cancel('Unimplemented unresolved type variable', |
| 3187 node: currentNode); | 3185 node: currentNode); |
| 3188 } | 3186 } |
| 3189 } | 3187 } |
| 3190 | 3188 |
| 3191 String template = rti.getTypeRepresentation(argument, | 3189 String template = rti.getTypeRepresentation(argument, |
| 3192 addTypeVariableReference); | 3190 addTypeVariableReference); |
| 3193 HInstruction result = createForeign(template, HType.STRING, inputs); | 3191 HInstruction result = createForeign(template, HType.STRING, inputs); |
| 3194 add(result); | 3192 add(result); |
| 3195 return result; | 3193 return result; |
| 3196 } | 3194 } |
| 3197 | 3195 |
| 3198 void handleListConstructor(InterfaceType type, | 3196 void handleListConstructor(InterfaceType type, |
| 3199 Node currentNode, | 3197 Node currentNode, |
| 3200 HInstruction newObject) { | 3198 HInstruction newObject) { |
| 3201 if (!compiler.world.needsRti(type.element)) return; | 3199 if (!compiler.world.needsRti(type.element)) return; |
| 3202 List<HInstruction> inputs = <HInstruction>[]; | |
| 3203 if (!type.isRaw) { | 3200 if (!type.isRaw) { |
| 3201 List<HInstruction> inputs = <HInstruction>[]; | |
| 3204 type.typeArguments.forEach((DartType argument) { | 3202 type.typeArguments.forEach((DartType argument) { |
| 3205 inputs.add(analyzeTypeArgument(argument, currentNode)); | 3203 inputs.add(analyzeTypeArgument(argument, currentNode)); |
| 3206 }); | 3204 }); |
| 3205 callSetRuntimeTypeInfo(type.element, inputs, newObject); | |
| 3207 } | 3206 } |
| 3208 callSetRuntimeTypeInfo(type.element, inputs, newObject); | |
| 3209 } | 3207 } |
| 3210 | 3208 |
| 3211 void callSetRuntimeTypeInfo(ClassElement element, | 3209 void callSetRuntimeTypeInfo(ClassElement element, |
| 3212 List<HInstruction> rtiInputs, | 3210 List<HInstruction> rtiInputs, |
| 3213 HInstruction newObject) { | 3211 HInstruction newObject) { |
| 3214 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) { | 3212 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) { |
| 3215 return; | 3213 return; |
| 3216 } | 3214 } |
| 3217 | 3215 |
| 3218 HInstruction typeInfo = new HLiteralList(rtiInputs); | 3216 HInstruction typeInfo = new HLiteralList(rtiInputs); |
| (...skipping 1806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5025 new HSubGraphBlockInformation(elseBranch.graph)); | 5023 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5026 | 5024 |
| 5027 HBasicBlock conditionStartBlock = conditionBranch.block; | 5025 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5028 conditionStartBlock.setBlockFlow(info, joinBlock); | 5026 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5029 SubGraph conditionGraph = conditionBranch.graph; | 5027 SubGraph conditionGraph = conditionBranch.graph; |
| 5030 HIf branch = conditionGraph.end.last; | 5028 HIf branch = conditionGraph.end.last; |
| 5031 assert(branch is HIf); | 5029 assert(branch is HIf); |
| 5032 branch.blockInformation = conditionStartBlock.blockFlow; | 5030 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5033 } | 5031 } |
| 5034 } | 5032 } |
| OLD | NEW |