Chromium Code Reviews| 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_.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.
| |
| 33 while (partial_.length() > 0) delete partial_.Pop(); | |
| 34 } | |
| 35 | |
| 36 | |
| 37 StoreBufferBlock* StoreBuffer::Blocks() { | |
| 38 MutexLocker ml(mutex_); | |
| 39 while (partial_.length() > 0) { | |
|
Ivan Posva
2015/06/08 13:05:21
ditto.
koda
2015/06/09 13:10:30
Done.
| |
| 40 full_.Push(partial_.Pop()); | |
| 41 } | |
| 42 return full_.PopAll(); | |
| 43 } | |
| 44 | |
| 45 | |
| 46 void StoreBuffer::Push(StoreBufferBlock* block, bool check_threshold) { | |
| 47 MutexLocker ml(mutex_); | |
| 48 List* list = block->IsFull() ? &full_ : &partial_; | |
| 49 list->Push(block); | |
| 50 if (check_threshold) { | |
| 51 CheckThreshold(); | |
| 26 } | 52 } |
| 27 } | 53 } |
| 28 | 54 |
| 29 | 55 |
| 30 void StoreBuffer::Reset() { | 56 StoreBufferBlock* StoreBuffer::PopPartialOrEmpty() { |
| 31 StoreBufferBlock* block = blocks_->next_; | 57 MutexLocker ml(mutex_); |
| 32 while (block != NULL) { | 58 return (partial_.length() > 0) ? partial_.Pop() : PopEmpty(); |
|
Ivan Posva
2015/06/08 13:05:21
ditto.
koda
2015/06/09 13:10:29
Done.
| |
| 33 StoreBufferBlock* next = block->next_; | |
| 34 delete block; | |
| 35 block = next; | |
| 36 } | |
| 37 blocks_->next_ = NULL; | |
| 38 blocks_->top_ = 0; | |
| 39 full_count_ = 0; | |
| 40 } | 59 } |
| 41 | 60 |
| 42 | 61 |
| 43 bool StoreBuffer::Contains(RawObject* raw) { | 62 StoreBufferBlock* StoreBuffer::PopEmpty() { |
| 44 StoreBufferBlock* block = blocks_; | 63 // TODO(koda): Reuse and share empty blocks between isolates. |
| 45 while (block != NULL) { | 64 return new StoreBufferBlock(); |
| 46 intptr_t count = block->Count(); | |
| 47 for (intptr_t i = 0; i < count; i++) { | |
| 48 if (block->At(i) == raw) { | |
| 49 return true; | |
| 50 } | |
| 51 } | |
| 52 block = block->next_; | |
| 53 } | |
| 54 return false; | |
| 55 } | 65 } |
| 56 | 66 |
| 57 | 67 |
| 58 void StoreBuffer::Expand(bool check) { | 68 StoreBuffer::List::~List() { |
| 59 ASSERT(blocks_->Count() == StoreBufferBlock::kSize); | 69 while (length() > 0) { |
|
Ivan Posva
2015/06/08 13:05:21
ditto.
koda
2015/06/09 13:10:29
Done.
| |
| 60 blocks_ = new StoreBufferBlock(blocks_); | 70 delete Pop(); |
| 61 full_count_++; | |
| 62 if (check) { | |
| 63 CheckThreshold(); | |
| 64 } | 71 } |
| 65 } | 72 } |
| 66 | 73 |
| 67 | 74 |
| 75 StoreBufferBlock* StoreBuffer::List::Pop() { | |
| 76 StoreBufferBlock* result = head_; | |
| 77 head_ = head_->next_; | |
| 78 --length_; | |
| 79 result->next_ = NULL; | |
| 80 return result; | |
| 81 } | |
| 82 | |
| 83 | |
| 84 StoreBufferBlock* StoreBuffer::List::PopAll() { | |
| 85 StoreBufferBlock* result = head_; | |
| 86 head_ = NULL; | |
| 87 length_ = 0; | |
| 88 return result; | |
| 89 } | |
| 90 | |
| 91 | |
| 92 void StoreBuffer::List::Push(StoreBufferBlock* block) { | |
| 93 block->next_ = head_; | |
| 94 head_ = block; | |
| 95 ++length_; | |
| 96 } | |
| 97 | |
| 98 | |
| 68 void StoreBuffer::CheckThreshold() { | 99 void StoreBuffer::CheckThreshold() { |
| 69 // Schedule an interrupt if we have run over the max number of | 100 // Schedule an interrupt if we have run over the max number of |
| 70 // StoreBufferBlocks. | 101 // StoreBufferBlocks. |
| 71 // TODO(iposva): Fix magic number. | 102 // TODO(koda): Pass threshold and callback in constructor. |
| 72 if (full_count_ > 100) { | 103 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
| |
| 73 Isolate::Current()->ScheduleInterrupts(Isolate::kStoreBufferInterrupt); | 104 Isolate::Current()->ScheduleInterrupts(Isolate::kStoreBufferInterrupt); |
| 74 } | 105 } |
| 75 } | 106 } |
| 76 | 107 |
| 77 } // namespace dart | 108 } // namespace dart |
| OLD | NEW |