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

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

Issue 11360228: Simplify runtime type support. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years 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 2554 matching lines...) Expand 10 before | Expand all | Expand 10 after
2565 stack.add(checked); 2565 stack.add(checked);
2566 } 2566 }
2567 localsHandler.updateLocal(element, checked); 2567 localsHandler.updateLocal(element, checked);
2568 } 2568 }
2569 } 2569 }
2570 2570
2571 void pushInvokeInterceptor(Element element, HInstruction receiver) { 2571 void pushInvokeInterceptor(Element element, HInstruction receiver) {
2572 HInstruction interceptor = new HStatic(element); 2572 HInstruction interceptor = new HStatic(element);
2573 add(interceptor); 2573 add(interceptor);
2574 List<HInstruction> inputs = <HInstruction>[interceptor, receiver]; 2574 List<HInstruction> inputs = <HInstruction>[interceptor, receiver];
2575 HInstruction result = new HInvokeStatic(inputs); 2575 HInvokeStatic result = new HInvokeStatic(inputs);
2576 result.isSideEffectFree = true; 2576 result.isSideEffectFree = true;
2577 push(result); 2577 push(result);
2578 } 2578 }
2579 2579
2580 void pushInvokeHelper0(Element helper) { 2580 void pushInvokeHelper0(Element helper) {
2581 HInstruction reference = new HStatic(helper); 2581 HInstruction reference = new HStatic(helper);
2582 add(reference); 2582 add(reference);
2583 List<HInstruction> inputs = <HInstruction>[reference]; 2583 List<HInstruction> inputs = <HInstruction>[reference];
2584 HInstruction result = new HInvokeStatic(inputs); 2584 HInstruction result = new HInvokeStatic(inputs);
2585 push(result); 2585 push(result);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2650 bool isNot = false; 2650 bool isNot = false;
2651 // TODO(ngeoffray): Duplicating pattern in resolver. We should 2651 // TODO(ngeoffray): Duplicating pattern in resolver. We should
2652 // add a new kind of node. 2652 // add a new kind of node.
2653 if (typeAnnotation == null) { 2653 if (typeAnnotation == null) {
2654 typeAnnotation = argument.asSend().receiver; 2654 typeAnnotation = argument.asSend().receiver;
2655 isNot = true; 2655 isNot = true;
2656 } 2656 }
2657 2657
2658 DartType type = elements.getType(typeAnnotation); 2658 DartType type = elements.getType(typeAnnotation);
2659 HInstruction typeInfo = null; 2659 HInstruction typeInfo = null;
2660 if (rti.hasTypeArguments(type)) { 2660 if (RuntimeTypeInformation.hasTypeArguments(type)) {
2661 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); 2661 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression);
2662 typeInfo = pop(); 2662 typeInfo = pop();
2663 } 2663 }
2664 if (type.element.isTypeVariable()) { 2664 if (type.element.isTypeVariable()) {
2665 // TODO(karlklose): We currently answer true to any is check 2665 // TODO(karlklose): We currently answer true to any is check
2666 // involving a type variable -- both is T and is !T -- until 2666 // involving a type variable -- both is T and is !T -- until
2667 // we have a proper implementation of reified generics. 2667 // we have a proper implementation of reified generics.
2668 stack.add(graph.addConstantBool(true, constantSystem)); 2668 stack.add(graph.addConstantBool(true, constantSystem));
2669 } else { 2669 } else {
2670 HInstruction instruction; 2670 HInstruction instruction;
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
3104 // The type variable is stored in a parameter of the factory. 3104 // The type variable is stored in a parameter of the factory.
3105 inputs.add(localsHandler.readLocal(type.element)); 3105 inputs.add(localsHandler.readLocal(type.element));
3106 } else if (member.isInstanceMember() 3106 } else if (member.isInstanceMember()
3107 || member.isGenerativeConstructor()) { 3107 || member.isGenerativeConstructor()) {
3108 // The type variable is stored in [this]. 3108 // The type variable is stored in [this].
3109 if (typeInfo == null) { 3109 if (typeInfo == null) {
3110 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), 3110 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(),
3111 localsHandler.readThis()); 3111 localsHandler.readThis());
3112 typeInfo = pop(); 3112 typeInfo = pop();
3113 } 3113 }
3114 int index = RuntimeTypeInformation.getTypeVariableIndex(type);
3114 HInstruction foreign = new HForeign( 3115 HInstruction foreign = new HForeign(
3115 new LiteralDartString('#.${type.name.slowToString()}'), 3116 new LiteralDartString('#[$index]'),
3116 new LiteralDartString('String'), 3117 new LiteralDartString('String'),
3117 <HInstruction>[typeInfo]); 3118 <HInstruction>[typeInfo]);
3118 add(foreign); 3119 add(foreign);
3119 inputs.add(foreign); 3120 inputs.add(foreign);
3120 } else { 3121 } else {
3121 // TODO(ngeoffray): Match the VM behavior and throw an 3122 // TODO(ngeoffray): Match the VM behavior and throw an
3122 // exception at runtime. 3123 // exception at runtime.
3123 compiler.cancel('Unimplemented unresolved type variable', 3124 compiler.cancel('Unimplemented unresolved type variable',
3124 node: currentNode); 3125 node: currentNode);
3125 } 3126 }
(...skipping 12 matching lines...) Expand all
3138 */ 3139 */
3139 void buildTypeString(DartType type, {isInQuotes: false}) { 3140 void buildTypeString(DartType type, {isInQuotes: false}) {
3140 if (type is TypeVariableType) { 3141 if (type is TypeVariableType) {
3141 addTypeVariableReference(type); 3142 addTypeVariableReference(type);
3142 template.add(isInQuotes ? "' + # +'" : "#"); 3143 template.add(isInQuotes ? "' + # +'" : "#");
3143 } else if (type is InterfaceType) { 3144 } else if (type is InterfaceType) {
3144 bool isFirstVariable = true; 3145 bool isFirstVariable = true;
3145 InterfaceType interfaceType = type; 3146 InterfaceType interfaceType = type;
3146 bool hasTypeArguments = !interfaceType.arguments.isEmpty; 3147 bool hasTypeArguments = !interfaceType.arguments.isEmpty;
3147 if (!isInQuotes) template.add("'"); 3148 if (!isInQuotes) template.add("'");
3148 template.add(rti.getName(type.element)); 3149 template.add(backend.namer.getName(type.element));
3149 if (hasTypeArguments) { 3150 if (hasTypeArguments) {
3150 template.add("<"); 3151 template.add("<");
3151 for (DartType argument in interfaceType.arguments) { 3152 for (DartType argument in interfaceType.arguments) {
3152 if (!isFirstVariable) { 3153 if (!isFirstVariable) {
3153 template.add(", "); 3154 template.add(", ");
3154 } else { 3155 } else {
3155 isFirstVariable = false; 3156 isFirstVariable = false;
3156 } 3157 }
3157 buildTypeString(argument, isInQuotes: true); 3158 buildTypeString(argument, isInQuotes: true);
3158 } 3159 }
3159 template.add(">"); 3160 template.add(">");
3160 } 3161 }
3161 if (!isInQuotes) template.add("'"); 3162 if (!isInQuotes) template.add("'");
3162 } else { 3163 } else {
3163 assert(type is TypedefType); 3164 assert(type is TypedefType);
3164 if (!isInQuotes) template.add("'"); 3165 if (!isInQuotes) template.add("'");
3165 template.add(rti.getName(argument.element)); 3166 template.add(backend.namer.getName(argument.element));
3166 if (!isInQuotes) template.add("'"); 3167 if (!isInQuotes) template.add("'");
3167 } 3168 }
3168 } 3169 }
3169 3170
3170 buildTypeString(argument, isInQuotes: false); 3171 buildTypeString(argument, isInQuotes: false);
3171 HInstruction result = 3172 HInstruction result =
3172 new HForeign(new LiteralDartString("$template"), 3173 new HForeign(new LiteralDartString("$template"),
3173 new LiteralDartString('String'), 3174 new LiteralDartString('String'),
3174 inputs); 3175 inputs);
3175 add(result); 3176 add(result);
3176 return result; 3177 return result;
3177 } 3178 }
3178 3179
3179 void handleListConstructor(InterfaceType type, 3180 void handleListConstructor(InterfaceType type,
3180 Node currentNode, 3181 Node currentNode,
3181 HInstruction newObject) { 3182 HInstruction newObject) {
3182 if (!compiler.world.needsRti(type.element)) return; 3183 if (!compiler.world.needsRti(type.element)) return;
3183 List<HInstruction> inputs = <HInstruction>[]; 3184 List<HInstruction> inputs = <HInstruction>[];
3184 type.arguments.forEach((DartType argument) { 3185 type.arguments.forEach((DartType argument) {
3185 inputs.add(analyzeTypeArgument(argument, currentNode)); 3186 inputs.add(analyzeTypeArgument(argument, currentNode));
3186 }); 3187 });
3187 callSetRuntimeTypeInfo(type.element, inputs, newObject); 3188 callSetRuntimeTypeInfo(type.element, inputs, newObject);
3188 } 3189 }
3189 3190
3190 void callSetRuntimeTypeInfo(ClassElement element, 3191 void callSetRuntimeTypeInfo(ClassElement element,
3191 List<HInstruction> rtiInputs, 3192 List<HInstruction> rtiInputs,
3192 HInstruction newObject) { 3193 HInstruction newObject) {
3193 bool needsRti = compiler.world.needsRti(element) && !rtiInputs.isEmpty; 3194 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) {
3194 bool runtimeTypeIsUsed = compiler.enabledRuntimeType; 3195 return;
3195 if (!needsRti && !runtimeTypeIsUsed) return;
3196
3197 HInstruction createForeign(String template,
3198 List<HInstruction> arguments,
3199 [String type = 'String']) {
3200 return new HForeign(new LiteralDartString(template),
3201 new LiteralDartString(type),
3202 arguments);
3203 } 3196 }
3204 3197
3205 // Construct the runtime type information. 3198 HInstruction typeInfo = new HLiteralList(rtiInputs);
3206 StringBuffer runtimeCode = new StringBuffer(); 3199 add(typeInfo);
3207 List<HInstruction> runtimeCodeInputs = <HInstruction>[];
3208 if (runtimeTypeIsUsed) {
3209 String runtimeTypeString =
3210 rti.generateRuntimeTypeString(element, rtiInputs.length);
3211 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs);
3212 add(runtimeType);
3213 runtimeCodeInputs.add(runtimeType);
3214 runtimeCode.add("runtimeType: '#'");
3215 }
3216 if (needsRti) {
3217 if (runtimeTypeIsUsed) runtimeCode.add(', ');
3218 String typeVariablesString =
3219 RuntimeTypeInformation.generateTypeVariableString(element,
3220 rtiInputs.length);
3221 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs);
3222 add(typeInfo);
3223 runtimeCodeInputs.add(typeInfo);
3224 runtimeCode.add('#');
3225 }
3226 HInstruction runtimeInfo =
3227 createForeign("{$runtimeCode}", runtimeCodeInputs, 'Object');
3228 add(runtimeInfo);
3229 3200
3230 // Set the runtime type information on the object. 3201 // Set the runtime type information on the object.
3231 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo(); 3202 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo();
3232 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement); 3203 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement);
3233 add(typeInfoSetter); 3204 add(typeInfoSetter);
3234 add(new HInvokeStatic( 3205 add(new HInvokeStatic(
3235 <HInstruction>[typeInfoSetter, newObject, runtimeInfo])); 3206 <HInstruction>[typeInfoSetter, newObject, typeInfo]));
3236 } 3207 }
3237 3208
3238 visitNewSend(Send node, InterfaceType type) { 3209 visitNewSend(Send node, InterfaceType type) {
3239 bool isListConstructor = false; 3210 bool isListConstructor = false;
3240 computeType(element) { 3211 computeType(element) {
3241 Element originalElement = elements[node]; 3212 Element originalElement = elements[node];
3242 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) { 3213 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) {
3243 isListConstructor = true; 3214 isListConstructor = true;
3244 if (node.arguments.isEmpty) { 3215 if (node.arguments.isEmpty) {
3245 return HType.EXTENDABLE_ARRAY; 3216 return HType.EXTENDABLE_ARRAY;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3280 if (constructor.getEnclosingClass().isAbstract(compiler) && 3251 if (constructor.getEnclosingClass().isAbstract(compiler) &&
3281 constructor.isGenerativeConstructor()) { 3252 constructor.isGenerativeConstructor()) {
3282 generateAbstractClassInstantiationError(node, type.name.slowToString()); 3253 generateAbstractClassInstantiationError(node, type.name.slowToString());
3283 return; 3254 return;
3284 } 3255 }
3285 if (compiler.world.needsRti(constructor.enclosingElement)) { 3256 if (compiler.world.needsRti(constructor.enclosingElement)) {
3286 if (!type.arguments.isEmpty) { 3257 if (!type.arguments.isEmpty) {
3287 type.arguments.forEach((DartType argument) { 3258 type.arguments.forEach((DartType argument) {
3288 inputs.add(analyzeTypeArgument(argument, node)); 3259 inputs.add(analyzeTypeArgument(argument, node));
3289 }); 3260 });
3290 } else if (compiler.enabledRuntimeType) {
3291 Link<DartType> variables =
3292 constructor.getEnclosingClass().typeVariables;
3293 if (!variables.isEmpty) {
3294 // If the class has type variables but no type arguments have been
3295 // provided, add [:dynamic:] as argument for all type variables.
3296 DartString stringDynamic = new DartString.literal('dynamic');
3297 HInstruction input = graph.addConstantString(stringDynamic,
3298 node,
3299 constantSystem);
3300 variables.forEach((_) => inputs.add(input));
3301 }
3302 } 3261 }
3303 } 3262 }
3304 3263
3305 HType elementType = computeType(constructor); 3264 HType elementType = computeType(constructor);
3306 HInstruction newInstance = new HInvokeStatic(inputs, elementType); 3265 HInstruction newInstance = new HInvokeStatic(inputs, elementType);
3307 pushWithPosition(newInstance, node); 3266 pushWithPosition(newInstance, node);
3308 3267
3309 // The List constructor forwards to a Dart static method that does 3268 // The List constructor forwards to a Dart static method that does
3310 // not know about the type argument. Therefore we special case 3269 // not know about the type argument. Therefore we special case
3311 // this constructor to have the setRuntimeTypeInfo called where 3270 // this constructor to have the setRuntimeTypeInfo called where
(...skipping 1647 matching lines...) Expand 10 before | Expand all | Expand 10 after
4959 new HSubGraphBlockInformation(elseBranch.graph)); 4918 new HSubGraphBlockInformation(elseBranch.graph));
4960 4919
4961 HBasicBlock conditionStartBlock = conditionBranch.block; 4920 HBasicBlock conditionStartBlock = conditionBranch.block;
4962 conditionStartBlock.setBlockFlow(info, joinBlock); 4921 conditionStartBlock.setBlockFlow(info, joinBlock);
4963 SubGraph conditionGraph = conditionBranch.graph; 4922 SubGraph conditionGraph = conditionBranch.graph;
4964 HIf branch = conditionGraph.end.last; 4923 HIf branch = conditionGraph.end.last;
4965 assert(branch is HIf); 4924 assert(branch is HIf);
4966 branch.blockInformation = conditionStartBlock.blockFlow; 4925 branch.blockInformation = conditionStartBlock.blockFlow;
4967 } 4926 }
4968 } 4927 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698