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 |