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

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: reset scratch register value when acquired 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
« no previous file with comments | « src/arm64/lithium-gap-resolver-arm64.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 15
22 // We use the MacroAssembler floating-point scratch register to break a cycle 16
23 // involving double values as the MacroAssembler will not need it for the 17 void DelayedGapMasm::EndDelayedUse() {
24 // operations performed by the gap resolver. 18 DelayedMasm::EndDelayedUse();
25 #define kSavedDoubleValue fp_scratch 19 if (scratch_register_used()) {
20 ASSERT(ScratchRegister().Is(root));
21 ASSERT(!pending());
22 InitializeRootRegister();
23 reset_scratch_register_used();
24 }
25 }
26 26
27 27
28 LGapResolver::LGapResolver(LCodeGen* owner) 28 LGapResolver::LGapResolver(LCodeGen* owner)
29 : cgen_(owner), moves_(32, owner->zone()), root_index_(0), in_cycle_(false), 29 : cgen_(owner), masm_(owner, owner->masm()), moves_(32, owner->zone()),
30 saved_destination_(NULL), need_to_restore_root_(false) { } 30 root_index_(0), in_cycle_(false), saved_destination_(NULL) {
31 }
31 32
32 33
33 #define __ ACCESS_MASM(cgen_->masm())
34
35 void LGapResolver::Resolve(LParallelMove* parallel_move) { 34 void LGapResolver::Resolve(LParallelMove* parallel_move) {
36 ASSERT(moves_.is_empty()); 35 ASSERT(moves_.is_empty());
36 ASSERT(!masm_.pending());
37 37
38 // Build up a worklist of moves. 38 // Build up a worklist of moves.
39 BuildInitialMoveList(parallel_move); 39 BuildInitialMoveList(parallel_move);
40 40
41 for (int i = 0; i < moves_.length(); ++i) { 41 for (int i = 0; i < moves_.length(); ++i) {
42 LMoveOperands move = moves_[i]; 42 LMoveOperands move = moves_[i];
43 43
44 // Skip constants to perform them last. They don't block other moves 44 // Skip constants to perform them last. They don't block other moves
45 // and skipping such moves with register destinations keeps those 45 // and skipping such moves with register destinations keeps those
46 // registers free for the whole algorithm. 46 // registers free for the whole algorithm.
47 if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { 47 if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
48 root_index_ = i; // Any cycle is found when we reach this move again. 48 root_index_ = i; // Any cycle is found when we reach this move again.
49 PerformMove(i); 49 PerformMove(i);
50 if (in_cycle_) RestoreValue(); 50 if (in_cycle_) RestoreValue();
51 } 51 }
52 } 52 }
53 53
54 // Perform the moves with constant sources. 54 // Perform the moves with constant sources.
55 for (int i = 0; i < moves_.length(); ++i) { 55 for (int i = 0; i < moves_.length(); ++i) {
56 LMoveOperands move = moves_[i]; 56 LMoveOperands move = moves_[i];
57 57
58 if (!move.IsEliminated()) { 58 if (!move.IsEliminated()) {
59 ASSERT(move.source()->IsConstantOperand()); 59 ASSERT(move.source()->IsConstantOperand());
60 EmitMove(i); 60 EmitMove(i);
61 } 61 }
62 } 62 }
63 63
64 if (need_to_restore_root_) { 64 __ EndDelayedUse();
65 ASSERT(kSavedValue.Is(root));
66 __ InitializeRootRegister();
67 need_to_restore_root_ = false;
68 }
69 65
70 moves_.Rewind(0); 66 moves_.Rewind(0);
71 } 67 }
72 68
73 69
74 void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { 70 void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
75 // Perform a linear sweep of the moves to add them to the initial list of 71 // 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 72 // moves to perform, ignoring any move that is redundant (the source is
77 // the same as the destination, the destination is ignored and 73 // the same as the destination, the destination is ignored and
78 // unallocated, or the move was already eliminated). 74 // unallocated, or the move was already eliminated).
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 } 141 }
146 } 142 }
147 #endif 143 #endif
148 } 144 }
149 145
150 146
151 void LGapResolver::BreakCycle(int index) { 147 void LGapResolver::BreakCycle(int index) {
152 ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source())); 148 ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
153 ASSERT(!in_cycle_); 149 ASSERT(!in_cycle_);
154 150
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 151 // 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 152 // destination. Then we mark this move as resolved so the cycle is
162 // broken and we can perform the other moves. 153 // broken and we can perform the other moves.
163 in_cycle_ = true; 154 in_cycle_ = true;
164 LOperand* source = moves_[index].source(); 155 LOperand* source = moves_[index].source();
165 saved_destination_ = moves_[index].destination(); 156 saved_destination_ = moves_[index].destination();
166 157
167 if (source->IsRegister()) { 158 if (source->IsRegister()) {
168 need_to_restore_root_ = true; 159 AcquireSavedValueRegister();
169 __ Mov(kSavedValue, cgen_->ToRegister(source)); 160 __ Mov(SavedValueRegister(), cgen_->ToRegister(source));
170 } else if (source->IsStackSlot()) { 161 } else if (source->IsStackSlot()) {
171 need_to_restore_root_ = true; 162 AcquireSavedValueRegister();
172 __ Ldr(kSavedValue, cgen_->ToMemOperand(source)); 163 __ Load(SavedValueRegister(), cgen_->ToMemOperand(source));
173 } else if (source->IsDoubleRegister()) { 164 } else if (source->IsDoubleRegister()) {
174 ASSERT(cgen_->masm()->FPTmpList()->IncludesAliasOf(kSavedDoubleValue)); 165 __ Fmov(SavedFPValueRegister(), cgen_->ToDoubleRegister(source));
175 cgen_->masm()->FPTmpList()->Remove(kSavedDoubleValue);
176 __ Fmov(kSavedDoubleValue, cgen_->ToDoubleRegister(source));
177 } else if (source->IsDoubleStackSlot()) { 166 } else if (source->IsDoubleStackSlot()) {
178 ASSERT(cgen_->masm()->FPTmpList()->IncludesAliasOf(kSavedDoubleValue)); 167 __ Load(SavedFPValueRegister(), cgen_->ToMemOperand(source));
179 cgen_->masm()->FPTmpList()->Remove(kSavedDoubleValue);
180 __ Ldr(kSavedDoubleValue, cgen_->ToMemOperand(source));
181 } else { 168 } else {
182 UNREACHABLE(); 169 UNREACHABLE();
183 } 170 }
184 171
185 // Mark this move as resolved. 172 // Mark this move as resolved.
186 // This move will be actually performed by moving the saved value to this 173 // This move will be actually performed by moving the saved value to this
187 // move's destination in LGapResolver::RestoreValue(). 174 // move's destination in LGapResolver::RestoreValue().
188 moves_[index].Eliminate(); 175 moves_[index].Eliminate();
189 } 176 }
190 177
191 178
192 void LGapResolver::RestoreValue() { 179 void LGapResolver::RestoreValue() {
193 ASSERT(in_cycle_); 180 ASSERT(in_cycle_);
194 ASSERT(saved_destination_ != NULL); 181 ASSERT(saved_destination_ != NULL);
195 182
196 if (saved_destination_->IsRegister()) { 183 if (saved_destination_->IsRegister()) {
197 __ Mov(cgen_->ToRegister(saved_destination_), kSavedValue); 184 __ Mov(cgen_->ToRegister(saved_destination_), SavedValueRegister());
185 ReleaseSavedValueRegister();
198 } else if (saved_destination_->IsStackSlot()) { 186 } else if (saved_destination_->IsStackSlot()) {
199 __ Str(kSavedValue, cgen_->ToMemOperand(saved_destination_)); 187 __ Store(SavedValueRegister(), cgen_->ToMemOperand(saved_destination_));
188 ReleaseSavedValueRegister();
200 } else if (saved_destination_->IsDoubleRegister()) { 189 } else if (saved_destination_->IsDoubleRegister()) {
201 __ Fmov(cgen_->ToDoubleRegister(saved_destination_), kSavedDoubleValue); 190 __ Fmov(cgen_->ToDoubleRegister(saved_destination_),
202 cgen_->masm()->FPTmpList()->Combine(kSavedDoubleValue); 191 SavedFPValueRegister());
203 } else if (saved_destination_->IsDoubleStackSlot()) { 192 } else if (saved_destination_->IsDoubleStackSlot()) {
204 __ Str(kSavedDoubleValue, cgen_->ToMemOperand(saved_destination_)); 193 __ Store(SavedFPValueRegister(), cgen_->ToMemOperand(saved_destination_));
205 cgen_->masm()->FPTmpList()->Combine(kSavedDoubleValue);
206 } else { 194 } else {
207 UNREACHABLE(); 195 UNREACHABLE();
208 } 196 }
209 197
210 in_cycle_ = false; 198 in_cycle_ = false;
211 saved_destination_ = NULL; 199 saved_destination_ = NULL;
212 } 200 }
213 201
214 202
215 void LGapResolver::EmitMove(int index) { 203 void LGapResolver::EmitMove(int index) {
216 LOperand* source = moves_[index].source(); 204 LOperand* source = moves_[index].source();
217 LOperand* destination = moves_[index].destination(); 205 LOperand* destination = moves_[index].destination();
218 206
219 // Dispatch on the source and destination operand kinds. Not all 207 // Dispatch on the source and destination operand kinds. Not all
220 // combinations are possible. 208 // combinations are possible.
221 209
222 if (source->IsRegister()) { 210 if (source->IsRegister()) {
223 Register source_register = cgen_->ToRegister(source); 211 Register source_register = cgen_->ToRegister(source);
224 if (destination->IsRegister()) { 212 if (destination->IsRegister()) {
225 __ Mov(cgen_->ToRegister(destination), source_register); 213 __ Mov(cgen_->ToRegister(destination), source_register);
226 } else { 214 } else {
227 ASSERT(destination->IsStackSlot()); 215 ASSERT(destination->IsStackSlot());
228 __ Str(source_register, cgen_->ToMemOperand(destination)); 216 __ Store(source_register, cgen_->ToMemOperand(destination));
229 } 217 }
230 218
231 } else if (source->IsStackSlot()) { 219 } else if (source->IsStackSlot()) {
232 MemOperand source_operand = cgen_->ToMemOperand(source); 220 MemOperand source_operand = cgen_->ToMemOperand(source);
233 if (destination->IsRegister()) { 221 if (destination->IsRegister()) {
234 __ Ldr(cgen_->ToRegister(destination), source_operand); 222 __ Load(cgen_->ToRegister(destination), source_operand);
235 } else { 223 } else {
236 ASSERT(destination->IsStackSlot()); 224 ASSERT(destination->IsStackSlot());
237 EmitStackSlotMove(index); 225 EmitStackSlotMove(index);
238 } 226 }
239 227
240 } else if (source->IsConstantOperand()) { 228 } else if (source->IsConstantOperand()) {
241 LConstantOperand* constant_source = LConstantOperand::cast(source); 229 LConstantOperand* constant_source = LConstantOperand::cast(source);
242 if (destination->IsRegister()) { 230 if (destination->IsRegister()) {
243 Register dst = cgen_->ToRegister(destination); 231 Register dst = cgen_->ToRegister(destination);
244 if (cgen_->IsSmi(constant_source)) { 232 if (cgen_->IsSmi(constant_source)) {
245 __ Mov(dst, cgen_->ToSmi(constant_source)); 233 __ Mov(dst, cgen_->ToSmi(constant_source));
246 } else if (cgen_->IsInteger32Constant(constant_source)) { 234 } else if (cgen_->IsInteger32Constant(constant_source)) {
247 __ Mov(dst, cgen_->ToInteger32(constant_source)); 235 __ Mov(dst, cgen_->ToInteger32(constant_source));
248 } else { 236 } else {
249 __ LoadObject(dst, cgen_->ToHandle(constant_source)); 237 __ LoadObject(dst, cgen_->ToHandle(constant_source));
250 } 238 }
251 } else if (destination->IsDoubleRegister()) { 239 } else if (destination->IsDoubleRegister()) {
252 DoubleRegister result = cgen_->ToDoubleRegister(destination); 240 DoubleRegister result = cgen_->ToDoubleRegister(destination);
253 __ Fmov(result, cgen_->ToDouble(constant_source)); 241 __ Fmov(result, cgen_->ToDouble(constant_source));
254 } else { 242 } else {
255 ASSERT(destination->IsStackSlot()); 243 ASSERT(destination->IsStackSlot());
256 ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone. 244 ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone.
257 need_to_restore_root_ = true;
258 if (cgen_->IsSmi(constant_source)) { 245 if (cgen_->IsSmi(constant_source)) {
259 __ Mov(kSavedValue, cgen_->ToSmi(constant_source)); 246 Smi* smi = cgen_->ToSmi(constant_source);
247 __ StoreConstant(reinterpret_cast<intptr_t>(smi),
248 cgen_->ToMemOperand(destination));
260 } else if (cgen_->IsInteger32Constant(constant_source)) { 249 } else if (cgen_->IsInteger32Constant(constant_source)) {
261 __ Mov(kSavedValue, cgen_->ToInteger32(constant_source)); 250 __ StoreConstant(cgen_->ToInteger32(constant_source),
251 cgen_->ToMemOperand(destination));
262 } else { 252 } else {
263 __ LoadObject(kSavedValue, cgen_->ToHandle(constant_source)); 253 Handle<Object> handle = cgen_->ToHandle(constant_source);
254 AllowDeferredHandleDereference smi_object_check;
255 if (handle->IsSmi()) {
256 Object* obj = *handle;
257 ASSERT(!obj->IsHeapObject());
258 __ StoreConstant(reinterpret_cast<intptr_t>(obj),
259 cgen_->ToMemOperand(destination));
260 } else {
261 AcquireSavedValueRegister();
262 __ LoadObject(SavedValueRegister(), handle);
263 __ Store(SavedValueRegister(), cgen_->ToMemOperand(destination));
264 ReleaseSavedValueRegister();
265 }
264 } 266 }
265 __ Str(kSavedValue, cgen_->ToMemOperand(destination));
266 } 267 }
267 268
268 } else if (source->IsDoubleRegister()) { 269 } else if (source->IsDoubleRegister()) {
269 DoubleRegister src = cgen_->ToDoubleRegister(source); 270 DoubleRegister src = cgen_->ToDoubleRegister(source);
270 if (destination->IsDoubleRegister()) { 271 if (destination->IsDoubleRegister()) {
271 __ Fmov(cgen_->ToDoubleRegister(destination), src); 272 __ Fmov(cgen_->ToDoubleRegister(destination), src);
272 } else { 273 } else {
273 ASSERT(destination->IsDoubleStackSlot()); 274 ASSERT(destination->IsDoubleStackSlot());
274 __ Str(src, cgen_->ToMemOperand(destination)); 275 __ Store(src, cgen_->ToMemOperand(destination));
275 } 276 }
276 277
277 } else if (source->IsDoubleStackSlot()) { 278 } else if (source->IsDoubleStackSlot()) {
278 MemOperand src = cgen_->ToMemOperand(source); 279 MemOperand src = cgen_->ToMemOperand(source);
279 if (destination->IsDoubleRegister()) { 280 if (destination->IsDoubleRegister()) {
280 __ Ldr(cgen_->ToDoubleRegister(destination), src); 281 __ Load(cgen_->ToDoubleRegister(destination), src);
281 } else { 282 } else {
282 ASSERT(destination->IsDoubleStackSlot()); 283 ASSERT(destination->IsDoubleStackSlot());
283 EmitStackSlotMove(index); 284 EmitStackSlotMove(index);
284 } 285 }
285 286
286 } else { 287 } else {
287 UNREACHABLE(); 288 UNREACHABLE();
288 } 289 }
289 290
290 // The move has been emitted, we can eliminate it. 291 // The move has been emitted, we can eliminate it.
291 moves_[index].Eliminate(); 292 moves_[index].Eliminate();
292 } 293 }
293 294
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 295 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm64/lithium-gap-resolver-arm64.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698