Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |