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

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: Address review comments. Created 8 years, 1 month 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 class Interceptors { 7 class Interceptors {
8 Compiler compiler; 8 Compiler compiler;
9 Interceptors(Compiler this.compiler); 9 Interceptors(Compiler this.compiler);
10 10
(...skipping 2504 matching lines...) Expand 10 before | Expand all | Expand 10 after
2515 bool isNot = false; 2515 bool isNot = false;
2516 // TODO(ngeoffray): Duplicating pattern in resolver. We should 2516 // TODO(ngeoffray): Duplicating pattern in resolver. We should
2517 // add a new kind of node. 2517 // add a new kind of node.
2518 if (typeAnnotation == null) { 2518 if (typeAnnotation == null) {
2519 typeAnnotation = argument.asSend().receiver; 2519 typeAnnotation = argument.asSend().receiver;
2520 isNot = true; 2520 isNot = true;
2521 } 2521 }
2522 2522
2523 DartType type = elements.getType(typeAnnotation); 2523 DartType type = elements.getType(typeAnnotation);
2524 HInstruction typeInfo = null; 2524 HInstruction typeInfo = null;
2525 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { 2525 if (RuntimeTypeInformation.hasTypeArguments(type)) {
2526 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); 2526 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression);
2527 typeInfo = pop(); 2527 typeInfo = pop();
2528 } 2528 }
2529 if (type.element.isTypeVariable()) { 2529 if (type.element.isTypeVariable()) {
2530 // TODO(karlklose): We currently answer true to any is check 2530 // TODO(karlklose): We currently answer true to any is check
2531 // involving a type variable -- both is T and is !T -- until 2531 // involving a type variable -- both is T and is !T -- until
2532 // we have a proper implementation of reified generics. 2532 // we have a proper implementation of reified generics.
2533 stack.add(graph.addConstantBool(true, constantSystem)); 2533 stack.add(graph.addConstantBool(true, constantSystem));
2534 } else { 2534 } else {
2535 HInstruction instruction; 2535 HInstruction instruction;
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
2985 // The type variable is stored in a parameter of the factory. 2985 // The type variable is stored in a parameter of the factory.
2986 inputs.add(localsHandler.readLocal(type.element)); 2986 inputs.add(localsHandler.readLocal(type.element));
2987 } else if (member.isInstanceMember() 2987 } else if (member.isInstanceMember()
2988 || member.isGenerativeConstructor()) { 2988 || member.isGenerativeConstructor()) {
2989 // The type variable is stored in [this]. 2989 // The type variable is stored in [this].
2990 if (typeInfo == null) { 2990 if (typeInfo == null) {
2991 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), 2991 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(),
2992 localsHandler.readThis()); 2992 localsHandler.readThis());
2993 typeInfo = pop(); 2993 typeInfo = pop();
2994 } 2994 }
2995 int index = RuntimeTypeInformation.getTypeVariableIndex(type);
2995 HInstruction foreign = new HForeign( 2996 HInstruction foreign = new HForeign(
2996 new LiteralDartString('#.${type.name.slowToString()}'), 2997 new LiteralDartString('#[$index]'),
2997 new LiteralDartString('String'), 2998 new LiteralDartString('String'),
2998 <HInstruction>[typeInfo]); 2999 <HInstruction>[typeInfo]);
2999 add(foreign); 3000 add(foreign);
3000 inputs.add(foreign); 3001 inputs.add(foreign);
3001 } else { 3002 } else {
3002 // TODO(ngeoffray): Match the VM behavior and throw an 3003 // TODO(ngeoffray): Match the VM behavior and throw an
3003 // exception at runtime. 3004 // exception at runtime.
3004 compiler.cancel('Unimplemented unresolved type variable', 3005 compiler.cancel('Unimplemented unresolved type variable',
3005 node: currentNode); 3006 node: currentNode);
3006 } 3007 }
(...skipping 12 matching lines...) Expand all
3019 */ 3020 */
3020 void buildTypeString(DartType type, {isInQuotes: false}) { 3021 void buildTypeString(DartType type, {isInQuotes: false}) {
3021 if (type is TypeVariableType) { 3022 if (type is TypeVariableType) {
3022 addTypeVariableReference(type); 3023 addTypeVariableReference(type);
3023 template.add(isInQuotes ? "' + # +'" : "#"); 3024 template.add(isInQuotes ? "' + # +'" : "#");
3024 } else if (type is InterfaceType) { 3025 } else if (type is InterfaceType) {
3025 bool isFirstVariable = true; 3026 bool isFirstVariable = true;
3026 InterfaceType interfaceType = type; 3027 InterfaceType interfaceType = type;
3027 bool hasTypeArguments = !interfaceType.arguments.isEmpty; 3028 bool hasTypeArguments = !interfaceType.arguments.isEmpty;
3028 if (!isInQuotes) template.add("'"); 3029 if (!isInQuotes) template.add("'");
3029 template.add(rti.getName(type.element)); 3030 template.add(backend.namer.getName(type.element,
3031 allowUnsafeName: true));
3030 if (hasTypeArguments) { 3032 if (hasTypeArguments) {
3031 template.add("<"); 3033 template.add("<");
3032 for (DartType argument in interfaceType.arguments) { 3034 for (DartType argument in interfaceType.arguments) {
3033 if (!isFirstVariable) { 3035 if (!isFirstVariable) {
3034 template.add(", "); 3036 template.add(", ");
3035 } else { 3037 } else {
3036 isFirstVariable = false; 3038 isFirstVariable = false;
3037 } 3039 }
3038 buildTypeString(argument, isInQuotes: true); 3040 buildTypeString(argument, isInQuotes: true);
3039 } 3041 }
3040 template.add(">"); 3042 template.add(">");
3041 } 3043 }
3042 if (!isInQuotes) template.add("'"); 3044 if (!isInQuotes) template.add("'");
3043 } else { 3045 } else {
3044 assert(type is TypedefType); 3046 assert(type is TypedefType);
3045 if (!isInQuotes) template.add("'"); 3047 if (!isInQuotes) template.add("'");
3046 template.add(rti.getName(argument.element)); 3048 template.add(backend.namer.getName(argument.element,
3049 allowUnsafeName: true));
3047 if (!isInQuotes) template.add("'"); 3050 if (!isInQuotes) template.add("'");
3048 } 3051 }
3049 } 3052 }
3050 3053
3051 buildTypeString(argument, isInQuotes: false); 3054 buildTypeString(argument, isInQuotes: false);
3052 HInstruction result = 3055 HInstruction result =
3053 new HForeign(new LiteralDartString("$template"), 3056 new HForeign(new LiteralDartString("$template"),
3054 new LiteralDartString('String'), 3057 new LiteralDartString('String'),
3055 inputs); 3058 inputs);
3056 add(result); 3059 add(result);
3057 return result; 3060 return result;
3058 } 3061 }
3059 3062
3060 void handleListConstructor(InterfaceType type, 3063 void handleListConstructor(InterfaceType type,
3061 Node currentNode, 3064 Node currentNode,
3062 HInstruction newObject) { 3065 HInstruction newObject) {
3063 if (!compiler.world.needsRti(type.element)) return; 3066 if (!compiler.world.needsRti(type.element)) return;
3064 List<HInstruction> inputs = <HInstruction>[]; 3067 List<HInstruction> inputs = <HInstruction>[];
3065 type.arguments.forEach((DartType argument) { 3068 type.arguments.forEach((DartType argument) {
3066 inputs.add(analyzeTypeArgument(argument, currentNode)); 3069 inputs.add(analyzeTypeArgument(argument, currentNode));
3067 }); 3070 });
3068 callSetRuntimeTypeInfo(type.element, inputs, newObject); 3071 callSetRuntimeTypeInfo(type.element, inputs, newObject);
3069 } 3072 }
3070 3073
3071 void callSetRuntimeTypeInfo(ClassElement element, 3074 void callSetRuntimeTypeInfo(ClassElement element,
3072 List<HInstruction> rtiInputs, 3075 List<HInstruction> rtiInputs,
3073 HInstruction newObject) { 3076 HInstruction newObject) {
3074 bool needsRti = compiler.world.needsRti(element) && !rtiInputs.isEmpty; 3077 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) {
3075 bool runtimeTypeIsUsed = compiler.enabledRuntimeType; 3078 return;
3076 if (!needsRti && !runtimeTypeIsUsed) return;
3077
3078 HInstruction createForeign(String template,
3079 List<HInstruction> arguments,
3080 [String type = 'String']) {
3081 return new HForeign(new LiteralDartString(template),
3082 new LiteralDartString(type),
3083 arguments);
3084 } 3079 }
3085 3080
3086 // Construct the runtime type information. 3081 HInstruction typeInfo = new HLiteralList(rtiInputs);
3087 StringBuffer runtimeCode = new StringBuffer(); 3082 add(typeInfo);
3088 List<HInstruction> runtimeCodeInputs = <HInstruction>[];
3089 if (runtimeTypeIsUsed) {
3090 String runtimeTypeString =
3091 rti.generateRuntimeTypeString(element, rtiInputs.length);
3092 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs);
3093 add(runtimeType);
3094 runtimeCodeInputs.add(runtimeType);
3095 runtimeCode.add("runtimeType: '#'");
3096 }
3097 if (needsRti) {
3098 if (runtimeTypeIsUsed) runtimeCode.add(', ');
3099 String typeVariablesString =
3100 RuntimeTypeInformation.generateTypeVariableString(element,
3101 rtiInputs.length);
3102 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs);
3103 add(typeInfo);
3104 runtimeCodeInputs.add(typeInfo);
3105 runtimeCode.add('#');
3106 }
3107 HInstruction runtimeInfo =
3108 createForeign("{$runtimeCode}", runtimeCodeInputs, 'Object');
3109 add(runtimeInfo);
3110 3083
3111 // Set the runtime type information on the object. 3084 // Set the runtime type information on the object.
3112 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo(); 3085 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo();
3113 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement); 3086 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement);
3114 add(typeInfoSetter); 3087 add(typeInfoSetter);
3115 add(new HInvokeStatic( 3088 add(new HInvokeStatic(
3116 <HInstruction>[typeInfoSetter, newObject, runtimeInfo])); 3089 <HInstruction>[typeInfoSetter, newObject, typeInfo]));
3117 } 3090 }
3118 3091
3119 visitNewSend(Send node, InterfaceType type) { 3092 visitNewSend(Send node, InterfaceType type) {
3120 bool isListConstructor = false; 3093 bool isListConstructor = false;
3121 computeType(element) { 3094 computeType(element) {
3122 Element originalElement = elements[node]; 3095 Element originalElement = elements[node];
3123 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) { 3096 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) {
3124 isListConstructor = true; 3097 isListConstructor = true;
3125 if (node.arguments.isEmpty) { 3098 if (node.arguments.isEmpty) {
3126 return HType.EXTENDABLE_ARRAY; 3099 return HType.EXTENDABLE_ARRAY;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3161 if (constructor.getEnclosingClass().isAbstract(compiler) && 3134 if (constructor.getEnclosingClass().isAbstract(compiler) &&
3162 constructor.isGenerativeConstructor()) { 3135 constructor.isGenerativeConstructor()) {
3163 generateAbstractClassInstantiationError(node, type.name.slowToString()); 3136 generateAbstractClassInstantiationError(node, type.name.slowToString());
3164 return; 3137 return;
3165 } 3138 }
3166 if (compiler.world.needsRti(constructor.enclosingElement)) { 3139 if (compiler.world.needsRti(constructor.enclosingElement)) {
3167 if (!type.arguments.isEmpty) { 3140 if (!type.arguments.isEmpty) {
3168 type.arguments.forEach((DartType argument) { 3141 type.arguments.forEach((DartType argument) {
3169 inputs.add(analyzeTypeArgument(argument, node)); 3142 inputs.add(analyzeTypeArgument(argument, node));
3170 }); 3143 });
3171 } else if (compiler.enabledRuntimeType) {
3172 Link<DartType> variables =
3173 constructor.getEnclosingClass().typeVariables;
3174 if (!variables.isEmpty) {
3175 // If the class has type variables but no type arguments have been
3176 // provided, add [:dynamic:] as argument for all type variables.
3177 DartString stringDynamic = new DartString.literal('dynamic');
3178 HInstruction input = graph.addConstantString(stringDynamic,
3179 node,
3180 constantSystem);
3181 variables.forEach((_) => inputs.add(input));
3182 }
3183 } 3144 }
3184 } 3145 }
3185 3146
3186 HType elementType = computeType(constructor); 3147 HType elementType = computeType(constructor);
3187 HInstruction newInstance = new HInvokeStatic(inputs, elementType); 3148 HInstruction newInstance = new HInvokeStatic(inputs, elementType);
3188 pushWithPosition(newInstance, node); 3149 pushWithPosition(newInstance, node);
3189 3150
3190 // The List constructor forwards to a Dart static method that does 3151 // The List constructor forwards to a Dart static method that does
3191 // not know about the type argument. Therefore we special case 3152 // not know about the type argument. Therefore we special case
3192 // this constructor to have the setRuntimeTypeInfo called where 3153 // this constructor to have the setRuntimeTypeInfo called where
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3257 Constant constant = constantSystem.createString(dartString, node); 3218 Constant constant = constantSystem.createString(dartString, node);
3258 return graph.addConstant(constant); 3219 return graph.addConstant(constant);
3259 } 3220 }
3260 3221
3261 visitTypeReferenceSend(Send node) { 3222 visitTypeReferenceSend(Send node) {
3262 Element element = elements[node]; 3223 Element element = elements[node];
3263 HInstruction name; 3224 HInstruction name;
3264 Element helper = 3225 Element helper =
3265 compiler.findHelper(const SourceString('createRuntimeType')); 3226 compiler.findHelper(const SourceString('createRuntimeType'));
3266 if (element.isClass()) { 3227 if (element.isClass()) {
3267 String string = rti.generateRuntimeTypeString(element, 0); 3228 ClassElement classElement = element;
3229 String string = backend.namer.getName(classElement,
3230 allowUnsafeName: true);
3231 if (!classElement.typeVariables.isEmpty) {
3232 String arguments =
3233 RuntimeTypeInformation.buildRawArguments(classElement);
3234 string = "$string<$arguments>";
3235 }
3268 name = addConstantString(node.selector, string); 3236 name = addConstantString(node.selector, string);
3269 } else if (element.isTypedef()) { 3237 } else if (element.isTypedef()) {
3270 // TODO(karlklose): implement support for type variables in typedefs. 3238 // TODO(karlklose): implement support for type variables in typedefs.
3271 name = addConstantString(node.selector, rti.getName(element)); 3239 name = addConstantString(node.selector, backend.namer.getName(element));
3272 } else if (element.isTypeVariable()) { 3240 } else if (element.isTypeVariable()) {
3273 // TODO(6248): implement support for type variables. 3241 // TODO(6248): implement support for type variables.
3274 compiler.unimplemented('first class type for type variable', node: node); 3242 compiler.unimplemented('first class type for type variable', node: node);
3275 } else { 3243 } else {
3276 internalError('unexpected element $element', node: node); 3244 internalError('unexpected element $element', node: node);
3277 } 3245 }
3278 pushInvokeHelper1(helper, name); 3246 pushInvokeHelper1(helper, name);
3279 if (node.isCall) { 3247 if (node.isCall) {
3280 // This send is of the form 'e(...)', where e is resolved to a type 3248 // This send is of the form 'e(...)', where e is resolved to a type
3281 // reference. We create a regular closure call on the result of the type 3249 // reference. We create a regular closure call on the result of the type
(...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after
4841 new HSubGraphBlockInformation(elseBranch.graph)); 4809 new HSubGraphBlockInformation(elseBranch.graph));
4842 4810
4843 HBasicBlock conditionStartBlock = conditionBranch.block; 4811 HBasicBlock conditionStartBlock = conditionBranch.block;
4844 conditionStartBlock.setBlockFlow(info, joinBlock); 4812 conditionStartBlock.setBlockFlow(info, joinBlock);
4845 SubGraph conditionGraph = conditionBranch.graph; 4813 SubGraph conditionGraph = conditionBranch.graph;
4846 HIf branch = conditionGraph.end.last; 4814 HIf branch = conditionGraph.end.last;
4847 assert(branch is HIf); 4815 assert(branch is HIf);
4848 branch.blockInformation = conditionStartBlock.blockFlow; 4816 branch.blockInformation = conditionStartBlock.blockFlow;
4849 } 4817 }
4850 } 4818 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698