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 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 |