| Index: src/global-handles.cc
|
| diff --git a/src/global-handles.cc b/src/global-handles.cc
|
| index 427eae0a9ecdd51c452463cc5f31af2891f49aad..5269ff3736e36d5b3c6f56564295247fc9cc2ad4 100644
|
| --- a/src/global-handles.cc
|
| +++ b/src/global-handles.cc
|
| @@ -78,8 +78,9 @@ class GlobalHandles::Node {
|
| set_independent(false);
|
| set_partially_dependent(false);
|
| set_in_new_space_list(false);
|
| + set_is_new_callback(false);
|
| + callback_.new_callback = NULL;
|
| parameter_or_next_free_.next_free = NULL;
|
| - callback_ = NULL;
|
| }
|
| #endif
|
|
|
| @@ -100,7 +101,8 @@ class GlobalHandles::Node {
|
| set_partially_dependent(false);
|
| set_state(NORMAL);
|
| parameter_or_next_free_.parameter = NULL;
|
| - callback_ = NULL;
|
| + set_is_new_callback(false);
|
| + callback_.new_callback = NULL;
|
| IncreaseBlockUses(global_handles);
|
| }
|
|
|
| @@ -154,6 +156,13 @@ class GlobalHandles::Node {
|
| flags_ = IsInNewSpaceList::update(flags_, v);
|
| }
|
|
|
| + bool is_new_callback() {
|
| + return IsNewCallback::decode(flags_);
|
| + }
|
| + void set_is_new_callback(bool v) {
|
| + flags_ = IsNewCallback::update(flags_, v);
|
| + }
|
| +
|
| bool IsNearDeath() const {
|
| // Check for PENDING to ensure correct answer when processing callbacks.
|
| return state() == PENDING || state() == NEAR_DEATH;
|
| @@ -188,8 +197,10 @@ class GlobalHandles::Node {
|
| }
|
| void clear_partially_dependent() { set_partially_dependent(false); }
|
|
|
| - // Callback accessor.
|
| - WeakReferenceCallback callback() { return callback_; }
|
| + // Callback accessors.
|
| + WeakReferenceCallback old_callback() { return callback_.old_callback; }
|
| + WeakHandleCallback new_callback() { return callback_.new_callback; }
|
| + bool callback_is_set() { return !!callback_.new_callback; }
|
|
|
| // Callback parameter accessors.
|
| void set_parameter(void* parameter) {
|
| @@ -217,7 +228,18 @@ class GlobalHandles::Node {
|
| ASSERT(state() != FREE);
|
| set_state(WEAK);
|
| set_parameter(parameter);
|
| - callback_ = callback;
|
| + set_is_new_callback(false);
|
| + callback_.old_callback = callback;
|
| + }
|
| +
|
| + void MakeWeak(GlobalHandles* global_handles,
|
| + void* parameter,
|
| + WeakHandleCallback callback) {
|
| + ASSERT(state() != FREE);
|
| + set_state(WEAK);
|
| + set_parameter(parameter);
|
| + set_is_new_callback(true);
|
| + callback_.new_callback = callback;
|
| }
|
|
|
| void ClearWeakness(GlobalHandles* global_handles) {
|
| @@ -229,8 +251,7 @@ class GlobalHandles::Node {
|
| bool PostGarbageCollectionProcessing(Isolate* isolate,
|
| GlobalHandles* global_handles) {
|
| if (state() != Node::PENDING) return false;
|
| - WeakReferenceCallback func = callback();
|
| - if (func == NULL) {
|
| + if (!callback_is_set()) {
|
| Release(global_handles);
|
| return false;
|
| }
|
| @@ -248,7 +269,13 @@ class GlobalHandles::Node {
|
| ExternalTwoByteString::cast(object_)->resource() != NULL);
|
| // Leaving V8.
|
| VMState state(isolate, EXTERNAL);
|
| - func(object, par);
|
| + if (is_new_callback()) {
|
| + WeakHandleCallback callback = new_callback();
|
| + callback(reinterpret_cast<v8::Isolate*>(isolate), object, par);
|
| + } else {
|
| + WeakReferenceCallback callback = old_callback();
|
| + callback(object, par);
|
| + }
|
| }
|
| // Absence of explicit cleanup or revival of weak handle
|
| // in most of the cases would lead to memory leak.
|
| @@ -280,11 +307,15 @@ class GlobalHandles::Node {
|
| class IsIndependent: public BitField<bool, 4, 1> {};
|
| class IsPartiallyDependent: public BitField<bool, 5, 1> {};
|
| class IsInNewSpaceList: public BitField<bool, 6, 1> {};
|
| + class IsNewCallback: public BitField<bool, 7, 1> {};
|
|
|
| uint8_t flags_;
|
|
|
| // Handle specific callback.
|
| - WeakReferenceCallback callback_;
|
| + union {
|
| + WeakReferenceCallback old_callback;
|
| + WeakHandleCallback new_callback;
|
| + } callback_;
|
|
|
| // Provided data for callback. In FREE state, this is used for
|
| // the free list link.
|
| @@ -457,6 +488,13 @@ void GlobalHandles::MakeWeak(Object** location, void* parameter,
|
| }
|
|
|
|
|
| +void GlobalHandles::MakeWeak(Object** location, void* parameter,
|
| + WeakHandleCallback callback) {
|
| + ASSERT(callback != NULL);
|
| + Node::FromLocation(location)->MakeWeak(this, parameter, callback);
|
| +}
|
| +
|
| +
|
| void GlobalHandles::ClearWeakness(Object** location) {
|
| Node::FromLocation(location)->ClearWeakness(this);
|
| }
|
|
|