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