OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 codegen_->RecordSafepoint(pointers_, deopt_mode_); | 57 codegen_->RecordSafepoint(pointers_, deopt_mode_); |
58 } | 58 } |
59 | 59 |
60 private: | 60 private: |
61 LCodeGen* codegen_; | 61 LCodeGen* codegen_; |
62 LPointerMap* pointers_; | 62 LPointerMap* pointers_; |
63 Safepoint::DeoptMode deopt_mode_; | 63 Safepoint::DeoptMode deopt_mode_; |
64 }; | 64 }; |
65 | 65 |
66 | 66 |
| 67 class LithiumSmiInstructionWrapper |
| 68 : public MacroAssembler::SmiInstructionWrapper { |
| 69 public: |
| 70 LithiumSmiInstructionWrapper(LCodeGen* codegen, |
| 71 LEnvironment* environment, |
| 72 bool check_overflow = false, |
| 73 bool check_minus_zero = false) |
| 74 : codegen_(codegen), |
| 75 environment_(environment), |
| 76 check_overflow_(check_overflow), |
| 77 check_minus_zero_(check_minus_zero) { } |
| 78 virtual ~LithiumSmiInstructionWrapper() { } |
| 79 virtual bool NeedsCheckOverflow() const { return check_overflow_; } |
| 80 virtual bool NeedsCheckMinusZero() const { return check_minus_zero_; } |
| 81 virtual bool NeedsKeepSourceOperandsIntact() const { return false; } |
| 82 virtual void BailoutIf(Condition cc) const { |
| 83 codegen_->DeoptimizeIf(cc, environment_); |
| 84 } |
| 85 |
| 86 private: |
| 87 LCodeGen* codegen_; |
| 88 LEnvironment* environment_; |
| 89 bool check_overflow_; |
| 90 bool check_minus_zero_; |
| 91 }; |
| 92 |
| 93 |
67 #define __ masm()-> | 94 #define __ masm()-> |
68 | 95 |
69 bool LCodeGen::GenerateCode() { | 96 bool LCodeGen::GenerateCode() { |
70 LPhase phase("Z_Code generation", chunk()); | 97 LPhase phase("Z_Code generation", chunk()); |
71 ASSERT(is_unused()); | 98 ASSERT(is_unused()); |
72 status_ = GENERATING; | 99 status_ = GENERATING; |
73 | 100 |
74 // Open a frame scope to indicate that there is a frame on the stack. The | 101 // Open a frame scope to indicate that there is a frame on the stack. The |
75 // MANUAL indicates that the scope shouldn't actually generate code to set up | 102 // MANUAL indicates that the scope shouldn't actually generate code to set up |
76 // the frame (that is done in GeneratePrologue). | 103 // the frame (that is done in GeneratePrologue). |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 } | 436 } |
410 | 437 |
411 | 438 |
412 bool LCodeGen::IsTaggedConstant(LConstantOperand* op) const { | 439 bool LCodeGen::IsTaggedConstant(LConstantOperand* op) const { |
413 return op->IsConstantOperand() && | 440 return op->IsConstantOperand() && |
414 chunk_->LookupLiteralRepresentation(op).IsTagged(); | 441 chunk_->LookupLiteralRepresentation(op).IsTagged(); |
415 } | 442 } |
416 | 443 |
417 | 444 |
418 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { | 445 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
419 HConstant* constant = chunk_->LookupConstant(op); | 446 return ToRepresentation(op, Representation::Integer32()); |
420 return constant->Integer32Value(); | |
421 } | 447 } |
422 | 448 |
423 | 449 |
| 450 int32_t LCodeGen::ToRepresentation(LConstantOperand* op, |
| 451 const Representation& r) const { |
| 452 HConstant* constant = chunk_->LookupConstant(op); |
| 453 int32_t value = constant->Integer32Value(); |
| 454 if (r.IsInteger32()) return value; |
| 455 ASSERT(r.IsSmiOrTagged()); |
| 456 return static_cast<int32_t>(reinterpret_cast<intptr_t>(Smi::FromInt(value))); |
| 457 } |
| 458 |
| 459 |
424 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { | 460 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { |
425 HConstant* constant = chunk_->LookupConstant(op); | 461 HConstant* constant = chunk_->LookupConstant(op); |
426 return Smi::FromInt(constant->Integer32Value()); | 462 return Smi::FromInt(constant->Integer32Value()); |
427 } | 463 } |
428 | 464 |
429 | 465 |
430 double LCodeGen::ToDouble(LConstantOperand* op) const { | 466 double LCodeGen::ToDouble(LConstantOperand* op) const { |
431 HConstant* constant = chunk_->LookupConstant(op); | 467 HConstant* constant = chunk_->LookupConstant(op); |
432 ASSERT(constant->HasDoubleValue()); | 468 ASSERT(constant->HasDoubleValue()); |
433 return constant->DoubleValue(); | 469 return constant->DoubleValue(); |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 } | 1391 } |
1356 | 1392 |
1357 | 1393 |
1358 void LCodeGen::DoBitI(LBitI* instr) { | 1394 void LCodeGen::DoBitI(LBitI* instr) { |
1359 LOperand* left = instr->left(); | 1395 LOperand* left = instr->left(); |
1360 LOperand* right = instr->right(); | 1396 LOperand* right = instr->right(); |
1361 ASSERT(left->Equals(instr->result())); | 1397 ASSERT(left->Equals(instr->result())); |
1362 ASSERT(left->IsRegister()); | 1398 ASSERT(left->IsRegister()); |
1363 | 1399 |
1364 if (right->IsConstantOperand()) { | 1400 if (right->IsConstantOperand()) { |
1365 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 1401 int32_t right_value = ToInteger32(LConstantOperand::cast(right)); |
1366 switch (instr->op()) { | 1402 switch (instr->op()) { |
1367 case Token::BIT_AND: | 1403 case Token::BIT_AND: |
1368 __ andl(ToRegister(left), Immediate(right_operand)); | 1404 if (instr->hydrogen()->representation().IsSmi()) { |
| 1405 __ SmiAndConstant(ToRegister(left), ToRegister(left), |
| 1406 Smi::FromInt(right_value)); |
| 1407 } else { |
| 1408 __ andl(ToRegister(left), Immediate(right_value)); |
| 1409 } |
1369 break; | 1410 break; |
1370 case Token::BIT_OR: | 1411 case Token::BIT_OR: |
1371 __ orl(ToRegister(left), Immediate(right_operand)); | 1412 if (instr->hydrogen()->representation().IsSmi()) { |
| 1413 __ SmiOrConstant(ToRegister(left), ToRegister(left), |
| 1414 Smi::FromInt(right_value)); |
| 1415 } else { |
| 1416 __ orl(ToRegister(left), Immediate(right_value)); |
| 1417 } |
1372 break; | 1418 break; |
1373 case Token::BIT_XOR: | 1419 case Token::BIT_XOR: |
1374 __ xorl(ToRegister(left), Immediate(right_operand)); | 1420 if (instr->hydrogen()->representation().IsSmi()) { |
| 1421 __ SmiXorConstant(ToRegister(left), ToRegister(left), |
| 1422 Smi::FromInt(right_value)); |
| 1423 } else { |
| 1424 __ xorl(ToRegister(left), Immediate(right_value)); |
| 1425 } |
1375 break; | 1426 break; |
1376 default: | 1427 default: |
1377 UNREACHABLE(); | 1428 UNREACHABLE(); |
1378 break; | 1429 break; |
1379 } | 1430 } |
1380 } else if (right->IsStackSlot()) { | 1431 } else if (right->IsStackSlot()) { |
1381 switch (instr->op()) { | 1432 switch (instr->op()) { |
1382 case Token::BIT_AND: | 1433 case Token::BIT_AND: |
1383 __ and_(ToRegister(left), ToOperand(right)); | 1434 __ and_(ToRegister(left), ToOperand(right)); |
1384 break; | 1435 break; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1459 if (shift_count == 0 && instr->can_deopt()) { | 1510 if (shift_count == 0 && instr->can_deopt()) { |
1460 __ testl(ToRegister(left), ToRegister(left)); | 1511 __ testl(ToRegister(left), ToRegister(left)); |
1461 DeoptimizeIf(negative, instr->environment()); | 1512 DeoptimizeIf(negative, instr->environment()); |
1462 } else { | 1513 } else { |
1463 __ shrl(ToRegister(left), Immediate(shift_count)); | 1514 __ shrl(ToRegister(left), Immediate(shift_count)); |
1464 } | 1515 } |
1465 break; | 1516 break; |
1466 case Token::SHL: | 1517 case Token::SHL: |
1467 if (shift_count != 0) { | 1518 if (shift_count != 0) { |
1468 if (instr->hydrogen_value()->representation().IsSmi()) { | 1519 if (instr->hydrogen_value()->representation().IsSmi()) { |
1469 __ shl(ToRegister(left), Immediate(shift_count)); | 1520 if (SmiValuesAre32Bits() || !instr->can_deopt()) { |
| 1521 __ shl(ToRegister(left), Immediate(shift_count)); |
| 1522 } else { |
| 1523 ASSERT(SmiValuesAre31Bits() && instr->can_deopt()); |
| 1524 LithiumSmiInstructionWrapper wrapper(this, instr->environment()); |
| 1525 __ SmiShiftLeftConstant(ToRegister(left), ToRegister(left), |
| 1526 shift_count, wrapper); |
| 1527 } |
1470 } else { | 1528 } else { |
1471 __ shll(ToRegister(left), Immediate(shift_count)); | 1529 __ shll(ToRegister(left), Immediate(shift_count)); |
1472 } | 1530 } |
1473 } | 1531 } |
1474 break; | 1532 break; |
1475 default: | 1533 default: |
1476 UNREACHABLE(); | 1534 UNREACHABLE(); |
1477 break; | 1535 break; |
1478 } | 1536 } |
1479 } | 1537 } |
1480 } | 1538 } |
1481 | 1539 |
1482 | 1540 |
1483 void LCodeGen::DoSubI(LSubI* instr) { | 1541 void LCodeGen::DoSubI(LSubI* instr) { |
1484 LOperand* left = instr->left(); | 1542 LOperand* left = instr->left(); |
1485 LOperand* right = instr->right(); | 1543 LOperand* right = instr->right(); |
1486 ASSERT(left->Equals(instr->result())); | 1544 ASSERT(left->Equals(instr->result())); |
1487 | 1545 |
| 1546 bool check_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1547 LithiumSmiInstructionWrapper wrapper(this, instr->environment(), |
| 1548 check_overflow); |
1488 if (right->IsConstantOperand()) { | 1549 if (right->IsConstantOperand()) { |
1489 __ subl(ToRegister(left), | 1550 int32_t right_value = ToInteger32(LConstantOperand::cast(right)); |
1490 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1551 if (instr->hydrogen()->representation().IsSmi()) { |
| 1552 __ SmiSubConstant(ToRegister(left), ToRegister(left), |
| 1553 Smi::FromInt(right_value), wrapper); |
| 1554 } else { |
| 1555 __ subl(ToRegister(left), Immediate(right_value)); |
| 1556 } |
1491 } else if (right->IsRegister()) { | 1557 } else if (right->IsRegister()) { |
1492 if (instr->hydrogen_value()->representation().IsSmi()) { | 1558 if (instr->hydrogen_value()->representation().IsSmi()) { |
1493 __ subq(ToRegister(left), ToRegister(right)); | 1559 __ SmiSub(ToRegister(left), ToRegister(left), ToRegister(right), wrapper); |
1494 } else { | 1560 } else { |
1495 __ subl(ToRegister(left), ToRegister(right)); | 1561 __ subl(ToRegister(left), ToRegister(right)); |
1496 } | 1562 } |
1497 } else { | 1563 } else { |
1498 if (instr->hydrogen_value()->representation().IsSmi()) { | 1564 if (instr->hydrogen_value()->representation().IsSmi()) { |
1499 __ subq(ToRegister(left), ToOperand(right)); | 1565 __ SmiSub(ToRegister(left), ToRegister(left), ToOperand(right), wrapper); |
1500 } else { | 1566 } else { |
1501 __ subl(ToRegister(left), ToOperand(right)); | 1567 __ subl(ToRegister(left), ToOperand(right)); |
1502 } | 1568 } |
1503 } | 1569 } |
1504 | 1570 |
1505 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1571 if (instr->hydrogen_value()->representation().IsInteger32() && |
| 1572 check_overflow) { |
1506 DeoptimizeIf(overflow, instr->environment()); | 1573 DeoptimizeIf(overflow, instr->environment()); |
1507 } | 1574 } |
1508 } | 1575 } |
1509 | 1576 |
1510 | 1577 |
1511 void LCodeGen::DoConstantI(LConstantI* instr) { | 1578 void LCodeGen::DoConstantI(LConstantI* instr) { |
1512 __ Set(ToRegister(instr->result()), instr->value()); | 1579 __ Set(ToRegister(instr->result()), instr->value()); |
1513 } | 1580 } |
1514 | 1581 |
1515 | 1582 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1673 } | 1740 } |
1674 } | 1741 } |
1675 | 1742 |
1676 | 1743 |
1677 void LCodeGen::DoAddI(LAddI* instr) { | 1744 void LCodeGen::DoAddI(LAddI* instr) { |
1678 LOperand* left = instr->left(); | 1745 LOperand* left = instr->left(); |
1679 LOperand* right = instr->right(); | 1746 LOperand* right = instr->right(); |
1680 | 1747 |
1681 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 1748 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
1682 if (right->IsConstantOperand()) { | 1749 if (right->IsConstantOperand()) { |
1683 int32_t offset = ToInteger32(LConstantOperand::cast(right)); | 1750 int32_t offset = ToRepresentation(LConstantOperand::cast(right), |
1684 __ leal(ToRegister(instr->result()), | 1751 instr->hydrogen()->representation()); |
1685 MemOperand(ToRegister(left), offset)); | 1752 if (instr->hydrogen()->representation().IsSmi()) { |
| 1753 __ lea(ToRegister(instr->result()), |
| 1754 MemOperand(ToRegister(left), offset)); |
| 1755 } else { |
| 1756 __ leal(ToRegister(instr->result()), |
| 1757 MemOperand(ToRegister(left), offset)); |
| 1758 } |
1686 } else { | 1759 } else { |
1687 Operand address(ToRegister(left), ToRegister(right), times_1, 0); | 1760 Operand address(ToRegister(left), ToRegister(right), times_1, 0); |
1688 if (instr->hydrogen()->representation().IsSmi()) { | 1761 if (instr->hydrogen()->representation().IsSmi()) { |
1689 __ lea(ToRegister(instr->result()), address); | 1762 __ lea(ToRegister(instr->result()), address); |
1690 } else { | 1763 } else { |
1691 __ leal(ToRegister(instr->result()), address); | 1764 __ leal(ToRegister(instr->result()), address); |
1692 } | 1765 } |
1693 } | 1766 } |
1694 } else { | 1767 } else { |
| 1768 bool check_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1769 LithiumSmiInstructionWrapper wrapper(this, instr->environment(), |
| 1770 check_overflow); |
1695 if (right->IsConstantOperand()) { | 1771 if (right->IsConstantOperand()) { |
1696 __ addl(ToRegister(left), | 1772 int32_t right_value = ToInteger32(LConstantOperand::cast(right)); |
1697 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1773 if (instr->hydrogen()->representation().IsSmi()) { |
| 1774 __ SmiAddConstant(ToRegister(left), ToRegister(left), |
| 1775 Smi::FromInt(right_value), wrapper); |
| 1776 } else { |
| 1777 __ addl(ToRegister(left), Immediate(right_value)); |
| 1778 } |
1698 } else if (right->IsRegister()) { | 1779 } else if (right->IsRegister()) { |
1699 if (instr->hydrogen_value()->representation().IsSmi()) { | 1780 if (instr->hydrogen_value()->representation().IsSmi()) { |
1700 __ addq(ToRegister(left), ToRegister(right)); | 1781 __ SmiAdd(ToRegister(left), ToRegister(left), ToRegister(right), |
| 1782 wrapper); |
1701 } else { | 1783 } else { |
1702 __ addl(ToRegister(left), ToRegister(right)); | 1784 __ addl(ToRegister(left), ToRegister(right)); |
1703 } | 1785 } |
1704 } else { | 1786 } else { |
1705 if (instr->hydrogen_value()->representation().IsSmi()) { | 1787 if (instr->hydrogen_value()->representation().IsSmi()) { |
1706 __ addq(ToRegister(left), ToOperand(right)); | 1788 __ SmiAdd(ToRegister(left), ToRegister(left), ToOperand(right), |
| 1789 wrapper); |
1707 } else { | 1790 } else { |
1708 __ addl(ToRegister(left), ToOperand(right)); | 1791 __ addl(ToRegister(left), ToOperand(right)); |
1709 } | 1792 } |
1710 } | 1793 } |
1711 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1794 |
| 1795 if (instr->hydrogen_value()->representation().IsInteger32() && |
| 1796 check_overflow) { |
1712 DeoptimizeIf(overflow, instr->environment()); | 1797 DeoptimizeIf(overflow, instr->environment()); |
1713 } | 1798 } |
1714 } | 1799 } |
1715 } | 1800 } |
1716 | 1801 |
1717 | 1802 |
1718 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1803 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1719 LOperand* left = instr->left(); | 1804 LOperand* left = instr->left(); |
1720 LOperand* right = instr->right(); | 1805 LOperand* right = instr->right(); |
1721 ASSERT(left->Equals(instr->result())); | 1806 ASSERT(left->Equals(instr->result())); |
1722 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1807 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
1723 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { | 1808 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
1724 Label return_left; | 1809 Label return_left; |
1725 Condition condition = (operation == HMathMinMax::kMathMin) | 1810 Condition condition = (operation == HMathMinMax::kMathMin) |
1726 ? less_equal | 1811 ? less_equal |
1727 : greater_equal; | 1812 : greater_equal; |
1728 Register left_reg = ToRegister(left); | 1813 Register left_reg = ToRegister(left); |
1729 if (right->IsConstantOperand()) { | 1814 if (right->IsConstantOperand()) { |
1730 Immediate right_imm = | 1815 Immediate right_imm = |
1731 Immediate(ToInteger32(LConstantOperand::cast(right))); | 1816 Immediate(ToRepresentation(LConstantOperand::cast(right), |
1732 ASSERT(!instr->hydrogen_value()->representation().IsSmi()); | 1817 instr->hydrogen()->representation())); |
1733 __ cmpl(left_reg, right_imm); | 1818 __ cmpl(left_reg, right_imm); |
1734 __ j(condition, &return_left, Label::kNear); | 1819 __ j(condition, &return_left, Label::kNear); |
1735 __ movq(left_reg, right_imm); | 1820 __ movq(left_reg, right_imm); |
1736 } else if (right->IsRegister()) { | 1821 } else if (right->IsRegister()) { |
1737 Register right_reg = ToRegister(right); | 1822 Register right_reg = ToRegister(right); |
1738 if (instr->hydrogen_value()->representation().IsSmi()) { | 1823 if (instr->hydrogen_value()->representation().IsSmi()) { |
1739 __ cmpq(left_reg, right_reg); | 1824 __ cmpq(left_reg, right_reg); |
1740 } else { | 1825 } else { |
1741 __ cmpl(left_reg, right_reg); | 1826 __ cmpl(left_reg, right_reg); |
1742 } | 1827 } |
(...skipping 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2920 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 3005 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
2921 ElementsKind elements_kind = instr->elements_kind(); | 3006 ElementsKind elements_kind = instr->elements_kind(); |
2922 LOperand* key = instr->key(); | 3007 LOperand* key = instr->key(); |
2923 if (!key->IsConstantOperand()) { | 3008 if (!key->IsConstantOperand()) { |
2924 Register key_reg = ToRegister(key); | 3009 Register key_reg = ToRegister(key); |
2925 // Even though the HLoad/StoreKeyed (in this case) instructions force | 3010 // Even though the HLoad/StoreKeyed (in this case) instructions force |
2926 // the input representation for the key to be an integer, the input | 3011 // the input representation for the key to be an integer, the input |
2927 // gets replaced during bound check elimination with the index argument | 3012 // gets replaced during bound check elimination with the index argument |
2928 // to the bounds check, which can be tagged, so that case must be | 3013 // to the bounds check, which can be tagged, so that case must be |
2929 // handled here, too. | 3014 // handled here, too. |
2930 if (instr->hydrogen()->IsDehoisted()) { | 3015 if (instr->hydrogen()->key()->representation().IsSmi()) { |
| 3016 ASSERT(SmiValuesAre31Bits()); |
| 3017 __ SmiToInteger64(key_reg, key_reg); |
| 3018 } else if (instr->hydrogen()->IsDehoisted()) { |
2931 // Sign extend key because it could be a 32 bit negative value | 3019 // Sign extend key because it could be a 32 bit negative value |
2932 // and the dehoisted address computation happens in 64 bits | 3020 // and the dehoisted address computation happens in 64 bits |
2933 __ movsxlq(key_reg, key_reg); | 3021 __ movsxlq(key_reg, key_reg); |
2934 } | 3022 } |
2935 } | 3023 } |
2936 Operand operand(BuildFastArrayOperand( | 3024 Operand operand(BuildFastArrayOperand( |
2937 instr->elements(), | 3025 instr->elements(), |
2938 key, | 3026 key, |
2939 elements_kind, | 3027 elements_kind, |
2940 0, | 3028 0, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2991 | 3079 |
2992 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { | 3080 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
2993 XMMRegister result(ToDoubleRegister(instr->result())); | 3081 XMMRegister result(ToDoubleRegister(instr->result())); |
2994 LOperand* key = instr->key(); | 3082 LOperand* key = instr->key(); |
2995 if (!key->IsConstantOperand()) { | 3083 if (!key->IsConstantOperand()) { |
2996 Register key_reg = ToRegister(key); | 3084 Register key_reg = ToRegister(key); |
2997 // Even though the HLoad/StoreKeyed instructions force the input | 3085 // Even though the HLoad/StoreKeyed instructions force the input |
2998 // representation for the key to be an integer, the input gets replaced | 3086 // representation for the key to be an integer, the input gets replaced |
2999 // during bound check elimination with the index argument to the bounds | 3087 // during bound check elimination with the index argument to the bounds |
3000 // check, which can be tagged, so that case must be handled here, too. | 3088 // check, which can be tagged, so that case must be handled here, too. |
3001 if (instr->hydrogen()->IsDehoisted()) { | 3089 if (instr->hydrogen()->key()->representation().IsSmi()) { |
| 3090 ASSERT(SmiValuesAre31Bits()); |
| 3091 __ SmiToInteger64(key_reg, key_reg); |
| 3092 } else if (instr->hydrogen()->IsDehoisted()) { |
3002 // Sign extend key because it could be a 32 bit negative value | 3093 // Sign extend key because it could be a 32 bit negative value |
3003 // and the dehoisted address computation happens in 64 bits | 3094 // and the dehoisted address computation happens in 64 bits |
3004 __ movsxlq(key_reg, key_reg); | 3095 __ movsxlq(key_reg, key_reg); |
3005 } | 3096 } |
3006 } | 3097 } |
3007 | 3098 |
3008 if (instr->hydrogen()->RequiresHoleCheck()) { | 3099 if (instr->hydrogen()->RequiresHoleCheck()) { |
3009 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | 3100 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
3010 sizeof(kHoleNanLower32); | 3101 sizeof(kHoleNanLower32); |
3011 Operand hole_check_operand = BuildFastArrayOperand( | 3102 Operand hole_check_operand = BuildFastArrayOperand( |
(...skipping 19 matching lines...) Expand all Loading... |
3031 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3122 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
3032 Register result = ToRegister(instr->result()); | 3123 Register result = ToRegister(instr->result()); |
3033 LOperand* key = instr->key(); | 3124 LOperand* key = instr->key(); |
3034 if (!key->IsConstantOperand()) { | 3125 if (!key->IsConstantOperand()) { |
3035 Register key_reg = ToRegister(key); | 3126 Register key_reg = ToRegister(key); |
3036 // Even though the HLoad/StoreKeyedFastElement instructions force | 3127 // Even though the HLoad/StoreKeyedFastElement instructions force |
3037 // the input representation for the key to be an integer, the input | 3128 // the input representation for the key to be an integer, the input |
3038 // gets replaced during bound check elimination with the index | 3129 // gets replaced during bound check elimination with the index |
3039 // argument to the bounds check, which can be tagged, so that | 3130 // argument to the bounds check, which can be tagged, so that |
3040 // case must be handled here, too. | 3131 // case must be handled here, too. |
3041 if (instr->hydrogen()->IsDehoisted()) { | 3132 if (instr->hydrogen()->key()->representation().IsSmi()) { |
| 3133 ASSERT(SmiValuesAre31Bits()); |
| 3134 __ SmiToInteger64(key_reg, key_reg); |
| 3135 } else if (instr->hydrogen()->IsDehoisted()) { |
3042 // Sign extend key because it could be a 32 bit negative value | 3136 // Sign extend key because it could be a 32 bit negative value |
3043 // and the dehoisted address computation happens in 64 bits | 3137 // and the dehoisted address computation happens in 64 bits |
3044 __ movsxlq(key_reg, key_reg); | 3138 __ movsxlq(key_reg, key_reg); |
3045 } | 3139 } |
3046 } | 3140 } |
3047 | 3141 |
3048 // Load the result. | 3142 // Load the result. |
3049 __ movq(result, | 3143 __ movq(result, |
3050 BuildFastArrayOperand(instr->elements(), | 3144 BuildFastArrayOperand(instr->elements(), |
3051 key, | 3145 key, |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3419 Register input_reg = ToRegister(instr->value()); | 3513 Register input_reg = ToRegister(instr->value()); |
3420 __ testl(input_reg, input_reg); | 3514 __ testl(input_reg, input_reg); |
3421 Label is_positive; | 3515 Label is_positive; |
3422 __ j(not_sign, &is_positive, Label::kNear); | 3516 __ j(not_sign, &is_positive, Label::kNear); |
3423 __ negl(input_reg); // Sets flags. | 3517 __ negl(input_reg); // Sets flags. |
3424 DeoptimizeIf(negative, instr->environment()); | 3518 DeoptimizeIf(negative, instr->environment()); |
3425 __ bind(&is_positive); | 3519 __ bind(&is_positive); |
3426 } | 3520 } |
3427 | 3521 |
3428 | 3522 |
3429 void LCodeGen::EmitInteger64MathAbs(LMathAbs* instr) { | 3523 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { |
3430 Register input_reg = ToRegister(instr->value()); | 3524 Register input_reg = ToRegister(instr->value()); |
3431 __ testq(input_reg, input_reg); | 3525 __ testq(input_reg, input_reg); |
3432 Label is_positive; | 3526 Label is_positive; |
3433 __ j(not_sign, &is_positive, Label::kNear); | 3527 __ j(not_sign, &is_positive, Label::kNear); |
3434 __ neg(input_reg); // Sets flags. | 3528 if (SmiValuesAre32Bits()) { |
| 3529 __ neg(input_reg); // Sets flags. |
| 3530 } else { |
| 3531 ASSERT(SmiValuesAre31Bits()); |
| 3532 __ negl(input_reg); // Sets flags. |
| 3533 } |
3435 DeoptimizeIf(negative, instr->environment()); | 3534 DeoptimizeIf(negative, instr->environment()); |
3436 __ bind(&is_positive); | 3535 __ bind(&is_positive); |
3437 } | 3536 } |
3438 | 3537 |
3439 | 3538 |
3440 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3539 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
3441 // Class for deferred case. | 3540 // Class for deferred case. |
3442 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3541 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3443 public: | 3542 public: |
3444 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3543 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
(...skipping 11 matching lines...) Expand all Loading... |
3456 | 3555 |
3457 if (r.IsDouble()) { | 3556 if (r.IsDouble()) { |
3458 XMMRegister scratch = xmm0; | 3557 XMMRegister scratch = xmm0; |
3459 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3558 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3460 __ xorps(scratch, scratch); | 3559 __ xorps(scratch, scratch); |
3461 __ subsd(scratch, input_reg); | 3560 __ subsd(scratch, input_reg); |
3462 __ andpd(input_reg, scratch); | 3561 __ andpd(input_reg, scratch); |
3463 } else if (r.IsInteger32()) { | 3562 } else if (r.IsInteger32()) { |
3464 EmitIntegerMathAbs(instr); | 3563 EmitIntegerMathAbs(instr); |
3465 } else if (r.IsSmi()) { | 3564 } else if (r.IsSmi()) { |
3466 EmitInteger64MathAbs(instr); | 3565 EmitSmiMathAbs(instr); |
3467 } else { // Tagged case. | 3566 } else { // Tagged case. |
3468 DeferredMathAbsTaggedHeapNumber* deferred = | 3567 DeferredMathAbsTaggedHeapNumber* deferred = |
3469 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3568 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
3470 Register input_reg = ToRegister(instr->value()); | 3569 Register input_reg = ToRegister(instr->value()); |
3471 // Smi check. | 3570 // Smi check. |
3472 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3571 __ JumpIfNotSmi(input_reg, deferred->entry()); |
3473 __ SmiToInteger32(input_reg, input_reg); | 3572 EmitSmiMathAbs(instr); |
3474 EmitIntegerMathAbs(instr); | |
3475 __ Integer32ToSmi(input_reg, input_reg); | |
3476 __ bind(deferred->exit()); | 3573 __ bind(deferred->exit()); |
3477 } | 3574 } |
3478 } | 3575 } |
3479 | 3576 |
3480 | 3577 |
3481 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3578 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
3482 XMMRegister xmm_scratch = xmm0; | 3579 XMMRegister xmm_scratch = xmm0; |
3483 Register output_reg = ToRegister(instr->result()); | 3580 Register output_reg = ToRegister(instr->result()); |
3484 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3581 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3485 | 3582 |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4133 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4230 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4134 ElementsKind elements_kind = instr->elements_kind(); | 4231 ElementsKind elements_kind = instr->elements_kind(); |
4135 LOperand* key = instr->key(); | 4232 LOperand* key = instr->key(); |
4136 if (!key->IsConstantOperand()) { | 4233 if (!key->IsConstantOperand()) { |
4137 Register key_reg = ToRegister(key); | 4234 Register key_reg = ToRegister(key); |
4138 // Even though the HLoad/StoreKeyedFastElement instructions force | 4235 // Even though the HLoad/StoreKeyedFastElement instructions force |
4139 // the input representation for the key to be an integer, the input | 4236 // the input representation for the key to be an integer, the input |
4140 // gets replaced during bound check elimination with the index | 4237 // gets replaced during bound check elimination with the index |
4141 // argument to the bounds check, which can be tagged, so that case | 4238 // argument to the bounds check, which can be tagged, so that case |
4142 // must be handled here, too. | 4239 // must be handled here, too. |
4143 if (instr->hydrogen()->IsDehoisted()) { | 4240 if (instr->hydrogen()->key()->representation().IsSmi()) { |
| 4241 ASSERT(SmiValuesAre31Bits()); |
| 4242 __ SmiToInteger64(key_reg, key_reg); |
| 4243 } else if (instr->hydrogen()->IsDehoisted()) { |
4144 // Sign extend key because it could be a 32 bit negative value | 4244 // Sign extend key because it could be a 32 bit negative value |
4145 // and the dehoisted address computation happens in 64 bits | 4245 // and the dehoisted address computation happens in 64 bits |
4146 __ movsxlq(key_reg, key_reg); | 4246 __ movsxlq(key_reg, key_reg); |
4147 } | 4247 } |
4148 } | 4248 } |
4149 Operand operand(BuildFastArrayOperand( | 4249 Operand operand(BuildFastArrayOperand( |
4150 instr->elements(), | 4250 instr->elements(), |
4151 key, | 4251 key, |
4152 elements_kind, | 4252 elements_kind, |
4153 0, | 4253 0, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4195 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { | 4295 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
4196 XMMRegister value = ToDoubleRegister(instr->value()); | 4296 XMMRegister value = ToDoubleRegister(instr->value()); |
4197 LOperand* key = instr->key(); | 4297 LOperand* key = instr->key(); |
4198 if (!key->IsConstantOperand()) { | 4298 if (!key->IsConstantOperand()) { |
4199 Register key_reg = ToRegister(key); | 4299 Register key_reg = ToRegister(key); |
4200 // Even though the HLoad/StoreKeyedFastElement instructions force | 4300 // Even though the HLoad/StoreKeyedFastElement instructions force |
4201 // the input representation for the key to be an integer, the | 4301 // the input representation for the key to be an integer, the |
4202 // input gets replaced during bound check elimination with the index | 4302 // input gets replaced during bound check elimination with the index |
4203 // argument to the bounds check, which can be tagged, so that case | 4303 // argument to the bounds check, which can be tagged, so that case |
4204 // must be handled here, too. | 4304 // must be handled here, too. |
4205 if (instr->hydrogen()->IsDehoisted()) { | 4305 if (instr->hydrogen()->key()->representation().IsSmi()) { |
| 4306 ASSERT(SmiValuesAre31Bits()); |
| 4307 __ SmiToInteger64(key_reg, key_reg); |
| 4308 } else if (instr->hydrogen()->IsDehoisted()) { |
4206 // Sign extend key because it could be a 32 bit negative value | 4309 // Sign extend key because it could be a 32 bit negative value |
4207 // and the dehoisted address computation happens in 64 bits | 4310 // and the dehoisted address computation happens in 64 bits |
4208 __ movsxlq(key_reg, key_reg); | 4311 __ movsxlq(key_reg, key_reg); |
4209 } | 4312 } |
4210 } | 4313 } |
4211 | 4314 |
4212 if (instr->NeedsCanonicalization()) { | 4315 if (instr->NeedsCanonicalization()) { |
4213 Label have_value; | 4316 Label have_value; |
4214 | 4317 |
4215 __ ucomisd(value, value); | 4318 __ ucomisd(value, value); |
(...skipping 20 matching lines...) Expand all Loading... |
4236 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4339 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
4237 Register elements = ToRegister(instr->elements()); | 4340 Register elements = ToRegister(instr->elements()); |
4238 LOperand* key = instr->key(); | 4341 LOperand* key = instr->key(); |
4239 if (!key->IsConstantOperand()) { | 4342 if (!key->IsConstantOperand()) { |
4240 Register key_reg = ToRegister(key); | 4343 Register key_reg = ToRegister(key); |
4241 // Even though the HLoad/StoreKeyedFastElement instructions force | 4344 // Even though the HLoad/StoreKeyedFastElement instructions force |
4242 // the input representation for the key to be an integer, the | 4345 // the input representation for the key to be an integer, the |
4243 // input gets replaced during bound check elimination with the index | 4346 // input gets replaced during bound check elimination with the index |
4244 // argument to the bounds check, which can be tagged, so that case | 4347 // argument to the bounds check, which can be tagged, so that case |
4245 // must be handled here, too. | 4348 // must be handled here, too. |
4246 if (instr->hydrogen()->IsDehoisted()) { | 4349 if (instr->hydrogen()->key()->representation().IsSmi()) { |
| 4350 ASSERT(SmiValuesAre31Bits()); |
| 4351 __ SmiToInteger64(key_reg, key_reg); |
| 4352 } else if (instr->hydrogen()->IsDehoisted()) { |
4247 // Sign extend key because it could be a 32 bit negative value | 4353 // Sign extend key because it could be a 32 bit negative value |
4248 // and the dehoisted address computation happens in 64 bits | 4354 // and the dehoisted address computation happens in 64 bits |
4249 __ movsxlq(key_reg, key_reg); | 4355 __ movsxlq(key_reg, key_reg); |
4250 } | 4356 } |
4251 } | 4357 } |
4252 | 4358 |
4253 Operand operand = | 4359 Operand operand = |
4254 BuildFastArrayOperand(instr->elements(), | 4360 BuildFastArrayOperand(instr->elements(), |
4255 key, | 4361 key, |
4256 FAST_ELEMENTS, | 4362 FAST_ELEMENTS, |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4493 LOperand* output = instr->result(); | 4599 LOperand* output = instr->result(); |
4494 LOperand* temp = instr->temp(); | 4600 LOperand* temp = instr->temp(); |
4495 | 4601 |
4496 __ LoadUint32(ToDoubleRegister(output), | 4602 __ LoadUint32(ToDoubleRegister(output), |
4497 ToRegister(input), | 4603 ToRegister(input), |
4498 ToDoubleRegister(temp)); | 4604 ToDoubleRegister(temp)); |
4499 } | 4605 } |
4500 | 4606 |
4501 | 4607 |
4502 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4608 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
4503 LOperand* input = instr->value(); | 4609 if (SmiValuesAre32Bits()) { |
4504 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4610 LOperand* input = instr->value(); |
4505 Register reg = ToRegister(input); | 4611 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4612 Register reg = ToRegister(input); |
4506 | 4613 |
4507 __ Integer32ToSmi(reg, reg); | 4614 __ Integer32ToSmi(reg, reg); |
| 4615 } else { |
| 4616 ASSERT(SmiValuesAre31Bits()); |
| 4617 class DeferredNumberTagI: public LDeferredCode { |
| 4618 public: |
| 4619 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 4620 : LDeferredCode(codegen), instr_(instr) { } |
| 4621 virtual void Generate() { |
| 4622 codegen()->DoDeferredNumberTagI(instr_); |
| 4623 } |
| 4624 virtual LInstruction* instr() { return instr_; } |
| 4625 private: |
| 4626 LNumberTagI* instr_; |
| 4627 }; |
| 4628 |
| 4629 LOperand* input = instr->value(); |
| 4630 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4631 Register reg = ToRegister(input); |
| 4632 |
| 4633 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
| 4634 __ shll(reg, Immediate(kSmiTagSize + kSmiShiftSize)); |
| 4635 __ j(overflow, deferred->entry()); |
| 4636 __ movsxlq(reg, reg); |
| 4637 __ bind(deferred->exit()); |
| 4638 } |
4508 } | 4639 } |
4509 | 4640 |
4510 | 4641 |
| 4642 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
| 4643 ASSERT(SmiValuesAre31Bits()); |
| 4644 Label slow; |
| 4645 Register reg = ToRegister(instr->value()); |
| 4646 Register tmp = reg.is(rax) ? kScratchRegister : rax; |
| 4647 |
| 4648 // Preserve the value of all registers. |
| 4649 PushSafepointRegistersScope scope(this); |
| 4650 |
| 4651 Label done; |
| 4652 // There was overflow, so bits 30 and 31 of the original integer |
| 4653 // disagree. Try to allocate a heap number in new space and store |
| 4654 // the value in there. If that fails, call the runtime system. |
| 4655 __ SmiToInteger32(reg, reg); |
| 4656 __ xorl(reg, Immediate(0x80000000)); |
| 4657 __ cvtlsi2sd(xmm1, reg); |
| 4658 |
| 4659 if (FLAG_inline_new) { |
| 4660 __ AllocateHeapNumber(reg, tmp, &slow); |
| 4661 __ jmp(&done, Label::kNear); |
| 4662 } |
| 4663 |
| 4664 // Slow case: Call the runtime system to do the number allocation. |
| 4665 __ bind(&slow); |
| 4666 |
| 4667 // Put a valid pointer value in the stack slot where the result |
| 4668 // register is stored, as this register is in the pointer map, but contains an |
| 4669 // integer value. |
| 4670 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); |
| 4671 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 4672 // Set the pointer to the new heap number in tmp. |
| 4673 if (!reg.is(rax)) __ movq(reg, rax); |
| 4674 |
| 4675 // Heap number allocated. Put the value in xmm0 into the value of the |
| 4676 // allocated heap number. |
| 4677 __ bind(&done); |
| 4678 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm1); |
| 4679 __ StoreToSafepointRegisterSlot(reg, reg); |
| 4680 } |
| 4681 |
| 4682 |
4511 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4683 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4512 class DeferredNumberTagU: public LDeferredCode { | 4684 class DeferredNumberTagU: public LDeferredCode { |
4513 public: | 4685 public: |
4514 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4686 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
4515 : LDeferredCode(codegen), instr_(instr) { } | 4687 : LDeferredCode(codegen), instr_(instr) { } |
4516 virtual void Generate() { | 4688 virtual void Generate() { |
4517 codegen()->DoDeferredNumberTagU(instr_); | 4689 codegen()->DoDeferredNumberTagU(instr_); |
4518 } | 4690 } |
4519 virtual LInstruction* instr() { return instr_; } | 4691 virtual LInstruction* instr() { return instr_; } |
4520 private: | 4692 private: |
(...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5577 FixedArray::kHeaderSize - kPointerSize)); | 5749 FixedArray::kHeaderSize - kPointerSize)); |
5578 __ bind(&done); | 5750 __ bind(&done); |
5579 } | 5751 } |
5580 | 5752 |
5581 | 5753 |
5582 #undef __ | 5754 #undef __ |
5583 | 5755 |
5584 } } // namespace v8::internal | 5756 } } // namespace v8::internal |
5585 | 5757 |
5586 #endif // V8_TARGET_ARCH_X64 | 5758 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |