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