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

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

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