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

Unified Diff: runtime/vm/scavenger.cc

Issue 9956138: Process weak reference sets when a scavenge invokes the API callbacks. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rebase Created 8 years, 8 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 | « runtime/vm/scavenger.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/scavenger.cc
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index 29bb59b8aafe037466e61f1d59fbe0317a431172..ba4b3db379090020e08ea29bfc8b88e62fd53afa 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -139,16 +139,9 @@ class ScavengerWeakVisitor : public HandleVisitor {
void VisitHandle(uword addr) {
FinalizablePersistentHandle* handle =
reinterpret_cast<FinalizablePersistentHandle*>(addr);
- RawObject* raw_obj = handle->raw();
- if (!raw_obj->IsHeapObject()) return;
- uword raw_addr = RawObject::ToAddr(raw_obj);
- if (scavenger_->from_->Contains(raw_addr)) {
- uword header = *reinterpret_cast<uword*>(raw_addr);
- if (IsForwarding(header)) {
- handle->set_raw(RawObject::FromAddr(ForwardedAddr(header)));
- } else {
- FinalizablePersistentHandle::Finalize(handle);
- }
+ RawObject** p = reinterpret_cast<RawObject**>(handle);
+ if (scavenger_->IsUnreachable(p)) {
+ FinalizablePersistentHandle::Finalize(handle);
}
}
@@ -225,7 +218,7 @@ void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) {
memset(from_->pointer(), 0xf3, from_->size());
#endif // defined(DEBUG)
if (invoke_api_callbacks) {
- isolate->gc_prologue_callbacks().Invoke();
+ isolate->gc_epilogue_callbacks().Invoke();
}
}
@@ -240,6 +233,80 @@ void Scavenger::IterateRoots(Isolate* isolate,
}
+bool Scavenger::IsUnreachable(RawObject** p) {
+ RawObject* raw_obj = *p;
+ if (!raw_obj->IsHeapObject()) {
+ return false;
+ }
+ if (!raw_obj->IsNewObject()) {
+ 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 scavenged.
+ 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 scavenged.
+ 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 unreachable 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 +370,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);
« no previous file with comments | « runtime/vm/scavenger.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698