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