OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
703 } | 703 } |
704 | 704 |
705 | 705 |
706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
707 return AssignEnvironment(new(zone()) LDeoptimize); | 707 return AssignEnvironment(new(zone()) LDeoptimize); |
708 } | 708 } |
709 | 709 |
710 | 710 |
711 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 711 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
712 HBitwiseBinaryOperation* instr) { | 712 HBitwiseBinaryOperation* instr) { |
713 if (instr->representation().IsTagged()) { | 713 if (instr->representation().IsSmiOrInteger32()) { |
714 ASSERT(instr->left()->representation().IsTagged()); | 714 ASSERT(instr->left()->representation().Equals(instr->representation())); |
715 ASSERT(instr->right()->representation().IsTagged()); | 715 ASSERT(instr->right()->representation().Equals(instr->representation())); |
716 LOperand* left = UseRegisterAtStart(instr->left()); | |
716 | 717 |
717 LOperand* left = UseFixed(instr->left(), r1); | 718 HValue* right_value = instr->right(); |
718 LOperand* right = UseFixed(instr->right(), r0); | 719 LOperand* right = NULL; |
719 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); | 720 int constant_value = 0; |
720 return MarkAsCall(DefineFixed(result, r0), instr); | 721 bool does_deopt = false; |
722 if (right_value->IsConstant()) { | |
723 HConstant* constant = HConstant::cast(right_value); | |
724 right = chunk_->DefineConstantOperand(constant); | |
725 constant_value = constant->Integer32Value() & 0x1f; | |
726 // Left shifts can deoptimize if we shift by > 0 and the result cannot be | |
727 // truncated to smi. | |
728 if (instr->representation().IsSmi() && constant_value > 0) { | |
729 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); | |
730 } | |
731 } else { | |
732 right = UseRegisterAtStart(right_value); | |
733 } | |
734 | |
735 // Shift operations can only deoptimize if we do a logical shift | |
736 // by 0 and the result cannot be truncated to int32. | |
737 if (op == Token::SHR && constant_value == 0) { | |
738 if (FLAG_opt_safe_uint32_operations) { | |
739 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | |
740 } else { | |
741 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); | |
742 } | |
743 } | |
744 | |
745 LInstruction* result = | |
746 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); | |
747 return does_deopt ? AssignEnvironment(result) : result; | |
748 } else { | |
749 return DoArithmeticT(op, instr); | |
721 } | 750 } |
722 | |
723 ASSERT(instr->representation().IsSmiOrInteger32()); | |
724 ASSERT(instr->left()->representation().Equals(instr->representation())); | |
725 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
726 LOperand* left = UseRegisterAtStart(instr->left()); | |
727 | |
728 HValue* right_value = instr->right(); | |
729 LOperand* right = NULL; | |
730 int constant_value = 0; | |
731 bool does_deopt = false; | |
732 if (right_value->IsConstant()) { | |
733 HConstant* constant = HConstant::cast(right_value); | |
734 right = chunk_->DefineConstantOperand(constant); | |
735 constant_value = constant->Integer32Value() & 0x1f; | |
736 // Left shifts can deoptimize if we shift by > 0 and the result cannot be | |
737 // truncated to smi. | |
738 if (instr->representation().IsSmi() && constant_value > 0) { | |
739 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); | |
740 } | |
741 } else { | |
742 right = UseRegisterAtStart(right_value); | |
743 } | |
744 | |
745 // Shift operations can only deoptimize if we do a logical shift | |
746 // by 0 and the result cannot be truncated to int32. | |
747 if (op == Token::SHR && constant_value == 0) { | |
748 if (FLAG_opt_safe_uint32_operations) { | |
749 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | |
750 } else { | |
751 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); | |
752 } | |
753 } | |
754 | |
755 LInstruction* result = | |
756 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); | |
757 return does_deopt ? AssignEnvironment(result) : result; | |
758 } | 751 } |
759 | 752 |
760 | 753 |
761 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 754 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
762 HArithmeticBinaryOperation* instr) { | 755 HArithmeticBinaryOperation* instr) { |
763 ASSERT(instr->representation().IsDouble()); | 756 ASSERT(instr->representation().IsDouble()); |
764 ASSERT(instr->left()->representation().IsDouble()); | 757 ASSERT(instr->left()->representation().IsDouble()); |
765 ASSERT(instr->right()->representation().IsDouble()); | 758 ASSERT(instr->right()->representation().IsDouble()); |
766 ASSERT(op != Token::MOD); | 759 LOperand* left = (op == Token::MOD) |
Sven Panne
2013/09/16 13:10:32
Refactor this into
if (op == Token::MOD) {
...
}
| |
767 LOperand* left = UseRegisterAtStart(instr->left()); | 760 ? UseFixedDouble(instr->left(), d1) |
768 LOperand* right = UseRegisterAtStart(instr->right()); | 761 : UseRegisterAtStart(instr->left()); |
762 LOperand* right = (op == Token::MOD) | |
763 ? UseFixedDouble(instr->right(), d2) | |
764 : UseRegisterAtStart(instr->right()); | |
769 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | 765 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
766 | |
767 // We call a C function for double modulo. It can't trigger a GC. We need | |
768 // to use fixed result register for the call. | |
769 // TODO(fschneider): Allow any register as input registers. | |
770 if (op == Token::MOD) return MarkAsCall(DefineFixedDouble(result, d1), instr); | |
770 return DefineAsRegister(result); | 771 return DefineAsRegister(result); |
771 } | 772 } |
772 | 773 |
773 | 774 |
774 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 775 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
775 HArithmeticBinaryOperation* instr) { | 776 HBinaryOperation* instr) { |
776 ASSERT(op == Token::ADD || | |
777 op == Token::DIV || | |
778 op == Token::MOD || | |
779 op == Token::MUL || | |
780 op == Token::SUB); | |
781 HValue* left = instr->left(); | 777 HValue* left = instr->left(); |
782 HValue* right = instr->right(); | 778 HValue* right = instr->right(); |
783 ASSERT(left->representation().IsTagged()); | 779 ASSERT(left->representation().IsTagged()); |
784 ASSERT(right->representation().IsTagged()); | 780 ASSERT(right->representation().IsTagged()); |
785 LOperand* left_operand = UseFixed(left, r1); | 781 LOperand* left_operand = UseFixed(left, r1); |
786 LOperand* right_operand = UseFixed(right, r0); | 782 LOperand* right_operand = UseFixed(right, r0); |
787 LArithmeticT* result = | 783 LArithmeticT* result = |
788 new(zone()) LArithmeticT(op, left_operand, right_operand); | 784 new(zone()) LArithmeticT(op, left_operand, right_operand); |
789 return MarkAsCall(DefineFixed(result, r0), instr); | 785 return MarkAsCall(DefineFixed(result, r0), instr); |
790 } | 786 } |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1340 | 1336 |
1341 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1337 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
1342 return DoShift(Token::SHL, instr); | 1338 return DoShift(Token::SHL, instr); |
1343 } | 1339 } |
1344 | 1340 |
1345 | 1341 |
1346 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1342 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
1347 if (instr->representation().IsSmiOrInteger32()) { | 1343 if (instr->representation().IsSmiOrInteger32()) { |
1348 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1344 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1349 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1345 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1346 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); | |
1350 | 1347 |
1351 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1348 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1352 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1349 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1353 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1350 return DefineAsRegister(new(zone()) LBitI(left, right)); |
1354 } else { | 1351 } else { |
1355 ASSERT(instr->representation().IsTagged()); | 1352 return DoArithmeticT(instr->op(), instr); |
1356 ASSERT(instr->left()->representation().IsTagged()); | |
1357 ASSERT(instr->right()->representation().IsTagged()); | |
1358 | |
1359 LOperand* left = UseFixed(instr->left(), r1); | |
1360 LOperand* right = UseFixed(instr->right(), r0); | |
1361 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); | |
1362 return MarkAsCall(DefineFixed(result, r0), instr); | |
1363 } | 1353 } |
1364 } | 1354 } |
1365 | 1355 |
1366 | 1356 |
1367 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1357 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1368 if (instr->representation().IsDouble()) { | 1358 if (instr->representation().IsSmiOrInteger32()) { |
1369 return DoArithmeticD(Token::DIV, instr); | |
1370 } else if (instr->representation().IsSmiOrInteger32()) { | |
1371 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1359 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1372 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1360 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1373 if (instr->HasPowerOf2Divisor()) { | 1361 if (instr->HasPowerOf2Divisor()) { |
1374 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1362 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
1375 LOperand* value = UseRegisterAtStart(instr->left()); | 1363 LOperand* value = UseRegisterAtStart(instr->left()); |
1376 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); | 1364 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); |
1377 return AssignEnvironment(DefineAsRegister(div)); | 1365 return AssignEnvironment(DefineAsRegister(div)); |
1378 } | 1366 } |
1379 LOperand* dividend = UseRegister(instr->left()); | 1367 LOperand* dividend = UseRegister(instr->left()); |
1380 LOperand* divisor = UseRegister(instr->right()); | 1368 LOperand* divisor = UseRegister(instr->right()); |
1381 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); | 1369 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
1382 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1370 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); |
1383 return AssignEnvironment(DefineAsRegister(div)); | 1371 return AssignEnvironment(DefineAsRegister(div)); |
1372 } else if (instr->representation().IsDouble()) { | |
1373 return DoArithmeticD(Token::DIV, instr); | |
1384 } else { | 1374 } else { |
1385 return DoArithmeticT(Token::DIV, instr); | 1375 return DoArithmeticT(Token::DIV, instr); |
1386 } | 1376 } |
1387 } | 1377 } |
1388 | 1378 |
1389 | 1379 |
1390 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { | 1380 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { |
1391 uint32_t divisor_abs = abs(divisor); | 1381 uint32_t divisor_abs = abs(divisor); |
1392 // Dividing by 0, 1, and powers of 2 is easy. | 1382 // Dividing by 0, 1, and powers of 2 is easy. |
1393 // Note that IsPowerOf2(0) returns true; | 1383 // Note that IsPowerOf2(0) returns true; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1494 FixedTemp(d10), | 1484 FixedTemp(d10), |
1495 FixedTemp(d11)); | 1485 FixedTemp(d11)); |
1496 LInstruction* result = DefineAsRegister(mod); | 1486 LInstruction* result = DefineAsRegister(mod); |
1497 return (right->CanBeZero() || | 1487 return (right->CanBeZero() || |
1498 (left->CanBeNegative() && | 1488 (left->CanBeNegative() && |
1499 instr->CanBeZero() && | 1489 instr->CanBeZero() && |
1500 instr->CheckFlag(HValue::kBailoutOnMinusZero))) | 1490 instr->CheckFlag(HValue::kBailoutOnMinusZero))) |
1501 ? AssignEnvironment(result) | 1491 ? AssignEnvironment(result) |
1502 : result; | 1492 : result; |
1503 } | 1493 } |
1504 } else if (instr->representation().IsTagged()) { | 1494 } else if (instr->representation().IsDouble()) { |
1495 return DoArithmeticD(Token::MOD, instr); | |
1496 } else { | |
1505 return DoArithmeticT(Token::MOD, instr); | 1497 return DoArithmeticT(Token::MOD, instr); |
1506 } else { | |
1507 ASSERT(instr->representation().IsDouble()); | |
1508 // We call a C function for double modulo. It can't trigger a GC. We need | |
1509 // to use fixed result register for the call. | |
1510 // TODO(fschneider): Allow any register as input registers. | |
1511 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, | |
1512 UseFixedDouble(left, d1), | |
1513 UseFixedDouble(right, d2)); | |
1514 return MarkAsCall(DefineFixedDouble(mod, d1), instr); | |
1515 } | 1498 } |
1516 } | 1499 } |
1517 | 1500 |
1518 | 1501 |
1519 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1502 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
1520 if (instr->representation().IsSmiOrInteger32()) { | 1503 if (instr->representation().IsSmiOrInteger32()) { |
1521 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1504 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1522 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1505 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1523 HValue* left = instr->BetterLeftOperand(); | 1506 HValue* left = instr->BetterLeftOperand(); |
1524 HValue* right = instr->BetterRightOperand(); | 1507 HValue* right = instr->BetterRightOperand(); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1671 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); | 1654 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); |
1672 } | 1655 } |
1673 | 1656 |
1674 if (instr->right()->IsMul()) { | 1657 if (instr->right()->IsMul()) { |
1675 ASSERT(!instr->left()->IsMul()); | 1658 ASSERT(!instr->left()->IsMul()); |
1676 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); | 1659 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); |
1677 } | 1660 } |
1678 | 1661 |
1679 return DoArithmeticD(Token::ADD, instr); | 1662 return DoArithmeticD(Token::ADD, instr); |
1680 } else { | 1663 } else { |
1681 ASSERT(instr->representation().IsTagged()); | |
1682 return DoArithmeticT(Token::ADD, instr); | 1664 return DoArithmeticT(Token::ADD, instr); |
1683 } | 1665 } |
1684 } | 1666 } |
1685 | 1667 |
1686 | 1668 |
1687 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1669 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
1688 LOperand* left = NULL; | 1670 LOperand* left = NULL; |
1689 LOperand* right = NULL; | 1671 LOperand* right = NULL; |
1690 if (instr->representation().IsSmiOrInteger32()) { | 1672 if (instr->representation().IsSmiOrInteger32()) { |
1691 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1673 ASSERT(instr->left()->representation().Equals(instr->representation())); |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2621 | 2603 |
2622 | 2604 |
2623 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2605 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2624 LOperand* object = UseRegister(instr->object()); | 2606 LOperand* object = UseRegister(instr->object()); |
2625 LOperand* index = UseRegister(instr->index()); | 2607 LOperand* index = UseRegister(instr->index()); |
2626 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2608 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
2627 } | 2609 } |
2628 | 2610 |
2629 | 2611 |
2630 } } // namespace v8::internal | 2612 } } // namespace v8::internal |
OLD | NEW |