| Index: src/a64/assembler-a64.h
|
| diff --git a/src/a64/assembler-a64.h b/src/a64/assembler-a64.h
|
| index a2c93df2ae274bf540e1c41f25c9b09e9d70f6f4..09a8a72014d9c7885266576e35094c6b60926e23 100644
|
| --- a/src/a64/assembler-a64.h
|
| +++ b/src/a64/assembler-a64.h
|
| @@ -730,7 +730,7 @@ class Assembler : public AssemblerBase {
|
| void bind(Label* label);
|
|
|
|
|
| - // RelocInfo and constant pool ----------------------------------------------
|
| + // RelocInfo and pools ------------------------------------------------------
|
|
|
| // Record relocation information for current pc_.
|
| void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
|
| @@ -841,6 +841,28 @@ class Assembler : public AssemblerBase {
|
| void ConstantPoolMarker(uint32_t size);
|
| void ConstantPoolGuard();
|
|
|
| + // Prevent veneer pool emission until EndBlockVeneerPool is called.
|
| + // Call to this function can be nested but must be followed by an equal
|
| + // number of call to EndBlockConstpool.
|
| + void StartBlockVeneerPool();
|
| +
|
| + // Resume constant pool emission. Need to be called as many time as
|
| + // StartBlockVeneerPool to have an effect.
|
| + void EndBlockVeneerPool();
|
| +
|
| + bool is_veneer_pool_blocked() const {
|
| + return veneer_pool_blocked_nesting_ > 0;
|
| + }
|
| +
|
| + // Block/resume emission of constant pools and veneer pools.
|
| + void StartBlockPools() {
|
| + StartBlockConstPool();
|
| + StartBlockVeneerPool();
|
| + }
|
| + void EndBlockPools() {
|
| + EndBlockConstPool();
|
| + EndBlockVeneerPool();
|
| + }
|
|
|
| // Debugging ----------------------------------------------------------------
|
| PositionsRecorder* positions_recorder() { return &positions_recorder_; }
|
| @@ -1718,6 +1740,44 @@ class Assembler : public AssemblerBase {
|
| // Check if is time to emit a constant pool.
|
| void CheckConstPool(bool force_emit, bool require_jump);
|
|
|
| +
|
| + // Returns true if we should emit a veneer as soon as possible for a branch
|
| + // which can at most reach to specified pc.
|
| + bool ShouldEmitVeneer(int max_reachable_pc,
|
| + int margin = kVeneerDistanceMargin);
|
| + bool ShouldEmitVeneers(int margin = kVeneerDistanceMargin) {
|
| + return ShouldEmitVeneer(unresolved_branches_first_limit(), margin);
|
| + }
|
| +
|
| + // The maximum code size generated for a veneer. Currently one branch
|
| + // instruction. This is for code size checking purposes, and can be extended
|
| + // in the future for example if we decide to add nops between the veneers.
|
| + static const int kMaxVeneerCodeSize = 1 * kInstructionSize;
|
| +
|
| + // Emits veneers for branches that are approaching their maximum range.
|
| + // If need_protection is true, the veneers are protected by a branch jumping
|
| + // over the code.
|
| + void EmitVeneers(bool need_protection, int margin = kVeneerDistanceMargin);
|
| + void EmitVeneersGuard();
|
| + // Checks whether veneers need to be emitted at this point.
|
| + void CheckVeneerPool(bool require_jump, int margin = kVeneerDistanceMargin);
|
| +
|
| +
|
| + class BlockPoolsScope {
|
| + public:
|
| + explicit BlockPoolsScope(Assembler* assem) : assem_(assem) {
|
| + assem_->StartBlockPools();
|
| + }
|
| + ~BlockPoolsScope() {
|
| + assem_->EndBlockPools();
|
| + }
|
| +
|
| + private:
|
| + Assembler* assem_;
|
| +
|
| + DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope);
|
| + };
|
| +
|
| // Available for constrained code generation scopes. Prefer
|
| // MacroAssembler::Mov() when possible.
|
| inline void LoadRelocated(const CPURegister& rt, const Operand& operand);
|
| @@ -1903,8 +1963,8 @@ class Assembler : public AssemblerBase {
|
| void GrowBuffer();
|
| void CheckBuffer();
|
|
|
| - // Pc offset of the next buffer check.
|
| - int next_buffer_check_;
|
| + // Pc offset of the next constant pool check.
|
| + int next_constant_pool_check_;
|
|
|
| // Constant pool generation
|
| // Pools are emitted in the instruction stream, preferably after unconditional
|
| @@ -1920,15 +1980,16 @@ class Assembler : public AssemblerBase {
|
| // expensive. By default we only check again once a number of instructions
|
| // has been generated. That also means that the sizing of the buffers is not
|
| // an exact science, and that we rely on some slop to not overrun buffers.
|
| - static const int kCheckPoolIntervalInst = 128;
|
| - static const int kCheckPoolInterval =
|
| - kCheckPoolIntervalInst * kInstructionSize;
|
| + static const int kCheckConstPoolIntervalInst = 128;
|
| + 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 kMaxDistToPool = 4 * KB;
|
| - static const int kMaxNumPendingRelocInfo = kMaxDistToPool / kInstructionSize;
|
| + static const int kMaxDistToConstPool = 4 * KB;
|
| + static const int kMaxNumPendingRelocInfo =
|
| + kMaxDistToConstPool / kInstructionSize;
|
|
|
|
|
| // Average distance beetween a constant pool and the first instruction
|
| @@ -1936,7 +1997,8 @@ class Assembler : public AssemblerBase {
|
| // 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 kAvgDistToPool = kMaxDistToPool - kCheckPoolInterval;
|
| + static const int kAvgDistToConstPool =
|
| + kMaxDistToConstPool - kCheckConstPoolInterval;
|
|
|
| // Emission of the constant pool may be blocked in some code sequences.
|
| int const_pool_blocked_nesting_; // Block emission if this is not zero.
|
| @@ -1946,6 +2008,9 @@ class Assembler : public AssemblerBase {
|
| // 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.
|
| +
|
| // Relocation info generation
|
| // Each relocation is encoded as a variable size value
|
| static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
| @@ -2013,6 +2078,25 @@ class Assembler : public AssemblerBase {
|
| // pc_offset() for convenience.
|
| std::multimap<int, FarBranchInfo> unresolved_branches_;
|
|
|
| + // We generate a veneer for a branch if we reach within this distance of the
|
| + // limit of the range.
|
| + static const int kVeneerDistanceMargin = 1 * KB;
|
| + // The factor of 2 is a finger in the air guess. With a default margin of
|
| + // 1KB, that leaves us an addional 256 instructions to avoid generating a
|
| + // protective branch.
|
| + static const int kVeneerNoProtectionFactor = 2;
|
| + static const int kVeneerDistanceCheckMargin =
|
| + kVeneerNoProtectionFactor * kVeneerDistanceMargin;
|
| + int unresolved_branches_first_limit() const {
|
| + ASSERT(!unresolved_branches_.empty());
|
| + return unresolved_branches_.begin()->first;
|
| + }
|
| + // This is similar to next_constant_pool_check_ and helps reduce the overhead
|
| + // of checking for veneer pools.
|
| + // It is maintained to the closest unresolved branch limit minus the maximum
|
| + // veneer margin (or kMaxInt if there are no unresolved branches).
|
| + int next_veneer_pool_check_;
|
| +
|
| private:
|
| // If a veneer is emitted for a branch instruction, that instruction must be
|
| // removed from the associated label's link chain so that the assembler does
|
| @@ -2021,14 +2105,6 @@ class Assembler : public AssemblerBase {
|
| void DeleteUnresolvedBranchInfoForLabel(Label* label);
|
|
|
| private:
|
| - // TODO(jbramley): VIXL uses next_literal_pool_check_ and
|
| - // literal_pool_monitor_ to determine when to consider emitting a literal
|
| - // pool. V8 doesn't use them, so they should either not be here at all, or
|
| - // should replace or be merged with next_buffer_check_ and
|
| - // const_pool_blocked_nesting_.
|
| - Instruction* next_literal_pool_check_;
|
| - unsigned literal_pool_monitor_;
|
| -
|
| PositionsRecorder positions_recorder_;
|
| friend class PositionsRecorder;
|
| friend class EnsureSpace;
|
|
|