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