OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/scavenger.h" | 5 #include "vm/scavenger.h" |
6 | 6 |
7 #include "vm/dart.h" | 7 #include "vm/dart.h" |
8 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/object.h" | 10 #include "vm/object.h" |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); | 130 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
131 }; | 131 }; |
132 | 132 |
133 | 133 |
134 class ScavengerWeakVisitor : public HandleVisitor { | 134 class ScavengerWeakVisitor : public HandleVisitor { |
135 public: | 135 public: |
136 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { | 136 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { |
137 } | 137 } |
138 | 138 |
139 void VisitHandle(uword addr) { | 139 void VisitHandle(uword addr) { |
140 WeakPersistentHandle* handle = | 140 FinalizablePersistentHandle* handle = |
141 reinterpret_cast<WeakPersistentHandle*>(addr); | 141 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
142 RawObject* raw_obj = handle->raw(); | 142 RawObject* raw_obj = handle->raw(); |
143 if (!raw_obj->IsHeapObject()) return; | 143 if (!raw_obj->IsHeapObject()) return; |
144 uword raw_addr = RawObject::ToAddr(raw_obj); | 144 uword raw_addr = RawObject::ToAddr(raw_obj); |
145 if (scavenger_->from_->Contains(raw_addr)) { | 145 if (scavenger_->from_->Contains(raw_addr)) { |
146 uword header = *reinterpret_cast<uword*>(raw_addr); | 146 uword header = *reinterpret_cast<uword*>(raw_addr); |
147 if (IsForwarding(header)) { | 147 if (IsForwarding(header)) { |
148 handle->set_raw(RawObject::FromAddr(ForwardedAddr(header))); | 148 handle->set_raw(RawObject::FromAddr(ForwardedAddr(header))); |
149 } else { | 149 } else { |
150 WeakPersistentHandle::Finalize(handle); | 150 FinalizablePersistentHandle::Finalize(handle); |
151 } | 151 } |
152 } | 152 } |
153 } | 153 } |
154 | 154 |
155 private: | 155 private: |
156 Scavenger* scavenger_; | 156 Scavenger* scavenger_; |
157 | 157 |
158 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); | 158 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); |
159 }; | 159 }; |
160 | 160 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 } | 195 } |
196 | 196 |
197 | 197 |
198 Scavenger::~Scavenger() { | 198 Scavenger::~Scavenger() { |
199 delete to_; | 199 delete to_; |
200 delete from_; | 200 delete from_; |
201 delete space_; | 201 delete space_; |
202 } | 202 } |
203 | 203 |
204 | 204 |
205 void Scavenger::Prologue() { | 205 void Scavenger::Prologue(Isolate* isolate, bool invoke_api_callbacks) { |
| 206 if (invoke_api_callbacks) { |
| 207 isolate->gc_prologue_callbacks().Invoke(); |
| 208 } |
206 // Flip the two semi-spaces so that to_ is always the space for allocating | 209 // Flip the two semi-spaces so that to_ is always the space for allocating |
207 // objects. | 210 // objects. |
208 MemoryRegion* temp = from_; | 211 MemoryRegion* temp = from_; |
209 from_ = to_; | 212 from_ = to_; |
210 to_ = temp; | 213 to_ = temp; |
211 top_ = FirstObjectStart(); | 214 top_ = FirstObjectStart(); |
212 end_ = to_->end(); | 215 end_ = to_->end(); |
213 } | 216 } |
214 | 217 |
215 | 218 |
216 void Scavenger::Epilogue() { | 219 void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { |
217 // All objects in the to space have been copied from the from space at this | 220 // All objects in the to space have been copied from the from space at this |
218 // moment. | 221 // moment. |
219 survivor_end_ = top_; | 222 survivor_end_ = top_; |
220 | 223 |
221 #if defined(DEBUG) | 224 #if defined(DEBUG) |
222 memset(from_->pointer(), 0xf3, from_->size()); | 225 memset(from_->pointer(), 0xf3, from_->size()); |
223 #endif // defined(DEBUG) | 226 #endif // defined(DEBUG) |
| 227 if (invoke_api_callbacks) { |
| 228 isolate->gc_prologue_callbacks().Invoke(); |
| 229 } |
224 } | 230 } |
225 | 231 |
226 | 232 |
227 void Scavenger::IterateRoots(Isolate* isolate, ObjectPointerVisitor* visitor) { | 233 void Scavenger::IterateRoots(Isolate* isolate, |
| 234 ObjectPointerVisitor* visitor, |
| 235 bool visit_prologue_weak_persistent_handles) { |
228 isolate->VisitObjectPointers(visitor, | 236 isolate->VisitObjectPointers(visitor, |
| 237 visit_prologue_weak_persistent_handles, |
229 StackFrameIterator::kDontValidateFrames); | 238 StackFrameIterator::kDontValidateFrames); |
230 heap_->IterateOldPointers(visitor); | 239 heap_->IterateOldPointers(visitor); |
231 } | 240 } |
232 | 241 |
233 | 242 |
234 void Scavenger::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { | 243 void Scavenger::IterateWeakRoots(Isolate* isolate, |
235 isolate->VisitWeakPersistentHandles(visitor); | 244 HandleVisitor* visitor, |
| 245 bool visit_prologue_weak_persistent_handles) { |
| 246 isolate->VisitWeakPersistentHandles(visitor, |
| 247 visit_prologue_weak_persistent_handles); |
236 } | 248 } |
237 | 249 |
238 | 250 |
239 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { | 251 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { |
240 uword resolved_top = FirstObjectStart(); | 252 uword resolved_top = FirstObjectStart(); |
241 // Iterate until all work has been drained. | 253 // Iterate until all work has been drained. |
242 while ((resolved_top < top_) || PromotedStackHasMore()) { | 254 while ((resolved_top < top_) || PromotedStackHasMore()) { |
243 while (resolved_top < top_) { | 255 while (resolved_top < top_) { |
244 RawObject* raw_obj = RawObject::FromAddr(resolved_top); | 256 RawObject* raw_obj = RawObject::FromAddr(resolved_top); |
245 resolved_top += raw_obj->VisitPointers(visitor); | 257 resolved_top += raw_obj->VisitPointers(visitor); |
(...skipping 12 matching lines...) Expand all Loading... |
258 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 270 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
259 uword cur = FirstObjectStart(); | 271 uword cur = FirstObjectStart(); |
260 while (cur < top_) { | 272 while (cur < top_) { |
261 RawObject* raw_obj = RawObject::FromAddr(cur); | 273 RawObject* raw_obj = RawObject::FromAddr(cur); |
262 cur += raw_obj->VisitPointers(visitor); | 274 cur += raw_obj->VisitPointers(visitor); |
263 } | 275 } |
264 } | 276 } |
265 | 277 |
266 | 278 |
267 void Scavenger::Scavenge() { | 279 void Scavenger::Scavenge() { |
| 280 // TODO(cshapiro): Add a decision procedure for determining when the |
| 281 // the API callbacks should be invoked. |
| 282 Scavenge(false); |
| 283 } |
| 284 |
| 285 |
| 286 void Scavenger::Scavenge(bool invoke_api_callbacks) { |
268 // Scavenging is not reentrant. Make sure that is the case. | 287 // Scavenging is not reentrant. Make sure that is the case. |
269 ASSERT(!scavenging_); | 288 ASSERT(!scavenging_); |
270 scavenging_ = true; | 289 scavenging_ = true; |
271 Isolate* isolate = Isolate::Current(); | 290 Isolate* isolate = Isolate::Current(); |
272 NoHandleScope no_handles(isolate); | 291 NoHandleScope no_handles(isolate); |
273 | 292 |
274 if (FLAG_verify_before_gc) { | 293 if (FLAG_verify_before_gc) { |
275 OS::PrintErr("Verifying before Scavenge... "); | 294 OS::PrintErr("Verifying before Scavenge... "); |
276 heap_->Verify(); | 295 heap_->Verify(); |
277 OS::PrintErr(" done.\n"); | 296 OS::PrintErr(" done.\n"); |
278 } | 297 } |
279 | 298 |
280 Timer timer(FLAG_verbose_gc, "Scavenge"); | 299 Timer timer(FLAG_verbose_gc, "Scavenge"); |
281 timer.Start(); | 300 timer.Start(); |
282 // Setup the visitor and run a scavenge. | 301 // Setup the visitor and run a scavenge. |
283 ScavengerVisitor visitor(this); | 302 ScavengerVisitor visitor(this); |
284 Prologue(); | 303 Prologue(isolate, invoke_api_callbacks); |
285 IterateRoots(isolate, &visitor); | 304 IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
286 ProcessToSpace(&visitor); | 305 ProcessToSpace(&visitor); |
287 ScavengerWeakVisitor weak_visitor(this); | 306 ScavengerWeakVisitor weak_visitor(this); |
288 IterateWeakRoots(isolate, &weak_visitor); | 307 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
289 Epilogue(); | 308 Epilogue(isolate, invoke_api_callbacks); |
290 timer.Stop(); | 309 timer.Stop(); |
291 if (FLAG_verbose_gc) { | 310 if (FLAG_verbose_gc) { |
292 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 311 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
293 } | 312 } |
294 | 313 |
295 if (FLAG_verify_after_gc) { | 314 if (FLAG_verify_after_gc) { |
296 OS::PrintErr("Verifying after Scavenge... "); | 315 OS::PrintErr("Verifying after Scavenge... "); |
297 heap_->Verify(); | 316 heap_->Verify(); |
298 OS::PrintErr(" done.\n"); | 317 OS::PrintErr(" done.\n"); |
299 } | 318 } |
300 | 319 |
301 count_++; | 320 count_++; |
302 // Done scavenging. Reset the marker. | 321 // Done scavenging. Reset the marker. |
303 ASSERT(scavenging_); | 322 ASSERT(scavenging_); |
304 scavenging_ = false; | 323 scavenging_ = false; |
305 } | 324 } |
306 | 325 |
307 } // namespace dart | 326 } // namespace dart |
OLD | NEW |