| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 // for a detailed comment on the layout (globals.h). | 688 // for a detailed comment on the layout (globals.h). |
| 689 // | 689 // |
| 690 // If the provided buffer is NULL, the assembler allocates and grows its own | 690 // If the provided buffer is NULL, the assembler allocates and grows its own |
| 691 // buffer, and buffer_size determines the initial buffer size. The buffer is | 691 // buffer, and buffer_size determines the initial buffer size. The buffer is |
| 692 // owned by the assembler and deallocated upon destruction of the assembler. | 692 // owned by the assembler and deallocated upon destruction of the assembler. |
| 693 // | 693 // |
| 694 // If the provided buffer is not NULL, the assembler uses the provided buffer | 694 // If the provided buffer is not NULL, the assembler uses the provided buffer |
| 695 // for code generation and assumes its size to be buffer_size. If the buffer | 695 // for code generation and assumes its size to be buffer_size. If the buffer |
| 696 // is too small, a fatal error occurs. No deallocation of the buffer is done | 696 // is too small, a fatal error occurs. No deallocation of the buffer is done |
| 697 // upon destruction of the assembler. | 697 // upon destruction of the assembler. |
| 698 Assembler(Isolate* isolate, void* buffer, int buffer_size); | 698 Assembler(Isolate* isolate, void* buffer, int buffer_size) |
| 699 : Assembler(IsolateData(isolate), buffer, buffer_size) {} |
| 700 Assembler(IsolateData isolate_data, void* buffer, int buffer_size); |
| 699 virtual ~Assembler(); | 701 virtual ~Assembler(); |
| 700 | 702 |
| 701 // GetCode emits any pending (non-emitted) code and fills the descriptor | 703 // GetCode emits any pending (non-emitted) code and fills the descriptor |
| 702 // desc. GetCode() is idempotent; it returns the same result if no other | 704 // desc. GetCode() is idempotent; it returns the same result if no other |
| 703 // Assembler functions are invoked in between GetCode() calls. | 705 // Assembler functions are invoked in between GetCode() calls. |
| 704 void GetCode(CodeDesc* desc); | 706 void GetCode(CodeDesc* desc); |
| 705 | 707 |
| 706 // Label operations & relative jumps (PPUM Appendix D) | 708 // Label operations & relative jumps (PPUM Appendix D) |
| 707 // | 709 // |
| 708 // Takes a branch opcode (cc) and a label (L) and generates | 710 // Takes a branch opcode (cc) and a label (L) and generates |
| (...skipping 19 matching lines...) Expand all Loading... |
| 728 // Returns true if the given pc address is the start of a constant pool load | 730 // Returns true if the given pc address is the start of a constant pool load |
| 729 // instruction sequence. | 731 // instruction sequence. |
| 730 INLINE(static bool is_constant_pool_load(Address pc)); | 732 INLINE(static bool is_constant_pool_load(Address pc)); |
| 731 | 733 |
| 732 // Return the address in the constant pool of the code target address used by | 734 // Return the address in the constant pool of the code target address used by |
| 733 // the branch/call instruction at pc, or the object in a mov. | 735 // the branch/call instruction at pc, or the object in a mov. |
| 734 INLINE(static Address constant_pool_entry_address(Address pc, | 736 INLINE(static Address constant_pool_entry_address(Address pc, |
| 735 Address constant_pool)); | 737 Address constant_pool)); |
| 736 | 738 |
| 737 // Read/Modify the code target address in the branch/call instruction at pc. | 739 // Read/Modify the code target address in the branch/call instruction at pc. |
| 740 // The isolate argument is unused (and may be nullptr) when skipping flushing. |
| 738 INLINE(static Address target_address_at(Address pc, Address constant_pool)); | 741 INLINE(static Address target_address_at(Address pc, Address constant_pool)); |
| 739 INLINE(static void set_target_address_at( | 742 INLINE(static void set_target_address_at( |
| 740 Isolate* isolate, Address pc, Address constant_pool, Address target, | 743 Isolate* isolate, Address pc, Address constant_pool, Address target, |
| 741 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); | 744 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); |
| 742 INLINE(static Address target_address_at(Address pc, Code* code)); | 745 INLINE(static Address target_address_at(Address pc, Code* code)); |
| 743 INLINE(static void set_target_address_at( | 746 INLINE(static void set_target_address_at( |
| 744 Isolate* isolate, Address pc, Code* code, Address target, | 747 Isolate* isolate, Address pc, Code* code, Address target, |
| 745 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); | 748 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); |
| 746 | 749 |
| 747 // Return the code target address at a call site from the return address | 750 // Return the code target address at a call site from the return address |
| (...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1692 return IsEnabled(VFP32DREGS) || | 1695 return IsEnabled(VFP32DREGS) || |
| 1693 (reg.reg_code < LowDwVfpRegister::kMaxNumLowRegisters); | 1696 (reg.reg_code < LowDwVfpRegister::kMaxNumLowRegisters); |
| 1694 } | 1697 } |
| 1695 | 1698 |
| 1696 bool VfpRegisterIsAvailable(QwNeonRegister reg) { | 1699 bool VfpRegisterIsAvailable(QwNeonRegister reg) { |
| 1697 DCHECK(reg.is_valid()); | 1700 DCHECK(reg.is_valid()); |
| 1698 return IsEnabled(VFP32DREGS) || | 1701 return IsEnabled(VFP32DREGS) || |
| 1699 (reg.reg_code < LowDwVfpRegister::kMaxNumLowRegisters / 2); | 1702 (reg.reg_code < LowDwVfpRegister::kMaxNumLowRegisters / 2); |
| 1700 } | 1703 } |
| 1701 | 1704 |
| 1702 private: | 1705 inline void emit(Instr x); |
| 1703 int next_buffer_check_; // pc offset of next buffer check | |
| 1704 | 1706 |
| 1705 // Code generation | 1707 // Code generation |
| 1706 // The relocation writer's position is at least kGap bytes below the end of | 1708 // The relocation writer's position is at least kGap bytes below the end of |
| 1707 // the generated instructions. This is so that multi-instruction sequences do | 1709 // the generated instructions. This is so that multi-instruction sequences do |
| 1708 // not have to check for overflow. The same is true for writes of large | 1710 // not have to check for overflow. The same is true for writes of large |
| 1709 // relocation info entries. | 1711 // relocation info entries. |
| 1710 static constexpr int kGap = 32; | 1712 static constexpr int kGap = 32; |
| 1711 | 1713 |
| 1714 // Relocation info generation |
| 1715 // Each relocation is encoded as a variable size value |
| 1716 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
| 1717 RelocInfoWriter reloc_info_writer; |
| 1718 |
| 1719 // ConstantPoolEntry records are used during code generation as temporary |
| 1720 // containers for constants and code target addresses until they are emitted |
| 1721 // to the constant pool. These records are temporarily stored in a separate |
| 1722 // buffer until a constant pool is emitted. |
| 1723 // If every instruction in a long sequence is accessing the pool, we need one |
| 1724 // pending relocation entry per instruction. |
| 1725 |
| 1726 // The buffers of pending constant pool entries. |
| 1727 std::vector<ConstantPoolEntry> pending_32_bit_constants_; |
| 1728 std::vector<ConstantPoolEntry> pending_64_bit_constants_; |
| 1729 |
| 1730 private: |
| 1731 int next_buffer_check_; // pc offset of next buffer check |
| 1732 |
| 1712 // Constant pool generation | 1733 // Constant pool generation |
| 1713 // Pools are emitted in the instruction stream, preferably after unconditional | 1734 // Pools are emitted in the instruction stream, preferably after unconditional |
| 1714 // jumps or after returns from functions (in dead code locations). | 1735 // jumps or after returns from functions (in dead code locations). |
| 1715 // If a long code sequence does not contain unconditional jumps, it is | 1736 // If a long code sequence does not contain unconditional jumps, it is |
| 1716 // necessary to emit the constant pool before the pool gets too far from the | 1737 // necessary to emit the constant pool before the pool gets too far from the |
| 1717 // location it is accessed from. In this case, we emit a jump over the emitted | 1738 // location it is accessed from. In this case, we emit a jump over the emitted |
| 1718 // constant pool. | 1739 // constant pool. |
| 1719 // Constants in the pool may be addresses of functions that gets relocated; | 1740 // Constants in the pool may be addresses of functions that gets relocated; |
| 1720 // if so, a relocation info entry is associated to the constant pool entry. | 1741 // if so, a relocation info entry is associated to the constant pool entry. |
| 1721 | 1742 |
| 1722 // Repeated checking whether the constant pool should be emitted is rather | 1743 // Repeated checking whether the constant pool should be emitted is rather |
| 1723 // expensive. By default we only check again once a number of instructions | 1744 // expensive. By default we only check again once a number of instructions |
| 1724 // has been generated. That also means that the sizing of the buffers is not | 1745 // has been generated. That also means that the sizing of the buffers is not |
| 1725 // an exact science, and that we rely on some slop to not overrun buffers. | 1746 // an exact science, and that we rely on some slop to not overrun buffers. |
| 1726 static constexpr int kCheckPoolIntervalInst = 32; | 1747 static constexpr int kCheckPoolIntervalInst = 32; |
| 1727 static constexpr int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize; | 1748 static constexpr int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize; |
| 1728 | 1749 |
| 1729 | 1750 |
| 1730 // Emission of the constant pool may be blocked in some code sequences. | 1751 // Emission of the constant pool may be blocked in some code sequences. |
| 1731 int const_pool_blocked_nesting_; // Block emission if this is not zero. | 1752 int const_pool_blocked_nesting_; // Block emission if this is not zero. |
| 1732 int no_const_pool_before_; // Block emission before this pc offset. | 1753 int no_const_pool_before_; // Block emission before this pc offset. |
| 1733 | 1754 |
| 1734 // Keep track of the first instruction requiring a constant pool entry | 1755 // Keep track of the first instruction requiring a constant pool entry |
| 1735 // since the previous constant pool was emitted. | 1756 // since the previous constant pool was emitted. |
| 1736 int first_const_pool_32_use_; | 1757 int first_const_pool_32_use_; |
| 1737 int first_const_pool_64_use_; | 1758 int first_const_pool_64_use_; |
| 1738 | 1759 |
| 1739 // Relocation info generation | |
| 1740 // Each relocation is encoded as a variable size value | |
| 1741 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize; | |
| 1742 RelocInfoWriter reloc_info_writer; | |
| 1743 | |
| 1744 // ConstantPoolEntry records are used during code generation as temporary | |
| 1745 // containers for constants and code target addresses until they are emitted | |
| 1746 // to the constant pool. These records are temporarily stored in a separate | |
| 1747 // buffer until a constant pool is emitted. | |
| 1748 // If every instruction in a long sequence is accessing the pool, we need one | |
| 1749 // pending relocation entry per instruction. | |
| 1750 | |
| 1751 // The buffers of pending constant pool entries. | |
| 1752 std::vector<ConstantPoolEntry> pending_32_bit_constants_; | |
| 1753 std::vector<ConstantPoolEntry> pending_64_bit_constants_; | |
| 1754 | |
| 1755 ConstantPoolBuilder constant_pool_builder_; | 1760 ConstantPoolBuilder constant_pool_builder_; |
| 1756 | 1761 |
| 1757 // The bound position, before this we cannot do instruction elimination. | 1762 // The bound position, before this we cannot do instruction elimination. |
| 1758 int last_bound_pos_; | 1763 int last_bound_pos_; |
| 1759 | 1764 |
| 1760 // Code emission | |
| 1761 inline void CheckBuffer(); | 1765 inline void CheckBuffer(); |
| 1762 void GrowBuffer(); | 1766 void GrowBuffer(); |
| 1763 inline void emit(Instr x); | |
| 1764 | 1767 |
| 1765 // 32-bit immediate values | 1768 // 32-bit immediate values |
| 1766 void move_32_bit_immediate(Register rd, | 1769 void move_32_bit_immediate(Register rd, |
| 1767 const Operand& x, | 1770 const Operand& x, |
| 1768 Condition cond = al); | 1771 Condition cond = al); |
| 1769 | 1772 |
| 1770 // Instruction generation | 1773 // Instruction generation |
| 1771 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); | 1774 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); |
| 1772 void addrmod2(Instr instr, Register rd, const MemOperand& x); | 1775 void addrmod2(Instr instr, Register rd, const MemOperand& x); |
| 1773 void addrmod3(Instr instr, Register rd, const MemOperand& x); | 1776 void addrmod3(Instr instr, Register rd, const MemOperand& x); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1792 friend class EnsureSpace; | 1795 friend class EnsureSpace; |
| 1793 }; | 1796 }; |
| 1794 | 1797 |
| 1795 constexpr int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; | 1798 constexpr int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; |
| 1796 | 1799 |
| 1797 class EnsureSpace BASE_EMBEDDED { | 1800 class EnsureSpace BASE_EMBEDDED { |
| 1798 public: | 1801 public: |
| 1799 INLINE(explicit EnsureSpace(Assembler* assembler)); | 1802 INLINE(explicit EnsureSpace(Assembler* assembler)); |
| 1800 }; | 1803 }; |
| 1801 | 1804 |
| 1805 class PatchingAssembler : public Assembler { |
| 1806 public: |
| 1807 PatchingAssembler(IsolateData isolate_data, byte* address, int instructions); |
| 1808 ~PatchingAssembler(); |
| 1809 |
| 1810 void Emit(Address addr); |
| 1811 void FlushICache(Isolate* isolate); |
| 1812 }; |
| 1813 |
| 1802 | 1814 |
| 1803 } // namespace internal | 1815 } // namespace internal |
| 1804 } // namespace v8 | 1816 } // namespace v8 |
| 1805 | 1817 |
| 1806 #endif // V8_ARM_ASSEMBLER_ARM_H_ | 1818 #endif // V8_ARM_ASSEMBLER_ARM_H_ |
| OLD | NEW |