Index: runtime/vm/store_buffer.cc |
diff --git a/runtime/vm/store_buffer.cc b/runtime/vm/store_buffer.cc |
index acf7ca6eac6cfbbdb144facf752c0bf0ffc32c88..9020340458aec40c783b14c8ea0cca6d040f22d0 100644 |
--- a/runtime/vm/store_buffer.cc |
+++ b/runtime/vm/store_buffer.cc |
@@ -5,71 +5,102 @@ |
#include "vm/store_buffer.h" |
#include "platform/assert.h" |
+#include "vm/lockers.h" |
#include "vm/runtime_entry.h" |
namespace dart { |
-DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Isolate* isolate) { |
- StoreBuffer* buffer = isolate->store_buffer(); |
- buffer->Expand(true); |
+DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread* thread) { |
+ thread->StoreBufferBlockProcess(true); |
} |
END_LEAF_RUNTIME_ENTRY |
+StoreBuffer::StoreBuffer() : mutex_(new Mutex()) { |
+} |
+ |
+ |
StoreBuffer::~StoreBuffer() { |
- StoreBufferBlock* block = blocks_; |
- blocks_ = NULL; |
- while (block != NULL) { |
- StoreBufferBlock* next = block->next(); |
- delete block; |
- block = next; |
- } |
+ Reset(); |
+ delete mutex_; |
} |
void StoreBuffer::Reset() { |
- StoreBufferBlock* block = blocks_->next_; |
- while (block != NULL) { |
- StoreBufferBlock* next = block->next_; |
- delete block; |
- block = next; |
- } |
- blocks_->next_ = NULL; |
- blocks_->top_ = 0; |
- full_count_ = 0; |
+ MutexLocker ml(mutex_); |
+ // TODO(koda): Reuse and share empty blocks between isolates. |
+ while (full_.length() > 0) delete full_.Pop(); |
Ivan Posva
2015/06/08 13:05:21
while (full_.head != NULL) {
delete full_.Pop();
koda
2015/06/09 13:10:30
Done, using IsEmpty.
|
+ while (partial_.length() > 0) delete partial_.Pop(); |
} |
-bool StoreBuffer::Contains(RawObject* raw) { |
- StoreBufferBlock* block = blocks_; |
- while (block != NULL) { |
- intptr_t count = block->Count(); |
- for (intptr_t i = 0; i < count; i++) { |
- if (block->At(i) == raw) { |
- return true; |
- } |
- } |
- block = block->next_; |
+StoreBufferBlock* StoreBuffer::Blocks() { |
+ MutexLocker ml(mutex_); |
+ while (partial_.length() > 0) { |
Ivan Posva
2015/06/08 13:05:21
ditto.
koda
2015/06/09 13:10:30
Done.
|
+ full_.Push(partial_.Pop()); |
} |
- return false; |
+ return full_.PopAll(); |
} |
-void StoreBuffer::Expand(bool check) { |
- ASSERT(blocks_->Count() == StoreBufferBlock::kSize); |
- blocks_ = new StoreBufferBlock(blocks_); |
- full_count_++; |
- if (check) { |
+void StoreBuffer::Push(StoreBufferBlock* block, bool check_threshold) { |
+ MutexLocker ml(mutex_); |
+ List* list = block->IsFull() ? &full_ : &partial_; |
+ list->Push(block); |
+ if (check_threshold) { |
CheckThreshold(); |
} |
} |
+StoreBufferBlock* StoreBuffer::PopPartialOrEmpty() { |
+ MutexLocker ml(mutex_); |
+ return (partial_.length() > 0) ? partial_.Pop() : PopEmpty(); |
Ivan Posva
2015/06/08 13:05:21
ditto.
koda
2015/06/09 13:10:29
Done.
|
+} |
+ |
+ |
+StoreBufferBlock* StoreBuffer::PopEmpty() { |
+ // TODO(koda): Reuse and share empty blocks between isolates. |
+ return new StoreBufferBlock(); |
+} |
+ |
+ |
+StoreBuffer::List::~List() { |
+ while (length() > 0) { |
Ivan Posva
2015/06/08 13:05:21
ditto.
koda
2015/06/09 13:10:29
Done.
|
+ delete Pop(); |
+ } |
+} |
+ |
+ |
+StoreBufferBlock* StoreBuffer::List::Pop() { |
+ StoreBufferBlock* result = head_; |
+ head_ = head_->next_; |
+ --length_; |
+ result->next_ = NULL; |
+ return result; |
+} |
+ |
+ |
+StoreBufferBlock* StoreBuffer::List::PopAll() { |
+ StoreBufferBlock* result = head_; |
+ head_ = NULL; |
+ length_ = 0; |
+ return result; |
+} |
+ |
+ |
+void StoreBuffer::List::Push(StoreBufferBlock* block) { |
+ block->next_ = head_; |
+ head_ = block; |
+ ++length_; |
+} |
+ |
+ |
void StoreBuffer::CheckThreshold() { |
// Schedule an interrupt if we have run over the max number of |
// StoreBufferBlocks. |
- // TODO(iposva): Fix magic number. |
- if (full_count_ > 100) { |
+ // TODO(koda): Pass threshold and callback in constructor. |
+ if (full_.length() > 100) { |
Ivan Posva
2015/06/08 13:05:21
Wondering whether we should be using the total num
koda
2015/06/09 13:10:29
Yes, I suppose there could be a temporary explosio
|
Isolate::Current()->ScheduleInterrupts(Isolate::kStoreBufferInterrupt); |
} |
} |