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"
22 // Structure for tracking global handles.
23 // A single list keeps all the allocated global handles.
24 // Destroyed handles stay in the list but is added to the free list.
25 // At GC the destroyed global handles are removed from the free list
28 // Data structures for tracking object groups and implicit references.
30 // An object group is treated like a single JS object: if one of object in
31 // the group is alive, all objects in the same group are considered alive.
32 // An object group is used to simulate object relationship in a DOM tree.
34 // An implicit references group consists of two parts: a parent object and a
35 // list of children objects. If the parent is alive, all the children are alive
39 explicit ObjectGroup(size_t length)
40 : info(NULL), length(length) {
42 objects = new Object**[length];
46 v8::RetainedObjectInfo* info;
52 struct ImplicitRefGroup {
53 ImplicitRefGroup(HeapObject** parent, size_t length)
54 : parent(parent), length(length) {
56 children = new Object**[length];
66 // For internal bookkeeping.
67 struct ObjectGroupConnection {
68 ObjectGroupConnection(UniqueId id, Object** object)
69 : id(id), object(object) {}
71 bool operator==(const ObjectGroupConnection& other) const {
72 return id == other.id;
75 bool operator<(const ObjectGroupConnection& other) const {
84 struct ObjectGroupRetainerInfo {
85 ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info)
86 : id(id), info(info) {}
88 bool operator==(const ObjectGroupRetainerInfo& other) const {
89 return id == other.id;
92 bool operator<(const ObjectGroupRetainerInfo& other) const {
97 RetainedObjectInfo* info;
101 class GlobalHandles {
105 // Creates a new global handle that is alive until Destroy is called.
106 Handle<Object> Create(Object* value);
108 // Copy a global handle
109 static Handle<Object> CopyGlobal(Object** location);
111 // Destroy a global handle.
112 static void Destroy(Object** location);
114 typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
116 // Make the global handle weak and set the callback parameter for the
117 // handle. When the garbage collector recognizes that only weak global
118 // handles point to an object the handles are cleared and the callback
119 // function is invoked (for each handle) with the handle and corresponding
120 // parameter as arguments. Note: cleared means set to Smi::FromInt(0). The
121 // reason is that Smi::FromInt(0) does not change during garage collection.
122 static void MakeWeak(Object** location,
124 WeakCallback weak_callback);
126 void RecordStats(HeapStats* stats);
128 // Returns the current number of weak handles.
129 int NumberOfWeakHandles();
131 // Returns the current number of weak handles to global objects.
132 // These handles are also included in NumberOfWeakHandles().
133 int NumberOfGlobalObjectWeakHandles();
135 // Returns the current number of handles to global objects.
136 int global_handles_count() const {
137 return number_of_global_handles_;
140 // Clear the weakness of a global handle.
141 static void* ClearWeakness(Object** location);
143 // Clear the weakness of a global handle.
144 static void MarkIndependent(Object** location);
146 // Mark the reference to this object externaly unreachable.
147 static void MarkPartiallyDependent(Object** location);
149 static bool IsIndependent(Object** location);
151 // Tells whether global handle is near death.
152 static bool IsNearDeath(Object** location);
154 // Tells whether global handle is weak.
155 static bool IsWeak(Object** location);
157 // Process pending weak handles.
158 // Returns true if next major GC is likely to collect more garbage.
159 bool PostGarbageCollectionProcessing(GarbageCollector collector,
162 // Iterates over all strong handles.
163 void IterateStrongRoots(ObjectVisitor* v);
165 // Iterates over all handles.
166 void IterateAllRoots(ObjectVisitor* v);
168 // Iterates over all handles that have embedder-assigned class ID.
169 void IterateAllRootsWithClassIds(ObjectVisitor* v);
171 // Iterates over all handles in the new space that have embedder-assigned
173 void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
175 // Iterates over all weak roots in heap.
176 void IterateWeakRoots(ObjectVisitor* v);
178 // Find all weak handles satisfying the callback predicate, mark
180 void IdentifyWeakHandles(WeakSlotCallback f);
182 // NOTE: Three ...NewSpace... functions below are used during
183 // scavenge collections and iterate over sets of handles that are
184 // guaranteed to contain all handles holding new space objects (but
185 // may also include old space objects).
187 // Iterates over strong and dependent handles. See the node above.
188 void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
190 // Finds weak independent or partially independent handles satisfying
191 // the callback predicate and marks them as pending. See the note above.
192 void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
194 // Iterates over weak independent or partially independent handles.
195 // See the note above.
196 void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
198 // Iterate over objects in object groups that have at least one object
199 // which requires visiting. The callback has to return true if objects
200 // can be skipped and false otherwise.
201 bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
203 // Add an object group.
204 // Should be only used in GC callback function before a collection.
205 // All groups are destroyed after a garbage collection.
206 void AddObjectGroup(Object*** handles,
208 v8::RetainedObjectInfo* info);
210 // Associates handle with the object group represented by id.
211 // Should be only used in GC callback function before a collection.
212 // All groups are destroyed after a garbage collection.
213 void SetObjectGroupId(Object** handle, UniqueId id);
215 // Set RetainedObjectInfo for an object group. Should not be called more than
216 // once for a group. Should not be called for a group which contains no
218 void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
220 // Add an implicit references' group.
221 // Should be only used in GC callback function before a collection.
222 // All groups are destroyed after a mark-compact collection.
223 void AddImplicitReferences(HeapObject** parent,
227 // Adds an implicit reference from a group to an object. Should be only used
228 // in GC callback function before a collection. All implicit references are
229 // destroyed after a mark-compact collection.
230 void SetReferenceFromGroup(UniqueId id, Object** child);
232 // Adds an implicit reference from a parent object to a child object. Should
233 // be only used in GC callback function before a collection. All implicit
234 // references are destroyed after a mark-compact collection.
235 void SetReference(HeapObject** parent, Object** child);
237 List<ObjectGroup*>* object_groups() {
238 ComputeObjectGroupsAndImplicitReferences();
239 return &object_groups_;
242 List<ImplicitRefGroup*>* implicit_ref_groups() {
243 ComputeObjectGroupsAndImplicitReferences();
244 return &implicit_ref_groups_;
247 // Remove bags, this should only happen after GC.
248 void RemoveObjectGroups();
249 void RemoveImplicitRefGroups();
251 // Tear down the global handle structure.
254 Isolate* isolate() { return isolate_; }
262 explicit GlobalHandles(Isolate* isolate);
264 // Migrates data from the internal representation (object_group_connections_,
265 // retainer_infos_ and implicit_ref_connections_) to the public and more
266 // efficient representation (object_groups_ and implicit_ref_groups_).
267 void ComputeObjectGroupsAndImplicitReferences();
269 // v8::internal::List is inefficient even for small number of elements, if we
270 // don't assign any initial capacity.
271 static const int kObjectGroupConnectionsCapacity = 20;
273 // Internal node structures.
280 // Field always containing the number of handles to global objects.
281 int number_of_global_handles_;
283 // List of all allocated node blocks.
284 NodeBlock* first_block_;
286 // List of node blocks with used nodes.
287 NodeBlock* first_used_block_;
289 // Free list of nodes.
292 // Contains all nodes holding new space objects. Note: when the list
293 // is accessed, some of the objects may have been promoted already.
294 List<Node*> new_space_nodes_;
296 int post_gc_processing_count_;
298 // Object groups and implicit references, public and more efficient
300 List<ObjectGroup*> object_groups_;
301 List<ImplicitRefGroup*> implicit_ref_groups_;
303 // Object groups and implicit references, temporary representation while
304 // constructing the groups.
305 List<ObjectGroupConnection> object_group_connections_;
306 List<ObjectGroupRetainerInfo> retainer_infos_;
307 List<ObjectGroupConnection> implicit_ref_connections_;
309 friend class Isolate;
311 DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
315 class EternalHandles {
317 enum SingletonHandle {
322 NUMBER_OF_SINGLETON_HANDLES
328 int NumberOfHandles() { return size_; }
330 // Create an EternalHandle, overwriting the index.
331 void Create(Isolate* isolate, Object* object, int* index);
333 // Grab the handle for an existing EternalHandle.
334 inline Handle<Object> Get(int index) {
335 return Handle<Object>(GetLocation(index));
338 // Grab the handle for an existing SingletonHandle.
339 inline Handle<Object> GetSingleton(SingletonHandle singleton) {
340 ASSERT(Exists(singleton));
341 return Get(singleton_handles_[singleton]);
344 // Checks whether a SingletonHandle has been assigned.
345 inline bool Exists(SingletonHandle singleton) {
346 return singleton_handles_[singleton] != kInvalidIndex;
349 // Assign a SingletonHandle to an empty slot and returns the handle.
350 Handle<Object> CreateSingleton(Isolate* isolate,
352 SingletonHandle singleton) {
353 Create(isolate, object, &singleton_handles_[singleton]);
354 return Get(singleton_handles_[singleton]);
357 // Iterates over all handles.
358 void IterateAllRoots(ObjectVisitor* visitor);
359 // Iterates over all handles which might be in new space.
360 void IterateNewSpaceRoots(ObjectVisitor* visitor);
361 // Rebuilds new space list.
362 void PostGarbageCollectionProcessing(Heap* heap);
365 static const int kInvalidIndex = -1;
366 static const int kShift = 8;
367 static const int kSize = 1 << kShift;
368 static const int kMask = 0xff;
370 // Gets the slot for an index
371 inline Object** GetLocation(int index) {
372 ASSERT(index >= 0 && index < size_);
373 return &blocks_[index >> kShift][index & kMask];
377 List<Object**> blocks_;
378 List<int> new_space_indices_;
379 int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
381 DISALLOW_COPY_AND_ASSIGN(EternalHandles);
385 } } // namespace v8::internal
387 #endif // V8_GLOBAL_HANDLES_H_