V8 Project
delayed-masm-arm64.h
Go to the documentation of this file.
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).
22  public:
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  }
36  DCHECK(!scratch_register_acquired_);
37  DCHECK(!scratch_register_used_);
38  DCHECK(!pending());
39  }
40  inline void EndDelayedUse();
41 
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.
53  EmitPending();
54  ResetSavedValue();
55 #ifdef DEBUG
56  DCHECK(!scratch_register_acquired_);
57  scratch_register_acquired_ = true;
58 #endif
59  }
61 #ifdef DEBUG
62  DCHECK(scratch_register_acquired_);
63  scratch_register_acquired_ = false;
64 #endif
65  }
66  bool pending() { return pending_ != kNone; }
67 
68  // Extra layer over the macro-assembler instructions (which emits the
69  // potential pending instruction).
70  inline void Mov(const Register& rd,
71  const Operand& operand,
73  inline void Fmov(FPRegister fd, FPRegister fn);
74  inline void Fmov(FPRegister fd, double imm);
75  inline void LoadObject(Register result, Handle<Object> object);
76  // Instructions which try to merge which the pending instructions.
77  void StackSlotMove(LOperand* src, LOperand* dst);
78  // StoreConstant can only be used if the scratch register is not acquired.
79  void StoreConstant(uint64_t value, const MemOperand& operand);
80  void Load(const CPURegister& rd, const MemOperand& operand);
81  void Store(const CPURegister& rd, const MemOperand& operand);
82  // Emit the potential pending instruction.
83  void EmitPending();
84  // Reset the pending state.
85  void ResetPending() {
86  pending_ = kNone;
87 #ifdef DEBUG
88  pending_register_ = no_reg;
89  MemOperand tmp;
90  pending_address_src_ = tmp;
91  pending_address_dst_ = tmp;
92  pending_value_ = 0;
93  pending_pc_ = 0;
94 #endif
95  }
97  masm_->InitializeRootRegister();
98  }
99 
100  private:
101  // Set the saved value and load the ScratchRegister with it.
102  void SetSavedValue(uint64_t saved_value) {
103  DCHECK(saved_value != 0);
104  if (saved_value_ != saved_value) {
105  masm_->Mov(ScratchRegister(), saved_value);
106  saved_value_ = saved_value;
107  }
108  }
109  // Reset the saved value (i.e. the value of ScratchRegister is no longer
110  // known).
112  saved_value_ = 0;
113  }
114 
115  LCodeGen* cgen_;
117 
118  // Register used to store a constant.
121 
122  // Sometimes we store or load two values in two contiguous stack slots.
123  // In this case, we try to use the ldp/stp instructions to reduce code size.
124  // To be able to do that, instead of generating directly the instructions,
125  // we register with the following fields that an instruction needs to be
126  // generated. Then with the next instruction, if the instruction is
127  // consistent with the pending one for stp/ldp we generate ldp/stp. Else,
128  // if they are not consistent, we generate the pending instruction and we
129  // register the new instruction (which becomes pending).
130 
131  // Enumeration of instructions which can be pending.
132  enum Pending {
135  kLoad, kStore,
136  kStackSlotMove
137  };
138  // The pending instruction.
140  // For kLoad, kStore: register which must be loaded/stored.
142  // For kLoad, kStackSlotMove: address of the load.
144  // For kStoreConstant, kStore, kStackSlotMove: address of the store.
146  // For kStoreConstant: value to be stored.
147  uint64_t pending_value_;
148  // Value held into the ScratchRegister if the saved_value_ is not 0.
149  // For 0, we use xzr.
150  uint64_t saved_value_;
151 #ifdef DEBUG
152  // Address where the pending instruction must be generated. It's only used to
153  // check that nothing else has been generated since we set the pending
154  // instruction.
155  int pending_pc_;
156  // If true, the scratch register has been acquired outside this class. The
157  // scratch register can no longer be used for constants.
158  bool scratch_register_acquired_;
159 #endif
160 };
161 
162 } } // namespace v8::internal
163 
164 #endif // V8_ARM64_DELAYED_MASM_ARM64_H_
#define BASE_EMBEDDED
Definition: allocation.h:45
void Store(const CPURegister &rd, const MemOperand &operand)
void Mov(const Register &rd, const Operand &operand, DiscardMoveMode discard_mode=kDontDiscardForSameWReg)
const Register & ScratchRegister()
void StoreConstant(uint64_t value, const MemOperand &operand)
DelayedMasm(LCodeGen *owner, MacroAssembler *masm, const Register &scratch_register)
bool IsScratchRegister(const CPURegister &reg)
void LoadObject(Register result, Handle< Object > object)
void Load(const CPURegister &rd, const MemOperand &operand)
void Fmov(FPRegister fd, double imm)
void Fmov(FPRegister fd, FPRegister fn)
void StackSlotMove(LOperand *src, LOperand *dst)
void SetSavedValue(uint64_t saved_value)
#define DCHECK(condition)
Definition: logging.h:205
const Register no_reg
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
bool Is(const CPURegister &other) const