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

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: 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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2443 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, 2447 return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
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 arguments = [buildFunctionType(type), original]; 2453 List arguments = [buildFunctionType(type), original];
2450 pushInvokeDynamic( 2454 pushInvokeDynamic(
2451 null, 2455 null,
2452 new Selector.call(name, backend.jsHelperLibrary, 1), 2456 new Selector.call(name, backend.jsHelperLibrary, 1),
2457 null,
2453 arguments); 2458 arguments);
2454 2459
2455 return new HTypeConversion(type, kind, original.instructionType, pop()); 2460 return new HTypeConversion(type, kind, original.instructionType, pop());
2456 } else { 2461 } else {
2457 return original.convertType(compiler, type, kind); 2462 return original.convertType(compiler, type, kind);
2458 } 2463 }
2459 } 2464 }
2460 2465
2461 HInstruction _trustType(HInstruction original, DartType type) { 2466 HInstruction _trustType(HInstruction original, DartType type) {
2462 assert(compiler.trustTypeAnnotations); 2467 assert(compiler.trustTypeAnnotations);
(...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after
3185 if (operand is HConstant) { 3190 if (operand is HConstant) {
3186 UnaryOperation operation = constantSystem.lookupUnary(operator); 3191 UnaryOperation operation = constantSystem.lookupUnary(operator);
3187 HConstant constant = operand; 3192 HConstant constant = operand;
3188 ConstantValue folded = operation.fold(constant.constant); 3193 ConstantValue folded = operation.fold(constant.constant);
3189 if (folded != null) { 3194 if (folded != null) {
3190 stack.add(graph.addConstant(folded, compiler)); 3195 stack.add(graph.addConstant(folded, compiler));
3191 return; 3196 return;
3192 } 3197 }
3193 } 3198 }
3194 3199
3195 pushInvokeDynamic(node, elements.getSelector(node), [operand]); 3200 pushInvokeDynamic(
3201 node,
3202 elements.getSelector(node),
3203 elements.getTypeMask(node),
3204 [operand]);
3196 } 3205 }
3197 3206
3198 @override 3207 @override
3199 void visitBinary(ast.Send node, 3208 void visitBinary(ast.Send node,
3200 ast.Node left, 3209 ast.Node left,
3201 BinaryOperator operator, 3210 BinaryOperator operator,
3202 ast.Node right, _) { 3211 ast.Node right, _) {
3203 handleBinary(node, left, right); 3212 handleBinary(node, left, right);
3204 } 3213 }
3205 3214
(...skipping 11 matching lines...) Expand all
3217 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { 3226 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) {
3218 handleBinary(node, left, right); 3227 handleBinary(node, left, right);
3219 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); 3228 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector);
3220 } 3229 }
3221 3230
3222 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { 3231 void handleBinary(ast.Send node, ast.Node left, ast.Node right) {
3223 visitBinarySend( 3232 visitBinarySend(
3224 visitAndPop(left), 3233 visitAndPop(left),
3225 visitAndPop(right), 3234 visitAndPop(right),
3226 elements.getSelector(node), 3235 elements.getSelector(node),
3236 elements.getTypeMask(node),
3227 node, 3237 node,
3228 location: node.selector); 3238 location: node.selector);
3229 } 3239 }
3230 3240
3231 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and 3241 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and
3232 /// remove use of [location] for source information. 3242 /// remove use of [location] for source information.
3233 void visitBinarySend(HInstruction left, 3243 void visitBinarySend(HInstruction left,
3234 HInstruction right, 3244 HInstruction right,
3235 Selector selector, 3245 Selector selector,
3246 TypeMask mask,
3236 ast.Send send, 3247 ast.Send send,
3237 {ast.Node location}) { 3248 {ast.Node location}) {
3238 pushInvokeDynamic(send, selector, [left, right], location: location); 3249 pushInvokeDynamic(send, selector, mask, [left, right], location: location);
3239 } 3250 }
3240 3251
3241 HInstruction generateInstanceSendReceiver(ast.Send send) { 3252 HInstruction generateInstanceSendReceiver(ast.Send send) {
3242 assert(Elements.isInstanceSend(send, elements)); 3253 assert(Elements.isInstanceSend(send, elements));
3243 if (send.receiver == null) { 3254 if (send.receiver == null) {
3244 return localsHandler.readThis(); 3255 return localsHandler.readThis();
3245 } 3256 }
3246 visit(send.receiver); 3257 visit(send.receiver);
3247 return pop(); 3258 return pop();
3248 } 3259 }
3249 3260
3250 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { 3261 String noSuchMethodTargetSymbolString(Element error, [String prefix]) {
3251 String result = error.name; 3262 String result = error.name;
3252 if (prefix == "set") return "$result="; 3263 if (prefix == "set") return "$result=";
3253 return result; 3264 return result;
3254 } 3265 }
3255 3266
3256 /** 3267 /**
3257 * Returns a set of interceptor classes that contain the given 3268 * Returns a set of interceptor classes that contain the given
3258 * [selector]. 3269 * [selector].
3259 */ 3270 */
3260 void generateInstanceGetterWithCompiledReceiver(ast.Send send, 3271 void generateInstanceGetterWithCompiledReceiver(
3261 Selector selector, 3272 ast.Send send,
3262 HInstruction receiver) { 3273 Selector selector,
3274 TypeMask mask,
3275 HInstruction receiver) {
3263 assert(Elements.isInstanceSend(send, elements)); 3276 assert(Elements.isInstanceSend(send, elements));
3264 assert(selector.isGetter); 3277 assert(selector.isGetter);
3265 pushInvokeDynamic(send, selector, [receiver]); 3278 pushInvokeDynamic(send, selector, mask, [receiver]);
3266 } 3279 }
3267 3280
3268 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. 3281 /// Inserts a call to checkDeferredIsLoaded for [prefixElement].
3269 /// If [prefixElement] is [null] ndo nothing. 3282 /// If [prefixElement] is [null] ndo nothing.
3270 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, 3283 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement,
3271 ast.Node location) { 3284 ast.Node location) {
3272 if (prefixElement == null) return; 3285 if (prefixElement == null) return;
3273 String loadId = 3286 String loadId =
3274 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; 3287 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport];
3275 HInstruction loadIdConstant = addConstantString(loadId); 3288 HInstruction loadIdConstant = addConstantString(loadId);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
3373 } else { 3386 } else {
3374 generateIsDeferredLoadedCheckOfSend(node); 3387 generateIsDeferredLoadedCheckOfSend(node);
3375 pushInvokeStatic(node, getter, <HInstruction>[]); 3388 pushInvokeStatic(node, getter, <HInstruction>[]);
3376 } 3389 }
3377 } 3390 }
3378 3391
3379 /// Generate a dynamic getter invocation. 3392 /// Generate a dynamic getter invocation.
3380 void generateDynamicGet(ast.Send node) { 3393 void generateDynamicGet(ast.Send node) {
3381 HInstruction receiver = generateInstanceSendReceiver(node); 3394 HInstruction receiver = generateInstanceSendReceiver(node);
3382 generateInstanceGetterWithCompiledReceiver( 3395 generateInstanceGetterWithCompiledReceiver(
3383 node, elements.getSelector(node), receiver); 3396 node, elements.getSelector(node), elements.getTypeMask(node), receiver);
3384 } 3397 }
3385 3398
3386 /// Generate a closurization of the static or top level [function]. 3399 /// Generate a closurization of the static or top level [function].
3387 void generateStaticFunctionGet(ast.Send node, MethodElement function) { 3400 void generateStaticFunctionGet(ast.Send node, MethodElement function) {
3388 generateIsDeferredLoadedCheckOfSend(node); 3401 generateIsDeferredLoadedCheckOfSend(node);
3389 // TODO(5346): Try to avoid the need for calling [declaration] before 3402 // TODO(5346): Try to avoid the need for calling [declaration] before
3390 // creating an [HStatic]. 3403 // creating an [HStatic].
3391 push(new HStatic(function.declaration, backend.nonNullType)); 3404 push(new HStatic(function.declaration, backend.nonNullType));
3392 // TODO(ahe): This should be registered in codegen. 3405 // TODO(ahe): This should be registered in codegen.
3393 registry.registerGetOfStaticFunction(function.declaration); 3406 registry.registerGetOfStaticFunction(function.declaration);
(...skipping 26 matching lines...) Expand all
3420 // we will be able to later compress it as: 3433 // we will be able to later compress it as:
3421 // t1 || t1.x 3434 // t1 || t1.x
3422 HInstruction expression; 3435 HInstruction expression;
3423 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 3436 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
3424 brancher.handleConditional( 3437 brancher.handleConditional(
3425 () { 3438 () {
3426 expression = visitAndPop(receiver); 3439 expression = visitAndPop(receiver);
3427 pushCheckNull(expression); 3440 pushCheckNull(expression);
3428 }, 3441 },
3429 () => stack.add(expression), 3442 () => stack.add(expression),
3430 () => generateInstanceGetterWithCompiledReceiver( 3443 () {
3431 node, elements.getSelector(node), expression)); 3444 generateInstanceGetterWithCompiledReceiver(
3445 node,
3446 elements.getSelector(node),
3447 elements.getTypeMask(node),
3448 expression);
3449 });
3432 } 3450 }
3433 3451
3434 /// Pushes a boolean checking [expression] against null. 3452 /// Pushes a boolean checking [expression] against null.
3435 pushCheckNull(HInstruction expression) { 3453 pushCheckNull(HInstruction expression) {
3436 push(new HIdentity(expression, graph.addConstantNull(compiler), 3454 push(new HIdentity(expression, graph.addConstantNull(compiler),
3437 null, backend.boolType)); 3455 null, backend.boolType));
3438 } 3456 }
3439 3457
3440 @override 3458 @override
3441 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { 3459 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3505 ast.Send node, 3523 ast.Send node,
3506 FunctionElement getter, 3524 FunctionElement getter,
3507 _) { 3525 _) {
3508 generateStaticGetterGet(node, getter); 3526 generateStaticGetterGet(node, getter);
3509 } 3527 }
3510 3528
3511 void generatePossiblyConditionalInstanceSetter(ast.Send send, 3529 void generatePossiblyConditionalInstanceSetter(ast.Send send,
3512 HInstruction pushReceiver(), 3530 HInstruction pushReceiver(),
3513 HInstruction pushValue(), 3531 HInstruction pushValue(),
3514 {Selector selector, 3532 {Selector selector,
3533 TypeMask mask,
3515 ast.Node location}) { 3534 ast.Node location}) {
3516 if (send.isConditional) { 3535 if (send.isConditional) {
3517 SsaBranchBuilder brancher = new SsaBranchBuilder(this, send); 3536 SsaBranchBuilder brancher = new SsaBranchBuilder(this, send);
3518 // compile e?.x = e2 to: 3537 // compile e?.x = e2 to:
3519 // 3538 //
3520 // t1 = e 3539 // t1 = e
3521 // if (t1 == null) 3540 // if (t1 == null)
3522 // result = t1 // same as result = null 3541 // result = t1 // same as result = null
3523 // else 3542 // else
3524 // result = e.x = e2 3543 // result = e.x = e2
3525 HInstruction receiver; 3544 HInstruction receiver;
3526 brancher.handleConditional( 3545 brancher.handleConditional(
3527 () { 3546 () {
3528 receiver = pushReceiver(); 3547 receiver = pushReceiver();
3529 pushCheckNull(receiver); 3548 pushCheckNull(receiver);
3530 }, 3549 },
3531 () => stack.add(receiver), 3550 () => stack.add(receiver),
3532 () => generateInstanceSetterWithCompiledReceiver( 3551 () => generateInstanceSetterWithCompiledReceiver(
3533 send, receiver, pushValue(), 3552 send, receiver, pushValue(),
3534 selector: selector, location: location)); 3553 selector: selector, mask: mask, location: location));
3535 } else { 3554 } else {
3536 generateInstanceSetterWithCompiledReceiver( 3555 generateInstanceSetterWithCompiledReceiver(
3537 send, pushReceiver(), pushValue(), 3556 send, pushReceiver(), pushValue(),
3538 selector: selector, location: location); 3557 selector: selector, mask: mask, location: location);
3539 } 3558 }
3540 } 3559 }
3541 3560
3542 void generateInstanceSetterWithCompiledReceiver(ast.Send send, 3561 void generateInstanceSetterWithCompiledReceiver(ast.Send send,
3543 HInstruction receiver, 3562 HInstruction receiver,
3544 HInstruction value, 3563 HInstruction value,
3545 {Selector selector, 3564 {Selector selector,
3565 TypeMask mask,
3546 ast.Node location}) { 3566 ast.Node location}) {
3547 assert(send == null || Elements.isInstanceSend(send, elements)); 3567 assert(send == null || Elements.isInstanceSend(send, elements));
3548 if (selector == null) { 3568 if (selector == null) {
3549 assert(send != null); 3569 assert(send != null);
3550 selector = elements.getSelector(send); 3570 selector = elements.getSelector(send);
3571 if (mask == null) {
3572 mask = elements.getTypeMask(send);
3573 }
3551 } 3574 }
3552 if (location == null) { 3575 if (location == null) {
3553 assert(send != null); 3576 assert(send != null);
3554 location = send; 3577 location = send;
3555 } 3578 }
3556 assert(selector.isSetter); 3579 assert(selector.isSetter);
3557 pushInvokeDynamic(location, selector, [receiver, value]); 3580 pushInvokeDynamic(location, selector, mask, [receiver, value]);
3558 pop(); 3581 pop();
3559 stack.add(value); 3582 stack.add(value);
3560 } 3583 }
3561 3584
3562 void generateNonInstanceSetter(ast.SendSet send, 3585 void generateNonInstanceSetter(ast.SendSet send,
3563 Element element, 3586 Element element,
3564 HInstruction value, 3587 HInstruction value,
3565 {ast.Node location}) { 3588 {ast.Node location}) {
3566 assert(send == null || !Elements.isInstanceSend(send, elements)); 3589 assert(send == null || !Elements.isInstanceSend(send, elements));
3567 if (location == null) { 3590 if (location == null) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3682 push(new HNot(instruction, backend.boolType)); 3705 push(new HNot(instruction, backend.boolType));
3683 } 3706 }
3684 3707
3685 HInstruction buildIsNode(ast.Node node, 3708 HInstruction buildIsNode(ast.Node node,
3686 DartType type, 3709 DartType type,
3687 HInstruction expression) { 3710 HInstruction expression) {
3688 type = localsHandler.substInContext(type).unalias(compiler); 3711 type = localsHandler.substInContext(type).unalias(compiler);
3689 if (type.isFunctionType) { 3712 if (type.isFunctionType) {
3690 List arguments = [buildFunctionType(type), expression]; 3713 List arguments = [buildFunctionType(type), expression];
3691 pushInvokeDynamic( 3714 pushInvokeDynamic(
3692 node, new Selector.call('_isTest', backend.jsHelperLibrary, 1), 3715 node,
3716 new Selector.call('_isTest', backend.jsHelperLibrary, 1),
3717 null,
3693 arguments); 3718 arguments);
3694 return new HIs.compound(type, expression, pop(), backend.boolType); 3719 return new HIs.compound(type, expression, pop(), backend.boolType);
3695 } else if (type.isTypeVariable) { 3720 } else if (type.isTypeVariable) {
3696 HInstruction runtimeType = addTypeVariableReference(type); 3721 HInstruction runtimeType = addTypeVariableReference(type);
3697 Element helper = backend.getCheckSubtypeOfRuntimeType(); 3722 Element helper = backend.getCheckSubtypeOfRuntimeType();
3698 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; 3723 List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
3699 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); 3724 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType);
3700 HInstruction call = pop(); 3725 HInstruction call = pop();
3701 return new HIs.variable(type, expression, call, backend.boolType); 3726 return new HIs.variable(type, expression, call, backend.boolType);
3702 } else if (RuntimeTypes.hasTypeArguments(type)) { 3727 } else if (RuntimeTypes.hasTypeArguments(type)) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3804 } 3829 }
3805 3830
3806 /// Generate a dynamic method, getter or setter invocation. 3831 /// Generate a dynamic method, getter or setter invocation.
3807 void generateDynamicSend(ast.Send node) { 3832 void generateDynamicSend(ast.Send node) {
3808 HInstruction receiver = generateInstanceSendReceiver(node); 3833 HInstruction receiver = generateInstanceSendReceiver(node);
3809 _generateDynamicSend(node, receiver); 3834 _generateDynamicSend(node, receiver);
3810 } 3835 }
3811 3836
3812 void _generateDynamicSend(ast.Send node, HInstruction receiver) { 3837 void _generateDynamicSend(ast.Send node, HInstruction receiver) {
3813 Selector selector = elements.getSelector(node); 3838 Selector selector = elements.getSelector(node);
3839 TypeMask mask = elements.getTypeMask(node);
3814 3840
3815 List<HInstruction> inputs = <HInstruction>[]; 3841 List<HInstruction> inputs = <HInstruction>[];
3816 inputs.add(receiver); 3842 inputs.add(receiver);
3817 addDynamicSendArgumentsToList(node, inputs); 3843 addDynamicSendArgumentsToList(node, inputs);
3818 3844
3819 pushInvokeDynamic(node, selector, inputs); 3845 pushInvokeDynamic(node, selector, mask, inputs);
3820 if (selector.isSetter || selector.isIndexSet) { 3846 if (selector.isSetter || selector.isIndexSet) {
3821 pop(); 3847 pop();
3822 stack.add(inputs.last); 3848 stack.add(inputs.last);
3823 } 3849 }
3824 } 3850 }
3825 3851
3826 @override 3852 @override
3827 visitDynamicPropertyInvoke( 3853 visitDynamicPropertyInvoke(
3828 ast.Send node, 3854 ast.Send node,
3829 ast.Node receiver, 3855 ast.Node receiver,
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
4173 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); 4199 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
4174 stack.add(graph.addConstantNull(compiler)); 4200 stack.add(graph.addConstantNull(compiler));
4175 } 4201 }
4176 4202
4177 void handleForeignJsCallInIsolate(ast.Send node) { 4203 void handleForeignJsCallInIsolate(ast.Send node) {
4178 Link<ast.Node> link = node.arguments; 4204 Link<ast.Node> link = node.arguments;
4179 if (!compiler.hasIsolateSupport) { 4205 if (!compiler.hasIsolateSupport) {
4180 // If the isolate library is not used, we just invoke the 4206 // If the isolate library is not used, we just invoke the
4181 // closure. 4207 // closure.
4182 visit(link.tail.head); 4208 visit(link.tail.head);
4183 Selector selector = new Selector.callClosure(0); 4209 push(new HInvokeClosure(new Selector.callClosure(0),
4184 push(new HInvokeClosure(selector,
4185 <HInstruction>[pop()], 4210 <HInstruction>[pop()],
4186 backend.dynamicType)); 4211 backend.dynamicType));
4187 } else { 4212 } else {
4188 // Call a helper method from the isolate library. 4213 // Call a helper method from the isolate library.
4189 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); 4214 Element element = backend.isolateHelperLibrary.find('_callInIsolate');
4190 if (element == null) { 4215 if (element == null) {
4191 compiler.internalError(node, 4216 compiler.internalError(node,
4192 'Isolate library and compiler mismatch.'); 4217 'Isolate library and compiler mismatch.');
4193 } 4218 }
4194 List<HInstruction> inputs = <HInstruction>[]; 4219 List<HInstruction> inputs = <HInstruction>[];
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
4316 String name = selector.name; 4341 String name = selector.name;
4317 4342
4318 ClassElement cls = currentNonClosureClass; 4343 ClassElement cls = currentNonClosureClass;
4319 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); 4344 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD);
4320 if (compiler.enabledInvokeOn 4345 if (compiler.enabledInvokeOn
4321 && element.enclosingElement.declaration != compiler.objectClass) { 4346 && element.enclosingElement.declaration != compiler.objectClass) {
4322 // Register the call as dynamic if [noSuchMethod] on the super 4347 // Register the call as dynamic if [noSuchMethod] on the super
4323 // class is _not_ the default implementation from [Object], in 4348 // class is _not_ the default implementation from [Object], in
4324 // case the [noSuchMethod] implementation calls 4349 // case the [noSuchMethod] implementation calls
4325 // [JSInvocationMirror._invokeOn]. 4350 // [JSInvocationMirror._invokeOn].
4326 registry.registerSelectorUse(selector.asUntyped); 4351 registry.registerSelectorUse(selector);
4327 } 4352 }
4328 String publicName = name; 4353 String publicName = name;
4329 if (selector.isSetter) publicName += '='; 4354 if (selector.isSetter) publicName += '=';
4330 4355
4331 ConstantValue nameConstant = constantSystem.createString( 4356 ConstantValue nameConstant = constantSystem.createString(
4332 new ast.DartString.literal(publicName)); 4357 new ast.DartString.literal(publicName));
4333 4358
4334 String internalName = backend.namer.invocationName(selector); 4359 String internalName = backend.namer.invocationName(selector);
4335 ConstantValue internalNameConstant = 4360 ConstantValue internalNameConstant =
4336 constantSystem.createString(new ast.DartString.literal(internalName)); 4361 constantSystem.createString(new ast.DartString.literal(internalName));
(...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after
5332 // in if it is not used (e.g., in a try/catch). 5357 // in if it is not used (e.g., in a try/catch).
5333 HInstruction target = pop(); 5358 HInstruction target = pop();
5334 generateCallInvoke(node, target); 5359 generateCallInvoke(node, target);
5335 } 5360 }
5336 5361
5337 /// Generate a '.call' invocation on [target]. 5362 /// Generate a '.call' invocation on [target].
5338 void generateCallInvoke(ast.Send node, HInstruction target) { 5363 void generateCallInvoke(ast.Send node, HInstruction target) {
5339 Selector selector = elements.getSelector(node); 5364 Selector selector = elements.getSelector(node);
5340 List<HInstruction> inputs = <HInstruction>[target]; 5365 List<HInstruction> inputs = <HInstruction>[target];
5341 addDynamicSendArgumentsToList(node, inputs); 5366 addDynamicSendArgumentsToList(node, inputs);
5342 Selector closureSelector = new Selector.callClosureFrom(selector);
5343 pushWithPosition( 5367 pushWithPosition(
5344 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node); 5368 new HInvokeClosure(
5369 new Selector.callClosureFrom(selector),
5370 inputs, backend.dynamicType),
5371 node);
5345 } 5372 }
5346 5373
5347 visitGetterSend(ast.Send node) { 5374 visitGetterSend(ast.Send node) {
5348 internalError(node, "Unexpected visitGetterSend"); 5375 internalError(node, "Unexpected visitGetterSend");
5349 } 5376 }
5350 5377
5351 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. 5378 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError.
5352 internalError(Spannable node, String reason) { 5379 internalError(Spannable node, String reason) {
5353 compiler.internalError(node, reason); 5380 compiler.internalError(node, reason);
5354 } 5381 }
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
5463 String nameString = stringConstant.toDartString().slowToString(); 5490 String nameString = stringConstant.toDartString().slowToString();
5464 registry.registerConstSymbol(nameString); 5491 registry.registerConstSymbol(nameString);
5465 } 5492 }
5466 } else { 5493 } else {
5467 handleNewSend(node); 5494 handleNewSend(node);
5468 } 5495 }
5469 } 5496 }
5470 5497
5471 void pushInvokeDynamic(ast.Node node, 5498 void pushInvokeDynamic(ast.Node node,
5472 Selector selector, 5499 Selector selector,
5500 TypeMask mask,
5473 List<HInstruction> arguments, 5501 List<HInstruction> arguments,
5474 {ast.Node location}) { 5502 {ast.Node location}) {
5475 if (location == null) location = node; 5503 if (location == null) location = node;
5476 5504
5477 // We prefer to not inline certain operations on indexables, 5505 // We prefer to not inline certain operations on indexables,
5478 // because the constant folder will handle them better and turn 5506 // because the constant folder will handle them better and turn
5479 // them into simpler instructions that allow further 5507 // them into simpler instructions that allow further
5480 // optimizations. 5508 // optimizations.
5481 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { 5509 bool isOptimizableOperationOnIndexable(Selector selector, Element element) {
5482 bool isLength = selector.isGetter 5510 bool isLength = selector.isGetter
(...skipping 20 matching lines...) Expand all
5503 if (selector.isIndex) return true; 5531 if (selector.isIndex) return true;
5504 if (selector.isIndexSet) return true; 5532 if (selector.isIndexSet) return true;
5505 if (element == backend.jsArrayAdd 5533 if (element == backend.jsArrayAdd
5506 || element == backend.jsArrayRemoveLast 5534 || element == backend.jsArrayRemoveLast
5507 || element == backend.jsStringSplit) { 5535 || element == backend.jsStringSplit) {
5508 return true; 5536 return true;
5509 } 5537 }
5510 return false; 5538 return false;
5511 } 5539 }
5512 5540
5513 Element element = compiler.world.locateSingleElement(selector); 5541 Element element = compiler.world.locateSingleElement(selector, mask);
5514 if (element != null 5542 if (element != null &&
5515 && !element.isField 5543 !element.isField &&
5516 && !(element.isGetter && selector.isCall) 5544 !(element.isGetter && selector.isCall) &&
5517 && !(element.isFunction && selector.isGetter) 5545 !(element.isFunction && selector.isGetter) &&
5518 && !isOptimizableOperation(selector, element)) { 5546 !isOptimizableOperation(selector, element)) {
5519 if (tryInlineMethod(element, selector, arguments, node)) { 5547 if (selector.name == 'double') {
5548 //debugPrint('Try to inline $node call to $element');
5549 }
5550 if (tryInlineMethod(element, selector, mask, arguments, node)) {
5520 return; 5551 return;
5521 } 5552 }
5553 if (selector.name == 'double') {
karlklose 2015/06/17 12:43:11 Remove debug code.
Johnni Winther 2015/06/17 13:03:52 Done.
5554 //debugPrint('Failed to inline $node');
5555 }
5522 } 5556 }
5523 5557
5524 HInstruction receiver = arguments[0]; 5558 HInstruction receiver = arguments[0];
5525 List<HInstruction> inputs = <HInstruction>[]; 5559 List<HInstruction> inputs = <HInstruction>[];
5526 bool isIntercepted = backend.isInterceptedSelector(selector); 5560 bool isIntercepted = backend.isInterceptedSelector(selector);
5527 if (isIntercepted) { 5561 if (isIntercepted) {
5528 inputs.add(invokeInterceptor(receiver)); 5562 inputs.add(invokeInterceptor(receiver));
5529 } 5563 }
5530 inputs.addAll(arguments); 5564 inputs.addAll(arguments);
5531 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); 5565 TypeMask type =
5566 TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler);
5532 if (selector.isGetter) { 5567 if (selector.isGetter) {
5533 pushWithPosition( 5568 pushWithPosition(
5534 new HInvokeDynamicGetter(selector, null, inputs, type), 5569 new HInvokeDynamicGetter(selector, mask, null, inputs, type),
5535 location); 5570 location);
5536 } else if (selector.isSetter) { 5571 } else if (selector.isSetter) {
5537 pushWithPosition( 5572 pushWithPosition(
5538 new HInvokeDynamicSetter(selector, null, inputs, type), 5573 new HInvokeDynamicSetter(selector, mask, null, inputs, type),
5539 location); 5574 location);
5540 } else { 5575 } else {
5541 pushWithPosition( 5576 pushWithPosition(
5542 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), 5577 new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted),
5543 location); 5578 location);
5544 } 5579 }
5545 } 5580 }
5546 5581
5547 void pushInvokeStatic(ast.Node location, 5582 void pushInvokeStatic(ast.Node location,
5548 Element element, 5583 Element element,
5549 List<HInstruction> arguments, 5584 List<HInstruction> arguments,
5550 {TypeMask typeMask, 5585 {TypeMask typeMask,
5551 InterfaceType instanceType}) { 5586 InterfaceType instanceType}) {
5552 if (tryInlineMethod(element, null, arguments, location, 5587 if (tryInlineMethod(element, null, null, arguments, location,
5553 instanceType: instanceType)) { 5588 instanceType: instanceType)) {
5554 return; 5589 return;
5555 } 5590 }
5556 5591
5557 if (typeMask == null) { 5592 if (typeMask == null) {
5558 typeMask = 5593 typeMask =
5559 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); 5594 TypeMaskFactory.inferredReturnTypeForElement(element, compiler);
5560 } 5595 }
5561 bool targetCanThrow = !compiler.world.getCannotThrow(element); 5596 bool targetCanThrow = !compiler.world.getCannotThrow(element);
5562 // TODO(5346): Try to avoid the need for calling [declaration] before 5597 // TODO(5346): Try to avoid the need for calling [declaration] before
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
5597 } else { 5632 } else {
5598 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); 5633 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler);
5599 } 5634 }
5600 HInstruction instruction = new HInvokeSuper( 5635 HInstruction instruction = new HInvokeSuper(
5601 element, 5636 element,
5602 currentNonClosureClass, 5637 currentNonClosureClass,
5603 selector, 5638 selector,
5604 inputs, 5639 inputs,
5605 type, 5640 type,
5606 isSetter: selector.isSetter || selector.isIndexSet); 5641 isSetter: selector.isSetter || selector.isIndexSet);
5607 instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector); 5642 instruction.sideEffects =
5643 compiler.world.getSideEffectsOfSelector(selector, null);
5608 return instruction; 5644 return instruction;
5609 } 5645 }
5610 5646
5611 void handleComplexOperatorSend(ast.SendSet node, 5647 void handleComplexOperatorSend(ast.SendSet node,
5612 HInstruction receiver, 5648 HInstruction receiver,
5613 Link<ast.Node> arguments) { 5649 Link<ast.Node> arguments) {
5614 HInstruction rhs; 5650 HInstruction rhs;
5615 if (node.isPrefix || node.isPostfix) { 5651 if (node.isPrefix || node.isPostfix) {
5616 rhs = graph.addConstantInt(1, compiler); 5652 rhs = graph.addConstantInt(1, compiler);
5617 } else { 5653 } else {
5618 visit(arguments.head); 5654 visit(arguments.head);
5619 assert(arguments.tail.isEmpty); 5655 assert(arguments.tail.isEmpty);
5620 rhs = pop(); 5656 rhs = pop();
5621 } 5657 }
5622 visitBinarySend(receiver, rhs, 5658 visitBinarySend(receiver, rhs,
5623 elements.getOperatorSelectorInComplexSendSet(node), 5659 elements.getOperatorSelectorInComplexSendSet(node),
5660 elements.getOperatorTypeMaskInComplexSendSet(node),
5624 node, 5661 node,
5625 location: node.assignmentOperator); 5662 location: node.assignmentOperator);
5626 } 5663 }
5627 5664
5628 @override 5665 @override
5629 handleSendSet(ast.SendSet node) { 5666 handleSendSet(ast.SendSet node) {
5630 generateIsDeferredLoadedCheckOfSend(node); 5667 generateIsDeferredLoadedCheckOfSend(node);
5631 Element element = elements[node]; 5668 Element element = elements[node];
5632 if (!Elements.isUnresolved(element) && element.impliesType) { 5669 if (!Elements.isUnresolved(element) && element.impliesType) {
5633 ast.Identifier selector = node.selector; 5670 ast.Identifier selector = node.selector;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
5708 HInstruction index; 5745 HInstruction index;
5709 if (node.isIndex) { 5746 if (node.isIndex) {
5710 visit(arguments.head); 5747 visit(arguments.head);
5711 arguments = arguments.tail; 5748 arguments = arguments.tail;
5712 index = pop(); 5749 index = pop();
5713 } 5750 }
5714 5751
5715 pushInvokeDynamic( 5752 pushInvokeDynamic(
5716 node, 5753 node,
5717 elements.getGetterSelectorInComplexSendSet(node), 5754 elements.getGetterSelectorInComplexSendSet(node),
5755 elements.getGetterTypeMaskInComplexSendSet(node),
5718 [receiver, index]); 5756 [receiver, index]);
5719 HInstruction getterInstruction = pop(); 5757 HInstruction getterInstruction = pop();
5720 if (node.isIfNullAssignment) { 5758 if (node.isIfNullAssignment) {
5721 // Compile x[i] ??= e as: 5759 // Compile x[i] ??= e as:
5722 // t1 = x[i] 5760 // t1 = x[i]
5723 // if (t1 == null) 5761 // if (t1 == null)
5724 // t1 = x[i] = e; 5762 // t1 = x[i] = e;
5725 // result = t1 5763 // result = t1
5726 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5764 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
5727 brancher.handleIfNull(() => stack.add(getterInstruction), 5765 brancher.handleIfNull(() => stack.add(getterInstruction),
5728 () { 5766 () {
5729 visit(arguments.head); 5767 visit(arguments.head);
5730 HInstruction value = pop(); 5768 HInstruction value = pop();
5731 pushInvokeDynamic( 5769 pushInvokeDynamic(
5732 node, elements.getSelector(node), [receiver, index, value]); 5770 node,
5771 elements.getSelector(node),
5772 elements.getTypeMask(node),
5773 [receiver, index, value]);
5733 pop(); 5774 pop();
5734 stack.add(value); 5775 stack.add(value);
5735 }); 5776 });
5736 } else { 5777 } else {
5737 handleComplexOperatorSend(node, getterInstruction, arguments); 5778 handleComplexOperatorSend(node, getterInstruction, arguments);
5738 HInstruction value = pop(); 5779 HInstruction value = pop();
5739 pushInvokeDynamic( 5780 pushInvokeDynamic(
5740 node, elements.getSelector(node), [receiver, index, value]); 5781 node,
5782 elements.getSelector(node),
5783 elements.getTypeMask(node),
5784 [receiver, index, value]);
5741 pop(); 5785 pop();
5742 if (node.isPostfix) { 5786 if (node.isPostfix) {
5743 stack.add(getterInstruction); 5787 stack.add(getterInstruction);
5744 } else { 5788 } else {
5745 stack.add(value); 5789 stack.add(value);
5746 } 5790 }
5747 } 5791 }
5748 } 5792 }
5749 } else if ("=" == op.source) { 5793 } else if ("=" == op.source) {
5750 Link<ast.Node> link = node.arguments; 5794 Link<ast.Node> link = node.arguments;
(...skipping 23 matching lines...) Expand all
5774 generateThrowNoSuchMethod(node, selector.source, 5818 generateThrowNoSuchMethod(node, selector.source,
5775 argumentNodes: node.arguments); 5819 argumentNodes: node.arguments);
5776 } 5820 }
5777 return; 5821 return;
5778 } 5822 }
5779 5823
5780 if (Elements.isInstanceSend(node, elements)) { 5824 if (Elements.isInstanceSend(node, elements)) {
5781 void generateAssignment(HInstruction receiver) { 5825 void generateAssignment(HInstruction receiver) {
5782 // desugars `e.x op= e2` to `e.x = e.x op e2` 5826 // desugars `e.x op= e2` to `e.x = e.x op e2`
5783 generateInstanceGetterWithCompiledReceiver( 5827 generateInstanceGetterWithCompiledReceiver(
5784 node, elements.getGetterSelectorInComplexSendSet(node), receiver); 5828 node,
5829 elements.getGetterSelectorInComplexSendSet(node),
5830 elements.getGetterTypeMaskInComplexSendSet(node),
5831 receiver);
5785 HInstruction getterInstruction = pop(); 5832 HInstruction getterInstruction = pop();
5786 if (node.isIfNullAssignment) { 5833 if (node.isIfNullAssignment) {
5787 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5834 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
5788 brancher.handleIfNull(() => stack.add(getterInstruction), 5835 brancher.handleIfNull(() => stack.add(getterInstruction),
5789 () { 5836 () {
5790 visit(node.arguments.head); 5837 visit(node.arguments.head);
5791 generateInstanceSetterWithCompiledReceiver( 5838 generateInstanceSetterWithCompiledReceiver(
5792 node, receiver, pop()); 5839 node, receiver, pop());
5793 }); 5840 });
5794 } else { 5841 } else {
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
6202 HInstruction expression = pop(); 6249 HInstruction expression = pop();
6203 pushInvokeStatic(node, 6250 pushInvokeStatic(node,
6204 backend.getStreamIteratorConstructor(), 6251 backend.getStreamIteratorConstructor(),
6205 [expression, graph.addConstantNull(compiler)]); 6252 [expression, graph.addConstantNull(compiler)]);
6206 streamIterator = pop(); 6253 streamIterator = pop();
6207 6254
6208 void buildInitializer() {} 6255 void buildInitializer() {}
6209 6256
6210 HInstruction buildCondition() { 6257 HInstruction buildCondition() {
6211 Selector selector = elements.getMoveNextSelector(node); 6258 Selector selector = elements.getMoveNextSelector(node);
6212 pushInvokeDynamic(node, selector, [streamIterator]); 6259 TypeMask mask = elements.getMoveNextTypeMask(node);
6260 pushInvokeDynamic(node, selector, mask, [streamIterator]);
6213 HInstruction future = pop(); 6261 HInstruction future = pop();
6214 push(new HAwait(future, new TypeMask.subclass(compiler.objectClass, 6262 push(new HAwait(future, new TypeMask.subclass(compiler.objectClass,
6215 compiler.world))); 6263 compiler.world)));
6216 return popBoolified(); 6264 return popBoolified();
6217 } 6265 }
6218 void buildBody() { 6266 void buildBody() {
6219 Selector call = elements.getCurrentSelector(node); 6267 Selector call = elements.getCurrentSelector(node);
6220 pushInvokeDynamic(node, call, [streamIterator]); 6268 TypeMask callMask = elements.getCurrentTypeMask(node);
6269 pushInvokeDynamic(node, call, callMask, [streamIterator]);
6221 6270
6222 ast.Node identifier = node.declaredIdentifier; 6271 ast.Node identifier = node.declaredIdentifier;
6223 Element variable = elements.getForInVariable(node); 6272 Element variable = elements.getForInVariable(node);
6224 Selector selector = elements.getSelector(identifier); 6273 Selector selector = elements.getSelector(identifier);
6274 TypeMask mask = elements.getTypeMask(identifier);
6225 6275
6226 HInstruction value = pop(); 6276 HInstruction value = pop();
6227 if (identifier.asSend() != null 6277 if (identifier.asSend() != null
6228 && Elements.isInstanceSend(identifier, elements)) { 6278 && Elements.isInstanceSend(identifier, elements)) {
6229 HInstruction receiver = generateInstanceSendReceiver(identifier); 6279 HInstruction receiver = generateInstanceSendReceiver(identifier);
6230 assert(receiver != null); 6280 assert(receiver != null);
6231 generateInstanceSetterWithCompiledReceiver( 6281 generateInstanceSetterWithCompiledReceiver(
6232 null, 6282 null,
6233 receiver, 6283 receiver,
6234 value, 6284 value,
6235 selector: selector, 6285 selector: selector,
6286 mask: mask,
6236 location: identifier); 6287 location: identifier);
6237 } else { 6288 } else {
6238 generateNonInstanceSetter( 6289 generateNonInstanceSetter(
6239 null, variable, value, location: identifier); 6290 null, variable, value, location: identifier);
6240 } 6291 }
6241 pop(); // Pop the value pushed by the setter call. 6292 pop(); // Pop the value pushed by the setter call.
6242 6293
6243 visit(node.body); 6294 visit(node.body);
6244 } 6295 }
6245 6296
6246 void buildUpdate() {}; 6297 void buildUpdate() {};
6247 6298
6248 buildProtectedByFinally(() { 6299 buildProtectedByFinally(() {
6249 handleLoop(node, 6300 handleLoop(node,
6250 buildInitializer, 6301 buildInitializer,
6251 buildCondition, 6302 buildCondition,
6252 buildUpdate, 6303 buildUpdate,
6253 buildBody); 6304 buildBody);
6254 }, () { 6305 }, () {
6255 pushInvokeDynamic(node, new Selector.call("cancel", null, 0), 6306 pushInvokeDynamic(node,
6307 new Selector.call("cancel", null, 0),
6308 null,
6256 [streamIterator]); 6309 [streamIterator]);
6257 push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass, 6310 push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass,
6258 compiler.world))); 6311 compiler.world)));
6259 pop(); 6312 pop();
6260 }); 6313 });
6261 } 6314 }
6262 6315
6263 visitSyncForIn(ast.SyncForIn node) { 6316 visitSyncForIn(ast.SyncForIn node) {
6264 // The 'get iterator' selector for this node has the inferred receiver type. 6317 // The 'get iterator' selector for this node has the inferred receiver type.
6265 // If the receiver supports JavaScript indexing we generate an indexing loop 6318 // If the receiver supports JavaScript indexing we generate an indexing loop
6266 // instead of allocating an iterator object. 6319 // instead of allocating an iterator object.
6267 6320
6268 // This scheme recognizes for-in on direct lists. It does not recognize all 6321 // This scheme recognizes for-in on direct lists. It does not recognize all
6269 // uses of ArrayIterator. They still occur when the receiver is an Iterable 6322 // uses of ArrayIterator. They still occur when the receiver is an Iterable
6270 // with a `get iterator` method that delegate to another Iterable and the 6323 // with a `get iterator` method that delegate to another Iterable and the
6271 // method is inlined. We would require full scalar replacement in that 6324 // method is inlined. We would require full scalar replacement in that
6272 // case. 6325 // case.
6273 6326
6274 Selector selector = elements.getIteratorSelector(node); 6327 Selector selector = elements.getIteratorSelector(node);
6275 TypeMask mask = selector.mask; 6328 TypeMask mask = elements.getIteratorTypeMask(node);
6276 6329
6277 ClassWorld classWorld = compiler.world; 6330 ClassWorld classWorld = compiler.world;
6278 if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) { 6331 if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) {
6279 return buildSyncForInIndexable(node, mask); 6332 return buildSyncForInIndexable(node, mask);
6280 } 6333 }
6281 buildSyncForInIterator(node); 6334 buildSyncForInIterator(node);
6282 } 6335 }
6283 6336
6284 buildSyncForInIterator(ast.SyncForIn node) { 6337 buildSyncForInIterator(ast.SyncForIn node) {
6285 // Generate a structure equivalent to: 6338 // Generate a structure equivalent to:
6286 // Iterator<E> $iter = <iterable>.iterator; 6339 // Iterator<E> $iter = <iterable>.iterator;
6287 // while ($iter.moveNext()) { 6340 // while ($iter.moveNext()) {
6288 // <declaredIdentifier> = $iter.current; 6341 // <declaredIdentifier> = $iter.current;
6289 // <body> 6342 // <body>
6290 // } 6343 // }
6291 6344
6292 // The iterator is shared between initializer, condition and body. 6345 // The iterator is shared between initializer, condition and body.
6293 HInstruction iterator; 6346 HInstruction iterator;
6294 6347
6295 void buildInitializer() { 6348 void buildInitializer() {
6296 Selector selector = elements.getIteratorSelector(node); 6349 Selector selector = elements.getIteratorSelector(node);
6350 TypeMask mask = elements.getIteratorTypeMask(node);
6297 visit(node.expression); 6351 visit(node.expression);
6298 HInstruction receiver = pop(); 6352 HInstruction receiver = pop();
6299 pushInvokeDynamic(node, selector, [receiver]); 6353 pushInvokeDynamic(node, selector, mask, [receiver]);
6300 iterator = pop(); 6354 iterator = pop();
6301 } 6355 }
6302 6356
6303 HInstruction buildCondition() { 6357 HInstruction buildCondition() {
6304 Selector selector = elements.getMoveNextSelector(node); 6358 Selector selector = elements.getMoveNextSelector(node);
6305 pushInvokeDynamic(node, selector, [iterator]); 6359 TypeMask mask = elements.getMoveNextTypeMask(node);
6360 pushInvokeDynamic(node, selector, mask, [iterator]);
6306 return popBoolified(); 6361 return popBoolified();
6307 } 6362 }
6308 6363
6309 void buildBody() { 6364 void buildBody() {
6310 Selector call = elements.getCurrentSelector(node); 6365 Selector call = elements.getCurrentSelector(node);
6311 pushInvokeDynamic(node, call, [iterator]); 6366 TypeMask mask = elements.getCurrentTypeMask(node);
6367 pushInvokeDynamic(node, call, mask, [iterator]);
6312 buildAssignLoopVariable(node, pop()); 6368 buildAssignLoopVariable(node, pop());
6313 visit(node.body); 6369 visit(node.body);
6314 } 6370 }
6315 6371
6316 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); 6372 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody);
6317 } 6373 }
6318 6374
6319 buildAssignLoopVariable(ast.ForIn node, HInstruction value) { 6375 buildAssignLoopVariable(ast.ForIn node, HInstruction value) {
6320 ast.Node identifier = node.declaredIdentifier; 6376 ast.Node identifier = node.declaredIdentifier;
6321 Element variable = elements.getForInVariable(node); 6377 Element variable = elements.getForInVariable(node);
6322 Selector selector = elements.getSelector(identifier); 6378 Selector selector = elements.getSelector(identifier);
6379 TypeMask mask = elements.getTypeMask(identifier);
6323 6380
6324 if (identifier.asSend() != null && 6381 if (identifier.asSend() != null &&
6325 Elements.isInstanceSend(identifier, elements)) { 6382 Elements.isInstanceSend(identifier, elements)) {
6326 HInstruction receiver = generateInstanceSendReceiver(identifier); 6383 HInstruction receiver = generateInstanceSendReceiver(identifier);
6327 assert(receiver != null); 6384 assert(receiver != null);
6328 generateInstanceSetterWithCompiledReceiver( 6385 generateInstanceSetterWithCompiledReceiver(
6329 null, 6386 null,
6330 receiver, 6387 receiver,
6331 value, 6388 value,
6332 selector: selector, 6389 selector: selector,
6390 mask: mask,
6333 location: identifier); 6391 location: identifier);
6334 } else { 6392 } else {
6335 generateNonInstanceSetter(null, variable, value, location: identifier); 6393 generateNonInstanceSetter(null, variable, value, location: identifier);
6336 } 6394 }
6337 pop(); // Discard the value pushed by the setter call. 6395 pop(); // Discard the value pushed by the setter call.
6338 } 6396 }
6339 6397
6340 buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) { 6398 buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) {
6341 // Generate a structure equivalent to: 6399 // Generate a structure equivalent to:
6342 // 6400 //
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
6402 // inserted the ConcurrentModificationError check as part of the 6460 // inserted the ConcurrentModificationError check as part of the
6403 // condition. It is not necessary on the first iteration since there is 6461 // condition. It is not necessary on the first iteration since there is
6404 // no code between calls to `get iterator` and `moveNext`, so the test is 6462 // no code between calls to `get iterator` and `moveNext`, so the test is
6405 // moved to the loop update. 6463 // moved to the loop update.
6406 6464
6407 // Find a type for the element. Use the element type of the indexer of the 6465 // Find a type for the element. Use the element type of the indexer of the
6408 // array, as this is stronger than the iterator's `get current` type, for 6466 // array, as this is stronger than the iterator's `get current` type, for
6409 // example, `get current` includes null. 6467 // example, `get current` includes null.
6410 // TODO(sra): The element type of a container type mask might be better. 6468 // TODO(sra): The element type of a container type mask might be better.
6411 Selector selector = new Selector.index(); 6469 Selector selector = new Selector.index();
6412 Selector refined = new TypedSelector(arrayType, selector, compiler.world); 6470 TypeMask type = TypeMaskFactory.inferredTypeForSelector(
6413 TypeMask type = 6471 selector, arrayType, compiler);
6414 TypeMaskFactory.inferredTypeForSelector(refined, compiler);
6415 6472
6416 HInstruction index = localsHandler.readLocal(indexVariable); 6473 HInstruction index = localsHandler.readLocal(indexVariable);
6417 HInstruction value = new HIndex(array, index, null, type); 6474 HInstruction value = new HIndex(array, index, null, type);
6418 add(value); 6475 add(value);
6419 6476
6420 buildAssignLoopVariable(node, value); 6477 buildAssignLoopVariable(node, value);
6421 visit(node.body); 6478 visit(node.body);
6422 } 6479 }
6423 6480
6424 void buildUpdate() { 6481 void buildUpdate() {
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after
7321 // conversions. 7378 // conversions.
7322 // 2. The value can be primitive, because the library stringifier has 7379 // 2. The value can be primitive, because the library stringifier has
7323 // fast-path code for most primitives. 7380 // fast-path code for most primitives.
7324 if (expression.canBePrimitive(compiler)) { 7381 if (expression.canBePrimitive(compiler)) {
7325 append(stringify(node, expression)); 7382 append(stringify(node, expression));
7326 return; 7383 return;
7327 } 7384 }
7328 7385
7329 // If the `toString` method is guaranteed to return a string we can call it 7386 // If the `toString` method is guaranteed to return a string we can call it
7330 // directly. 7387 // directly.
7331 Selector selector = 7388 Selector selector = new Selector.call('toString', null, 0);
7332 new TypedSelector(expression.instructionType, 7389 TypeMask type = TypeMaskFactory.inferredTypeForSelector(
7333 new Selector.call('toString', null, 0), compiler.world); 7390 selector, expression.instructionType, compiler);
7334 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler);
7335 if (type.containsOnlyString(compiler.world)) { 7391 if (type.containsOnlyString(compiler.world)) {
7336 builder.pushInvokeDynamic(node, selector, <HInstruction>[expression]); 7392 builder.pushInvokeDynamic(
7393 node, selector, expression.instructionType, <HInstruction>[expression] );
7337 append(builder.pop()); 7394 append(builder.pop());
7338 return; 7395 return;
7339 } 7396 }
7340 7397
7341 append(stringify(node, expression)); 7398 append(stringify(node, expression));
7342 } 7399 }
7343 7400
7344 void visitStringInterpolation(ast.StringInterpolation node) { 7401 void visitStringInterpolation(ast.StringInterpolation node) {
7345 node.visitChildren(this); 7402 node.visitChildren(this);
7346 } 7403 }
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
7872 if (unaliased is TypedefType) throw 'unable to unalias $type'; 7929 if (unaliased is TypedefType) throw 'unable to unalias $type';
7873 unaliased.accept(this, builder); 7930 unaliased.accept(this, builder);
7874 } 7931 }
7875 7932
7876 void visitDynamicType(DynamicType type, SsaBuilder builder) { 7933 void visitDynamicType(DynamicType type, SsaBuilder builder) {
7877 JavaScriptBackend backend = builder.compiler.backend; 7934 JavaScriptBackend backend = builder.compiler.backend;
7878 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 7935 ClassElement cls = backend.findHelper('DynamicRuntimeType');
7879 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 7936 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
7880 } 7937 }
7881 } 7938 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698