| 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 /** | 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 implement [TypedElement.type] because our | 9 * methods. We need to implement [TypedElement.type] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1165 | 1165 |
| 1166 // Bail out early if the inlining decision is in the cache and we can't | 1166 // Bail out early if the inlining decision is in the cache and we can't |
| 1167 // inline (no need to check the hard constraints). | 1167 // inline (no need to check the hard constraints). |
| 1168 bool cachedCanBeInlined = | 1168 bool cachedCanBeInlined = |
| 1169 backend.inlineCache.canInline(function, insideLoop: insideLoop); | 1169 backend.inlineCache.canInline(function, insideLoop: insideLoop); |
| 1170 if (cachedCanBeInlined == false) return false; | 1170 if (cachedCanBeInlined == false) return false; |
| 1171 | 1171 |
| 1172 bool meetsHardConstraints() { | 1172 bool meetsHardConstraints() { |
| 1173 // Don't inline from one output unit to another. If something is deferred | 1173 // Don't inline from one output unit to another. If something is deferred |
| 1174 // it is to save space in the loading code. | 1174 // it is to save space in the loading code. |
| 1175 var getOutputUnit = compiler.deferredLoadTask.outputUnitForElement; | 1175 if (!compiler.deferredLoadTask |
| 1176 if (getOutputUnit(element) != | 1176 .inSameOutputUnit(element,compiler.currentElement)) { |
| 1177 getOutputUnit(compiler.currentElement)) { | |
| 1178 return false; | 1177 return false; |
| 1179 } | 1178 } |
| 1180 if (compiler.disableInlining) return false; | 1179 if (compiler.disableInlining) return false; |
| 1181 | 1180 |
| 1182 assert(selector != null | 1181 assert(selector != null |
| 1183 || Elements.isStaticOrTopLevel(element) | 1182 || Elements.isStaticOrTopLevel(element) |
| 1184 || element.isGenerativeConstructorBody()); | 1183 || element.isGenerativeConstructorBody()); |
| 1185 if (selector != null && !selector.applies(function, compiler)) { | 1184 if (selector != null && !selector.applies(function, compiler)) { |
| 1186 return false; | 1185 return false; |
| 1187 } | 1186 } |
| (...skipping 1734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2922 * [selector]. | 2921 * [selector]. |
| 2923 */ | 2922 */ |
| 2924 void generateInstanceGetterWithCompiledReceiver(ast.Send send, | 2923 void generateInstanceGetterWithCompiledReceiver(ast.Send send, |
| 2925 Selector selector, | 2924 Selector selector, |
| 2926 HInstruction receiver) { | 2925 HInstruction receiver) { |
| 2927 assert(Elements.isInstanceSend(send, elements)); | 2926 assert(Elements.isInstanceSend(send, elements)); |
| 2928 assert(selector.isGetter()); | 2927 assert(selector.isGetter()); |
| 2929 pushInvokeDynamic(send, selector, [receiver]); | 2928 pushInvokeDynamic(send, selector, [receiver]); |
| 2930 } | 2929 } |
| 2931 | 2930 |
| 2931 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that |
| 2932 /// resolves to a deferred library. |
| 2933 void generateIsDeferredLoadedCheckIfNeeded(ast.Send node) { |
| 2934 DeferredLoadTask deferredTask = compiler.deferredLoadTask; |
| 2935 PrefixElement prefixElement = |
| 2936 deferredTask.deferredPrefixElement(node, elements); |
| 2937 if (prefixElement != null) { |
| 2938 String loadId = |
| 2939 deferredTask.importDeferName[prefixElement.deferredImport]; |
| 2940 HInstruction loadIdConstant = addConstantString(loadId); |
| 2941 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); |
| 2942 HInstruction uriConstant = addConstantString(uri); |
| 2943 Element helper = backend.getCheckDeferredIsLoaded(); |
| 2944 pushInvokeStatic(node, helper, [loadIdConstant, uriConstant]); |
| 2945 pop(); |
| 2946 } |
| 2947 } |
| 2948 |
| 2932 void generateGetter(ast.Send send, Element element) { | 2949 void generateGetter(ast.Send send, Element element) { |
| 2933 if (element != null && element.isForeign(compiler)) { | 2950 if (element != null && element.isForeign(compiler)) { |
| 2934 visitForeignGetter(send); | 2951 visitForeignGetter(send); |
| 2935 } else if (Elements.isStaticOrTopLevelField(element)) { | 2952 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 2936 Constant value; | 2953 Constant value; |
| 2937 if (element.isField() && !element.isAssignable()) { | 2954 if (element.isField() && !element.isAssignable()) { |
| 2938 // A static final or const. Get its constant value and inline it if | 2955 // A static final or const. Get its constant value and inline it if |
| 2939 // the value can be compiled eagerly. | 2956 // the value can be compiled eagerly. |
| 2940 value = backend.constants.getConstantForVariable(element); | 2957 value = backend.constants.getConstantForVariable(element); |
| 2941 } | 2958 } |
| (...skipping 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3902 // The new object will now be referenced through the | 3919 // The new object will now be referenced through the |
| 3903 // `setRuntimeTypeInfo` call. We therefore set the type of that | 3920 // `setRuntimeTypeInfo` call. We therefore set the type of that |
| 3904 // instruction to be of the object's type. | 3921 // instruction to be of the object's type. |
| 3905 assert(stack.last is HInvokeStatic || stack.last == newObject); | 3922 assert(stack.last is HInvokeStatic || stack.last == newObject); |
| 3906 stack.last.instructionType = newObject.instructionType; | 3923 stack.last.instructionType = newObject.instructionType; |
| 3907 return pop(); | 3924 return pop(); |
| 3908 } | 3925 } |
| 3909 | 3926 |
| 3910 handleNewSend(ast.NewExpression node) { | 3927 handleNewSend(ast.NewExpression node) { |
| 3911 ast.Send send = node.send; | 3928 ast.Send send = node.send; |
| 3929 generateIsDeferredLoadedCheckIfNeeded(send); |
| 3930 |
| 3912 bool isFixedList = false; | 3931 bool isFixedList = false; |
| 3913 bool isFixedListConstructorCall = | 3932 bool isFixedListConstructorCall = |
| 3914 Elements.isFixedListConstructorCall(elements[send], send, compiler); | 3933 Elements.isFixedListConstructorCall(elements[send], send, compiler); |
| 3915 bool isGrowableListConstructorCall = | 3934 bool isGrowableListConstructorCall = |
| 3916 Elements.isGrowableListConstructorCall(elements[send], send, compiler); | 3935 Elements.isGrowableListConstructorCall(elements[send], send, compiler); |
| 3917 | 3936 |
| 3918 TypeMask computeType(element) { | 3937 TypeMask computeType(element) { |
| 3919 Element originalElement = elements[send]; | 3938 Element originalElement = elements[send]; |
| 3920 if (isFixedListConstructorCall | 3939 if (isFixedListConstructorCall |
| 3921 || Elements.isFilledListConstructorCall( | 3940 || Elements.isFilledListConstructorCall( |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4153 } | 4172 } |
| 4154 if (element.isErroneous()) { | 4173 if (element.isErroneous()) { |
| 4155 // An erroneous element indicates that the funciton could not be resolved | 4174 // An erroneous element indicates that the funciton could not be resolved |
| 4156 // (a warning has been issued). | 4175 // (a warning has been issued). |
| 4157 generateThrowNoSuchMethod(node, | 4176 generateThrowNoSuchMethod(node, |
| 4158 getTargetName(element), | 4177 getTargetName(element), |
| 4159 argumentNodes: node.arguments); | 4178 argumentNodes: node.arguments); |
| 4160 return; | 4179 return; |
| 4161 } | 4180 } |
| 4162 invariant(element, !element.isGenerativeConstructor()); | 4181 invariant(element, !element.isGenerativeConstructor()); |
| 4182 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4163 if (element.isFunction()) { | 4183 if (element.isFunction()) { |
| 4164 var inputs = <HInstruction>[]; | 4184 var inputs = <HInstruction>[]; |
| 4165 // TODO(5347): Try to avoid the need for calling [implementation] before | 4185 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4166 // calling [addStaticSendArgumentsToList]. | 4186 // calling [addStaticSendArgumentsToList]. |
| 4167 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 4187 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 4168 element.implementation, | 4188 element.implementation, |
| 4169 inputs); | 4189 inputs); |
| 4170 if (!succeeded) { | 4190 if (!succeeded) { |
| 4171 generateWrongArgumentCountError(node, element, node.arguments); | 4191 generateWrongArgumentCountError(node, element, node.arguments); |
| 4172 return; | 4192 return; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4228 HInstruction target = pop(); | 4248 HInstruction target = pop(); |
| 4229 Selector selector = elements.getSelector(node); | 4249 Selector selector = elements.getSelector(node); |
| 4230 List<HInstruction> inputs = <HInstruction>[target]; | 4250 List<HInstruction> inputs = <HInstruction>[target]; |
| 4231 addDynamicSendArgumentsToList(node, inputs); | 4251 addDynamicSendArgumentsToList(node, inputs); |
| 4232 Selector closureSelector = new Selector.callClosureFrom(selector); | 4252 Selector closureSelector = new Selector.callClosureFrom(selector); |
| 4233 push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType)); | 4253 push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType)); |
| 4234 } | 4254 } |
| 4235 } | 4255 } |
| 4236 | 4256 |
| 4237 visitGetterSend(ast.Send node) { | 4257 visitGetterSend(ast.Send node) { |
| 4258 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4238 generateGetter(node, elements[node]); | 4259 generateGetter(node, elements[node]); |
| 4239 } | 4260 } |
| 4240 | 4261 |
| 4241 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 4262 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
| 4242 internalError(String reason, {ast.Node node}) { | 4263 internalError(String reason, {ast.Node node}) { |
| 4243 compiler.internalError(node, reason); | 4264 compiler.internalError(node, reason); |
| 4244 } | 4265 } |
| 4245 | 4266 |
| 4246 void generateError(ast.Node node, String message, Element helper) { | 4267 void generateError(ast.Node node, String message, Element helper) { |
| 4247 HInstruction errorMessage = addConstantString(message); | 4268 HInstruction errorMessage = addConstantString(message); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4496 } else { | 4517 } else { |
| 4497 visit(arguments.head); | 4518 visit(arguments.head); |
| 4498 assert(arguments.tail.isEmpty); | 4519 assert(arguments.tail.isEmpty); |
| 4499 rhs = pop(); | 4520 rhs = pop(); |
| 4500 } | 4521 } |
| 4501 visitBinary(receiver, node.assignmentOperator, rhs, | 4522 visitBinary(receiver, node.assignmentOperator, rhs, |
| 4502 elements.getOperatorSelectorInComplexSendSet(node), node); | 4523 elements.getOperatorSelectorInComplexSendSet(node), node); |
| 4503 } | 4524 } |
| 4504 | 4525 |
| 4505 visitSendSet(ast.SendSet node) { | 4526 visitSendSet(ast.SendSet node) { |
| 4527 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4506 Element element = elements[node]; | 4528 Element element = elements[node]; |
| 4507 if (!Elements.isUnresolved(element) && element.impliesType()) { | 4529 if (!Elements.isUnresolved(element) && element.impliesType()) { |
| 4508 ast.Identifier selector = node.selector; | 4530 ast.Identifier selector = node.selector; |
| 4509 generateThrowNoSuchMethod(node, selector.source, | 4531 generateThrowNoSuchMethod(node, selector.source, |
| 4510 argumentNodes: node.arguments); | 4532 argumentNodes: node.arguments); |
| 4511 return; | 4533 return; |
| 4512 } | 4534 } |
| 4513 ast.Operator op = node.assignmentOperator; | 4535 ast.Operator op = node.assignmentOperator; |
| 4514 if (node.isSuperCall) { | 4536 if (node.isSuperCall) { |
| 4515 HInstruction result; | 4537 HInstruction result; |
| (...skipping 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6258 DartType unaliased = type.unalias(builder.compiler); | 6280 DartType unaliased = type.unalias(builder.compiler); |
| 6259 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6281 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6260 unaliased.accept(this, builder); | 6282 unaliased.accept(this, builder); |
| 6261 } | 6283 } |
| 6262 | 6284 |
| 6263 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6285 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6264 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); | 6286 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); |
| 6265 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); | 6287 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 6266 } | 6288 } |
| 6267 } | 6289 } |
| OLD | NEW |