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

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: Removed obsolete function. 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.
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698