Chromium Code Reviews| Index: src/arm64/assembler-arm64.h |
| diff --git a/src/arm64/assembler-arm64.h b/src/arm64/assembler-arm64.h |
| index c0ad4d053b184141221b70363592a6ee104dde01..3d1e4c828e984244af56ef9163a43f68599f218c 100644 |
| --- a/src/arm64/assembler-arm64.h |
| +++ b/src/arm64/assembler-arm64.h |
| @@ -6,6 +6,7 @@ |
| #define V8_ARM64_ASSEMBLER_ARM64_H_ |
| #include <list> |
| +#include <vector> |
| #include <map> |
| #include "src/cpu.h" |
| @@ -740,6 +741,52 @@ class MemOperand { |
| }; |
| +class ConstPool { |
| + public: |
| + explicit ConstPool(Assembler* assm) |
| + : assm_(assm), |
| + first_use_(-1), |
| + shared_entries_count(0) {} |
| + void RecordEntry(intptr_t data, RelocInfo::Mode mode); |
| + int EntryCount() const { |
| + return shared_entries_count + unique_entries_.size(); |
| + } |
| + bool IsEmpty() const { |
| + return shared_entries_.empty() && unique_entries_.empty(); |
| + } |
| + // Distance in bytes between the current pc and the first instruction |
| + // using the pool. If there are no pending entries return kMaxInt. |
| + int DistanceToFirstUse(); |
| + // Offset after which instructions using the pool will be out of range. |
| + int MaxPcOffset(); |
| + // Maximum size the constant pool can be with current entries. It always |
| + // includes alignment padding and branch over. |
| + int WorstCaseSize(); |
| + // Size in bytes of the literal pool *if* it is emitted at the current |
| + // pc. The size will include the branch over the pool if it was requested. |
| + int SizeIfEmittedAtCurrentPc(bool require_jump); |
| + 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.
|
| + void Clear(); |
| + |
| + private: |
| + bool CanBeShared(RelocInfo::Mode mode); |
| + void EmitMarker(); |
| + void EmitGuard(); |
| + void EmitEntries(); |
| + |
| + Assembler* assm_; |
| + // Keep track of the first instruction requiring a constant pool entry |
| + // since the previous constant pool was emitted. |
| + int first_use_; |
| + // values, pc offset(s) of entries which can be shared. |
| + std::multimap<uint64_t, int> shared_entries_; |
| + // Number of distinct literal in shared entries. |
| + int shared_entries_count; |
| + // values, pc offset of entries which cannot be shared. |
| + std::vector<std::pair<uint64_t, int> > unique_entries_; |
| +}; |
| + |
| + |
| // ----------------------------------------------------------------------------- |
| // Assembler. |
| @@ -763,7 +810,7 @@ class Assembler : public AssemblerBase { |
| virtual ~Assembler(); |
| virtual void AbortedCodeGeneration() { |
| - num_pending_reloc_info_ = 0; |
| + constpool_.Clear(); |
| } |
| // System functions --------------------------------------------------------- |
| @@ -912,9 +959,7 @@ class Assembler : public AssemblerBase { |
| static bool IsConstantPoolAt(Instruction* instr); |
| static int ConstantPoolSizeAt(Instruction* instr); |
| // See Assembler::CheckConstPool for more info. |
| - void ConstantPoolMarker(uint32_t size); |
| void EmitPoolGuard(); |
| - void ConstantPoolGuard(); |
| // Prevent veneer pool emission until EndBlockVeneerPool is called. |
| // Call to this function can be nested but must be followed by an equal |
| @@ -1695,7 +1740,9 @@ class Assembler : public AssemblerBase { |
| // Code generation helpers -------------------------------------------------- |
| - unsigned num_pending_reloc_info() const { return num_pending_reloc_info_; } |
| + bool IsConstPoolEmpty() const { return constpool_.IsEmpty(); } |
| + |
| + Instruction* pc() const { return Instruction::Cast(pc_); } |
| Instruction* InstructionAt(int offset) const { |
| return reinterpret_cast<Instruction*>(buffer_ + offset); |
| @@ -2050,12 +2097,13 @@ class Assembler : public AssemblerBase { |
| int next_constant_pool_check_; |
| // Constant pool generation |
| - // Pools are emitted in the instruction stream, preferably after unconditional |
| - // jumps or after returns from functions (in dead code locations). |
| - // If a long code sequence does not contain unconditional jumps, it is |
| - // necessary to emit the constant pool before the pool gets too far from the |
| - // location it is accessed from. In this case, we emit a jump over the emitted |
| - // constant pool. |
| + // Pools are emitted in the instruction stream. They are emitted when: |
| + // * the distance to the first use is above a pre-defined distance or |
| + // * the numbers of entries in the pool is above a pre-defined size or |
| + // * 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.
|
| + // If a pool needs to be emitted before code generation is finished a branch |
| + // over the emitted pool will be inserted. |
| + |
| // Constants in the pool may be addresses of functions that gets relocated; |
| // if so, a relocation info entry is associated to the constant pool entry. |
| @@ -2067,30 +2115,20 @@ class Assembler : public AssemblerBase { |
| static const int kCheckConstPoolInterval = |
| kCheckConstPoolIntervalInst * kInstructionSize; |
| - // Constants in pools are accessed via pc relative addressing, which can |
| - // reach +/-4KB thereby defining a maximum distance between the instruction |
| - // and the accessed constant. |
| - static const int kMaxDistToConstPool = 4 * KB; |
| - static const int kMaxNumPendingRelocInfo = |
| - kMaxDistToConstPool / kInstructionSize; |
| + // Distance to first use after a which a pool will be emitted. Pool entries |
| + // are accessed with pc relative load therefore this cannot be more than |
| + // 1 * MB. Since constant pool emission checks are interval based this value |
| + // is an approximation. |
| + 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.
|
| - |
| - // Average distance beetween a constant pool and the first instruction |
| - // accessing the constant pool. Longer distance should result in less I-cache |
| - // pollution. |
| - // In practice the distance will be smaller since constant pool emission is |
| - // forced after function return and sometimes after unconditional branches. |
| - static const int kAvgDistToConstPool = |
| - kMaxDistToConstPool - kCheckConstPoolInterval; |
| + // Number of pool entries after which a pool will be emitted. Since constant |
| + // pool emission checks are interval based this value is an approximation. |
| + static const int kApproximatePoolEntryCount = 512; |
|
rmcilroy
2014/06/17 13:09:57
kApproxMaxPoolEntryCount?
Rodolph Perfetta (ARM)
2014/06/18 16:53:23
Done.
|
| // Emission of the constant pool may be blocked in some code sequences. |
| int const_pool_blocked_nesting_; // Block emission if this is not zero. |
| int no_const_pool_before_; // Block emission before this pc offset. |
| - // Keep track of the first instruction requiring a constant pool entry |
| - // since the previous constant pool was emitted. |
| - int first_const_pool_use_; |
| - |
| // Emission of the veneer pools may be blocked in some code sequences. |
| int veneer_pool_blocked_nesting_; // Block emission if this is not zero. |
| @@ -2106,10 +2144,8 @@ class Assembler : public AssemblerBase { |
| // If every instruction in a long sequence is accessing the pool, we need one |
| // pending relocation entry per instruction. |
| - // the buffer of pending relocation info |
| - RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo]; |
| - // number of pending reloc info entries in the buffer |
| - int num_pending_reloc_info_; |
| + // The pending constant pool. |
| + ConstPool constpool_; |
| // Relocation for a type-recording IC has the AST id added to it. This |
| // member variable is a way to pass the information from the call site to |
| @@ -2196,6 +2232,7 @@ class Assembler : public AssemblerBase { |
| PositionsRecorder positions_recorder_; |
| friend class PositionsRecorder; |
| friend class EnsureSpace; |
| + friend class ConstPool; |
| }; |
| class PatchingAssembler : public Assembler { |
| @@ -2228,7 +2265,7 @@ class PatchingAssembler : public Assembler { |
| // Verify we have generated the number of instruction we expected. |
| ASSERT((pc_offset() + kGap) == buffer_size_); |
| // Verify no relocation information has been emitted. |
| - ASSERT(num_pending_reloc_info() == 0); |
| + ASSERT(IsConstPoolEmpty()); |
| // Flush the Instruction cache. |
| size_t length = buffer_size_ - kGap; |
| CPU::FlushICache(buffer_, length); |