| 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 "src/v8.h" | 5 #include "src/v8.h" | 
| 6 | 6 | 
| 7 #include "src/hydrogen.h" | 7 #include "src/hydrogen.h" | 
| 8 #include "src/lithium-inl.h" | 8 #include "src/lithium-inl.h" | 
| 9 #include "src/lithium-allocator-inl.h" | 9 #include "src/lithium-allocator-inl.h" | 
| 10 #include "src/string-stream.h" | 10 #include "src/string-stream.h" | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 30       pos_(pos), | 30       pos_(pos), | 
| 31       next_(NULL), | 31       next_(NULL), | 
| 32       requires_reg_(false), | 32       requires_reg_(false), | 
| 33       register_beneficial_(true) { | 33       register_beneficial_(true) { | 
| 34   if (operand_ != NULL && operand_->IsUnallocated()) { | 34   if (operand_ != NULL && operand_->IsUnallocated()) { | 
| 35     LUnallocated* unalloc = LUnallocated::cast(operand_); | 35     LUnallocated* unalloc = LUnallocated::cast(operand_); | 
| 36     requires_reg_ = unalloc->HasRegisterPolicy() || | 36     requires_reg_ = unalloc->HasRegisterPolicy() || | 
| 37         unalloc->HasDoubleRegisterPolicy(); | 37         unalloc->HasDoubleRegisterPolicy(); | 
| 38     register_beneficial_ = !unalloc->HasAnyPolicy(); | 38     register_beneficial_ = !unalloc->HasAnyPolicy(); | 
| 39   } | 39   } | 
| 40   ASSERT(pos_.IsValid()); | 40   DCHECK(pos_.IsValid()); | 
| 41 } | 41 } | 
| 42 | 42 | 
| 43 | 43 | 
| 44 bool UsePosition::HasHint() const { | 44 bool UsePosition::HasHint() const { | 
| 45   return hint_ != NULL && !hint_->IsUnallocated(); | 45   return hint_ != NULL && !hint_->IsUnallocated(); | 
| 46 } | 46 } | 
| 47 | 47 | 
| 48 | 48 | 
| 49 bool UsePosition::RequiresRegister() const { | 49 bool UsePosition::RequiresRegister() const { | 
| 50   return requires_reg_; | 50   return requires_reg_; | 
| 51 } | 51 } | 
| 52 | 52 | 
| 53 | 53 | 
| 54 bool UsePosition::RegisterIsBeneficial() const { | 54 bool UsePosition::RegisterIsBeneficial() const { | 
| 55   return register_beneficial_; | 55   return register_beneficial_; | 
| 56 } | 56 } | 
| 57 | 57 | 
| 58 | 58 | 
| 59 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { | 59 void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { | 
| 60   ASSERT(Contains(pos) && pos.Value() != start().Value()); | 60   DCHECK(Contains(pos) && pos.Value() != start().Value()); | 
| 61   UseInterval* after = new(zone) UseInterval(pos, end_); | 61   UseInterval* after = new(zone) UseInterval(pos, end_); | 
| 62   after->next_ = next_; | 62   after->next_ = next_; | 
| 63   next_ = after; | 63   next_ = after; | 
| 64   end_ = pos; | 64   end_ = pos; | 
| 65 } | 65 } | 
| 66 | 66 | 
| 67 | 67 | 
| 68 #ifdef DEBUG | 68 #ifdef DEBUG | 
| 69 | 69 | 
| 70 | 70 | 
| 71 void LiveRange::Verify() const { | 71 void LiveRange::Verify() const { | 
| 72   UsePosition* cur = first_pos_; | 72   UsePosition* cur = first_pos_; | 
| 73   while (cur != NULL) { | 73   while (cur != NULL) { | 
| 74     ASSERT(Start().Value() <= cur->pos().Value() && | 74     DCHECK(Start().Value() <= cur->pos().Value() && | 
| 75            cur->pos().Value() <= End().Value()); | 75            cur->pos().Value() <= End().Value()); | 
| 76     cur = cur->next(); | 76     cur = cur->next(); | 
| 77   } | 77   } | 
| 78 } | 78 } | 
| 79 | 79 | 
| 80 | 80 | 
| 81 bool LiveRange::HasOverlap(UseInterval* target) const { | 81 bool LiveRange::HasOverlap(UseInterval* target) const { | 
| 82   UseInterval* current_interval = first_interval_; | 82   UseInterval* current_interval = first_interval_; | 
| 83   while (current_interval != NULL) { | 83   while (current_interval != NULL) { | 
| 84     // Intervals overlap if the start of one is contained in the other. | 84     // Intervals overlap if the start of one is contained in the other. | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 106       parent_(NULL), | 106       parent_(NULL), | 
| 107       next_(NULL), | 107       next_(NULL), | 
| 108       current_interval_(NULL), | 108       current_interval_(NULL), | 
| 109       last_processed_use_(NULL), | 109       last_processed_use_(NULL), | 
| 110       current_hint_operand_(NULL), | 110       current_hint_operand_(NULL), | 
| 111       spill_operand_(new(zone) LOperand()), | 111       spill_operand_(new(zone) LOperand()), | 
| 112       spill_start_index_(kMaxInt) { } | 112       spill_start_index_(kMaxInt) { } | 
| 113 | 113 | 
| 114 | 114 | 
| 115 void LiveRange::set_assigned_register(int reg, Zone* zone) { | 115 void LiveRange::set_assigned_register(int reg, Zone* zone) { | 
| 116   ASSERT(!HasRegisterAssigned() && !IsSpilled()); | 116   DCHECK(!HasRegisterAssigned() && !IsSpilled()); | 
| 117   assigned_register_ = reg; | 117   assigned_register_ = reg; | 
| 118   ConvertOperands(zone); | 118   ConvertOperands(zone); | 
| 119 } | 119 } | 
| 120 | 120 | 
| 121 | 121 | 
| 122 void LiveRange::MakeSpilled(Zone* zone) { | 122 void LiveRange::MakeSpilled(Zone* zone) { | 
| 123   ASSERT(!IsSpilled()); | 123   DCHECK(!IsSpilled()); | 
| 124   ASSERT(TopLevel()->HasAllocatedSpillOperand()); | 124   DCHECK(TopLevel()->HasAllocatedSpillOperand()); | 
| 125   spilled_ = true; | 125   spilled_ = true; | 
| 126   assigned_register_ = kInvalidAssignment; | 126   assigned_register_ = kInvalidAssignment; | 
| 127   ConvertOperands(zone); | 127   ConvertOperands(zone); | 
| 128 } | 128 } | 
| 129 | 129 | 
| 130 | 130 | 
| 131 bool LiveRange::HasAllocatedSpillOperand() const { | 131 bool LiveRange::HasAllocatedSpillOperand() const { | 
| 132   ASSERT(spill_operand_ != NULL); | 132   DCHECK(spill_operand_ != NULL); | 
| 133   return !spill_operand_->IsIgnored(); | 133   return !spill_operand_->IsIgnored(); | 
| 134 } | 134 } | 
| 135 | 135 | 
| 136 | 136 | 
| 137 void LiveRange::SetSpillOperand(LOperand* operand) { | 137 void LiveRange::SetSpillOperand(LOperand* operand) { | 
| 138   ASSERT(!operand->IsUnallocated()); | 138   DCHECK(!operand->IsUnallocated()); | 
| 139   ASSERT(spill_operand_ != NULL); | 139   DCHECK(spill_operand_ != NULL); | 
| 140   ASSERT(spill_operand_->IsIgnored()); | 140   DCHECK(spill_operand_->IsIgnored()); | 
| 141   spill_operand_->ConvertTo(operand->kind(), operand->index()); | 141   spill_operand_->ConvertTo(operand->kind(), operand->index()); | 
| 142 } | 142 } | 
| 143 | 143 | 
| 144 | 144 | 
| 145 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { | 145 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { | 
| 146   UsePosition* use_pos = last_processed_use_; | 146   UsePosition* use_pos = last_processed_use_; | 
| 147   if (use_pos == NULL) use_pos = first_pos(); | 147   if (use_pos == NULL) use_pos = first_pos(); | 
| 148   while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { | 148   while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { | 
| 149     use_pos = use_pos->next(); | 149     use_pos = use_pos->next(); | 
| 150   } | 150   } | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 190   UsePosition* use_pos = NextRegisterPosition(pos); | 190   UsePosition* use_pos = NextRegisterPosition(pos); | 
| 191   if (use_pos == NULL) return true; | 191   if (use_pos == NULL) return true; | 
| 192   return | 192   return | 
| 193       use_pos->pos().Value() > pos.NextInstruction().InstructionEnd().Value(); | 193       use_pos->pos().Value() > pos.NextInstruction().InstructionEnd().Value(); | 
| 194 } | 194 } | 
| 195 | 195 | 
| 196 | 196 | 
| 197 LOperand* LiveRange::CreateAssignedOperand(Zone* zone) { | 197 LOperand* LiveRange::CreateAssignedOperand(Zone* zone) { | 
| 198   LOperand* op = NULL; | 198   LOperand* op = NULL; | 
| 199   if (HasRegisterAssigned()) { | 199   if (HasRegisterAssigned()) { | 
| 200     ASSERT(!IsSpilled()); | 200     DCHECK(!IsSpilled()); | 
| 201     switch (Kind()) { | 201     switch (Kind()) { | 
| 202       case GENERAL_REGISTERS: | 202       case GENERAL_REGISTERS: | 
| 203         op = LRegister::Create(assigned_register(), zone); | 203         op = LRegister::Create(assigned_register(), zone); | 
| 204         break; | 204         break; | 
| 205       case DOUBLE_REGISTERS: | 205       case DOUBLE_REGISTERS: | 
| 206         op = LDoubleRegister::Create(assigned_register(), zone); | 206         op = LDoubleRegister::Create(assigned_register(), zone); | 
| 207         break; | 207         break; | 
| 208       default: | 208       default: | 
| 209         UNREACHABLE(); | 209         UNREACHABLE(); | 
| 210     } | 210     } | 
| 211   } else if (IsSpilled()) { | 211   } else if (IsSpilled()) { | 
| 212     ASSERT(!HasRegisterAssigned()); | 212     DCHECK(!HasRegisterAssigned()); | 
| 213     op = TopLevel()->GetSpillOperand(); | 213     op = TopLevel()->GetSpillOperand(); | 
| 214     ASSERT(!op->IsUnallocated()); | 214     DCHECK(!op->IsUnallocated()); | 
| 215   } else { | 215   } else { | 
| 216     LUnallocated* unalloc = new(zone) LUnallocated(LUnallocated::NONE); | 216     LUnallocated* unalloc = new(zone) LUnallocated(LUnallocated::NONE); | 
| 217     unalloc->set_virtual_register(id_); | 217     unalloc->set_virtual_register(id_); | 
| 218     op = unalloc; | 218     op = unalloc; | 
| 219   } | 219   } | 
| 220   return op; | 220   return op; | 
| 221 } | 221 } | 
| 222 | 222 | 
| 223 | 223 | 
| 224 UseInterval* LiveRange::FirstSearchIntervalForPosition( | 224 UseInterval* LiveRange::FirstSearchIntervalForPosition( | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 241                                 : current_interval_->start(); | 241                                 : current_interval_->start(); | 
| 242   if (to_start_of->start().Value() > start.Value()) { | 242   if (to_start_of->start().Value() > start.Value()) { | 
| 243     current_interval_ = to_start_of; | 243     current_interval_ = to_start_of; | 
| 244   } | 244   } | 
| 245 } | 245 } | 
| 246 | 246 | 
| 247 | 247 | 
| 248 void LiveRange::SplitAt(LifetimePosition position, | 248 void LiveRange::SplitAt(LifetimePosition position, | 
| 249                         LiveRange* result, | 249                         LiveRange* result, | 
| 250                         Zone* zone) { | 250                         Zone* zone) { | 
| 251   ASSERT(Start().Value() < position.Value()); | 251   DCHECK(Start().Value() < position.Value()); | 
| 252   ASSERT(result->IsEmpty()); | 252   DCHECK(result->IsEmpty()); | 
| 253   // Find the last interval that ends before the position. If the | 253   // Find the last interval that ends before the position. If the | 
| 254   // position is contained in one of the intervals in the chain, we | 254   // position is contained in one of the intervals in the chain, we | 
| 255   // split that interval and use the first part. | 255   // split that interval and use the first part. | 
| 256   UseInterval* current = FirstSearchIntervalForPosition(position); | 256   UseInterval* current = FirstSearchIntervalForPosition(position); | 
| 257 | 257 | 
| 258   // If the split position coincides with the beginning of a use interval | 258   // If the split position coincides with the beginning of a use interval | 
| 259   // we need to split use positons in a special way. | 259   // we need to split use positons in a special way. | 
| 260   bool split_at_start = false; | 260   bool split_at_start = false; | 
| 261 | 261 | 
| 262   if (current->start().Value() == position.Value()) { | 262   if (current->start().Value() == position.Value()) { | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 346     UsePosition* other_pos = other->first_pos(); | 346     UsePosition* other_pos = other->first_pos(); | 
| 347     if (other_pos == NULL) return true; | 347     if (other_pos == NULL) return true; | 
| 348     return pos->pos().Value() < other_pos->pos().Value(); | 348     return pos->pos().Value() < other_pos->pos().Value(); | 
| 349   } | 349   } | 
| 350   return start.Value() < other_start.Value(); | 350   return start.Value() < other_start.Value(); | 
| 351 } | 351 } | 
| 352 | 352 | 
| 353 | 353 | 
| 354 void LiveRange::ShortenTo(LifetimePosition start) { | 354 void LiveRange::ShortenTo(LifetimePosition start) { | 
| 355   LAllocator::TraceAlloc("Shorten live range %d to [%d\n", id_, start.Value()); | 355   LAllocator::TraceAlloc("Shorten live range %d to [%d\n", id_, start.Value()); | 
| 356   ASSERT(first_interval_ != NULL); | 356   DCHECK(first_interval_ != NULL); | 
| 357   ASSERT(first_interval_->start().Value() <= start.Value()); | 357   DCHECK(first_interval_->start().Value() <= start.Value()); | 
| 358   ASSERT(start.Value() < first_interval_->end().Value()); | 358   DCHECK(start.Value() < first_interval_->end().Value()); | 
| 359   first_interval_->set_start(start); | 359   first_interval_->set_start(start); | 
| 360 } | 360 } | 
| 361 | 361 | 
| 362 | 362 | 
| 363 void LiveRange::EnsureInterval(LifetimePosition start, | 363 void LiveRange::EnsureInterval(LifetimePosition start, | 
| 364                                LifetimePosition end, | 364                                LifetimePosition end, | 
| 365                                Zone* zone) { | 365                                Zone* zone) { | 
| 366   LAllocator::TraceAlloc("Ensure live range %d in interval [%d %d[\n", | 366   LAllocator::TraceAlloc("Ensure live range %d in interval [%d %d[\n", | 
| 367                          id_, | 367                          id_, | 
| 368                          start.Value(), | 368                          start.Value(), | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 400     if (end.Value() == first_interval_->start().Value()) { | 400     if (end.Value() == first_interval_->start().Value()) { | 
| 401       first_interval_->set_start(start); | 401       first_interval_->set_start(start); | 
| 402     } else if (end.Value() < first_interval_->start().Value()) { | 402     } else if (end.Value() < first_interval_->start().Value()) { | 
| 403       UseInterval* interval = new(zone) UseInterval(start, end); | 403       UseInterval* interval = new(zone) UseInterval(start, end); | 
| 404       interval->set_next(first_interval_); | 404       interval->set_next(first_interval_); | 
| 405       first_interval_ = interval; | 405       first_interval_ = interval; | 
| 406     } else { | 406     } else { | 
| 407       // Order of instruction's processing (see ProcessInstructions) guarantees | 407       // Order of instruction's processing (see ProcessInstructions) guarantees | 
| 408       // that each new use interval either precedes or intersects with | 408       // that each new use interval either precedes or intersects with | 
| 409       // last added interval. | 409       // last added interval. | 
| 410       ASSERT(start.Value() < first_interval_->end().Value()); | 410       DCHECK(start.Value() < first_interval_->end().Value()); | 
| 411       first_interval_->start_ = Min(start, first_interval_->start_); | 411       first_interval_->start_ = Min(start, first_interval_->start_); | 
| 412       first_interval_->end_ = Max(end, first_interval_->end_); | 412       first_interval_->end_ = Max(end, first_interval_->end_); | 
| 413     } | 413     } | 
| 414   } | 414   } | 
| 415 } | 415 } | 
| 416 | 416 | 
| 417 | 417 | 
| 418 void LiveRange::AddUsePosition(LifetimePosition pos, | 418 void LiveRange::AddUsePosition(LifetimePosition pos, | 
| 419                                LOperand* operand, | 419                                LOperand* operand, | 
| 420                                LOperand* hint, | 420                                LOperand* hint, | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 443   if (prev_hint == NULL && use_pos->HasHint()) { | 443   if (prev_hint == NULL && use_pos->HasHint()) { | 
| 444     current_hint_operand_ = hint; | 444     current_hint_operand_ = hint; | 
| 445   } | 445   } | 
| 446 } | 446 } | 
| 447 | 447 | 
| 448 | 448 | 
| 449 void LiveRange::ConvertOperands(Zone* zone) { | 449 void LiveRange::ConvertOperands(Zone* zone) { | 
| 450   LOperand* op = CreateAssignedOperand(zone); | 450   LOperand* op = CreateAssignedOperand(zone); | 
| 451   UsePosition* use_pos = first_pos(); | 451   UsePosition* use_pos = first_pos(); | 
| 452   while (use_pos != NULL) { | 452   while (use_pos != NULL) { | 
| 453     ASSERT(Start().Value() <= use_pos->pos().Value() && | 453     DCHECK(Start().Value() <= use_pos->pos().Value() && | 
| 454            use_pos->pos().Value() <= End().Value()); | 454            use_pos->pos().Value() <= End().Value()); | 
| 455 | 455 | 
| 456     if (use_pos->HasOperand()) { | 456     if (use_pos->HasOperand()) { | 
| 457       ASSERT(op->IsRegister() || op->IsDoubleRegister() || | 457       DCHECK(op->IsRegister() || op->IsDoubleRegister() || | 
| 458              !use_pos->RequiresRegister()); | 458              !use_pos->RequiresRegister()); | 
| 459       use_pos->operand()->ConvertTo(op->kind(), op->index()); | 459       use_pos->operand()->ConvertTo(op->kind(), op->index()); | 
| 460     } | 460     } | 
| 461     use_pos = use_pos->next(); | 461     use_pos = use_pos->next(); | 
| 462   } | 462   } | 
| 463 } | 463 } | 
| 464 | 464 | 
| 465 | 465 | 
| 466 bool LiveRange::CanCover(LifetimePosition position) const { | 466 bool LiveRange::CanCover(LifetimePosition position) const { | 
| 467   if (IsEmpty()) return false; | 467   if (IsEmpty()) return false; | 
| 468   return Start().Value() <= position.Value() && | 468   return Start().Value() <= position.Value() && | 
| 469          position.Value() < End().Value(); | 469          position.Value() < End().Value(); | 
| 470 } | 470 } | 
| 471 | 471 | 
| 472 | 472 | 
| 473 bool LiveRange::Covers(LifetimePosition position) { | 473 bool LiveRange::Covers(LifetimePosition position) { | 
| 474   if (!CanCover(position)) return false; | 474   if (!CanCover(position)) return false; | 
| 475   UseInterval* start_search = FirstSearchIntervalForPosition(position); | 475   UseInterval* start_search = FirstSearchIntervalForPosition(position); | 
| 476   for (UseInterval* interval = start_search; | 476   for (UseInterval* interval = start_search; | 
| 477        interval != NULL; | 477        interval != NULL; | 
| 478        interval = interval->next()) { | 478        interval = interval->next()) { | 
| 479     ASSERT(interval->next() == NULL || | 479     DCHECK(interval->next() == NULL || | 
| 480            interval->next()->start().Value() >= interval->start().Value()); | 480            interval->next()->start().Value() >= interval->start().Value()); | 
| 481     AdvanceLastProcessedMarker(interval, position); | 481     AdvanceLastProcessedMarker(interval, position); | 
| 482     if (interval->Contains(position)) return true; | 482     if (interval->Contains(position)) return true; | 
| 483     if (interval->start().Value() > position.Value()) return false; | 483     if (interval->start().Value() > position.Value()) return false; | 
| 484   } | 484   } | 
| 485   return false; | 485   return false; | 
| 486 } | 486 } | 
| 487 | 487 | 
| 488 | 488 | 
| 489 LifetimePosition LiveRange::FirstIntersection(LiveRange* other) { | 489 LifetimePosition LiveRange::FirstIntersection(LiveRange* other) { | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 587 | 587 | 
| 588 int LAllocator::FixedDoubleLiveRangeID(int index) { | 588 int LAllocator::FixedDoubleLiveRangeID(int index) { | 
| 589   return -index - 1 - Register::kMaxNumAllocatableRegisters; | 589   return -index - 1 - Register::kMaxNumAllocatableRegisters; | 
| 590 } | 590 } | 
| 591 | 591 | 
| 592 | 592 | 
| 593 LOperand* LAllocator::AllocateFixed(LUnallocated* operand, | 593 LOperand* LAllocator::AllocateFixed(LUnallocated* operand, | 
| 594                                     int pos, | 594                                     int pos, | 
| 595                                     bool is_tagged) { | 595                                     bool is_tagged) { | 
| 596   TraceAlloc("Allocating fixed reg for op %d\n", operand->virtual_register()); | 596   TraceAlloc("Allocating fixed reg for op %d\n", operand->virtual_register()); | 
| 597   ASSERT(operand->HasFixedPolicy()); | 597   DCHECK(operand->HasFixedPolicy()); | 
| 598   if (operand->HasFixedSlotPolicy()) { | 598   if (operand->HasFixedSlotPolicy()) { | 
| 599     operand->ConvertTo(LOperand::STACK_SLOT, operand->fixed_slot_index()); | 599     operand->ConvertTo(LOperand::STACK_SLOT, operand->fixed_slot_index()); | 
| 600   } else if (operand->HasFixedRegisterPolicy()) { | 600   } else if (operand->HasFixedRegisterPolicy()) { | 
| 601     int reg_index = operand->fixed_register_index(); | 601     int reg_index = operand->fixed_register_index(); | 
| 602     operand->ConvertTo(LOperand::REGISTER, reg_index); | 602     operand->ConvertTo(LOperand::REGISTER, reg_index); | 
| 603   } else if (operand->HasFixedDoubleRegisterPolicy()) { | 603   } else if (operand->HasFixedDoubleRegisterPolicy()) { | 
| 604     int reg_index = operand->fixed_register_index(); | 604     int reg_index = operand->fixed_register_index(); | 
| 605     operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index); | 605     operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index); | 
| 606   } else { | 606   } else { | 
| 607     UNREACHABLE(); | 607     UNREACHABLE(); | 
| 608   } | 608   } | 
| 609   if (is_tagged) { | 609   if (is_tagged) { | 
| 610     TraceAlloc("Fixed reg is tagged at %d\n", pos); | 610     TraceAlloc("Fixed reg is tagged at %d\n", pos); | 
| 611     LInstruction* instr = InstructionAt(pos); | 611     LInstruction* instr = InstructionAt(pos); | 
| 612     if (instr->HasPointerMap()) { | 612     if (instr->HasPointerMap()) { | 
| 613       instr->pointer_map()->RecordPointer(operand, chunk()->zone()); | 613       instr->pointer_map()->RecordPointer(operand, chunk()->zone()); | 
| 614     } | 614     } | 
| 615   } | 615   } | 
| 616   return operand; | 616   return operand; | 
| 617 } | 617 } | 
| 618 | 618 | 
| 619 | 619 | 
| 620 LiveRange* LAllocator::FixedLiveRangeFor(int index) { | 620 LiveRange* LAllocator::FixedLiveRangeFor(int index) { | 
| 621   ASSERT(index < Register::kMaxNumAllocatableRegisters); | 621   DCHECK(index < Register::kMaxNumAllocatableRegisters); | 
| 622   LiveRange* result = fixed_live_ranges_[index]; | 622   LiveRange* result = fixed_live_ranges_[index]; | 
| 623   if (result == NULL) { | 623   if (result == NULL) { | 
| 624     result = new(zone()) LiveRange(FixedLiveRangeID(index), chunk()->zone()); | 624     result = new(zone()) LiveRange(FixedLiveRangeID(index), chunk()->zone()); | 
| 625     ASSERT(result->IsFixed()); | 625     DCHECK(result->IsFixed()); | 
| 626     result->kind_ = GENERAL_REGISTERS; | 626     result->kind_ = GENERAL_REGISTERS; | 
| 627     SetLiveRangeAssignedRegister(result, index); | 627     SetLiveRangeAssignedRegister(result, index); | 
| 628     fixed_live_ranges_[index] = result; | 628     fixed_live_ranges_[index] = result; | 
| 629   } | 629   } | 
| 630   return result; | 630   return result; | 
| 631 } | 631 } | 
| 632 | 632 | 
| 633 | 633 | 
| 634 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) { | 634 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) { | 
| 635   ASSERT(index < DoubleRegister::NumAllocatableRegisters()); | 635   DCHECK(index < DoubleRegister::NumAllocatableRegisters()); | 
| 636   LiveRange* result = fixed_double_live_ranges_[index]; | 636   LiveRange* result = fixed_double_live_ranges_[index]; | 
| 637   if (result == NULL) { | 637   if (result == NULL) { | 
| 638     result = new(zone()) LiveRange(FixedDoubleLiveRangeID(index), | 638     result = new(zone()) LiveRange(FixedDoubleLiveRangeID(index), | 
| 639                                    chunk()->zone()); | 639                                    chunk()->zone()); | 
| 640     ASSERT(result->IsFixed()); | 640     DCHECK(result->IsFixed()); | 
| 641     result->kind_ = DOUBLE_REGISTERS; | 641     result->kind_ = DOUBLE_REGISTERS; | 
| 642     SetLiveRangeAssignedRegister(result, index); | 642     SetLiveRangeAssignedRegister(result, index); | 
| 643     fixed_double_live_ranges_[index] = result; | 643     fixed_double_live_ranges_[index] = result; | 
| 644   } | 644   } | 
| 645   return result; | 645   return result; | 
| 646 } | 646 } | 
| 647 | 647 | 
| 648 | 648 | 
| 649 LiveRange* LAllocator::LiveRangeFor(int index) { | 649 LiveRange* LAllocator::LiveRangeFor(int index) { | 
| 650   if (index >= live_ranges_.length()) { | 650   if (index >= live_ranges_.length()) { | 
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 820       LUnallocated* cur_input = LUnallocated::cast(it.Current()); | 820       LUnallocated* cur_input = LUnallocated::cast(it.Current()); | 
| 821       if (cur_input->HasFixedPolicy()) { | 821       if (cur_input->HasFixedPolicy()) { | 
| 822         LUnallocated* input_copy = cur_input->CopyUnconstrained( | 822         LUnallocated* input_copy = cur_input->CopyUnconstrained( | 
| 823             chunk()->zone()); | 823             chunk()->zone()); | 
| 824         bool is_tagged = HasTaggedValue(cur_input->virtual_register()); | 824         bool is_tagged = HasTaggedValue(cur_input->virtual_register()); | 
| 825         AllocateFixed(cur_input, gap_index + 1, is_tagged); | 825         AllocateFixed(cur_input, gap_index + 1, is_tagged); | 
| 826         AddConstraintsGapMove(gap_index, input_copy, cur_input); | 826         AddConstraintsGapMove(gap_index, input_copy, cur_input); | 
| 827       } else if (cur_input->HasWritableRegisterPolicy()) { | 827       } else if (cur_input->HasWritableRegisterPolicy()) { | 
| 828         // The live range of writable input registers always goes until the end | 828         // The live range of writable input registers always goes until the end | 
| 829         // of the instruction. | 829         // of the instruction. | 
| 830         ASSERT(!cur_input->IsUsedAtStart()); | 830         DCHECK(!cur_input->IsUsedAtStart()); | 
| 831 | 831 | 
| 832         LUnallocated* input_copy = cur_input->CopyUnconstrained( | 832         LUnallocated* input_copy = cur_input->CopyUnconstrained( | 
| 833             chunk()->zone()); | 833             chunk()->zone()); | 
| 834         int vreg = GetVirtualRegister(); | 834         int vreg = GetVirtualRegister(); | 
| 835         if (!AllocationOk()) return; | 835         if (!AllocationOk()) return; | 
| 836         cur_input->set_virtual_register(vreg); | 836         cur_input->set_virtual_register(vreg); | 
| 837 | 837 | 
| 838         if (RequiredRegisterKind(input_copy->virtual_register()) == | 838         if (RequiredRegisterKind(input_copy->virtual_register()) == | 
| 839             DOUBLE_REGISTERS) { | 839             DOUBLE_REGISTERS) { | 
| 840           double_artificial_registers_.Add( | 840           double_artificial_registers_.Add( | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 920           } else { | 920           } else { | 
| 921             Define(curr_position, to, from); | 921             Define(curr_position, to, from); | 
| 922           } | 922           } | 
| 923         } | 923         } | 
| 924         Use(block_start_position, curr_position, from, hint); | 924         Use(block_start_position, curr_position, from, hint); | 
| 925         if (from->IsUnallocated()) { | 925         if (from->IsUnallocated()) { | 
| 926           live->Add(LUnallocated::cast(from)->virtual_register()); | 926           live->Add(LUnallocated::cast(from)->virtual_register()); | 
| 927         } | 927         } | 
| 928       } | 928       } | 
| 929     } else { | 929     } else { | 
| 930       ASSERT(!IsGapAt(index)); | 930       DCHECK(!IsGapAt(index)); | 
| 931       LInstruction* instr = InstructionAt(index); | 931       LInstruction* instr = InstructionAt(index); | 
| 932 | 932 | 
| 933       if (instr != NULL) { | 933       if (instr != NULL) { | 
| 934         LOperand* output = instr->Output(); | 934         LOperand* output = instr->Output(); | 
| 935         if (output != NULL) { | 935         if (output != NULL) { | 
| 936           if (output->IsUnallocated()) { | 936           if (output->IsUnallocated()) { | 
| 937             live->Remove(LUnallocated::cast(output)->virtual_register()); | 937             live->Remove(LUnallocated::cast(output)->virtual_register()); | 
| 938           } | 938           } | 
| 939           Define(curr_position, output, NULL); | 939           Define(curr_position, output, NULL); | 
| 940         } | 940         } | 
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1018     LUnallocated* phi_operand = | 1018     LUnallocated* phi_operand = | 
| 1019         new(chunk()->zone()) LUnallocated(LUnallocated::NONE); | 1019         new(chunk()->zone()) LUnallocated(LUnallocated::NONE); | 
| 1020     phi_operand->set_virtual_register(phi->id()); | 1020     phi_operand->set_virtual_register(phi->id()); | 
| 1021     for (int j = 0; j < phi->OperandCount(); ++j) { | 1021     for (int j = 0; j < phi->OperandCount(); ++j) { | 
| 1022       HValue* op = phi->OperandAt(j); | 1022       HValue* op = phi->OperandAt(j); | 
| 1023       LOperand* operand = NULL; | 1023       LOperand* operand = NULL; | 
| 1024       if (op->IsConstant() && op->EmitAtUses()) { | 1024       if (op->IsConstant() && op->EmitAtUses()) { | 
| 1025         HConstant* constant = HConstant::cast(op); | 1025         HConstant* constant = HConstant::cast(op); | 
| 1026         operand = chunk_->DefineConstantOperand(constant); | 1026         operand = chunk_->DefineConstantOperand(constant); | 
| 1027       } else { | 1027       } else { | 
| 1028         ASSERT(!op->EmitAtUses()); | 1028         DCHECK(!op->EmitAtUses()); | 
| 1029         LUnallocated* unalloc = | 1029         LUnallocated* unalloc = | 
| 1030             new(chunk()->zone()) LUnallocated(LUnallocated::ANY); | 1030             new(chunk()->zone()) LUnallocated(LUnallocated::ANY); | 
| 1031         unalloc->set_virtual_register(op->id()); | 1031         unalloc->set_virtual_register(op->id()); | 
| 1032         operand = unalloc; | 1032         operand = unalloc; | 
| 1033       } | 1033       } | 
| 1034       HBasicBlock* cur_block = block->predecessors()->at(j); | 1034       HBasicBlock* cur_block = block->predecessors()->at(j); | 
| 1035       // The gap move must be added without any special processing as in | 1035       // The gap move must be added without any special processing as in | 
| 1036       // the AddConstraintsGapMove. | 1036       // the AddConstraintsGapMove. | 
| 1037       chunk_->AddGapMove(cur_block->last_instruction_index() - 1, | 1037       chunk_->AddGapMove(cur_block->last_instruction_index() - 1, | 
| 1038                          operand, | 1038                          operand, | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 1060     LiveRange* live_range = LiveRangeFor(phi->id()); | 1060     LiveRange* live_range = LiveRangeFor(phi->id()); | 
| 1061     LLabel* label = chunk_->GetLabel(phi->block()->block_id()); | 1061     LLabel* label = chunk_->GetLabel(phi->block()->block_id()); | 
| 1062     label->GetOrCreateParallelMove(LGap::START, chunk()->zone())-> | 1062     label->GetOrCreateParallelMove(LGap::START, chunk()->zone())-> | 
| 1063         AddMove(phi_operand, live_range->GetSpillOperand(), chunk()->zone()); | 1063         AddMove(phi_operand, live_range->GetSpillOperand(), chunk()->zone()); | 
| 1064     live_range->SetSpillStartIndex(phi->block()->first_instruction_index()); | 1064     live_range->SetSpillStartIndex(phi->block()->first_instruction_index()); | 
| 1065   } | 1065   } | 
| 1066 } | 1066 } | 
| 1067 | 1067 | 
| 1068 | 1068 | 
| 1069 bool LAllocator::Allocate(LChunk* chunk) { | 1069 bool LAllocator::Allocate(LChunk* chunk) { | 
| 1070   ASSERT(chunk_ == NULL); | 1070   DCHECK(chunk_ == NULL); | 
| 1071   chunk_ = static_cast<LPlatformChunk*>(chunk); | 1071   chunk_ = static_cast<LPlatformChunk*>(chunk); | 
| 1072   assigned_registers_ = | 1072   assigned_registers_ = | 
| 1073       new(chunk->zone()) BitVector(Register::NumAllocatableRegisters(), | 1073       new(chunk->zone()) BitVector(Register::NumAllocatableRegisters(), | 
| 1074                                    chunk->zone()); | 1074                                    chunk->zone()); | 
| 1075   assigned_double_registers_ = | 1075   assigned_double_registers_ = | 
| 1076       new(chunk->zone()) BitVector(DoubleRegister::NumAllocatableRegisters(), | 1076       new(chunk->zone()) BitVector(DoubleRegister::NumAllocatableRegisters(), | 
| 1077                                    chunk->zone()); | 1077                                    chunk->zone()); | 
| 1078   MeetRegisterConstraints(); | 1078   MeetRegisterConstraints(); | 
| 1079   if (!AllocationOk()) return false; | 1079   if (!AllocationOk()) return false; | 
| 1080   ResolvePhis(); | 1080   ResolvePhis(); | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1118                                     HBasicBlock* pred) { | 1118                                     HBasicBlock* pred) { | 
| 1119   LifetimePosition pred_end = | 1119   LifetimePosition pred_end = | 
| 1120       LifetimePosition::FromInstructionIndex(pred->last_instruction_index()); | 1120       LifetimePosition::FromInstructionIndex(pred->last_instruction_index()); | 
| 1121   LifetimePosition cur_start = | 1121   LifetimePosition cur_start = | 
| 1122       LifetimePosition::FromInstructionIndex(block->first_instruction_index()); | 1122       LifetimePosition::FromInstructionIndex(block->first_instruction_index()); | 
| 1123   LiveRange* pred_cover = NULL; | 1123   LiveRange* pred_cover = NULL; | 
| 1124   LiveRange* cur_cover = NULL; | 1124   LiveRange* cur_cover = NULL; | 
| 1125   LiveRange* cur_range = range; | 1125   LiveRange* cur_range = range; | 
| 1126   while (cur_range != NULL && (cur_cover == NULL || pred_cover == NULL)) { | 1126   while (cur_range != NULL && (cur_cover == NULL || pred_cover == NULL)) { | 
| 1127     if (cur_range->CanCover(cur_start)) { | 1127     if (cur_range->CanCover(cur_start)) { | 
| 1128       ASSERT(cur_cover == NULL); | 1128       DCHECK(cur_cover == NULL); | 
| 1129       cur_cover = cur_range; | 1129       cur_cover = cur_range; | 
| 1130     } | 1130     } | 
| 1131     if (cur_range->CanCover(pred_end)) { | 1131     if (cur_range->CanCover(pred_end)) { | 
| 1132       ASSERT(pred_cover == NULL); | 1132       DCHECK(pred_cover == NULL); | 
| 1133       pred_cover = cur_range; | 1133       pred_cover = cur_range; | 
| 1134     } | 1134     } | 
| 1135     cur_range = cur_range->next(); | 1135     cur_range = cur_range->next(); | 
| 1136   } | 1136   } | 
| 1137 | 1137 | 
| 1138   if (cur_cover->IsSpilled()) return; | 1138   if (cur_cover->IsSpilled()) return; | 
| 1139   ASSERT(pred_cover != NULL && cur_cover != NULL); | 1139   DCHECK(pred_cover != NULL && cur_cover != NULL); | 
| 1140   if (pred_cover != cur_cover) { | 1140   if (pred_cover != cur_cover) { | 
| 1141     LOperand* pred_op = pred_cover->CreateAssignedOperand(chunk()->zone()); | 1141     LOperand* pred_op = pred_cover->CreateAssignedOperand(chunk()->zone()); | 
| 1142     LOperand* cur_op = cur_cover->CreateAssignedOperand(chunk()->zone()); | 1142     LOperand* cur_op = cur_cover->CreateAssignedOperand(chunk()->zone()); | 
| 1143     if (!pred_op->Equals(cur_op)) { | 1143     if (!pred_op->Equals(cur_op)) { | 
| 1144       LGap* gap = NULL; | 1144       LGap* gap = NULL; | 
| 1145       if (block->predecessors()->length() == 1) { | 1145       if (block->predecessors()->length() == 1) { | 
| 1146         gap = GapAt(block->first_instruction_index()); | 1146         gap = GapAt(block->first_instruction_index()); | 
| 1147       } else { | 1147       } else { | 
| 1148         ASSERT(pred->end()->SecondSuccessor() == NULL); | 1148         DCHECK(pred->end()->SecondSuccessor() == NULL); | 
| 1149         gap = GetLastGap(pred); | 1149         gap = GetLastGap(pred); | 
| 1150 | 1150 | 
| 1151         // We are going to insert a move before the branch instruction. | 1151         // We are going to insert a move before the branch instruction. | 
| 1152         // Some branch instructions (e.g. loops' back edges) | 1152         // Some branch instructions (e.g. loops' back edges) | 
| 1153         // can potentially cause a GC so they have a pointer map. | 1153         // can potentially cause a GC so they have a pointer map. | 
| 1154         // By inserting a move we essentially create a copy of a | 1154         // By inserting a move we essentially create a copy of a | 
| 1155         // value which is invisible to PopulatePointerMaps(), because we store | 1155         // value which is invisible to PopulatePointerMaps(), because we store | 
| 1156         // it into a location different from the operand of a live range | 1156         // it into a location different from the operand of a live range | 
| 1157         // covering a branch instruction. | 1157         // covering a branch instruction. | 
| 1158         // Thus we need to manually record a pointer. | 1158         // Thus we need to manually record a pointer. | 
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1287                                                          chunk()->zone()); | 1287                                                          chunk()->zone()); | 
| 1288       for (int j = 0; j < move->move_operands()->length(); ++j) { | 1288       for (int j = 0; j < move->move_operands()->length(); ++j) { | 
| 1289         LOperand* to = move->move_operands()->at(j).destination(); | 1289         LOperand* to = move->move_operands()->at(j).destination(); | 
| 1290         if (to->IsUnallocated() && | 1290         if (to->IsUnallocated() && | 
| 1291             LUnallocated::cast(to)->virtual_register() == phi->id()) { | 1291             LUnallocated::cast(to)->virtual_register() == phi->id()) { | 
| 1292           hint = move->move_operands()->at(j).source(); | 1292           hint = move->move_operands()->at(j).source(); | 
| 1293           phi_operand = to; | 1293           phi_operand = to; | 
| 1294           break; | 1294           break; | 
| 1295         } | 1295         } | 
| 1296       } | 1296       } | 
| 1297       ASSERT(hint != NULL); | 1297       DCHECK(hint != NULL); | 
| 1298 | 1298 | 
| 1299       LifetimePosition block_start = LifetimePosition::FromInstructionIndex( | 1299       LifetimePosition block_start = LifetimePosition::FromInstructionIndex( | 
| 1300               block->first_instruction_index()); | 1300               block->first_instruction_index()); | 
| 1301       Define(block_start, phi_operand, hint); | 1301       Define(block_start, phi_operand, hint); | 
| 1302     } | 1302     } | 
| 1303 | 1303 | 
| 1304     // Now live is live_in for this block except not including values live | 1304     // Now live is live_in for this block except not including values live | 
| 1305     // out on backward successor edges. | 1305     // out on backward successor edges. | 
| 1306     live_in_sets_[block_id] = live; | 1306     live_in_sets_[block_id] = live; | 
| 1307 | 1307 | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 1334     if (block_id == 0) { | 1334     if (block_id == 0) { | 
| 1335       BitVector::Iterator iterator(live); | 1335       BitVector::Iterator iterator(live); | 
| 1336       bool found = false; | 1336       bool found = false; | 
| 1337       while (!iterator.Done()) { | 1337       while (!iterator.Done()) { | 
| 1338         found = true; | 1338         found = true; | 
| 1339         int operand_index = iterator.Current(); | 1339         int operand_index = iterator.Current(); | 
| 1340         if (chunk_->info()->IsStub()) { | 1340         if (chunk_->info()->IsStub()) { | 
| 1341           CodeStub::Major major_key = chunk_->info()->code_stub()->MajorKey(); | 1341           CodeStub::Major major_key = chunk_->info()->code_stub()->MajorKey(); | 
| 1342           PrintF("Function: %s\n", CodeStub::MajorName(major_key, false)); | 1342           PrintF("Function: %s\n", CodeStub::MajorName(major_key, false)); | 
| 1343         } else { | 1343         } else { | 
| 1344           ASSERT(chunk_->info()->IsOptimizing()); | 1344           DCHECK(chunk_->info()->IsOptimizing()); | 
| 1345           AllowHandleDereference allow_deref; | 1345           AllowHandleDereference allow_deref; | 
| 1346           PrintF("Function: %s\n", | 1346           PrintF("Function: %s\n", | 
| 1347                  chunk_->info()->function()->debug_name()->ToCString().get()); | 1347                  chunk_->info()->function()->debug_name()->ToCString().get()); | 
| 1348         } | 1348         } | 
| 1349         PrintF("Value %d used before first definition!\n", operand_index); | 1349         PrintF("Value %d used before first definition!\n", operand_index); | 
| 1350         LiveRange* range = LiveRangeFor(operand_index); | 1350         LiveRange* range = LiveRangeFor(operand_index); | 
| 1351         PrintF("First use is at %d\n", range->first_pos()->pos().Value()); | 1351         PrintF("First use is at %d\n", range->first_pos()->pos().Value()); | 
| 1352         iterator.Advance(); | 1352         iterator.Advance(); | 
| 1353       } | 1353       } | 
| 1354       ASSERT(!found); | 1354       DCHECK(!found); | 
| 1355     } | 1355     } | 
| 1356 #endif | 1356 #endif | 
| 1357   } | 1357   } | 
| 1358 | 1358 | 
| 1359   for (int i = 0; i < live_ranges_.length(); ++i) { | 1359   for (int i = 0; i < live_ranges_.length(); ++i) { | 
| 1360     if (live_ranges_[i] != NULL) { | 1360     if (live_ranges_[i] != NULL) { | 
| 1361       live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); | 1361       live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); | 
| 1362     } | 1362     } | 
| 1363   } | 1363   } | 
| 1364 } | 1364 } | 
| 1365 | 1365 | 
| 1366 | 1366 | 
| 1367 bool LAllocator::SafePointsAreInOrder() const { | 1367 bool LAllocator::SafePointsAreInOrder() const { | 
| 1368   const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps(); | 1368   const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps(); | 
| 1369   int safe_point = 0; | 1369   int safe_point = 0; | 
| 1370   for (int i = 0; i < pointer_maps->length(); ++i) { | 1370   for (int i = 0; i < pointer_maps->length(); ++i) { | 
| 1371     LPointerMap* map = pointer_maps->at(i); | 1371     LPointerMap* map = pointer_maps->at(i); | 
| 1372     if (safe_point > map->lithium_position()) return false; | 1372     if (safe_point > map->lithium_position()) return false; | 
| 1373     safe_point = map->lithium_position(); | 1373     safe_point = map->lithium_position(); | 
| 1374   } | 1374   } | 
| 1375   return true; | 1375   return true; | 
| 1376 } | 1376 } | 
| 1377 | 1377 | 
| 1378 | 1378 | 
| 1379 void LAllocator::PopulatePointerMaps() { | 1379 void LAllocator::PopulatePointerMaps() { | 
| 1380   LAllocatorPhase phase("L_Populate pointer maps", this); | 1380   LAllocatorPhase phase("L_Populate pointer maps", this); | 
| 1381   const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps(); | 1381   const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps(); | 
| 1382 | 1382 | 
| 1383   ASSERT(SafePointsAreInOrder()); | 1383   DCHECK(SafePointsAreInOrder()); | 
| 1384 | 1384 | 
| 1385   // Iterate over all safe point positions and record a pointer | 1385   // Iterate over all safe point positions and record a pointer | 
| 1386   // for all spilled live ranges at this point. | 1386   // for all spilled live ranges at this point. | 
| 1387   int first_safe_point_index = 0; | 1387   int first_safe_point_index = 0; | 
| 1388   int last_range_start = 0; | 1388   int last_range_start = 0; | 
| 1389   for (int range_idx = 0; range_idx < live_ranges()->length(); ++range_idx) { | 1389   for (int range_idx = 0; range_idx < live_ranges()->length(); ++range_idx) { | 
| 1390     LiveRange* range = live_ranges()->at(range_idx); | 1390     LiveRange* range = live_ranges()->at(range_idx); | 
| 1391     if (range == NULL) continue; | 1391     if (range == NULL) continue; | 
| 1392     // Iterate over the first parts of multi-part live ranges. | 1392     // Iterate over the first parts of multi-part live ranges. | 
| 1393     if (range->parent() != NULL) continue; | 1393     if (range->parent() != NULL) continue; | 
| 1394     // Skip non-pointer values. | 1394     // Skip non-pointer values. | 
| 1395     if (!HasTaggedValue(range->id())) continue; | 1395     if (!HasTaggedValue(range->id())) continue; | 
| 1396     // Skip empty live ranges. | 1396     // Skip empty live ranges. | 
| 1397     if (range->IsEmpty()) continue; | 1397     if (range->IsEmpty()) continue; | 
| 1398 | 1398 | 
| 1399     // Find the extent of the range and its children. | 1399     // Find the extent of the range and its children. | 
| 1400     int start = range->Start().InstructionIndex(); | 1400     int start = range->Start().InstructionIndex(); | 
| 1401     int end = 0; | 1401     int end = 0; | 
| 1402     for (LiveRange* cur = range; cur != NULL; cur = cur->next()) { | 1402     for (LiveRange* cur = range; cur != NULL; cur = cur->next()) { | 
| 1403       LifetimePosition this_end = cur->End(); | 1403       LifetimePosition this_end = cur->End(); | 
| 1404       if (this_end.InstructionIndex() > end) end = this_end.InstructionIndex(); | 1404       if (this_end.InstructionIndex() > end) end = this_end.InstructionIndex(); | 
| 1405       ASSERT(cur->Start().InstructionIndex() >= start); | 1405       DCHECK(cur->Start().InstructionIndex() >= start); | 
| 1406     } | 1406     } | 
| 1407 | 1407 | 
| 1408     // Most of the ranges are in order, but not all.  Keep an eye on when | 1408     // Most of the ranges are in order, but not all.  Keep an eye on when | 
| 1409     // they step backwards and reset the first_safe_point_index so we don't | 1409     // they step backwards and reset the first_safe_point_index so we don't | 
| 1410     // miss any safe points. | 1410     // miss any safe points. | 
| 1411     if (start < last_range_start) { | 1411     if (start < last_range_start) { | 
| 1412       first_safe_point_index = 0; | 1412       first_safe_point_index = 0; | 
| 1413     } | 1413     } | 
| 1414     last_range_start = start; | 1414     last_range_start = start; | 
| 1415 | 1415 | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1449         TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n", | 1449         TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n", | 
| 1450                    range->id(), range->spill_start_index(), safe_point); | 1450                    range->id(), range->spill_start_index(), safe_point); | 
| 1451         map->RecordPointer(range->GetSpillOperand(), chunk()->zone()); | 1451         map->RecordPointer(range->GetSpillOperand(), chunk()->zone()); | 
| 1452       } | 1452       } | 
| 1453 | 1453 | 
| 1454       if (!cur->IsSpilled()) { | 1454       if (!cur->IsSpilled()) { | 
| 1455         TraceAlloc("Pointer in register for range %d (start at %d) " | 1455         TraceAlloc("Pointer in register for range %d (start at %d) " | 
| 1456                    "at safe point %d\n", | 1456                    "at safe point %d\n", | 
| 1457                    cur->id(), cur->Start().Value(), safe_point); | 1457                    cur->id(), cur->Start().Value(), safe_point); | 
| 1458         LOperand* operand = cur->CreateAssignedOperand(chunk()->zone()); | 1458         LOperand* operand = cur->CreateAssignedOperand(chunk()->zone()); | 
| 1459         ASSERT(!operand->IsStackSlot()); | 1459         DCHECK(!operand->IsStackSlot()); | 
| 1460         map->RecordPointer(operand, chunk()->zone()); | 1460         map->RecordPointer(operand, chunk()->zone()); | 
| 1461       } | 1461       } | 
| 1462     } | 1462     } | 
| 1463   } | 1463   } | 
| 1464 } | 1464 } | 
| 1465 | 1465 | 
| 1466 | 1466 | 
| 1467 void LAllocator::AllocateGeneralRegisters() { | 1467 void LAllocator::AllocateGeneralRegisters() { | 
| 1468   LAllocatorPhase phase("L_Allocate general registers", this); | 1468   LAllocatorPhase phase("L_Allocate general registers", this); | 
| 1469   num_registers_ = Register::NumAllocatableRegisters(); | 1469   num_registers_ = Register::NumAllocatableRegisters(); | 
| 1470   mode_ = GENERAL_REGISTERS; | 1470   mode_ = GENERAL_REGISTERS; | 
| 1471   AllocateRegisters(); | 1471   AllocateRegisters(); | 
| 1472 } | 1472 } | 
| 1473 | 1473 | 
| 1474 | 1474 | 
| 1475 void LAllocator::AllocateDoubleRegisters() { | 1475 void LAllocator::AllocateDoubleRegisters() { | 
| 1476   LAllocatorPhase phase("L_Allocate double registers", this); | 1476   LAllocatorPhase phase("L_Allocate double registers", this); | 
| 1477   num_registers_ = DoubleRegister::NumAllocatableRegisters(); | 1477   num_registers_ = DoubleRegister::NumAllocatableRegisters(); | 
| 1478   mode_ = DOUBLE_REGISTERS; | 1478   mode_ = DOUBLE_REGISTERS; | 
| 1479   AllocateRegisters(); | 1479   AllocateRegisters(); | 
| 1480 } | 1480 } | 
| 1481 | 1481 | 
| 1482 | 1482 | 
| 1483 void LAllocator::AllocateRegisters() { | 1483 void LAllocator::AllocateRegisters() { | 
| 1484   ASSERT(unhandled_live_ranges_.is_empty()); | 1484   DCHECK(unhandled_live_ranges_.is_empty()); | 
| 1485 | 1485 | 
| 1486   for (int i = 0; i < live_ranges_.length(); ++i) { | 1486   for (int i = 0; i < live_ranges_.length(); ++i) { | 
| 1487     if (live_ranges_[i] != NULL) { | 1487     if (live_ranges_[i] != NULL) { | 
| 1488       if (live_ranges_[i]->Kind() == mode_) { | 1488       if (live_ranges_[i]->Kind() == mode_) { | 
| 1489         AddToUnhandledUnsorted(live_ranges_[i]); | 1489         AddToUnhandledUnsorted(live_ranges_[i]); | 
| 1490       } | 1490       } | 
| 1491     } | 1491     } | 
| 1492   } | 1492   } | 
| 1493   SortUnhandled(); | 1493   SortUnhandled(); | 
| 1494   ASSERT(UnhandledIsSorted()); | 1494   DCHECK(UnhandledIsSorted()); | 
| 1495 | 1495 | 
| 1496   ASSERT(reusable_slots_.is_empty()); | 1496   DCHECK(reusable_slots_.is_empty()); | 
| 1497   ASSERT(active_live_ranges_.is_empty()); | 1497   DCHECK(active_live_ranges_.is_empty()); | 
| 1498   ASSERT(inactive_live_ranges_.is_empty()); | 1498   DCHECK(inactive_live_ranges_.is_empty()); | 
| 1499 | 1499 | 
| 1500   if (mode_ == DOUBLE_REGISTERS) { | 1500   if (mode_ == DOUBLE_REGISTERS) { | 
| 1501     for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) { | 1501     for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) { | 
| 1502       LiveRange* current = fixed_double_live_ranges_.at(i); | 1502       LiveRange* current = fixed_double_live_ranges_.at(i); | 
| 1503       if (current != NULL) { | 1503       if (current != NULL) { | 
| 1504         AddToInactive(current); | 1504         AddToInactive(current); | 
| 1505       } | 1505       } | 
| 1506     } | 1506     } | 
| 1507   } else { | 1507   } else { | 
| 1508     ASSERT(mode_ == GENERAL_REGISTERS); | 1508     DCHECK(mode_ == GENERAL_REGISTERS); | 
| 1509     for (int i = 0; i < fixed_live_ranges_.length(); ++i) { | 1509     for (int i = 0; i < fixed_live_ranges_.length(); ++i) { | 
| 1510       LiveRange* current = fixed_live_ranges_.at(i); | 1510       LiveRange* current = fixed_live_ranges_.at(i); | 
| 1511       if (current != NULL) { | 1511       if (current != NULL) { | 
| 1512         AddToInactive(current); | 1512         AddToInactive(current); | 
| 1513       } | 1513       } | 
| 1514     } | 1514     } | 
| 1515   } | 1515   } | 
| 1516 | 1516 | 
| 1517   while (!unhandled_live_ranges_.is_empty()) { | 1517   while (!unhandled_live_ranges_.is_empty()) { | 
| 1518     ASSERT(UnhandledIsSorted()); | 1518     DCHECK(UnhandledIsSorted()); | 
| 1519     LiveRange* current = unhandled_live_ranges_.RemoveLast(); | 1519     LiveRange* current = unhandled_live_ranges_.RemoveLast(); | 
| 1520     ASSERT(UnhandledIsSorted()); | 1520     DCHECK(UnhandledIsSorted()); | 
| 1521     LifetimePosition position = current->Start(); | 1521     LifetimePosition position = current->Start(); | 
| 1522 #ifdef DEBUG | 1522 #ifdef DEBUG | 
| 1523     allocation_finger_ = position; | 1523     allocation_finger_ = position; | 
| 1524 #endif | 1524 #endif | 
| 1525     TraceAlloc("Processing interval %d start=%d\n", | 1525     TraceAlloc("Processing interval %d start=%d\n", | 
| 1526                current->id(), | 1526                current->id(), | 
| 1527                position.Value()); | 1527                position.Value()); | 
| 1528 | 1528 | 
| 1529     if (current->HasAllocatedSpillOperand()) { | 1529     if (current->HasAllocatedSpillOperand()) { | 
| 1530       TraceAlloc("Live range %d already has a spill operand\n", current->id()); | 1530       TraceAlloc("Live range %d already has a spill operand\n", current->id()); | 
| 1531       LifetimePosition next_pos = position; | 1531       LifetimePosition next_pos = position; | 
| 1532       if (IsGapAt(next_pos.InstructionIndex())) { | 1532       if (IsGapAt(next_pos.InstructionIndex())) { | 
| 1533         next_pos = next_pos.NextInstruction(); | 1533         next_pos = next_pos.NextInstruction(); | 
| 1534       } | 1534       } | 
| 1535       UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); | 1535       UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); | 
| 1536       // If the range already has a spill operand and it doesn't need a | 1536       // If the range already has a spill operand and it doesn't need a | 
| 1537       // register immediately, split it and spill the first part of the range. | 1537       // register immediately, split it and spill the first part of the range. | 
| 1538       if (pos == NULL) { | 1538       if (pos == NULL) { | 
| 1539         Spill(current); | 1539         Spill(current); | 
| 1540         continue; | 1540         continue; | 
| 1541       } else if (pos->pos().Value() > | 1541       } else if (pos->pos().Value() > | 
| 1542                  current->Start().NextInstruction().Value()) { | 1542                  current->Start().NextInstruction().Value()) { | 
| 1543         // Do not spill live range eagerly if use position that can benefit from | 1543         // Do not spill live range eagerly if use position that can benefit from | 
| 1544         // the register is too close to the start of live range. | 1544         // the register is too close to the start of live range. | 
| 1545         SpillBetween(current, current->Start(), pos->pos()); | 1545         SpillBetween(current, current->Start(), pos->pos()); | 
| 1546         if (!AllocationOk()) return; | 1546         if (!AllocationOk()) return; | 
| 1547         ASSERT(UnhandledIsSorted()); | 1547         DCHECK(UnhandledIsSorted()); | 
| 1548         continue; | 1548         continue; | 
| 1549       } | 1549       } | 
| 1550     } | 1550     } | 
| 1551 | 1551 | 
| 1552     for (int i = 0; i < active_live_ranges_.length(); ++i) { | 1552     for (int i = 0; i < active_live_ranges_.length(); ++i) { | 
| 1553       LiveRange* cur_active = active_live_ranges_.at(i); | 1553       LiveRange* cur_active = active_live_ranges_.at(i); | 
| 1554       if (cur_active->End().Value() <= position.Value()) { | 1554       if (cur_active->End().Value() <= position.Value()) { | 
| 1555         ActiveToHandled(cur_active); | 1555         ActiveToHandled(cur_active); | 
| 1556         --i;  // The live range was removed from the list of active live ranges. | 1556         --i;  // The live range was removed from the list of active live ranges. | 
| 1557       } else if (!cur_active->Covers(position)) { | 1557       } else if (!cur_active->Covers(position)) { | 
| 1558         ActiveToInactive(cur_active); | 1558         ActiveToInactive(cur_active); | 
| 1559         --i;  // The live range was removed from the list of active live ranges. | 1559         --i;  // The live range was removed from the list of active live ranges. | 
| 1560       } | 1560       } | 
| 1561     } | 1561     } | 
| 1562 | 1562 | 
| 1563     for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 1563     for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 
| 1564       LiveRange* cur_inactive = inactive_live_ranges_.at(i); | 1564       LiveRange* cur_inactive = inactive_live_ranges_.at(i); | 
| 1565       if (cur_inactive->End().Value() <= position.Value()) { | 1565       if (cur_inactive->End().Value() <= position.Value()) { | 
| 1566         InactiveToHandled(cur_inactive); | 1566         InactiveToHandled(cur_inactive); | 
| 1567         --i;  // Live range was removed from the list of inactive live ranges. | 1567         --i;  // Live range was removed from the list of inactive live ranges. | 
| 1568       } else if (cur_inactive->Covers(position)) { | 1568       } else if (cur_inactive->Covers(position)) { | 
| 1569         InactiveToActive(cur_inactive); | 1569         InactiveToActive(cur_inactive); | 
| 1570         --i;  // Live range was removed from the list of inactive live ranges. | 1570         --i;  // Live range was removed from the list of inactive live ranges. | 
| 1571       } | 1571       } | 
| 1572     } | 1572     } | 
| 1573 | 1573 | 
| 1574     ASSERT(!current->HasRegisterAssigned() && !current->IsSpilled()); | 1574     DCHECK(!current->HasRegisterAssigned() && !current->IsSpilled()); | 
| 1575 | 1575 | 
| 1576     bool result = TryAllocateFreeReg(current); | 1576     bool result = TryAllocateFreeReg(current); | 
| 1577     if (!AllocationOk()) return; | 1577     if (!AllocationOk()) return; | 
| 1578 | 1578 | 
| 1579     if (!result) AllocateBlockedReg(current); | 1579     if (!result) AllocateBlockedReg(current); | 
| 1580     if (!AllocationOk()) return; | 1580     if (!AllocationOk()) return; | 
| 1581 | 1581 | 
| 1582     if (current->HasRegisterAssigned()) { | 1582     if (current->HasRegisterAssigned()) { | 
| 1583       AddToActive(current); | 1583       AddToActive(current); | 
| 1584     } | 1584     } | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1638 | 1638 | 
| 1639 | 1639 | 
| 1640 void LAllocator::AddToInactive(LiveRange* range) { | 1640 void LAllocator::AddToInactive(LiveRange* range) { | 
| 1641   TraceAlloc("Add live range %d to inactive\n", range->id()); | 1641   TraceAlloc("Add live range %d to inactive\n", range->id()); | 
| 1642   inactive_live_ranges_.Add(range, zone()); | 1642   inactive_live_ranges_.Add(range, zone()); | 
| 1643 } | 1643 } | 
| 1644 | 1644 | 
| 1645 | 1645 | 
| 1646 void LAllocator::AddToUnhandledSorted(LiveRange* range) { | 1646 void LAllocator::AddToUnhandledSorted(LiveRange* range) { | 
| 1647   if (range == NULL || range->IsEmpty()) return; | 1647   if (range == NULL || range->IsEmpty()) return; | 
| 1648   ASSERT(!range->HasRegisterAssigned() && !range->IsSpilled()); | 1648   DCHECK(!range->HasRegisterAssigned() && !range->IsSpilled()); | 
| 1649   ASSERT(allocation_finger_.Value() <= range->Start().Value()); | 1649   DCHECK(allocation_finger_.Value() <= range->Start().Value()); | 
| 1650   for (int i = unhandled_live_ranges_.length() - 1; i >= 0; --i) { | 1650   for (int i = unhandled_live_ranges_.length() - 1; i >= 0; --i) { | 
| 1651     LiveRange* cur_range = unhandled_live_ranges_.at(i); | 1651     LiveRange* cur_range = unhandled_live_ranges_.at(i); | 
| 1652     if (range->ShouldBeAllocatedBefore(cur_range)) { | 1652     if (range->ShouldBeAllocatedBefore(cur_range)) { | 
| 1653       TraceAlloc("Add live range %d to unhandled at %d\n", range->id(), i + 1); | 1653       TraceAlloc("Add live range %d to unhandled at %d\n", range->id(), i + 1); | 
| 1654       unhandled_live_ranges_.InsertAt(i + 1, range, zone()); | 1654       unhandled_live_ranges_.InsertAt(i + 1, range, zone()); | 
| 1655       ASSERT(UnhandledIsSorted()); | 1655       DCHECK(UnhandledIsSorted()); | 
| 1656       return; | 1656       return; | 
| 1657     } | 1657     } | 
| 1658   } | 1658   } | 
| 1659   TraceAlloc("Add live range %d to unhandled at start\n", range->id()); | 1659   TraceAlloc("Add live range %d to unhandled at start\n", range->id()); | 
| 1660   unhandled_live_ranges_.InsertAt(0, range, zone()); | 1660   unhandled_live_ranges_.InsertAt(0, range, zone()); | 
| 1661   ASSERT(UnhandledIsSorted()); | 1661   DCHECK(UnhandledIsSorted()); | 
| 1662 } | 1662 } | 
| 1663 | 1663 | 
| 1664 | 1664 | 
| 1665 void LAllocator::AddToUnhandledUnsorted(LiveRange* range) { | 1665 void LAllocator::AddToUnhandledUnsorted(LiveRange* range) { | 
| 1666   if (range == NULL || range->IsEmpty()) return; | 1666   if (range == NULL || range->IsEmpty()) return; | 
| 1667   ASSERT(!range->HasRegisterAssigned() && !range->IsSpilled()); | 1667   DCHECK(!range->HasRegisterAssigned() && !range->IsSpilled()); | 
| 1668   TraceAlloc("Add live range %d to unhandled unsorted at end\n", range->id()); | 1668   TraceAlloc("Add live range %d to unhandled unsorted at end\n", range->id()); | 
| 1669   unhandled_live_ranges_.Add(range, zone()); | 1669   unhandled_live_ranges_.Add(range, zone()); | 
| 1670 } | 1670 } | 
| 1671 | 1671 | 
| 1672 | 1672 | 
| 1673 static int UnhandledSortHelper(LiveRange* const* a, LiveRange* const* b) { | 1673 static int UnhandledSortHelper(LiveRange* const* a, LiveRange* const* b) { | 
| 1674   ASSERT(!(*a)->ShouldBeAllocatedBefore(*b) || | 1674   DCHECK(!(*a)->ShouldBeAllocatedBefore(*b) || | 
| 1675          !(*b)->ShouldBeAllocatedBefore(*a)); | 1675          !(*b)->ShouldBeAllocatedBefore(*a)); | 
| 1676   if ((*a)->ShouldBeAllocatedBefore(*b)) return 1; | 1676   if ((*a)->ShouldBeAllocatedBefore(*b)) return 1; | 
| 1677   if ((*b)->ShouldBeAllocatedBefore(*a)) return -1; | 1677   if ((*b)->ShouldBeAllocatedBefore(*a)) return -1; | 
| 1678   return (*a)->id() - (*b)->id(); | 1678   return (*a)->id() - (*b)->id(); | 
| 1679 } | 1679 } | 
| 1680 | 1680 | 
| 1681 | 1681 | 
| 1682 // Sort the unhandled live ranges so that the ranges to be processed first are | 1682 // Sort the unhandled live ranges so that the ranges to be processed first are | 
| 1683 // at the end of the array list.  This is convenient for the register allocation | 1683 // at the end of the array list.  This is convenient for the register allocation | 
| 1684 // algorithm because it is efficient to remove elements from the end. | 1684 // algorithm because it is efficient to remove elements from the end. | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1718       range->TopLevel()->Start().Value()) { | 1718       range->TopLevel()->Start().Value()) { | 
| 1719     return NULL; | 1719     return NULL; | 
| 1720   } | 1720   } | 
| 1721   LOperand* result = reusable_slots_.first()->TopLevel()->GetSpillOperand(); | 1721   LOperand* result = reusable_slots_.first()->TopLevel()->GetSpillOperand(); | 
| 1722   reusable_slots_.Remove(0); | 1722   reusable_slots_.Remove(0); | 
| 1723   return result; | 1723   return result; | 
| 1724 } | 1724 } | 
| 1725 | 1725 | 
| 1726 | 1726 | 
| 1727 void LAllocator::ActiveToHandled(LiveRange* range) { | 1727 void LAllocator::ActiveToHandled(LiveRange* range) { | 
| 1728   ASSERT(active_live_ranges_.Contains(range)); | 1728   DCHECK(active_live_ranges_.Contains(range)); | 
| 1729   active_live_ranges_.RemoveElement(range); | 1729   active_live_ranges_.RemoveElement(range); | 
| 1730   TraceAlloc("Moving live range %d from active to handled\n", range->id()); | 1730   TraceAlloc("Moving live range %d from active to handled\n", range->id()); | 
| 1731   FreeSpillSlot(range); | 1731   FreeSpillSlot(range); | 
| 1732 } | 1732 } | 
| 1733 | 1733 | 
| 1734 | 1734 | 
| 1735 void LAllocator::ActiveToInactive(LiveRange* range) { | 1735 void LAllocator::ActiveToInactive(LiveRange* range) { | 
| 1736   ASSERT(active_live_ranges_.Contains(range)); | 1736   DCHECK(active_live_ranges_.Contains(range)); | 
| 1737   active_live_ranges_.RemoveElement(range); | 1737   active_live_ranges_.RemoveElement(range); | 
| 1738   inactive_live_ranges_.Add(range, zone()); | 1738   inactive_live_ranges_.Add(range, zone()); | 
| 1739   TraceAlloc("Moving live range %d from active to inactive\n", range->id()); | 1739   TraceAlloc("Moving live range %d from active to inactive\n", range->id()); | 
| 1740 } | 1740 } | 
| 1741 | 1741 | 
| 1742 | 1742 | 
| 1743 void LAllocator::InactiveToHandled(LiveRange* range) { | 1743 void LAllocator::InactiveToHandled(LiveRange* range) { | 
| 1744   ASSERT(inactive_live_ranges_.Contains(range)); | 1744   DCHECK(inactive_live_ranges_.Contains(range)); | 
| 1745   inactive_live_ranges_.RemoveElement(range); | 1745   inactive_live_ranges_.RemoveElement(range); | 
| 1746   TraceAlloc("Moving live range %d from inactive to handled\n", range->id()); | 1746   TraceAlloc("Moving live range %d from inactive to handled\n", range->id()); | 
| 1747   FreeSpillSlot(range); | 1747   FreeSpillSlot(range); | 
| 1748 } | 1748 } | 
| 1749 | 1749 | 
| 1750 | 1750 | 
| 1751 void LAllocator::InactiveToActive(LiveRange* range) { | 1751 void LAllocator::InactiveToActive(LiveRange* range) { | 
| 1752   ASSERT(inactive_live_ranges_.Contains(range)); | 1752   DCHECK(inactive_live_ranges_.Contains(range)); | 
| 1753   inactive_live_ranges_.RemoveElement(range); | 1753   inactive_live_ranges_.RemoveElement(range); | 
| 1754   active_live_ranges_.Add(range, zone()); | 1754   active_live_ranges_.Add(range, zone()); | 
| 1755   TraceAlloc("Moving live range %d from inactive to active\n", range->id()); | 1755   TraceAlloc("Moving live range %d from inactive to active\n", range->id()); | 
| 1756 } | 1756 } | 
| 1757 | 1757 | 
| 1758 | 1758 | 
| 1759 // TryAllocateFreeReg and AllocateBlockedReg assume this | 1759 // TryAllocateFreeReg and AllocateBlockedReg assume this | 
| 1760 // when allocating local arrays. | 1760 // when allocating local arrays. | 
| 1761 STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >= | 1761 STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >= | 
| 1762               Register::kMaxNumAllocatableRegisters); | 1762               Register::kMaxNumAllocatableRegisters); | 
| 1763 | 1763 | 
| 1764 | 1764 | 
| 1765 bool LAllocator::TryAllocateFreeReg(LiveRange* current) { | 1765 bool LAllocator::TryAllocateFreeReg(LiveRange* current) { | 
| 1766   LifetimePosition free_until_pos[DoubleRegister::kMaxNumAllocatableRegisters]; | 1766   LifetimePosition free_until_pos[DoubleRegister::kMaxNumAllocatableRegisters]; | 
| 1767 | 1767 | 
| 1768   for (int i = 0; i < num_registers_; i++) { | 1768   for (int i = 0; i < num_registers_; i++) { | 
| 1769     free_until_pos[i] = LifetimePosition::MaxPosition(); | 1769     free_until_pos[i] = LifetimePosition::MaxPosition(); | 
| 1770   } | 1770   } | 
| 1771 | 1771 | 
| 1772   for (int i = 0; i < active_live_ranges_.length(); ++i) { | 1772   for (int i = 0; i < active_live_ranges_.length(); ++i) { | 
| 1773     LiveRange* cur_active = active_live_ranges_.at(i); | 1773     LiveRange* cur_active = active_live_ranges_.at(i); | 
| 1774     free_until_pos[cur_active->assigned_register()] = | 1774     free_until_pos[cur_active->assigned_register()] = | 
| 1775         LifetimePosition::FromInstructionIndex(0); | 1775         LifetimePosition::FromInstructionIndex(0); | 
| 1776   } | 1776   } | 
| 1777 | 1777 | 
| 1778   for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 1778   for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 
| 1779     LiveRange* cur_inactive = inactive_live_ranges_.at(i); | 1779     LiveRange* cur_inactive = inactive_live_ranges_.at(i); | 
| 1780     ASSERT(cur_inactive->End().Value() > current->Start().Value()); | 1780     DCHECK(cur_inactive->End().Value() > current->Start().Value()); | 
| 1781     LifetimePosition next_intersection = | 1781     LifetimePosition next_intersection = | 
| 1782         cur_inactive->FirstIntersection(current); | 1782         cur_inactive->FirstIntersection(current); | 
| 1783     if (!next_intersection.IsValid()) continue; | 1783     if (!next_intersection.IsValid()) continue; | 
| 1784     int cur_reg = cur_inactive->assigned_register(); | 1784     int cur_reg = cur_inactive->assigned_register(); | 
| 1785     free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); | 1785     free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); | 
| 1786   } | 1786   } | 
| 1787 | 1787 | 
| 1788   LOperand* hint = current->FirstHint(); | 1788   LOperand* hint = current->FirstHint(); | 
| 1789   if (hint != NULL && (hint->IsRegister() || hint->IsDoubleRegister())) { | 1789   if (hint != NULL && (hint->IsRegister() || hint->IsDoubleRegister())) { | 
| 1790     int register_index = hint->index(); | 1790     int register_index = hint->index(); | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1824     // Register reg is available at the range start but becomes blocked before | 1824     // Register reg is available at the range start but becomes blocked before | 
| 1825     // the range end. Split current at position where it becomes blocked. | 1825     // the range end. Split current at position where it becomes blocked. | 
| 1826     LiveRange* tail = SplitRangeAt(current, pos); | 1826     LiveRange* tail = SplitRangeAt(current, pos); | 
| 1827     if (!AllocationOk()) return false; | 1827     if (!AllocationOk()) return false; | 
| 1828     AddToUnhandledSorted(tail); | 1828     AddToUnhandledSorted(tail); | 
| 1829   } | 1829   } | 
| 1830 | 1830 | 
| 1831 | 1831 | 
| 1832   // Register reg is available at the range start and is free until | 1832   // Register reg is available at the range start and is free until | 
| 1833   // the range end. | 1833   // the range end. | 
| 1834   ASSERT(pos.Value() >= current->End().Value()); | 1834   DCHECK(pos.Value() >= current->End().Value()); | 
| 1835   TraceAlloc("Assigning free reg %s to live range %d\n", | 1835   TraceAlloc("Assigning free reg %s to live range %d\n", | 
| 1836              RegisterName(reg), | 1836              RegisterName(reg), | 
| 1837              current->id()); | 1837              current->id()); | 
| 1838   SetLiveRangeAssignedRegister(current, reg); | 1838   SetLiveRangeAssignedRegister(current, reg); | 
| 1839 | 1839 | 
| 1840   return true; | 1840   return true; | 
| 1841 } | 1841 } | 
| 1842 | 1842 | 
| 1843 | 1843 | 
| 1844 void LAllocator::AllocateBlockedReg(LiveRange* current) { | 1844 void LAllocator::AllocateBlockedReg(LiveRange* current) { | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 1870       if (next_use == NULL) { | 1870       if (next_use == NULL) { | 
| 1871         use_pos[cur_reg] = range->End(); | 1871         use_pos[cur_reg] = range->End(); | 
| 1872       } else { | 1872       } else { | 
| 1873         use_pos[cur_reg] = next_use->pos(); | 1873         use_pos[cur_reg] = next_use->pos(); | 
| 1874       } | 1874       } | 
| 1875     } | 1875     } | 
| 1876   } | 1876   } | 
| 1877 | 1877 | 
| 1878   for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 1878   for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 
| 1879     LiveRange* range = inactive_live_ranges_.at(i); | 1879     LiveRange* range = inactive_live_ranges_.at(i); | 
| 1880     ASSERT(range->End().Value() > current->Start().Value()); | 1880     DCHECK(range->End().Value() > current->Start().Value()); | 
| 1881     LifetimePosition next_intersection = range->FirstIntersection(current); | 1881     LifetimePosition next_intersection = range->FirstIntersection(current); | 
| 1882     if (!next_intersection.IsValid()) continue; | 1882     if (!next_intersection.IsValid()) continue; | 
| 1883     int cur_reg = range->assigned_register(); | 1883     int cur_reg = range->assigned_register(); | 
| 1884     if (range->IsFixed()) { | 1884     if (range->IsFixed()) { | 
| 1885       block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); | 1885       block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); | 
| 1886       use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); | 1886       use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); | 
| 1887     } else { | 1887     } else { | 
| 1888       use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); | 1888       use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); | 
| 1889     } | 1889     } | 
| 1890   } | 1890   } | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 1909     // Register becomes blocked before the current range end. Split before that | 1909     // Register becomes blocked before the current range end. Split before that | 
| 1910     // position. | 1910     // position. | 
| 1911     LiveRange* tail = SplitBetween(current, | 1911     LiveRange* tail = SplitBetween(current, | 
| 1912                                    current->Start(), | 1912                                    current->Start(), | 
| 1913                                    block_pos[reg].InstructionStart()); | 1913                                    block_pos[reg].InstructionStart()); | 
| 1914     if (!AllocationOk()) return; | 1914     if (!AllocationOk()) return; | 
| 1915     AddToUnhandledSorted(tail); | 1915     AddToUnhandledSorted(tail); | 
| 1916   } | 1916   } | 
| 1917 | 1917 | 
| 1918   // Register reg is not blocked for the whole range. | 1918   // Register reg is not blocked for the whole range. | 
| 1919   ASSERT(block_pos[reg].Value() >= current->End().Value()); | 1919   DCHECK(block_pos[reg].Value() >= current->End().Value()); | 
| 1920   TraceAlloc("Assigning blocked reg %s to live range %d\n", | 1920   TraceAlloc("Assigning blocked reg %s to live range %d\n", | 
| 1921              RegisterName(reg), | 1921              RegisterName(reg), | 
| 1922              current->id()); | 1922              current->id()); | 
| 1923   SetLiveRangeAssignedRegister(current, reg); | 1923   SetLiveRangeAssignedRegister(current, reg); | 
| 1924 | 1924 | 
| 1925   // This register was not free. Thus we need to find and spill | 1925   // This register was not free. Thus we need to find and spill | 
| 1926   // parts of active and inactive live regions that use the same register | 1926   // parts of active and inactive live regions that use the same register | 
| 1927   // at the same lifetime positions as current. | 1927   // at the same lifetime positions as current. | 
| 1928   SplitAndSpillIntersecting(current); | 1928   SplitAndSpillIntersecting(current); | 
| 1929 } | 1929 } | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 1956 | 1956 | 
| 1957     // Try hoisting out to an outer loop. | 1957     // Try hoisting out to an outer loop. | 
| 1958     loop_header = loop_header->parent_loop_header(); | 1958     loop_header = loop_header->parent_loop_header(); | 
| 1959   } | 1959   } | 
| 1960 | 1960 | 
| 1961   return pos; | 1961   return pos; | 
| 1962 } | 1962 } | 
| 1963 | 1963 | 
| 1964 | 1964 | 
| 1965 void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { | 1965 void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { | 
| 1966   ASSERT(current->HasRegisterAssigned()); | 1966   DCHECK(current->HasRegisterAssigned()); | 
| 1967   int reg = current->assigned_register(); | 1967   int reg = current->assigned_register(); | 
| 1968   LifetimePosition split_pos = current->Start(); | 1968   LifetimePosition split_pos = current->Start(); | 
| 1969   for (int i = 0; i < active_live_ranges_.length(); ++i) { | 1969   for (int i = 0; i < active_live_ranges_.length(); ++i) { | 
| 1970     LiveRange* range = active_live_ranges_[i]; | 1970     LiveRange* range = active_live_ranges_[i]; | 
| 1971     if (range->assigned_register() == reg) { | 1971     if (range->assigned_register() == reg) { | 
| 1972       UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 1972       UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 
| 1973       LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); | 1973       LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); | 
| 1974       if (next_pos == NULL) { | 1974       if (next_pos == NULL) { | 
| 1975         SpillAfter(range, spill_pos); | 1975         SpillAfter(range, spill_pos); | 
| 1976       } else { | 1976       } else { | 
| 1977         // When spilling between spill_pos and next_pos ensure that the range | 1977         // When spilling between spill_pos and next_pos ensure that the range | 
| 1978         // remains spilled at least until the start of the current live range. | 1978         // remains spilled at least until the start of the current live range. | 
| 1979         // This guarantees that we will not introduce new unhandled ranges that | 1979         // This guarantees that we will not introduce new unhandled ranges that | 
| 1980         // start before the current range as this violates allocation invariant | 1980         // start before the current range as this violates allocation invariant | 
| 1981         // and will lead to an inconsistent state of active and inactive | 1981         // and will lead to an inconsistent state of active and inactive | 
| 1982         // live-ranges: ranges are allocated in order of their start positions, | 1982         // live-ranges: ranges are allocated in order of their start positions, | 
| 1983         // ranges are retired from active/inactive when the start of the | 1983         // ranges are retired from active/inactive when the start of the | 
| 1984         // current live-range is larger than their end. | 1984         // current live-range is larger than their end. | 
| 1985         SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); | 1985         SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); | 
| 1986       } | 1986       } | 
| 1987       if (!AllocationOk()) return; | 1987       if (!AllocationOk()) return; | 
| 1988       ActiveToHandled(range); | 1988       ActiveToHandled(range); | 
| 1989       --i; | 1989       --i; | 
| 1990     } | 1990     } | 
| 1991   } | 1991   } | 
| 1992 | 1992 | 
| 1993   for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 1993   for (int i = 0; i < inactive_live_ranges_.length(); ++i) { | 
| 1994     LiveRange* range = inactive_live_ranges_[i]; | 1994     LiveRange* range = inactive_live_ranges_[i]; | 
| 1995     ASSERT(range->End().Value() > current->Start().Value()); | 1995     DCHECK(range->End().Value() > current->Start().Value()); | 
| 1996     if (range->assigned_register() == reg && !range->IsFixed()) { | 1996     if (range->assigned_register() == reg && !range->IsFixed()) { | 
| 1997       LifetimePosition next_intersection = range->FirstIntersection(current); | 1997       LifetimePosition next_intersection = range->FirstIntersection(current); | 
| 1998       if (next_intersection.IsValid()) { | 1998       if (next_intersection.IsValid()) { | 
| 1999         UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 1999         UsePosition* next_pos = range->NextRegisterPosition(current->Start()); | 
| 2000         if (next_pos == NULL) { | 2000         if (next_pos == NULL) { | 
| 2001           SpillAfter(range, split_pos); | 2001           SpillAfter(range, split_pos); | 
| 2002         } else { | 2002         } else { | 
| 2003           next_intersection = Min(next_intersection, next_pos->pos()); | 2003           next_intersection = Min(next_intersection, next_pos->pos()); | 
| 2004           SpillBetween(range, split_pos, next_intersection); | 2004           SpillBetween(range, split_pos, next_intersection); | 
| 2005         } | 2005         } | 
| 2006         if (!AllocationOk()) return; | 2006         if (!AllocationOk()) return; | 
| 2007         InactiveToHandled(range); | 2007         InactiveToHandled(range); | 
| 2008         --i; | 2008         --i; | 
| 2009       } | 2009       } | 
| 2010     } | 2010     } | 
| 2011   } | 2011   } | 
| 2012 } | 2012 } | 
| 2013 | 2013 | 
| 2014 | 2014 | 
| 2015 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { | 2015 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { | 
| 2016   return pos.IsInstructionStart() && | 2016   return pos.IsInstructionStart() && | 
| 2017       InstructionAt(pos.InstructionIndex())->IsLabel(); | 2017       InstructionAt(pos.InstructionIndex())->IsLabel(); | 
| 2018 } | 2018 } | 
| 2019 | 2019 | 
| 2020 | 2020 | 
| 2021 LiveRange* LAllocator::SplitRangeAt(LiveRange* range, LifetimePosition pos) { | 2021 LiveRange* LAllocator::SplitRangeAt(LiveRange* range, LifetimePosition pos) { | 
| 2022   ASSERT(!range->IsFixed()); | 2022   DCHECK(!range->IsFixed()); | 
| 2023   TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); | 2023   TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); | 
| 2024 | 2024 | 
| 2025   if (pos.Value() <= range->Start().Value()) return range; | 2025   if (pos.Value() <= range->Start().Value()) return range; | 
| 2026 | 2026 | 
| 2027   // We can't properly connect liveranges if split occured at the end | 2027   // We can't properly connect liveranges if split occured at the end | 
| 2028   // of control instruction. | 2028   // of control instruction. | 
| 2029   ASSERT(pos.IsInstructionStart() || | 2029   DCHECK(pos.IsInstructionStart() || | 
| 2030          !chunk_->instructions()->at(pos.InstructionIndex())->IsControl()); | 2030          !chunk_->instructions()->at(pos.InstructionIndex())->IsControl()); | 
| 2031 | 2031 | 
| 2032   int vreg = GetVirtualRegister(); | 2032   int vreg = GetVirtualRegister(); | 
| 2033   if (!AllocationOk()) return NULL; | 2033   if (!AllocationOk()) return NULL; | 
| 2034   LiveRange* result = LiveRangeFor(vreg); | 2034   LiveRange* result = LiveRangeFor(vreg); | 
| 2035   range->SplitAt(pos, result, zone()); | 2035   range->SplitAt(pos, result, zone()); | 
| 2036   return result; | 2036   return result; | 
| 2037 } | 2037 } | 
| 2038 | 2038 | 
| 2039 | 2039 | 
| 2040 LiveRange* LAllocator::SplitBetween(LiveRange* range, | 2040 LiveRange* LAllocator::SplitBetween(LiveRange* range, | 
| 2041                                     LifetimePosition start, | 2041                                     LifetimePosition start, | 
| 2042                                     LifetimePosition end) { | 2042                                     LifetimePosition end) { | 
| 2043   ASSERT(!range->IsFixed()); | 2043   DCHECK(!range->IsFixed()); | 
| 2044   TraceAlloc("Splitting live range %d in position between [%d, %d]\n", | 2044   TraceAlloc("Splitting live range %d in position between [%d, %d]\n", | 
| 2045              range->id(), | 2045              range->id(), | 
| 2046              start.Value(), | 2046              start.Value(), | 
| 2047              end.Value()); | 2047              end.Value()); | 
| 2048 | 2048 | 
| 2049   LifetimePosition split_pos = FindOptimalSplitPos(start, end); | 2049   LifetimePosition split_pos = FindOptimalSplitPos(start, end); | 
| 2050   ASSERT(split_pos.Value() >= start.Value()); | 2050   DCHECK(split_pos.Value() >= start.Value()); | 
| 2051   return SplitRangeAt(range, split_pos); | 2051   return SplitRangeAt(range, split_pos); | 
| 2052 } | 2052 } | 
| 2053 | 2053 | 
| 2054 | 2054 | 
| 2055 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start, | 2055 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start, | 
| 2056                                                  LifetimePosition end) { | 2056                                                  LifetimePosition end) { | 
| 2057   int start_instr = start.InstructionIndex(); | 2057   int start_instr = start.InstructionIndex(); | 
| 2058   int end_instr = end.InstructionIndex(); | 2058   int end_instr = end.InstructionIndex(); | 
| 2059   ASSERT(start_instr <= end_instr); | 2059   DCHECK(start_instr <= end_instr); | 
| 2060 | 2060 | 
| 2061   // We have no choice | 2061   // We have no choice | 
| 2062   if (start_instr == end_instr) return end; | 2062   if (start_instr == end_instr) return end; | 
| 2063 | 2063 | 
| 2064   HBasicBlock* start_block = GetBlock(start); | 2064   HBasicBlock* start_block = GetBlock(start); | 
| 2065   HBasicBlock* end_block = GetBlock(end); | 2065   HBasicBlock* end_block = GetBlock(end); | 
| 2066 | 2066 | 
| 2067   if (end_block == start_block) { | 2067   if (end_block == start_block) { | 
| 2068     // The interval is split in the same basic block. Split at the latest | 2068     // The interval is split in the same basic block. Split at the latest | 
| 2069     // possible position. | 2069     // possible position. | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2111   if (second_part->Start().Value() < end.Value()) { | 2111   if (second_part->Start().Value() < end.Value()) { | 
| 2112     // The split result intersects with [start, end[. | 2112     // The split result intersects with [start, end[. | 
| 2113     // Split it at position between ]start+1, end[, spill the middle part | 2113     // Split it at position between ]start+1, end[, spill the middle part | 
| 2114     // and put the rest to unhandled. | 2114     // and put the rest to unhandled. | 
| 2115     LiveRange* third_part = SplitBetween( | 2115     LiveRange* third_part = SplitBetween( | 
| 2116         second_part, | 2116         second_part, | 
| 2117         Max(second_part->Start().InstructionEnd(), until), | 2117         Max(second_part->Start().InstructionEnd(), until), | 
| 2118         end.PrevInstruction().InstructionEnd()); | 2118         end.PrevInstruction().InstructionEnd()); | 
| 2119     if (!AllocationOk()) return; | 2119     if (!AllocationOk()) return; | 
| 2120 | 2120 | 
| 2121     ASSERT(third_part != second_part); | 2121     DCHECK(third_part != second_part); | 
| 2122 | 2122 | 
| 2123     Spill(second_part); | 2123     Spill(second_part); | 
| 2124     AddToUnhandledSorted(third_part); | 2124     AddToUnhandledSorted(third_part); | 
| 2125   } else { | 2125   } else { | 
| 2126     // The split result does not intersect with [start, end[. | 2126     // The split result does not intersect with [start, end[. | 
| 2127     // Nothing to spill. Just put it to unhandled as whole. | 2127     // Nothing to spill. Just put it to unhandled as whole. | 
| 2128     AddToUnhandledSorted(second_part); | 2128     AddToUnhandledSorted(second_part); | 
| 2129   } | 2129   } | 
| 2130 } | 2130 } | 
| 2131 | 2131 | 
| 2132 | 2132 | 
| 2133 void LAllocator::Spill(LiveRange* range) { | 2133 void LAllocator::Spill(LiveRange* range) { | 
| 2134   ASSERT(!range->IsSpilled()); | 2134   DCHECK(!range->IsSpilled()); | 
| 2135   TraceAlloc("Spilling live range %d\n", range->id()); | 2135   TraceAlloc("Spilling live range %d\n", range->id()); | 
| 2136   LiveRange* first = range->TopLevel(); | 2136   LiveRange* first = range->TopLevel(); | 
| 2137 | 2137 | 
| 2138   if (!first->HasAllocatedSpillOperand()) { | 2138   if (!first->HasAllocatedSpillOperand()) { | 
| 2139     LOperand* op = TryReuseSpillSlot(range); | 2139     LOperand* op = TryReuseSpillSlot(range); | 
| 2140     if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind()); | 2140     if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind()); | 
| 2141     first->SetSpillOperand(op); | 2141     first->SetSpillOperand(op); | 
| 2142   } | 2142   } | 
| 2143   range->MakeSpilled(chunk()->zone()); | 2143   range->MakeSpilled(chunk()->zone()); | 
| 2144 } | 2144 } | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2185     isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_); | 2185     isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_); | 
| 2186   } | 2186   } | 
| 2187 | 2187 | 
| 2188 #ifdef DEBUG | 2188 #ifdef DEBUG | 
| 2189   if (allocator_ != NULL) allocator_->Verify(); | 2189   if (allocator_ != NULL) allocator_->Verify(); | 
| 2190 #endif | 2190 #endif | 
| 2191 } | 2191 } | 
| 2192 | 2192 | 
| 2193 | 2193 | 
| 2194 } }  // namespace v8::internal | 2194 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|