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

Unified Diff: src/global-handles.cc

Issue 998253006: two pass phantom collection (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix debugger Created 5 years, 9 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 | « src/global-handles.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/global-handles.cc
diff --git a/src/global-handles.cc b/src/global-handles.cc
index 0554c53bb5deca3d5458199a29793ced681fdb1b..25c6b4efda9dd9172f14df8d327828c417ab46ae 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -264,38 +264,28 @@ class GlobalHandles::Node {
if (weak_callback_ != NULL) {
if (weakness_type() == NORMAL_WEAK) return;
- v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate);
-
DCHECK(weakness_type() == PHANTOM_WEAK ||
weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
- Object* internal_field0 = nullptr;
- Object* internal_field1 = nullptr;
- if (weakness_type() != PHANTOM_WEAK) {
- if (object()->IsJSObject()) {
- JSObject* jsobject = JSObject::cast(object());
- int field_count = jsobject->GetInternalFieldCount();
- if (field_count > 0) {
- internal_field0 = jsobject->GetInternalField(0);
- if (!internal_field0->IsSmi()) internal_field0 = nullptr;
- }
- if (field_count > 1) {
- internal_field1 = jsobject->GetInternalField(1);
- if (!internal_field1->IsSmi()) internal_field1 = nullptr;
- }
+ void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr,
+ nullptr};
+ if (weakness_type() != PHANTOM_WEAK && object()->IsJSObject()) {
+ auto jsobject = JSObject::cast(object());
+ int field_count = jsobject->GetInternalFieldCount();
+ for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) {
+ if (field_count == i) break;
+ auto field = jsobject->GetInternalField(i);
+ if (field->IsSmi()) internal_fields[i] = field;
}
}
- // Zap with harmless value.
- *location() = Smi::FromInt(0);
- typedef v8::WeakCallbackInfo<void> Data;
-
- Data data(api_isolate, parameter(), internal_field0, internal_field1);
- Data::Callback callback =
- reinterpret_cast<Data::Callback>(weak_callback_);
+ // Zap with something dangerous.
+ *location() = reinterpret_cast<Object*>(0x6057ca11);
+ typedef v8::WeakCallbackInfo<void> Data;
+ auto callback = reinterpret_cast<Data::Callback>(weak_callback_);
pending_phantom_callbacks->Add(
- PendingPhantomCallback(this, data, callback));
+ PendingPhantomCallback(this, callback, parameter(), internal_fields));
DCHECK(IsInUse());
set_state(NEAR_DEATH);
}
@@ -838,17 +828,50 @@ void GlobalHandles::UpdateListOfNewSpaceNodes() {
int GlobalHandles::DispatchPendingPhantomCallbacks() {
int freed_nodes = 0;
+ {
+ // The initial pass callbacks must simply clear the nodes.
+ for (auto i = pending_phantom_callbacks_.begin();
+ i != pending_phantom_callbacks_.end(); ++i) {
+ auto callback = i;
+ // Skip callbacks that have already been processed once.
+ if (callback->node() == nullptr) continue;
+ callback->Invoke(isolate());
+ freed_nodes++;
+ }
+ }
+ // The second pass empties the list.
while (pending_phantom_callbacks_.length() != 0) {
- PendingPhantomCallback callback = pending_phantom_callbacks_.RemoveLast();
- DCHECK(callback.node()->IsInUse());
- callback.invoke();
- DCHECK(!callback.node()->IsInUse());
- freed_nodes++;
+ auto callback = pending_phantom_callbacks_.RemoveLast();
+ DCHECK(callback.node() == nullptr);
+ // No second pass callback required.
+ if (callback.callback() == nullptr) continue;
+ // Fire second pass callback.
+ callback.Invoke(isolate());
}
return freed_nodes;
}
+void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) {
+ Data::Callback* callback_addr = nullptr;
+ if (node_ != nullptr) {
+ // Initialize for first pass callback.
+ DCHECK(node_->state() == Node::NEAR_DEATH);
+ callback_addr = &callback_;
+ }
+ Data data(reinterpret_cast<v8::Isolate*>(isolate), parameter_,
+ internal_fields_, callback_addr);
+ Data::Callback callback = callback_;
+ callback_ = nullptr;
+ callback(data);
+ if (node_ != nullptr) {
+ // Transition to second pass state.
+ DCHECK(node_->state() == Node::FREE);
+ node_ = nullptr;
+ }
+}
+
+
int GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) {
// Process weak global handle callbacks. This must be done after the
// GC is completely done, because the callbacks may invoke arbitrary
@@ -879,14 +902,6 @@ int GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) {
}
-void GlobalHandles::PendingPhantomCallback::invoke() {
- if (node_->state() == Node::FREE) return;
- DCHECK(node_->state() == Node::NEAR_DEATH);
- callback_(data_);
- if (node_->state() != Node::FREE) node_->Release();
-}
-
-
void GlobalHandles::IterateStrongRoots(ObjectVisitor* v) {
for (NodeIterator it(this); !it.done(); it.Advance()) {
if (it.node()->IsStrongRetainer()) {
« no previous file with comments | « src/global-handles.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698