Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Unified Diff: src/global-handles.h

Issue 7062004: Move young independent handles to the end of the global handle's list. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/global-handles.cc » ('j') | src/global-handles.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « no previous file | src/global-handles.cc » ('j') | src/global-handles.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698