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. |
| 11 */ | 11 */ |
| 12 class InterceptedElement extends ElementX { | 12 class InterceptedElement extends ElementX { |
| 13 final HType ssaType; | 13 final HType ssaType; |
| 14 InterceptedElement(this.ssaType, Element enclosing) | 14 InterceptedElement(this.ssaType, Element enclosing) |
| 15 : super(const SourceString('receiver'), | 15 : super(const SourceString('receiver'), |
| 16 ElementKind.PARAMETER, | 16 ElementKind.PARAMETER, |
| 17 enclosing); | 17 enclosing); |
| 18 | 18 |
| 19 DartType computeType(Compiler compiler) => ssaType.computeType(compiler); | 19 DartType computeType(Compiler compiler) => ssaType.computeType(compiler); |
| 20 } | 20 } |
| 21 | 21 |
| 22 | |
|
kasperl
2013/01/29 15:02:34
wat
karlklose
2013/01/30 12:01:19
Exactly. Removed.
| |
| 22 class SsaBuilderTask extends CompilerTask { | 23 class SsaBuilderTask extends CompilerTask { |
| 23 final CodeEmitterTask emitter; | 24 final CodeEmitterTask emitter; |
| 24 // Loop tracking information. | 25 // Loop tracking information. |
| 25 final Set<FunctionElement> functionsCalledInLoop; | 26 final Set<FunctionElement> functionsCalledInLoop; |
| 26 final Map<SourceString, Selector> selectorsCalledInLoop; | 27 final Map<SourceString, Selector> selectorsCalledInLoop; |
| 27 final JavaScriptBackend backend; | 28 final JavaScriptBackend backend; |
| 28 | 29 |
| 29 String get name => 'SSA builder'; | 30 String get name => 'SSA builder'; |
| 30 | 31 |
| 31 SsaBuilderTask(JavaScriptBackend backend) | 32 SsaBuilderTask(JavaScriptBackend backend) |
| (...skipping 2510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2542 } else { | 2543 } else { |
| 2543 assert(type.element.isClass()); | 2544 assert(type.element.isClass()); |
| 2544 List<HInstruction> arguments = <HInstruction>[]; | 2545 List<HInstruction> arguments = <HInstruction>[]; |
| 2545 InterfaceType interface = type; | 2546 InterfaceType interface = type; |
| 2546 for (DartType argument in interface.typeArguments) { | 2547 for (DartType argument in interface.typeArguments) { |
| 2547 List<HInstruction> inputs = <HInstruction>[]; | 2548 List<HInstruction> inputs = <HInstruction>[]; |
| 2548 String template = rti.getTypeRepresentation(argument, (variable) { | 2549 String template = rti.getTypeRepresentation(argument, (variable) { |
| 2549 HInstruction runtimeType = getTypeArgument(variable); | 2550 HInstruction runtimeType = getTypeArgument(variable); |
| 2550 add(runtimeType); | 2551 add(runtimeType); |
| 2551 inputs.add(runtimeType); | 2552 inputs.add(runtimeType); |
| 2553 return '#'; | |
|
kasperl
2013/01/29 15:02:34
wat? This isn't a List<HInstruction>.
karlklose
2013/01/30 12:01:19
This return belongs to the closure given to getTyp
| |
| 2552 }); | 2554 }); |
| 2553 HInstruction representation = createForeignArray(template, inputs); | 2555 HInstruction representation = createForeignArray(template, inputs); |
| 2554 add(representation); | 2556 add(representation); |
| 2555 arguments.add(representation); | 2557 arguments.add(representation); |
| 2556 } | 2558 } |
| 2557 return arguments; | 2559 return arguments; |
| 2558 } | 2560 } |
| 2559 } | 2561 } |
| 2560 | 2562 |
| 2561 visitOperatorSend(node) { | 2563 visitOperatorSend(node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2595 // TODO(karlklose): remove this check when the backend can deal with | 2597 // TODO(karlklose): remove this check when the backend can deal with |
| 2596 // checks of the form [:o is T:] where [:T:] is a type variable. | 2598 // checks of the form [:o is T:] where [:T:] is a type variable. |
| 2597 stack.add(graph.addConstantBool(true, constantSystem)); | 2599 stack.add(graph.addConstantBool(true, constantSystem)); |
| 2598 return; | 2600 return; |
| 2599 } | 2601 } |
| 2600 | 2602 |
| 2601 HInstruction instruction; | 2603 HInstruction instruction; |
| 2602 if (type.element.isTypeVariable() || | 2604 if (type.element.isTypeVariable() || |
| 2603 RuntimeTypeInformation.hasTypeArguments(type)) { | 2605 RuntimeTypeInformation.hasTypeArguments(type)) { |
| 2604 HInstruction typeInfo = getRuntimeTypeInfo(expression); | 2606 HInstruction typeInfo = getRuntimeTypeInfo(expression); |
| 2605 // TODO(karlklose): make isSubtype a HInstruction to enable | 2607 Element helper = |
| 2606 // optimizations? | 2608 compiler.findHelper(const SourceString('checkArguments')); |
| 2607 Element helper = compiler.findHelper(const SourceString('isSubtype')); | 2609 HInstruction helperCall = new HStatic(helper); |
| 2608 HInstruction isSubtype = new HStatic(helper); | 2610 add(helperCall); |
| 2609 add(isSubtype); | |
| 2610 // Build a list of representations for the type arguments. | |
| 2611 List<HInstruction> representations = | 2611 List<HInstruction> representations = |
| 2612 buildTypeArgumentRepresentations(type); | 2612 buildTypeArgumentRepresentations(type); |
| 2613 // For each type argument, build a call to isSubtype, with the type | 2613 String substitution = backend.namer.substitutionName(type.element); |
| 2614 // argument as first and the representation of the tested type as | 2614 HInstruction fieldGet = |
| 2615 // second argument. | 2615 createForeign('#.$substitution', 'Object', [expression]); |
|
kasperl
2013/01/29 15:02:34
Should the namer know about $substitution?
karlklose
2013/01/30 12:01:19
It does, this is interpolating the name that we go
| |
| 2616 List<HInstruction> checks = <HInstruction>[]; | 2616 HInstruction representationList = new HLiteralList(representations); |
| 2617 int index = 0; | 2617 add(fieldGet); |
| 2618 representations.forEach((HInstruction representation) { | 2618 add(representationList); |
| 2619 HInstruction position = graph.addConstantInt(index, constantSystem); | 2619 List<HInstruction> inputs = <HInstruction>[helperCall, |
| 2620 // Get the index'th type argument from the runtime type information. | 2620 fieldGet, |
| 2621 HInstruction typeArgument = | 2621 typeInfo, |
| 2622 createForeign('#[#]', 'Object', [typeInfo, position]); | 2622 representationList]; |
| 2623 add(typeArgument); | 2623 HInstruction check = new HInvokeStatic(inputs); |
| 2624 // Create the call to isSubtype. | 2624 add(check); |
| 2625 List<HInstruction> inputs = | 2625 instruction = new HIs(type, <HInstruction>[expression, check]); |
| 2626 <HInstruction>[isSubtype, typeArgument, representation]; | |
| 2627 HInstruction call = new HInvokeStatic(inputs); | |
| 2628 add(call); | |
| 2629 checks.add(call); | |
| 2630 index++; | |
| 2631 }); | |
| 2632 instruction = new HIs(type, <HInstruction>[expression]..addAll(checks)); | |
| 2633 } else { | 2626 } else { |
| 2634 instruction = new HIs(type, <HInstruction>[expression]); | 2627 instruction = new HIs(type, <HInstruction>[expression]); |
| 2635 } | 2628 } |
| 2636 if (isNot) { | 2629 if (isNot) { |
| 2637 add(instruction); | 2630 add(instruction); |
| 2638 instruction = new HNot(instruction); | 2631 instruction = new HNot(instruction); |
| 2639 } | 2632 } |
| 2640 push(instruction); | 2633 push(instruction); |
| 2641 } else if (const SourceString("as") == op.source) { | 2634 } else if (const SourceString("as") == op.source) { |
| 2642 visit(node.receiver); | 2635 visit(node.receiver); |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2998 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { | 2991 } else if (name == const SourceString('DART_CLOSURE_TO_JS')) { |
| 2999 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); | 2992 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); |
| 3000 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { | 2993 } else if (name == const SourceString('RAW_DART_FUNCTION_REF')) { |
| 3001 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); | 2994 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); |
| 3002 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { | 2995 } else if (name == const SourceString('JS_SET_CURRENT_ISOLATE')) { |
| 3003 handleForeignSetCurrentIsolate(node); | 2996 handleForeignSetCurrentIsolate(node); |
| 3004 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { | 2997 } else if (name == const SourceString('JS_CREATE_ISOLATE')) { |
| 3005 handleForeignCreateIsolate(node); | 2998 handleForeignCreateIsolate(node); |
| 3006 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { | 2999 } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) { |
| 3007 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); | 3000 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); |
| 3001 } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) { | |
| 3002 stack.add(addConstantString(node, backend.namer.operatorAsPrefix())); | |
| 3008 } else { | 3003 } else { |
| 3009 throw "Unknown foreign: ${selector}"; | 3004 throw "Unknown foreign: ${selector}"; |
| 3010 } | 3005 } |
| 3011 } | 3006 } |
| 3012 | 3007 |
| 3013 generateSuperNoSuchMethodSend(Send node) { | 3008 generateSuperNoSuchMethodSend(Send node) { |
| 3014 Selector selector = elements.getSelector(node); | 3009 Selector selector = elements.getSelector(node); |
| 3015 SourceString name = selector.name; | 3010 SourceString name = selector.name; |
| 3016 | 3011 |
| 3017 ClassElement cls = work.element.getEnclosingClass(); | 3012 ClassElement cls = work.element.getEnclosingClass(); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3116 */ | 3111 */ |
| 3117 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { | 3112 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { |
| 3118 assert(invariant(currentNode, | 3113 assert(invariant(currentNode, |
| 3119 !compiler.enableTypeAssertions || !argument.isMalformed, | 3114 !compiler.enableTypeAssertions || !argument.isMalformed, |
| 3120 message: '$argument is malformed in checked mode')); | 3115 message: '$argument is malformed in checked mode')); |
| 3121 if (argument == compiler.types.dynamicType || argument.isMalformed) { | 3116 if (argument == compiler.types.dynamicType || argument.isMalformed) { |
| 3122 // Represent [dynamic] as [null]. | 3117 // Represent [dynamic] as [null]. |
| 3123 return graph.addConstantNull(constantSystem); | 3118 return graph.addConstantNull(constantSystem); |
| 3124 } | 3119 } |
| 3125 | 3120 |
| 3126 // These variables are shared between invocations of the helper. | 3121 // The inputs are shared between invocations of the helper. |
| 3127 HInstruction typeInfo; | |
| 3128 List<HInstruction> inputs = <HInstruction>[]; | 3122 List<HInstruction> inputs = <HInstruction>[]; |
| 3129 | 3123 |
| 3130 /** | 3124 /** |
| 3131 * Helper to create an instruction that gets the value of a type variable. | 3125 * Helper to create an instruction that gets the value of a type variable. |
| 3132 */ | 3126 */ |
| 3133 void addTypeVariableReference(TypeVariableType type) { | 3127 String addTypeVariableReference(TypeVariableType type) { |
| 3134 Element member = work.element; | 3128 Element member = work.element; |
| 3135 if (member.enclosingElement.isClosure()) { | 3129 if (member.enclosingElement.isClosure()) { |
| 3136 ClosureClassElement closureClass = member.enclosingElement; | 3130 ClosureClassElement closureClass = member.enclosingElement; |
| 3137 member = closureClass.methodElement; | 3131 member = closureClass.methodElement; |
| 3138 member = member.getOutermostEnclosingMemberOrTopLevel(); | 3132 member = member.getOutermostEnclosingMemberOrTopLevel(); |
| 3139 } | 3133 } |
| 3140 if (member.isFactoryConstructor()) { | 3134 if (member.isFactoryConstructor()) { |
| 3141 // The type variable is stored in a parameter of the factory. | 3135 // The type variable is stored in a parameter of the method. |
| 3142 inputs.add(localsHandler.readLocal(type.element)); | 3136 inputs.add(localsHandler.readLocal(type.element)); |
| 3143 } else if (member.isInstanceMember() | 3137 } else if (member.isInstanceMember() || |
| 3144 || member.isGenerativeConstructor()) { | 3138 member.isGenerativeConstructor()) { |
| 3145 // The type variable is stored in [this]. | 3139 // The type variable is stored in [this]. |
| 3146 if (typeInfo == null) { | |
| 3147 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), | |
| 3148 localsHandler.readThis()); | |
| 3149 typeInfo = pop(); | |
| 3150 } | |
| 3151 int index = RuntimeTypeInformation.getTypeVariableIndex(type); | 3140 int index = RuntimeTypeInformation.getTypeVariableIndex(type); |
| 3152 HInstruction foreign = createForeign('#[$index]', 'String', | 3141 pushInvokeHelper2(backend.getGetRuntimeTypeArgument(), |
| 3153 <HInstruction>[typeInfo]); | 3142 localsHandler.readThis(), |
| 3154 add(foreign); | 3143 graph.addConstantInt(index, constantSystem)); |
| 3155 inputs.add(foreign); | 3144 inputs.add(pop()); |
| 3156 } else { | 3145 } else { |
| 3157 // TODO(ngeoffray): Match the VM behavior and throw an | 3146 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3158 // exception at runtime. | 3147 // exception at runtime. |
| 3159 compiler.cancel('Unimplemented unresolved type variable', | 3148 compiler.cancel('Unimplemented unresolved type variable', |
| 3160 node: currentNode); | 3149 node: currentNode); |
| 3161 } | 3150 } |
| 3151 return '#'; | |
| 3162 } | 3152 } |
| 3163 | 3153 |
| 3164 String template = rti.getTypeRepresentation(argument, | 3154 String template = rti.getTypeRepresentation(argument, |
| 3165 addTypeVariableReference); | 3155 addTypeVariableReference); |
| 3166 HInstruction result = createForeign(template, 'String', inputs); | 3156 HInstruction result = createForeign(template, 'String', inputs); |
| 3167 add(result); | 3157 add(result); |
| 3168 return result; | 3158 return result; |
| 3169 } | 3159 } |
| 3170 | 3160 |
| 3171 void handleListConstructor(InterfaceType type, | 3161 void handleListConstructor(InterfaceType type, |
| 3172 Node currentNode, | 3162 Node currentNode, |
| 3173 HInstruction newObject) { | 3163 HInstruction newObject) { |
| 3174 if (!compiler.world.needsRti(type.element)) return; | 3164 if (!compiler.world.needsRti(type.element)) return; |
| 3175 List<HInstruction> inputs = <HInstruction>[]; | |
| 3176 if (!type.isRaw) { | 3165 if (!type.isRaw) { |
| 3166 List<HInstruction> inputs = <HInstruction>[]; | |
| 3177 type.typeArguments.forEach((DartType argument) { | 3167 type.typeArguments.forEach((DartType argument) { |
| 3178 inputs.add(analyzeTypeArgument(argument, currentNode)); | 3168 inputs.add(analyzeTypeArgument(argument, currentNode)); |
| 3179 }); | 3169 }); |
| 3170 callSetRuntimeTypeInfo(type.element, inputs, newObject); | |
| 3180 } | 3171 } |
| 3181 callSetRuntimeTypeInfo(type.element, inputs, newObject); | |
| 3182 } | 3172 } |
| 3183 | 3173 |
| 3184 void callSetRuntimeTypeInfo(ClassElement element, | 3174 void callSetRuntimeTypeInfo(ClassElement element, |
| 3185 List<HInstruction> rtiInputs, | 3175 List<HInstruction> rtiInputs, |
| 3186 HInstruction newObject) { | 3176 HInstruction newObject) { |
| 3187 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) { | 3177 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) { |
| 3188 return; | 3178 return; |
| 3189 } | 3179 } |
| 3190 | 3180 |
| 3191 HInstruction typeInfo = new HLiteralList(rtiInputs); | 3181 HInstruction typeInfo = new HLiteralList(rtiInputs); |
| (...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4951 new HSubGraphBlockInformation(elseBranch.graph)); | 4941 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4952 | 4942 |
| 4953 HBasicBlock conditionStartBlock = conditionBranch.block; | 4943 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4954 conditionStartBlock.setBlockFlow(info, joinBlock); | 4944 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4955 SubGraph conditionGraph = conditionBranch.graph; | 4945 SubGraph conditionGraph = conditionBranch.graph; |
| 4956 HIf branch = conditionGraph.end.last; | 4946 HIf branch = conditionGraph.end.last; |
| 4957 assert(branch is HIf); | 4947 assert(branch is HIf); |
| 4958 branch.blockInformation = conditionStartBlock.blockFlow; | 4948 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4959 } | 4949 } |
| 4960 } | 4950 } |
| OLD | NEW |