| 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 |