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

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

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

Powered by Google App Engine
This is Rietveld 408576698