1// Copyright 2011 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 "../include/v8-profiler.h"
32
33#include "list.h"
34
35namespace v8 {
36namespace internal {
37
38// Structure for tracking global handles.
39// A single list keeps all the allocated global handles.
40// Destroyed handles stay in the list but is added to the free list.
41// At GC the destroyed global handles are removed from the free list
42// and deallocated.
43
44// An object group is treated like a single JS object: if one of object in
45// the group is alive, all objects in the same group are considered alive.
46// An object group is used to simulate object relationship in a DOM tree.
47class ObjectGroup {
48 public:
49  static ObjectGroup* New(Object*** handles,
50                          size_t length,
51                          v8::RetainedObjectInfo* info) {
52    ASSERT(length > 0);
53    ObjectGroup* group = reinterpret_cast<ObjectGroup*>(
54        malloc(OFFSET_OF(ObjectGroup, objects_[length])));
55    group->length_ = length;
56    group->info_ = info;
57    CopyWords(group->objects_, handles, static_cast<int>(length));
58    return group;
59  }
60
61  void Dispose() {
62    if (info_ != NULL) info_->Dispose();
63    free(this);
64  }
65
66  size_t length_;
67  v8::RetainedObjectInfo* info_;
68  Object** objects_[1];  // Variable sized array.
69
70 private:
71  void* operator new(size_t size);
72  void operator delete(void* p);
73  ~ObjectGroup();
74  DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectGroup);
75};
76
77
78// An implicit references group consists of two parts: a parent object and
79// a list of children objects.  If the parent is alive, all the children
80// are alive too.
81class ImplicitRefGroup {
82 public:
83  static ImplicitRefGroup* New(HeapObject** parent,
84                               Object*** children,
85                               size_t length) {
86    ASSERT(length > 0);
87    ImplicitRefGroup* group = reinterpret_cast<ImplicitRefGroup*>(
88        malloc(OFFSET_OF(ImplicitRefGroup, children_[length])));
89    group->parent_ = parent;
90    group->length_ = length;
91    CopyWords(group->children_, children, static_cast<int>(length));
92    return group;
93  }
94
95  void Dispose() {
96    free(this);
97  }
98
99  HeapObject** parent_;
100  size_t length_;
101  Object** children_[1];  // Variable sized array.
102
103 private:
104  void* operator new(size_t size);
105  void operator delete(void* p);
106  ~ImplicitRefGroup();
107  DISALLOW_IMPLICIT_CONSTRUCTORS(ImplicitRefGroup);
108};
109
110
111typedef void (*WeakReferenceGuest)(Object* object, void* parameter);
112
113class GlobalHandles {
114 public:
115  ~GlobalHandles();
116
117  // Creates a new global handle that is alive until Destroy is called.
118  Handle<Object> Create(Object* value);
119
120  // Destroy a global handle.
121  void Destroy(Object** location);
122
123  // Make the global handle weak and set the callback parameter for the
124  // handle.  When the garbage collector recognizes that only weak global
125  // handles point to an object the handles are cleared and the callback
126  // function is invoked (for each handle) with the handle and corresponding
127  // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
128  // reason is that Smi::FromInt(0) does not change during garage collection.
129  void MakeWeak(Object** location,
130                void* parameter,
131                WeakReferenceCallback callback);
132
133  static void SetWrapperClassId(Object** location, uint16_t class_id);
134
135  // Returns the current number of weak handles.
136  int NumberOfWeakHandles() { return number_of_weak_handles_; }
137
138  void RecordStats(HeapStats* stats);
139
140  // Returns the current number of weak handles to global objects.
141  // These handles are also included in NumberOfWeakHandles().
142  int NumberOfGlobalObjectWeakHandles() {
143    return number_of_global_object_weak_handles_;
144  }
145
146  // Returns the current number of handles to global objects.
147  int NumberOfGlobalHandles() {
148    return number_of_global_handles_;
149  }
150
151  // Clear the weakness of a global handle.
152  void ClearWeakness(Object** location);
153
154  // Clear the weakness of a global handle.
155  void MarkIndependent(Object** location);
156
157  // Tells whether global handle is near death.
158  static bool IsNearDeath(Object** location);
159
160  // Tells whether global handle is weak.
161  static bool IsWeak(Object** location);
162
163  // Process pending weak handles.
164  // Returns true if next major GC is likely to collect more garbage.
165  bool PostGarbageCollectionProcessing(GarbageCollector collector);
166
167  // Iterates over all strong handles.
168  void IterateStrongRoots(ObjectVisitor* v);
169
170  // Iterates over all handles.
171  void IterateAllRoots(ObjectVisitor* v);
172
173  // Iterates over all handles that have embedder-assigned class ID.
174  void IterateAllRootsWithClassIds(ObjectVisitor* v);
175
176  // Iterates over all weak roots in heap.
177  void IterateWeakRoots(ObjectVisitor* v);
178
179  // Iterates over weak roots that are bound to a given callback.
180  void IterateWeakRoots(WeakReferenceGuest f,
181                        WeakReferenceCallback callback);
182
183  // Find all weak handles satisfying the callback predicate, mark
184  // them as pending.
185  void IdentifyWeakHandles(WeakSlotCallback f);
186
187  // NOTE: Three ...NewSpace... functions below are used during
188  // scavenge collections and iterate over sets of handles that are
189  // guaranteed to contain all handles holding new space objects (but
190  // may also include old space objects).
191
192  // Iterates over strong and dependent handles. See the node above.
193  void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
194
195  // Finds weak independent handles satisfying the callback predicate
196  // and marks them as pending. See the note above.
197  void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
198
199  // Iterates over weak independent handles. See the note above.
200  void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
201
202  // Add an object group.
203  // Should be only used in GC callback function before a collection.
204  // All groups are destroyed after a mark-compact collection.
205  void AddObjectGroup(Object*** handles,
206                      size_t length,
207                      v8::RetainedObjectInfo* info);
208
209  // Add an implicit references' group.
210  // Should be only used in GC callback function before a collection.
211  // All groups are destroyed after a mark-compact collection.
212  void AddImplicitReferences(HeapObject** parent,
213                             Object*** children,
214                             size_t length);
215
216  // Returns the object groups.
217  List<ObjectGroup*>* object_groups() { return &object_groups_; }
218
219  // Returns the implicit references' groups.
220  List<ImplicitRefGroup*>* implicit_ref_groups() {
221    return &implicit_ref_groups_;
222  }
223
224  // Remove bags, this should only happen after GC.
225  void RemoveObjectGroups();
226  void RemoveImplicitRefGroups();
227
228  // Tear down the global handle structure.
229  void TearDown();
230
231  Isolate* isolate() { return isolate_; }
232
233#ifdef DEBUG
234  void PrintStats();
235  void Print();
236#endif
237
238 private:
239  explicit GlobalHandles(Isolate* isolate);
240
241  // Internal node structures.
242  class Node;
243  class NodeBlock;
244  class NodeIterator;
245
246  Isolate* isolate_;
247
248  // Field always containing the number of weak and near-death handles.
249  int number_of_weak_handles_;
250
251  // Field always containing the number of weak and near-death handles
252  // to global objects.  These objects are also included in
253  // number_of_weak_handles_.
254  int number_of_global_object_weak_handles_;
255
256  // Field always containing the number of handles to global objects.
257  int number_of_global_handles_;
258
259  // List of all allocated node blocks.
260  NodeBlock* first_block_;
261
262  // List of node blocks with used nodes.
263  NodeBlock* first_used_block_;
264
265  // Free list of nodes.
266  Node* first_free_;
267
268  // Contains all nodes holding new space objects. Note: when the list
269  // is accessed, some of the objects may have been promoted already.
270  List<Node*> new_space_nodes_;
271
272  int post_gc_processing_count_;
273
274  List<ObjectGroup*> object_groups_;
275  List<ImplicitRefGroup*> implicit_ref_groups_;
276
277  friend class Isolate;
278
279  DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
280};
281
282
283} }  // namespace v8::internal
284
285#endif  // V8_GLOBAL_HANDLES_H_
286