Chromium Code Reviews| Index: src/global-handles.cc |
| diff --git a/src/global-handles.cc b/src/global-handles.cc |
| index 3f4e3bea59d5fb8d96e9435d3dbb0f6932ffd532..609dc6efa306ce6673443ba0f56e0eb90fc31cb2 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); |
| } |
| @@ -161,6 +163,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; |
| @@ -195,8 +204,9 @@ 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; } |
| + WeakenedReferenceCallback new_callback() { return callback_.new_callback; } |
| // Callback parameter accessors. |
| void set_parameter(void* parameter) { |
| @@ -230,7 +240,24 @@ class GlobalHandles::Node { |
| } |
| set_state(WEAK); |
| set_parameter(parameter); |
| - callback_ = callback; |
| + set_is_new_callback(false); |
| + callback_.old_callback = callback; |
| + } |
| + |
| + void MakeWeak(GlobalHandles* global_handles, |
| + void* parameter, |
| + WeakenedReferenceCallback callback) { |
| + ASSERT(state() != FREE); |
| + if (!IsWeakRetainer()) { |
| + global_handles->number_of_weak_handles_++; |
| + if (object_->IsJSGlobalObject()) { |
| + global_handles->number_of_global_object_weak_handles_++; |
| + } |
| + } |
| + set_state(WEAK); |
| + set_parameter(parameter); |
| + set_is_new_callback(true); |
| + callback_.new_callback = callback; |
| } |
| void ClearWeakness(GlobalHandles* global_handles) { |
| @@ -248,8 +275,7 @@ class GlobalHandles::Node { |
| bool PostGarbageCollectionProcessing(Isolate* isolate, |
| GlobalHandles* global_handles) { |
| if (state() != Node::PENDING) return false; |
| - WeakReferenceCallback func = callback(); |
| - if (func == NULL) { |
| + if (new_callback() == NULL) { |
|
Sven Panne
2013/01/18 08:08:12
This is a hack and works only because we don't act
haraken
2013/01/22 00:27:37
Done.
|
| Release(global_handles); |
| return false; |
| } |
| @@ -267,7 +293,13 @@ class GlobalHandles::Node { |
| ExternalTwoByteString::cast(object_)->resource() != NULL); |
| // Leaving V8. |
| VMState state(isolate, EXTERNAL); |
| - func(object, par); |
| + if (is_new_callback()) { |
| + WeakenedReferenceCallback 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. |
| @@ -299,11 +331,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; |
| + WeakenedReferenceCallback new_callback; |
| + } callback_; |
| // Provided data for callback. In FREE state, this is used for |
| // the free list link. |
| @@ -478,6 +514,13 @@ void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| } |
| +void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| + WeakenedReferenceCallback callback) { |
| + ASSERT(callback != NULL); |
| + Node::FromLocation(location)->MakeWeak(this, parameter, callback); |
| +} |
| + |
| + |
| void GlobalHandles::ClearWeakness(Object** location) { |
| Node::FromLocation(location)->ClearWeakness(this); |
| } |
| @@ -523,16 +566,6 @@ void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
| } |
| -void GlobalHandles::IterateWeakRoots(WeakReferenceGuest f, |
| - WeakReferenceCallback callback) { |
| - for (NodeIterator it(this); !it.done(); it.Advance()) { |
| - if (it.node()->IsWeak() && it.node()->callback() == callback) { |
| - f(it.node()->object(), it.node()->parameter()); |
| - } |
| - } |
| -} |
| - |
| - |
| void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
| for (NodeIterator it(this); !it.done(); it.Advance()) { |
| if (it.node()->IsWeak() && f(it.node()->location())) { |