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 SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 backend.constants.getConstantForNode(node, elements); | 1511 backend.constants.getConstantForNode(node, elements); |
1512 assert(invariant(node, constant != null, | 1512 assert(invariant(node, constant != null, |
1513 message: 'No constant computed for $node')); | 1513 message: 'No constant computed for $node')); |
1514 return constant.value; | 1514 return constant.value; |
1515 } | 1515 } |
1516 | 1516 |
1517 HInstruction addConstant(ast.Node node) { | 1517 HInstruction addConstant(ast.Node node) { |
1518 return graph.addConstant(getConstantForNode(node), compiler); | 1518 return graph.addConstant(getConstantForNode(node), compiler); |
1519 } | 1519 } |
1520 | 1520 |
1521 bool isLazilyInitialized(VariableElement element) { | |
1522 ConstantExpression initialValue = | |
1523 backend.constants.getConstantForVariable(element); | |
1524 return initialValue == null; | |
1525 } | |
1526 | |
1527 TypeMask cachedTypeOfThis; | 1521 TypeMask cachedTypeOfThis; |
1528 | 1522 |
1529 TypeMask getTypeOfThis() { | 1523 TypeMask getTypeOfThis() { |
1530 TypeMask result = cachedTypeOfThis; | 1524 TypeMask result = cachedTypeOfThis; |
1531 if (result == null) { | 1525 if (result == null) { |
1532 ThisLocal local = localsHandler.closureData.thisLocal; | 1526 ThisLocal local = localsHandler.closureData.thisLocal; |
1533 ClassElement cls = local.enclosingClass; | 1527 ClassElement cls = local.enclosingClass; |
1534 ClassWorld classWorld = compiler.world; | 1528 ClassWorld classWorld = compiler.world; |
1535 if (classWorld.isUsedAsMixin(cls)) { | 1529 if (classWorld.isUsedAsMixin(cls)) { |
1536 // If the enclosing class is used as a mixin, [:this:] can be | 1530 // If the enclosing class is used as a mixin, [:this:] can be |
(...skipping 1701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3238 deferredTask.importDeferName[prefixElement.deferredImport]; | 3232 deferredTask.importDeferName[prefixElement.deferredImport]; |
3239 HInstruction loadIdConstant = addConstantString(loadId); | 3233 HInstruction loadIdConstant = addConstantString(loadId); |
3240 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); | 3234 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); |
3241 HInstruction uriConstant = addConstantString(uri); | 3235 HInstruction uriConstant = addConstantString(uri); |
3242 Element helper = backend.getCheckDeferredIsLoaded(); | 3236 Element helper = backend.getCheckDeferredIsLoaded(); |
3243 pushInvokeStatic(node, helper, [loadIdConstant, uriConstant]); | 3237 pushInvokeStatic(node, helper, [loadIdConstant, uriConstant]); |
3244 pop(); | 3238 pop(); |
3245 } | 3239 } |
3246 } | 3240 } |
3247 | 3241 |
3248 void generateGetter(ast.Send send, Element element) { | 3242 /// Generate read access of an unresolved static or top level entity. |
3249 if (element != null && element.isForeign(backend)) { | 3243 void generateStaticUnresolvedGet(ast.Send node, Element element) { |
3250 visitForeignGetter(send); | 3244 if (element is ErroneousElement) { |
3251 } else if (Elements.isStaticOrTopLevelField(element)) { | 3245 // An erroneous element indicates an unresolved static getter. |
3252 ConstantExpression constant; | 3246 generateThrowNoSuchMethod( |
3253 if (element.isField && !element.isAssignable) { | 3247 node, |
| 3248 noSuchMethodTargetSymbolString(element, 'get'), |
| 3249 argumentNodes: const Link<ast.Node>()); |
| 3250 } else { |
| 3251 // This happens when [element] has parse errors. |
| 3252 assert(invariant(node, element.isErroneous)); |
| 3253 // TODO(ahe): Do something like the above, that is, emit a runtime |
| 3254 // error. |
| 3255 stack.add(graph.addConstantNull(compiler)); |
| 3256 } |
| 3257 } |
| 3258 |
| 3259 /// Read a static or top level [field] of constant value. |
| 3260 void generateStaticConstGet( |
| 3261 ast.Send node, |
| 3262 FieldElement field, |
| 3263 ConstantExpression constant) { |
| 3264 ConstantValue value = constant.value; |
| 3265 HConstant instruction; |
| 3266 // Constants that are referred via a deferred prefix should be referred |
| 3267 // by reference. |
| 3268 PrefixElement prefix = compiler.deferredLoadTask |
| 3269 .deferredPrefixElement(node, elements); |
| 3270 if (prefix != null) { |
| 3271 instruction = graph.addDeferredConstant(value, prefix, compiler); |
| 3272 } else { |
| 3273 instruction = graph.addConstant(value, compiler); |
| 3274 } |
| 3275 stack.add(instruction); |
| 3276 // The inferrer may have found a better type than the constant |
| 3277 // handler in the case of lists, because the constant handler |
| 3278 // does not look at elements in the list. |
| 3279 TypeMask type = |
| 3280 TypeMaskFactory.inferredTypeForElement(field, compiler); |
| 3281 if (!type.containsAll(compiler.world) && |
| 3282 !instruction.isConstantNull()) { |
| 3283 // TODO(13429): The inferrer should know that an element |
| 3284 // cannot be null. |
| 3285 instruction.instructionType = type.nonNullable(); |
| 3286 } |
| 3287 } |
| 3288 |
| 3289 /// Read a static or top level [field]. |
| 3290 void generateStaticFieldGet(ast.Send node, FieldElement field) { |
| 3291 generateIsDeferredLoadedCheckIfNeeded(node); |
| 3292 |
| 3293 ConstantExpression constant = |
| 3294 backend.constants.getConstantForVariable(field); |
| 3295 if (constant != null) { |
| 3296 if (!field.isAssignable) { |
3254 // A static final or const. Get its constant value and inline it if | 3297 // A static final or const. Get its constant value and inline it if |
3255 // the value can be compiled eagerly. | 3298 // the value can be compiled eagerly. |
3256 constant = backend.constants.getConstantForVariable(element); | 3299 generateStaticConstGet(node, field, constant); |
3257 } | 3300 } else { |
3258 if (constant != null) { | 3301 // TODO(5346): Try to avoid the need for calling [declaration] before |
3259 ConstantValue value = constant.value; | 3302 // creating an [HStatic]. |
3260 HConstant instruction; | 3303 HInstruction instruction = new HStatic( |
3261 // Constants that are referred via a deferred prefix should be referred | 3304 field.declaration, |
3262 // by reference. | 3305 TypeMaskFactory.inferredTypeForElement(field, compiler)); |
3263 PrefixElement prefix = compiler.deferredLoadTask | |
3264 .deferredPrefixElement(send, elements); | |
3265 if (prefix != null) { | |
3266 instruction = graph.addDeferredConstant(value, prefix, compiler); | |
3267 } else { | |
3268 instruction = graph.addConstant(value, compiler); | |
3269 } | |
3270 stack.add(instruction); | |
3271 // The inferrer may have found a better type than the constant | |
3272 // handler in the case of lists, because the constant handler | |
3273 // does not look at elements in the list. | |
3274 TypeMask type = | |
3275 TypeMaskFactory.inferredTypeForElement(element, compiler); | |
3276 if (!type.containsAll(compiler.world) && | |
3277 !instruction.isConstantNull()) { | |
3278 // TODO(13429): The inferrer should know that an element | |
3279 // cannot be null. | |
3280 instruction.instructionType = type.nonNullable(); | |
3281 } | |
3282 } else if (element.isField && isLazilyInitialized(element)) { | |
3283 HInstruction instruction = new HLazyStatic( | |
3284 element, | |
3285 TypeMaskFactory.inferredTypeForElement(element, compiler)); | |
3286 push(instruction); | 3306 push(instruction); |
3287 } else { | |
3288 if (element.isGetter) { | |
3289 pushInvokeStatic(send, element, <HInstruction>[]); | |
3290 } else { | |
3291 // TODO(5346): Try to avoid the need for calling [declaration] before | |
3292 // creating an [HStatic]. | |
3293 HInstruction instruction = new HStatic( | |
3294 element.declaration, | |
3295 TypeMaskFactory.inferredTypeForElement(element, compiler)); | |
3296 push(instruction); | |
3297 } | |
3298 } | |
3299 } else if (Elements.isInstanceSend(send, elements)) { | |
3300 HInstruction receiver = generateInstanceSendReceiver(send); | |
3301 generateInstanceGetterWithCompiledReceiver( | |
3302 send, elements.getSelector(send), receiver); | |
3303 } else if (Elements.isStaticOrTopLevelFunction(element)) { | |
3304 // TODO(5346): Try to avoid the need for calling [declaration] before | |
3305 // creating an [HStatic]. | |
3306 push(new HStatic(element.declaration, backend.nonNullType)); | |
3307 // TODO(ahe): This should be registered in codegen. | |
3308 registry.registerGetOfStaticFunction(element.declaration); | |
3309 } else if (Elements.isErroneous(element)) { | |
3310 if (element is ErroneousElement) { | |
3311 // An erroneous element indicates an unresolved static getter. | |
3312 generateThrowNoSuchMethod( | |
3313 send, | |
3314 noSuchMethodTargetSymbolString(element, 'get'), | |
3315 argumentNodes: const Link<ast.Node>()); | |
3316 } else { | |
3317 // TODO(ahe): Do something like the above, that is, emit a runtime | |
3318 // error. | |
3319 stack.add(graph.addConstantNull(compiler)); | |
3320 } | 3307 } |
3321 } else { | 3308 } else { |
3322 if (send.asSendSet() == null) { | 3309 HInstruction instruction = new HLazyStatic( |
3323 internalError(send, "Unhandled local: $element"); | 3310 field, |
3324 } | 3311 TypeMaskFactory.inferredTypeForElement(field, compiler)); |
3325 // TODO(johnniwinther): Remove this when [generateGetter] is no longer | 3312 push(instruction); |
3326 // called from [visitSendSet] (for compound assignments). | |
3327 handleLocalGet(element); | |
3328 } | 3313 } |
3329 } | 3314 } |
3330 | 3315 |
| 3316 /// Generate a getter invocation of the static or top level [getter]. |
| 3317 void generateStaticGetterGet(ast.Send node, MethodElement getter) { |
| 3318 if (getter.isDeferredLoaderGetter) { |
| 3319 generateDeferredLoaderGet(node, getter); |
| 3320 } else { |
| 3321 generateIsDeferredLoadedCheckIfNeeded(node); |
| 3322 pushInvokeStatic(node, getter, <HInstruction>[]); |
| 3323 } |
| 3324 } |
| 3325 |
| 3326 /// Generate a dynamic getter invocation. |
| 3327 void generateDynamicGet(ast.Send node) { |
| 3328 HInstruction receiver = generateInstanceSendReceiver(node); |
| 3329 generateInstanceGetterWithCompiledReceiver( |
| 3330 node, elements.getSelector(node), receiver); |
| 3331 } |
| 3332 |
| 3333 /// Generate a closurization of the static or top level [function]. |
| 3334 void generateStaticFunctionGet(ast.Send node, MethodElement function) { |
| 3335 generateIsDeferredLoadedCheckIfNeeded(node); |
| 3336 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3337 // creating an [HStatic]. |
| 3338 push(new HStatic(function.declaration, backend.nonNullType)); |
| 3339 // TODO(ahe): This should be registered in codegen. |
| 3340 registry.registerGetOfStaticFunction(function.declaration); |
| 3341 } |
| 3342 |
3331 /// Read a local variable, function or parameter. | 3343 /// Read a local variable, function or parameter. |
3332 void handleLocalGet(LocalElement local) { | 3344 void handleLocalGet(LocalElement local) { |
3333 stack.add(localsHandler.readLocal(local)); | 3345 stack.add(localsHandler.readLocal(local)); |
3334 } | 3346 } |
3335 | 3347 |
3336 @override | 3348 @override |
| 3349 void visitDynamicPropertyGet( |
| 3350 ast.Send node, |
| 3351 ast.Node receiver, |
| 3352 Selector selector, |
| 3353 _) { |
| 3354 generateDynamicGet(node); |
| 3355 } |
| 3356 |
| 3357 @override |
3337 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 3358 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
3338 handleLocalGet(variable); | 3359 handleLocalGet(variable); |
3339 } | 3360 } |
3340 | 3361 |
3341 @override | 3362 @override |
3342 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { | 3363 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { |
3343 handleLocalGet(parameter); | 3364 handleLocalGet(parameter); |
3344 } | 3365 } |
3345 | 3366 |
3346 @override | 3367 @override |
3347 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { | 3368 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { |
3348 handleLocalGet(function); | 3369 handleLocalGet(function); |
3349 } | 3370 } |
3350 | 3371 |
| 3372 @override |
| 3373 void visitStaticFieldGet( |
| 3374 ast.Send node, |
| 3375 FieldElement field, |
| 3376 _) { |
| 3377 generateStaticFieldGet(node, field); |
| 3378 } |
| 3379 |
| 3380 @override |
| 3381 void visitStaticFunctionGet( |
| 3382 ast.Send node, |
| 3383 MethodElement function, |
| 3384 _) { |
| 3385 generateStaticFunctionGet(node, function); |
| 3386 } |
| 3387 |
| 3388 @override |
| 3389 void visitStaticGetterGet( |
| 3390 ast.Send node, |
| 3391 FunctionElement getter, |
| 3392 _) { |
| 3393 generateStaticGetterGet(node, getter); |
| 3394 } |
| 3395 |
| 3396 @override |
| 3397 void visitThisPropertyGet( |
| 3398 ast.Send node, |
| 3399 Selector selector, |
| 3400 _) { |
| 3401 generateDynamicGet(node); |
| 3402 } |
| 3403 |
| 3404 @override |
| 3405 void visitTopLevelFieldGet( |
| 3406 ast.Send node, |
| 3407 FieldElement field, |
| 3408 _) { |
| 3409 generateStaticFieldGet(node, field); |
| 3410 } |
| 3411 |
| 3412 @override |
| 3413 void visitTopLevelFunctionGet( |
| 3414 ast.Send node, |
| 3415 MethodElement function, |
| 3416 _) { |
| 3417 generateStaticFunctionGet(node, function); |
| 3418 } |
| 3419 |
| 3420 @override |
| 3421 void visitTopLevelGetterGet( |
| 3422 ast.Send node, |
| 3423 FunctionElement getter, |
| 3424 _) { |
| 3425 generateStaticGetterGet(node, getter); |
| 3426 } |
| 3427 |
3351 void generateInstanceSetterWithCompiledReceiver(ast.Send send, | 3428 void generateInstanceSetterWithCompiledReceiver(ast.Send send, |
3352 HInstruction receiver, | 3429 HInstruction receiver, |
3353 HInstruction value, | 3430 HInstruction value, |
3354 {Selector selector, | 3431 {Selector selector, |
3355 ast.Node location}) { | 3432 ast.Node location}) { |
3356 assert(send == null || Elements.isInstanceSend(send, elements)); | 3433 assert(send == null || Elements.isInstanceSend(send, elements)); |
3357 if (selector == null) { | 3434 if (selector == null) { |
3358 assert(send != null); | 3435 assert(send != null); |
3359 selector = elements.getSelector(send); | 3436 selector = elements.getSelector(send); |
3360 } | 3437 } |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4007 | 4084 |
4008 void handleForeignJsCurrentIsolate(ast.Send node) { | 4085 void handleForeignJsCurrentIsolate(ast.Send node) { |
4009 if (!node.arguments.isEmpty) { | 4086 if (!node.arguments.isEmpty) { |
4010 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 4087 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
4011 } | 4088 } |
4012 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), | 4089 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), |
4013 backend.dynamicType, | 4090 backend.dynamicType, |
4014 <HInstruction>[])); | 4091 <HInstruction>[])); |
4015 } | 4092 } |
4016 | 4093 |
4017 visitForeignSend(ast.Send node) { | 4094 void handleForeignSend(ast.Send node, FunctionElement element) { |
4018 Selector selector = elements.getSelector(node); | 4095 String name = element.name; |
4019 String name = selector.name; | |
4020 if (name == 'JS') { | 4096 if (name == 'JS') { |
4021 handleForeignJs(node); | 4097 handleForeignJs(node); |
4022 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { | 4098 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { |
4023 handleForeignJsCurrentIsolateContext(node); | 4099 handleForeignJsCurrentIsolateContext(node); |
4024 } else if (name == 'JS_CALL_IN_ISOLATE') { | 4100 } else if (name == 'JS_CALL_IN_ISOLATE') { |
4025 handleForeignJsCallInIsolate(node); | 4101 handleForeignJsCallInIsolate(node); |
4026 } else if (name == 'DART_CLOSURE_TO_JS') { | 4102 } else if (name == 'DART_CLOSURE_TO_JS') { |
4027 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); | 4103 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); |
4028 } else if (name == 'RAW_DART_FUNCTION_REF') { | 4104 } else if (name == 'RAW_DART_FUNCTION_REF') { |
4029 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); | 4105 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4084 handleForeignJsBuiltin(node); | 4160 handleForeignJsBuiltin(node); |
4085 } else if (name == 'JS_GET_FLAG') { | 4161 } else if (name == 'JS_GET_FLAG') { |
4086 handleForeingJsGetFlag(node); | 4162 handleForeingJsGetFlag(node); |
4087 } else if (name == 'JS_EFFECT') { | 4163 } else if (name == 'JS_EFFECT') { |
4088 stack.add(graph.addConstantNull(compiler)); | 4164 stack.add(graph.addConstantNull(compiler)); |
4089 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4165 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
4090 handleJsInterceptorConstant(node); | 4166 handleJsInterceptorConstant(node); |
4091 } else if (name == 'JS_STRING_CONCAT') { | 4167 } else if (name == 'JS_STRING_CONCAT') { |
4092 handleJsStringConcat(node); | 4168 handleJsStringConcat(node); |
4093 } else { | 4169 } else { |
4094 throw "Unknown foreign: ${selector}"; | 4170 throw "Unknown foreign: ${element}"; |
4095 } | 4171 } |
4096 } | 4172 } |
4097 | 4173 |
4098 visitForeignGetter(ast.Send node) { | 4174 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader) { |
4099 Element element = elements[node]; | |
4100 // Until now we only handle these as getters. | 4175 // Until now we only handle these as getters. |
4101 invariant(node, element.isDeferredLoaderGetter); | 4176 invariant(node, deferredLoader.isDeferredLoaderGetter); |
4102 FunctionElement deferredLoader = element; | |
4103 Element loadFunction = compiler.loadLibraryFunction; | 4177 Element loadFunction = compiler.loadLibraryFunction; |
4104 PrefixElement prefixElement = deferredLoader.enclosingElement; | 4178 PrefixElement prefixElement = deferredLoader.enclosingElement; |
4105 String loadId = compiler.deferredLoadTask | 4179 String loadId = compiler.deferredLoadTask |
4106 .importDeferName[prefixElement.deferredImport]; | 4180 .importDeferName[prefixElement.deferredImport]; |
4107 var inputs = [graph.addConstantString( | 4181 var inputs = [graph.addConstantString( |
4108 new ast.DartString.literal(loadId), compiler)]; | 4182 new ast.DartString.literal(loadId), compiler)]; |
4109 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, | 4183 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, |
4110 targetCanThrow: false)); | 4184 targetCanThrow: false)); |
4111 } | 4185 } |
4112 | 4186 |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4791 } | 4865 } |
4792 | 4866 |
4793 @override | 4867 @override |
4794 visitAssert(ast.Send node, ast.Node expression, _) { | 4868 visitAssert(ast.Send node, ast.Node expression, _) { |
4795 if (!compiler.enableUserAssertions) { | 4869 if (!compiler.enableUserAssertions) { |
4796 stack.add(graph.addConstantNull(compiler)); | 4870 stack.add(graph.addConstantNull(compiler)); |
4797 return; | 4871 return; |
4798 } | 4872 } |
4799 assert(invariant(node, node.arguments.tail.isEmpty, | 4873 assert(invariant(node, node.arguments.tail.isEmpty, |
4800 message: "Invalid assertion: $node")); | 4874 message: "Invalid assertion: $node")); |
4801 buildStaticFunctionInvoke( | 4875 generateStaticFunctionInvoke( |
4802 node, backend.assertMethod, CallStructure.ONE_ARG); | 4876 node, backend.assertMethod, CallStructure.ONE_ARG); |
4803 } | 4877 } |
4804 | 4878 |
4805 visitStaticSend(ast.Send node) { | 4879 visitStaticSend(ast.Send node) { |
4806 CallStructure callStructure = elements.getSelector(node).callStructure; | 4880 internalError(node, "Unexpected visitStaticSend"); |
4807 Element element = elements[node]; | |
4808 if (elements.isAssert(node)) { | |
4809 element = backend.assertMethod; | |
4810 } | |
4811 if (element.isForeign(backend) && element.isFunction) { | |
4812 visitForeignSend(node); | |
4813 return; | |
4814 } | |
4815 if (element.isErroneous) { | |
4816 if (element is ErroneousElement) { | |
4817 // An erroneous element indicates that the funciton could not be | |
4818 // resolved (a warning has been issued). | |
4819 generateThrowNoSuchMethod(node, | |
4820 noSuchMethodTargetSymbolString(element), | |
4821 argumentNodes: node.arguments); | |
4822 } else { | |
4823 // TODO(ahe): Do something like [generateWrongArgumentCountError]. | |
4824 stack.add(graph.addConstantNull(compiler)); | |
4825 } | |
4826 return; | |
4827 } | |
4828 invariant(element, !element.isGenerativeConstructor); | |
4829 generateIsDeferredLoadedCheckIfNeeded(node); | |
4830 if (element.isFunction) { | |
4831 // TODO(5347): Try to avoid the need for calling [implementation] before | |
4832 // calling [makeStaticArgumentList]. | |
4833 if (!callStructure.signatureApplies(element.implementation)) { | |
4834 generateWrongArgumentCountError(node, element, node.arguments); | |
4835 return; | |
4836 } | |
4837 buildStaticFunctionInvoke(node, element, callStructure); | |
4838 } else { | |
4839 generateGetter(node, element); | |
4840 List<HInstruction> inputs = <HInstruction>[pop()]; | |
4841 addDynamicSendArgumentsToList(node, inputs); | |
4842 Selector closureSelector = callStructure.callSelector; | |
4843 pushWithPosition( | |
4844 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), | |
4845 node); | |
4846 } | |
4847 } | 4881 } |
4848 | 4882 |
4849 void buildStaticFunctionInvoke( | 4883 /// Generate an invocation to the static or top level [function]. |
| 4884 void generateStaticFunctionInvoke( |
4850 ast.Send node, | 4885 ast.Send node, |
4851 FunctionElement element, | 4886 FunctionElement function, |
4852 CallStructure callStructure) { | 4887 CallStructure callStructure) { |
4853 List<HInstruction> inputs = makeStaticArgumentList( | 4888 List<HInstruction> inputs = makeStaticArgumentList( |
4854 callStructure, | 4889 callStructure, |
4855 node.arguments, | 4890 node.arguments, |
4856 element.implementation); | 4891 function.implementation); |
4857 | 4892 |
4858 if (element == compiler.identicalFunction) { | 4893 if (function == compiler.identicalFunction) { |
4859 pushWithPosition( | 4894 pushWithPosition( |
4860 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); | 4895 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); |
4861 return; | 4896 return; |
4862 } else { | 4897 } else { |
4863 pushInvokeStatic(node, element, inputs); | 4898 pushInvokeStatic(node, function, inputs); |
4864 } | 4899 } |
4865 } | 4900 } |
4866 | 4901 |
| 4902 /// Generate an invocation to a static or top level function with the wrong |
| 4903 /// number of arguments. |
| 4904 void generateStaticFunctionIncompatibleInvoke(ast.Send node, |
| 4905 Element element) { |
| 4906 generateWrongArgumentCountError(node, element, node.arguments); |
| 4907 } |
| 4908 |
| 4909 @override |
| 4910 void visitStaticFieldInvoke( |
| 4911 ast.Send node, |
| 4912 FieldElement field, |
| 4913 ast.NodeList arguments, |
| 4914 CallStructure callStructure, |
| 4915 _) { |
| 4916 generateStaticFieldGet(node, field); |
| 4917 generateCallInvoke(node, pop()); |
| 4918 } |
| 4919 |
| 4920 @override |
| 4921 void visitStaticFunctionInvoke( |
| 4922 ast.Send node, |
| 4923 MethodElement function, |
| 4924 ast.NodeList arguments, |
| 4925 CallStructure callStructure, |
| 4926 _) { |
| 4927 generateStaticFunctionInvoke(node, function, callStructure); |
| 4928 } |
| 4929 |
| 4930 @override |
| 4931 void visitStaticFunctionIncompatibleInvoke( |
| 4932 ast.Send node, |
| 4933 MethodElement function, |
| 4934 ast.NodeList arguments, |
| 4935 CallStructure callStructure, |
| 4936 _) { |
| 4937 generateStaticFunctionIncompatibleInvoke(node, function); |
| 4938 } |
| 4939 |
| 4940 @override |
| 4941 void visitStaticGetterInvoke( |
| 4942 ast.Send node, |
| 4943 FunctionElement getter, |
| 4944 ast.NodeList arguments, |
| 4945 CallStructure callStructure, |
| 4946 _) { |
| 4947 generateStaticGetterGet(node, getter); |
| 4948 generateCallInvoke(node, pop()); |
| 4949 } |
| 4950 |
| 4951 @override |
| 4952 void visitTopLevelFieldInvoke( |
| 4953 ast.Send node, |
| 4954 FieldElement field, |
| 4955 ast.NodeList arguments, |
| 4956 CallStructure callStructure, |
| 4957 _) { |
| 4958 generateStaticFieldGet(node, field); |
| 4959 generateCallInvoke(node, pop()); |
| 4960 } |
| 4961 |
| 4962 @override |
| 4963 void visitTopLevelFunctionInvoke( |
| 4964 ast.Send node, |
| 4965 MethodElement function, |
| 4966 ast.NodeList arguments, |
| 4967 CallStructure callStructure, |
| 4968 _) { |
| 4969 if (function.isForeign(backend)) { |
| 4970 handleForeignSend(node, function); |
| 4971 } else { |
| 4972 generateStaticFunctionInvoke(node, function, callStructure); |
| 4973 } |
| 4974 } |
| 4975 |
| 4976 @override |
| 4977 void visitTopLevelFunctionIncompatibleInvoke( |
| 4978 ast.Send node, |
| 4979 MethodElement function, |
| 4980 ast.NodeList arguments, |
| 4981 CallStructure callStructure, |
| 4982 _) { |
| 4983 generateStaticFunctionIncompatibleInvoke(node, function); |
| 4984 } |
| 4985 |
| 4986 @override |
| 4987 void visitTopLevelGetterInvoke( |
| 4988 ast.Send node, |
| 4989 FunctionElement getter, |
| 4990 ast.NodeList arguments, |
| 4991 CallStructure callStructure, |
| 4992 _) { |
| 4993 generateStaticGetterGet(node, getter); |
| 4994 generateCallInvoke(node, pop()); |
| 4995 } |
| 4996 |
| 4997 @override |
| 4998 void visitUnresolvedGet( |
| 4999 ast.Send node, |
| 5000 Element element, |
| 5001 _) { |
| 5002 generateStaticUnresolvedGet(node, element); |
| 5003 } |
| 5004 |
| 5005 @override |
| 5006 void visitUnresolvedInvoke( |
| 5007 ast.Send node, |
| 5008 Element element, |
| 5009 ast.NodeList arguments, |
| 5010 Selector selector, |
| 5011 _) { |
| 5012 if (element is ErroneousElement) { |
| 5013 // An erroneous element indicates that the funciton could not be |
| 5014 // resolved (a warning has been issued). |
| 5015 generateThrowNoSuchMethod(node, |
| 5016 noSuchMethodTargetSymbolString(element), |
| 5017 argumentNodes: node.arguments); |
| 5018 } else { |
| 5019 // TODO(ahe): Do something like [generateWrongArgumentCountError]. |
| 5020 stack.add(graph.addConstantNull(compiler)); |
| 5021 } |
| 5022 return; |
| 5023 } |
| 5024 |
4867 HConstant addConstantString(String string) { | 5025 HConstant addConstantString(String string) { |
4868 ast.DartString dartString = new ast.DartString.literal(string); | 5026 ast.DartString dartString = new ast.DartString.literal(string); |
4869 ConstantValue constant = constantSystem.createString(dartString); | 5027 ConstantValue constant = constantSystem.createString(dartString); |
4870 return graph.addConstant(constant, compiler); | 5028 return graph.addConstant(constant, compiler); |
4871 } | 5029 } |
4872 | 5030 |
4873 visitClassTypeLiteralGet( | 5031 visitClassTypeLiteralGet( |
4874 ast.Send node, | 5032 ast.Send node, |
4875 ConstantExpression constant, | 5033 ConstantExpression constant, |
4876 _) { | 5034 _) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4978 void generateCallInvoke(ast.Send node, HInstruction target) { | 5136 void generateCallInvoke(ast.Send node, HInstruction target) { |
4979 Selector selector = elements.getSelector(node); | 5137 Selector selector = elements.getSelector(node); |
4980 List<HInstruction> inputs = <HInstruction>[target]; | 5138 List<HInstruction> inputs = <HInstruction>[target]; |
4981 addDynamicSendArgumentsToList(node, inputs); | 5139 addDynamicSendArgumentsToList(node, inputs); |
4982 Selector closureSelector = new Selector.callClosureFrom(selector); | 5140 Selector closureSelector = new Selector.callClosureFrom(selector); |
4983 pushWithPosition( | 5141 pushWithPosition( |
4984 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node); | 5142 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node); |
4985 } | 5143 } |
4986 | 5144 |
4987 visitGetterSend(ast.Send node) { | 5145 visitGetterSend(ast.Send node) { |
4988 generateIsDeferredLoadedCheckIfNeeded(node); | 5146 internalError(node, "Unexpected visitGetterSend"); |
4989 generateGetter(node, elements[node]); | |
4990 } | 5147 } |
4991 | 5148 |
4992 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 5149 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
4993 internalError(Spannable node, String reason) { | 5150 internalError(Spannable node, String reason) { |
4994 compiler.internalError(node, reason); | 5151 compiler.internalError(node, reason); |
4995 } | 5152 } |
4996 | 5153 |
4997 void generateError(ast.Node node, String message, Element helper) { | 5154 void generateError(ast.Node node, String message, Element helper) { |
4998 HInstruction errorMessage = addConstantString(message); | 5155 HInstruction errorMessage = addConstantString(message); |
4999 pushInvokeStatic(node, helper, [errorMessage]); | 5156 pushInvokeStatic(node, helper, [errorMessage]); |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5383 | 5540 |
5384 if (!Elements.isUnresolved(getter) && getter.impliesType) { | 5541 if (!Elements.isUnresolved(getter) && getter.impliesType) { |
5385 ast.Identifier selector = node.selector; | 5542 ast.Identifier selector = node.selector; |
5386 generateThrowNoSuchMethod(node, selector.source, | 5543 generateThrowNoSuchMethod(node, selector.source, |
5387 argumentNodes: node.arguments); | 5544 argumentNodes: node.arguments); |
5388 return; | 5545 return; |
5389 } else if (Elements.isInstanceSend(node, elements)) { | 5546 } else if (Elements.isInstanceSend(node, elements)) { |
5390 receiver = generateInstanceSendReceiver(node); | 5547 receiver = generateInstanceSendReceiver(node); |
5391 generateInstanceGetterWithCompiledReceiver( | 5548 generateInstanceGetterWithCompiledReceiver( |
5392 node, elements.getGetterSelectorInComplexSendSet(node), receiver); | 5549 node, elements.getGetterSelectorInComplexSendSet(node), receiver); |
| 5550 } else if (getter.isErroneous) { |
| 5551 generateStaticUnresolvedGet(node, getter); |
| 5552 } else if (getter.isField) { |
| 5553 generateStaticFieldGet(node, getter); |
| 5554 } else if (getter.isGetter) { |
| 5555 generateStaticGetterGet(node, getter); |
| 5556 } else if (getter.isFunction) { |
| 5557 generateStaticFunctionGet(node, getter); |
| 5558 } else if (getter.isLocal) { |
| 5559 handleLocalGet(getter); |
5393 } else { | 5560 } else { |
5394 generateGetter(node, getter); | 5561 internalError(node, "Unexpected getter: $getter"); |
5395 } | 5562 } |
5396 HInstruction getterInstruction = pop(); | 5563 HInstruction getterInstruction = pop(); |
5397 handleComplexOperatorSend(node, getterInstruction, node.arguments); | 5564 handleComplexOperatorSend(node, getterInstruction, node.arguments); |
5398 HInstruction value = pop(); | 5565 HInstruction value = pop(); |
5399 assert(value != null); | 5566 assert(value != null); |
5400 if (Elements.isInstanceSend(node, elements)) { | 5567 if (Elements.isInstanceSend(node, elements)) { |
5401 assert(receiver != null); | 5568 assert(receiver != null); |
5402 generateInstanceSetterWithCompiledReceiver(node, receiver, value); | 5569 generateInstanceSetterWithCompiledReceiver(node, receiver, value); |
5403 } else { | 5570 } else { |
5404 assert(receiver == null); | 5571 assert(receiver == null); |
(...skipping 2015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7420 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7587 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
7421 unaliased.accept(this, builder); | 7588 unaliased.accept(this, builder); |
7422 } | 7589 } |
7423 | 7590 |
7424 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7591 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
7425 JavaScriptBackend backend = builder.compiler.backend; | 7592 JavaScriptBackend backend = builder.compiler.backend; |
7426 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7593 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
7427 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7594 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
7428 } | 7595 } |
7429 } | 7596 } |
OLD | NEW |