Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: src/arm64/lithium-gap-resolver-arm64.cc

Issue 268673003: ARM64: Optimize generated code for gaps (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: use new includes norm Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/arm64/delayed-masm-arm64-inl.h"
7 #include "src/arm64/lithium-gap-resolver-arm64.h" 8 #include "src/arm64/lithium-gap-resolver-arm64.h"
8 #include "src/arm64/lithium-codegen-arm64.h" 9 #include "src/arm64/lithium-codegen-arm64.h"
9 10
10 namespace v8 { 11 namespace v8 {
11 namespace internal { 12 namespace internal {
12 13
13 // We use the root register to spill a value while breaking a cycle in parallel 14 #define __ ACCESS_MASM((&masm_))
14 // moves. We don't need access to roots while resolving the move list and using
15 // the root register has two advantages:
16 // - It is not in crankshaft allocatable registers list, so it can't interfere
17 // with any of the moves we are resolving.
18 // - We don't need to push it on the stack, as we can reload it with its value
19 // once we have resolved a cycle.
20 #define kSavedValue root
21
22 // We use the MacroAssembler floating-point scratch register to break a cycle
23 // involving double values as the MacroAssembler will not need it for the
24 // operations performed by the gap resolver.
25 #define kSavedDoubleValue fp_scratch
26 15
27 16
28 LGapResolver::LGapResolver(LCodeGen* owner) 17 LGapResolver::LGapResolver(LCodeGen* owner)
29 : cgen_(owner), moves_(32, owner->zone()), root_index_(0), in_cycle_(false), 18 : cgen_(owner), masm_(owner, owner->masm()), moves_(32, owner->zone()),
30 saved_destination_(NULL), need_to_restore_root_(false) { } 19 root_index_(0), in_cycle_(false), saved_destination_(NULL) {
20 }
31 21
32 22
33 #define __ ACCESS_MASM(cgen_->masm())
34
35 void LGapResolver::Resolve(LParallelMove* parallel_move) { 23 void LGapResolver::Resolve(LParallelMove* parallel_move) {
36 ASSERT(moves_.is_empty()); 24 ASSERT(moves_.is_empty());
25 ASSERT(!masm_.pending());
37 26
38 // Build up a worklist of moves. 27 // Build up a worklist of moves.
39 BuildInitialMoveList(parallel_move); 28 BuildInitialMoveList(parallel_move);
40 29
41 for (int i = 0; i < moves_.length(); ++i) { 30 for (int i = 0; i < moves_.length(); ++i) {
42 LMoveOperands move = moves_[i]; 31 LMoveOperands move = moves_[i];
43 32
44 // Skip constants to perform them last. They don't block other moves 33 // Skip constants to perform them last. They don't block other moves
45 // and skipping such moves with register destinations keeps those 34 // and skipping such moves with register destinations keeps those
46 // registers free for the whole algorithm. 35 // registers free for the whole algorithm.
47 if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { 36 if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
48 root_index_ = i; // Any cycle is found when we reach this move again. 37 root_index_ = i; // Any cycle is found when we reach this move again.
49 PerformMove(i); 38 PerformMove(i);
50 if (in_cycle_) RestoreValue(); 39 if (in_cycle_) RestoreValue();
51 } 40 }
52 } 41 }
53 42
54 // Perform the moves with constant sources. 43 // Perform the moves with constant sources.
55 for (int i = 0; i < moves_.length(); ++i) { 44 for (int i = 0; i < moves_.length(); ++i) {
56 LMoveOperands move = moves_[i]; 45 LMoveOperands move = moves_[i];
57 46
58 if (!move.IsEliminated()) { 47 if (!move.IsEliminated()) {
59 ASSERT(move.source()->IsConstantOperand()); 48 ASSERT(move.source()->IsConstantOperand());
60 EmitMove(i); 49 EmitMove(i);
61 } 50 }
62 } 51 }
63 52
64 if (need_to_restore_root_) { 53 __ EndDelayedUse();
65 ASSERT(kSavedValue.Is(root));
66 __ InitializeRootRegister();
67 need_to_restore_root_ = false;
68 }
69 54
70 moves_.Rewind(0); 55 moves_.Rewind(0);
71 } 56 }
72 57
73 58
74 void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { 59 void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
75 // Perform a linear sweep of the moves to add them to the initial list of 60 // Perform a linear sweep of the moves to add them to the initial list of
76 // moves to perform, ignoring any move that is redundant (the source is 61 // moves to perform, ignoring any move that is redundant (the source is
77 // the same as the destination, the destination is ignored and 62 // the same as the destination, the destination is ignored and
78 // unallocated, or the move was already eliminated). 63 // unallocated, or the move was already eliminated).
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 } 130 }
146 } 131 }
147 #endif 132 #endif
148 } 133 }
149 134
150 135
151 void LGapResolver::BreakCycle(int index) { 136 void LGapResolver::BreakCycle(int index) {
152 ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source())); 137 ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
153 ASSERT(!in_cycle_); 138 ASSERT(!in_cycle_);
154 139
155 // We use registers which are not allocatable by crankshaft to break the cycle
156 // to be sure they don't interfere with the moves we are resolving.
157 ASSERT(!kSavedValue.IsAllocatable());
158 ASSERT(!kSavedDoubleValue.IsAllocatable());
159
160 // We save in a register the source of that move and we remember its 140 // We save in a register the source of that move and we remember its
161 // destination. Then we mark this move as resolved so the cycle is 141 // destination. Then we mark this move as resolved so the cycle is
162 // broken and we can perform the other moves. 142 // broken and we can perform the other moves.
163 in_cycle_ = true; 143 in_cycle_ = true;
164 LOperand* source = moves_[index].source(); 144 LOperand* source = moves_[index].source();
165 saved_destination_ = moves_[index].destination(); 145 saved_destination_ = moves_[index].destination();
166 146
167 if (source->IsRegister()) { 147 if (source->IsRegister()) {
168 need_to_restore_root_ = true; 148 __ Mov(SavedValueRegister(), cgen_->ToRegister(source));
169 __ Mov(kSavedValue, cgen_->ToRegister(source));
170 } else if (source->IsStackSlot()) { 149 } else if (source->IsStackSlot()) {
171 need_to_restore_root_ = true; 150 __ Load(SavedValueRegister(), cgen_->ToMemOperand(source));
172 __ Ldr(kSavedValue, cgen_->ToMemOperand(source));
173 } else if (source->IsDoubleRegister()) { 151 } else if (source->IsDoubleRegister()) {
174 ASSERT(cgen_->masm()->FPTmpList()->IncludesAliasOf(kSavedDoubleValue)); 152 __ Fmov(SavedFPValueRegister(), cgen_->ToDoubleRegister(source));
175 cgen_->masm()->FPTmpList()->Remove(kSavedDoubleValue);
176 __ Fmov(kSavedDoubleValue, cgen_->ToDoubleRegister(source));
177 } else if (source->IsDoubleStackSlot()) { 153 } else if (source->IsDoubleStackSlot()) {
178 ASSERT(cgen_->masm()->FPTmpList()->IncludesAliasOf(kSavedDoubleValue)); 154 __ Load(SavedFPValueRegister(), cgen_->ToMemOperand(source));
179 cgen_->masm()->FPTmpList()->Remove(kSavedDoubleValue);
180 __ Ldr(kSavedDoubleValue, cgen_->ToMemOperand(source));
181 } else { 155 } else {
182 UNREACHABLE(); 156 UNREACHABLE();
183 } 157 }
184 158
185 // Mark this move as resolved. 159 // Mark this move as resolved.
186 // This move will be actually performed by moving the saved value to this 160 // This move will be actually performed by moving the saved value to this
187 // move's destination in LGapResolver::RestoreValue(). 161 // move's destination in LGapResolver::RestoreValue().
188 moves_[index].Eliminate(); 162 moves_[index].Eliminate();
189 } 163 }
190 164
191 165
192 void LGapResolver::RestoreValue() { 166 void LGapResolver::RestoreValue() {
193 ASSERT(in_cycle_); 167 ASSERT(in_cycle_);
194 ASSERT(saved_destination_ != NULL); 168 ASSERT(saved_destination_ != NULL);
195 169
196 if (saved_destination_->IsRegister()) { 170 if (saved_destination_->IsRegister()) {
197 __ Mov(cgen_->ToRegister(saved_destination_), kSavedValue); 171 __ Mov(cgen_->ToRegister(saved_destination_), SavedValueRegister());
198 } else if (saved_destination_->IsStackSlot()) { 172 } else if (saved_destination_->IsStackSlot()) {
199 __ Str(kSavedValue, cgen_->ToMemOperand(saved_destination_)); 173 __ Store(SavedValueRegister(), cgen_->ToMemOperand(saved_destination_));
200 } else if (saved_destination_->IsDoubleRegister()) { 174 } else if (saved_destination_->IsDoubleRegister()) {
201 __ Fmov(cgen_->ToDoubleRegister(saved_destination_), kSavedDoubleValue); 175 __ Fmov(cgen_->ToDoubleRegister(saved_destination_),
202 cgen_->masm()->FPTmpList()->Combine(kSavedDoubleValue); 176 SavedFPValueRegister());
203 } else if (saved_destination_->IsDoubleStackSlot()) { 177 } else if (saved_destination_->IsDoubleStackSlot()) {
204 __ Str(kSavedDoubleValue, cgen_->ToMemOperand(saved_destination_)); 178 __ Store(SavedFPValueRegister(), cgen_->ToMemOperand(saved_destination_));
205 cgen_->masm()->FPTmpList()->Combine(kSavedDoubleValue);
206 } else { 179 } else {
207 UNREACHABLE(); 180 UNREACHABLE();
208 } 181 }
209 182
210 in_cycle_ = false; 183 in_cycle_ = false;
211 saved_destination_ = NULL; 184 saved_destination_ = NULL;
212 } 185 }
213 186
214 187
215 void LGapResolver::EmitMove(int index) { 188 void LGapResolver::EmitMove(int index) {
216 LOperand* source = moves_[index].source(); 189 LOperand* source = moves_[index].source();
217 LOperand* destination = moves_[index].destination(); 190 LOperand* destination = moves_[index].destination();
218 191
219 // Dispatch on the source and destination operand kinds. Not all 192 // Dispatch on the source and destination operand kinds. Not all
220 // combinations are possible. 193 // combinations are possible.
221 194
222 if (source->IsRegister()) { 195 if (source->IsRegister()) {
223 Register source_register = cgen_->ToRegister(source); 196 Register source_register = cgen_->ToRegister(source);
224 if (destination->IsRegister()) { 197 if (destination->IsRegister()) {
225 __ Mov(cgen_->ToRegister(destination), source_register); 198 __ Mov(cgen_->ToRegister(destination), source_register);
226 } else { 199 } else {
227 ASSERT(destination->IsStackSlot()); 200 ASSERT(destination->IsStackSlot());
228 __ Str(source_register, cgen_->ToMemOperand(destination)); 201 __ Store(source_register, cgen_->ToMemOperand(destination));
229 } 202 }
230 203
231 } else if (source->IsStackSlot()) { 204 } else if (source->IsStackSlot()) {
232 MemOperand source_operand = cgen_->ToMemOperand(source); 205 MemOperand source_operand = cgen_->ToMemOperand(source);
233 if (destination->IsRegister()) { 206 if (destination->IsRegister()) {
234 __ Ldr(cgen_->ToRegister(destination), source_operand); 207 __ Load(cgen_->ToRegister(destination), source_operand);
235 } else { 208 } else {
236 ASSERT(destination->IsStackSlot()); 209 ASSERT(destination->IsStackSlot());
237 EmitStackSlotMove(index); 210 EmitStackSlotMove(index);
238 } 211 }
239 212
240 } else if (source->IsConstantOperand()) { 213 } else if (source->IsConstantOperand()) {
241 LConstantOperand* constant_source = LConstantOperand::cast(source); 214 LConstantOperand* constant_source = LConstantOperand::cast(source);
242 if (destination->IsRegister()) { 215 if (destination->IsRegister()) {
243 Register dst = cgen_->ToRegister(destination); 216 Register dst = cgen_->ToRegister(destination);
244 if (cgen_->IsSmi(constant_source)) { 217 if (cgen_->IsSmi(constant_source)) {
245 __ Mov(dst, cgen_->ToSmi(constant_source)); 218 __ Mov(dst, cgen_->ToSmi(constant_source));
246 } else if (cgen_->IsInteger32Constant(constant_source)) { 219 } else if (cgen_->IsInteger32Constant(constant_source)) {
247 __ Mov(dst, cgen_->ToInteger32(constant_source)); 220 __ Mov(dst, cgen_->ToInteger32(constant_source));
248 } else { 221 } else {
249 __ LoadObject(dst, cgen_->ToHandle(constant_source)); 222 __ LoadObject(dst, cgen_->ToHandle(constant_source));
250 } 223 }
251 } else if (destination->IsDoubleRegister()) { 224 } else if (destination->IsDoubleRegister()) {
252 DoubleRegister result = cgen_->ToDoubleRegister(destination); 225 DoubleRegister result = cgen_->ToDoubleRegister(destination);
253 __ Fmov(result, cgen_->ToDouble(constant_source)); 226 __ Fmov(result, cgen_->ToDouble(constant_source));
254 } else { 227 } else {
255 ASSERT(destination->IsStackSlot()); 228 ASSERT(destination->IsStackSlot());
256 ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone. 229 ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone.
257 need_to_restore_root_ = true;
258 if (cgen_->IsSmi(constant_source)) { 230 if (cgen_->IsSmi(constant_source)) {
259 __ Mov(kSavedValue, cgen_->ToSmi(constant_source)); 231 Smi* smi = cgen_->ToSmi(constant_source);
232 __ StoreConstant(reinterpret_cast<intptr_t>(smi),
233 cgen_->ToMemOperand(destination));
260 } else if (cgen_->IsInteger32Constant(constant_source)) { 234 } else if (cgen_->IsInteger32Constant(constant_source)) {
261 __ Mov(kSavedValue, cgen_->ToInteger32(constant_source)); 235 __ StoreConstant(cgen_->ToInteger32(constant_source),
236 cgen_->ToMemOperand(destination));
262 } else { 237 } else {
263 __ LoadObject(kSavedValue, cgen_->ToHandle(constant_source)); 238 Handle<Object> handle = cgen_->ToHandle(constant_source);
239 AllowDeferredHandleDereference smi_object_check;
240 if (handle->IsSmi()) {
241 Object* obj = *handle;
242 ASSERT(!obj->IsHeapObject());
243 __ StoreConstant(reinterpret_cast<intptr_t>(obj),
244 cgen_->ToMemOperand(destination));
245 } else {
246 __ LoadObject(SavedValueRegister(), handle);
247 __ Store(SavedValueRegister(), cgen_->ToMemOperand(destination));
248 }
264 } 249 }
265 __ Str(kSavedValue, cgen_->ToMemOperand(destination));
266 } 250 }
267 251
268 } else if (source->IsDoubleRegister()) { 252 } else if (source->IsDoubleRegister()) {
269 DoubleRegister src = cgen_->ToDoubleRegister(source); 253 DoubleRegister src = cgen_->ToDoubleRegister(source);
270 if (destination->IsDoubleRegister()) { 254 if (destination->IsDoubleRegister()) {
271 __ Fmov(cgen_->ToDoubleRegister(destination), src); 255 __ Fmov(cgen_->ToDoubleRegister(destination), src);
272 } else { 256 } else {
273 ASSERT(destination->IsDoubleStackSlot()); 257 ASSERT(destination->IsDoubleStackSlot());
274 __ Str(src, cgen_->ToMemOperand(destination)); 258 __ Store(src, cgen_->ToMemOperand(destination));
275 } 259 }
276 260
277 } else if (source->IsDoubleStackSlot()) { 261 } else if (source->IsDoubleStackSlot()) {
278 MemOperand src = cgen_->ToMemOperand(source); 262 MemOperand src = cgen_->ToMemOperand(source);
279 if (destination->IsDoubleRegister()) { 263 if (destination->IsDoubleRegister()) {
280 __ Ldr(cgen_->ToDoubleRegister(destination), src); 264 __ Load(cgen_->ToDoubleRegister(destination), src);
281 } else { 265 } else {
282 ASSERT(destination->IsDoubleStackSlot()); 266 ASSERT(destination->IsDoubleStackSlot());
283 EmitStackSlotMove(index); 267 EmitStackSlotMove(index);
284 } 268 }
285 269
286 } else { 270 } else {
287 UNREACHABLE(); 271 UNREACHABLE();
288 } 272 }
289 273
290 // The move has been emitted, we can eliminate it. 274 // The move has been emitted, we can eliminate it.
291 moves_[index].Eliminate(); 275 moves_[index].Eliminate();
292 } 276 }
293 277
294
295 void LGapResolver::EmitStackSlotMove(int index) {
296 // We need a temp register to perform a stack slot to stack slot move, and
297 // the register must not be involved in breaking cycles.
298
299 // Use the Crankshaft double scratch register as the temporary.
300 DoubleRegister temp = crankshaft_fp_scratch;
301
302 LOperand* src = moves_[index].source();
303 LOperand* dst = moves_[index].destination();
304
305 ASSERT(src->IsStackSlot());
306 ASSERT(dst->IsStackSlot());
307 __ Ldr(temp, cgen_->ToMemOperand(src));
308 __ Str(temp, cgen_->ToMemOperand(dst));
309 }
310
311 } } // namespace v8::internal 278 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698