| OLD | NEW |
| 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 2926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2937 | 2937 |
| 2938 // Construct the runtime type information. | 2938 // Construct the runtime type information. |
| 2939 StringBuffer runtimeCode = new StringBuffer(); | 2939 StringBuffer runtimeCode = new StringBuffer(); |
| 2940 List<HInstruction> runtimeCodeInputs = <HInstruction>[]; | 2940 List<HInstruction> runtimeCodeInputs = <HInstruction>[]; |
| 2941 if (runtimeTypeIsUsed) { | 2941 if (runtimeTypeIsUsed) { |
| 2942 String runtimeTypeString = | 2942 String runtimeTypeString = |
| 2943 rti.generateRuntimeTypeString(element, rtiInputs.length); | 2943 rti.generateRuntimeTypeString(element, rtiInputs.length); |
| 2944 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs); | 2944 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs); |
| 2945 add(runtimeType); | 2945 add(runtimeType); |
| 2946 runtimeCodeInputs.add(runtimeType); | 2946 runtimeCodeInputs.add(runtimeType); |
| 2947 runtimeCode.add('runtimeType: #'); | 2947 runtimeCode.add("runtimeType: '#'"); |
| 2948 } | 2948 } |
| 2949 if (needsRti) { | 2949 if (needsRti) { |
| 2950 if (runtimeTypeIsUsed) runtimeCode.add(', '); | 2950 if (runtimeTypeIsUsed) runtimeCode.add(', '); |
| 2951 String typeVariablesString = | 2951 String typeVariablesString = |
| 2952 RuntimeTypeInformation.generateTypeVariableString(element, | 2952 RuntimeTypeInformation.generateTypeVariableString(element, |
| 2953 rtiInputs.length); | 2953 rtiInputs.length); |
| 2954 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs); | 2954 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs); |
| 2955 add(typeInfo); | 2955 add(typeInfo); |
| 2956 runtimeCodeInputs.add(typeInfo); | 2956 runtimeCodeInputs.add(typeInfo); |
| 2957 runtimeCode.add('#'); | 2957 runtimeCode.add('#'); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3009 generateWrongArgumentCountError(node, constructor, node.arguments); | 3009 generateWrongArgumentCountError(node, constructor, node.arguments); |
| 3010 return; | 3010 return; |
| 3011 } | 3011 } |
| 3012 | 3012 |
| 3013 if (type.element.modifiers.isAbstract() && | 3013 if (type.element.modifiers.isAbstract() && |
| 3014 constructor.isGenerativeConstructor()) { | 3014 constructor.isGenerativeConstructor()) { |
| 3015 generateAbstractClassInstantiationError(node, type.name.slowToString()); | 3015 generateAbstractClassInstantiationError(node, type.name.slowToString()); |
| 3016 return; | 3016 return; |
| 3017 } | 3017 } |
| 3018 if (compiler.world.needsRti(constructor.enclosingElement)) { | 3018 if (compiler.world.needsRti(constructor.enclosingElement)) { |
| 3019 type.arguments.forEach((DartType argument) { | 3019 if (!type.arguments.isEmpty) { |
| 3020 inputs.add(analyzeTypeArgument(argument, node)); | 3020 type.arguments.forEach((DartType argument) { |
| 3021 }); | 3021 inputs.add(analyzeTypeArgument(argument, node)); |
| 3022 }); |
| 3023 } else if (compiler.enabledRuntimeType) { |
| 3024 Link<DartType> variables = |
| 3025 constructor.getEnclosingClass().typeVariables; |
| 3026 if (!variables.isEmpty) { |
| 3027 // If the class has type variables but no type arguments have been |
| 3028 // provided, add [:dynamic:] as argument for all type variables. |
| 3029 DartString stringDynamic = new DartString.literal('dynamic'); |
| 3030 HInstruction input = graph.addConstantString(stringDynamic, |
| 3031 node, |
| 3032 constantSystem); |
| 3033 variables.forEach((_) => inputs.add(input)); |
| 3034 } |
| 3035 } |
| 3022 } | 3036 } |
| 3023 | 3037 |
| 3024 HType elementType = computeType(constructor); | 3038 HType elementType = computeType(constructor); |
| 3025 HInstruction newInstance = new HInvokeStatic(inputs, elementType); | 3039 HInstruction newInstance = new HInvokeStatic(inputs, elementType); |
| 3026 pushWithPosition(newInstance, node); | 3040 pushWithPosition(newInstance, node); |
| 3027 | 3041 |
| 3028 // The List constructor forwards to a Dart static method that does | 3042 // The List constructor forwards to a Dart static method that does |
| 3029 // not know about the type argument. Therefore we special case | 3043 // not know about the type argument. Therefore we special case |
| 3030 // this constructor to have the setRuntimeTypeInfo called where | 3044 // this constructor to have the setRuntimeTypeInfo called where |
| 3031 // the 'new' is done. | 3045 // the 'new' is done. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3083 if (returnType != null) instruction.guaranteedType = returnType; | 3097 if (returnType != null) instruction.guaranteedType = returnType; |
| 3084 pushWithPosition(instruction, node); | 3098 pushWithPosition(instruction, node); |
| 3085 } else { | 3099 } else { |
| 3086 generateGetter(node, element); | 3100 generateGetter(node, element); |
| 3087 List<HInstruction> inputs = <HInstruction>[pop()]; | 3101 List<HInstruction> inputs = <HInstruction>[pop()]; |
| 3088 addDynamicSendArgumentsToList(node, inputs); | 3102 addDynamicSendArgumentsToList(node, inputs); |
| 3089 pushWithPosition(new HInvokeClosure(selector, inputs), node); | 3103 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
| 3090 } | 3104 } |
| 3091 } | 3105 } |
| 3092 | 3106 |
| 3107 HConstant addConstantString(Send node, String string) { |
| 3108 DartString dartString = new DartString.literal(string); |
| 3109 Constant constant = constantSystem.createString(dartString, node); |
| 3110 return graph.addConstant(constant); |
| 3111 } |
| 3112 |
| 3113 visitTypeReferenceSend(Send node) { |
| 3114 Element element = elements[node]; |
| 3115 HInstruction name; |
| 3116 Element helper = |
| 3117 compiler.findHelper(RuntimeTypeInformation.CACHE_HELPER_NAME); |
| 3118 if (element.isClass()) { |
| 3119 String string = rti.generateRuntimeTypeString(element, 0); |
| 3120 name = addConstantString(node.selector, string); |
| 3121 } else if (element.isTypedef()) { |
| 3122 // TODO(karlklose): implement support for type variables in typedefs. |
| 3123 name = addConstantString(node.selector, rti.getName(element)); |
| 3124 } else if (element.isTypeVariable()) { |
| 3125 // TODO(6248): implement support for type variables. |
| 3126 compiler.unimplemented('first class type for type variable', node: node); |
| 3127 } else { |
| 3128 internalError('unexpected element $element', node: node); |
| 3129 } |
| 3130 pushInvokeHelper1(helper, name); |
| 3131 if (node.isCall) { |
| 3132 // This send is of the form 'e(...)', where e is resolved to a type |
| 3133 // reference. We create a regular closure call on the result of the type |
| 3134 // reference instead of creating a NoSuchMethodError to avoid pulling it |
| 3135 // in if it is not used (e.g., in a try/catch). |
| 3136 HInstruction target = pop(); |
| 3137 Selector selector = elements.getSelector(node); |
| 3138 List<HInstruction> inputs = <HInstruction>[target]; |
| 3139 addDynamicSendArgumentsToList(node, inputs); |
| 3140 push(new HInvokeClosure(selector, inputs)); |
| 3141 } |
| 3142 // Enable the runtime type cache, so that the emitter generates one even |
| 3143 // if we do not have [runtimeType] in the program. |
| 3144 compiler.enableRuntimeTypeCache(); |
| 3145 } |
| 3146 |
| 3093 visitGetterSend(Send node) { | 3147 visitGetterSend(Send node) { |
| 3094 generateGetter(node, elements[node]); | 3148 generateGetter(node, elements[node]); |
| 3095 } | 3149 } |
| 3096 | 3150 |
| 3097 // TODO(antonm): migrate rest of SsaBuilder to internalError. | 3151 // TODO(antonm): migrate rest of SsaBuilder to internalError. |
| 3098 internalError(String reason, {Node node}) { | 3152 internalError(String reason, {Node node}) { |
| 3099 compiler.internalError(reason, node: node); | 3153 compiler.internalError(reason, node: node); |
| 3100 } | 3154 } |
| 3101 | 3155 |
| 3102 void generateError(Node node, String message, Element helper) { | 3156 void generateError(Node node, String message, Element helper) { |
| 3103 DartString messageObject = new DartString.literal(message); | 3157 HInstruction errorMessage = addConstantString(node, message); |
| 3104 Constant messageConstant = | |
| 3105 constantSystem.createString(messageObject, node); | |
| 3106 HInstruction errorMessage = graph.addConstant(messageConstant); | |
| 3107 pushInvokeHelper1(helper, errorMessage); | 3158 pushInvokeHelper1(helper, errorMessage); |
| 3108 } | 3159 } |
| 3109 | 3160 |
| 3110 void generateRuntimeError(Node node, String message) { | 3161 void generateRuntimeError(Node node, String message) { |
| 3111 generateError(node, message, interceptors.getThrowRuntimeError()); | 3162 generateError(node, message, interceptors.getThrowRuntimeError()); |
| 3112 } | 3163 } |
| 3113 | 3164 |
| 3114 void generateAbstractClassInstantiationError(Node node, String message) { | 3165 void generateAbstractClassInstantiationError(Node node, String message) { |
| 3115 generateError(node, | 3166 generateError(node, |
| 3116 message, | 3167 message, |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3276 } else { | 3327 } else { |
| 3277 assert(const SourceString("++") == op.source || | 3328 assert(const SourceString("++") == op.source || |
| 3278 const SourceString("--") == op.source || | 3329 const SourceString("--") == op.source || |
| 3279 node.assignmentOperator.source.stringValue.endsWith("=")); | 3330 node.assignmentOperator.source.stringValue.endsWith("=")); |
| 3280 Element element = elements[node]; | 3331 Element element = elements[node]; |
| 3281 bool isCompoundAssignment = !node.arguments.isEmpty; | 3332 bool isCompoundAssignment = !node.arguments.isEmpty; |
| 3282 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. | 3333 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. |
| 3283 | 3334 |
| 3284 // [receiver] is only used if the node is an instance send. | 3335 // [receiver] is only used if the node is an instance send. |
| 3285 HInstruction receiver = null; | 3336 HInstruction receiver = null; |
| 3286 if (Elements.isInstanceSend(node, elements)) { | 3337 Element selectorElement = elements[node]; |
| 3338 if (!Elements.isUnresolved(selectorElement) |
| 3339 && selectorElement.impliesType()) { |
| 3340 visitTypeReferenceSend(node); |
| 3341 } else if (Elements.isInstanceSend(node, elements)) { |
| 3287 receiver = generateInstanceSendReceiver(node); | 3342 receiver = generateInstanceSendReceiver(node); |
| 3288 generateInstanceGetterWithCompiledReceiver(node, receiver); | 3343 generateInstanceGetterWithCompiledReceiver(node, receiver); |
| 3289 } else { | 3344 } else { |
| 3290 generateGetter(node, elements[node.selector]); | 3345 generateGetter(node, elements[node.selector]); |
| 3291 } | 3346 } |
| 3292 HInstruction left = pop(); | 3347 HInstruction left = pop(); |
| 3293 HInstruction right; | 3348 HInstruction right; |
| 3294 if (isCompoundAssignment) { | 3349 if (isCompoundAssignment) { |
| 3295 visit(node.argumentsNode); | 3350 visit(node.argumentsNode); |
| 3296 right = pop(); | 3351 right = pop(); |
| (...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4603 new HSubGraphBlockInformation(elseBranch.graph)); | 4658 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4604 | 4659 |
| 4605 HBasicBlock conditionStartBlock = conditionBranch.block; | 4660 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4606 conditionStartBlock.setBlockFlow(info, joinBlock); | 4661 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4607 SubGraph conditionGraph = conditionBranch.graph; | 4662 SubGraph conditionGraph = conditionBranch.graph; |
| 4608 HIf branch = conditionGraph.end.last; | 4663 HIf branch = conditionGraph.end.last; |
| 4609 assert(branch is HIf); | 4664 assert(branch is HIf); |
| 4610 branch.blockInformation = conditionStartBlock.blockFlow; | 4665 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4611 } | 4666 } |
| 4612 } | 4667 } |
| OLD | NEW |