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

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: Remove test again. 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 2477 matching lines...) Expand 10 before | Expand all | Expand 10 after
2488 bool isNot = false; 2488 bool isNot = false;
2489 // TODO(ngeoffray): Duplicating pattern in resolver. We should 2489 // TODO(ngeoffray): Duplicating pattern in resolver. We should
2490 // add a new kind of node. 2490 // add a new kind of node.
2491 if (typeAnnotation == null) { 2491 if (typeAnnotation == null) {
2492 typeAnnotation = argument.asSend().receiver; 2492 typeAnnotation = argument.asSend().receiver;
2493 isNot = true; 2493 isNot = true;
2494 } 2494 }
2495 2495
2496 DartType type = elements.getType(typeAnnotation); 2496 DartType type = elements.getType(typeAnnotation);
2497 HInstruction typeInfo = null; 2497 HInstruction typeInfo = null;
2498 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { 2498 if (RuntimeTypeInformation.hasTypeArguments(type)) {
2499 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); 2499 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression);
2500 typeInfo = pop(); 2500 typeInfo = pop();
2501 } 2501 }
2502 if (type.element.isTypeVariable()) { 2502 if (type.element.isTypeVariable()) {
2503 // TODO(karlklose): We currently answer true to any is check 2503 // TODO(karlklose): We currently answer true to any is check
2504 // involving a type variable -- both is T and is !T -- until 2504 // involving a type variable -- both is T and is !T -- until
2505 // we have a proper implementation of reified generics. 2505 // we have a proper implementation of reified generics.
2506 stack.add(graph.addConstantBool(true, constantSystem)); 2506 stack.add(graph.addConstantBool(true, constantSystem));
2507 } else { 2507 } else {
2508 HInstruction instruction; 2508 HInstruction instruction;
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2954 // The type variable is stored in a parameter of the factory. 2954 // The type variable is stored in a parameter of the factory.
2955 inputs.add(localsHandler.readLocal(type.element)); 2955 inputs.add(localsHandler.readLocal(type.element));
2956 } else if (member.isInstanceMember() 2956 } else if (member.isInstanceMember()
2957 || member.isGenerativeConstructor()) { 2957 || member.isGenerativeConstructor()) {
2958 // The type variable is stored in [this]. 2958 // The type variable is stored in [this].
2959 if (typeInfo == null) { 2959 if (typeInfo == null) {
2960 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), 2960 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(),
2961 localsHandler.readThis()); 2961 localsHandler.readThis());
2962 typeInfo = pop(); 2962 typeInfo = pop();
2963 } 2963 }
2964 int index = RuntimeTypeInformation.getTypeVariableIndex(type);
2964 HInstruction foreign = new HForeign( 2965 HInstruction foreign = new HForeign(
2965 new LiteralDartString('#.${type.name.slowToString()}'), 2966 new LiteralDartString('#[$index]'),
2966 new LiteralDartString('String'), 2967 new LiteralDartString('String'),
2967 <HInstruction>[typeInfo]); 2968 <HInstruction>[typeInfo]);
2968 add(foreign); 2969 add(foreign);
2969 inputs.add(foreign); 2970 inputs.add(foreign);
2970 } else { 2971 } else {
2971 // TODO(ngeoffray): Match the VM behavior and throw an 2972 // TODO(ngeoffray): Match the VM behavior and throw an
2972 // exception at runtime. 2973 // exception at runtime.
2973 compiler.cancel('Unimplemented unresolved type variable', 2974 compiler.cancel('Unimplemented unresolved type variable',
2974 node: currentNode); 2975 node: currentNode);
2975 } 2976 }
(...skipping 12 matching lines...) Expand all
2988 */ 2989 */
2989 void buildTypeString(DartType type, {isInQuotes: false}) { 2990 void buildTypeString(DartType type, {isInQuotes: false}) {
2990 if (type is TypeVariableType) { 2991 if (type is TypeVariableType) {
2991 addTypeVariableReference(type); 2992 addTypeVariableReference(type);
2992 template.add(isInQuotes ? "' + # +'" : "#"); 2993 template.add(isInQuotes ? "' + # +'" : "#");
2993 } else if (type is InterfaceType) { 2994 } else if (type is InterfaceType) {
2994 bool isFirstVariable = true; 2995 bool isFirstVariable = true;
2995 InterfaceType interfaceType = type; 2996 InterfaceType interfaceType = type;
2996 bool hasTypeArguments = !interfaceType.arguments.isEmpty; 2997 bool hasTypeArguments = !interfaceType.arguments.isEmpty;
2997 if (!isInQuotes) template.add("'"); 2998 if (!isInQuotes) template.add("'");
2998 template.add(rti.getName(type.element)); 2999 template.add(backend.namer.getName(type.element,
3000 allowUnsafeName: true));
2999 if (hasTypeArguments) { 3001 if (hasTypeArguments) {
3000 template.add("<"); 3002 template.add("<");
3001 for (DartType argument in interfaceType.arguments) { 3003 for (DartType argument in interfaceType.arguments) {
3002 if (!isFirstVariable) { 3004 if (!isFirstVariable) {
3003 template.add(", "); 3005 template.add(", ");
3004 } else { 3006 } else {
3005 isFirstVariable = false; 3007 isFirstVariable = false;
3006 } 3008 }
3007 buildTypeString(argument, isInQuotes: true); 3009 buildTypeString(argument, isInQuotes: true);
3008 } 3010 }
3009 template.add(">"); 3011 template.add(">");
3010 } 3012 }
3011 if (!isInQuotes) template.add("'"); 3013 if (!isInQuotes) template.add("'");
3012 } else { 3014 } else {
3013 assert(type is TypedefType); 3015 assert(type is TypedefType);
3014 if (!isInQuotes) template.add("'"); 3016 if (!isInQuotes) template.add("'");
3015 template.add(rti.getName(argument.element)); 3017 template.add(backend.namer.getName(argument.element,
3018 allowUnsafeName: true));
3016 if (!isInQuotes) template.add("'"); 3019 if (!isInQuotes) template.add("'");
3017 } 3020 }
3018 } 3021 }
3019 3022
3020 buildTypeString(argument, isInQuotes: false); 3023 buildTypeString(argument, isInQuotes: false);
3021 HInstruction result = 3024 HInstruction result =
3022 new HForeign(new LiteralDartString("$template"), 3025 new HForeign(new LiteralDartString("$template"),
3023 new LiteralDartString('String'), 3026 new LiteralDartString('String'),
3024 inputs); 3027 inputs);
3025 add(result); 3028 add(result);
3026 return result; 3029 return result;
3027 } 3030 }
3028 3031
3029 void handleListConstructor(InterfaceType type, 3032 void handleListConstructor(InterfaceType type,
3030 Node currentNode, 3033 Node currentNode,
3031 HInstruction newObject) { 3034 HInstruction newObject) {
3032 if (!compiler.world.needsRti(type.element)) return; 3035 if (!compiler.world.needsRti(type.element)) return;
3033 List<HInstruction> inputs = <HInstruction>[]; 3036 List<HInstruction> inputs = <HInstruction>[];
3034 type.arguments.forEach((DartType argument) { 3037 type.arguments.forEach((DartType argument) {
3035 inputs.add(analyzeTypeArgument(argument, currentNode)); 3038 inputs.add(analyzeTypeArgument(argument, currentNode));
3036 }); 3039 });
3037 callSetRuntimeTypeInfo(type.element, inputs, newObject); 3040 callSetRuntimeTypeInfo(type.element, inputs, newObject);
3038 } 3041 }
3039 3042
3040 void callSetRuntimeTypeInfo(ClassElement element, 3043 void callSetRuntimeTypeInfo(ClassElement element,
3041 List<HInstruction> rtiInputs, 3044 List<HInstruction> rtiInputs,
3042 HInstruction newObject) { 3045 HInstruction newObject) {
3043 bool needsRti = compiler.world.needsRti(element) && !rtiInputs.isEmpty; 3046 if (!compiler.world.needsRti(element) || element.typeVariables.isEmpty) {
3044 bool runtimeTypeIsUsed = compiler.enabledRuntimeType; 3047 return;
3045 if (!needsRti && !runtimeTypeIsUsed) return;
3046
3047 HInstruction createForeign(String template,
3048 List<HInstruction> arguments,
3049 [String type = 'String']) {
3050 return new HForeign(new LiteralDartString(template),
3051 new LiteralDartString(type),
3052 arguments);
3053 } 3048 }
3054 3049
3055 // Construct the runtime type information. 3050 HInstruction typeInfo = new HLiteralList(rtiInputs);
3056 StringBuffer runtimeCode = new StringBuffer(); 3051 add(typeInfo);
3057 List<HInstruction> runtimeCodeInputs = <HInstruction>[];
3058 if (runtimeTypeIsUsed) {
3059 String runtimeTypeString =
3060 rti.generateRuntimeTypeString(element, rtiInputs.length);
3061 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs);
3062 add(runtimeType);
3063 runtimeCodeInputs.add(runtimeType);
3064 runtimeCode.add("runtimeType: '#'");
3065 }
3066 if (needsRti) {
3067 if (runtimeTypeIsUsed) runtimeCode.add(', ');
3068 String typeVariablesString =
3069 RuntimeTypeInformation.generateTypeVariableString(element,
3070 rtiInputs.length);
3071 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs);
3072 add(typeInfo);
3073 runtimeCodeInputs.add(typeInfo);
3074 runtimeCode.add('#');
3075 }
3076 HInstruction runtimeInfo =
3077 createForeign("{$runtimeCode}", runtimeCodeInputs, 'Object');
3078 add(runtimeInfo);
3079 3052
3080 // Set the runtime type information on the object. 3053 // Set the runtime type information on the object.
3081 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo(); 3054 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo();
3082 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement); 3055 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement);
3083 add(typeInfoSetter); 3056 add(typeInfoSetter);
3084 add(new HInvokeStatic( 3057 add(new HInvokeStatic(
3085 <HInstruction>[typeInfoSetter, newObject, runtimeInfo])); 3058 <HInstruction>[typeInfoSetter, newObject, typeInfo]));
3086 } 3059 }
3087 3060
3088 visitNewSend(Send node, InterfaceType type) { 3061 visitNewSend(Send node, InterfaceType type) {
3089 bool isListConstructor = false; 3062 bool isListConstructor = false;
3090 computeType(element) { 3063 computeType(element) {
3091 Element originalElement = elements[node]; 3064 Element originalElement = elements[node];
3092 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) { 3065 if (identical(originalElement.getEnclosingClass(), compiler.listClass)) {
3093 isListConstructor = true; 3066 isListConstructor = true;
3094 if (node.arguments.isEmpty) { 3067 if (node.arguments.isEmpty) {
3095 return HType.EXTENDABLE_ARRAY; 3068 return HType.EXTENDABLE_ARRAY;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3130 if (type.element.modifiers.isAbstract() && 3103 if (type.element.modifiers.isAbstract() &&
3131 constructor.isGenerativeConstructor()) { 3104 constructor.isGenerativeConstructor()) {
3132 generateAbstractClassInstantiationError(node, type.name.slowToString()); 3105 generateAbstractClassInstantiationError(node, type.name.slowToString());
3133 return; 3106 return;
3134 } 3107 }
3135 if (compiler.world.needsRti(constructor.enclosingElement)) { 3108 if (compiler.world.needsRti(constructor.enclosingElement)) {
3136 if (!type.arguments.isEmpty) { 3109 if (!type.arguments.isEmpty) {
3137 type.arguments.forEach((DartType argument) { 3110 type.arguments.forEach((DartType argument) {
3138 inputs.add(analyzeTypeArgument(argument, node)); 3111 inputs.add(analyzeTypeArgument(argument, node));
3139 }); 3112 });
3140 } else if (compiler.enabledRuntimeType) {
3141 Link<DartType> variables =
3142 constructor.getEnclosingClass().typeVariables;
3143 if (!variables.isEmpty) {
3144 // If the class has type variables but no type arguments have been
3145 // provided, add [:dynamic:] as argument for all type variables.
3146 DartString stringDynamic = new DartString.literal('dynamic');
3147 HInstruction input = graph.addConstantString(stringDynamic,
3148 node,
3149 constantSystem);
3150 variables.forEach((_) => inputs.add(input));
3151 }
3152 } 3113 }
3153 } 3114 }
3154 3115
3155 HType elementType = computeType(constructor); 3116 HType elementType = computeType(constructor);
3156 HInstruction newInstance = new HInvokeStatic(inputs, elementType); 3117 HInstruction newInstance = new HInvokeStatic(inputs, elementType);
3157 pushWithPosition(newInstance, node); 3118 pushWithPosition(newInstance, node);
3158 3119
3159 // The List constructor forwards to a Dart static method that does 3120 // The List constructor forwards to a Dart static method that does
3160 // not know about the type argument. Therefore we special case 3121 // not know about the type argument. Therefore we special case
3161 // this constructor to have the setRuntimeTypeInfo called where 3122 // this constructor to have the setRuntimeTypeInfo called where
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3226 Constant constant = constantSystem.createString(dartString, node); 3187 Constant constant = constantSystem.createString(dartString, node);
3227 return graph.addConstant(constant); 3188 return graph.addConstant(constant);
3228 } 3189 }
3229 3190
3230 visitTypeReferenceSend(Send node) { 3191 visitTypeReferenceSend(Send node) {
3231 Element element = elements[node]; 3192 Element element = elements[node];
3232 HInstruction name; 3193 HInstruction name;
3233 Element helper = 3194 Element helper =
3234 compiler.findHelper(RuntimeTypeInformation.CACHE_HELPER_NAME); 3195 compiler.findHelper(RuntimeTypeInformation.CACHE_HELPER_NAME);
3235 if (element.isClass()) { 3196 if (element.isClass()) {
3236 String string = rti.generateRuntimeTypeString(element, 0); 3197 ClassElement classElement = element;
3198 String string = backend.namer.getName(classElement,
3199 allowUnsafeName: true);
3200 if (!classElement.typeVariables.isEmpty) {
3201 String arguments =
3202 RuntimeTypeInformation.buildRawArguments(classElement);
3203 string = "$string<$arguments>";
3204 }
3237 name = addConstantString(node.selector, string); 3205 name = addConstantString(node.selector, string);
3238 } else if (element.isTypedef()) { 3206 } else if (element.isTypedef()) {
3239 // TODO(karlklose): implement support for type variables in typedefs. 3207 // TODO(karlklose): implement support for type variables in typedefs.
3240 name = addConstantString(node.selector, rti.getName(element)); 3208 name = addConstantString(node.selector, backend.namer.getName(element));
3241 } else if (element.isTypeVariable()) { 3209 } else if (element.isTypeVariable()) {
3242 // TODO(6248): implement support for type variables. 3210 // TODO(6248): implement support for type variables.
3243 compiler.unimplemented('first class type for type variable', node: node); 3211 compiler.unimplemented('first class type for type variable', node: node);
3244 } else { 3212 } else {
3245 internalError('unexpected element $element', node: node); 3213 internalError('unexpected element $element', node: node);
3246 } 3214 }
3247 pushInvokeHelper1(helper, name); 3215 pushInvokeHelper1(helper, name);
3248 if (node.isCall) { 3216 if (node.isCall) {
3249 // This send is of the form 'e(...)', where e is resolved to a type 3217 // This send is of the form 'e(...)', where e is resolved to a type
3250 // reference. We create a regular closure call on the result of the type 3218 // 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
4810 new HSubGraphBlockInformation(elseBranch.graph)); 4778 new HSubGraphBlockInformation(elseBranch.graph));
4811 4779
4812 HBasicBlock conditionStartBlock = conditionBranch.block; 4780 HBasicBlock conditionStartBlock = conditionBranch.block;
4813 conditionStartBlock.setBlockFlow(info, joinBlock); 4781 conditionStartBlock.setBlockFlow(info, joinBlock);
4814 SubGraph conditionGraph = conditionBranch.graph; 4782 SubGraph conditionGraph = conditionBranch.graph;
4815 HIf branch = conditionGraph.end.last; 4783 HIf branch = conditionGraph.end.last;
4816 assert(branch is HIf); 4784 assert(branch is HIf);
4817 branch.blockInformation = conditionStartBlock.blockFlow; 4785 branch.blockInformation = conditionStartBlock.blockFlow;
4818 } 4786 }
4819 } 4787 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698