| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 "v8.h" | 5 #include "v8.h" |
| 6 #include "lithium-allocator-inl.h" | 6 #include "lithium-allocator-inl.h" |
| 7 | 7 |
| 8 #include "hydrogen.h" | 8 #include "hydrogen.h" |
| 9 #include "string-stream.h" | 9 #include "string-stream.h" |
| 10 | 10 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 assigned_register_(kInvalidAssignment), | 117 assigned_register_(kInvalidAssignment), |
| 118 last_interval_(NULL), | 118 last_interval_(NULL), |
| 119 first_interval_(NULL), | 119 first_interval_(NULL), |
| 120 first_pos_(NULL), | 120 first_pos_(NULL), |
| 121 parent_(NULL), | 121 parent_(NULL), |
| 122 next_(NULL), | 122 next_(NULL), |
| 123 current_interval_(NULL), | 123 current_interval_(NULL), |
| 124 last_processed_use_(NULL), | 124 last_processed_use_(NULL), |
| 125 current_hint_operand_(NULL), | 125 current_hint_operand_(NULL), |
| 126 spill_operand_(new(zone) LOperand()), | 126 spill_operand_(new(zone) LOperand()), |
| 127 spill_start_index_(kMaxInt) { } | 127 spill_start_index_(kMaxInt), |
| 128 parent_linstr_(NULL) { } |
| 128 | 129 |
| 129 | 130 |
| 130 void LiveRange::set_assigned_register(int reg, Zone* zone) { | 131 void LiveRange::set_assigned_register(int reg, Zone* zone) { |
| 131 ASSERT(!HasRegisterAssigned() && !IsSpilled()); | 132 ASSERT(!HasRegisterAssigned() && !IsSpilled()); |
| 132 assigned_register_ = reg; | 133 assigned_register_ = reg; |
| 133 ConvertOperands(zone); | 134 ConvertOperands(zone); |
| 134 } | 135 } |
| 135 | 136 |
| 136 | 137 |
| 137 void LiveRange::MakeSpilled(Zone* zone) { | 138 void LiveRange::MakeSpilled(Zone* zone) { |
| 138 ASSERT(!IsSpilled()); | 139 ASSERT(!IsSpilled()); |
| 139 ASSERT(TopLevel()->HasAllocatedSpillOperand()); | 140 ASSERT(TopLevel()->HasAllocatedSpillOperand()); |
| 140 spilled_ = true; | 141 spilled_ = true; |
| 141 assigned_register_ = kInvalidAssignment; | 142 assigned_register_ = kInvalidAssignment; |
| 142 ConvertOperands(zone); | 143 ConvertOperands(zone); |
| 144 spill_operand_->set_parent_linstr(parent_linstr()); |
| 143 } | 145 } |
| 144 | 146 |
| 145 | 147 |
| 146 bool LiveRange::HasAllocatedSpillOperand() const { | 148 bool LiveRange::HasAllocatedSpillOperand() const { |
| 147 ASSERT(spill_operand_ != NULL); | 149 ASSERT(spill_operand_ != NULL); |
| 148 return !spill_operand_->IsIgnored(); | 150 return !spill_operand_->IsIgnored(); |
| 149 } | 151 } |
| 150 | 152 |
| 151 | 153 |
| 152 void LiveRange::SetSpillOperand(LOperand* operand) { | 154 void LiveRange::SetSpillOperand(LOperand* operand) { |
| 153 ASSERT(!operand->IsUnallocated()); | 155 ASSERT(!operand->IsUnallocated()); |
| 154 ASSERT(spill_operand_ != NULL); | 156 ASSERT(spill_operand_ != NULL); |
| 155 ASSERT(spill_operand_->IsIgnored()); | 157 ASSERT(spill_operand_->IsIgnored()); |
| 158 ASSERT((spill_operand_->parent_linstr() == NULL) || |
| 159 (spill_operand_->parent_linstr() == parent_linstr())); |
| 156 spill_operand_->ConvertTo(operand->kind(), operand->index()); | 160 spill_operand_->ConvertTo(operand->kind(), operand->index()); |
| 161 spill_operand_->set_parent_linstr(parent_linstr()); |
| 157 } | 162 } |
| 158 | 163 |
| 159 | 164 |
| 160 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { | 165 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { |
| 161 UsePosition* use_pos = last_processed_use_; | 166 UsePosition* use_pos = last_processed_use_; |
| 162 if (use_pos == NULL) use_pos = first_pos(); | 167 if (use_pos == NULL) use_pos = first_pos(); |
| 163 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { | 168 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { |
| 164 use_pos = use_pos->next(); | 169 use_pos = use_pos->next(); |
| 165 } | 170 } |
| 166 last_processed_use_ = use_pos; | 171 last_processed_use_ = use_pos; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 // at the current or the immediate next position. | 209 // at the current or the immediate next position. |
| 205 UsePosition* use_pos = NextRegisterPosition(pos); | 210 UsePosition* use_pos = NextRegisterPosition(pos); |
| 206 if (use_pos == NULL) return true; | 211 if (use_pos == NULL) return true; |
| 207 return | 212 return |
| 208 use_pos->pos().Value() > pos.NextInstruction().InstructionEnd().Value(); | 213 use_pos->pos().Value() > pos.NextInstruction().InstructionEnd().Value(); |
| 209 } | 214 } |
| 210 | 215 |
| 211 | 216 |
| 212 LOperand* LiveRange::CreateAssignedOperand(Zone* zone) { | 217 LOperand* LiveRange::CreateAssignedOperand(Zone* zone) { |
| 213 LOperand* op = NULL; | 218 LOperand* op = NULL; |
| 219 bool allow_use_cache = parent_linstr() == NULL; |
| 214 if (HasRegisterAssigned()) { | 220 if (HasRegisterAssigned()) { |
| 215 ASSERT(!IsSpilled()); | 221 ASSERT(!IsSpilled()); |
| 216 switch (Kind()) { | 222 switch (Kind()) { |
| 217 case GENERAL_REGISTERS: | 223 case GENERAL_REGISTERS: |
| 218 op = LRegister::Create(assigned_register(), zone); | 224 op = LRegister::Create(assigned_register(), zone, allow_use_cache); |
| 219 break; | 225 break; |
| 220 case DOUBLE_REGISTERS: | 226 case DOUBLE_REGISTERS: |
| 221 op = LDoubleRegister::Create(assigned_register(), zone); | 227 op = LDoubleRegister::Create(assigned_register(), zone, |
| 228 allow_use_cache); |
| 222 break; | 229 break; |
| 223 default: | 230 default: |
| 224 UNREACHABLE(); | 231 UNREACHABLE(); |
| 225 } | 232 } |
| 226 } else if (IsSpilled()) { | 233 } else if (IsSpilled()) { |
| 227 ASSERT(!HasRegisterAssigned()); | 234 ASSERT(!HasRegisterAssigned()); |
| 228 op = TopLevel()->GetSpillOperand(); | 235 op = TopLevel()->GetSpillOperand(); |
| 229 ASSERT(!op->IsUnallocated()); | 236 ASSERT(!op->IsUnallocated()); |
| 237 ASSERT(op->parent_linstr() == parent_linstr()); |
| 230 } else { | 238 } else { |
| 231 LUnallocated* unalloc = new(zone) LUnallocated(LUnallocated::NONE); | 239 LUnallocated* unalloc = new(zone) LUnallocated(LUnallocated::NONE); |
| 232 unalloc->set_virtual_register(id_); | 240 unalloc->set_virtual_register(id_); |
| 233 op = unalloc; | 241 op = unalloc; |
| 234 } | 242 } |
| 243 op->set_parent_linstr(parent_linstr()); |
| 235 return op; | 244 return op; |
| 236 } | 245 } |
| 237 | 246 |
| 238 | 247 |
| 239 UseInterval* LiveRange::FirstSearchIntervalForPosition( | 248 UseInterval* LiveRange::FirstSearchIntervalForPosition( |
| 240 LifetimePosition position) const { | 249 LifetimePosition position) const { |
| 241 if (current_interval_ == NULL) return first_interval_; | 250 if (current_interval_ == NULL) return first_interval_; |
| 242 if (current_interval_->start().Value() > position.Value()) { | 251 if (current_interval_->start().Value() > position.Value()) { |
| 243 current_interval_ = NULL; | 252 current_interval_ = NULL; |
| 244 return first_interval_; | 253 return first_interval_; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 258 current_interval_ = to_start_of; | 267 current_interval_ = to_start_of; |
| 259 } | 268 } |
| 260 } | 269 } |
| 261 | 270 |
| 262 | 271 |
| 263 void LiveRange::SplitAt(LifetimePosition position, | 272 void LiveRange::SplitAt(LifetimePosition position, |
| 264 LiveRange* result, | 273 LiveRange* result, |
| 265 Zone* zone) { | 274 Zone* zone) { |
| 266 ASSERT(Start().Value() < position.Value()); | 275 ASSERT(Start().Value() < position.Value()); |
| 267 ASSERT(result->IsEmpty()); | 276 ASSERT(result->IsEmpty()); |
| 277 |
| 278 result->set_parent_linstr(parent_linstr()); |
| 279 |
| 268 // Find the last interval that ends before the position. If the | 280 // Find the last interval that ends before the position. If the |
| 269 // position is contained in one of the intervals in the chain, we | 281 // position is contained in one of the intervals in the chain, we |
| 270 // split that interval and use the first part. | 282 // split that interval and use the first part. |
| 271 UseInterval* current = FirstSearchIntervalForPosition(position); | 283 UseInterval* current = FirstSearchIntervalForPosition(position); |
| 272 | 284 |
| 273 // If the split position coincides with the beginning of a use interval | 285 // If the split position coincides with the beginning of a use interval |
| 274 // we need to split use positons in a special way. | 286 // we need to split use positons in a special way. |
| 275 bool split_at_start = false; | 287 bool split_at_start = false; |
| 276 | 288 |
| 277 if (current->start().Value() == position.Value()) { | 289 if (current->start().Value() == position.Value()) { |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 int index = LUnallocated::cast(operand)->virtual_register(); | 698 int index = LUnallocated::cast(operand)->virtual_register(); |
| 687 HValue* instr = graph_->LookupValue(index); | 699 HValue* instr = graph_->LookupValue(index); |
| 688 if (instr != NULL && instr->IsPhi()) { | 700 if (instr != NULL && instr->IsPhi()) { |
| 689 return HPhi::cast(instr); | 701 return HPhi::cast(instr); |
| 690 } | 702 } |
| 691 return NULL; | 703 return NULL; |
| 692 } | 704 } |
| 693 | 705 |
| 694 | 706 |
| 695 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) { | 707 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) { |
| 708 LiveRange* result; |
| 696 if (operand->IsUnallocated()) { | 709 if (operand->IsUnallocated()) { |
| 697 return LiveRangeFor(LUnallocated::cast(operand)->virtual_register()); | 710 result = LiveRangeFor(LUnallocated::cast(operand)->virtual_register()); |
| 698 } else if (operand->IsRegister()) { | 711 } else if (operand->IsRegister()) { |
| 699 return FixedLiveRangeFor(operand->index()); | 712 result = FixedLiveRangeFor(operand->index()); |
| 700 } else if (operand->IsDoubleRegister()) { | 713 } else if (operand->IsDoubleRegister()) { |
| 701 return FixedDoubleLiveRangeFor(operand->index()); | 714 result = FixedDoubleLiveRangeFor(operand->index()); |
| 702 } else { | 715 } else { |
| 703 return NULL; | 716 return NULL; |
| 704 } | 717 } |
| 718 result->set_parent_linstr(operand->parent_linstr()); |
| 719 return result; |
| 705 } | 720 } |
| 706 | 721 |
| 707 | 722 |
| 708 void LAllocator::Define(LifetimePosition position, | 723 void LAllocator::Define(LifetimePosition position, |
| 709 LOperand* operand, | 724 LOperand* operand, |
| 710 LOperand* hint) { | 725 LOperand* hint) { |
| 711 LiveRange* range = LiveRangeFor(operand); | 726 LiveRange* range = LiveRangeFor(operand); |
| 712 if (range == NULL) return; | 727 if (range == NULL) return; |
| 713 | 728 |
| 714 if (range->IsEmpty() || range->Start().Value() > position.Value()) { | 729 if (range->IsEmpty() || range->Start().Value() > position.Value()) { |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 return true; | 1728 return true; |
| 1714 } | 1729 } |
| 1715 | 1730 |
| 1716 | 1731 |
| 1717 void LAllocator::FreeSpillSlot(LiveRange* range) { | 1732 void LAllocator::FreeSpillSlot(LiveRange* range) { |
| 1718 // Check that we are the last range. | 1733 // Check that we are the last range. |
| 1719 if (range->next() != NULL) return; | 1734 if (range->next() != NULL) return; |
| 1720 | 1735 |
| 1721 if (!range->TopLevel()->HasAllocatedSpillOperand()) return; | 1736 if (!range->TopLevel()->HasAllocatedSpillOperand()) return; |
| 1722 | 1737 |
| 1738 if (range->parent_linstr() != NULL) { |
| 1739 // Reusing live ranges with parent instruction information may prevent |
| 1740 // optimizing away gap moves. |
| 1741 return; |
| 1742 } |
| 1743 |
| 1723 int index = range->TopLevel()->GetSpillOperand()->index(); | 1744 int index = range->TopLevel()->GetSpillOperand()->index(); |
| 1724 if (index >= 0) { | 1745 if (index >= 0) { |
| 1725 reusable_slots_.Add(range, zone()); | 1746 reusable_slots_.Add(range, zone()); |
| 1726 } | 1747 } |
| 1727 } | 1748 } |
| 1728 | 1749 |
| 1729 | 1750 |
| 1730 LOperand* LAllocator::TryReuseSpillSlot(LiveRange* range) { | 1751 LOperand* LAllocator::TryReuseSpillSlot(LiveRange* range) { |
| 1731 if (reusable_slots_.is_empty()) return NULL; | 1752 if (reusable_slots_.is_empty()) return NULL; |
| 1732 if (reusable_slots_.first()->End().Value() > | 1753 if (reusable_slots_.first()->End().Value() > |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2142 // Nothing to spill. Just put it to unhandled as whole. | 2163 // Nothing to spill. Just put it to unhandled as whole. |
| 2143 AddToUnhandledSorted(second_part); | 2164 AddToUnhandledSorted(second_part); |
| 2144 } | 2165 } |
| 2145 } | 2166 } |
| 2146 | 2167 |
| 2147 | 2168 |
| 2148 void LAllocator::Spill(LiveRange* range) { | 2169 void LAllocator::Spill(LiveRange* range) { |
| 2149 ASSERT(!range->IsSpilled()); | 2170 ASSERT(!range->IsSpilled()); |
| 2150 TraceAlloc("Spilling live range %d\n", range->id()); | 2171 TraceAlloc("Spilling live range %d\n", range->id()); |
| 2151 LiveRange* first = range->TopLevel(); | 2172 LiveRange* first = range->TopLevel(); |
| 2173 ASSERT(first->parent_linstr() == range->parent_linstr()); |
| 2152 | 2174 |
| 2153 if (!first->HasAllocatedSpillOperand()) { | 2175 if (!first->HasAllocatedSpillOperand()) { |
| 2154 LOperand* op = TryReuseSpillSlot(range); | 2176 LOperand* op = TryReuseSpillSlot(range); |
| 2155 if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind()); | 2177 if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind()); |
| 2156 first->SetSpillOperand(op); | 2178 first->SetSpillOperand(op); |
| 2157 } | 2179 } |
| 2158 range->MakeSpilled(chunk()->zone()); | 2180 range->MakeSpilled(chunk()->zone()); |
| 2159 } | 2181 } |
| 2160 | 2182 |
| 2161 | 2183 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2200 isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_); | 2222 isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_); |
| 2201 } | 2223 } |
| 2202 | 2224 |
| 2203 #ifdef DEBUG | 2225 #ifdef DEBUG |
| 2204 if (allocator_ != NULL) allocator_->Verify(); | 2226 if (allocator_ != NULL) allocator_->Verify(); |
| 2205 #endif | 2227 #endif |
| 2206 } | 2228 } |
| 2207 | 2229 |
| 2208 | 2230 |
| 2209 } } // namespace v8::internal | 2231 } } // namespace v8::internal |
| OLD | NEW |