Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Unified Diff: runtime/vm/gc_marker.cc

Issue 2001713002: - Removed the kWatchedBit and the associated weak property handling (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove residual watched bit. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/object.cc » ('j') | runtime/vm/raw_object.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/gc_marker.cc
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 2c2643ec8295fa2778a28acc90f3af0c5ba7c41e..93c9e7cff8be847fc204568d2694826dc9e61498 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -4,10 +4,6 @@
#include "vm/gc_marker.h"
-#include <map>
-#include <utility>
-#include <vector>
-
#include "vm/allocation.h"
#include "vm/dart_api_state.h"
#include "vm/isolate.h"
@@ -25,64 +21,6 @@
namespace dart {
-class DelaySet {
- private:
- typedef std::multimap<RawObject*, RawWeakProperty*> Map;
- typedef std::pair<RawObject*, RawWeakProperty*> MapEntry;
-
- public:
- DelaySet() : mutex_(new Mutex()) {}
- ~DelaySet() { delete mutex_; }
-
- // After atomically setting the watched bit on a white key (see
- // EnsureWatchedIfWhitewhich; this means the mark bit cannot be set
- // without observing the watched bit), this method atomically
- // inserts raw_weak if its key is *still* white, so that any future
- // call to VisitValuesForKey is guaranteed to include its
- // value. Returns true on success, and false if the key is no longer white.
- bool InsertIfWhite(RawWeakProperty* raw_weak) {
- MutexLocker ml(mutex_);
- RawObject* raw_key = raw_weak->ptr()->key_;
- if (raw_key->IsMarked()) return false;
- // The key was white *after* acquiring the lock. Thus any future call to
- // VisitValuesForKey is guaranteed to include the entry inserted below.
- delay_set_.insert(std::make_pair(raw_key, raw_weak));
- return true;
- }
-
- void ClearReferences() {
- MutexLocker ml(mutex_);
- for (Map::iterator it = delay_set_.begin(); it != delay_set_.end(); ++it) {
- ASSERT(!it->first->IsMarked());
- WeakProperty::Clear(it->second);
- }
- }
-
- // Visit all values with a key equal to raw_obj, which must already be marked.
- void VisitValuesForKey(RawObject* raw_obj, ObjectPointerVisitor* visitor) {
- ASSERT(raw_obj->IsMarked());
- // Extract the range into a temporary vector to iterate over it
- // while delay_set_ may be modified.
- std::vector<MapEntry> temp_copy;
- {
- MutexLocker ml(mutex_);
- std::pair<Map::iterator, Map::iterator> ret =
- delay_set_.equal_range(raw_obj);
- temp_copy.insert(temp_copy.end(), ret.first, ret.second);
- delay_set_.erase(ret.first, ret.second);
- }
- for (std::vector<MapEntry>::iterator it = temp_copy.begin();
- it != temp_copy.end(); ++it) {
- it->second->VisitPointers(visitor);
- }
- }
-
- private:
- Map delay_set_;
- Mutex* mutex_;
-};
-
-
class SkippedCodeFunctions : public ZoneAllocated {
public:
SkippedCodeFunctions() {}
@@ -206,7 +144,6 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
Heap* heap,
PageSpace* page_space,
MarkingStack* marking_stack,
- DelaySet* delay_set,
SkippedCodeFunctions* skipped_code_functions)
: ObjectPointerVisitor(isolate),
thread_(Thread::Current()),
@@ -216,7 +153,7 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
class_stats_size_(isolate->class_table()->NumCids()),
page_space_(page_space),
work_list_(marking_stack),
- delay_set_(delay_set),
+ delayed_weak_properties_(NULL),
visiting_old_object_(NULL),
skipped_code_functions_(skipped_code_functions),
marked_bytes_(0) {
@@ -248,15 +185,44 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
return false;
}
do {
- VisitingOldObject(raw_obj);
- const intptr_t class_id = raw_obj->GetClassId();
- if (class_id != kWeakPropertyCid) {
- marked_bytes_ += raw_obj->VisitPointers(this);
- } else {
- RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj);
- marked_bytes_ += raw_weak->Size();
- ProcessWeakProperty(raw_weak);
+ do {
+ // First drain the marking stacks.
+ VisitingOldObject(raw_obj);
+ const intptr_t class_id = raw_obj->GetClassId();
+ if (class_id != kWeakPropertyCid) {
+ marked_bytes_ += raw_obj->VisitPointers(this);
+ } else {
+ RawWeakProperty* raw_weak =
+ reinterpret_cast<RawWeakProperty*>(raw_obj);
+ marked_bytes_ += ProcessWeakProperty(raw_weak);
+ }
+ raw_obj = work_list_.Pop();
+ } while (raw_obj != NULL);
+
+ // Marking stack is empty.
+ // Process all the pending weak properties in this visitor.
+ RawWeakProperty* cur_weak = delayed_weak_properties_;
+ delayed_weak_properties_ = NULL;
+ while (cur_weak != NULL) {
+ uword next_weak = cur_weak->ptr()->next_;
+ RawObject* raw_key = cur_weak->ptr()->key_;
+ // Reset the next pointer in the weak property.
+ cur_weak->ptr()->next_ = 0;
+ if (raw_key->IsMarked()) {
+ // The key is marked so we make sure to properly visit all pointers
+ // originating from this weak property.
+ VisitingOldObject(cur_weak);
+ cur_weak->VisitPointers(this);
+ } else {
+ // Requeue this weak property to be handled later.
+ EnqueueWeakProperty(cur_weak);
+ }
+ // Advance to next weak property in the queue.
+ cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
}
+
+ // Check whether any further work was pushed either by other markers or
+ // by the handling of weak properties.
raw_obj = work_list_.Pop();
} while (raw_obj != NULL);
VisitingOldObject(NULL);
@@ -278,47 +244,49 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
skipped_code_functions_->Add(func);
}
- // If unmarked, sets the watch bit and returns true.
- // If marked, does nothing and returns false.
- static bool EnsureWatchedIfWhite(RawObject* obj) {
- if (!sync) {
- if (obj->IsMarked()) return false;
- if (!obj->IsWatched()) obj->SetWatchedBitUnsynchronized();
- return true;
- }
- uword tags = obj->ptr()->tags_;
- uword old_tags;
- do {
- old_tags = tags;
- if (RawObject::MarkBit::decode(tags)) return false;
- if (RawObject::WatchedBit::decode(tags)) return true;
- uword new_tags = RawObject::WatchedBit::update(true, old_tags);
- tags = AtomicOperations::CompareAndSwapWord(
- &obj->ptr()->tags_, old_tags, new_tags);
- } while (tags != old_tags);
- return true;
+ void EnqueueWeakProperty(RawWeakProperty* raw_weak) {
+ ASSERT(raw_weak->IsHeapObject());
+ ASSERT(raw_weak->IsOldObject());
+ ASSERT(raw_weak->IsWeakProperty());
+ ASSERT(raw_weak->IsMarked());
+ ASSERT(raw_weak->ptr()->next_ == 0);
+ raw_weak->ptr()->next_ = reinterpret_cast<uword>(delayed_weak_properties_);
+ delayed_weak_properties_ = raw_weak;
}
- void ProcessWeakProperty(RawWeakProperty* raw_weak) {
+ intptr_t ProcessWeakProperty(RawWeakProperty* raw_weak) {
// The fate of the weak property is determined by its key.
RawObject* raw_key = raw_weak->ptr()->key_;
if (raw_key->IsHeapObject() &&
raw_key->IsOldObject() &&
- EnsureWatchedIfWhite(raw_key) &&
- delay_set_->InsertIfWhite(raw_weak)) {
- // Key was white. Delayed the weak property.
- } else {
- // Key is gray or black. Make the weak property black.
- raw_weak->VisitPointers(this);
+ !raw_key->IsMarked()) {
+ // Key was white. Enqueue the weak property.
+ EnqueueWeakProperty(raw_weak);
+ return raw_weak->Size();
}
+ // Key is gray or black. Make the weak property black.
+ return raw_weak->VisitPointers(this);
}
// Called when all marking is complete.
void Finalize() {
work_list_.Finalize();
+ // Detach code from functions.
if (skipped_code_functions_ != NULL) {
skipped_code_functions_->DetachCode();
}
+ // Clear pending weak properties.
+ RawWeakProperty* cur_weak = delayed_weak_properties_;
+ delayed_weak_properties_ = NULL;
+ intptr_t weak_properties_cleared = 0;
+ while (cur_weak != NULL) {
+ uword next_weak = cur_weak->ptr()->next_;
+ cur_weak->ptr()->next_ = 0;
+ WeakProperty::Clear(cur_weak);
siva 2016/05/23 20:35:33 Maybe set next_ to 0 inside Clear so reseting of a
+ weak_properties_cleared++;
+ // Advance to next weak property in the queue.
+ cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
+ }
}
void VisitingOldObject(RawObject* obj) {
@@ -335,15 +303,10 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
// Push the marked object on the marking stack.
ASSERT(raw_obj->IsMarked());
- const bool is_watched = raw_obj->IsWatched();
// We acquired the mark bit => no other task is modifying the header.
// TODO(koda): For concurrent mutator, this needs synchronization. Consider
// clearing these bits already in the CAS for the mark bit.
raw_obj->ClearRememberedBitUnsynchronized();
- raw_obj->ClearWatchedBitUnsynchronized();
- if (is_watched) {
- delay_set_->VisitValuesForKey(raw_obj, this);
- }
work_list_.Push(raw_obj);
}
@@ -430,7 +393,7 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
GrowableArray<intptr_t> class_stats_size_;
PageSpace* page_space_;
MarkerWorkList work_list_;
- DelaySet* delay_set_;
+ RawWeakProperty* delayed_weak_properties_;
RawObject* visiting_old_object_;
SkippedCodeFunctions* skipped_code_functions_;
uintptr_t marked_bytes_;
@@ -574,7 +537,6 @@ class MarkTask : public ThreadPool::Task {
Heap* heap,
PageSpace* page_space,
MarkingStack* marking_stack,
- DelaySet* delay_set,
ThreadBarrier* barrier,
bool collect_code,
intptr_t task_index,
@@ -585,7 +547,6 @@ class MarkTask : public ThreadPool::Task {
heap_(heap),
page_space_(page_space),
marking_stack_(marking_stack),
- delay_set_(delay_set),
barrier_(barrier),
collect_code_(collect_code),
task_index_(task_index),
@@ -605,7 +566,7 @@ class MarkTask : public ThreadPool::Task {
SkippedCodeFunctions* skipped_code_functions =
collect_code_ ? new(zone) SkippedCodeFunctions() : NULL;
SyncMarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_,
- delay_set_, skipped_code_functions);
+ skipped_code_functions);
// Phase 1: Iterate over roots and drain marking stack in tasks.
marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_);
do {
@@ -653,7 +614,6 @@ class MarkTask : public ThreadPool::Task {
Heap* heap_;
PageSpace* page_space_;
MarkingStack* marking_stack_;
- DelaySet* delay_set_;
ThreadBarrier* barrier_;
bool collect_code_;
const intptr_t task_index_;
@@ -695,7 +655,6 @@ void GCMarker::MarkObjects(Isolate* isolate,
StackZone stack_zone(Thread::Current());
Zone* zone = stack_zone.GetZone();
MarkingStack marking_stack;
- DelaySet delay_set;
marked_bytes_ = 0;
const int num_tasks = FLAG_marker_tasks;
if (num_tasks == 0) {
@@ -703,7 +662,7 @@ void GCMarker::MarkObjects(Isolate* isolate,
SkippedCodeFunctions* skipped_code_functions =
collect_code ? new(zone) SkippedCodeFunctions() : NULL;
UnsyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
- &delay_set, skipped_code_functions);
+ skipped_code_functions);
IterateRoots(isolate, &mark, 0, 1);
mark.DrainMarkingStack();
MarkingWeakVisitor mark_weak;
@@ -720,31 +679,21 @@ void GCMarker::MarkObjects(Isolate* isolate,
for (intptr_t i = 0; i < num_tasks; ++i) {
MarkTask* mark_task =
new MarkTask(this, isolate, heap_, page_space, &marking_stack,
- &delay_set, &barrier, collect_code,
+ &barrier, collect_code,
i, num_tasks, &num_busy);
ThreadPool* pool = Dart::thread_pool();
pool->Run(mark_task);
}
barrier.Sync();
- // Phase 2: Weak processing and follow-up marking on main thread.
- SkippedCodeFunctions* skipped_code_functions =
- collect_code ? new(zone) SkippedCodeFunctions() : NULL;
- SyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
- &delay_set, skipped_code_functions);
+ // Phase 2: Weak processing on main thread.
MarkingWeakVisitor mark_weak;
IterateWeakRoots(isolate, &mark_weak);
barrier.Sync();
// Phase 3: Finalize results from all markers (detach code, etc.).
- if (FLAG_log_marker_tasks) {
- THR_Print("Main thread marked %" Pd " bytes.\n",
- mark.marked_bytes());
- }
- FinalizeResultsFrom(&mark);
barrier.Exit();
}
- delay_set.ClearReferences();
ProcessWeakTables(page_space);
ProcessObjectIdTable(isolate);
}
« no previous file with comments | « no previous file | runtime/vm/object.cc » ('j') | runtime/vm/raw_object.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698