1// Copyright 2007-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_GLOBAL_HANDLES_H_
29#define V8_GLOBAL_HANDLES_H_
30
31#include "list-inl.h"
32
33namespace v8 {
34namespace internal {
35
36// Structure for tracking global handles.
37// A single list keeps all the allocated global handles.
38// Destroyed handles stay in the list but is added to the free list.
39// At GC the destroyed global handles are removed from the free list
40// and deallocated.
41
42// Callback function on handling weak global handles.
43// typedef bool (*WeakSlotCallback)(Object** pointer);
44
45// An object group is treated like a single JS object: if one of object in
46// the group is alive, all objects in the same group are considered alive.
47// An object group is used to simulate object relationship in a DOM tree.
48class ObjectGroup : public Malloced {
49 public:
50  ObjectGroup() : objects_(4) {}
51  explicit ObjectGroup(size_t capacity)
52      : objects_(static_cast<int>(capacity)) { }
53
54  List<Object**> objects_;
55};
56
57
58typedef void (*WeakReferenceGuest)(Object* object, void* parameter);
59
60class GlobalHandles : public AllStatic {
61 public:
62  // Creates a new global handle that is alive until Destroy is called.
63  static Handle<Object> Create(Object* value);
64
65  // Destroy a global handle.
66  static void Destroy(Object** location);
67
68  // Make the global handle weak and set the callback parameter for the
69  // handle.  When the garbage collector recognizes that only weak global
70  // handles point to an object the handles are cleared and the callback
71  // function is invoked (for each handle) with the handle and corresponding
72  // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
73  // reason is that Smi::FromInt(0) does not change during garage collection.
74  static void MakeWeak(Object** location,
75                       void* parameter,
76                       WeakReferenceCallback callback);
77
78  // Returns the current number of weak handles.
79  static int NumberOfWeakHandles() { return number_of_weak_handles_; }
80
81  static void RecordStats(HeapStats* stats);
82
83  // Returns the current number of weak handles to global objects.
84  // These handles are also included in NumberOfWeakHandles().
85  static int NumberOfGlobalObjectWeakHandles() {
86    return number_of_global_object_weak_handles_;
87  }
88
89  // Clear the weakness of a global handle.
90  static void ClearWeakness(Object** location);
91
92  // Tells whether global handle is near death.
93  static bool IsNearDeath(Object** location);
94
95  // Tells whether global handle is weak.
96  static bool IsWeak(Object** location);
97
98  // Process pending weak handles.
99  static void PostGarbageCollectionProcessing();
100
101  // Iterates over all strong handles.
102  static void IterateStrongRoots(ObjectVisitor* v);
103
104  // Iterates over all handles.
105  static void IterateAllRoots(ObjectVisitor* v);
106
107  // Iterates over all weak roots in heap.
108  static void IterateWeakRoots(ObjectVisitor* v);
109
110  // Iterates over weak roots that are bound to a given callback.
111  static void IterateWeakRoots(WeakReferenceGuest f,
112                               WeakReferenceCallback callback);
113
114  // Find all weak handles satisfying the callback predicate, mark
115  // them as pending.
116  static void IdentifyWeakHandles(WeakSlotCallback f);
117
118  // Add an object group.
119  // Should only used in GC callback function before a collection.
120  // All groups are destroyed after a mark-compact collection.
121  static void AddGroup(Object*** handles, size_t length);
122
123  // Returns the object groups.
124  static List<ObjectGroup*>* ObjectGroups();
125
126  // Remove bags, this should only happen after GC.
127  static void RemoveObjectGroups();
128
129  // Tear down the global handle structure.
130  static void TearDown();
131
132#ifdef DEBUG
133  static void PrintStats();
134  static void Print();
135#endif
136  class Pool;
137 private:
138  // Internal node structure, one for each global handle.
139  class Node;
140
141  // Field always containing the number of weak and near-death handles.
142  static int number_of_weak_handles_;
143
144  // Field always containing the number of weak and near-death handles
145  // to global objects.  These objects are also included in
146  // number_of_weak_handles_.
147  static int number_of_global_object_weak_handles_;
148
149  // Global handles are kept in a single linked list pointed to by head_.
150  static Node* head_;
151  static Node* head() { return head_; }
152  static void set_head(Node* value) { head_ = value; }
153
154  // Free list for DESTROYED global handles not yet deallocated.
155  static Node* first_free_;
156  static Node* first_free() { return first_free_; }
157  static void set_first_free(Node* value) { first_free_ = value; }
158
159  // List of deallocated nodes.
160  // Deallocated nodes form a prefix of all the nodes and
161  // |first_deallocated| points to last deallocated node before
162  // |head|.  Those deallocated nodes are additionally linked
163  // by |next_free|:
164  //                                    1st deallocated  head
165  //                                           |          |
166  //                                           V          V
167  //    node          node        ...         node       node
168  //      .next      -> .next ->                .next ->
169  //   <- .next_free <- .next_free           <- .next_free
170  static Node* first_deallocated_;
171  static Node* first_deallocated() { return first_deallocated_; }
172  static void set_first_deallocated(Node* value) {
173    first_deallocated_ = value;
174  }
175};
176
177
178} }  // namespace v8::internal
179
180#endif  // V8_GLOBAL_HANDLES_H_
181