Chromium Code Reviews| Index: src/global-handles.h |
| diff --git a/src/global-handles.h b/src/global-handles.h |
| index 3477bcaaa9504d2fd370d6a253487ff32e9581ab..af0e4ea2e871dc02d1ebfc6c0fc1378dcd6c398e 100644 |
| --- a/src/global-handles.h |
| +++ b/src/global-handles.h |
| @@ -229,7 +229,152 @@ class GlobalHandles { |
| explicit GlobalHandles(Isolate* isolate); |
| // Internal node structure, one for each global handle. |
| - class Node; |
| + class Node : public Malloced { |
| + public: |
| + |
| + void Initialize(Object* object) { |
| + // Set the initial value of the handle. |
| + object_ = object; |
| + class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| + independent_ = false; |
| + is_in_independent_tail_ = false; |
| + state_ = NORMAL; |
| + parameter_or_next_free_.parameter = NULL; |
| + callback_ = NULL; |
| + } |
| + |
| + Node() { |
| + state_ = DESTROYED; |
| + // Initialize link structure. |
| + next_ = NULL; |
| + prev_ = NULL; |
| + } |
| + |
| + explicit Node(Object* object) { |
| + Initialize(object); |
| + // Initialize link structure. |
| + next_ = NULL; |
| + prev_ = NULL; |
| + } |
| + |
| + ~Node(); |
| + |
| + void Destroy(GlobalHandles* global_handles) { |
| + if (state_ == WEAK || IsNearDeath()) { |
| + global_handles->number_of_weak_handles_--; |
| + if (object_->IsJSGlobalObject()) { |
| + global_handles->number_of_global_object_weak_handles_--; |
| + } |
| + } |
| + state_ = DESTROYED; |
| + } |
| + |
| + // Accessors for next_. |
| + Node* next() { return next_; } |
| + void set_next(Node* value) { next_ = value; } |
| + Node** next_addr() { return &next_; } |
| + |
| + Node* prev() { return prev_; } |
| + void set_prev(Node* value) { prev_ = value; } |
| + |
| + // Accessors for next free node in the free list. |
| + Node* next_free() { |
| + ASSERT(state_ == DESTROYED); |
| + return parameter_or_next_free_.next_free; |
| + } |
| + void set_next_free(Node* value) { |
| + ASSERT(state_ == DESTROYED); |
| + parameter_or_next_free_.next_free = value; |
| + } |
| + |
| + // Returns a link from the handle. |
| + static Node* FromLocation(Object** location) { |
| + ASSERT(OFFSET_OF(Node, object_) == 0); |
| + return reinterpret_cast<Node*>(location); |
| + } |
| + |
| + // Returns the handle. |
| + Handle<Object> handle() { return Handle<Object>(&object_); } |
| + |
| + // Make this handle weak. |
| + void MakeWeak(GlobalHandles* global_handles, |
| + void* parameter, |
| + WeakReferenceCallback callback); |
| + |
| + void ClearWeakness(GlobalHandles* global_handles); |
| + |
| + void MarkIndependent(GlobalHandles* global_handles); |
| + |
| + bool IsNearDeath() { |
| + // Check for PENDING to ensure correct answer when processing callbacks. |
| + return state_ == PENDING || state_ == NEAR_DEATH; |
| + } |
| + |
| + bool IsWeak() { |
| + return state_ == WEAK; |
| + } |
| + |
| + bool CanBeRetainer() { |
| + return state_ != DESTROYED && state_ != NEAR_DEATH; |
| + } |
| + |
| + void SetWrapperClassId(uint16_t class_id) { |
| + class_id_ = class_id; |
| + } |
| + |
| + // Returns the id for this weak handle. |
| + void set_parameter(void* parameter) { |
| + ASSERT(state_ != DESTROYED); |
| + parameter_or_next_free_.parameter = parameter; |
| + } |
| + void* parameter() { |
| + ASSERT(state_ != DESTROYED); |
| + return parameter_or_next_free_.parameter; |
| + } |
| + |
| + // Returns the callback for this weak handle. |
| + WeakReferenceCallback callback() { return callback_; } |
| + |
| + bool PostGarbageCollectionProcessing(Isolate* isolate, |
| + GlobalHandles* global_handles); |
| + |
| + // Place the handle address first to avoid offset computation. |
| + Object* object_; // Storage for object pointer. |
| + |
| + uint16_t class_id_; |
| + |
| + // Transition diagram: |
| + // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } |
| + enum State { |
| + NORMAL, // Normal global handle. |
| + WEAK, // Flagged as weak but not yet finalized. |
| + PENDING, // Has been recognized as only reachable by weak handles. |
| + NEAR_DEATH, // Callback has informed the handle is near death. |
| + DESTROYED |
| + }; |
| + State state_ : 4; // Need one more bit for MSVC as it treats enums as signed. |
|
antonm
2011/05/23 19:44:19
nit: apparently more than 80 chars (or my browser
|
| + |
| + bool independent_ : 1; |
| + bool is_in_independent_tail_ : 1; |
| + |
| + private: |
| + // Handle specific callback. |
| + WeakReferenceCallback callback_; |
| + // Provided data for callback. In DESTROYED state, this is used for |
| + // the free list link. |
| + union { |
| + void* parameter; |
| + Node* next_free; |
| + } parameter_or_next_free_; |
| + |
| + // Linkage for the list. |
| + Node* next_; |
| + Node* prev_; |
| + |
| + public: |
| + TRACK_MEMORY("GlobalHandles::Node") |
| + }; |
| + |
| Isolate* isolate_; |
| @@ -241,16 +386,46 @@ class GlobalHandles { |
| // number_of_weak_handles_. |
| int number_of_global_object_weak_handles_; |
| - // Global handles are kept in a single linked list pointed to by head_. |
| - Node* head_; |
| - Node* head() { return head_; } |
| - void set_head(Node* value) { head_ = value; } |
| + // Global handles are kept in a single linked list pointed to by |
| + // next field of an achor node. |
| + Node anchor_node_; |
| + |
| + Node* head() { |
| + return anchor_node_.next(); |
| + } |
| + |
| + void set_head(Node* value) { |
|
antonm
2011/05/23 19:44:19
it might be more easier to reason about this code
|
| + anchor_node_.set_next(value); |
| + if (value != NULL) { |
| + value->set_prev(&anchor_node_); |
| + if (young_independent_anchor_ == &anchor_node_ && |
| + !value->independent_) { |
|
antonm
2011/05/23 19:44:19
given that set_head is invoked from ::Create, is i
|
| + young_independent_anchor_ = value; |
| + } |
| + } else { |
| + young_independent_anchor_ = &anchor_node_; |
| + } |
| + } |
| + |
| + // List of independent nodes pointing to young objects. |
| + // This list forms a suffix of the whole list of nodes. |
|
antonm
2011/05/23 19:44:19
in veryfyheap, can we assert this? or overall, do
|
| + Node* young_independent_anchor_; |
| + |
| + Node* FirstYoungIndependent() { |
| + ASSERT(young_independent_anchor_ != NULL); |
| + return young_independent_anchor_->next(); |
| + } |
| // Free list for DESTROYED global handles not yet deallocated. |
| Node* first_free_; |
| Node* first_free() { return first_free_; } |
| void set_first_free(Node* value) { first_free_ = value; } |
| + void UnlinkNode(Node* node); |
| + void LinkAfter(Node* prev, Node* node); |
| + void RemoveFromIndependentTail(Node* node); |
| + |
| + |
|
antonm
2011/05/23 19:44:19
nit: extra blank line?
|
| // List of deallocated nodes. |
| // Deallocated nodes form a prefix of all the nodes and |
| // |first_deallocated| points to last deallocated node before |