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