| 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 FinalizablePersistentHandle* handle = | 140 FinalizablePersistentHandle* handle = |
| 141 reinterpret_cast<FinalizablePersistentHandle*>(addr); | 141 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
| 142 RawObject* raw_obj = handle->raw(); | 142 RawObject** p = reinterpret_cast<RawObject**>(handle); |
| 143 if (!raw_obj->IsHeapObject()) return; | 143 if (scavenger_->IsUnreachable(p)) { |
| 144 uword raw_addr = RawObject::ToAddr(raw_obj); | 144 FinalizablePersistentHandle::Finalize(handle); |
| 145 if (scavenger_->from_->Contains(raw_addr)) { | |
| 146 uword header = *reinterpret_cast<uword*>(raw_addr); | |
| 147 if (IsForwarding(header)) { | |
| 148 handle->set_raw(RawObject::FromAddr(ForwardedAddr(header))); | |
| 149 } else { | |
| 150 FinalizablePersistentHandle::Finalize(handle); | |
| 151 } | |
| 152 } | 145 } |
| 153 } | 146 } |
| 154 | 147 |
| 155 private: | 148 private: |
| 156 Scavenger* scavenger_; | 149 Scavenger* scavenger_; |
| 157 | 150 |
| 158 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); | 151 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); |
| 159 }; | 152 }; |
| 160 | 153 |
| 161 | 154 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 | 211 |
| 219 void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { | 212 void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { |
| 220 // All objects in the to space have been copied from the from space at this | 213 // All objects in the to space have been copied from the from space at this |
| 221 // moment. | 214 // moment. |
| 222 survivor_end_ = top_; | 215 survivor_end_ = top_; |
| 223 | 216 |
| 224 #if defined(DEBUG) | 217 #if defined(DEBUG) |
| 225 memset(from_->pointer(), 0xf3, from_->size()); | 218 memset(from_->pointer(), 0xf3, from_->size()); |
| 226 #endif // defined(DEBUG) | 219 #endif // defined(DEBUG) |
| 227 if (invoke_api_callbacks) { | 220 if (invoke_api_callbacks) { |
| 228 isolate->gc_prologue_callbacks().Invoke(); | 221 isolate->gc_epilogue_callbacks().Invoke(); |
| 229 } | 222 } |
| 230 } | 223 } |
| 231 | 224 |
| 232 | 225 |
| 233 void Scavenger::IterateRoots(Isolate* isolate, | 226 void Scavenger::IterateRoots(Isolate* isolate, |
| 234 ObjectPointerVisitor* visitor, | 227 ObjectPointerVisitor* visitor, |
| 235 bool visit_prologue_weak_persistent_handles) { | 228 bool visit_prologue_weak_persistent_handles) { |
| 236 isolate->VisitObjectPointers(visitor, | 229 isolate->VisitObjectPointers(visitor, |
| 237 visit_prologue_weak_persistent_handles, | 230 visit_prologue_weak_persistent_handles, |
| 238 StackFrameIterator::kDontValidateFrames); | 231 StackFrameIterator::kDontValidateFrames); |
| 239 heap_->IterateOldPointers(visitor); | 232 heap_->IterateOldPointers(visitor); |
| 240 } | 233 } |
| 241 | 234 |
| 242 | 235 |
| 236 bool Scavenger::IsUnreachable(RawObject** p) { |
| 237 RawObject* raw_obj = *p; |
| 238 if (!raw_obj->IsHeapObject()) { |
| 239 return false; |
| 240 } |
| 241 if (!raw_obj->IsNewObject()) { |
| 242 return false; |
| 243 } |
| 244 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 245 if (!from_->Contains(raw_addr)) { |
| 246 return false; |
| 247 } |
| 248 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 249 if (IsForwarding(header)) { |
| 250 uword new_addr = ForwardedAddr(header); |
| 251 *p = RawObject::FromAddr(new_addr); |
| 252 return false; |
| 253 } |
| 254 return true; |
| 255 } |
| 256 |
| 257 |
| 258 void Scavenger::IterateWeakReferences(Isolate* isolate, |
| 259 ObjectPointerVisitor* visitor) { |
| 260 ApiState* state = isolate->api_state(); |
| 261 ASSERT(state != NULL); |
| 262 while (true) { |
| 263 WeakReference* queue = state->delayed_weak_references(); |
| 264 if (queue == NULL) { |
| 265 // The delay queue is empty therefore no clean-up is required. |
| 266 return; |
| 267 } |
| 268 state->set_delayed_weak_references(NULL); |
| 269 while (queue != NULL) { |
| 270 WeakReference* reference = WeakReference::Pop(&queue); |
| 271 ASSERT(reference != NULL); |
| 272 bool is_unreachable = true; |
| 273 // Test each key object for reachability. If a key object is |
| 274 // reachable, all value objects should be scavenged. |
| 275 for (intptr_t k = 0; k < reference->num_keys(); ++k) { |
| 276 if (!IsUnreachable(reference->get_key(k))) { |
| 277 for (intptr_t v = 0; v < reference->num_values(); ++v) { |
| 278 visitor->VisitPointer(reference->get_value(v)); |
| 279 } |
| 280 is_unreachable = false; |
| 281 delete reference; |
| 282 break; |
| 283 } |
| 284 } |
| 285 // If all key objects are unreachable put the reference on a |
| 286 // delay queue. This reference will be revisited if another |
| 287 // reference is scavenged. |
| 288 if (is_unreachable) { |
| 289 state->DelayWeakReference(reference); |
| 290 } |
| 291 } |
| 292 if ((FirstObjectStart() < top_) || PromotedStackHasMore()) { |
| 293 ProcessToSpace(visitor); |
| 294 } else { |
| 295 // Break out of the loop if there has been no forward process. |
| 296 break; |
| 297 } |
| 298 } |
| 299 // Deallocate any unreachable references on the delay queue. |
| 300 if (state->delayed_weak_references() != NULL) { |
| 301 WeakReference* queue = state->delayed_weak_references(); |
| 302 state->set_delayed_weak_references(NULL); |
| 303 while (queue != NULL) { |
| 304 delete WeakReference::Pop(&queue); |
| 305 } |
| 306 } |
| 307 } |
| 308 |
| 309 |
| 243 void Scavenger::IterateWeakRoots(Isolate* isolate, | 310 void Scavenger::IterateWeakRoots(Isolate* isolate, |
| 244 HandleVisitor* visitor, | 311 HandleVisitor* visitor, |
| 245 bool visit_prologue_weak_persistent_handles) { | 312 bool visit_prologue_weak_persistent_handles) { |
| 246 isolate->VisitWeakPersistentHandles(visitor, | 313 isolate->VisitWeakPersistentHandles(visitor, |
| 247 visit_prologue_weak_persistent_handles); | 314 visit_prologue_weak_persistent_handles); |
| 248 } | 315 } |
| 249 | 316 |
| 250 | 317 |
| 251 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { | 318 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { |
| 252 uword resolved_top = FirstObjectStart(); | 319 uword resolved_top = FirstObjectStart(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 OS::PrintErr(" done.\n"); | 363 OS::PrintErr(" done.\n"); |
| 297 } | 364 } |
| 298 | 365 |
| 299 Timer timer(FLAG_verbose_gc, "Scavenge"); | 366 Timer timer(FLAG_verbose_gc, "Scavenge"); |
| 300 timer.Start(); | 367 timer.Start(); |
| 301 // Setup the visitor and run a scavenge. | 368 // Setup the visitor and run a scavenge. |
| 302 ScavengerVisitor visitor(this); | 369 ScavengerVisitor visitor(this); |
| 303 Prologue(isolate, invoke_api_callbacks); | 370 Prologue(isolate, invoke_api_callbacks); |
| 304 IterateRoots(isolate, &visitor, !invoke_api_callbacks); | 371 IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
| 305 ProcessToSpace(&visitor); | 372 ProcessToSpace(&visitor); |
| 373 IterateWeakReferences(isolate, &visitor); |
| 306 ScavengerWeakVisitor weak_visitor(this); | 374 ScavengerWeakVisitor weak_visitor(this); |
| 307 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); | 375 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
| 308 Epilogue(isolate, invoke_api_callbacks); | 376 Epilogue(isolate, invoke_api_callbacks); |
| 309 timer.Stop(); | 377 timer.Stop(); |
| 310 if (FLAG_verbose_gc) { | 378 if (FLAG_verbose_gc) { |
| 311 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 379 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
| 312 } | 380 } |
| 313 | 381 |
| 314 if (FLAG_verify_after_gc) { | 382 if (FLAG_verify_after_gc) { |
| 315 OS::PrintErr("Verifying after Scavenge... "); | 383 OS::PrintErr("Verifying after Scavenge... "); |
| 316 heap_->Verify(); | 384 heap_->Verify(); |
| 317 OS::PrintErr(" done.\n"); | 385 OS::PrintErr(" done.\n"); |
| 318 } | 386 } |
| 319 | 387 |
| 320 count_++; | 388 count_++; |
| 321 // Done scavenging. Reset the marker. | 389 // Done scavenging. Reset the marker. |
| 322 ASSERT(scavenging_); | 390 ASSERT(scavenging_); |
| 323 scavenging_ = false; | 391 scavenging_ = false; |
| 324 } | 392 } |
| 325 | 393 |
| 326 } // namespace dart | 394 } // namespace dart |
| OLD | NEW |