Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(350)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 12218007: Implement substitution for type variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698