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 |