Chromium Code Reviews| Index: runtime/vm/scavenger.cc |
| diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc |
| index 29bb59b8aafe037466e61f1d59fbe0317a431172..148134ab269c7b5879b101bf7950ecd2561995d1 100644 |
| --- a/runtime/vm/scavenger.cc |
| +++ b/runtime/vm/scavenger.cc |
| @@ -240,6 +240,80 @@ void Scavenger::IterateRoots(Isolate* isolate, |
| } |
| +bool Scavenger::IsUnreachable(RawObject** p) { |
|
Ivan Posva
2012/04/06 21:54:06
Can you change this to Scavenger::IsReachable() to
cshapiro
2012/04/06 22:24:31
Yes, will do.
cshapiro
2012/04/10 02:40:31
While this is very rational adjustment when consid
|
| + RawObject* raw_obj = *p; |
| + if (!raw_obj->IsHeapObject()) { |
|
Ivan Posva
2012/04/06 21:54:06
This is surprising to me to say the least. Having
cshapiro
2012/04/06 22:24:31
I am not sure why this is surprising. Smi instanc
cshapiro
2012/04/10 02:40:31
I thought about this over the weekend. Numbers ar
|
| + return false; |
| + } |
| + if (!raw_obj->IsNewObject()) { |
|
siva
2012/04/06 17:12:25
Wouldn't just this check be sufficient, it also im
cshapiro
2012/04/06 22:24:31
Objects that become unreferenced after a new space
|
| + return false; |
| + } |
| + uword raw_addr = RawObject::ToAddr(raw_obj); |
| + if (!from_->Contains(raw_addr)) { |
| + return false; |
| + } |
| + uword header = *reinterpret_cast<uword*>(raw_addr); |
| + if (IsForwarding(header)) { |
| + uword new_addr = ForwardedAddr(header); |
| + *p = RawObject::FromAddr(new_addr); |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| + |
| +void Scavenger::IterateWeakReferences(Isolate* isolate, |
| + ObjectPointerVisitor* visitor) { |
| + ApiState* state = isolate->api_state(); |
| + ASSERT(state != NULL); |
| + while (true) { |
| + WeakReference* queue = state->delayed_weak_references(); |
| + if (queue == NULL) { |
| + // The delay queue is empty therefore no clean-up is required. |
| + return; |
| + } |
| + state->set_delayed_weak_references(NULL); |
| + while (queue != NULL) { |
| + WeakReference* reference = WeakReference::Pop(&queue); |
| + ASSERT(reference != NULL); |
| + bool is_unreachable = true; |
| + // Test each key object for reachability. If a key object is |
| + // reachable, all value objects should be marked. |
| + for (intptr_t k = 0; k < reference->num_keys(); ++k) { |
| + if (!IsUnreachable(reference->get_key(k))) { |
| + for (intptr_t v = 0; v < reference->num_values(); ++v) { |
| + visitor->VisitPointer(reference->get_value(v)); |
| + } |
| + is_unreachable = false; |
| + delete reference; |
| + break; |
| + } |
| + } |
| + // If all key objects are unreachable put the reference on a |
| + // delay queue. This reference will be revisited if another |
| + // reference is marked. |
| + if (is_unreachable) { |
| + state->DelayWeakReference(reference); |
| + } |
| + } |
| + if ((FirstObjectStart() < top_) || PromotedStackHasMore()) { |
| + ProcessToSpace(visitor); |
| + } else { |
| + // Break out of the loop if there has been no forward process. |
| + break; |
| + } |
| + } |
| + // Deallocate any unmarked references on the delay queue. |
| + if (state->delayed_weak_references() != NULL) { |
| + WeakReference* queue = state->delayed_weak_references(); |
| + state->set_delayed_weak_references(NULL); |
| + while (queue != NULL) { |
| + delete WeakReference::Pop(&queue); |
| + } |
| + } |
| +} |
| + |
| + |
| void Scavenger::IterateWeakRoots(Isolate* isolate, |
| HandleVisitor* visitor, |
| bool visit_prologue_weak_persistent_handles) { |
| @@ -303,6 +377,7 @@ void Scavenger::Scavenge(bool invoke_api_callbacks) { |
| Prologue(isolate, invoke_api_callbacks); |
| IterateRoots(isolate, &visitor, !invoke_api_callbacks); |
| ProcessToSpace(&visitor); |
| + IterateWeakReferences(isolate, &visitor); |
| ScavengerWeakVisitor weak_visitor(this); |
| IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); |
| Epilogue(isolate, invoke_api_callbacks); |