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

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: 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') | src/arm64/assembler-arm64.cc » ('J')
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 void Emit(bool require_jump);
rmcilroy 2014/06/17 13:09:57 comments on Emit and Clear please
Rodolph Perfetta (ARM) 2014/06/18 16:53:23 Done.
769 void Clear();
770
771 private:
772 bool CanBeShared(RelocInfo::Mode mode);
773 void EmitMarker();
774 void EmitGuard();
775 void EmitEntries();
776
777 Assembler* assm_;
778 // Keep track of the first instruction requiring a constant pool entry
779 // since the previous constant pool was emitted.
780 int first_use_;
781 // values, pc offset(s) of entries which can be shared.
782 std::multimap<uint64_t, int> shared_entries_;
783 // Number of distinct literal in shared entries.
784 int shared_entries_count;
785 // values, pc offset of entries which cannot be shared.
786 std::vector<std::pair<uint64_t, int> > unique_entries_;
787 };
788
789
743 // ----------------------------------------------------------------------------- 790 // -----------------------------------------------------------------------------
744 // Assembler. 791 // Assembler.
745 792
746 class Assembler : public AssemblerBase { 793 class Assembler : public AssemblerBase {
747 public: 794 public:
748 // Create an assembler. Instructions and relocation information are emitted 795 // Create an assembler. Instructions and relocation information are emitted
749 // into a buffer, with the instructions starting from the beginning and the 796 // into a buffer, with the instructions starting from the beginning and the
750 // relocation information starting from the end of the buffer. See CodeDesc 797 // relocation information starting from the end of the buffer. See CodeDesc
751 // for a detailed comment on the layout (globals.h). 798 // for a detailed comment on the layout (globals.h).
752 // 799 //
753 // If the provided buffer is NULL, the assembler allocates and grows its own 800 // 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 801 // buffer, and buffer_size determines the initial buffer size. The buffer is
755 // owned by the assembler and deallocated upon destruction of the assembler. 802 // owned by the assembler and deallocated upon destruction of the assembler.
756 // 803 //
757 // If the provided buffer is not NULL, the assembler uses the provided buffer 804 // 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 805 // 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 806 // is too small, a fatal error occurs. No deallocation of the buffer is done
760 // upon destruction of the assembler. 807 // upon destruction of the assembler.
761 Assembler(Isolate* arg_isolate, void* buffer, int buffer_size); 808 Assembler(Isolate* arg_isolate, void* buffer, int buffer_size);
762 809
763 virtual ~Assembler(); 810 virtual ~Assembler();
764 811
765 virtual void AbortedCodeGeneration() { 812 virtual void AbortedCodeGeneration() {
766 num_pending_reloc_info_ = 0; 813 constpool_.Clear();
767 } 814 }
768 815
769 // System functions --------------------------------------------------------- 816 // System functions ---------------------------------------------------------
770 // Start generating code from the beginning of the buffer, discarding any code 817 // Start generating code from the beginning of the buffer, discarding any code
771 // and data that has already been emitted into the buffer. 818 // and data that has already been emitted into the buffer.
772 // 819 //
773 // In order to avoid any accidental transfer of state, Reset ASSERTs that the 820 // In order to avoid any accidental transfer of state, Reset ASSERTs that the
774 // constant pool is not blocked. 821 // constant pool is not blocked.
775 void Reset(); 822 void Reset();
776 823
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 void StartBlockConstPool(); 952 void StartBlockConstPool();
906 953
907 // Resume constant pool emission. Need to be called as many time as 954 // Resume constant pool emission. Need to be called as many time as
908 // StartBlockConstPool to have an effect. 955 // StartBlockConstPool to have an effect.
909 void EndBlockConstPool(); 956 void EndBlockConstPool();
910 957
911 bool is_const_pool_blocked() const; 958 bool is_const_pool_blocked() const;
912 static bool IsConstantPoolAt(Instruction* instr); 959 static bool IsConstantPoolAt(Instruction* instr);
913 static int ConstantPoolSizeAt(Instruction* instr); 960 static int ConstantPoolSizeAt(Instruction* instr);
914 // See Assembler::CheckConstPool for more info. 961 // See Assembler::CheckConstPool for more info.
915 void ConstantPoolMarker(uint32_t size);
916 void EmitPoolGuard(); 962 void EmitPoolGuard();
917 void ConstantPoolGuard();
918 963
919 // Prevent veneer pool emission until EndBlockVeneerPool is called. 964 // Prevent veneer pool emission until EndBlockVeneerPool is called.
920 // Call to this function can be nested but must be followed by an equal 965 // Call to this function can be nested but must be followed by an equal
921 // number of call to EndBlockConstpool. 966 // number of call to EndBlockConstpool.
922 void StartBlockVeneerPool(); 967 void StartBlockVeneerPool();
923 968
924 // Resume constant pool emission. Need to be called as many time as 969 // Resume constant pool emission. Need to be called as many time as
925 // StartBlockVeneerPool to have an effect. 970 // StartBlockVeneerPool to have an effect.
926 void EndBlockVeneerPool(); 971 void EndBlockVeneerPool();
927 972
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 1733
1689 // Parameters are described in arm64/instructions-arm64.h. 1734 // Parameters are described in arm64/instructions-arm64.h.
1690 void debug(const char* message, uint32_t code, Instr params = BREAK); 1735 void debug(const char* message, uint32_t code, Instr params = BREAK);
1691 1736
1692 // Required by V8. 1737 // Required by V8.
1693 void dd(uint32_t data) { dc32(data); } 1738 void dd(uint32_t data) { dc32(data); }
1694 void db(uint8_t data) { dc8(data); } 1739 void db(uint8_t data) { dc8(data); }
1695 1740
1696 // Code generation helpers -------------------------------------------------- 1741 // Code generation helpers --------------------------------------------------
1697 1742
1698 unsigned num_pending_reloc_info() const { return num_pending_reloc_info_; } 1743 bool IsConstPoolEmpty() const { return constpool_.IsEmpty(); }
1744
1745 Instruction* pc() const { return Instruction::Cast(pc_); }
1699 1746
1700 Instruction* InstructionAt(int offset) const { 1747 Instruction* InstructionAt(int offset) const {
1701 return reinterpret_cast<Instruction*>(buffer_ + offset); 1748 return reinterpret_cast<Instruction*>(buffer_ + offset);
1702 } 1749 }
1703 1750
1704 ptrdiff_t InstructionOffset(Instruction* instr) const { 1751 ptrdiff_t InstructionOffset(Instruction* instr) const {
1705 return reinterpret_cast<byte*>(instr) - buffer_; 1752 return reinterpret_cast<byte*>(instr) - buffer_;
1706 } 1753 }
1707 1754
1708 // Register encoding. 1755 // Register encoding.
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
2043 } 2090 }
2044 2091
2045 void GrowBuffer(); 2092 void GrowBuffer();
2046 void CheckBufferSpace(); 2093 void CheckBufferSpace();
2047 void CheckBuffer(); 2094 void CheckBuffer();
2048 2095
2049 // Pc offset of the next constant pool check. 2096 // Pc offset of the next constant pool check.
2050 int next_constant_pool_check_; 2097 int next_constant_pool_check_;
2051 2098
2052 // Constant pool generation 2099 // Constant pool generation
2053 // Pools are emitted in the instruction stream, preferably after unconditional 2100 // Pools are emitted in the instruction stream. They are emitted when:
2054 // jumps or after returns from functions (in dead code locations). 2101 // * 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 2102 // * 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 2103 // * code generation is finished
rmcilroy 2014/06/17 13:09:57 Is it no longer the case that they are emitted in
Rodolph Perfetta (ARM) 2014/06/18 16:53:23 No we no longer emit in dead code location. On ARM
rmcilroy 2014/06/19 09:58:16 Interesting. Sounds good in that case.
2057 // location it is accessed from. In this case, we emit a jump over the emitted 2104 // If a pool needs to be emitted before code generation is finished a branch
2058 // constant pool. 2105 // over the emitted pool will be inserted.
2106
2059 // Constants in the pool may be addresses of functions that gets relocated; 2107 // 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. 2108 // if so, a relocation info entry is associated to the constant pool entry.
2061 2109
2062 // Repeated checking whether the constant pool should be emitted is rather 2110 // Repeated checking whether the constant pool should be emitted is rather
2063 // expensive. By default we only check again once a number of instructions 2111 // 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 2112 // 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. 2113 // an exact science, and that we rely on some slop to not overrun buffers.
2066 static const int kCheckConstPoolIntervalInst = 128; 2114 static const int kCheckConstPoolIntervalInst = 128;
2067 static const int kCheckConstPoolInterval = 2115 static const int kCheckConstPoolInterval =
2068 kCheckConstPoolIntervalInst * kInstructionSize; 2116 kCheckConstPoolIntervalInst * kInstructionSize;
2069 2117
2070 // Constants in pools are accessed via pc relative addressing, which can 2118 // 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 2119 // are accessed with pc relative load therefore this cannot be more than
2072 // and the accessed constant. 2120 // 1 * MB. Since constant pool emission checks are interval based this value
2073 static const int kMaxDistToConstPool = 4 * KB; 2121 // is an approximation.
2074 static const int kMaxNumPendingRelocInfo = 2122 static const int kApproximateDistToConstPool = 64 * KB;
rmcilroy 2014/06/17 13:09:57 How about kApproxMaxDistToConstPool?
Rodolph Perfetta (ARM) 2014/06/18 16:53:23 Done.
2075 kMaxDistToConstPool / kInstructionSize;
2076 2123
2077 2124 // Number of pool entries after which a pool will be emitted. Since constant
2078 // Average distance beetween a constant pool and the first instruction 2125 // pool emission checks are interval based this value is an approximation.
2079 // accessing the constant pool. Longer distance should result in less I-cache 2126 static const int kApproximatePoolEntryCount = 512;
rmcilroy 2014/06/17 13:09:57 kApproxMaxPoolEntryCount?
Rodolph Perfetta (ARM) 2014/06/18 16:53:23 Done.
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 2127
2086 // Emission of the constant pool may be blocked in some code sequences. 2128 // 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. 2129 int const_pool_blocked_nesting_; // Block emission if this is not zero.
2088 int no_const_pool_before_; // Block emission before this pc offset. 2130 int no_const_pool_before_; // Block emission before this pc offset.
2089 2131
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. 2132 // 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. 2133 int veneer_pool_blocked_nesting_; // Block emission if this is not zero.
2096 2134
2097 // Relocation info generation 2135 // Relocation info generation
2098 // Each relocation is encoded as a variable size value 2136 // Each relocation is encoded as a variable size value
2099 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 2137 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
2100 RelocInfoWriter reloc_info_writer; 2138 RelocInfoWriter reloc_info_writer;
2101 2139
2102 // Relocation info records are also used during code generation as temporary 2140 // Relocation info records are also used during code generation as temporary
2103 // containers for constants and code target addresses until they are emitted 2141 // containers for constants and code target addresses until they are emitted
2104 // to the constant pool. These pending relocation info records are temporarily 2142 // to the constant pool. These pending relocation info records are temporarily
2105 // stored in a separate buffer until a constant pool is emitted. 2143 // 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 2144 // If every instruction in a long sequence is accessing the pool, we need one
2107 // pending relocation entry per instruction. 2145 // pending relocation entry per instruction.
2108 2146
2109 // the buffer of pending relocation info 2147 // The pending constant pool.
2110 RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo]; 2148 ConstPool constpool_;
2111 // number of pending reloc info entries in the buffer
2112 int num_pending_reloc_info_;
2113 2149
2114 // Relocation for a type-recording IC has the AST id added to it. This 2150 // 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 2151 // member variable is a way to pass the information from the call site to
2116 // the relocation info. 2152 // the relocation info.
2117 TypeFeedbackId recorded_ast_id_; 2153 TypeFeedbackId recorded_ast_id_;
2118 2154
2119 inline TypeFeedbackId RecordedAstId(); 2155 inline TypeFeedbackId RecordedAstId();
2120 inline void ClearRecordedAstId(); 2156 inline void ClearRecordedAstId();
2121 2157
2122 protected: 2158 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 2225 // 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 2226 // the label chain, and for each PC-relative instruction in the chain checking
2191 // if pending unresolved information exists. Its complexity is proportional to 2227 // if pending unresolved information exists. Its complexity is proportional to
2192 // the length of the label chain. 2228 // the length of the label chain.
2193 void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label); 2229 void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label);
2194 2230
2195 private: 2231 private:
2196 PositionsRecorder positions_recorder_; 2232 PositionsRecorder positions_recorder_;
2197 friend class PositionsRecorder; 2233 friend class PositionsRecorder;
2198 friend class EnsureSpace; 2234 friend class EnsureSpace;
2235 friend class ConstPool;
2199 }; 2236 };
2200 2237
2201 class PatchingAssembler : public Assembler { 2238 class PatchingAssembler : public Assembler {
2202 public: 2239 public:
2203 // Create an Assembler with a buffer starting at 'start'. 2240 // Create an Assembler with a buffer starting at 'start'.
2204 // The buffer size is 2241 // The buffer size is
2205 // size of instructions to patch + kGap 2242 // size of instructions to patch + kGap
2206 // Where kGap is the distance from which the Assembler tries to grow the 2243 // Where kGap is the distance from which the Assembler tries to grow the
2207 // buffer. 2244 // buffer.
2208 // If more or fewer instructions than expected are generated or if some 2245 // If more or fewer instructions than expected are generated or if some
(...skipping 12 matching lines...) Expand all
2221 StartBlockPools(); 2258 StartBlockPools();
2222 } 2259 }
2223 2260
2224 ~PatchingAssembler() { 2261 ~PatchingAssembler() {
2225 // Const pool should still be blocked. 2262 // Const pool should still be blocked.
2226 ASSERT(is_const_pool_blocked()); 2263 ASSERT(is_const_pool_blocked());
2227 EndBlockPools(); 2264 EndBlockPools();
2228 // Verify we have generated the number of instruction we expected. 2265 // Verify we have generated the number of instruction we expected.
2229 ASSERT((pc_offset() + kGap) == buffer_size_); 2266 ASSERT((pc_offset() + kGap) == buffer_size_);
2230 // Verify no relocation information has been emitted. 2267 // Verify no relocation information has been emitted.
2231 ASSERT(num_pending_reloc_info() == 0); 2268 ASSERT(IsConstPoolEmpty());
2232 // Flush the Instruction cache. 2269 // Flush the Instruction cache.
2233 size_t length = buffer_size_ - kGap; 2270 size_t length = buffer_size_ - kGap;
2234 CPU::FlushICache(buffer_, length); 2271 CPU::FlushICache(buffer_, length);
2235 } 2272 }
2236 2273
2237 static const int kMovInt64NInstrs = 4; 2274 static const int kMovInt64NInstrs = 4;
2238 void MovInt64(const Register& rd, int64_t imm); 2275 void MovInt64(const Register& rd, int64_t imm);
2239 2276
2240 // See definition of PatchAdrFar() for details. 2277 // See definition of PatchAdrFar() for details.
2241 static const int kAdrFarPatchableNNops = kMovInt64NInstrs - 1; 2278 static const int kAdrFarPatchableNNops = kMovInt64NInstrs - 1;
2242 static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 3; 2279 static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 3;
2243 void PatchAdrFar(Instruction* target); 2280 void PatchAdrFar(Instruction* target);
2244 }; 2281 };
2245 2282
2246 2283
2247 class EnsureSpace BASE_EMBEDDED { 2284 class EnsureSpace BASE_EMBEDDED {
2248 public: 2285 public:
2249 explicit EnsureSpace(Assembler* assembler) { 2286 explicit EnsureSpace(Assembler* assembler) {
2250 assembler->CheckBufferSpace(); 2287 assembler->CheckBufferSpace();
2251 } 2288 }
2252 }; 2289 };
2253 2290
2254 } } // namespace v8::internal 2291 } } // namespace v8::internal
2255 2292
2256 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ 2293 #endif // V8_ARM64_ASSEMBLER_ARM64_H_
OLDNEW
« no previous file with comments | « no previous file | src/arm64/assembler-arm64.cc » ('j') | src/arm64/assembler-arm64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698