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); |
} |