Chromium Code Reviews| Index: src/a64/macro-assembler-a64.h |
| diff --git a/src/a64/macro-assembler-a64.h b/src/a64/macro-assembler-a64.h |
| index 8bd24d3033f6eb9d945e5363359b37b6087de2af..7b8dd3f806734d3f4dfed8b984998b39da58b402 100644 |
| --- a/src/a64/macro-assembler-a64.h |
| +++ b/src/a64/macro-assembler-a64.h |
| @@ -212,7 +212,7 @@ class MacroAssembler : public Assembler { |
| inline void Asr(const Register& rd, const Register& rn, const Register& rm); |
| inline void B(Label* label); |
| inline void B(Condition cond, Label* label); |
| - inline void B(Label* label, Condition cond); |
| + void B(Label* label, Condition cond); |
| inline void Bfi(const Register& rd, |
| const Register& rn, |
| unsigned lsb, |
| @@ -226,8 +226,8 @@ class MacroAssembler : public Assembler { |
| inline void Blr(const Register& xn); |
| inline void Br(const Register& xn); |
| inline void Brk(int code); |
| - inline void Cbnz(const Register& rt, Label* label); |
| - inline void Cbz(const Register& rt, Label* label); |
| + void Cbnz(const Register& rt, Label* label); |
| + void Cbz(const Register& rt, Label* label); |
| inline void Cinc(const Register& rd, const Register& rn, Condition cond); |
| inline void Cinv(const Register& rd, const Register& rn, Condition cond); |
| inline void Cls(const Register& rd, const Register& rn); |
| @@ -400,8 +400,8 @@ class MacroAssembler : public Assembler { |
| inline void Sxtb(const Register& rd, const Register& rn); |
| inline void Sxth(const Register& rd, const Register& rn); |
| inline void Sxtw(const Register& rd, const Register& rn); |
| - inline void Tbnz(const Register& rt, unsigned bit_pos, Label* label); |
| - inline void Tbz(const Register& rt, unsigned bit_pos, Label* label); |
| + void Tbnz(const Register& rt, unsigned bit_pos, Label* label); |
| + void Tbz(const Register& rt, unsigned bit_pos, Label* label); |
| inline void Ubfiz(const Register& rd, |
| const Register& rn, |
| unsigned lsb, |
| @@ -422,7 +422,6 @@ class MacroAssembler : public Assembler { |
| const Register& rn, |
| const Register& rm, |
| const Register& ra); |
| - inline void Unreachable(); |
| inline void Uxtb(const Register& rd, const Register& rn); |
| inline void Uxth(const Register& rd, const Register& rn); |
| inline void Uxtw(const Register& rd, const Register& rn); |
| @@ -2074,6 +2073,58 @@ class MacroAssembler : public Assembler { |
| Heap::RootListIndex map_index, |
| Register scratch1, |
| Register scratch2); |
| + |
| + public: |
| + // Far branches resolving. |
| + // |
| + // The various classes of branch instructions with immediate offsets have |
| + // different ranges. While the Assembler will fail to assemble a branch |
| + // exceeding its range, the MacroAssembler offers a mechanism to resolve |
| + // branches to too distant targets, either by tweaking the generated code to |
| + // use branch instructions with wider ranges or generating veneers. |
| + // |
| + // Currently branches to distant targets are resolved using unconditional |
| + // branch isntructions with a range of +-128MB. If that becomes too little |
| + // (!), the mechanism can be extended to generate special veneers for really |
| + // far targets. |
| + |
| + // 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); |
| + |
| + // 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); |
| + void EmitVeneersGuard(); |
| + // Checks wether veneers need to be emitted at this point. |
| + void CheckVeneers(bool need_protection); |
| + |
| + // Helps resolve branching to labels potentially out of range. |
| + // If the label is not bound, it registers the information necessary to later |
| + // be able to emit a veneer for this branch if necessary. |
| + // If the label is bound, it returns true if the label (or the previous link |
| + // in the label chain) is out of range. In that case the caller is responsible |
| + // for generating appropriate code. |
| + // Otherwise it returns false. |
| + // This function also checks wether veneers need to be emitted. |
| + bool NeedExtraInstructionsOrRegisterBranch(Label *label, |
| + ImmBranchType branch_type); |
| + |
| + private: |
| + // We generate a veneer for a branch if we reach within this distance of the |
| + // limit of the range. |
| + static const int kVeneerDistanceMargin = 2 * KB; |
|
ulan
2014/02/18 10:17:40
To check my understanding:
if there are no branch
Alexandre Rames
2014/02/18 11:59:20
Yes. This would fire a CHECK.
My take was that we
|
| + int unresolved_branches_first_limit() const { |
| + ASSERT(!unresolved_branches_.empty()); |
| + return unresolved_branches_.begin()->first; |
| + } |
| }; |
| @@ -2083,20 +2134,13 @@ class MacroAssembler : public Assembler { |
| // emitted is what you specified when creating the scope. |
| class InstructionAccurateScope BASE_EMBEDDED { |
| public: |
| - explicit InstructionAccurateScope(MacroAssembler* masm) |
| - : masm_(masm), size_(0) { |
| - masm_->StartBlockConstPool(); |
| -#ifdef DEBUG |
| - previous_allow_macro_instructions_ = masm_->allow_macro_instructions(); |
| - masm_->set_allow_macro_instructions(false); |
| -#endif |
| - } |
| - |
| - InstructionAccurateScope(MacroAssembler* masm, size_t count) |
| + InstructionAccurateScope(MacroAssembler* masm, size_t count = 0) |
| : masm_(masm), size_(count * kInstructionSize) { |
| masm_->StartBlockConstPool(); |
| #ifdef DEBUG |
| - masm_->bind(&start_); |
| + if (count != 0) { |
| + masm_->bind(&start_); |
| + } |
| previous_allow_macro_instructions_ = masm_->allow_macro_instructions(); |
| masm_->set_allow_macro_instructions(false); |
| #endif |