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/lockers.h" |
9 #include "vm/runtime_entry.h" | 9 #include "vm/runtime_entry.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread* thread) { | 13 DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread* thread) { |
14 thread->StoreBufferBlockProcess(StoreBuffer::kCheckThreshold); | 14 thread->StoreBufferBlockProcess(StoreBuffer::kCheckThreshold); |
15 } | 15 } |
16 END_LEAF_RUNTIME_ENTRY | 16 END_LEAF_RUNTIME_ENTRY |
17 | 17 |
18 template<int BlockSize> | 18 template <int BlockSize> |
19 typename BlockStack<BlockSize>::List* | 19 typename BlockStack<BlockSize>::List* BlockStack<BlockSize>::global_empty_ = |
20 BlockStack<BlockSize>::global_empty_ = NULL; | 20 NULL; |
21 template<int BlockSize> | 21 template <int BlockSize> |
22 Mutex* BlockStack<BlockSize>::global_mutex_ = NULL; | 22 Mutex* BlockStack<BlockSize>::global_mutex_ = NULL; |
23 | 23 |
24 | 24 |
25 template<int BlockSize> | 25 template <int BlockSize> |
26 void BlockStack<BlockSize>::InitOnce() { | 26 void BlockStack<BlockSize>::InitOnce() { |
27 global_empty_ = new List(); | 27 global_empty_ = new List(); |
28 global_mutex_ = new Mutex(); | 28 global_mutex_ = new Mutex(); |
29 } | 29 } |
30 | 30 |
31 | 31 |
32 template<int BlockSize> | 32 template <int BlockSize> |
33 void BlockStack<BlockSize>::ShutDown() { | 33 void BlockStack<BlockSize>::ShutDown() { |
34 delete global_empty_; | 34 delete global_empty_; |
35 delete global_mutex_; | 35 delete global_mutex_; |
36 } | 36 } |
37 | 37 |
38 | 38 |
39 template<int BlockSize> | 39 template <int BlockSize> |
40 BlockStack<BlockSize>::BlockStack() : mutex_(new Mutex()) { | 40 BlockStack<BlockSize>::BlockStack() : mutex_(new Mutex()) {} |
41 } | |
42 | 41 |
43 | 42 |
44 template<int BlockSize> | 43 template <int BlockSize> |
45 BlockStack<BlockSize>::~BlockStack() { | 44 BlockStack<BlockSize>::~BlockStack() { |
46 Reset(); | 45 Reset(); |
47 delete mutex_; | 46 delete mutex_; |
48 } | 47 } |
49 | 48 |
50 | 49 |
51 template<int BlockSize> | 50 template <int BlockSize> |
52 void BlockStack<BlockSize>::Reset() { | 51 void BlockStack<BlockSize>::Reset() { |
53 MutexLocker local_mutex_locker(mutex_); | 52 MutexLocker local_mutex_locker(mutex_); |
54 { | 53 { |
55 // Empty all blocks and move them to the global cache. | 54 // Empty all blocks and move them to the global cache. |
56 MutexLocker global_mutex_locker(global_mutex_); | 55 MutexLocker global_mutex_locker(global_mutex_); |
57 while (!full_.IsEmpty()) { | 56 while (!full_.IsEmpty()) { |
58 Block* block = full_.Pop(); | 57 Block* block = full_.Pop(); |
59 block->Reset(); | 58 block->Reset(); |
60 global_empty_->Push(block); | 59 global_empty_->Push(block); |
61 } | 60 } |
62 while (!partial_.IsEmpty()) { | 61 while (!partial_.IsEmpty()) { |
63 Block* block = partial_.Pop(); | 62 Block* block = partial_.Pop(); |
64 block->Reset(); | 63 block->Reset(); |
65 global_empty_->Push(block); | 64 global_empty_->Push(block); |
66 } | 65 } |
67 TrimGlobalEmpty(); | 66 TrimGlobalEmpty(); |
68 } | 67 } |
69 } | 68 } |
70 | 69 |
71 | 70 |
72 template<int BlockSize> | 71 template <int BlockSize> |
73 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::Blocks() { | 72 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::Blocks() { |
74 MutexLocker ml(mutex_); | 73 MutexLocker ml(mutex_); |
75 while (!partial_.IsEmpty()) { | 74 while (!partial_.IsEmpty()) { |
76 full_.Push(partial_.Pop()); | 75 full_.Push(partial_.Pop()); |
77 } | 76 } |
78 return full_.PopAll(); | 77 return full_.PopAll(); |
79 } | 78 } |
80 | 79 |
81 | 80 |
82 template<int BlockSize> | 81 template <int BlockSize> |
83 void BlockStack<BlockSize>::PushBlockImpl(Block* block) { | 82 void BlockStack<BlockSize>::PushBlockImpl(Block* block) { |
84 ASSERT(block->next() == NULL); // Should be just a single block. | 83 ASSERT(block->next() == NULL); // Should be just a single block. |
85 if (block->IsFull()) { | 84 if (block->IsFull()) { |
86 MutexLocker ml(mutex_); | 85 MutexLocker ml(mutex_); |
87 full_.Push(block); | 86 full_.Push(block); |
88 } else if (block->IsEmpty()) { | 87 } else if (block->IsEmpty()) { |
89 MutexLocker ml(global_mutex_); | 88 MutexLocker ml(global_mutex_); |
90 global_empty_->Push(block); | 89 global_empty_->Push(block); |
91 TrimGlobalEmpty(); | 90 TrimGlobalEmpty(); |
92 } else { | 91 } else { |
(...skipping 10 matching lines...) Expand all Loading... |
103 Thread* thread = Thread::Current(); | 102 Thread* thread = Thread::Current(); |
104 // Sanity check: it makes no sense to schedule the GC in another isolate. | 103 // Sanity check: it makes no sense to schedule the GC in another isolate. |
105 // (If Isolate ever gets multiple store buffers, we should avoid this | 104 // (If Isolate ever gets multiple store buffers, we should avoid this |
106 // coupling by passing in an explicit callback+parameter at construction.) | 105 // coupling by passing in an explicit callback+parameter at construction.) |
107 ASSERT(thread->isolate()->store_buffer() == this); | 106 ASSERT(thread->isolate()->store_buffer() == this); |
108 thread->ScheduleInterrupts(Thread::kVMInterrupt); | 107 thread->ScheduleInterrupts(Thread::kVMInterrupt); |
109 } | 108 } |
110 } | 109 } |
111 | 110 |
112 | 111 |
113 template<int BlockSize> | 112 template <int BlockSize> |
114 typename BlockStack<BlockSize>::Block* | 113 typename BlockStack<BlockSize>::Block* |
115 BlockStack<BlockSize>::PopNonFullBlock() { | 114 BlockStack<BlockSize>::PopNonFullBlock() { |
116 { | 115 { |
117 MutexLocker ml(mutex_); | 116 MutexLocker ml(mutex_); |
118 if (!partial_.IsEmpty()) { | 117 if (!partial_.IsEmpty()) { |
119 return partial_.Pop(); | 118 return partial_.Pop(); |
120 } | 119 } |
121 } | 120 } |
122 return PopEmptyBlock(); | 121 return PopEmptyBlock(); |
123 } | 122 } |
124 | 123 |
125 | 124 |
126 template<int BlockSize> | 125 template <int BlockSize> |
127 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::PopEmptyBlock() { | 126 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::PopEmptyBlock() { |
128 { | 127 { |
129 MutexLocker ml(global_mutex_); | 128 MutexLocker ml(global_mutex_); |
130 if (!global_empty_->IsEmpty()) { | 129 if (!global_empty_->IsEmpty()) { |
131 return global_empty_->Pop(); | 130 return global_empty_->Pop(); |
132 } | 131 } |
133 } | 132 } |
134 return new Block(); | 133 return new Block(); |
135 } | 134 } |
136 | 135 |
137 | 136 |
138 template<int BlockSize> | 137 template <int BlockSize> |
139 typename BlockStack<BlockSize>::Block* | 138 typename BlockStack<BlockSize>::Block* |
140 BlockStack<BlockSize>::PopNonEmptyBlock() { | 139 BlockStack<BlockSize>::PopNonEmptyBlock() { |
141 MutexLocker ml(mutex_); | 140 MutexLocker ml(mutex_); |
142 if (!full_.IsEmpty()) { | 141 if (!full_.IsEmpty()) { |
143 return full_.Pop(); | 142 return full_.Pop(); |
144 } else if (!partial_.IsEmpty()) { | 143 } else if (!partial_.IsEmpty()) { |
145 return partial_.Pop(); | 144 return partial_.Pop(); |
146 } else { | 145 } else { |
147 return NULL; | 146 return NULL; |
148 } | 147 } |
149 } | 148 } |
150 | 149 |
151 | 150 |
152 template<int BlockSize> | 151 template <int BlockSize> |
153 bool BlockStack<BlockSize>::IsEmpty() { | 152 bool BlockStack<BlockSize>::IsEmpty() { |
154 MutexLocker ml(mutex_); | 153 MutexLocker ml(mutex_); |
155 return full_.IsEmpty() && partial_.IsEmpty(); | 154 return full_.IsEmpty() && partial_.IsEmpty(); |
156 } | 155 } |
157 | 156 |
158 | 157 |
159 template<int BlockSize> | 158 template <int BlockSize> |
160 BlockStack<BlockSize>::List::~List() { | 159 BlockStack<BlockSize>::List::~List() { |
161 while (!IsEmpty()) { | 160 while (!IsEmpty()) { |
162 delete Pop(); | 161 delete Pop(); |
163 } | 162 } |
164 } | 163 } |
165 | 164 |
166 | 165 |
167 template<int BlockSize> | 166 template <int BlockSize> |
168 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::List::Pop() { | 167 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::List::Pop() { |
169 Block* result = head_; | 168 Block* result = head_; |
170 head_ = head_->next_; | 169 head_ = head_->next_; |
171 --length_; | 170 --length_; |
172 result->next_ = NULL; | 171 result->next_ = NULL; |
173 return result; | 172 return result; |
174 } | 173 } |
175 | 174 |
176 | 175 |
177 template<int BlockSize> | 176 template <int BlockSize> |
178 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::List::PopAll() { | 177 typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::List::PopAll() { |
179 Block* result = head_; | 178 Block* result = head_; |
180 head_ = NULL; | 179 head_ = NULL; |
181 length_ = 0; | 180 length_ = 0; |
182 return result; | 181 return result; |
183 } | 182 } |
184 | 183 |
185 | 184 |
186 template<int BlockSize> | 185 template <int BlockSize> |
187 void BlockStack<BlockSize>::List::Push(Block* block) { | 186 void BlockStack<BlockSize>::List::Push(Block* block) { |
188 ASSERT(block->next_ == NULL); | 187 ASSERT(block->next_ == NULL); |
189 block->next_ = head_; | 188 block->next_ = head_; |
190 head_ = block; | 189 head_ = block; |
191 ++length_; | 190 ++length_; |
192 } | 191 } |
193 | 192 |
194 | 193 |
195 bool StoreBuffer::Overflowed() { | 194 bool StoreBuffer::Overflowed() { |
196 MutexLocker ml(mutex_); | 195 MutexLocker ml(mutex_); |
197 return (full_.length() + partial_.length()) > kMaxNonEmpty; | 196 return (full_.length() + partial_.length()) > kMaxNonEmpty; |
198 } | 197 } |
199 | 198 |
200 | 199 |
201 template<int BlockSize> | 200 template <int BlockSize> |
202 void BlockStack<BlockSize>::TrimGlobalEmpty() { | 201 void BlockStack<BlockSize>::TrimGlobalEmpty() { |
203 DEBUG_ASSERT(global_mutex_->IsOwnedByCurrentThread()); | 202 DEBUG_ASSERT(global_mutex_->IsOwnedByCurrentThread()); |
204 while (global_empty_->length() > kMaxGlobalEmpty) { | 203 while (global_empty_->length() > kMaxGlobalEmpty) { |
205 delete global_empty_->Pop(); | 204 delete global_empty_->Pop(); |
206 } | 205 } |
207 } | 206 } |
208 | 207 |
209 | 208 |
210 template class BlockStack<kStoreBufferBlockSize>; | 209 template class BlockStack<kStoreBufferBlockSize>; |
211 template class BlockStack<kMarkingStackBlockSize>; | 210 template class BlockStack<kMarkingStackBlockSize>; |
212 | 211 |
213 } // namespace dart | 212 } // namespace dart |
OLD | NEW |