OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/x64/lithium-codegen-x64.h" | 9 #include "src/x64/lithium-codegen-x64.h" |
10 #include "src/x64/lithium-gap-resolver-x64.h" | 10 #include "src/x64/lithium-gap-resolver-x64.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 LGapResolver::LGapResolver(LCodeGen* owner) | 15 LGapResolver::LGapResolver(LCodeGen* owner) |
16 : cgen_(owner), moves_(32, owner->zone()) {} | 16 : cgen_(owner), moves_(32, owner->zone()) {} |
17 | 17 |
18 | 18 |
19 void LGapResolver::Resolve(LParallelMove* parallel_move) { | 19 void LGapResolver::Resolve(LParallelMove* parallel_move) { |
20 ASSERT(moves_.is_empty()); | 20 DCHECK(moves_.is_empty()); |
21 // Build up a worklist of moves. | 21 // Build up a worklist of moves. |
22 BuildInitialMoveList(parallel_move); | 22 BuildInitialMoveList(parallel_move); |
23 | 23 |
24 for (int i = 0; i < moves_.length(); ++i) { | 24 for (int i = 0; i < moves_.length(); ++i) { |
25 LMoveOperands move = moves_[i]; | 25 LMoveOperands move = moves_[i]; |
26 // Skip constants to perform them last. They don't block other moves | 26 // Skip constants to perform them last. They don't block other moves |
27 // and skipping such moves with register destinations keeps those | 27 // and skipping such moves with register destinations keeps those |
28 // registers free for the whole algorithm. | 28 // registers free for the whole algorithm. |
29 if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { | 29 if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { |
30 PerformMove(i); | 30 PerformMove(i); |
31 } | 31 } |
32 } | 32 } |
33 | 33 |
34 // Perform the moves with constant sources. | 34 // Perform the moves with constant sources. |
35 for (int i = 0; i < moves_.length(); ++i) { | 35 for (int i = 0; i < moves_.length(); ++i) { |
36 if (!moves_[i].IsEliminated()) { | 36 if (!moves_[i].IsEliminated()) { |
37 ASSERT(moves_[i].source()->IsConstantOperand()); | 37 DCHECK(moves_[i].source()->IsConstantOperand()); |
38 EmitMove(i); | 38 EmitMove(i); |
39 } | 39 } |
40 } | 40 } |
41 | 41 |
42 moves_.Rewind(0); | 42 moves_.Rewind(0); |
43 } | 43 } |
44 | 44 |
45 | 45 |
46 void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { | 46 void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { |
47 // Perform a linear sweep of the moves to add them to the initial list of | 47 // Perform a linear sweep of the moves to add them to the initial list of |
(...skipping 10 matching lines...) Expand all Loading... |
58 | 58 |
59 | 59 |
60 void LGapResolver::PerformMove(int index) { | 60 void LGapResolver::PerformMove(int index) { |
61 // Each call to this function performs a move and deletes it from the move | 61 // Each call to this function performs a move and deletes it from the move |
62 // graph. We first recursively perform any move blocking this one. We | 62 // graph. We first recursively perform any move blocking this one. We |
63 // mark a move as "pending" on entry to PerformMove in order to detect | 63 // mark a move as "pending" on entry to PerformMove in order to detect |
64 // cycles in the move graph. We use operand swaps to resolve cycles, | 64 // cycles in the move graph. We use operand swaps to resolve cycles, |
65 // which means that a call to PerformMove could change any source operand | 65 // which means that a call to PerformMove could change any source operand |
66 // in the move graph. | 66 // in the move graph. |
67 | 67 |
68 ASSERT(!moves_[index].IsPending()); | 68 DCHECK(!moves_[index].IsPending()); |
69 ASSERT(!moves_[index].IsRedundant()); | 69 DCHECK(!moves_[index].IsRedundant()); |
70 | 70 |
71 // Clear this move's destination to indicate a pending move. The actual | 71 // Clear this move's destination to indicate a pending move. The actual |
72 // destination is saved in a stack-allocated local. Recursion may allow | 72 // destination is saved in a stack-allocated local. Recursion may allow |
73 // multiple moves to be pending. | 73 // multiple moves to be pending. |
74 ASSERT(moves_[index].source() != NULL); // Or else it will look eliminated. | 74 DCHECK(moves_[index].source() != NULL); // Or else it will look eliminated. |
75 LOperand* destination = moves_[index].destination(); | 75 LOperand* destination = moves_[index].destination(); |
76 moves_[index].set_destination(NULL); | 76 moves_[index].set_destination(NULL); |
77 | 77 |
78 // Perform a depth-first traversal of the move graph to resolve | 78 // Perform a depth-first traversal of the move graph to resolve |
79 // dependencies. Any unperformed, unpending move with a source the same | 79 // dependencies. Any unperformed, unpending move with a source the same |
80 // as this one's destination blocks this one so recursively perform all | 80 // as this one's destination blocks this one so recursively perform all |
81 // such moves. | 81 // such moves. |
82 for (int i = 0; i < moves_.length(); ++i) { | 82 for (int i = 0; i < moves_.length(); ++i) { |
83 LMoveOperands other_move = moves_[i]; | 83 LMoveOperands other_move = moves_[i]; |
84 if (other_move.Blocks(destination) && !other_move.IsPending()) { | 84 if (other_move.Blocks(destination) && !other_move.IsPending()) { |
(...skipping 20 matching lines...) Expand all Loading... |
105 moves_[index].Eliminate(); | 105 moves_[index].Eliminate(); |
106 return; | 106 return; |
107 } | 107 } |
108 | 108 |
109 // The move may be blocked on a (at most one) pending move, in which case | 109 // The move may be blocked on a (at most one) pending move, in which case |
110 // we have a cycle. Search for such a blocking move and perform a swap to | 110 // we have a cycle. Search for such a blocking move and perform a swap to |
111 // resolve it. | 111 // resolve it. |
112 for (int i = 0; i < moves_.length(); ++i) { | 112 for (int i = 0; i < moves_.length(); ++i) { |
113 LMoveOperands other_move = moves_[i]; | 113 LMoveOperands other_move = moves_[i]; |
114 if (other_move.Blocks(destination)) { | 114 if (other_move.Blocks(destination)) { |
115 ASSERT(other_move.IsPending()); | 115 DCHECK(other_move.IsPending()); |
116 EmitSwap(index); | 116 EmitSwap(index); |
117 return; | 117 return; |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 // This move is not blocked. | 121 // This move is not blocked. |
122 EmitMove(index); | 122 EmitMove(index); |
123 } | 123 } |
124 | 124 |
125 | 125 |
126 void LGapResolver::Verify() { | 126 void LGapResolver::Verify() { |
127 #ifdef ENABLE_SLOW_ASSERTS | 127 #ifdef ENABLE_SLOW_DCHECKS |
128 // No operand should be the destination for more than one move. | 128 // No operand should be the destination for more than one move. |
129 for (int i = 0; i < moves_.length(); ++i) { | 129 for (int i = 0; i < moves_.length(); ++i) { |
130 LOperand* destination = moves_[i].destination(); | 130 LOperand* destination = moves_[i].destination(); |
131 for (int j = i + 1; j < moves_.length(); ++j) { | 131 for (int j = i + 1; j < moves_.length(); ++j) { |
132 SLOW_ASSERT(!destination->Equals(moves_[j].destination())); | 132 SLOW_DCHECK(!destination->Equals(moves_[j].destination())); |
133 } | 133 } |
134 } | 134 } |
135 #endif | 135 #endif |
136 } | 136 } |
137 | 137 |
138 | 138 |
139 #define __ ACCESS_MASM(cgen_->masm()) | 139 #define __ ACCESS_MASM(cgen_->masm()) |
140 | 140 |
141 | 141 |
142 void LGapResolver::EmitMove(int index) { | 142 void LGapResolver::EmitMove(int index) { |
143 LOperand* source = moves_[index].source(); | 143 LOperand* source = moves_[index].source(); |
144 LOperand* destination = moves_[index].destination(); | 144 LOperand* destination = moves_[index].destination(); |
145 | 145 |
146 // Dispatch on the source and destination operand kinds. Not all | 146 // Dispatch on the source and destination operand kinds. Not all |
147 // combinations are possible. | 147 // combinations are possible. |
148 if (source->IsRegister()) { | 148 if (source->IsRegister()) { |
149 Register src = cgen_->ToRegister(source); | 149 Register src = cgen_->ToRegister(source); |
150 if (destination->IsRegister()) { | 150 if (destination->IsRegister()) { |
151 Register dst = cgen_->ToRegister(destination); | 151 Register dst = cgen_->ToRegister(destination); |
152 __ movp(dst, src); | 152 __ movp(dst, src); |
153 } else { | 153 } else { |
154 ASSERT(destination->IsStackSlot()); | 154 DCHECK(destination->IsStackSlot()); |
155 Operand dst = cgen_->ToOperand(destination); | 155 Operand dst = cgen_->ToOperand(destination); |
156 __ movp(dst, src); | 156 __ movp(dst, src); |
157 } | 157 } |
158 | 158 |
159 } else if (source->IsStackSlot()) { | 159 } else if (source->IsStackSlot()) { |
160 Operand src = cgen_->ToOperand(source); | 160 Operand src = cgen_->ToOperand(source); |
161 if (destination->IsRegister()) { | 161 if (destination->IsRegister()) { |
162 Register dst = cgen_->ToRegister(destination); | 162 Register dst = cgen_->ToRegister(destination); |
163 __ movp(dst, src); | 163 __ movp(dst, src); |
164 } else { | 164 } else { |
165 ASSERT(destination->IsStackSlot()); | 165 DCHECK(destination->IsStackSlot()); |
166 Operand dst = cgen_->ToOperand(destination); | 166 Operand dst = cgen_->ToOperand(destination); |
167 __ movp(kScratchRegister, src); | 167 __ movp(kScratchRegister, src); |
168 __ movp(dst, kScratchRegister); | 168 __ movp(dst, kScratchRegister); |
169 } | 169 } |
170 | 170 |
171 } else if (source->IsConstantOperand()) { | 171 } else if (source->IsConstantOperand()) { |
172 LConstantOperand* constant_source = LConstantOperand::cast(source); | 172 LConstantOperand* constant_source = LConstantOperand::cast(source); |
173 if (destination->IsRegister()) { | 173 if (destination->IsRegister()) { |
174 Register dst = cgen_->ToRegister(destination); | 174 Register dst = cgen_->ToRegister(destination); |
175 if (cgen_->IsSmiConstant(constant_source)) { | 175 if (cgen_->IsSmiConstant(constant_source)) { |
(...skipping 14 matching lines...) Expand all Loading... |
190 double v = cgen_->ToDouble(constant_source); | 190 double v = cgen_->ToDouble(constant_source); |
191 uint64_t int_val = BitCast<uint64_t, double>(v); | 191 uint64_t int_val = BitCast<uint64_t, double>(v); |
192 XMMRegister dst = cgen_->ToDoubleRegister(destination); | 192 XMMRegister dst = cgen_->ToDoubleRegister(destination); |
193 if (int_val == 0) { | 193 if (int_val == 0) { |
194 __ xorps(dst, dst); | 194 __ xorps(dst, dst); |
195 } else { | 195 } else { |
196 __ Set(kScratchRegister, int_val); | 196 __ Set(kScratchRegister, int_val); |
197 __ movq(dst, kScratchRegister); | 197 __ movq(dst, kScratchRegister); |
198 } | 198 } |
199 } else { | 199 } else { |
200 ASSERT(destination->IsStackSlot()); | 200 DCHECK(destination->IsStackSlot()); |
201 Operand dst = cgen_->ToOperand(destination); | 201 Operand dst = cgen_->ToOperand(destination); |
202 if (cgen_->IsSmiConstant(constant_source)) { | 202 if (cgen_->IsSmiConstant(constant_source)) { |
203 __ Move(dst, cgen_->ToSmi(constant_source)); | 203 __ Move(dst, cgen_->ToSmi(constant_source)); |
204 } else if (cgen_->IsInteger32Constant(constant_source)) { | 204 } else if (cgen_->IsInteger32Constant(constant_source)) { |
205 // Do sign extension to 64 bits when stored into stack slot. | 205 // Do sign extension to 64 bits when stored into stack slot. |
206 __ movp(dst, Immediate(cgen_->ToInteger32(constant_source))); | 206 __ movp(dst, Immediate(cgen_->ToInteger32(constant_source))); |
207 } else { | 207 } else { |
208 __ Move(kScratchRegister, cgen_->ToHandle(constant_source)); | 208 __ Move(kScratchRegister, cgen_->ToHandle(constant_source)); |
209 __ movp(dst, kScratchRegister); | 209 __ movp(dst, kScratchRegister); |
210 } | 210 } |
211 } | 211 } |
212 | 212 |
213 } else if (source->IsDoubleRegister()) { | 213 } else if (source->IsDoubleRegister()) { |
214 XMMRegister src = cgen_->ToDoubleRegister(source); | 214 XMMRegister src = cgen_->ToDoubleRegister(source); |
215 if (destination->IsDoubleRegister()) { | 215 if (destination->IsDoubleRegister()) { |
216 __ movaps(cgen_->ToDoubleRegister(destination), src); | 216 __ movaps(cgen_->ToDoubleRegister(destination), src); |
217 } else { | 217 } else { |
218 ASSERT(destination->IsDoubleStackSlot()); | 218 DCHECK(destination->IsDoubleStackSlot()); |
219 __ movsd(cgen_->ToOperand(destination), src); | 219 __ movsd(cgen_->ToOperand(destination), src); |
220 } | 220 } |
221 } else if (source->IsDoubleStackSlot()) { | 221 } else if (source->IsDoubleStackSlot()) { |
222 Operand src = cgen_->ToOperand(source); | 222 Operand src = cgen_->ToOperand(source); |
223 if (destination->IsDoubleRegister()) { | 223 if (destination->IsDoubleRegister()) { |
224 __ movsd(cgen_->ToDoubleRegister(destination), src); | 224 __ movsd(cgen_->ToDoubleRegister(destination), src); |
225 } else { | 225 } else { |
226 ASSERT(destination->IsDoubleStackSlot()); | 226 DCHECK(destination->IsDoubleStackSlot()); |
227 __ movsd(xmm0, src); | 227 __ movsd(xmm0, src); |
228 __ movsd(cgen_->ToOperand(destination), xmm0); | 228 __ movsd(cgen_->ToOperand(destination), xmm0); |
229 } | 229 } |
230 } else { | 230 } else { |
231 UNREACHABLE(); | 231 UNREACHABLE(); |
232 } | 232 } |
233 | 233 |
234 moves_[index].Eliminate(); | 234 moves_[index].Eliminate(); |
235 } | 235 } |
236 | 236 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) { | 271 } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) { |
272 // Swap two double registers. | 272 // Swap two double registers. |
273 XMMRegister source_reg = cgen_->ToDoubleRegister(source); | 273 XMMRegister source_reg = cgen_->ToDoubleRegister(source); |
274 XMMRegister destination_reg = cgen_->ToDoubleRegister(destination); | 274 XMMRegister destination_reg = cgen_->ToDoubleRegister(destination); |
275 __ movaps(xmm0, source_reg); | 275 __ movaps(xmm0, source_reg); |
276 __ movaps(source_reg, destination_reg); | 276 __ movaps(source_reg, destination_reg); |
277 __ movaps(destination_reg, xmm0); | 277 __ movaps(destination_reg, xmm0); |
278 | 278 |
279 } else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) { | 279 } else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) { |
280 // Swap a double register and a double stack slot. | 280 // Swap a double register and a double stack slot. |
281 ASSERT((source->IsDoubleRegister() && destination->IsDoubleStackSlot()) || | 281 DCHECK((source->IsDoubleRegister() && destination->IsDoubleStackSlot()) || |
282 (source->IsDoubleStackSlot() && destination->IsDoubleRegister())); | 282 (source->IsDoubleStackSlot() && destination->IsDoubleRegister())); |
283 XMMRegister reg = cgen_->ToDoubleRegister(source->IsDoubleRegister() | 283 XMMRegister reg = cgen_->ToDoubleRegister(source->IsDoubleRegister() |
284 ? source | 284 ? source |
285 : destination); | 285 : destination); |
286 LOperand* other = source->IsDoubleRegister() ? destination : source; | 286 LOperand* other = source->IsDoubleRegister() ? destination : source; |
287 ASSERT(other->IsDoubleStackSlot()); | 287 DCHECK(other->IsDoubleStackSlot()); |
288 Operand other_operand = cgen_->ToOperand(other); | 288 Operand other_operand = cgen_->ToOperand(other); |
289 __ movsd(xmm0, other_operand); | 289 __ movsd(xmm0, other_operand); |
290 __ movsd(other_operand, reg); | 290 __ movsd(other_operand, reg); |
291 __ movaps(reg, xmm0); | 291 __ movaps(reg, xmm0); |
292 | 292 |
293 } else { | 293 } else { |
294 // No other combinations are possible. | 294 // No other combinations are possible. |
295 UNREACHABLE(); | 295 UNREACHABLE(); |
296 } | 296 } |
297 | 297 |
(...skipping 12 matching lines...) Expand all Loading... |
310 moves_[i].set_source(source); | 310 moves_[i].set_source(source); |
311 } | 311 } |
312 } | 312 } |
313 } | 313 } |
314 | 314 |
315 #undef __ | 315 #undef __ |
316 | 316 |
317 } } // namespace v8::internal | 317 } } // namespace v8::internal |
318 | 318 |
319 #endif // V8_TARGET_ARCH_X64 | 319 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |