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 |