Index: src/global-handles.cc |
diff --git a/src/global-handles.cc b/src/global-handles.cc |
index 282ca2d5d86a63d86dd00b1eb4b43888c3289e6b..574b2489ea2bc1e21dc8d917a2935700a050bdee 100644 |
--- a/src/global-handles.cc |
+++ b/src/global-handles.cc |
@@ -146,6 +146,13 @@ class GlobalHandles::Node { |
flags_ = IsInNewSpaceList::update(flags_, v); |
} |
+ bool is_zapped_during_weak_callback() { |
+ return IsZappedDuringWeakCallback::decode(flags_); |
+ } |
+ void set_is_zapped_during_weak_callback(bool v) { |
+ flags_ = IsZappedDuringWeakCallback::update(flags_, v); |
+ } |
+ |
bool IsNearDeath() const { |
// Check for PENDING to ensure correct answer when processing callbacks. |
return state() == PENDING || state() == NEAR_DEATH; |
@@ -204,12 +211,14 @@ class GlobalHandles::Node { |
parameter_or_next_free_.next_free = value; |
} |
- void MakeWeak(void* parameter, WeakCallback weak_callback) { |
+ void MakeWeak(void* parameter, WeakCallback weak_callback, |
+ bool is_zapped_during_weak_callback = false) { |
DCHECK(weak_callback != NULL); |
DCHECK(state() != FREE); |
CHECK(object_ != NULL); |
set_state(WEAK); |
set_parameter(parameter); |
+ set_is_zapped_during_weak_callback(is_zapped_during_weak_callback); |
weak_callback_ = weak_callback; |
} |
@@ -227,7 +236,7 @@ class GlobalHandles::Node { |
Release(); |
return false; |
} |
- void* par = parameter(); |
+ void* param = parameter(); |
set_state(NEAR_DEATH); |
set_parameter(NULL); |
@@ -240,14 +249,28 @@ class GlobalHandles::Node { |
DCHECK(!object_->IsExternalTwoByteString() || |
ExternalTwoByteString::cast(object_)->resource() != NULL); |
// Leaving V8. |
- VMState<EXTERNAL> state(isolate); |
+ VMState<EXTERNAL> vmstate(isolate); |
HandleScope handle_scope(isolate); |
- Handle<Object> handle(*object, isolate); |
- v8::WeakCallbackData<v8::Value, void> data( |
- reinterpret_cast<v8::Isolate*>(isolate), |
- v8::Utils::ToLocal(handle), |
- par); |
- weak_callback_(data); |
+ if (is_zapped_during_weak_callback()) { |
+ // Phantom weak pointer case. |
+ DCHECK(*object == Smi::FromInt(kPhantomReferenceZap)); |
+ // Make data with a null handle. |
+ v8::WeakCallbackData<v8::Value, void> data( |
+ reinterpret_cast<v8::Isolate*>(isolate), v8::Local<v8::Object>(), |
+ param); |
+ weak_callback_(data); |
+ if (state() != FREE) { |
+ // Callback does not have to clear the global handle if it is a |
+ // phantom handle. |
+ Release(); |
+ } |
+ } else { |
+ Handle<Object> handle(*object, isolate); |
Erik Corry
2014/11/02 18:41:45
This CL is a reland of https://codereview.chromium
|
+ v8::WeakCallbackData<v8::Value, void> data( |
+ reinterpret_cast<v8::Isolate*>(isolate), v8::Utils::ToLocal(handle), |
+ param); |
+ weak_callback_(data); |
+ } |
} |
// Absence of explicit cleanup or revival of weak handle |
// in most of the cases would lead to memory leak. |
@@ -277,10 +300,11 @@ class GlobalHandles::Node { |
// This stores three flags (independent, partially_dependent and |
// in_new_space_list) and a State. |
- class NodeState: public BitField<State, 0, 4> {}; |
- class IsIndependent: public BitField<bool, 4, 1> {}; |
- class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
- class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
+ class NodeState : public BitField<State, 0, 4> {}; |
+ class IsIndependent : public BitField<bool, 4, 1> {}; |
+ class IsPartiallyDependent : public BitField<bool, 5, 1> {}; |
+ class IsInNewSpaceList : public BitField<bool, 6, 1> {}; |
+ class IsZappedDuringWeakCallback : public BitField<bool, 7, 1> {}; |
uint8_t flags_; |
@@ -475,10 +499,10 @@ void GlobalHandles::Destroy(Object** location) { |
} |
-void GlobalHandles::MakeWeak(Object** location, |
- void* parameter, |
- WeakCallback weak_callback) { |
- Node::FromLocation(location)->MakeWeak(parameter, weak_callback); |
+void GlobalHandles::MakeWeak(Object** location, void* parameter, |
+ WeakCallback weak_callback, PhantomState phantom) { |
+ Node::FromLocation(location) |
+ ->MakeWeak(parameter, weak_callback, phantom == Phantom); |
} |
@@ -514,7 +538,15 @@ bool GlobalHandles::IsWeak(Object** location) { |
void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
for (NodeIterator it(this); !it.done(); it.Advance()) { |
- if (it.node()->IsWeakRetainer()) v->VisitPointer(it.node()->location()); |
+ Node* node = it.node(); |
+ if (node->IsWeakRetainer()) { |
+ if (node->state() == Node::PENDING && |
+ node->is_zapped_during_weak_callback()) { |
+ *(node->location()) = Smi::FromInt(kPhantomReferenceZap); |
+ } else { |
+ v->VisitPointer(node->location()); |
+ } |
+ } |
} |
} |
@@ -559,7 +591,11 @@ void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
DCHECK(node->is_in_new_space_list()); |
if ((node->is_independent() || node->is_partially_dependent()) && |
node->IsWeakRetainer()) { |
- v->VisitPointer(node->location()); |
+ if (node->is_zapped_during_weak_callback()) { |
+ *(node->location()) = Smi::FromInt(kPhantomReferenceZap); |
+ } else { |
+ v->VisitPointer(node->location()); |
+ } |
} |
} |
} |