Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1412)

Side by Side Diff: src/arm64/assembler-arm64.h

Issue 338523005: ARM64: updated literal pool implementation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed review comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/arm64/assembler-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_
6 #define V8_ARM64_ASSEMBLER_ARM64_H_ 6 #define V8_ARM64_ASSEMBLER_ARM64_H_
7 7
8 #include <list> 8 #include <list>
9 #include <vector>
9 #include <map> 10 #include <map>
10 11
11 #include "src/cpu.h" 12 #include "src/cpu.h"
12 #include "src/globals.h" 13 #include "src/globals.h"
13 #include "src/utils.h" 14 #include "src/utils.h"
14 #include "src/assembler.h" 15 #include "src/assembler.h"
15 #include "src/serialize.h" 16 #include "src/serialize.h"
16 #include "src/arm64/instructions-arm64.h" 17 #include "src/arm64/instructions-arm64.h"
17 18
18 19
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 Register base_; 734 Register base_;
734 Register regoffset_; 735 Register regoffset_;
735 ptrdiff_t offset_; 736 ptrdiff_t offset_;
736 AddrMode addrmode_; 737 AddrMode addrmode_;
737 Shift shift_; 738 Shift shift_;
738 Extend extend_; 739 Extend extend_;
739 unsigned shift_amount_; 740 unsigned shift_amount_;
740 }; 741 };
741 742
742 743
744 class ConstPool {
745 public:
746 explicit ConstPool(Assembler* assm)
747 : assm_(assm),
748 first_use_(-1),
749 shared_entries_count(0) {}
750 void RecordEntry(intptr_t data, RelocInfo::Mode mode);
751 int EntryCount() const {
752 return shared_entries_count + unique_entries_.size();
753 }
754 bool IsEmpty() const {
755 return shared_entries_.empty() && unique_entries_.empty();
756 }
757 // Distance in bytes between the current pc and the first instruction
758 // using the pool. If there are no pending entries return kMaxInt.
759 int DistanceToFirstUse();
760 // Offset after which instructions using the pool will be out of range.
761 int MaxPcOffset();
762 // Maximum size the constant pool can be with current entries. It always
763 // includes alignment padding and branch over.
764 int WorstCaseSize();
765 // Size in bytes of the literal pool *if* it is emitted at the current
766 // pc. The size will include the branch over the pool if it was requested.
767 int SizeIfEmittedAtCurrentPc(bool require_jump);
768 // Emit the literal pool at the current pc with a branch over the pool if
769 // requested.
770 void Emit(bool require_jump);
771 // Discard any pending pool entries.
772 void Clear();
773
774 private:
775 bool CanBeShared(RelocInfo::Mode mode);
776 void EmitMarker();
777 void EmitGuard();
778 void EmitEntries();
779
780 Assembler* assm_;
781 // Keep track of the first instruction requiring a constant pool entry
782 // since the previous constant pool was emitted.
783 int first_use_;
784 // values, pc offset(s) of entries which can be shared.
785 std::multimap<uint64_t, int> shared_entries_;
786 // Number of distinct literal in shared entries.
787 int shared_entries_count;
788 // values, pc offset of entries which cannot be shared.
789 std::vector<std::pair<uint64_t, int> > unique_entries_;
790 };
791
792
743 // ----------------------------------------------------------------------------- 793 // -----------------------------------------------------------------------------
744 // Assembler. 794 // Assembler.
745 795
746 class Assembler : public AssemblerBase { 796 class Assembler : public AssemblerBase {
747 public: 797 public:
748 // Create an assembler. Instructions and relocation information are emitted 798 // Create an assembler. Instructions and relocation information are emitted
749 // into a buffer, with the instructions starting from the beginning and the 799 // into a buffer, with the instructions starting from the beginning and the
750 // relocation information starting from the end of the buffer. See CodeDesc 800 // relocation information starting from the end of the buffer. See CodeDesc
751 // for a detailed comment on the layout (globals.h). 801 // for a detailed comment on the layout (globals.h).
752 // 802 //
753 // If the provided buffer is NULL, the assembler allocates and grows its own 803 // If the provided buffer is NULL, the assembler allocates and grows its own
754 // buffer, and buffer_size determines the initial buffer size. The buffer is 804 // buffer, and buffer_size determines the initial buffer size. The buffer is
755 // owned by the assembler and deallocated upon destruction of the assembler. 805 // owned by the assembler and deallocated upon destruction of the assembler.
756 // 806 //
757 // If the provided buffer is not NULL, the assembler uses the provided buffer 807 // If the provided buffer is not NULL, the assembler uses the provided buffer
758 // for code generation and assumes its size to be buffer_size. If the buffer 808 // for code generation and assumes its size to be buffer_size. If the buffer
759 // is too small, a fatal error occurs. No deallocation of the buffer is done 809 // is too small, a fatal error occurs. No deallocation of the buffer is done
760 // upon destruction of the assembler. 810 // upon destruction of the assembler.
761 Assembler(Isolate* arg_isolate, void* buffer, int buffer_size); 811 Assembler(Isolate* arg_isolate, void* buffer, int buffer_size);
762 812
763 virtual ~Assembler(); 813 virtual ~Assembler();
764 814
765 virtual void AbortedCodeGeneration() { 815 virtual void AbortedCodeGeneration() {
766 num_pending_reloc_info_ = 0; 816 constpool_.Clear();
767 } 817 }
768 818
769 // System functions --------------------------------------------------------- 819 // System functions ---------------------------------------------------------
770 // Start generating code from the beginning of the buffer, discarding any code 820 // Start generating code from the beginning of the buffer, discarding any code
771 // and data that has already been emitted into the buffer. 821 // and data that has already been emitted into the buffer.
772 // 822 //
773 // In order to avoid any accidental transfer of state, Reset ASSERTs that the 823 // In order to avoid any accidental transfer of state, Reset ASSERTs that the
774 // constant pool is not blocked. 824 // constant pool is not blocked.
775 void Reset(); 825 void Reset();
776 826
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 void StartBlockConstPool(); 955 void StartBlockConstPool();
906 956
907 // Resume constant pool emission. Need to be called as many time as 957 // Resume constant pool emission. Need to be called as many time as
908 // StartBlockConstPool to have an effect. 958 // StartBlockConstPool to have an effect.
909 void EndBlockConstPool(); 959 void EndBlockConstPool();
910 960
911 bool is_const_pool_blocked() const; 961 bool is_const_pool_blocked() const;
912 static bool IsConstantPoolAt(Instruction* instr); 962 static bool IsConstantPoolAt(Instruction* instr);
913 static int ConstantPoolSizeAt(Instruction* instr); 963 static int ConstantPoolSizeAt(Instruction* instr);
914 // See Assembler::CheckConstPool for more info. 964 // See Assembler::CheckConstPool for more info.
915 void ConstantPoolMarker(uint32_t size);
916 void EmitPoolGuard(); 965 void EmitPoolGuard();
917 void ConstantPoolGuard();
918 966
919 // Prevent veneer pool emission until EndBlockVeneerPool is called. 967 // Prevent veneer pool emission until EndBlockVeneerPool is called.
920 // Call to this function can be nested but must be followed by an equal 968 // Call to this function can be nested but must be followed by an equal
921 // number of call to EndBlockConstpool. 969 // number of call to EndBlockConstpool.
922 void StartBlockVeneerPool(); 970 void StartBlockVeneerPool();
923 971
924 // Resume constant pool emission. Need to be called as many time as 972 // Resume constant pool emission. Need to be called as many time as
925 // StartBlockVeneerPool to have an effect. 973 // StartBlockVeneerPool to have an effect.
926 void EndBlockVeneerPool(); 974 void EndBlockVeneerPool();
927 975
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 1736
1689 // Parameters are described in arm64/instructions-arm64.h. 1737 // Parameters are described in arm64/instructions-arm64.h.
1690 void debug(const char* message, uint32_t code, Instr params = BREAK); 1738 void debug(const char* message, uint32_t code, Instr params = BREAK);
1691 1739
1692 // Required by V8. 1740 // Required by V8.
1693 void dd(uint32_t data) { dc32(data); } 1741 void dd(uint32_t data) { dc32(data); }
1694 void db(uint8_t data) { dc8(data); } 1742 void db(uint8_t data) { dc8(data); }
1695 1743
1696 // Code generation helpers -------------------------------------------------- 1744 // Code generation helpers --------------------------------------------------
1697 1745
1698 unsigned num_pending_reloc_info() const { return num_pending_reloc_info_; } 1746 bool IsConstPoolEmpty() const { return constpool_.IsEmpty(); }
1747
1748 Instruction* pc() const { return Instruction::Cast(pc_); }
1699 1749
1700 Instruction* InstructionAt(int offset) const { 1750 Instruction* InstructionAt(int offset) const {
1701 return reinterpret_cast<Instruction*>(buffer_ + offset); 1751 return reinterpret_cast<Instruction*>(buffer_ + offset);
1702 } 1752 }
1703 1753
1704 ptrdiff_t InstructionOffset(Instruction* instr) const { 1754 ptrdiff_t InstructionOffset(Instruction* instr) const {
1705 return reinterpret_cast<byte*>(instr) - buffer_; 1755 return reinterpret_cast<byte*>(instr) - buffer_;
1706 } 1756 }
1707 1757
1708 // Register encoding. 1758 // Register encoding.
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
2012 2062
2013 // Verify that a label's link chain is intact. 2063 // Verify that a label's link chain is intact.
2014 void CheckLabelLinkChain(Label const * label); 2064 void CheckLabelLinkChain(Label const * label);
2015 2065
2016 void RecordLiteral(int64_t imm, unsigned size); 2066 void RecordLiteral(int64_t imm, unsigned size);
2017 2067
2018 // Postpone the generation of the constant pool for the specified number of 2068 // Postpone the generation of the constant pool for the specified number of
2019 // instructions. 2069 // instructions.
2020 void BlockConstPoolFor(int instructions); 2070 void BlockConstPoolFor(int instructions);
2021 2071
2072 // Set how far from current pc the next constant pool check will be.
2073 void SetNextConstPoolCheckIn(int instructions) {
2074 next_constant_pool_check_ = pc_offset() + instructions * kInstructionSize;
2075 }
2076
2022 // Emit the instruction at pc_. 2077 // Emit the instruction at pc_.
2023 void Emit(Instr instruction) { 2078 void Emit(Instr instruction) {
2024 STATIC_ASSERT(sizeof(*pc_) == 1); 2079 STATIC_ASSERT(sizeof(*pc_) == 1);
2025 STATIC_ASSERT(sizeof(instruction) == kInstructionSize); 2080 STATIC_ASSERT(sizeof(instruction) == kInstructionSize);
2026 ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_)); 2081 ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_));
2027 2082
2028 memcpy(pc_, &instruction, sizeof(instruction)); 2083 memcpy(pc_, &instruction, sizeof(instruction));
2029 pc_ += sizeof(instruction); 2084 pc_ += sizeof(instruction);
2030 CheckBuffer(); 2085 CheckBuffer();
2031 } 2086 }
(...skipping 11 matching lines...) Expand all
2043 } 2098 }
2044 2099
2045 void GrowBuffer(); 2100 void GrowBuffer();
2046 void CheckBufferSpace(); 2101 void CheckBufferSpace();
2047 void CheckBuffer(); 2102 void CheckBuffer();
2048 2103
2049 // Pc offset of the next constant pool check. 2104 // Pc offset of the next constant pool check.
2050 int next_constant_pool_check_; 2105 int next_constant_pool_check_;
2051 2106
2052 // Constant pool generation 2107 // Constant pool generation
2053 // Pools are emitted in the instruction stream, preferably after unconditional 2108 // Pools are emitted in the instruction stream. They are emitted when:
2054 // jumps or after returns from functions (in dead code locations). 2109 // * the distance to the first use is above a pre-defined distance or
2055 // If a long code sequence does not contain unconditional jumps, it is 2110 // * the numbers of entries in the pool is above a pre-defined size or
2056 // necessary to emit the constant pool before the pool gets too far from the 2111 // * code generation is finished
2057 // location it is accessed from. In this case, we emit a jump over the emitted 2112 // If a pool needs to be emitted before code generation is finished a branch
2058 // constant pool. 2113 // over the emitted pool will be inserted.
2114
2059 // Constants in the pool may be addresses of functions that gets relocated; 2115 // Constants in the pool may be addresses of functions that gets relocated;
2060 // if so, a relocation info entry is associated to the constant pool entry. 2116 // if so, a relocation info entry is associated to the constant pool entry.
2061 2117
2062 // Repeated checking whether the constant pool should be emitted is rather 2118 // Repeated checking whether the constant pool should be emitted is rather
2063 // expensive. By default we only check again once a number of instructions 2119 // expensive. By default we only check again once a number of instructions
2064 // has been generated. That also means that the sizing of the buffers is not 2120 // has been generated. That also means that the sizing of the buffers is not
2065 // an exact science, and that we rely on some slop to not overrun buffers. 2121 // an exact science, and that we rely on some slop to not overrun buffers.
2066 static const int kCheckConstPoolIntervalInst = 128; 2122 static const int kCheckConstPoolInterval = 128;
2067 static const int kCheckConstPoolInterval =
2068 kCheckConstPoolIntervalInst * kInstructionSize;
2069 2123
2070 // Constants in pools are accessed via pc relative addressing, which can 2124 // Distance to first use after a which a pool will be emitted. Pool entries
2071 // reach +/-4KB thereby defining a maximum distance between the instruction 2125 // are accessed with pc relative load therefore this cannot be more than
2072 // and the accessed constant. 2126 // 1 * MB. Since constant pool emission checks are interval based this value
2073 static const int kMaxDistToConstPool = 4 * KB; 2127 // is an approximation.
2074 static const int kMaxNumPendingRelocInfo = 2128 static const int kApproxMaxDistToConstPool = 64 * KB;
2075 kMaxDistToConstPool / kInstructionSize;
2076 2129
2077 2130 // Number of pool entries after which a pool will be emitted. Since constant
2078 // Average distance beetween a constant pool and the first instruction 2131 // pool emission checks are interval based this value is an approximation.
2079 // accessing the constant pool. Longer distance should result in less I-cache 2132 static const int kApproxMaxPoolEntryCount = 512;
2080 // pollution.
2081 // In practice the distance will be smaller since constant pool emission is
2082 // forced after function return and sometimes after unconditional branches.
2083 static const int kAvgDistToConstPool =
2084 kMaxDistToConstPool - kCheckConstPoolInterval;
2085 2133
2086 // Emission of the constant pool may be blocked in some code sequences. 2134 // Emission of the constant pool may be blocked in some code sequences.
2087 int const_pool_blocked_nesting_; // Block emission if this is not zero. 2135 int const_pool_blocked_nesting_; // Block emission if this is not zero.
2088 int no_const_pool_before_; // Block emission before this pc offset. 2136 int no_const_pool_before_; // Block emission before this pc offset.
2089 2137
2090 // Keep track of the first instruction requiring a constant pool entry
2091 // since the previous constant pool was emitted.
2092 int first_const_pool_use_;
2093
2094 // Emission of the veneer pools may be blocked in some code sequences. 2138 // Emission of the veneer pools may be blocked in some code sequences.
2095 int veneer_pool_blocked_nesting_; // Block emission if this is not zero. 2139 int veneer_pool_blocked_nesting_; // Block emission if this is not zero.
2096 2140
2097 // Relocation info generation 2141 // Relocation info generation
2098 // Each relocation is encoded as a variable size value 2142 // Each relocation is encoded as a variable size value
2099 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 2143 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
2100 RelocInfoWriter reloc_info_writer; 2144 RelocInfoWriter reloc_info_writer;
2101 2145
2102 // Relocation info records are also used during code generation as temporary 2146 // Relocation info records are also used during code generation as temporary
2103 // containers for constants and code target addresses until they are emitted 2147 // containers for constants and code target addresses until they are emitted
2104 // to the constant pool. These pending relocation info records are temporarily 2148 // to the constant pool. These pending relocation info records are temporarily
2105 // stored in a separate buffer until a constant pool is emitted. 2149 // stored in a separate buffer until a constant pool is emitted.
2106 // If every instruction in a long sequence is accessing the pool, we need one 2150 // If every instruction in a long sequence is accessing the pool, we need one
2107 // pending relocation entry per instruction. 2151 // pending relocation entry per instruction.
2108 2152
2109 // the buffer of pending relocation info 2153 // The pending constant pool.
2110 RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo]; 2154 ConstPool constpool_;
2111 // number of pending reloc info entries in the buffer
2112 int num_pending_reloc_info_;
2113 2155
2114 // Relocation for a type-recording IC has the AST id added to it. This 2156 // Relocation for a type-recording IC has the AST id added to it. This
2115 // member variable is a way to pass the information from the call site to 2157 // member variable is a way to pass the information from the call site to
2116 // the relocation info. 2158 // the relocation info.
2117 TypeFeedbackId recorded_ast_id_; 2159 TypeFeedbackId recorded_ast_id_;
2118 2160
2119 inline TypeFeedbackId RecordedAstId(); 2161 inline TypeFeedbackId RecordedAstId();
2120 inline void ClearRecordedAstId(); 2162 inline void ClearRecordedAstId();
2121 2163
2122 protected: 2164 protected:
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 // This function deletes the information related to the label by traversing 2231 // This function deletes the information related to the label by traversing
2190 // the label chain, and for each PC-relative instruction in the chain checking 2232 // the label chain, and for each PC-relative instruction in the chain checking
2191 // if pending unresolved information exists. Its complexity is proportional to 2233 // if pending unresolved information exists. Its complexity is proportional to
2192 // the length of the label chain. 2234 // the length of the label chain.
2193 void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label); 2235 void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label);
2194 2236
2195 private: 2237 private:
2196 PositionsRecorder positions_recorder_; 2238 PositionsRecorder positions_recorder_;
2197 friend class PositionsRecorder; 2239 friend class PositionsRecorder;
2198 friend class EnsureSpace; 2240 friend class EnsureSpace;
2241 friend class ConstPool;
2199 }; 2242 };
2200 2243
2201 class PatchingAssembler : public Assembler { 2244 class PatchingAssembler : public Assembler {
2202 public: 2245 public:
2203 // Create an Assembler with a buffer starting at 'start'. 2246 // Create an Assembler with a buffer starting at 'start'.
2204 // The buffer size is 2247 // The buffer size is
2205 // size of instructions to patch + kGap 2248 // size of instructions to patch + kGap
2206 // Where kGap is the distance from which the Assembler tries to grow the 2249 // Where kGap is the distance from which the Assembler tries to grow the
2207 // buffer. 2250 // buffer.
2208 // If more or fewer instructions than expected are generated or if some 2251 // If more or fewer instructions than expected are generated or if some
(...skipping 12 matching lines...) Expand all
2221 StartBlockPools(); 2264 StartBlockPools();
2222 } 2265 }
2223 2266
2224 ~PatchingAssembler() { 2267 ~PatchingAssembler() {
2225 // Const pool should still be blocked. 2268 // Const pool should still be blocked.
2226 ASSERT(is_const_pool_blocked()); 2269 ASSERT(is_const_pool_blocked());
2227 EndBlockPools(); 2270 EndBlockPools();
2228 // Verify we have generated the number of instruction we expected. 2271 // Verify we have generated the number of instruction we expected.
2229 ASSERT((pc_offset() + kGap) == buffer_size_); 2272 ASSERT((pc_offset() + kGap) == buffer_size_);
2230 // Verify no relocation information has been emitted. 2273 // Verify no relocation information has been emitted.
2231 ASSERT(num_pending_reloc_info() == 0); 2274 ASSERT(IsConstPoolEmpty());
2232 // Flush the Instruction cache. 2275 // Flush the Instruction cache.
2233 size_t length = buffer_size_ - kGap; 2276 size_t length = buffer_size_ - kGap;
2234 CPU::FlushICache(buffer_, length); 2277 CPU::FlushICache(buffer_, length);
2235 } 2278 }
2236 2279
2237 static const int kMovInt64NInstrs = 4; 2280 static const int kMovInt64NInstrs = 4;
2238 void MovInt64(const Register& rd, int64_t imm); 2281 void MovInt64(const Register& rd, int64_t imm);
2239 2282
2240 // See definition of PatchAdrFar() for details. 2283 // See definition of PatchAdrFar() for details.
2241 static const int kAdrFarPatchableNNops = kMovInt64NInstrs - 1; 2284 static const int kAdrFarPatchableNNops = kMovInt64NInstrs - 1;
2242 static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 3; 2285 static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 3;
2243 void PatchAdrFar(Instruction* target); 2286 void PatchAdrFar(Instruction* target);
2244 }; 2287 };
2245 2288
2246 2289
2247 class EnsureSpace BASE_EMBEDDED { 2290 class EnsureSpace BASE_EMBEDDED {
2248 public: 2291 public:
2249 explicit EnsureSpace(Assembler* assembler) { 2292 explicit EnsureSpace(Assembler* assembler) {
2250 assembler->CheckBufferSpace(); 2293 assembler->CheckBufferSpace();
2251 } 2294 }
2252 }; 2295 };
2253 2296
2254 } } // namespace v8::internal 2297 } } // namespace v8::internal
2255 2298
2256 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ 2299 #endif // V8_ARM64_ASSEMBLER_ARM64_H_
OLDNEW
« no previous file with comments | « no previous file | src/arm64/assembler-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698