1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_GLOBAL_HANDLES_H_
6 #define V8_GLOBAL_HANDLES_H_
8 #include "include/v8.h"
9 #include "include/v8-profiler.h"
11 #include "src/handles.h"
13 #include "src/utils.h"
21 // Structure for tracking global handles.
22 // A single list keeps all the allocated global handles.
23 // Destroyed handles stay in the list but is added to the free list.
24 // At GC the destroyed global handles are removed from the free list
27 // Data structures for tracking object groups and implicit references.
29 // An object group is treated like a single JS object: if one of object in
30 // the group is alive, all objects in the same group are considered alive.
31 // An object group is used to simulate object relationship in a DOM tree.
33 // An implicit references group consists of two parts: a parent object and a
34 // list of children objects. If the parent is alive, all the children are alive
38 explicit ObjectGroup(size_t length)
39 : info(NULL), length(length) {
41 objects = new Object**[length];
45 v8::RetainedObjectInfo* info;
51 struct ImplicitRefGroup {
52 ImplicitRefGroup(HeapObject** parent, size_t length)
53 : parent(parent), length(length) {
55 children = new Object**[length];
65 // For internal bookkeeping.
66 struct ObjectGroupConnection {
67 ObjectGroupConnection(UniqueId id, Object** object)
68 : id(id), object(object) {}
70 bool operator==(const ObjectGroupConnection& other) const {
71 return id == other.id;
74 bool operator<(const ObjectGroupConnection& other) const {
83 struct ObjectGroupRetainerInfo {
84 ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info)
85 : id(id), info(info) {}
87 bool operator==(const ObjectGroupRetainerInfo& other) const {
88 return id == other.id;
91 bool operator<(const ObjectGroupRetainerInfo& other) const {
96 RetainedObjectInfo* info;
100 class GlobalHandles {
104 // Creates a new global handle that is alive until Destroy is called.
105 Handle<Object> Create(Object* value);
107 // Copy a global handle
108 static Handle<Object> CopyGlobal(Object** location);
110 // Destroy a global handle.
111 static void Destroy(Object** location);
113 typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
115 // Make the global handle weak and set the callback parameter for the
116 // handle. When the garbage collector recognizes that only weak global
117 // handles point to an object the handles are cleared and the callback
118 // function is invoked (for each handle) with the handle and corresponding
119 // parameter as arguments. Note: cleared means set to Smi::FromInt(0). The
120 // reason is that Smi::FromInt(0) does not change during garage collection.
121 static void MakeWeak(Object** location,
123 WeakCallback weak_callback);
125 void RecordStats(HeapStats* stats);
127 // Returns the current number of weak handles.
128 int NumberOfWeakHandles();
130 // Returns the current number of weak handles to global objects.
131 // These handles are also included in NumberOfWeakHandles().
132 int NumberOfGlobalObjectWeakHandles();
134 // Returns the current number of handles to global objects.
135 int global_handles_count() const {
136 return number_of_global_handles_;
139 // Clear the weakness of a global handle.
140 static void* ClearWeakness(Object** location);
142 // Clear the weakness of a global handle.
143 static void MarkIndependent(Object** location);
145 // Mark the reference to this object externaly unreachable.
146 static void MarkPartiallyDependent(Object** location);
148 static bool IsIndependent(Object** location);
150 // Tells whether global handle is near death.
151 static bool IsNearDeath(Object** location);
153 // Tells whether global handle is weak.
154 static bool IsWeak(Object** location);
156 // Process pending weak handles.
157 // Returns the number of freed nodes.
158 int PostGarbageCollectionProcessing(GarbageCollector collector);
160 // Iterates over all strong handles.
161 void IterateStrongRoots(ObjectVisitor* v);
163 // Iterates over all handles.
164 void IterateAllRoots(ObjectVisitor* v);
166 // Iterates over all handles that have embedder-assigned class ID.
167 void IterateAllRootsWithClassIds(ObjectVisitor* v);
169 // Iterates over all handles in the new space that have embedder-assigned
171 void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
173 // Iterates over all weak roots in heap.
174 void IterateWeakRoots(ObjectVisitor* v);
176 // Find all weak handles satisfying the callback predicate, mark
178 void IdentifyWeakHandles(WeakSlotCallback f);
180 // NOTE: Three ...NewSpace... functions below are used during
181 // scavenge collections and iterate over sets of handles that are
182 // guaranteed to contain all handles holding new space objects (but
183 // may also include old space objects).
185 // Iterates over strong and dependent handles. See the node above.
186 void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
188 // Finds weak independent or partially independent handles satisfying
189 // the callback predicate and marks them as pending. See the note above.
190 void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
192 // Iterates over weak independent or partially independent handles.
193 // See the note above.
194 void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
196 // Iterate over objects in object groups that have at least one object
197 // which requires visiting. The callback has to return true if objects
198 // can be skipped and false otherwise.
199 bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
201 // Add an object group.
202 // Should be only used in GC callback function before a collection.
203 // All groups are destroyed after a garbage collection.
204 void AddObjectGroup(Object*** handles,
206 v8::RetainedObjectInfo* info);
208 // Associates handle with the object group represented by id.
209 // Should be only used in GC callback function before a collection.
210 // All groups are destroyed after a garbage collection.
211 void SetObjectGroupId(Object** handle, UniqueId id);
213 // Set RetainedObjectInfo for an object group. Should not be called more than
214 // once for a group. Should not be called for a group which contains no
216 void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
218 // Add an implicit references' group.
219 // Should be only used in GC callback function before a collection.
220 // All groups are destroyed after a mark-compact collection.
221 void AddImplicitReferences(HeapObject** parent,
225 // Adds an implicit reference from a group to an object. Should be only used
226 // in GC callback function before a collection. All implicit references are
227 // destroyed after a mark-compact collection.
228 void SetReferenceFromGroup(UniqueId id, Object** child);
230 // Adds an implicit reference from a parent object to a child object. Should
231 // be only used in GC callback function before a collection. All implicit
232 // references are destroyed after a mark-compact collection.
233 void SetReference(HeapObject** parent, Object** child);
235 List<ObjectGroup*>* object_groups() {
236 ComputeObjectGroupsAndImplicitReferences();
237 return &object_groups_;
240 List<ImplicitRefGroup*>* implicit_ref_groups() {
241 ComputeObjectGroupsAndImplicitReferences();
242 return &implicit_ref_groups_;
245 // Remove bags, this should only happen after GC.
246 void RemoveObjectGroups();
247 void RemoveImplicitRefGroups();
249 // Tear down the global handle structure.
252 Isolate* isolate() { return isolate_; }
260 explicit GlobalHandles(Isolate* isolate);
262 // Migrates data from the internal representation (object_group_connections_,
263 // retainer_infos_ and implicit_ref_connections_) to the public and more
264 // efficient representation (object_groups_ and implicit_ref_groups_).
265 void ComputeObjectGroupsAndImplicitReferences();
267 // v8::internal::List is inefficient even for small number of elements, if we
268 // don't assign any initial capacity.
269 static const int kObjectGroupConnectionsCapacity = 20;
271 // Internal node structures.
278 // Field always containing the number of handles to global objects.
279 int number_of_global_handles_;
281 // List of all allocated node blocks.
282 NodeBlock* first_block_;
284 // List of node blocks with used nodes.
285 NodeBlock* first_used_block_;
287 // Free list of nodes.
290 // Contains all nodes holding new space objects. Note: when the list
291 // is accessed, some of the objects may have been promoted already.
292 List<Node*> new_space_nodes_;
294 int post_gc_processing_count_;
296 // Object groups and implicit references, public and more efficient
298 List<ObjectGroup*> object_groups_;
299 List<ImplicitRefGroup*> implicit_ref_groups_;
301 // Object groups and implicit references, temporary representation while
302 // constructing the groups.
303 List<ObjectGroupConnection> object_group_connections_;
304 List<ObjectGroupRetainerInfo> retainer_infos_;
305 List<ObjectGroupConnection> implicit_ref_connections_;
307 friend class Isolate;
309 DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
313 class EternalHandles {
315 enum SingletonHandle {
320 NUMBER_OF_SINGLETON_HANDLES
326 int NumberOfHandles() { return size_; }
328 // Create an EternalHandle, overwriting the index.
329 void Create(Isolate* isolate, Object* object, int* index);
331 // Grab the handle for an existing EternalHandle.
332 inline Handle<Object> Get(int index) {
333 return Handle<Object>(GetLocation(index));
336 // Grab the handle for an existing SingletonHandle.
337 inline Handle<Object> GetSingleton(SingletonHandle singleton) {
338 DCHECK(Exists(singleton));
339 return Get(singleton_handles_[singleton]);
342 // Checks whether a SingletonHandle has been assigned.
343 inline bool Exists(SingletonHandle singleton) {
344 return singleton_handles_[singleton] != kInvalidIndex;
347 // Assign a SingletonHandle to an empty slot and returns the handle.
348 Handle<Object> CreateSingleton(Isolate* isolate,
350 SingletonHandle singleton) {
351 Create(isolate, object, &singleton_handles_[singleton]);
352 return Get(singleton_handles_[singleton]);
355 // Iterates over all handles.
356 void IterateAllRoots(ObjectVisitor* visitor);
357 // Iterates over all handles which might be in new space.
358 void IterateNewSpaceRoots(ObjectVisitor* visitor);
359 // Rebuilds new space list.
360 void PostGarbageCollectionProcessing(Heap* heap);
363 static const int kInvalidIndex = -1;
364 static const int kShift = 8;
365 static const int kSize = 1 << kShift;
366 static const int kMask = 0xff;
368 // Gets the slot for an index
369 inline Object** GetLocation(int index) {
370 DCHECK(index >= 0 && index < size_);
371 return &blocks_[index >> kShift][index & kMask];
375 List<Object**> blocks_;
376 List<int> new_space_indices_;
377 int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
379 DISALLOW_COPY_AND_ASSIGN(EternalHandles);
383 } } // namespace v8::internal
385 #endif // V8_GLOBAL_HANDLES_H_