| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/store_buffer.h" | 5 #include "vm/store_buffer.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/lockers.h" |
| 8 #include "vm/runtime_entry.h" | 9 #include "vm/runtime_entry.h" |
| 9 | 10 |
| 10 namespace dart { | 11 namespace dart { |
| 11 | 12 |
| 12 DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Isolate* isolate) { | 13 DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread* thread) { |
| 13 StoreBuffer* buffer = isolate->store_buffer(); | 14 thread->StoreBufferBlockProcess(true); |
| 14 buffer->Expand(true); | |
| 15 } | 15 } |
| 16 END_LEAF_RUNTIME_ENTRY | 16 END_LEAF_RUNTIME_ENTRY |
| 17 | 17 |
| 18 | 18 |
| 19 StoreBuffer::StoreBuffer() : mutex_(new Mutex()) { |
| 20 } |
| 21 |
| 22 |
| 19 StoreBuffer::~StoreBuffer() { | 23 StoreBuffer::~StoreBuffer() { |
| 20 StoreBufferBlock* block = blocks_; | 24 Reset(); |
| 21 blocks_ = NULL; | 25 delete mutex_; |
| 22 while (block != NULL) { | 26 } |
| 23 StoreBufferBlock* next = block->next(); | 27 |
| 24 delete block; | 28 |
| 25 block = next; | 29 void StoreBuffer::Reset() { |
| 30 MutexLocker ml(mutex_); |
| 31 // TODO(koda): Reuse and share empty blocks between isolates. |
| 32 while (!full_.IsEmpty()) { |
| 33 delete full_.Pop(); |
| 34 } |
| 35 while (!partial_.IsEmpty()) { |
| 36 delete partial_.Pop(); |
| 26 } | 37 } |
| 27 } | 38 } |
| 28 | 39 |
| 29 | 40 |
| 30 void StoreBuffer::Reset() { | 41 StoreBufferBlock* StoreBuffer::Blocks() { |
| 31 StoreBufferBlock* block = blocks_->next_; | 42 MutexLocker ml(mutex_); |
| 32 while (block != NULL) { | 43 while (!partial_.IsEmpty()) { |
| 33 StoreBufferBlock* next = block->next_; | 44 full_.Push(partial_.Pop()); |
| 34 delete block; | |
| 35 block = next; | |
| 36 } | 45 } |
| 37 blocks_->next_ = NULL; | 46 return full_.PopAll(); |
| 38 blocks_->top_ = 0; | |
| 39 full_count_ = 0; | |
| 40 } | 47 } |
| 41 | 48 |
| 42 | 49 |
| 43 bool StoreBuffer::Contains(RawObject* raw) { | 50 void StoreBuffer::PushBlock(StoreBufferBlock* block, bool check_threshold) { |
| 44 StoreBufferBlock* block = blocks_; | 51 MutexLocker ml(mutex_); |
| 45 while (block != NULL) { | 52 List* list = block->IsFull() ? &full_ : &partial_; |
| 46 intptr_t count = block->Count(); | 53 list->Push(block); |
| 47 for (intptr_t i = 0; i < count; i++) { | 54 if (check_threshold) { |
| 48 if (block->At(i) == raw) { | 55 CheckThreshold(); |
| 49 return true; | |
| 50 } | |
| 51 } | |
| 52 block = block->next_; | |
| 53 } | 56 } |
| 54 return false; | |
| 55 } | 57 } |
| 56 | 58 |
| 57 | 59 |
| 58 void StoreBuffer::Expand(bool check) { | 60 StoreBufferBlock* StoreBuffer::PopBlock() { |
| 59 ASSERT(blocks_->Count() == StoreBufferBlock::kSize); | 61 MutexLocker ml(mutex_); |
| 60 blocks_ = new StoreBufferBlock(blocks_); | 62 return (!partial_.IsEmpty()) ? partial_.Pop() : PopEmptyBlock(); |
| 61 full_count_++; | 63 } |
| 62 if (check) { | 64 |
| 63 CheckThreshold(); | 65 |
| 66 StoreBufferBlock* StoreBuffer::PopEmptyBlock() { |
| 67 // TODO(koda): Reuse and share empty blocks between isolates. |
| 68 return new StoreBufferBlock(); |
| 69 } |
| 70 |
| 71 |
| 72 StoreBuffer::List::~List() { |
| 73 while (!IsEmpty()) { |
| 74 delete Pop(); |
| 64 } | 75 } |
| 65 } | 76 } |
| 66 | 77 |
| 67 | 78 |
| 79 StoreBufferBlock* StoreBuffer::List::Pop() { |
| 80 StoreBufferBlock* result = head_; |
| 81 head_ = head_->next_; |
| 82 --length_; |
| 83 result->next_ = NULL; |
| 84 return result; |
| 85 } |
| 86 |
| 87 |
| 88 StoreBufferBlock* StoreBuffer::List::PopAll() { |
| 89 StoreBufferBlock* result = head_; |
| 90 head_ = NULL; |
| 91 length_ = 0; |
| 92 return result; |
| 93 } |
| 94 |
| 95 |
| 96 void StoreBuffer::List::Push(StoreBufferBlock* block) { |
| 97 block->next_ = head_; |
| 98 head_ = block; |
| 99 ++length_; |
| 100 } |
| 101 |
| 102 |
| 68 void StoreBuffer::CheckThreshold() { | 103 void StoreBuffer::CheckThreshold() { |
| 69 // Schedule an interrupt if we have run over the max number of | 104 // Schedule an interrupt if we have run over the max number of |
| 70 // StoreBufferBlocks. | 105 // StoreBufferBlocks. |
| 71 // TODO(iposva): Fix magic number. | 106 // TODO(koda): Pass threshold and callback in constructor. Cap total? |
| 72 if (full_count_ > 100) { | 107 if (full_.length() > 100) { |
| 73 Isolate::Current()->ScheduleInterrupts(Isolate::kStoreBufferInterrupt); | 108 Isolate::Current()->ScheduleInterrupts(Isolate::kStoreBufferInterrupt); |
| 74 } | 109 } |
| 75 } | 110 } |
| 76 | 111 |
| 77 } // namespace dart | 112 } // namespace dart |
| OLD | NEW |