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.h"
32#include "../include/v8-profiler.h"
33
34#include "handles.h"
35#include "list.h"
36#include "v8utils.h"
37
38namespace v8 {
39namespace internal {
40
41class GCTracer;
42class HeapStats;
43class ObjectVisitor;
44
45// Structure for tracking global handles.
46// A single list keeps all the allocated global handles.
47// Destroyed handles stay in the list but is added to the free list.
48// At GC the destroyed global handles are removed from the free list
49// and deallocated.
50
51// Data structures for tracking object groups and implicit references.
52
53// An object group is treated like a single JS object: if one of object in
54// the group is alive, all objects in the same group are considered alive.
55// An object group is used to simulate object relationship in a DOM tree.
56
57// An implicit references group consists of two parts: a parent object and a
58// list of children objects.  If the parent is alive, all the children are alive
59// too.
60
61struct ObjectGroup {
62  explicit ObjectGroup(size_t length)
63      : info(NULL), length(length) {
64    ASSERT(length > 0);
65    objects = new Object**[length];
66  }
67  ~ObjectGroup();
68
69  v8::RetainedObjectInfo* info;
70  Object*** objects;
71  size_t length;
72};
73
74
75struct ImplicitRefGroup {
76  ImplicitRefGroup(HeapObject** parent, size_t length)
77      : parent(parent), length(length) {
78    ASSERT(length > 0);
79    children = new Object**[length];
80  }
81  ~ImplicitRefGroup();
82
83  HeapObject** parent;
84  Object*** children;
85  size_t length;
86};
87
88
89// For internal bookkeeping.
90struct ObjectGroupConnection {
91  ObjectGroupConnection(UniqueId id, Object** object)
92      : id(id), object(object) {}
93
94  bool operator==(const ObjectGroupConnection& other) const {
95    return id == other.id;
96  }
97
98  bool operator<(const ObjectGroupConnection& other) const {
99    return id < other.id;
100  }
101
102  UniqueId id;
103  Object** object;
104};
105
106
107struct ObjectGroupRetainerInfo {
108  ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info)
109      : id(id), info(info) {}
110
111  bool operator==(const ObjectGroupRetainerInfo& other) const {
112    return id == other.id;
113  }
114
115  bool operator<(const ObjectGroupRetainerInfo& other) const {
116    return id < other.id;
117  }
118
119  UniqueId id;
120  RetainedObjectInfo* info;
121};
122
123
124class GlobalHandles {
125 public:
126  ~GlobalHandles();
127
128  // Creates a new global handle that is alive until Destroy is called.
129  Handle<Object> Create(Object* value);
130
131  // Copy a global handle
132  static Handle<Object> CopyGlobal(Object** location);
133
134  // Destroy a global handle.
135  static void Destroy(Object** location);
136
137  typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
138  typedef WeakReferenceCallbacks<v8::Value, void>::Revivable RevivableCallback;
139
140  // Make the global handle weak and set the callback parameter for the
141  // handle.  When the garbage collector recognizes that only weak global
142  // handles point to an object the handles are cleared and the callback
143  // function is invoked (for each handle) with the handle and corresponding
144  // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
145  // reason is that Smi::FromInt(0) does not change during garage collection.
146  static void MakeWeak(Object** location,
147                       void* parameter,
148                       WeakCallback weak_callback,
149                       RevivableCallback revivable_callback);
150
151  static inline void MakeWeak(Object** location,
152                              void* parameter,
153                              RevivableCallback revivable_callback) {
154    MakeWeak(location, parameter, NULL, revivable_callback);
155  }
156
157  void RecordStats(HeapStats* stats);
158
159  // Returns the current number of weak handles.
160  int NumberOfWeakHandles();
161
162  // Returns the current number of weak handles to global objects.
163  // These handles are also included in NumberOfWeakHandles().
164  int NumberOfGlobalObjectWeakHandles();
165
166  // Returns the current number of handles to global objects.
167  int global_handles_count() const {
168    return number_of_global_handles_;
169  }
170
171  // Clear the weakness of a global handle.
172  static void ClearWeakness(Object** location);
173
174  // Clear the weakness of a global handle.
175  static void MarkIndependent(Object** location);
176
177  // Mark the reference to this object externaly unreachable.
178  static void MarkPartiallyDependent(Object** location);
179
180  static bool IsIndependent(Object** location);
181
182  // Tells whether global handle is near death.
183  static bool IsNearDeath(Object** location);
184
185  // Tells whether global handle is weak.
186  static bool IsWeak(Object** location);
187
188  // Process pending weak handles.
189  // Returns true if next major GC is likely to collect more garbage.
190  bool PostGarbageCollectionProcessing(GarbageCollector collector,
191                                       GCTracer* tracer);
192
193  // Iterates over all strong handles.
194  void IterateStrongRoots(ObjectVisitor* v);
195
196  // Iterates over all handles.
197  void IterateAllRoots(ObjectVisitor* v);
198
199  // Iterates over all handles that have embedder-assigned class ID.
200  void IterateAllRootsWithClassIds(ObjectVisitor* v);
201
202  // Iterates over all handles in the new space that have embedder-assigned
203  // class ID.
204  void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
205
206  // Iterates over all weak roots in heap.
207  void IterateWeakRoots(ObjectVisitor* v);
208
209  // Find all weak handles satisfying the callback predicate, mark
210  // them as pending.
211  void IdentifyWeakHandles(WeakSlotCallback f);
212
213  // NOTE: Three ...NewSpace... functions below are used during
214  // scavenge collections and iterate over sets of handles that are
215  // guaranteed to contain all handles holding new space objects (but
216  // may also include old space objects).
217
218  // Iterates over strong and dependent handles. See the node above.
219  void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
220
221  // Finds weak independent or partially independent handles satisfying
222  // the callback predicate and marks them as pending. See the note above.
223  void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
224
225  // Iterates over weak independent or partially independent handles.
226  // See the note above.
227  void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
228
229  // Iterate over objects in object groups that have at least one object
230  // which requires visiting. The callback has to return true if objects
231  // can be skipped and false otherwise.
232  bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
233
234  // Add an object group.
235  // Should be only used in GC callback function before a collection.
236  // All groups are destroyed after a garbage collection.
237  void AddObjectGroup(Object*** handles,
238                      size_t length,
239                      v8::RetainedObjectInfo* info);
240
241  // Associates handle with the object group represented by id.
242  // Should be only used in GC callback function before a collection.
243  // All groups are destroyed after a garbage collection.
244  void SetObjectGroupId(Object** handle, UniqueId id);
245
246  // Set RetainedObjectInfo for an object group. Should not be called more than
247  // once for a group. Should not be called for a group which contains no
248  // handles.
249  void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
250
251  // Add an implicit references' group.
252  // Should be only used in GC callback function before a collection.
253  // All groups are destroyed after a mark-compact collection.
254  void AddImplicitReferences(HeapObject** parent,
255                             Object*** children,
256                             size_t length);
257
258  // Adds an implicit reference from a group to an object. Should be only used
259  // in GC callback function before a collection. All implicit references are
260  // destroyed after a mark-compact collection.
261  void SetReferenceFromGroup(UniqueId id, Object** child);
262
263  // Adds an implicit reference from a parent object to a child object. Should
264  // be only used in GC callback function before a collection. All implicit
265  // references are destroyed after a mark-compact collection.
266  void SetReference(HeapObject** parent, Object** child);
267
268  List<ObjectGroup*>* object_groups() {
269    ComputeObjectGroupsAndImplicitReferences();
270    return &object_groups_;
271  }
272
273  List<ImplicitRefGroup*>* implicit_ref_groups() {
274    ComputeObjectGroupsAndImplicitReferences();
275    return &implicit_ref_groups_;
276  }
277
278  // Remove bags, this should only happen after GC.
279  void RemoveObjectGroups();
280  void RemoveImplicitRefGroups();
281
282  // Tear down the global handle structure.
283  void TearDown();
284
285  Isolate* isolate() { return isolate_; }
286
287#ifdef DEBUG
288  void PrintStats();
289  void Print();
290#endif
291
292 private:
293  explicit GlobalHandles(Isolate* isolate);
294
295  // Migrates data from the internal representation (object_group_connections_,
296  // retainer_infos_ and implicit_ref_connections_) to the public and more
297  // efficient representation (object_groups_ and implicit_ref_groups_).
298  void ComputeObjectGroupsAndImplicitReferences();
299
300  // v8::internal::List is inefficient even for small number of elements, if we
301  // don't assign any initial capacity.
302  static const int kObjectGroupConnectionsCapacity = 20;
303
304  // Internal node structures.
305  class Node;
306  class NodeBlock;
307  class NodeIterator;
308
309  Isolate* isolate_;
310
311  // Field always containing the number of handles to global objects.
312  int number_of_global_handles_;
313
314  // List of all allocated node blocks.
315  NodeBlock* first_block_;
316
317  // List of node blocks with used nodes.
318  NodeBlock* first_used_block_;
319
320  // Free list of nodes.
321  Node* first_free_;
322
323  // Contains all nodes holding new space objects. Note: when the list
324  // is accessed, some of the objects may have been promoted already.
325  List<Node*> new_space_nodes_;
326
327  int post_gc_processing_count_;
328
329  // Object groups and implicit references, public and more efficient
330  // representation.
331  List<ObjectGroup*> object_groups_;
332  List<ImplicitRefGroup*> implicit_ref_groups_;
333
334  // Object groups and implicit references, temporary representation while
335  // constructing the groups.
336  List<ObjectGroupConnection> object_group_connections_;
337  List<ObjectGroupRetainerInfo> retainer_infos_;
338  List<ObjectGroupConnection> implicit_ref_connections_;
339
340  friend class Isolate;
341
342  DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
343};
344
345
346class EternalHandles {
347 public:
348  enum SingletonHandle {
349    I18N_TEMPLATE_ONE,
350    I18N_TEMPLATE_TWO,
351
352    NUMBER_OF_SINGLETON_HANDLES
353  };
354
355  EternalHandles();
356  ~EternalHandles();
357
358  int NumberOfHandles() { return size_; }
359
360  // Create an EternalHandle, overwriting the index.
361  void Create(Isolate* isolate, Object* object, int* index);
362
363  // Grab the handle for an existing EternalHandle.
364  inline Handle<Object> Get(int index) {
365    return Handle<Object>(GetLocation(index));
366  }
367
368  // Grab the handle for an existing SingletonHandle.
369  inline Handle<Object> GetSingleton(SingletonHandle singleton) {
370    ASSERT(Exists(singleton));
371    return Get(singleton_handles_[singleton]);
372  }
373
374  // Checks whether a SingletonHandle has been assigned.
375  inline bool Exists(SingletonHandle singleton) {
376    return singleton_handles_[singleton] != kInvalidIndex;
377  }
378
379  // Assign a SingletonHandle to an empty slot and returns the handle.
380  Handle<Object> CreateSingleton(Isolate* isolate,
381                                 Object* object,
382                                 SingletonHandle singleton) {
383    Create(isolate, object, &singleton_handles_[singleton]);
384    return Get(singleton_handles_[singleton]);
385  }
386
387  // Iterates over all handles.
388  void IterateAllRoots(ObjectVisitor* visitor);
389  // Iterates over all handles which might be in new space.
390  void IterateNewSpaceRoots(ObjectVisitor* visitor);
391  // Rebuilds new space list.
392  void PostGarbageCollectionProcessing(Heap* heap);
393
394 private:
395  static const int kInvalidIndex = -1;
396  static const int kShift = 8;
397  static const int kSize = 1 << kShift;
398  static const int kMask = 0xff;
399
400  // Gets the slot for an index
401  inline Object** GetLocation(int index) {
402    ASSERT(index >= 0 && index < size_);
403    return &blocks_[index >> kShift][index & kMask];
404  }
405
406  int size_;
407  List<Object**> blocks_;
408  List<int> new_space_indices_;
409  int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
410
411  DISALLOW_COPY_AND_ASSIGN(EternalHandles);
412};
413
414
415} }  // namespace v8::internal
416
417#endif  // V8_GLOBAL_HANDLES_H_
418