Chromium Code Reviews| Index: runtime/vm/store_buffer.h |
| diff --git a/runtime/vm/store_buffer.h b/runtime/vm/store_buffer.h |
| index cc92d72db3143fb878f285ba46552cd89ecc229f..c20f72ac754007bfbf4acdc619da3395dd406879 100644 |
| --- a/runtime/vm/store_buffer.h |
| +++ b/runtime/vm/store_buffer.h |
| @@ -12,20 +12,26 @@ namespace dart { |
| // Forward declarations. |
| class Isolate; |
| +class Mutex; |
| class RawObject; |
| class StoreBufferBlock { |
| public: |
| - // Each block contains kSize pointers. |
| + // Each full block contains kSize pointers. |
| static const int32_t kSize = 1024; |
| - explicit StoreBufferBlock(StoreBufferBlock* next) : next_(next), top_(0) {} |
| - |
| void Reset() { top_ = 0; } |
| + // TODO(koda): Make private after adding visitor interface to StoreBuffer. |
| StoreBufferBlock* next() const { return next_; } |
| intptr_t Count() const { return top_; } |
| + bool IsFull() const { return Count() == kSize; } |
| + |
| + void Add(RawObject* obj) { |
| + ASSERT(!IsFull()); |
| + pointers_[top_++] = obj; |
| + } |
| RawObject* At(intptr_t i) const { |
| ASSERT(i >= 0); |
| @@ -33,12 +39,25 @@ class StoreBufferBlock { |
| return pointers_[i]; |
| } |
| +#if defined(TESTING) |
| + bool Contains(RawObject* obj) const { |
| + for (intptr_t i = 0; i < Count(); i++) { |
| + if (At(i) == obj) { |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| +#endif // TESTING |
| + |
| static intptr_t top_offset() { return OFFSET_OF(StoreBufferBlock, top_); } |
| static intptr_t pointers_offset() { |
| return OFFSET_OF(StoreBufferBlock, pointers_); |
| } |
| private: |
| + StoreBufferBlock() : next_(NULL), top_(0) {} |
| + |
| StoreBufferBlock* next_; |
| int32_t top_; |
| RawObject* pointers_[kSize]; |
| @@ -51,59 +70,47 @@ class StoreBufferBlock { |
| class StoreBuffer { |
| public: |
| - StoreBuffer() : blocks_(new StoreBufferBlock(NULL)), full_count_(0) {} |
| - explicit StoreBuffer(bool shallow_copy) : blocks_(NULL), full_count_(0) { |
| - // The value shallow_copy is only used to select this non-allocating |
| - // constructor. It is always expected to be true. |
| - ASSERT(shallow_copy); |
| - } |
| + StoreBuffer(); |
| ~StoreBuffer(); |
| - intptr_t Count() const { |
| - return blocks_->Count() + (full_count_ * StoreBufferBlock::kSize); |
| - } |
| - |
| - void Reset(); |
| - |
| - void AddObject(RawObject* obj) { |
| - StoreBufferBlock* block = blocks_; |
| - ASSERT(block->top_ < StoreBufferBlock::kSize); |
| - block->pointers_[block->top_++] = obj; |
| - if (block->top_ == StoreBufferBlock::kSize) { |
| - Expand(true); |
| - } |
| - } |
| + // Adds and transfers ownership of the block to the buffer. |
| + void Push(StoreBufferBlock* block, bool check_threshold = true); |
| + // Partially filled blocks can be reused, and there is an "inifite" supply |
| + // of empty blocks (reused or newly allocated). In any case, the caller |
| + // takes ownership of the returned block. |
| + StoreBufferBlock* PopPartialOrEmpty(); |
|
Ivan Posva
2015/06/08 13:05:21
How about just Pop() to get a partial or empty blo
|
| + StoreBufferBlock* PopEmpty(); |
| - void AddObjectGC(RawObject* obj) { |
| - StoreBufferBlock* block = blocks_; |
| - ASSERT(block->top_ < StoreBufferBlock::kSize); |
| - block->pointers_[block->top_++] = obj; |
| - if (block->top_ == StoreBufferBlock::kSize) { |
| - Expand(false); |
| - } |
| - } |
| + // Pops and returns all non-empty blocks as a linked list (owned by caller). |
| + // TODO(koda): Replace with VisitObjectPointers. |
| + StoreBufferBlock* Blocks(); |
| - StoreBufferBlock* Blocks() { |
| - StoreBufferBlock* result = blocks_; |
| - blocks_ = new StoreBufferBlock(NULL); |
| - full_count_ = 0; |
| - return result; |
| - } |
| - |
| - // Expand the storage and optionally check whethe to schedule an interrupt. |
| - void Expand(bool check); |
| - |
| - bool Contains(RawObject* raw); |
| - |
| - static int blocks_offset() { return OFFSET_OF(StoreBuffer, blocks_); } |
| + // Discards the contents of this store buffer. |
| + void Reset(); |
| private: |
| + class List { |
|
Ivan Posva
2015/06/08 13:05:21
Maybe too much overhead as we do not really need t
koda
2015/06/09 13:10:30
This abstraction will be useful also for the share
|
| + public: |
| + List() : head_(NULL), length_(0) {} |
| + ~List(); |
| + void Push(StoreBufferBlock* block); |
| + StoreBufferBlock* Pop(); |
| + intptr_t length() const { return length_; } |
| + StoreBufferBlock* PopAll(); |
| + private: |
| + StoreBufferBlock* head_; |
| + intptr_t length_; |
| + DISALLOW_COPY_AND_ASSIGN(List); |
| + }; |
| + |
| // Check if we run over the max number of deduplication sets. |
| // If we did schedule an interrupt. |
| void CheckThreshold(); |
| - StoreBufferBlock* blocks_; |
| - intptr_t full_count_; |
| + List full_; |
| + List partial_; |
| + // TODO(koda): static List empty_ |
| + Mutex* mutex_; |
| DISALLOW_COPY_AND_ASSIGN(StoreBuffer); |
| }; |