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 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1290 } | 1290 } |
1291 return compiledArguments; | 1291 return compiledArguments; |
1292 } | 1292 } |
1293 | 1293 |
1294 /** | 1294 /** |
1295 * Try to inline [element] within the currect context of the builder. The | 1295 * Try to inline [element] within the currect context of the builder. The |
1296 * insertion point is the state of the builder. | 1296 * insertion point is the state of the builder. |
1297 */ | 1297 */ |
1298 bool tryInlineMethod(Element element, | 1298 bool tryInlineMethod(Element element, |
1299 Selector selector, | 1299 Selector selector, |
1300 TypeMask mask, | |
1301 List<HInstruction> providedArguments, | 1300 List<HInstruction> providedArguments, |
1302 ast.Node currentNode, | 1301 ast.Node currentNode, |
1303 {InterfaceType instanceType}) { | 1302 {InterfaceType instanceType}) { |
1304 // TODO(johnniwinther): Register this on the [registry]. Currently the | 1303 // TODO(johnniwinther): Register this on the [registry]. Currently the |
1305 // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be | 1304 // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be |
1306 // enqueued. | 1305 // enqueued. |
1307 backend.registerStaticUse(element, compiler.enqueuer.codegen); | 1306 backend.registerStaticUse(element, compiler.enqueuer.codegen); |
1308 | 1307 |
1309 // Ensure that [element] is an implementation element. | 1308 // Ensure that [element] is an implementation element. |
1310 element = element.implementation; | 1309 element = element.implementation; |
(...skipping 11 matching lines...) Expand all Loading... |
1322 | 1321 |
1323 bool meetsHardConstraints() { | 1322 bool meetsHardConstraints() { |
1324 if (compiler.disableInlining) return false; | 1323 if (compiler.disableInlining) return false; |
1325 | 1324 |
1326 assert(invariant( | 1325 assert(invariant( |
1327 currentNode != null ? currentNode : element, | 1326 currentNode != null ? currentNode : element, |
1328 selector != null || | 1327 selector != null || |
1329 Elements.isStaticOrTopLevel(element) || | 1328 Elements.isStaticOrTopLevel(element) || |
1330 element.isGenerativeConstructorBody, | 1329 element.isGenerativeConstructorBody, |
1331 message: "Missing selector for inlining of $element.")); | 1330 message: "Missing selector for inlining of $element.")); |
1332 if (selector != null) { | 1331 if (selector != null && !selector.applies(function, compiler.world)) { |
1333 if (!selector.applies(function, compiler.world)) return false; | 1332 return false; |
1334 if (mask != null && !mask.canHit(function, selector, compiler.world)) { | |
1335 return false; | |
1336 } | |
1337 } | 1333 } |
1338 | 1334 |
1339 // Don't inline operator== methods if the parameter can be null. | 1335 // Don't inline operator== methods if the parameter can be null. |
1340 if (element.name == '==') { | 1336 if (element.name == '==') { |
1341 if (element.enclosingClass != compiler.objectClass | 1337 if (element.enclosingClass != compiler.objectClass |
1342 && providedArguments[1].canBeNull()) { | 1338 && providedArguments[1].canBeNull()) { |
1343 return false; | 1339 return false; |
1344 } | 1340 } |
1345 } | 1341 } |
1346 | 1342 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 } else { | 1441 } else { |
1446 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 1442 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
1447 } | 1443 } |
1448 return canInline; | 1444 return canInline; |
1449 } | 1445 } |
1450 | 1446 |
1451 void doInlining() { | 1447 void doInlining() { |
1452 // Add an explicit null check on the receiver before doing the | 1448 // Add an explicit null check on the receiver before doing the |
1453 // inlining. We use [element] to get the same name in the | 1449 // inlining. We use [element] to get the same name in the |
1454 // NoSuchMethodError message as if we had called it. | 1450 // NoSuchMethodError message as if we had called it. |
1455 if (element.isInstanceMember && | 1451 if (element.isInstanceMember |
1456 !element.isGenerativeConstructorBody && | 1452 && !element.isGenerativeConstructorBody |
1457 (mask == null || mask.isNullable)) { | 1453 && (selector.mask == null || selector.mask.isNullable)) { |
1458 addWithPosition( | 1454 addWithPosition( |
1459 new HFieldGet(null, providedArguments[0], backend.dynamicType, | 1455 new HFieldGet(null, providedArguments[0], backend.dynamicType, |
1460 isAssignable: false), | 1456 isAssignable: false), |
1461 currentNode); | 1457 currentNode); |
1462 } | 1458 } |
1463 List<HInstruction> compiledArguments = completeSendArgumentsList( | 1459 List<HInstruction> compiledArguments = completeSendArgumentsList( |
1464 function, selector, providedArguments, currentNode); | 1460 function, selector, providedArguments, currentNode); |
1465 enterInlinedMethod( | 1461 enterInlinedMethod( |
1466 function, currentNode, compiledArguments, instanceType: instanceType); | 1462 function, currentNode, compiledArguments, instanceType: instanceType); |
1467 inlinedFrom(function, () { | 1463 inlinedFrom(function, () { |
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2294 // parameters of the generative constructor body. | 2290 // parameters of the generative constructor body. |
2295 currentClass.typeVariables.forEach((TypeVariableType argument) { | 2291 currentClass.typeVariables.forEach((TypeVariableType argument) { |
2296 // TODO(johnniwinther): Substitute [argument] with | 2292 // TODO(johnniwinther): Substitute [argument] with |
2297 // `localsHandler.substInContext(argument)`. | 2293 // `localsHandler.substInContext(argument)`. |
2298 bodyCallInputs.add(localsHandler.readLocal( | 2294 bodyCallInputs.add(localsHandler.readLocal( |
2299 localsHandler.getTypeVariableAsLocal(argument))); | 2295 localsHandler.getTypeVariableAsLocal(argument))); |
2300 }); | 2296 }); |
2301 } | 2297 } |
2302 | 2298 |
2303 if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. | 2299 if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. |
2304 tryInlineMethod(body, null, null, bodyCallInputs, function)) { | 2300 tryInlineMethod(body, null, bodyCallInputs, function)) { |
2305 pop(); | 2301 pop(); |
2306 } else { | 2302 } else { |
2307 HInvokeConstructorBody invoke = new HInvokeConstructorBody( | 2303 HInvokeConstructorBody invoke = new HInvokeConstructorBody( |
2308 body.declaration, bodyCallInputs, backend.nonNullType); | 2304 body.declaration, bodyCallInputs, backend.nonNullType); |
2309 invoke.sideEffects = | 2305 invoke.sideEffects = |
2310 compiler.world.getSideEffectsOfElement(constructor); | 2306 compiler.world.getSideEffectsOfElement(constructor); |
2311 add(invoke); | 2307 add(invoke); |
2312 } | 2308 } |
2313 } | 2309 } |
2314 if (inliningStack.isEmpty) { | 2310 if (inliningStack.isEmpty) { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2448 original, typeVariable); | 2444 original, typeVariable); |
2449 } else if (type.isFunctionType) { | 2445 } else if (type.isFunctionType) { |
2450 String name = kind == HTypeConversion.CAST_TYPE_CHECK | 2446 String name = kind == HTypeConversion.CAST_TYPE_CHECK |
2451 ? '_asCheck' : '_assertCheck'; | 2447 ? '_asCheck' : '_assertCheck'; |
2452 | 2448 |
2453 List<HInstruction> arguments = | 2449 List<HInstruction> arguments = |
2454 <HInstruction>[buildFunctionType(type), original]; | 2450 <HInstruction>[buildFunctionType(type), original]; |
2455 pushInvokeDynamic( | 2451 pushInvokeDynamic( |
2456 null, | 2452 null, |
2457 new Selector.call(name, backend.jsHelperLibrary, 1), | 2453 new Selector.call(name, backend.jsHelperLibrary, 1), |
2458 null, | |
2459 arguments); | 2454 arguments); |
2460 | 2455 |
2461 return new HTypeConversion(type, kind, original.instructionType, pop()); | 2456 return new HTypeConversion(type, kind, original.instructionType, pop()); |
2462 } else { | 2457 } else { |
2463 return original.convertType(compiler, type, kind); | 2458 return original.convertType(compiler, type, kind); |
2464 } | 2459 } |
2465 } | 2460 } |
2466 | 2461 |
2467 HInstruction _trustType(HInstruction original, DartType type) { | 2462 HInstruction _trustType(HInstruction original, DartType type) { |
2468 assert(compiler.trustTypeAnnotations); | 2463 assert(compiler.trustTypeAnnotations); |
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3189 if (operand is HConstant) { | 3184 if (operand is HConstant) { |
3190 UnaryOperation operation = constantSystem.lookupUnary(operator); | 3185 UnaryOperation operation = constantSystem.lookupUnary(operator); |
3191 HConstant constant = operand; | 3186 HConstant constant = operand; |
3192 ConstantValue folded = operation.fold(constant.constant); | 3187 ConstantValue folded = operation.fold(constant.constant); |
3193 if (folded != null) { | 3188 if (folded != null) { |
3194 stack.add(graph.addConstant(folded, compiler)); | 3189 stack.add(graph.addConstant(folded, compiler)); |
3195 return; | 3190 return; |
3196 } | 3191 } |
3197 } | 3192 } |
3198 | 3193 |
3199 pushInvokeDynamic( | 3194 pushInvokeDynamic(node, elements.getSelector(node), [operand]); |
3200 node, | |
3201 elements.getSelector(node), | |
3202 elements.getTypeMask(node), | |
3203 [operand]); | |
3204 } | 3195 } |
3205 | 3196 |
3206 @override | 3197 @override |
3207 void visitBinary(ast.Send node, | 3198 void visitBinary(ast.Send node, |
3208 ast.Node left, | 3199 ast.Node left, |
3209 BinaryOperator operator, | 3200 BinaryOperator operator, |
3210 ast.Node right, _) { | 3201 ast.Node right, _) { |
3211 handleBinary(node, left, right); | 3202 handleBinary(node, left, right); |
3212 } | 3203 } |
3213 | 3204 |
(...skipping 11 matching lines...) Expand all Loading... |
3225 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { | 3216 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { |
3226 handleBinary(node, left, right); | 3217 handleBinary(node, left, right); |
3227 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); | 3218 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); |
3228 } | 3219 } |
3229 | 3220 |
3230 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { | 3221 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { |
3231 visitBinarySend( | 3222 visitBinarySend( |
3232 visitAndPop(left), | 3223 visitAndPop(left), |
3233 visitAndPop(right), | 3224 visitAndPop(right), |
3234 elements.getSelector(node), | 3225 elements.getSelector(node), |
3235 elements.getTypeMask(node), | |
3236 node, | 3226 node, |
3237 location: node.selector); | 3227 location: node.selector); |
3238 } | 3228 } |
3239 | 3229 |
3240 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and | 3230 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and |
3241 /// remove use of [location] for source information. | 3231 /// remove use of [location] for source information. |
3242 void visitBinarySend(HInstruction left, | 3232 void visitBinarySend(HInstruction left, |
3243 HInstruction right, | 3233 HInstruction right, |
3244 Selector selector, | 3234 Selector selector, |
3245 TypeMask mask, | |
3246 ast.Send send, | 3235 ast.Send send, |
3247 {ast.Node location}) { | 3236 {ast.Node location}) { |
3248 pushInvokeDynamic(send, selector, mask, [left, right], location: location); | 3237 pushInvokeDynamic(send, selector, [left, right], location: location); |
3249 } | 3238 } |
3250 | 3239 |
3251 HInstruction generateInstanceSendReceiver(ast.Send send) { | 3240 HInstruction generateInstanceSendReceiver(ast.Send send) { |
3252 assert(Elements.isInstanceSend(send, elements)); | 3241 assert(Elements.isInstanceSend(send, elements)); |
3253 if (send.receiver == null) { | 3242 if (send.receiver == null) { |
3254 return localsHandler.readThis(); | 3243 return localsHandler.readThis(); |
3255 } | 3244 } |
3256 visit(send.receiver); | 3245 visit(send.receiver); |
3257 return pop(); | 3246 return pop(); |
3258 } | 3247 } |
3259 | 3248 |
3260 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { | 3249 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { |
3261 String result = error.name; | 3250 String result = error.name; |
3262 if (prefix == "set") return "$result="; | 3251 if (prefix == "set") return "$result="; |
3263 return result; | 3252 return result; |
3264 } | 3253 } |
3265 | 3254 |
3266 /** | 3255 /** |
3267 * Returns a set of interceptor classes that contain the given | 3256 * Returns a set of interceptor classes that contain the given |
3268 * [selector]. | 3257 * [selector]. |
3269 */ | 3258 */ |
3270 void generateInstanceGetterWithCompiledReceiver( | 3259 void generateInstanceGetterWithCompiledReceiver(ast.Send send, |
3271 ast.Send send, | 3260 Selector selector, |
3272 Selector selector, | 3261 HInstruction receiver) { |
3273 TypeMask mask, | |
3274 HInstruction receiver) { | |
3275 assert(Elements.isInstanceSend(send, elements)); | 3262 assert(Elements.isInstanceSend(send, elements)); |
3276 assert(selector.isGetter); | 3263 assert(selector.isGetter); |
3277 pushInvokeDynamic(send, selector, mask, [receiver]); | 3264 pushInvokeDynamic(send, selector, [receiver]); |
3278 } | 3265 } |
3279 | 3266 |
3280 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. | 3267 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. |
3281 /// If [prefixElement] is [null] ndo nothing. | 3268 /// If [prefixElement] is [null] ndo nothing. |
3282 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, | 3269 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, |
3283 ast.Node location) { | 3270 ast.Node location) { |
3284 if (prefixElement == null) return; | 3271 if (prefixElement == null) return; |
3285 String loadId = | 3272 String loadId = |
3286 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; | 3273 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; |
3287 HInstruction loadIdConstant = addConstantString(loadId); | 3274 HInstruction loadIdConstant = addConstantString(loadId); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3385 } else { | 3372 } else { |
3386 generateIsDeferredLoadedCheckOfSend(node); | 3373 generateIsDeferredLoadedCheckOfSend(node); |
3387 pushInvokeStatic(node, getter, <HInstruction>[]); | 3374 pushInvokeStatic(node, getter, <HInstruction>[]); |
3388 } | 3375 } |
3389 } | 3376 } |
3390 | 3377 |
3391 /// Generate a dynamic getter invocation. | 3378 /// Generate a dynamic getter invocation. |
3392 void generateDynamicGet(ast.Send node) { | 3379 void generateDynamicGet(ast.Send node) { |
3393 HInstruction receiver = generateInstanceSendReceiver(node); | 3380 HInstruction receiver = generateInstanceSendReceiver(node); |
3394 generateInstanceGetterWithCompiledReceiver( | 3381 generateInstanceGetterWithCompiledReceiver( |
3395 node, elements.getSelector(node), elements.getTypeMask(node), receiver); | 3382 node, elements.getSelector(node), receiver); |
3396 } | 3383 } |
3397 | 3384 |
3398 /// Generate a closurization of the static or top level [function]. | 3385 /// Generate a closurization of the static or top level [function]. |
3399 void generateStaticFunctionGet(ast.Send node, MethodElement function) { | 3386 void generateStaticFunctionGet(ast.Send node, MethodElement function) { |
3400 generateIsDeferredLoadedCheckOfSend(node); | 3387 generateIsDeferredLoadedCheckOfSend(node); |
3401 // TODO(5346): Try to avoid the need for calling [declaration] before | 3388 // TODO(5346): Try to avoid the need for calling [declaration] before |
3402 // creating an [HStatic]. | 3389 // creating an [HStatic]. |
3403 push(new HStatic(function.declaration, backend.nonNullType)); | 3390 push(new HStatic(function.declaration, backend.nonNullType)); |
3404 // TODO(ahe): This should be registered in codegen. | 3391 // TODO(ahe): This should be registered in codegen. |
3405 registry.registerGetOfStaticFunction(function.declaration); | 3392 registry.registerGetOfStaticFunction(function.declaration); |
(...skipping 26 matching lines...) Expand all Loading... |
3432 // we will be able to later compress it as: | 3419 // we will be able to later compress it as: |
3433 // t1 || t1.x | 3420 // t1 || t1.x |
3434 HInstruction expression; | 3421 HInstruction expression; |
3435 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 3422 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
3436 brancher.handleConditional( | 3423 brancher.handleConditional( |
3437 () { | 3424 () { |
3438 expression = visitAndPop(receiver); | 3425 expression = visitAndPop(receiver); |
3439 pushCheckNull(expression); | 3426 pushCheckNull(expression); |
3440 }, | 3427 }, |
3441 () => stack.add(expression), | 3428 () => stack.add(expression), |
3442 () { | 3429 () => generateInstanceGetterWithCompiledReceiver( |
3443 generateInstanceGetterWithCompiledReceiver( | 3430 node, elements.getSelector(node), expression)); |
3444 node, | |
3445 elements.getSelector(node), | |
3446 elements.getTypeMask(node), | |
3447 expression); | |
3448 }); | |
3449 } | 3431 } |
3450 | 3432 |
3451 /// Pushes a boolean checking [expression] against null. | 3433 /// Pushes a boolean checking [expression] against null. |
3452 pushCheckNull(HInstruction expression) { | 3434 pushCheckNull(HInstruction expression) { |
3453 push(new HIdentity(expression, graph.addConstantNull(compiler), | 3435 push(new HIdentity(expression, graph.addConstantNull(compiler), |
3454 null, backend.boolType)); | 3436 null, backend.boolType)); |
3455 } | 3437 } |
3456 | 3438 |
3457 @override | 3439 @override |
3458 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 3440 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3522 ast.Send node, | 3504 ast.Send node, |
3523 FunctionElement getter, | 3505 FunctionElement getter, |
3524 _) { | 3506 _) { |
3525 generateStaticGetterGet(node, getter); | 3507 generateStaticGetterGet(node, getter); |
3526 } | 3508 } |
3527 | 3509 |
3528 void generateInstanceSetterWithCompiledReceiver(ast.Send send, | 3510 void generateInstanceSetterWithCompiledReceiver(ast.Send send, |
3529 HInstruction receiver, | 3511 HInstruction receiver, |
3530 HInstruction value, | 3512 HInstruction value, |
3531 {Selector selector, | 3513 {Selector selector, |
3532 TypeMask mask, | |
3533 ast.Node location}) { | 3514 ast.Node location}) { |
3534 assert(send == null || Elements.isInstanceSend(send, elements)); | 3515 assert(send == null || Elements.isInstanceSend(send, elements)); |
3535 if (selector == null) { | 3516 if (selector == null) { |
3536 assert(send != null); | 3517 assert(send != null); |
3537 selector = elements.getSelector(send); | 3518 selector = elements.getSelector(send); |
3538 if (mask == null) { | |
3539 mask = elements.getTypeMask(send); | |
3540 } | |
3541 } | 3519 } |
3542 if (location == null) { | 3520 if (location == null) { |
3543 assert(send != null); | 3521 assert(send != null); |
3544 location = send; | 3522 location = send; |
3545 } | 3523 } |
3546 assert(selector.isSetter); | 3524 assert(selector.isSetter); |
3547 pushInvokeDynamic(location, selector, mask, [receiver, value]); | 3525 pushInvokeDynamic(location, selector, [receiver, value]); |
3548 pop(); | 3526 pop(); |
3549 stack.add(value); | 3527 stack.add(value); |
3550 } | 3528 } |
3551 | 3529 |
3552 void generateNonInstanceSetter(ast.SendSet send, | 3530 void generateNonInstanceSetter(ast.SendSet send, |
3553 Element element, | 3531 Element element, |
3554 HInstruction value, | 3532 HInstruction value, |
3555 {ast.Node location}) { | 3533 {ast.Node location}) { |
3556 assert(send == null || !Elements.isInstanceSend(send, elements)); | 3534 assert(send == null || !Elements.isInstanceSend(send, elements)); |
3557 if (location == null) { | 3535 if (location == null) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3672 push(new HNot(instruction, backend.boolType)); | 3650 push(new HNot(instruction, backend.boolType)); |
3673 } | 3651 } |
3674 | 3652 |
3675 HInstruction buildIsNode(ast.Node node, | 3653 HInstruction buildIsNode(ast.Node node, |
3676 DartType type, | 3654 DartType type, |
3677 HInstruction expression) { | 3655 HInstruction expression) { |
3678 type = localsHandler.substInContext(type).unalias(compiler); | 3656 type = localsHandler.substInContext(type).unalias(compiler); |
3679 if (type.isFunctionType) { | 3657 if (type.isFunctionType) { |
3680 List arguments = [buildFunctionType(type), expression]; | 3658 List arguments = [buildFunctionType(type), expression]; |
3681 pushInvokeDynamic( | 3659 pushInvokeDynamic( |
3682 node, | 3660 node, new Selector.call('_isTest', backend.jsHelperLibrary, 1), |
3683 new Selector.call('_isTest', backend.jsHelperLibrary, 1), | |
3684 null, | |
3685 arguments); | 3661 arguments); |
3686 return new HIs.compound(type, expression, pop(), backend.boolType); | 3662 return new HIs.compound(type, expression, pop(), backend.boolType); |
3687 } else if (type.isTypeVariable) { | 3663 } else if (type.isTypeVariable) { |
3688 HInstruction runtimeType = addTypeVariableReference(type); | 3664 HInstruction runtimeType = addTypeVariableReference(type); |
3689 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 3665 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
3690 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3666 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
3691 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 3667 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); |
3692 HInstruction call = pop(); | 3668 HInstruction call = pop(); |
3693 return new HIs.variable(type, expression, call, backend.boolType); | 3669 return new HIs.variable(type, expression, call, backend.boolType); |
3694 } else if (RuntimeTypes.hasTypeArguments(type)) { | 3670 } else if (RuntimeTypes.hasTypeArguments(type)) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3796 } | 3772 } |
3797 | 3773 |
3798 /// Generate a dynamic method, getter or setter invocation. | 3774 /// Generate a dynamic method, getter or setter invocation. |
3799 void generateDynamicSend(ast.Send node) { | 3775 void generateDynamicSend(ast.Send node) { |
3800 HInstruction receiver = generateInstanceSendReceiver(node); | 3776 HInstruction receiver = generateInstanceSendReceiver(node); |
3801 _generateDynamicSend(node, receiver); | 3777 _generateDynamicSend(node, receiver); |
3802 } | 3778 } |
3803 | 3779 |
3804 void _generateDynamicSend(ast.Send node, HInstruction receiver) { | 3780 void _generateDynamicSend(ast.Send node, HInstruction receiver) { |
3805 Selector selector = elements.getSelector(node); | 3781 Selector selector = elements.getSelector(node); |
3806 TypeMask mask = elements.getTypeMask(node); | |
3807 | 3782 |
3808 List<HInstruction> inputs = <HInstruction>[]; | 3783 List<HInstruction> inputs = <HInstruction>[]; |
3809 inputs.add(receiver); | 3784 inputs.add(receiver); |
3810 addDynamicSendArgumentsToList(node, inputs); | 3785 addDynamicSendArgumentsToList(node, inputs); |
3811 | 3786 |
3812 pushInvokeDynamic(node, selector, mask, inputs); | 3787 pushInvokeDynamic(node, selector, inputs); |
3813 if (selector.isSetter || selector.isIndexSet) { | 3788 if (selector.isSetter || selector.isIndexSet) { |
3814 pop(); | 3789 pop(); |
3815 stack.add(inputs.last); | 3790 stack.add(inputs.last); |
3816 } | 3791 } |
3817 } | 3792 } |
3818 | 3793 |
3819 @override | 3794 @override |
3820 visitDynamicPropertyInvoke( | 3795 visitDynamicPropertyInvoke( |
3821 ast.Send node, | 3796 ast.Send node, |
3822 ast.Node receiver, | 3797 ast.Node receiver, |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4166 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 4141 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
4167 stack.add(graph.addConstantNull(compiler)); | 4142 stack.add(graph.addConstantNull(compiler)); |
4168 } | 4143 } |
4169 | 4144 |
4170 void handleForeignJsCallInIsolate(ast.Send node) { | 4145 void handleForeignJsCallInIsolate(ast.Send node) { |
4171 Link<ast.Node> link = node.arguments; | 4146 Link<ast.Node> link = node.arguments; |
4172 if (!compiler.hasIsolateSupport) { | 4147 if (!compiler.hasIsolateSupport) { |
4173 // If the isolate library is not used, we just invoke the | 4148 // If the isolate library is not used, we just invoke the |
4174 // closure. | 4149 // closure. |
4175 visit(link.tail.head); | 4150 visit(link.tail.head); |
4176 push(new HInvokeClosure(new Selector.callClosure(0), | 4151 Selector selector = new Selector.callClosure(0); |
| 4152 push(new HInvokeClosure(selector, |
4177 <HInstruction>[pop()], | 4153 <HInstruction>[pop()], |
4178 backend.dynamicType)); | 4154 backend.dynamicType)); |
4179 } else { | 4155 } else { |
4180 // Call a helper method from the isolate library. | 4156 // Call a helper method from the isolate library. |
4181 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); | 4157 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); |
4182 if (element == null) { | 4158 if (element == null) { |
4183 compiler.internalError(node, | 4159 compiler.internalError(node, |
4184 'Isolate library and compiler mismatch.'); | 4160 'Isolate library and compiler mismatch.'); |
4185 } | 4161 } |
4186 List<HInstruction> inputs = <HInstruction>[]; | 4162 List<HInstruction> inputs = <HInstruction>[]; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4308 String name = selector.name; | 4284 String name = selector.name; |
4309 | 4285 |
4310 ClassElement cls = currentNonClosureClass; | 4286 ClassElement cls = currentNonClosureClass; |
4311 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 4287 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); |
4312 if (compiler.enabledInvokeOn | 4288 if (compiler.enabledInvokeOn |
4313 && element.enclosingElement.declaration != compiler.objectClass) { | 4289 && element.enclosingElement.declaration != compiler.objectClass) { |
4314 // Register the call as dynamic if [noSuchMethod] on the super | 4290 // Register the call as dynamic if [noSuchMethod] on the super |
4315 // class is _not_ the default implementation from [Object], in | 4291 // class is _not_ the default implementation from [Object], in |
4316 // case the [noSuchMethod] implementation calls | 4292 // case the [noSuchMethod] implementation calls |
4317 // [JSInvocationMirror._invokeOn]. | 4293 // [JSInvocationMirror._invokeOn]. |
4318 registry.registerSelectorUse(selector); | 4294 registry.registerSelectorUse(selector.asUntyped); |
4319 } | 4295 } |
4320 String publicName = name; | 4296 String publicName = name; |
4321 if (selector.isSetter) publicName += '='; | 4297 if (selector.isSetter) publicName += '='; |
4322 | 4298 |
4323 ConstantValue nameConstant = constantSystem.createString( | 4299 ConstantValue nameConstant = constantSystem.createString( |
4324 new ast.DartString.literal(publicName)); | 4300 new ast.DartString.literal(publicName)); |
4325 | 4301 |
4326 String internalName = backend.namer.invocationName(selector); | 4302 String internalName = backend.namer.invocationName(selector); |
4327 ConstantValue internalNameConstant = | 4303 ConstantValue internalNameConstant = |
4328 constantSystem.createString(new ast.DartString.literal(internalName)); | 4304 constantSystem.createString(new ast.DartString.literal(internalName)); |
(...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5324 // in if it is not used (e.g., in a try/catch). | 5300 // in if it is not used (e.g., in a try/catch). |
5325 HInstruction target = pop(); | 5301 HInstruction target = pop(); |
5326 generateCallInvoke(node, target); | 5302 generateCallInvoke(node, target); |
5327 } | 5303 } |
5328 | 5304 |
5329 /// Generate a '.call' invocation on [target]. | 5305 /// Generate a '.call' invocation on [target]. |
5330 void generateCallInvoke(ast.Send node, HInstruction target) { | 5306 void generateCallInvoke(ast.Send node, HInstruction target) { |
5331 Selector selector = elements.getSelector(node); | 5307 Selector selector = elements.getSelector(node); |
5332 List<HInstruction> inputs = <HInstruction>[target]; | 5308 List<HInstruction> inputs = <HInstruction>[target]; |
5333 addDynamicSendArgumentsToList(node, inputs); | 5309 addDynamicSendArgumentsToList(node, inputs); |
| 5310 Selector closureSelector = new Selector.callClosureFrom(selector); |
5334 pushWithPosition( | 5311 pushWithPosition( |
5335 new HInvokeClosure( | 5312 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node); |
5336 new Selector.callClosureFrom(selector), | |
5337 inputs, backend.dynamicType), | |
5338 node); | |
5339 } | 5313 } |
5340 | 5314 |
5341 visitGetterSend(ast.Send node) { | 5315 visitGetterSend(ast.Send node) { |
5342 internalError(node, "Unexpected visitGetterSend"); | 5316 internalError(node, "Unexpected visitGetterSend"); |
5343 } | 5317 } |
5344 | 5318 |
5345 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 5319 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
5346 internalError(Spannable node, String reason) { | 5320 internalError(Spannable node, String reason) { |
5347 compiler.internalError(node, reason); | 5321 compiler.internalError(node, reason); |
5348 } | 5322 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5457 String nameString = stringConstant.toDartString().slowToString(); | 5431 String nameString = stringConstant.toDartString().slowToString(); |
5458 registry.registerConstSymbol(nameString); | 5432 registry.registerConstSymbol(nameString); |
5459 } | 5433 } |
5460 } else { | 5434 } else { |
5461 handleNewSend(node); | 5435 handleNewSend(node); |
5462 } | 5436 } |
5463 } | 5437 } |
5464 | 5438 |
5465 void pushInvokeDynamic(ast.Node node, | 5439 void pushInvokeDynamic(ast.Node node, |
5466 Selector selector, | 5440 Selector selector, |
5467 TypeMask mask, | |
5468 List<HInstruction> arguments, | 5441 List<HInstruction> arguments, |
5469 {ast.Node location}) { | 5442 {ast.Node location}) { |
5470 if (location == null) location = node; | 5443 if (location == null) location = node; |
5471 | 5444 |
5472 // We prefer to not inline certain operations on indexables, | 5445 // We prefer to not inline certain operations on indexables, |
5473 // because the constant folder will handle them better and turn | 5446 // because the constant folder will handle them better and turn |
5474 // them into simpler instructions that allow further | 5447 // them into simpler instructions that allow further |
5475 // optimizations. | 5448 // optimizations. |
5476 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 5449 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { |
5477 bool isLength = selector.isGetter | 5450 bool isLength = selector.isGetter |
(...skipping 20 matching lines...) Expand all Loading... |
5498 if (selector.isIndex) return true; | 5471 if (selector.isIndex) return true; |
5499 if (selector.isIndexSet) return true; | 5472 if (selector.isIndexSet) return true; |
5500 if (element == backend.jsArrayAdd | 5473 if (element == backend.jsArrayAdd |
5501 || element == backend.jsArrayRemoveLast | 5474 || element == backend.jsArrayRemoveLast |
5502 || element == backend.jsStringSplit) { | 5475 || element == backend.jsStringSplit) { |
5503 return true; | 5476 return true; |
5504 } | 5477 } |
5505 return false; | 5478 return false; |
5506 } | 5479 } |
5507 | 5480 |
5508 Element element = compiler.world.locateSingleElement(selector, mask); | 5481 Element element = compiler.world.locateSingleElement(selector); |
5509 if (element != null && | 5482 if (element != null |
5510 !element.isField && | 5483 && !element.isField |
5511 !(element.isGetter && selector.isCall) && | 5484 && !(element.isGetter && selector.isCall) |
5512 !(element.isFunction && selector.isGetter) && | 5485 && !(element.isFunction && selector.isGetter) |
5513 !isOptimizableOperation(selector, element)) { | 5486 && !isOptimizableOperation(selector, element)) { |
5514 if (tryInlineMethod(element, selector, mask, arguments, node)) { | 5487 if (tryInlineMethod(element, selector, arguments, node)) { |
5515 return; | 5488 return; |
5516 } | 5489 } |
5517 } | 5490 } |
5518 | 5491 |
5519 HInstruction receiver = arguments[0]; | 5492 HInstruction receiver = arguments[0]; |
5520 List<HInstruction> inputs = <HInstruction>[]; | 5493 List<HInstruction> inputs = <HInstruction>[]; |
5521 bool isIntercepted = backend.isInterceptedSelector(selector); | 5494 bool isIntercepted = backend.isInterceptedSelector(selector); |
5522 if (isIntercepted) { | 5495 if (isIntercepted) { |
5523 inputs.add(invokeInterceptor(receiver)); | 5496 inputs.add(invokeInterceptor(receiver)); |
5524 } | 5497 } |
5525 inputs.addAll(arguments); | 5498 inputs.addAll(arguments); |
5526 TypeMask type = | 5499 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); |
5527 TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler); | |
5528 if (selector.isGetter) { | 5500 if (selector.isGetter) { |
5529 pushWithPosition( | 5501 pushWithPosition( |
5530 new HInvokeDynamicGetter(selector, mask, null, inputs, type), | 5502 new HInvokeDynamicGetter(selector, null, inputs, type), |
5531 location); | 5503 location); |
5532 } else if (selector.isSetter) { | 5504 } else if (selector.isSetter) { |
5533 pushWithPosition( | 5505 pushWithPosition( |
5534 new HInvokeDynamicSetter(selector, mask, null, inputs, type), | 5506 new HInvokeDynamicSetter(selector, null, inputs, type), |
5535 location); | 5507 location); |
5536 } else { | 5508 } else { |
5537 pushWithPosition( | 5509 pushWithPosition( |
5538 new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted), | 5510 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), |
5539 location); | 5511 location); |
5540 } | 5512 } |
5541 } | 5513 } |
5542 | 5514 |
5543 void pushInvokeStatic(ast.Node location, | 5515 void pushInvokeStatic(ast.Node location, |
5544 Element element, | 5516 Element element, |
5545 List<HInstruction> arguments, | 5517 List<HInstruction> arguments, |
5546 {TypeMask typeMask, | 5518 {TypeMask typeMask, |
5547 InterfaceType instanceType}) { | 5519 InterfaceType instanceType}) { |
5548 if (tryInlineMethod(element, null, null, arguments, location, | 5520 if (tryInlineMethod(element, null, arguments, location, |
5549 instanceType: instanceType)) { | 5521 instanceType: instanceType)) { |
5550 return; | 5522 return; |
5551 } | 5523 } |
5552 | 5524 |
5553 if (typeMask == null) { | 5525 if (typeMask == null) { |
5554 typeMask = | 5526 typeMask = |
5555 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5527 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
5556 } | 5528 } |
5557 bool targetCanThrow = !compiler.world.getCannotThrow(element); | 5529 bool targetCanThrow = !compiler.world.getCannotThrow(element); |
5558 // TODO(5346): Try to avoid the need for calling [declaration] before | 5530 // TODO(5346): Try to avoid the need for calling [declaration] before |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5593 } else { | 5565 } else { |
5594 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5566 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
5595 } | 5567 } |
5596 HInstruction instruction = new HInvokeSuper( | 5568 HInstruction instruction = new HInvokeSuper( |
5597 element, | 5569 element, |
5598 currentNonClosureClass, | 5570 currentNonClosureClass, |
5599 selector, | 5571 selector, |
5600 inputs, | 5572 inputs, |
5601 type, | 5573 type, |
5602 isSetter: selector.isSetter || selector.isIndexSet); | 5574 isSetter: selector.isSetter || selector.isIndexSet); |
5603 instruction.sideEffects = | 5575 instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector); |
5604 compiler.world.getSideEffectsOfSelector(selector, null); | |
5605 return instruction; | 5576 return instruction; |
5606 } | 5577 } |
5607 | 5578 |
5608 void handleComplexOperatorSend(ast.SendSet node, | 5579 void handleComplexOperatorSend(ast.SendSet node, |
5609 HInstruction receiver, | 5580 HInstruction receiver, |
5610 Link<ast.Node> arguments) { | 5581 Link<ast.Node> arguments) { |
5611 HInstruction rhs; | 5582 HInstruction rhs; |
5612 if (node.isPrefix || node.isPostfix) { | 5583 if (node.isPrefix || node.isPostfix) { |
5613 rhs = graph.addConstantInt(1, compiler); | 5584 rhs = graph.addConstantInt(1, compiler); |
5614 } else { | 5585 } else { |
5615 visit(arguments.head); | 5586 visit(arguments.head); |
5616 assert(arguments.tail.isEmpty); | 5587 assert(arguments.tail.isEmpty); |
5617 rhs = pop(); | 5588 rhs = pop(); |
5618 } | 5589 } |
5619 visitBinarySend(receiver, rhs, | 5590 visitBinarySend(receiver, rhs, |
5620 elements.getOperatorSelectorInComplexSendSet(node), | 5591 elements.getOperatorSelectorInComplexSendSet(node), |
5621 elements.getOperatorTypeMaskInComplexSendSet(node), | |
5622 node, | 5592 node, |
5623 location: node.assignmentOperator); | 5593 location: node.assignmentOperator); |
5624 } | 5594 } |
5625 | 5595 |
5626 void handleSuperSendSet(ast.SendSet node) { | 5596 void handleSuperSendSet(ast.SendSet node) { |
5627 Element element = elements[node]; | 5597 Element element = elements[node]; |
5628 List<HInstruction> setterInputs = <HInstruction>[]; | 5598 List<HInstruction> setterInputs = <HInstruction>[]; |
5629 void generateSuperSendSet() { | 5599 void generateSuperSendSet() { |
5630 Selector setterSelector = elements.getSelector(node); | 5600 Selector setterSelector = elements.getSelector(node); |
5631 if (Elements.isUnresolved(element) | 5601 if (Elements.isUnresolved(element) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5709 HInstruction index; | 5679 HInstruction index; |
5710 if (node.isIndex) { | 5680 if (node.isIndex) { |
5711 visit(arguments.head); | 5681 visit(arguments.head); |
5712 arguments = arguments.tail; | 5682 arguments = arguments.tail; |
5713 index = pop(); | 5683 index = pop(); |
5714 } | 5684 } |
5715 | 5685 |
5716 pushInvokeDynamic( | 5686 pushInvokeDynamic( |
5717 node, | 5687 node, |
5718 elements.getGetterSelectorInComplexSendSet(node), | 5688 elements.getGetterSelectorInComplexSendSet(node), |
5719 elements.getGetterTypeMaskInComplexSendSet(node), | |
5720 [receiver, index]); | 5689 [receiver, index]); |
5721 HInstruction getterInstruction = pop(); | 5690 HInstruction getterInstruction = pop(); |
5722 if (node.isIfNullAssignment) { | 5691 if (node.isIfNullAssignment) { |
5723 // Compile x[i] ??= e as: | 5692 // Compile x[i] ??= e as: |
5724 // t1 = x[i] | 5693 // t1 = x[i] |
5725 // if (t1 == null) | 5694 // if (t1 == null) |
5726 // t1 = x[i] = e; | 5695 // t1 = x[i] = e; |
5727 // result = t1 | 5696 // result = t1 |
5728 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 5697 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
5729 brancher.handleIfNull(() => stack.add(getterInstruction), | 5698 brancher.handleIfNull(() => stack.add(getterInstruction), |
5730 () { | 5699 () { |
5731 visit(arguments.head); | 5700 visit(arguments.head); |
5732 HInstruction value = pop(); | 5701 HInstruction value = pop(); |
5733 pushInvokeDynamic( | 5702 pushInvokeDynamic( |
5734 node, | 5703 node, elements.getSelector(node), [receiver, index, value]); |
5735 elements.getSelector(node), | |
5736 elements.getTypeMask(node), | |
5737 [receiver, index, value]); | |
5738 pop(); | 5704 pop(); |
5739 stack.add(value); | 5705 stack.add(value); |
5740 }); | 5706 }); |
5741 } else { | 5707 } else { |
5742 handleComplexOperatorSend(node, getterInstruction, arguments); | 5708 handleComplexOperatorSend(node, getterInstruction, arguments); |
5743 HInstruction value = pop(); | 5709 HInstruction value = pop(); |
5744 pushInvokeDynamic( | 5710 pushInvokeDynamic( |
5745 node, | 5711 node, elements.getSelector(node), [receiver, index, value]); |
5746 elements.getSelector(node), | |
5747 elements.getTypeMask(node), | |
5748 [receiver, index, value]); | |
5749 pop(); | 5712 pop(); |
5750 if (node.isPostfix) { | 5713 if (node.isPostfix) { |
5751 stack.add(getterInstruction); | 5714 stack.add(getterInstruction); |
5752 } else { | 5715 } else { |
5753 stack.add(value); | 5716 stack.add(value); |
5754 } | 5717 } |
5755 } | 5718 } |
5756 } | 5719 } |
5757 } | 5720 } |
5758 | 5721 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6025 generateThrowNoSuchMethod(node, selector.source, | 5988 generateThrowNoSuchMethod(node, selector.source, |
6026 argumentNodes: node.arguments); | 5989 argumentNodes: node.arguments); |
6027 } | 5990 } |
6028 return; | 5991 return; |
6029 } | 5992 } |
6030 | 5993 |
6031 if (Elements.isInstanceSend(node, elements)) { | 5994 if (Elements.isInstanceSend(node, elements)) { |
6032 void generateAssignment(HInstruction receiver) { | 5995 void generateAssignment(HInstruction receiver) { |
6033 // desugars `e.x op= e2` to `e.x = e.x op e2` | 5996 // desugars `e.x op= e2` to `e.x = e.x op e2` |
6034 generateInstanceGetterWithCompiledReceiver( | 5997 generateInstanceGetterWithCompiledReceiver( |
6035 node, | 5998 node, elements.getGetterSelectorInComplexSendSet(node), receiver); |
6036 elements.getGetterSelectorInComplexSendSet(node), | |
6037 elements.getGetterTypeMaskInComplexSendSet(node), | |
6038 receiver); | |
6039 HInstruction getterInstruction = pop(); | 5999 HInstruction getterInstruction = pop(); |
6040 if (node.isIfNullAssignment) { | 6000 if (node.isIfNullAssignment) { |
6041 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 6001 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
6042 brancher.handleIfNull(() => stack.add(getterInstruction), | 6002 brancher.handleIfNull(() => stack.add(getterInstruction), |
6043 () { | 6003 () { |
6044 visit(node.arguments.head); | 6004 visit(node.arguments.head); |
6045 generateInstanceSetterWithCompiledReceiver( | 6005 generateInstanceSetterWithCompiledReceiver( |
6046 node, receiver, pop()); | 6006 node, receiver, pop()); |
6047 }); | 6007 }); |
6048 } else { | 6008 } else { |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6479 HInstruction expression = pop(); | 6439 HInstruction expression = pop(); |
6480 pushInvokeStatic(node, | 6440 pushInvokeStatic(node, |
6481 backend.getStreamIteratorConstructor(), | 6441 backend.getStreamIteratorConstructor(), |
6482 [expression, graph.addConstantNull(compiler)]); | 6442 [expression, graph.addConstantNull(compiler)]); |
6483 streamIterator = pop(); | 6443 streamIterator = pop(); |
6484 | 6444 |
6485 void buildInitializer() {} | 6445 void buildInitializer() {} |
6486 | 6446 |
6487 HInstruction buildCondition() { | 6447 HInstruction buildCondition() { |
6488 Selector selector = elements.getMoveNextSelector(node); | 6448 Selector selector = elements.getMoveNextSelector(node); |
6489 TypeMask mask = elements.getMoveNextTypeMask(node); | 6449 pushInvokeDynamic(node, selector, [streamIterator]); |
6490 pushInvokeDynamic(node, selector, mask, [streamIterator]); | |
6491 HInstruction future = pop(); | 6450 HInstruction future = pop(); |
6492 push(new HAwait(future, new TypeMask.subclass(compiler.objectClass, | 6451 push(new HAwait(future, new TypeMask.subclass(compiler.objectClass, |
6493 compiler.world))); | 6452 compiler.world))); |
6494 return popBoolified(); | 6453 return popBoolified(); |
6495 } | 6454 } |
6496 void buildBody() { | 6455 void buildBody() { |
6497 Selector call = elements.getCurrentSelector(node); | 6456 Selector call = elements.getCurrentSelector(node); |
6498 TypeMask callMask = elements.getCurrentTypeMask(node); | 6457 pushInvokeDynamic(node, call, [streamIterator]); |
6499 pushInvokeDynamic(node, call, callMask, [streamIterator]); | |
6500 | 6458 |
6501 ast.Node identifier = node.declaredIdentifier; | 6459 ast.Node identifier = node.declaredIdentifier; |
6502 Element variable = elements.getForInVariable(node); | 6460 Element variable = elements.getForInVariable(node); |
6503 Selector selector = elements.getSelector(identifier); | 6461 Selector selector = elements.getSelector(identifier); |
6504 TypeMask mask = elements.getTypeMask(identifier); | |
6505 | 6462 |
6506 HInstruction value = pop(); | 6463 HInstruction value = pop(); |
6507 if (identifier.asSend() != null | 6464 if (identifier.asSend() != null |
6508 && Elements.isInstanceSend(identifier, elements)) { | 6465 && Elements.isInstanceSend(identifier, elements)) { |
6509 HInstruction receiver = generateInstanceSendReceiver(identifier); | 6466 HInstruction receiver = generateInstanceSendReceiver(identifier); |
6510 assert(receiver != null); | 6467 assert(receiver != null); |
6511 generateInstanceSetterWithCompiledReceiver( | 6468 generateInstanceSetterWithCompiledReceiver( |
6512 null, | 6469 null, |
6513 receiver, | 6470 receiver, |
6514 value, | 6471 value, |
6515 selector: selector, | 6472 selector: selector, |
6516 mask: mask, | |
6517 location: identifier); | 6473 location: identifier); |
6518 } else { | 6474 } else { |
6519 generateNonInstanceSetter( | 6475 generateNonInstanceSetter( |
6520 null, variable, value, location: identifier); | 6476 null, variable, value, location: identifier); |
6521 } | 6477 } |
6522 pop(); // Pop the value pushed by the setter call. | 6478 pop(); // Pop the value pushed by the setter call. |
6523 | 6479 |
6524 visit(node.body); | 6480 visit(node.body); |
6525 } | 6481 } |
6526 | 6482 |
6527 void buildUpdate() {}; | 6483 void buildUpdate() {}; |
6528 | 6484 |
6529 buildProtectedByFinally(() { | 6485 buildProtectedByFinally(() { |
6530 handleLoop(node, | 6486 handleLoop(node, |
6531 buildInitializer, | 6487 buildInitializer, |
6532 buildCondition, | 6488 buildCondition, |
6533 buildUpdate, | 6489 buildUpdate, |
6534 buildBody); | 6490 buildBody); |
6535 }, () { | 6491 }, () { |
6536 pushInvokeDynamic(node, | 6492 pushInvokeDynamic(node, new Selector.call("cancel", null, 0), |
6537 new Selector.call("cancel", null, 0), | |
6538 null, | |
6539 [streamIterator]); | 6493 [streamIterator]); |
6540 push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass, | 6494 push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass, |
6541 compiler.world))); | 6495 compiler.world))); |
6542 pop(); | 6496 pop(); |
6543 }); | 6497 }); |
6544 } | 6498 } |
6545 | 6499 |
6546 visitSyncForIn(ast.SyncForIn node) { | 6500 visitSyncForIn(ast.SyncForIn node) { |
6547 // The 'get iterator' selector for this node has the inferred receiver type. | 6501 // The 'get iterator' selector for this node has the inferred receiver type. |
6548 // If the receiver supports JavaScript indexing we generate an indexing loop | 6502 // If the receiver supports JavaScript indexing we generate an indexing loop |
6549 // instead of allocating an iterator object. | 6503 // instead of allocating an iterator object. |
6550 | 6504 |
6551 // This scheme recognizes for-in on direct lists. It does not recognize all | 6505 // This scheme recognizes for-in on direct lists. It does not recognize all |
6552 // uses of ArrayIterator. They still occur when the receiver is an Iterable | 6506 // uses of ArrayIterator. They still occur when the receiver is an Iterable |
6553 // with a `get iterator` method that delegate to another Iterable and the | 6507 // with a `get iterator` method that delegate to another Iterable and the |
6554 // method is inlined. We would require full scalar replacement in that | 6508 // method is inlined. We would require full scalar replacement in that |
6555 // case. | 6509 // case. |
6556 | 6510 |
6557 Selector selector = elements.getIteratorSelector(node); | 6511 Selector selector = elements.getIteratorSelector(node); |
6558 TypeMask mask = elements.getIteratorTypeMask(node); | 6512 TypeMask mask = selector.mask; |
6559 | 6513 |
6560 ClassWorld classWorld = compiler.world; | 6514 ClassWorld classWorld = compiler.world; |
6561 if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) { | 6515 if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) { |
6562 return buildSyncForInIndexable(node, mask); | 6516 return buildSyncForInIndexable(node, mask); |
6563 } | 6517 } |
6564 buildSyncForInIterator(node); | 6518 buildSyncForInIterator(node); |
6565 } | 6519 } |
6566 | 6520 |
6567 buildSyncForInIterator(ast.SyncForIn node) { | 6521 buildSyncForInIterator(ast.SyncForIn node) { |
6568 // Generate a structure equivalent to: | 6522 // Generate a structure equivalent to: |
6569 // Iterator<E> $iter = <iterable>.iterator; | 6523 // Iterator<E> $iter = <iterable>.iterator; |
6570 // while ($iter.moveNext()) { | 6524 // while ($iter.moveNext()) { |
6571 // <declaredIdentifier> = $iter.current; | 6525 // <declaredIdentifier> = $iter.current; |
6572 // <body> | 6526 // <body> |
6573 // } | 6527 // } |
6574 | 6528 |
6575 // The iterator is shared between initializer, condition and body. | 6529 // The iterator is shared between initializer, condition and body. |
6576 HInstruction iterator; | 6530 HInstruction iterator; |
6577 | 6531 |
6578 void buildInitializer() { | 6532 void buildInitializer() { |
6579 Selector selector = elements.getIteratorSelector(node); | 6533 Selector selector = elements.getIteratorSelector(node); |
6580 TypeMask mask = elements.getIteratorTypeMask(node); | |
6581 visit(node.expression); | 6534 visit(node.expression); |
6582 HInstruction receiver = pop(); | 6535 HInstruction receiver = pop(); |
6583 pushInvokeDynamic(node, selector, mask, [receiver]); | 6536 pushInvokeDynamic(node, selector, [receiver]); |
6584 iterator = pop(); | 6537 iterator = pop(); |
6585 } | 6538 } |
6586 | 6539 |
6587 HInstruction buildCondition() { | 6540 HInstruction buildCondition() { |
6588 Selector selector = elements.getMoveNextSelector(node); | 6541 Selector selector = elements.getMoveNextSelector(node); |
6589 TypeMask mask = elements.getMoveNextTypeMask(node); | 6542 pushInvokeDynamic(node, selector, [iterator]); |
6590 pushInvokeDynamic(node, selector, mask, [iterator]); | |
6591 return popBoolified(); | 6543 return popBoolified(); |
6592 } | 6544 } |
6593 | 6545 |
6594 void buildBody() { | 6546 void buildBody() { |
6595 Selector call = elements.getCurrentSelector(node); | 6547 Selector call = elements.getCurrentSelector(node); |
6596 TypeMask mask = elements.getCurrentTypeMask(node); | 6548 pushInvokeDynamic(node, call, [iterator]); |
6597 pushInvokeDynamic(node, call, mask, [iterator]); | |
6598 buildAssignLoopVariable(node, pop()); | 6549 buildAssignLoopVariable(node, pop()); |
6599 visit(node.body); | 6550 visit(node.body); |
6600 } | 6551 } |
6601 | 6552 |
6602 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); | 6553 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); |
6603 } | 6554 } |
6604 | 6555 |
6605 buildAssignLoopVariable(ast.ForIn node, HInstruction value) { | 6556 buildAssignLoopVariable(ast.ForIn node, HInstruction value) { |
6606 ast.Node identifier = node.declaredIdentifier; | 6557 ast.Node identifier = node.declaredIdentifier; |
6607 Element variable = elements.getForInVariable(node); | 6558 Element variable = elements.getForInVariable(node); |
6608 Selector selector = elements.getSelector(identifier); | 6559 Selector selector = elements.getSelector(identifier); |
6609 TypeMask mask = elements.getTypeMask(identifier); | |
6610 | 6560 |
6611 if (identifier.asSend() != null && | 6561 if (identifier.asSend() != null && |
6612 Elements.isInstanceSend(identifier, elements)) { | 6562 Elements.isInstanceSend(identifier, elements)) { |
6613 HInstruction receiver = generateInstanceSendReceiver(identifier); | 6563 HInstruction receiver = generateInstanceSendReceiver(identifier); |
6614 assert(receiver != null); | 6564 assert(receiver != null); |
6615 generateInstanceSetterWithCompiledReceiver( | 6565 generateInstanceSetterWithCompiledReceiver( |
6616 null, | 6566 null, |
6617 receiver, | 6567 receiver, |
6618 value, | 6568 value, |
6619 selector: selector, | 6569 selector: selector, |
6620 mask: mask, | |
6621 location: identifier); | 6570 location: identifier); |
6622 } else { | 6571 } else { |
6623 generateNonInstanceSetter(null, variable, value, location: identifier); | 6572 generateNonInstanceSetter(null, variable, value, location: identifier); |
6624 } | 6573 } |
6625 pop(); // Discard the value pushed by the setter call. | 6574 pop(); // Discard the value pushed by the setter call. |
6626 } | 6575 } |
6627 | 6576 |
6628 buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) { | 6577 buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) { |
6629 // Generate a structure equivalent to: | 6578 // Generate a structure equivalent to: |
6630 // | 6579 // |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6690 // inserted the ConcurrentModificationError check as part of the | 6639 // inserted the ConcurrentModificationError check as part of the |
6691 // condition. It is not necessary on the first iteration since there is | 6640 // condition. It is not necessary on the first iteration since there is |
6692 // no code between calls to `get iterator` and `moveNext`, so the test is | 6641 // no code between calls to `get iterator` and `moveNext`, so the test is |
6693 // moved to the loop update. | 6642 // moved to the loop update. |
6694 | 6643 |
6695 // Find a type for the element. Use the element type of the indexer of the | 6644 // Find a type for the element. Use the element type of the indexer of the |
6696 // array, as this is stronger than the iterator's `get current` type, for | 6645 // array, as this is stronger than the iterator's `get current` type, for |
6697 // example, `get current` includes null. | 6646 // example, `get current` includes null. |
6698 // TODO(sra): The element type of a container type mask might be better. | 6647 // TODO(sra): The element type of a container type mask might be better. |
6699 Selector selector = new Selector.index(); | 6648 Selector selector = new Selector.index(); |
6700 TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 6649 Selector refined = new TypedSelector(arrayType, selector, compiler.world); |
6701 selector, arrayType, compiler); | 6650 TypeMask type = |
| 6651 TypeMaskFactory.inferredTypeForSelector(refined, compiler); |
6702 | 6652 |
6703 HInstruction index = localsHandler.readLocal(indexVariable); | 6653 HInstruction index = localsHandler.readLocal(indexVariable); |
6704 HInstruction value = new HIndex(array, index, null, type); | 6654 HInstruction value = new HIndex(array, index, null, type); |
6705 add(value); | 6655 add(value); |
6706 | 6656 |
6707 buildAssignLoopVariable(node, value); | 6657 buildAssignLoopVariable(node, value); |
6708 visit(node.body); | 6658 visit(node.body); |
6709 } | 6659 } |
6710 | 6660 |
6711 void buildUpdate() { | 6661 void buildUpdate() { |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7608 // conversions. | 7558 // conversions. |
7609 // 2. The value can be primitive, because the library stringifier has | 7559 // 2. The value can be primitive, because the library stringifier has |
7610 // fast-path code for most primitives. | 7560 // fast-path code for most primitives. |
7611 if (expression.canBePrimitive(compiler)) { | 7561 if (expression.canBePrimitive(compiler)) { |
7612 append(stringify(node, expression)); | 7562 append(stringify(node, expression)); |
7613 return; | 7563 return; |
7614 } | 7564 } |
7615 | 7565 |
7616 // If the `toString` method is guaranteed to return a string we can call it | 7566 // If the `toString` method is guaranteed to return a string we can call it |
7617 // directly. | 7567 // directly. |
7618 Selector selector = new Selector.call('toString', null, 0); | 7568 Selector selector = |
7619 TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 7569 new TypedSelector(expression.instructionType, |
7620 selector, expression.instructionType, compiler); | 7570 new Selector.call('toString', null, 0), compiler.world); |
| 7571 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); |
7621 if (type.containsOnlyString(compiler.world)) { | 7572 if (type.containsOnlyString(compiler.world)) { |
7622 builder.pushInvokeDynamic( | 7573 builder.pushInvokeDynamic(node, selector, <HInstruction>[expression]); |
7623 node, selector, expression.instructionType, <HInstruction>[expression]
); | |
7624 append(builder.pop()); | 7574 append(builder.pop()); |
7625 return; | 7575 return; |
7626 } | 7576 } |
7627 | 7577 |
7628 append(stringify(node, expression)); | 7578 append(stringify(node, expression)); |
7629 } | 7579 } |
7630 | 7580 |
7631 void visitStringInterpolation(ast.StringInterpolation node) { | 7581 void visitStringInterpolation(ast.StringInterpolation node) { |
7632 node.visitChildren(this); | 7582 node.visitChildren(this); |
7633 } | 7583 } |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8159 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8109 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
8160 unaliased.accept(this, builder); | 8110 unaliased.accept(this, builder); |
8161 } | 8111 } |
8162 | 8112 |
8163 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8113 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
8164 JavaScriptBackend backend = builder.compiler.backend; | 8114 JavaScriptBackend backend = builder.compiler.backend; |
8165 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8115 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
8166 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8116 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
8167 } | 8117 } |
8168 } | 8118 } |
OLD | NEW |