Index: src/heap.h |
diff --git a/src/heap.h b/src/heap.h |
index f488b8cda276316df11e6df8b3e645a533c8b111..e2d4cfdb72ad7f8239b4cf2df177191920036857 100644 |
--- a/src/heap.h |
+++ b/src/heap.h |
@@ -282,24 +282,58 @@ class HeapDebugUtils; |
// by it's size to avoid dereferencing a map pointer for scanning. |
class PromotionQueue { |
public: |
- PromotionQueue() : front_(NULL), rear_(NULL) { } |
+ PromotionQueue(Heap* heap) |
+ : front_(NULL), |
+ rear_(NULL), |
+ limit_(NULL), |
+ emergency_stack_(0), |
+ heap_(heap) { } |
- void Initialize(Address start_address) { |
- // Assumes that a NewSpacePage exactly fits a number of promotion queue |
- // entries (where each is a pair of intptr_t). This allows us to simplify |
- // the test fpr when to switch pages. |
- ASSERT((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) |
- == 0); |
- ASSERT(NewSpacePage::IsAtEnd(start_address)); |
- front_ = rear_ = reinterpret_cast<intptr_t*>(start_address); |
+ void Initialize(); |
+ |
+ void Destroy() { |
+ ASSERT(is_empty()); |
+ delete emergency_stack_; |
+ emergency_stack_ = NULL; |
+ } |
+ |
+ inline void ActivateGuardIfOnTheSamePage(); |
+ |
+ Page* GetHeadPage() { |
+ return Page::FromAllocationTop(reinterpret_cast<Address>(rear_)); |
+ } |
+ |
+ void SetNewLimit(Address limit) { |
+ if (!guard_) { |
+ return; |
+ } |
+ |
+ ASSERT(GetHeadPage() == Page::FromAllocationTop(limit)); |
+ limit_ = reinterpret_cast<intptr_t*>(limit); |
+ |
+ if (limit_ <= rear_) { |
+ return; |
+ } |
+ |
+ RelocateQueueHead(); |
} |
- bool is_empty() { return front_ == rear_; } |
+ bool is_empty() { |
+ return (front_ == rear_) && |
+ (emergency_stack_ == NULL || emergency_stack_->length() == 0); |
+ } |
inline void insert(HeapObject* target, int size); |
void remove(HeapObject** target, int* size) { |
ASSERT(!is_empty()); |
+ if (front_ == rear_) { |
+ Entry e = emergency_stack_->RemoveLast(); |
+ *target = e.obj_; |
+ *size = e.size_; |
+ return; |
+ } |
+ |
if (NewSpacePage::IsAtStart(reinterpret_cast<Address>(front_))) { |
NewSpacePage* front_page = |
NewSpacePage::FromAddress(reinterpret_cast<Address>(front_)); |
@@ -318,6 +352,23 @@ class PromotionQueue { |
// The front of the queue is higher in the memory page chain than the rear. |
intptr_t* front_; |
intptr_t* rear_; |
+ intptr_t* limit_; |
+ |
+ bool guard_; |
+ |
+ static const int kEntrySizeInWords = 2; |
+ |
+ struct Entry { |
+ Entry(HeapObject* obj, int size) : obj_(obj), size_(size) { } |
+ |
+ HeapObject* obj_; |
+ int size_; |
+ }; |
+ List<Entry>* emergency_stack_; |
+ |
+ Heap* heap_; |
+ |
+ void RelocateQueueHead(); |
DISALLOW_COPY_AND_ASSIGN(PromotionQueue); |
}; |