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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/ia32/lithium-codegen-ia32.h" | 7 #include "src/ia32/lithium-codegen-ia32.h" |
8 #include "src/ia32/lithium-gap-resolver-ia32.h" | 8 #include "src/ia32/lithium-gap-resolver-ia32.h" |
9 #include "src/register-configuration.h" | |
10 | 9 |
11 namespace v8 { | 10 namespace v8 { |
12 namespace internal { | 11 namespace internal { |
13 | 12 |
14 LGapResolver::LGapResolver(LCodeGen* owner) | 13 LGapResolver::LGapResolver(LCodeGen* owner) |
15 : cgen_(owner), | 14 : cgen_(owner), |
16 moves_(32, owner->zone()), | 15 moves_(32, owner->zone()), |
17 source_uses_(), | 16 source_uses_(), |
18 destination_uses_(), | 17 destination_uses_(), |
19 spilled_register_(-1) {} | 18 spilled_register_(-1) {} |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 for (int i = 0; i < moves_.length(); ++i) { | 158 for (int i = 0; i < moves_.length(); ++i) { |
160 if (!moves_[i].IsEliminated() && moves_[i].source()->Equals(operand)) { | 159 if (!moves_[i].IsEliminated() && moves_[i].source()->Equals(operand)) { |
161 ++count; | 160 ++count; |
162 } | 161 } |
163 } | 162 } |
164 return count; | 163 return count; |
165 } | 164 } |
166 | 165 |
167 | 166 |
168 Register LGapResolver::GetFreeRegisterNot(Register reg) { | 167 Register LGapResolver::GetFreeRegisterNot(Register reg) { |
169 int skip_index = reg.is(no_reg) ? -1 : reg.code(); | 168 int skip_index = reg.is(no_reg) ? -1 : Register::ToAllocationIndex(reg); |
170 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); | 169 for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { |
171 for (int i = 0; i < config->num_allocatable_general_registers(); ++i) { | 170 if (source_uses_[i] == 0 && destination_uses_[i] > 0 && i != skip_index) { |
172 int code = config->GetAllocatableGeneralCode(i); | 171 return Register::FromAllocationIndex(i); |
173 if (source_uses_[code] == 0 && destination_uses_[code] > 0 && | |
174 code != skip_index) { | |
175 return Register::from_code(code); | |
176 } | 172 } |
177 } | 173 } |
178 return no_reg; | 174 return no_reg; |
179 } | 175 } |
180 | 176 |
181 | 177 |
182 bool LGapResolver::HasBeenReset() { | 178 bool LGapResolver::HasBeenReset() { |
183 if (!moves_.is_empty()) return false; | 179 if (!moves_.is_empty()) return false; |
184 if (spilled_register_ >= 0) return false; | 180 if (spilled_register_ >= 0) return false; |
185 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); | 181 |
186 for (int i = 0; i < config->num_allocatable_general_registers(); ++i) { | 182 for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { |
187 int code = config->GetAllocatableGeneralCode(i); | 183 if (source_uses_[i] != 0) return false; |
188 if (source_uses_[code] != 0) return false; | 184 if (destination_uses_[i] != 0) return false; |
189 if (destination_uses_[code] != 0) return false; | |
190 } | 185 } |
191 return true; | 186 return true; |
192 } | 187 } |
193 | 188 |
194 | 189 |
195 void LGapResolver::Verify() { | 190 void LGapResolver::Verify() { |
196 #ifdef ENABLE_SLOW_DCHECKS | 191 #ifdef ENABLE_SLOW_DCHECKS |
197 // No operand should be the destination for more than one move. | 192 // No operand should be the destination for more than one move. |
198 for (int i = 0; i < moves_.length(); ++i) { | 193 for (int i = 0; i < moves_.length(); ++i) { |
199 LOperand* destination = moves_[i].destination(); | 194 LOperand* destination = moves_[i].destination(); |
200 for (int j = i + 1; j < moves_.length(); ++j) { | 195 for (int j = i + 1; j < moves_.length(); ++j) { |
201 SLOW_DCHECK(!destination->Equals(moves_[j].destination())); | 196 SLOW_DCHECK(!destination->Equals(moves_[j].destination())); |
202 } | 197 } |
203 } | 198 } |
204 #endif | 199 #endif |
205 } | 200 } |
206 | 201 |
207 | 202 |
208 #define __ ACCESS_MASM(cgen_->masm()) | 203 #define __ ACCESS_MASM(cgen_->masm()) |
209 | 204 |
210 void LGapResolver::Finish() { | 205 void LGapResolver::Finish() { |
211 if (spilled_register_ >= 0) { | 206 if (spilled_register_ >= 0) { |
212 __ pop(Register::from_code(spilled_register_)); | 207 __ pop(Register::FromAllocationIndex(spilled_register_)); |
213 spilled_register_ = -1; | 208 spilled_register_ = -1; |
214 } | 209 } |
215 moves_.Rewind(0); | 210 moves_.Rewind(0); |
216 } | 211 } |
217 | 212 |
218 | 213 |
219 void LGapResolver::EnsureRestored(LOperand* operand) { | 214 void LGapResolver::EnsureRestored(LOperand* operand) { |
220 if (operand->IsRegister() && operand->index() == spilled_register_) { | 215 if (operand->IsRegister() && operand->index() == spilled_register_) { |
221 __ pop(Register::from_code(spilled_register_)); | 216 __ pop(Register::FromAllocationIndex(spilled_register_)); |
222 spilled_register_ = -1; | 217 spilled_register_ = -1; |
223 } | 218 } |
224 } | 219 } |
225 | 220 |
226 | 221 |
227 Register LGapResolver::EnsureTempRegister() { | 222 Register LGapResolver::EnsureTempRegister() { |
228 // 1. We may have already spilled to create a temp register. | 223 // 1. We may have already spilled to create a temp register. |
229 if (spilled_register_ >= 0) { | 224 if (spilled_register_ >= 0) { |
230 return Register::from_code(spilled_register_); | 225 return Register::FromAllocationIndex(spilled_register_); |
231 } | 226 } |
232 | 227 |
233 // 2. We may have a free register that we can use without spilling. | 228 // 2. We may have a free register that we can use without spilling. |
234 Register free = GetFreeRegisterNot(no_reg); | 229 Register free = GetFreeRegisterNot(no_reg); |
235 if (!free.is(no_reg)) return free; | 230 if (!free.is(no_reg)) return free; |
236 | 231 |
237 // 3. Prefer to spill a register that is not used in any remaining move | 232 // 3. Prefer to spill a register that is not used in any remaining move |
238 // because it will not need to be restored until the end. | 233 // because it will not need to be restored until the end. |
239 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); | 234 for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { |
240 for (int i = 0; i < config->num_allocatable_general_registers(); ++i) { | 235 if (source_uses_[i] == 0 && destination_uses_[i] == 0) { |
241 int code = config->GetAllocatableGeneralCode(i); | 236 Register scratch = Register::FromAllocationIndex(i); |
242 if (source_uses_[code] == 0 && destination_uses_[code] == 0) { | |
243 Register scratch = Register::from_code(code); | |
244 __ push(scratch); | 237 __ push(scratch); |
245 spilled_register_ = code; | 238 spilled_register_ = i; |
246 return scratch; | 239 return scratch; |
247 } | 240 } |
248 } | 241 } |
249 | 242 |
250 // 4. Use an arbitrary register. Register 0 is as arbitrary as any other. | 243 // 4. Use an arbitrary register. Register 0 is as arbitrary as any other. |
251 spilled_register_ = config->GetAllocatableGeneralCode(0); | 244 Register scratch = Register::FromAllocationIndex(0); |
252 Register scratch = Register::from_code(spilled_register_); | |
253 __ push(scratch); | 245 __ push(scratch); |
| 246 spilled_register_ = 0; |
254 return scratch; | 247 return scratch; |
255 } | 248 } |
256 | 249 |
257 | 250 |
258 void LGapResolver::EmitMove(int index) { | 251 void LGapResolver::EmitMove(int index) { |
259 LOperand* source = moves_[index].source(); | 252 LOperand* source = moves_[index].source(); |
260 LOperand* destination = moves_[index].destination(); | 253 LOperand* destination = moves_[index].destination(); |
261 EnsureRestored(source); | 254 EnsureRestored(source); |
262 EnsureRestored(destination); | 255 EnsureRestored(destination); |
263 | 256 |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 source_uses_[destination->index()] = CountSourceUses(destination); | 472 source_uses_[destination->index()] = CountSourceUses(destination); |
480 } | 473 } |
481 } | 474 } |
482 | 475 |
483 #undef __ | 476 #undef __ |
484 | 477 |
485 } // namespace internal | 478 } // namespace internal |
486 } // namespace v8 | 479 } // namespace v8 |
487 | 480 |
488 #endif // V8_TARGET_ARCH_IA32 | 481 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |