Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef V8_ARM64_DELAYED_MASM_ARM64_H_ | |
| 6 #define V8_ARM64_DELAYED_MASM_ARM64_H_ | |
| 7 | |
| 8 #include "src/lithium.h" | |
| 9 | |
| 10 namespace v8 { | |
| 11 namespace internal { | |
| 12 | |
| 13 class LCodeGen; | |
| 14 | |
| 15 // This class delays the generation of some instructions. This way, we have a | |
| 16 // chance to merge two instructions in one (with load/store pair). | |
| 17 // Each instruction must either: | |
| 18 // - merge with the pending instruction and generate just one instruction. | |
| 19 // - emit the pending instruction and then generate the instruction (or set the | |
| 20 // pending instruction). | |
| 21 class DelayedMasm BASE_EMBEDDED { | |
| 22 public: | |
| 23 DelayedMasm(LCodeGen* owner, | |
| 24 MacroAssembler* masm, | |
| 25 const Register& scratch_register) | |
| 26 : cgen_(owner), masm_(masm), scratch_register_(scratch_register), | |
| 27 scratch_register_used_(false), pending_(kNone), saved_value_(0) { | |
| 28 #ifdef DEBUG | |
| 29 pending_register_ = no_reg; | |
| 30 pending_value_ = 0; | |
| 31 pending_pc_ = 0; | |
| 32 scratch_register_acquired_ = false; | |
| 33 #endif | |
| 34 } | |
| 35 ~DelayedMasm() { | |
| 36 ASSERT(!scratch_register_acquired_); | |
| 37 ASSERT(!scratch_register_used_); | |
| 38 ASSERT(!pending()); | |
| 39 } | |
| 40 inline void EndDelayedUse(); | |
| 41 | |
| 42 const Register& ScratchRegister() { | |
| 43 scratch_register_used_ = true; | |
| 44 return scratch_register_; | |
| 45 } | |
| 46 bool IsScratchRegister(const CPURegister& reg) { | |
| 47 return reg.Is(scratch_register_); | |
| 48 } | |
| 49 bool scratch_register_used() const { return scratch_register_used_; } | |
| 50 void reset_scratch_register_used() { scratch_register_used_ = false; } | |
| 51 // Acquire/Release scratch register for use outside this class. | |
| 52 void AcquireScratchRegister() { | |
| 53 #ifdef DEBUG | |
| 54 ASSERT(!scratch_register_acquired_); | |
| 55 scratch_register_acquired_ = true; | |
|
ulan
2014/06/10 08:54:40
Shouldn't we reset the saved value here since no l
vincent.belliard
2014/06/10 09:00:12
This function is only used in debug to ensure that
vincent.belliard
2014/06/12 12:57:57
Done.
| |
| 56 #endif | |
| 57 } | |
| 58 void ReleaseScratchRegister() { | |
| 59 #ifdef DEBUG | |
| 60 ASSERT(scratch_register_acquired_); | |
| 61 scratch_register_acquired_ = false; | |
| 62 #endif | |
| 63 } | |
| 64 bool pending() { return pending_ != kNone; } | |
| 65 | |
| 66 // Extra layer over the macro-assembler instructions (which emits the | |
| 67 // potential pending instruction). | |
| 68 inline void Mov(const Register& rd, | |
| 69 const Operand& operand, | |
| 70 DiscardMoveMode discard_mode = kDontDiscardForSameWReg); | |
| 71 inline void Fmov(FPRegister fd, FPRegister fn); | |
| 72 inline void Fmov(FPRegister fd, double imm); | |
| 73 inline void LoadObject(Register result, Handle<Object> object); | |
| 74 // Instructions which try to merge which the pending instructions. | |
| 75 void StackSlotMove(LOperand* src, LOperand* dst); | |
| 76 // StoreConstant can only be used if the scratch register is not acquired. | |
| 77 void StoreConstant(uint64_t value, const MemOperand& operand); | |
| 78 void Load(const CPURegister& rd, const MemOperand& operand); | |
| 79 void Store(const CPURegister& rd, const MemOperand& operand); | |
| 80 // Emit the potential pending instruction. | |
| 81 void EmitPending(); | |
| 82 // Reset the pending state. | |
| 83 void ResetPending() { | |
| 84 pending_ = kNone; | |
| 85 #ifdef DEBUG | |
| 86 pending_register_ = no_reg; | |
| 87 MemOperand tmp; | |
| 88 pending_address_src_ = tmp; | |
| 89 pending_address_dst_ = tmp; | |
| 90 pending_value_ = 0; | |
| 91 pending_pc_ = 0; | |
| 92 #endif | |
| 93 } | |
| 94 void InitializeRootRegister() { | |
| 95 masm_->InitializeRootRegister(); | |
| 96 } | |
| 97 | |
| 98 private: | |
| 99 // Set the saved value and load the ScratchRegister with it. | |
| 100 void SetSavedValue(uint64_t saved_value) { | |
| 101 ASSERT(saved_value != 0); | |
| 102 if (saved_value_ != saved_value) { | |
| 103 masm_->Mov(ScratchRegister(), saved_value); | |
| 104 saved_value_ = saved_value; | |
| 105 } | |
| 106 } | |
| 107 // Reset the saved value (i.e. the value of ScratchRegister is no longer | |
| 108 // known). | |
| 109 void ResetSavedValue() { | |
| 110 saved_value_ = 0; | |
| 111 } | |
| 112 | |
| 113 LCodeGen* cgen_; | |
| 114 MacroAssembler* masm_; | |
| 115 | |
| 116 // Register used to store a constant. | |
| 117 Register scratch_register_; | |
| 118 bool scratch_register_used_; | |
| 119 | |
| 120 // Sometimes we store or load two values in two contiguous stack slots. | |
| 121 // In this case, we try to use the ldp/stp instructions to reduce code size. | |
| 122 // To be able to do that, instead of generating directly the instructions, | |
| 123 // we register with the following fields that an instruction needs to be | |
| 124 // generated. Then with the next instruction, if the instruction is | |
| 125 // consistent with the pending one for stp/ldp we generate ldp/stp. Else, | |
| 126 // if they are not consistent, we generate the pending instruction and we | |
| 127 // register the new instruction (which becomes pending). | |
| 128 | |
| 129 // Enumeration of instructions which can be pending. | |
| 130 enum Pending { | |
| 131 kNone, | |
| 132 kStoreConstant, | |
| 133 kLoad, kStore, | |
| 134 kStackSlotMove | |
| 135 }; | |
| 136 // The pending instruction. | |
| 137 Pending pending_; | |
| 138 // For kLoad, kStore: register which must be loaded/stored. | |
| 139 CPURegister pending_register_; | |
| 140 // For kLoad, kStackSlotMove: address of the load. | |
| 141 MemOperand pending_address_src_; | |
| 142 // For kStoreConstant, kStore, kStackSlotMove: address of the store. | |
| 143 MemOperand pending_address_dst_; | |
| 144 // For kStoreConstant: value to be stored. | |
| 145 uint64_t pending_value_; | |
| 146 // Value held into the ScratchRegister if the saved_value_ is not 0. | |
| 147 // For 0, we use xzr. | |
| 148 uint64_t saved_value_; | |
| 149 #ifdef DEBUG | |
| 150 // Address where the pending instruction must be generated. It's only used to | |
| 151 // check that nothing else has been generated since we set the pending | |
| 152 // instruction. | |
| 153 int pending_pc_; | |
| 154 // If true, the scratch register has been acquired outside this class. The | |
| 155 // scratch register can no longer be used for constants. | |
| 156 bool scratch_register_acquired_; | |
| 157 #endif | |
| 158 }; | |
| 159 | |
| 160 } } // namespace v8::internal | |
| 161 | |
| 162 #endif // V8_ARM64_DELAYED_MASM_ARM64_H_ | |
| OLD | NEW |