Index: runtime/vm/gc_marker.cc |
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc |
index 55199b460c2b87da057836677eb93cdf68f6f4a2..12fe96ec2ffe79e22d4a58c53a32c13792e8e71a 100644 |
--- a/runtime/vm/gc_marker.cc |
+++ b/runtime/vm/gc_marker.cc |
@@ -4,6 +4,8 @@ |
#include "vm/gc_marker.h" |
+#include <map> |
turnidge
2012/08/09 18:34:34
Do we get to use stl now? That's helpful.
|
+ |
#include "vm/allocation.h" |
#include "vm/dart_api_state.h" |
#include "vm/isolate.h" |
@@ -137,6 +139,29 @@ class MarkingVisitor : public ObjectPointerVisitor { |
} |
} |
+ void DelayWeakProperty(RawWeakProperty* raw_weak) { |
+ RawObject* raw_key = raw_weak->ptr()->key_; |
+ DelaySet::iterator it = delay_set_.find(raw_key); |
+ if (it != delay_set_.end()) { |
+ ASSERT(raw_key->IsWatched()); |
+ WeakProperty::Push(raw_weak, &it->second); |
+ } else { |
+ ASSERT(!raw_key->IsWatched()); |
+ raw_key->SetWatchedBit(); |
+ delay_set_[raw_key] = raw_weak; |
+ } |
turnidge
2012/08/09 18:34:34
So what we are implementing here is a map from Key
cshapiro
2012/08/14 04:58:18
I am now using a multimap instead of a map. As su
|
+ } |
+ |
+ void Finalize() { |
+ DelaySet::iterator it = delay_set_.begin(); |
+ for (; it != delay_set_.end(); ++it) { |
+ while (it->second != Object::null()) { |
+ RawWeakProperty* head = WeakProperty::Pop(&it->second); |
+ WeakProperty::Clear(head); |
+ } |
+ } |
+ } |
+ |
void set_update_store_buffers(bool val) { update_store_buffers_ = val; } |
private: |
@@ -148,6 +173,19 @@ class MarkingVisitor : public ObjectPointerVisitor { |
ASSERT(!raw_obj->IsMarked()); |
RawClass* raw_class = isolate()->class_table()->At(raw_obj->GetClassId()); |
raw_obj->SetMarkBit(); |
+ if (raw_obj->IsWatched()) { |
+ DelaySet::iterator it = delay_set_.find(raw_obj); |
+ ASSERT(it != delay_set_.end()); |
+ RawWeakProperty* raw_weak = it->second; |
+ while (raw_weak != WeakProperty::null()) { |
turnidge
2012/08/09 18:34:34
Is there are reason that you use WeakProperty::Pop
cshapiro
2012/08/14 04:58:18
That was an oversight. This has been superseded b
|
+ raw_weak->VisitPointers(this); |
+ RawWeakProperty* next = raw_weak->ptr()->next_; |
+ raw_weak->ptr()->next_ = WeakProperty::null(); |
+ raw_weak = next; |
+ } |
+ delay_set_.erase(it); |
+ raw_obj->ClearWatchedBit(); |
+ } |
marking_stack_->Push(raw_obj); |
// Update the number of used bytes on this page for fast accounting. |
@@ -184,6 +222,8 @@ class MarkingVisitor : public ObjectPointerVisitor { |
Heap* vm_heap_; |
PageSpace* page_space_; |
MarkingStack* marking_stack_; |
+ typedef std::map<RawObject*, RawWeakProperty*> DelaySet; |
+ DelaySet delay_set_; |
bool update_store_buffers_; |
DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor); |
@@ -318,12 +358,31 @@ void GCMarker::DrainMarkingStack(Isolate* isolate, |
visitor->set_update_store_buffers(true); |
while (!visitor->marking_stack()->IsEmpty()) { |
RawObject* raw_obj = visitor->marking_stack()->Pop(); |
- raw_obj->VisitPointers(visitor); |
+ if (raw_obj->GetClassId() != kWeakProperty) { |
+ raw_obj->VisitPointers(visitor); |
+ } else { |
+ RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); |
+ ProcessWeakProperty(raw_weak, visitor); |
+ } |
} |
visitor->set_update_store_buffers(false); |
} |
+void GCMarker::ProcessWeakProperty(RawWeakProperty* raw_weak, |
+ MarkingVisitor* visitor) { |
+ // The fate of the weak property is determined by its key. |
+ RawObject* raw_key = raw_weak->ptr()->key_; |
+ if (!raw_key->IsMarked()) { |
+ // Key is white. Delay the weak property. |
+ visitor->DelayWeakProperty(raw_weak); |
+ } else { |
+ // Key is gray or black. Make the weak property black. |
+ raw_weak->VisitPointers(visitor); |
+ } |
+} |
+ |
+ |
void GCMarker::MarkObjects(Isolate* isolate, |
PageSpace* page_space, |
bool invoke_api_callbacks) { |
@@ -335,6 +394,7 @@ void GCMarker::MarkObjects(Isolate* isolate, |
IterateWeakReferences(isolate, &mark); |
MarkingWeakVisitor mark_weak; |
IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); |
+ mark.Finalize(); |
Epilogue(isolate, invoke_api_callbacks); |
} |