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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart

Issue 36073002: Separate HTypeConversion checked type from output type. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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 | Annotate | Revision Log
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 SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 10
(...skipping 2451 matching lines...) Expand 10 before | Expand all | Expand 10 after
2462 js.Expression objectTest = pop(); 2462 js.Expression objectTest = pop();
2463 checkType(input, interceptor, type, negative: negative); 2463 checkType(input, interceptor, type, negative: negative);
2464 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node); 2464 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node);
2465 } else { 2465 } else {
2466 checkType(input, interceptor, type, negative: negative); 2466 checkType(input, interceptor, type, negative: negative);
2467 attachLocationToLast(node); 2467 attachLocationToLast(node);
2468 } 2468 }
2469 } 2469 }
2470 } 2470 }
2471 2471
2472 js.Expression generateTest(HCheck node) { 2472 js.Expression generateTest(HInstruction input, HType checkedType) {
2473 HInstruction input = node.checkedInput;
2474 TypeMask receiver = input.instructionType.computeMask(compiler); 2473 TypeMask receiver = input.instructionType.computeMask(compiler);
2475 TypeMask mask = node.instructionType.computeMask(compiler); 2474 TypeMask mask = checkedType.computeMask(compiler);
2476 // Figure out if it is beneficial to turn this into a null check. 2475 // Figure out if it is beneficial to turn this into a null check.
2477 // V8 generally prefers 'typeof' checks, but for integers and 2476 // V8 generally prefers 'typeof' checks, but for integers and
2478 // indexable primitives we cannot compile this test into a single 2477 // indexable primitives we cannot compile this test into a single
2479 // typeof check so the null check is cheaper. 2478 // typeof check so the null check is cheaper.
2480 bool turnIntoNumCheck = input.isIntegerOrNull() && node.isInteger(); 2479 bool turnIntoNumCheck = input.isIntegerOrNull() && checkedType.isInteger();
2481 bool turnIntoNullCheck = !turnIntoNumCheck 2480 bool turnIntoNullCheck = !turnIntoNumCheck
2482 && (mask.nullable() == receiver) 2481 && (mask.nullable() == receiver)
2483 && (node.isInteger() || node.isIndexablePrimitive(compiler)); 2482 && (checkedType.isInteger() || checkedType.isIndexablePrimitive(compiler ));
ngeoffray 2013/10/24 06:50:55 Line too long.
sra1 2013/10/25 03:48:53 Done.
2484 js.Expression test; 2483 js.Expression test;
2485 if (turnIntoNullCheck) { 2484 if (turnIntoNullCheck) {
2486 use(input); 2485 use(input);
2487 test = new js.Binary("==", pop(), new js.LiteralNull()); 2486 test = new js.Binary("==", pop(), new js.LiteralNull());
2488 } else if (node.isInteger() && !turnIntoNumCheck) { 2487 } else if (checkedType.isInteger() && !turnIntoNumCheck) {
2489 // input is !int 2488 // input is !int
2490 checkInt(input, '!=='); 2489 checkInt(input, '!==');
2491 test = pop(); 2490 test = pop();
2492 } else if (node.isNumber() || turnIntoNumCheck) { 2491 } else if (checkedType.isNumber() || turnIntoNumCheck) {
2493 // input is !num 2492 // input is !num
2494 checkNum(input, '!=='); 2493 checkNum(input, '!==');
2495 test = pop(); 2494 test = pop();
2496 } else if (node.isBoolean()) { 2495 } else if (checkedType.isBoolean()) {
2497 // input is !bool 2496 // input is !bool
2498 checkBool(input, '!=='); 2497 checkBool(input, '!==');
2499 test = pop(); 2498 test = pop();
2500 } else if (node.isString(compiler)) { 2499 } else if (checkedType.isString(compiler)) {
2501 // input is !string 2500 // input is !string
2502 checkString(input, '!=='); 2501 checkString(input, '!==');
2503 test = pop(); 2502 test = pop();
2504 } else if (node.isExtendableArray(compiler)) { 2503 } else if (checkedType.isExtendableArray(compiler)) {
2505 // input is !Object || input is !Array || input.isFixed 2504 // input is !Object || input is !Array || input.isFixed
2506 checkObject(input, '!=='); 2505 checkObject(input, '!==');
2507 js.Expression objectTest = pop(); 2506 js.Expression objectTest = pop();
2508 checkArray(input, '!=='); 2507 checkArray(input, '!==');
2509 js.Expression arrayTest = pop(); 2508 js.Expression arrayTest = pop();
2510 checkFixedArray(input); 2509 checkFixedArray(input);
2511 test = new js.Binary('||', objectTest, arrayTest); 2510 test = new js.Binary('||', objectTest, arrayTest);
2512 test = new js.Binary('||', test, pop()); 2511 test = new js.Binary('||', test, pop());
2513 } else if (node.isMutableArray(compiler)) { 2512 } else if (checkedType.isMutableArray(compiler)) {
2514 // input is !Object 2513 // input is !Object
2515 // || ((input is !Array || input.isImmutable) 2514 // || ((input is !Array || input.isImmutable)
2516 // && input is !JsIndexingBehavior) 2515 // && input is !JsIndexingBehavior)
2517 checkObject(input, '!=='); 2516 checkObject(input, '!==');
2518 js.Expression objectTest = pop(); 2517 js.Expression objectTest = pop();
2519 checkArray(input, '!=='); 2518 checkArray(input, '!==');
2520 js.Expression arrayTest = pop(); 2519 js.Expression arrayTest = pop();
2521 checkImmutableArray(input); 2520 checkImmutableArray(input);
2522 js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop()); 2521 js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop());
2523 2522
2524 js.Binary notIndexing = checkIndexingBehavior(input, negative: true) 2523 js.Binary notIndexing = checkIndexingBehavior(input, negative: true)
2525 ? new js.Binary('&&', notArrayOrImmutable, pop()) 2524 ? new js.Binary('&&', notArrayOrImmutable, pop())
2526 : notArrayOrImmutable; 2525 : notArrayOrImmutable;
2527 test = new js.Binary('||', objectTest, notIndexing); 2526 test = new js.Binary('||', objectTest, notIndexing);
2528 } else if (node.isReadableArray(compiler)) { 2527 } else if (checkedType.isReadableArray(compiler)) {
2529 // input is !Object 2528 // input is !Object
2530 // || (input is !Array && input is !JsIndexingBehavior) 2529 // || (input is !Array && input is !JsIndexingBehavior)
2531 checkObject(input, '!=='); 2530 checkObject(input, '!==');
2532 js.Expression objectTest = pop(); 2531 js.Expression objectTest = pop();
2533 checkArray(input, '!=='); 2532 checkArray(input, '!==');
2534 js.Expression arrayTest = pop(); 2533 js.Expression arrayTest = pop();
2535 2534
2536 js.Expression notIndexing = checkIndexingBehavior(input, negative: true) 2535 js.Expression notIndexing = checkIndexingBehavior(input, negative: true)
2537 ? new js.Binary('&&', arrayTest, pop()) 2536 ? new js.Binary('&&', arrayTest, pop())
2538 : arrayTest; 2537 : arrayTest;
2539 test = new js.Binary('||', objectTest, notIndexing); 2538 test = new js.Binary('||', objectTest, notIndexing);
2540 } else if (node.isIndexablePrimitive(compiler)) { 2539 } else if (checkedType.isIndexablePrimitive(compiler)) {
2541 // input is !String 2540 // input is !String
2542 // && (input is !Object 2541 // && (input is !Object
2543 // || (input is !Array && input is !JsIndexingBehavior)) 2542 // || (input is !Array && input is !JsIndexingBehavior))
2544 checkString(input, '!=='); 2543 checkString(input, '!==');
2545 js.Expression stringTest = pop(); 2544 js.Expression stringTest = pop();
2546 checkObject(input, '!=='); 2545 checkObject(input, '!==');
2547 js.Expression objectTest = pop(); 2546 js.Expression objectTest = pop();
2548 checkArray(input, '!=='); 2547 checkArray(input, '!==');
2549 js.Expression arrayTest = pop(); 2548 js.Expression arrayTest = pop();
2550 2549
2551 js.Binary notIndexingTest = checkIndexingBehavior(input, negative: true) 2550 js.Binary notIndexingTest = checkIndexingBehavior(input, negative: true)
2552 ? new js.Binary('&&', arrayTest, pop()) 2551 ? new js.Binary('&&', arrayTest, pop())
2553 : arrayTest; 2552 : arrayTest;
2554 js.Binary notObjectOrIndexingTest = 2553 js.Binary notObjectOrIndexingTest =
2555 new js.Binary('||', objectTest, notIndexingTest); 2554 new js.Binary('||', objectTest, notIndexingTest);
2556 test = new js.Binary('&&', stringTest, notObjectOrIndexingTest); 2555 test = new js.Binary('&&', stringTest, notObjectOrIndexingTest);
2557 } else { 2556 } else {
2558 compiler.internalError('Unexpected check', instruction: input); 2557 compiler.internalError('Unexpected check', instruction: input);
2559 } 2558 }
2560 return test; 2559 return test;
2561 } 2560 }
2562 2561
2563 void visitTypeConversion(HTypeConversion node) { 2562 void visitTypeConversion(HTypeConversion node) {
2564 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { 2563 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
2565 // An int check if the input is not int or null, is not 2564 // An int check if the input is not int or null, is not
2566 // sufficient for doing a argument or receiver check. 2565 // sufficient for doing a argument or receiver check.
2567 assert(!node.isInteger() || node.checkedInput.isIntegerOrNull()); 2566 assert(!node.checkedType.isInteger() ||
2568 js.Expression test = generateTest(node); 2567 node.checkedInput.isIntegerOrNull());
2568 js.Expression test = generateTest(node.checkedInput, node.checkedType);
2569 js.Block oldContainer = currentContainer; 2569 js.Block oldContainer = currentContainer;
2570 js.Statement body = new js.Block.empty(); 2570 js.Statement body = new js.Block.empty();
2571 currentContainer = body; 2571 currentContainer = body;
2572 if (node.isArgumentTypeCheck) { 2572 if (node.isArgumentTypeCheck) {
2573 generateThrowWithHelper('iae', node.checkedInput); 2573 generateThrowWithHelper('iae', node.checkedInput);
2574 } else if (node.isReceiverTypeCheck) { 2574 } else if (node.isReceiverTypeCheck) {
2575 use(node.checkedInput); 2575 use(node.checkedInput);
2576 String methodName = 2576 String methodName =
2577 backend.namer.invocationName(node.receiverTypeCheckSelector); 2577 backend.namer.invocationName(node.receiverTypeCheckSelector);
2578 js.Expression call = jsPropertyCall(pop(), methodName, []); 2578 js.Expression call = jsPropertyCall(pop(), methodName, []);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2658 bailoutTarget = new js.VariableUse(namer.isolateBailoutAccess(method)); 2658 bailoutTarget = new js.VariableUse(namer.isolateBailoutAccess(method));
2659 } 2659 }
2660 js.Call call = new js.Call(bailoutTarget, arguments); 2660 js.Call call = new js.Call(bailoutTarget, arguments);
2661 attachLocation(call, guard); 2661 attachLocation(call, guard);
2662 return new js.Return(call); 2662 return new js.Return(call);
2663 } 2663 }
2664 2664
2665 // Generate a type guard, something like "if (typeof t0 == 'number')" and the 2665 // Generate a type guard, something like "if (typeof t0 == 'number')" and the
2666 // corresponding bailout call, something like "return $.foo$bailout(t0, t1);" 2666 // corresponding bailout call, something like "return $.foo$bailout(t0, t1);"
2667 void visitTypeGuard(HTypeGuard node) { 2667 void visitTypeGuard(HTypeGuard node) {
2668 js.Expression test = generateTest(node); 2668 js.Expression test = generateTest(node.checkedInput, node.instructionType);
2669 pushStatement(new js.If.noElse(test, bailout(node)), node); 2669 pushStatement(new js.If.noElse(test, bailout(node)), node);
2670 } 2670 }
2671 2671
2672 void visitBailoutTarget(HBailoutTarget target) { 2672 void visitBailoutTarget(HBailoutTarget target) {
2673 // Do nothing. Bailout targets are only used in the non-optimized version. 2673 // Do nothing. Bailout targets are only used in the non-optimized version.
2674 } 2674 }
2675 2675
2676 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2676 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2677 } 2677 }
2678 2678
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
3052 if (leftType.canBeNull() && rightType.canBeNull()) { 3052 if (leftType.canBeNull() && rightType.canBeNull()) {
3053 if (left.isConstantNull() || right.isConstantNull() || 3053 if (left.isConstantNull() || right.isConstantNull() ||
3054 (leftType.isPrimitive(compiler) && leftType == rightType)) { 3054 (leftType.isPrimitive(compiler) && leftType == rightType)) {
3055 return '=='; 3055 return '==';
3056 } 3056 }
3057 return null; 3057 return null;
3058 } else { 3058 } else {
3059 return '==='; 3059 return '===';
3060 } 3060 }
3061 } 3061 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698