| Index: src/global-handles.cc
|
| diff --git a/src/global-handles.cc b/src/global-handles.cc
|
| index 282ca2d5d86a63d86dd00b1eb4b43888c3289e6b..44abef7517b2bc6a0a2f1d276acb50441a9f602c 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);
|
|
|
| @@ -243,10 +252,12 @@ class GlobalHandles::Node {
|
| VMState<EXTERNAL> state(isolate);
|
| HandleScope handle_scope(isolate);
|
| Handle<Object> handle(*object, isolate);
|
| + if (is_zapped_during_weak_callback()) {
|
| + DCHECK(*handle == Smi::FromInt(kPhantomReferenceZap));
|
| + }
|
| v8::WeakCallbackData<v8::Value, void> data(
|
| - reinterpret_cast<v8::Isolate*>(isolate),
|
| - v8::Utils::ToLocal(handle),
|
| - par);
|
| + reinterpret_cast<v8::Isolate*>(isolate), v8::Utils::ToLocal(handle),
|
| + param);
|
| weak_callback_(data);
|
| }
|
| // Absence of explicit cleanup or revival of weak handle
|
| @@ -277,10 +288,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 +487,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 +526,14 @@ 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());
|
| + if (it.node()->IsWeakRetainer()) {
|
| + if (it.node()->state() == Node::PENDING &&
|
| + it.node()->is_zapped_during_weak_callback()) {
|
| + *(it.node()->location()) = Smi::FromInt(kPhantomReferenceZap);
|
| + } else {
|
| + v->VisitPointer(it.node()->location());
|
| + }
|
| + }
|
| }
|
| }
|
|
|
|
|