Chromium Code Reviews| 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 2909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2920 | 2920 |
| 2921 // Construct the runtime type information. | 2921 // Construct the runtime type information. |
| 2922 StringBuffer runtimeCode = new StringBuffer(); | 2922 StringBuffer runtimeCode = new StringBuffer(); |
| 2923 List<HInstruction> runtimeCodeInputs = <HInstruction>[]; | 2923 List<HInstruction> runtimeCodeInputs = <HInstruction>[]; |
| 2924 if (runtimeTypeIsUsed) { | 2924 if (runtimeTypeIsUsed) { |
| 2925 String runtimeTypeString = | 2925 String runtimeTypeString = |
| 2926 rti.generateRuntimeTypeString(element, rtiInputs.length); | 2926 rti.generateRuntimeTypeString(element, rtiInputs.length); |
| 2927 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs); | 2927 HInstruction runtimeType = createForeign(runtimeTypeString, rtiInputs); |
| 2928 add(runtimeType); | 2928 add(runtimeType); |
| 2929 runtimeCodeInputs.add(runtimeType); | 2929 runtimeCodeInputs.add(runtimeType); |
| 2930 runtimeCode.add('runtimeType: #'); | 2930 runtimeCode.add("runtimeType: '#'"); |
| 2931 } | 2931 } |
| 2932 if (needsRti) { | 2932 if (needsRti) { |
| 2933 if (runtimeTypeIsUsed) runtimeCode.add(', '); | 2933 if (runtimeTypeIsUsed) runtimeCode.add(', '); |
| 2934 String typeVariablesString = | 2934 String typeVariablesString = |
| 2935 RuntimeTypeInformation.generateTypeVariableString(element, | 2935 RuntimeTypeInformation.generateTypeVariableString(element, |
| 2936 rtiInputs.length); | 2936 rtiInputs.length); |
| 2937 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs); | 2937 HInstruction typeInfo = createForeign(typeVariablesString, rtiInputs); |
| 2938 add(typeInfo); | 2938 add(typeInfo); |
| 2939 runtimeCodeInputs.add(typeInfo); | 2939 runtimeCodeInputs.add(typeInfo); |
| 2940 runtimeCode.add('#'); | 2940 runtimeCode.add('#'); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2992 generateWrongArgumentCountError(node, constructor, node.arguments); | 2992 generateWrongArgumentCountError(node, constructor, node.arguments); |
| 2993 return; | 2993 return; |
| 2994 } | 2994 } |
| 2995 | 2995 |
| 2996 if (type.element.modifiers.isAbstract() && | 2996 if (type.element.modifiers.isAbstract() && |
| 2997 constructor.isGenerativeConstructor()) { | 2997 constructor.isGenerativeConstructor()) { |
| 2998 generateAbstractClassInstantiationError(node, type.name.slowToString()); | 2998 generateAbstractClassInstantiationError(node, type.name.slowToString()); |
| 2999 return; | 2999 return; |
| 3000 } | 3000 } |
| 3001 if (compiler.world.needsRti(constructor.enclosingElement)) { | 3001 if (compiler.world.needsRti(constructor.enclosingElement)) { |
| 3002 type.arguments.forEach((DartType argument) { | 3002 if (!type.arguments.isEmpty) { |
| 3003 inputs.add(analyzeTypeArgument(argument, node)); | 3003 type.arguments.forEach((DartType argument) { |
| 3004 }); | 3004 inputs.add(analyzeTypeArgument(argument, node)); |
| 3005 }); | |
| 3006 } else if (compiler.enabledRuntimeType) { | |
| 3007 Link<DartType> variables = | |
| 3008 constructor.getEnclosingClass().typeVariables; | |
| 3009 if (!variables.isEmpty) { | |
| 3010 // If the class has type variables but no type arguments have been | |
| 3011 // provided, add [:dynamic:] as argument for all type variables. | |
|
ngeoffray
2012/10/31 10:33:03
Can't we find that at runtime instead?
karlklose
2012/10/31 13:01:18
We could by wrapping each type variable in a call
ngeoffray
2012/10/31 14:32:43
What other solution are you thinking of? One that
| |
| 3012 DartString stringDynamic = new DartString.literal('dynamic'); | |
| 3013 HInstruction input = graph.addConstantString(stringDynamic, | |
| 3014 node, | |
| 3015 constantSystem); | |
| 3016 variables.forEach((_) => inputs.add(input)); | |
| 3017 } | |
| 3018 } | |
| 3005 } | 3019 } |
| 3006 | 3020 |
| 3007 HType elementType = computeType(constructor); | 3021 HType elementType = computeType(constructor); |
| 3008 HInstruction newInstance = new HInvokeStatic(inputs, elementType); | 3022 HInstruction newInstance = new HInvokeStatic(inputs, elementType); |
| 3009 pushWithPosition(newInstance, node); | 3023 pushWithPosition(newInstance, node); |
| 3010 | 3024 |
| 3011 // The List constructor forwards to a Dart static method that does | 3025 // The List constructor forwards to a Dart static method that does |
| 3012 // not know about the type argument. Therefore we special case | 3026 // not know about the type argument. Therefore we special case |
| 3013 // this constructor to have the setRuntimeTypeInfo called where | 3027 // this constructor to have the setRuntimeTypeInfo called where |
| 3014 // the 'new' is done. | 3028 // the 'new' is done. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3066 if (returnType != null) instruction.guaranteedType = returnType; | 3080 if (returnType != null) instruction.guaranteedType = returnType; |
| 3067 pushWithPosition(instruction, node); | 3081 pushWithPosition(instruction, node); |
| 3068 } else { | 3082 } else { |
| 3069 generateGetter(node, element); | 3083 generateGetter(node, element); |
| 3070 List<HInstruction> inputs = <HInstruction>[pop()]; | 3084 List<HInstruction> inputs = <HInstruction>[pop()]; |
| 3071 addDynamicSendArgumentsToList(node, inputs); | 3085 addDynamicSendArgumentsToList(node, inputs); |
| 3072 pushWithPosition(new HInvokeClosure(selector, inputs), node); | 3086 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
| 3073 } | 3087 } |
| 3074 } | 3088 } |
| 3075 | 3089 |
| 3090 HConstant addConstantString(Send node, String string) { | |
| 3091 DartString dartString = new DartString.literal(string); | |
| 3092 Constant constant = constantSystem.createString(dartString, node); | |
| 3093 return graph.addConstant(constant); | |
| 3094 } | |
| 3095 | |
| 3096 visitTypeReferenceSend(Send node) { | |
| 3097 Element element = elements[node]; | |
| 3098 HInstruction name; | |
| 3099 Element helper = | |
| 3100 compiler.findHelper(RuntimeTypeInformation.CACHE_HELPER_NAME); | |
| 3101 if (element.isClass()) { | |
| 3102 String string = rti.generateRuntimeTypeString(element, 0); | |
| 3103 name = addConstantString(node.selector, string); | |
| 3104 } else if (element.isTypedef()) { | |
| 3105 // TODO(karlklose): implement support for type variables in typedefs. | |
| 3106 name = addConstantString(node.selector, rti.getName(element)); | |
| 3107 } else if (element.isTypeVariable()) { | |
| 3108 // TODO(6248): implement support for type variables. | |
| 3109 compiler.unimplemented('first class type for type variable', node: node); | |
| 3110 } else { | |
| 3111 internalError('unexpected element $element', node: node); | |
| 3112 } | |
| 3113 pushInvokeHelper1(helper, name); | |
| 3114 if (node.isFunctionObjectInvocation) { | |
| 3115 // This send is of the form 'e(...)', where e is resolved to a type | |
| 3116 // reference. | |
|
ngeoffray
2012/10/31 10:33:03
Please add a comment that you're doing a regular c
karlklose
2012/10/31 13:01:18
Done.
| |
| 3117 HInstruction target = pop(); | |
| 3118 Selector selector = elements.getSelector(node); | |
| 3119 selector = new Selector.callClosure(selector.argumentCount, | |
| 3120 selector.namedArguments); | |
| 3121 List<HInstruction> inputs = <HInstruction>[target]; | |
| 3122 addDynamicSendArgumentsToList(node, inputs); | |
| 3123 push(new HInvokeDynamicMethod(selector, inputs)); | |
|
ngeoffray
2012/10/31 10:33:03
Could you use HInvokeDynamicClosure? You should no
karlklose
2012/10/31 13:01:18
Yes, it works!
| |
| 3124 } | |
| 3125 // Enable the runtime type cache, so that the emitter generates one even | |
| 3126 // if we do not have [runtimeType] in the program. | |
|
ngeoffray
2012/10/31 10:33:03
How can that happen?
karlklose
2012/10/31 13:01:18
If we use a class literal, but not the runtimeType
| |
| 3127 compiler.enableRuntimeTypeCache(); | |
| 3128 } | |
| 3129 | |
| 3076 visitGetterSend(Send node) { | 3130 visitGetterSend(Send node) { |
| 3077 generateGetter(node, elements[node]); | 3131 generateGetter(node, elements[node]); |
| 3078 } | 3132 } |
| 3079 | 3133 |
| 3080 // TODO(antonm): migrate rest of SsaBuilder to internalError. | 3134 // TODO(antonm): migrate rest of SsaBuilder to internalError. |
| 3081 internalError(String reason, {Node node}) { | 3135 internalError(String reason, {Node node}) { |
| 3082 compiler.internalError(reason, node: node); | 3136 compiler.internalError(reason, node: node); |
| 3083 } | 3137 } |
| 3084 | 3138 |
| 3085 void generateError(Node node, String message, Element helper) { | 3139 void generateError(Node node, String message, Element helper) { |
| 3086 DartString messageObject = new DartString.literal(message); | 3140 HInstruction errorMessage = addConstantString(node, message); |
| 3087 Constant messageConstant = | |
| 3088 constantSystem.createString(messageObject, node); | |
| 3089 HInstruction errorMessage = graph.addConstant(messageConstant); | |
| 3090 pushInvokeHelper1(helper, errorMessage); | 3141 pushInvokeHelper1(helper, errorMessage); |
| 3091 } | 3142 } |
| 3092 | 3143 |
| 3093 void generateRuntimeError(Node node, String message) { | 3144 void generateRuntimeError(Node node, String message) { |
| 3094 generateError(node, message, interceptors.getThrowRuntimeError()); | 3145 generateError(node, message, interceptors.getThrowRuntimeError()); |
| 3095 } | 3146 } |
| 3096 | 3147 |
| 3097 void generateAbstractClassInstantiationError(Node node, String message) { | 3148 void generateAbstractClassInstantiationError(Node node, String message) { |
| 3098 generateError(node, | 3149 generateError(node, |
| 3099 message, | 3150 message, |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3259 } else { | 3310 } else { |
| 3260 assert(const SourceString("++") == op.source || | 3311 assert(const SourceString("++") == op.source || |
| 3261 const SourceString("--") == op.source || | 3312 const SourceString("--") == op.source || |
| 3262 node.assignmentOperator.source.stringValue.endsWith("=")); | 3313 node.assignmentOperator.source.stringValue.endsWith("=")); |
| 3263 Element element = elements[node]; | 3314 Element element = elements[node]; |
| 3264 bool isCompoundAssignment = !node.arguments.isEmpty; | 3315 bool isCompoundAssignment = !node.arguments.isEmpty; |
| 3265 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. | 3316 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. |
| 3266 | 3317 |
| 3267 // [receiver] is only used if the node is an instance send. | 3318 // [receiver] is only used if the node is an instance send. |
| 3268 HInstruction receiver = null; | 3319 HInstruction receiver = null; |
| 3269 if (Elements.isInstanceSend(node, elements)) { | 3320 Element selectorElement = elements[node.selector]; |
|
ngeoffray
2012/10/31 10:33:03
Why is the class on the selector and not the recei
karlklose
2012/10/31 13:01:18
It is on both, but I changed it to read it from th
| |
| 3321 if (!Elements.isUnresolved(selectorElement) | |
| 3322 && selectorElement.impliesType()) { | |
| 3323 visitTypeReferenceSend(node); | |
| 3324 } else if (Elements.isInstanceSend(node, elements)) { | |
| 3270 receiver = generateInstanceSendReceiver(node); | 3325 receiver = generateInstanceSendReceiver(node); |
| 3271 generateInstanceGetterWithCompiledReceiver(node, receiver); | 3326 generateInstanceGetterWithCompiledReceiver(node, receiver); |
| 3272 } else { | 3327 } else { |
| 3273 generateGetter(node, elements[node.selector]); | 3328 generateGetter(node, elements[node.selector]); |
| 3274 } | 3329 } |
| 3275 HInstruction left = pop(); | 3330 HInstruction left = pop(); |
| 3276 HInstruction right; | 3331 HInstruction right; |
| 3277 if (isCompoundAssignment) { | 3332 if (isCompoundAssignment) { |
| 3278 visit(node.argumentsNode); | 3333 visit(node.argumentsNode); |
| 3279 right = pop(); | 3334 right = pop(); |
| (...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4586 new HSubGraphBlockInformation(elseBranch.graph)); | 4641 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4587 | 4642 |
| 4588 HBasicBlock conditionStartBlock = conditionBranch.block; | 4643 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4589 conditionStartBlock.setBlockFlow(info, joinBlock); | 4644 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4590 SubGraph conditionGraph = conditionBranch.graph; | 4645 SubGraph conditionGraph = conditionBranch.graph; |
| 4591 HIf branch = conditionGraph.end.last; | 4646 HIf branch = conditionGraph.end.last; |
| 4592 assert(branch is HIf); | 4647 assert(branch is HIf); |
| 4593 branch.blockInformation = conditionStartBlock.blockFlow; | 4648 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4594 } | 4649 } |
| 4595 } | 4650 } |
| OLD | NEW |