| 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) |
| 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 = | 1364 LDivI* div = |
| 1377 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); | 1365 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); |
| 1378 return AssignEnvironment(DefineSameAsFirst(div)); | 1366 return AssignEnvironment(DefineSameAsFirst(div)); |
| 1379 } | 1367 } |
| 1380 LOperand* dividend = UseRegister(instr->left()); | 1368 LOperand* dividend = UseRegister(instr->left()); |
| 1381 LOperand* divisor = UseRegister(instr->right()); | 1369 LOperand* divisor = UseRegister(instr->right()); |
| 1382 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); | 1370 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
| 1383 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1371 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); |
| 1384 return AssignEnvironment(DefineAsRegister(div)); | 1372 return AssignEnvironment(DefineAsRegister(div)); |
| 1373 } else if (instr->representation().IsDouble()) { |
| 1374 return DoArithmeticD(Token::DIV, instr); |
| 1385 } else { | 1375 } else { |
| 1386 return DoArithmeticT(Token::DIV, instr); | 1376 return DoArithmeticT(Token::DIV, instr); |
| 1387 } | 1377 } |
| 1388 } | 1378 } |
| 1389 | 1379 |
| 1390 | 1380 |
| 1391 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { | 1381 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { |
| 1392 uint32_t divisor_abs = abs(divisor); | 1382 uint32_t divisor_abs = abs(divisor); |
| 1393 // Dividing by 0, 1, and powers of 2 is easy. | 1383 // Dividing by 0, 1, and powers of 2 is easy. |
| 1394 // Note that IsPowerOf2(0) returns true; | 1384 // Note that IsPowerOf2(0) returns true; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 FixedTemp(d10), | 1485 FixedTemp(d10), |
| 1496 FixedTemp(d11)); | 1486 FixedTemp(d11)); |
| 1497 LInstruction* result = DefineAsRegister(mod); | 1487 LInstruction* result = DefineAsRegister(mod); |
| 1498 return (right->CanBeZero() || | 1488 return (right->CanBeZero() || |
| 1499 (left->CanBeNegative() && | 1489 (left->CanBeNegative() && |
| 1500 instr->CanBeZero() && | 1490 instr->CanBeZero() && |
| 1501 instr->CheckFlag(HValue::kBailoutOnMinusZero))) | 1491 instr->CheckFlag(HValue::kBailoutOnMinusZero))) |
| 1502 ? AssignEnvironment(result) | 1492 ? AssignEnvironment(result) |
| 1503 : result; | 1493 : result; |
| 1504 } | 1494 } |
| 1505 } else if (instr->representation().IsTagged()) { | 1495 } else if (instr->representation().IsDouble()) { |
| 1496 return DoArithmeticD(Token::MOD, instr); |
| 1497 } else { |
| 1506 return DoArithmeticT(Token::MOD, instr); | 1498 return DoArithmeticT(Token::MOD, instr); |
| 1507 } else { | |
| 1508 ASSERT(instr->representation().IsDouble()); | |
| 1509 // We call a C function for double modulo. It can't trigger a GC. We need | |
| 1510 // to use fixed result register for the call. | |
| 1511 // TODO(fschneider): Allow any register as input registers. | |
| 1512 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, | |
| 1513 UseFixedDouble(left, d1), | |
| 1514 UseFixedDouble(right, d2)); | |
| 1515 return MarkAsCall(DefineFixedDouble(mod, d1), instr); | |
| 1516 } | 1499 } |
| 1517 } | 1500 } |
| 1518 | 1501 |
| 1519 | 1502 |
| 1520 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1503 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1521 if (instr->representation().IsSmiOrInteger32()) { | 1504 if (instr->representation().IsSmiOrInteger32()) { |
| 1522 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1505 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1523 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1506 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1524 HValue* left = instr->BetterLeftOperand(); | 1507 HValue* left = instr->BetterLeftOperand(); |
| 1525 HValue* right = instr->BetterRightOperand(); | 1508 HValue* right = instr->BetterRightOperand(); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1672 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); | 1655 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); |
| 1673 } | 1656 } |
| 1674 | 1657 |
| 1675 if (instr->right()->IsMul()) { | 1658 if (instr->right()->IsMul()) { |
| 1676 ASSERT(!instr->left()->IsMul()); | 1659 ASSERT(!instr->left()->IsMul()); |
| 1677 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); | 1660 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); |
| 1678 } | 1661 } |
| 1679 | 1662 |
| 1680 return DoArithmeticD(Token::ADD, instr); | 1663 return DoArithmeticD(Token::ADD, instr); |
| 1681 } else { | 1664 } else { |
| 1682 ASSERT(instr->representation().IsTagged()); | |
| 1683 return DoArithmeticT(Token::ADD, instr); | 1665 return DoArithmeticT(Token::ADD, instr); |
| 1684 } | 1666 } |
| 1685 } | 1667 } |
| 1686 | 1668 |
| 1687 | 1669 |
| 1688 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1670 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1689 LOperand* left = NULL; | 1671 LOperand* left = NULL; |
| 1690 LOperand* right = NULL; | 1672 LOperand* right = NULL; |
| 1691 if (instr->representation().IsSmiOrInteger32()) { | 1673 if (instr->representation().IsSmiOrInteger32()) { |
| 1692 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1674 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| (...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2624 | 2606 |
| 2625 | 2607 |
| 2626 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2608 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2627 LOperand* object = UseRegister(instr->object()); | 2609 LOperand* object = UseRegister(instr->object()); |
| 2628 LOperand* index = UseRegister(instr->index()); | 2610 LOperand* index = UseRegister(instr->index()); |
| 2629 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2611 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
| 2630 } | 2612 } |
| 2631 | 2613 |
| 2632 | 2614 |
| 2633 } } // namespace v8::internal | 2615 } } // namespace v8::internal |
| OLD | NEW |