| 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 |