Chromium Code Reviews| Index: src/global-handles.cc |
| diff --git a/src/global-handles.cc b/src/global-handles.cc |
| index e51c4aadf13d68bd581064f33628caf8bbf588d6..5ab9acb3c6db551fd081e361222e042a95b3de33 100644 |
| --- a/src/global-handles.cc |
| +++ b/src/global-handles.cc |
| @@ -39,6 +39,7 @@ class GlobalHandles::Node : public Malloced { |
| void Initialize(Object* object) { |
| // Set the initial value of the handle. |
| object_ = object; |
| + really_weak_ = false; |
| state_ = NORMAL; |
| parameter_or_next_free_.parameter = NULL; |
| callback_ = NULL; |
| @@ -63,9 +64,6 @@ class GlobalHandles::Node : public Malloced { |
| void Destroy() { |
| if (state_ == WEAK || IsNearDeath()) { |
| GlobalHandles::number_of_weak_handles_--; |
| - if (object_->IsJSGlobalObject()) { |
| - GlobalHandles::number_of_global_object_weak_handles_--; |
| - } |
| } |
| state_ = DESTROYED; |
| } |
| @@ -95,15 +93,14 @@ class GlobalHandles::Node : public Malloced { |
| Handle<Object> handle() { return Handle<Object>(&object_); } |
| // Make this handle weak. |
| - void MakeWeak(void* parameter, WeakReferenceCallback callback) { |
| + void MakeWeak(void* parameter, WeakReferenceCallback callback, |
|
Christian Plesner Hansen
2009/10/06 13:47:21
The 'callback' parameter should be moved to the ne
|
| + bool really_weak) { |
| LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location())); |
| ASSERT(state_ != DESTROYED); |
| if (state_ != WEAK && !IsNearDeath()) { |
| GlobalHandles::number_of_weak_handles_++; |
| - if (object_->IsJSGlobalObject()) { |
| - GlobalHandles::number_of_global_object_weak_handles_++; |
| - } |
| } |
| + really_weak_ = really_weak; |
| state_ = WEAK; |
| set_parameter(parameter); |
| callback_ = callback; |
| @@ -113,11 +110,12 @@ class GlobalHandles::Node : public Malloced { |
| LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location())); |
| ASSERT(state_ != DESTROYED); |
| if (state_ == WEAK || IsNearDeath()) { |
| + // Can't clear weakness of near death really weak handle because |
| + // the object may have been collected already. |
| + ASSERT(!IsNearDeath() || !really_weak_); |
|
Christian Plesner Hansen
2009/10/06 13:47:21
Are we sure this can't happen? Wouldn't it be saf
|
| GlobalHandles::number_of_weak_handles_--; |
| - if (object_->IsJSGlobalObject()) { |
| - GlobalHandles::number_of_global_object_weak_handles_--; |
| - } |
| } |
| + really_weak_ = false; |
| state_ = NORMAL; |
| set_parameter(NULL); |
| } |
| @@ -131,6 +129,10 @@ class GlobalHandles::Node : public Malloced { |
| return state_ == WEAK; |
| } |
| + bool IsReallyWeak() { |
| + return really_weak_; |
| + } |
| + |
| // Returns the id for this weak handle. |
| void set_parameter(void* parameter) { |
| ASSERT(state_ != DESTROYED); |
| @@ -171,6 +173,8 @@ class GlobalHandles::Node : public Malloced { |
| // Place the handle address first to avoid offset computation. |
| Object* object_; // Storage for object pointer. |
| + bool really_weak_ : 1; |
| + |
| // Transition diagram: |
| // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } |
| enum State { |
| @@ -180,7 +184,7 @@ class GlobalHandles::Node : public Malloced { |
| NEAR_DEATH, // Callback has informed the handle is near death. |
| DESTROYED |
| }; |
| - State state_; |
| + State state_ : 3; |
| private: |
| // Handle specific callback. |
| @@ -232,7 +236,14 @@ void GlobalHandles::Destroy(Object** location) { |
| void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| WeakReferenceCallback callback) { |
| ASSERT(callback != NULL); |
| - Node::FromLocation(location)->MakeWeak(parameter, callback); |
| + Node::FromLocation(location)->MakeWeak(parameter, callback, false); |
| +} |
| + |
| + |
| +void GlobalHandles::MakeReallyWeak(Object** location, void* parameter, |
| + WeakReferenceCallback callback) { |
| + ASSERT(callback != NULL); |
| + Node::FromLocation(location)->MakeWeak(parameter, callback, true); |
| } |
| @@ -251,13 +262,19 @@ bool GlobalHandles::IsWeak(Object** location) { |
| } |
| +bool GlobalHandles::IsReallyWeak(Object** location) { |
| + return Node::FromLocation(location)->IsReallyWeak(); |
| +} |
| + |
| + |
| void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
| // Traversal of GC roots in the global handle list that are marked as |
| // WEAK or PENDING. |
| for (Node* current = head_; current != NULL; current = current->next()) { |
| - if (current->state_ == Node::WEAK |
| - || current->state_ == Node::PENDING |
| - || current->state_ == Node::NEAR_DEATH) { |
| + if (current->state_ == Node::WEAK || |
| + (!current->really_weak_ && |
| + (current->state_ == Node::PENDING || |
| + current->state_ == Node::NEAR_DEATH))) { |
| v->VisitPointer(¤t->object_); |
| } |
| } |
| @@ -310,7 +327,7 @@ void GlobalHandles::PostGarbageCollectionProcessing() { |
| void GlobalHandles::IterateRoots(ObjectVisitor* v) { |
| - // Traversal of global handles marked as NORMAL or NEAR_DEATH. |
| + // Traversal of global handles marked as NORMAL. |
| for (Node* current = head_; current != NULL; current = current->next()) { |
| if (current->state_ == Node::NORMAL) { |
| v->VisitPointer(¤t->object_); |
| @@ -333,7 +350,6 @@ void GlobalHandles::TearDown() { |
| int GlobalHandles::number_of_weak_handles_ = 0; |
| -int GlobalHandles::number_of_global_object_weak_handles_ = 0; |
| GlobalHandles::Node* GlobalHandles::head_ = NULL; |
| GlobalHandles::Node* GlobalHandles::first_free_ = NULL; |
| @@ -380,6 +396,7 @@ List<ObjectGroup*>* GlobalHandles::ObjectGroups() { |
| return &groups; |
| } |
| + |
| void GlobalHandles::AddGroup(Object*** handles, size_t length) { |
| ObjectGroup* new_entry = new ObjectGroup(length); |
| for (size_t i = 0; i < length; ++i) |
| @@ -390,7 +407,7 @@ void GlobalHandles::AddGroup(Object*** handles, size_t length) { |
| void GlobalHandles::RemoveObjectGroups() { |
| List<ObjectGroup*>* object_groups = ObjectGroups(); |
| - for (int i = 0; i< object_groups->length(); i++) { |
| + for (int i = 0; i < object_groups->length(); ++i) { |
|
Christian Plesner Hansen
2009/10/06 13:47:21
Changing from i++ to ++i shouldn't make any differ
|
| delete object_groups->at(i); |
| } |
| object_groups->Clear(); |