Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 1182913003: Split TypedSelector into Selector and TypeMask. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/tree_elements.dart ('k') | pkg/compiler/lib/src/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698