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;
101 NORMAL_WEAK, // Embedder gets a handle to the dying object.
102 // In the following cases, the embedder gets the parameter they passed in
103 // earlier, and 0 or 2 first internal fields. Note that the internal
104 // fields must contain aligned non-V8 pointers. Getting pointers to V8
105 // objects through this interface would be GC unsafe so in that case the
106 // embedder gets a null pointer instead.
108 PHANTOM_WEAK_2_INTERNAL_FIELDS
112 class GlobalHandles {
116 // Creates a new global handle that is alive until Destroy is called.
117 Handle<Object> Create(Object* value);
119 // Copy a global handle
120 static Handle<Object> CopyGlobal(Object** location);
122 // Destroy a global handle.
123 static void Destroy(Object** location);
125 typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
127 // For a phantom weak reference, the callback does not have access to the
128 // dying object. Phantom weak references are preferred because they allow
129 // memory to be reclaimed in one GC cycle rather than two. However, for
130 // historical reasons the default is non-phantom.
131 enum PhantomState { Nonphantom, Phantom };
133 // Make the global handle weak and set the callback parameter for the
134 // handle. When the garbage collector recognizes that only weak global
135 // handles point to an object the callback function is invoked (for each
136 // handle) with the handle and corresponding parameter as arguments. By
137 // default the handle still contains a pointer to the object that is being
138 // collected. For this reason the object is not collected until the next
139 // GC. For a phantom weak handle the handle is cleared (set to a Smi)
140 // before the callback is invoked, but the handle can still be identified
141 // in the callback by using the location() of the handle.
142 static void MakeWeak(Object** location, void* parameter,
143 WeakCallback weak_callback);
145 // It would be nice to template this one, but it's really hard to get
146 // the template instantiator to work right if you do.
147 static void MakeWeak(Object** location, void* parameter,
148 WeakCallbackInfo<void>::Callback weak_callback,
149 v8::WeakCallbackType type);
151 void RecordStats(HeapStats* stats);
153 // Returns the current number of weak handles.
154 int NumberOfWeakHandles();
156 // Returns the current number of weak handles to global objects.
157 // These handles are also included in NumberOfWeakHandles().
158 int NumberOfGlobalObjectWeakHandles();
160 // Returns the current number of handles to global objects.
161 int global_handles_count() const {
162 return number_of_global_handles_;
165 // Collect up data for the weak handle callbacks after GC has completed, but
166 // before memory is reclaimed.
167 void CollectAllPhantomCallbackData();
169 // Collect up data for the weak handle callbacks referenced by young
170 // generation after GC has completed, but before memory is reclaimed.
171 void CollectYoungPhantomCallbackData();
173 // Clear the weakness of a global handle.
174 static void* ClearWeakness(Object** location);
176 // Clear the weakness of a global handle.
177 static void MarkIndependent(Object** location);
179 // Mark the reference to this object externaly unreachable.
180 static void MarkPartiallyDependent(Object** location);
182 static bool IsIndependent(Object** location);
184 // Tells whether global handle is near death.
185 static bool IsNearDeath(Object** location);
187 // Tells whether global handle is weak.
188 static bool IsWeak(Object** location);
190 // Process pending weak handles.
191 // Returns the number of freed nodes.
192 int PostGarbageCollectionProcessing(GarbageCollector collector);
194 // Iterates over all strong handles.
195 void IterateStrongRoots(ObjectVisitor* v);
197 // Iterates over all handles.
198 void IterateAllRoots(ObjectVisitor* v);
200 // Iterates over all handles that have embedder-assigned class ID.
201 void IterateAllRootsWithClassIds(ObjectVisitor* v);
203 // Iterates over all handles in the new space that have embedder-assigned
205 void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
207 // Iterates over all weak roots in heap.
208 void IterateWeakRoots(ObjectVisitor* v);
210 // Find all weak handles satisfying the callback predicate, mark
212 void IdentifyWeakHandles(WeakSlotCallback f);
214 // NOTE: Three ...NewSpace... functions below are used during
215 // scavenge collections and iterate over sets of handles that are
216 // guaranteed to contain all handles holding new space objects (but
217 // may also include old space objects).
219 // Iterates over strong and dependent handles. See the node above.
220 void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
222 // Finds weak independent or partially independent handles satisfying
223 // the callback predicate and marks them as pending. See the note above.
224 void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
226 // Iterates over weak independent or partially independent handles.
227 // See the note above.
228 void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
230 // Iterate over objects in object groups that have at least one object
231 // which requires visiting. The callback has to return true if objects
232 // can be skipped and false otherwise.
233 bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
235 // Add an object group.
236 // Should be only used in GC callback function before a collection.
237 // All groups are destroyed after a garbage collection.
238 void AddObjectGroup(Object*** handles,
240 v8::RetainedObjectInfo* info);
242 // Associates handle with the object group represented by id.
243 // Should be only used in GC callback function before a collection.
244 // All groups are destroyed after a garbage collection.
245 void SetObjectGroupId(Object** handle, UniqueId id);
247 // Set RetainedObjectInfo for an object group. Should not be called more than
248 // once for a group. Should not be called for a group which contains no
250 void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
252 // Adds an implicit reference from a group to an object. Should be only used
253 // in GC callback function before a collection. All implicit references are
254 // destroyed after a mark-compact collection.
255 void SetReferenceFromGroup(UniqueId id, Object** child);
257 // Adds an implicit reference from a parent object to a child object. Should
258 // be only used in GC callback function before a collection. All implicit
259 // references are destroyed after a mark-compact collection.
260 void SetReference(HeapObject** parent, Object** child);
262 List<ObjectGroup*>* object_groups() {
263 ComputeObjectGroupsAndImplicitReferences();
264 return &object_groups_;
267 List<ImplicitRefGroup*>* implicit_ref_groups() {
268 ComputeObjectGroupsAndImplicitReferences();
269 return &implicit_ref_groups_;
272 // Remove bags, this should only happen after GC.
273 void RemoveObjectGroups();
274 void RemoveImplicitRefGroups();
276 // Tear down the global handle structure.
279 Isolate* isolate() { return isolate_; }
287 explicit GlobalHandles(Isolate* isolate);
289 // Migrates data from the internal representation (object_group_connections_,
290 // retainer_infos_ and implicit_ref_connections_) to the public and more
291 // efficient representation (object_groups_ and implicit_ref_groups_).
292 void ComputeObjectGroupsAndImplicitReferences();
294 // v8::internal::List is inefficient even for small number of elements, if we
295 // don't assign any initial capacity.
296 static const int kObjectGroupConnectionsCapacity = 20;
298 // Helpers for PostGarbageCollectionProcessing.
299 int PostScavengeProcessing(int initial_post_gc_processing_count);
300 int PostMarkSweepProcessing(int initial_post_gc_processing_count);
301 int DispatchPendingPhantomCallbacks();
302 void UpdateListOfNewSpaceNodes();
304 // Internal node structures.
308 class PendingPhantomCallback;
312 // Field always containing the number of handles to global objects.
313 int number_of_global_handles_;
315 // List of all allocated node blocks.
316 NodeBlock* first_block_;
318 // List of node blocks with used nodes.
319 NodeBlock* first_used_block_;
321 // Free list of nodes.
324 // Contains all nodes holding new space objects. Note: when the list
325 // is accessed, some of the objects may have been promoted already.
326 List<Node*> new_space_nodes_;
328 int post_gc_processing_count_;
330 // Object groups and implicit references, public and more efficient
332 List<ObjectGroup*> object_groups_;
333 List<ImplicitRefGroup*> implicit_ref_groups_;
335 // Object groups and implicit references, temporary representation while
336 // constructing the groups.
337 List<ObjectGroupConnection> object_group_connections_;
338 List<ObjectGroupRetainerInfo> retainer_infos_;
339 List<ObjectGroupConnection> implicit_ref_connections_;
341 List<PendingPhantomCallback> pending_phantom_callbacks_;
343 friend class Isolate;
345 DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
349 class GlobalHandles::PendingPhantomCallback {
351 typedef v8::WeakCallbackInfo<void> Data;
352 PendingPhantomCallback(
353 Node* node, Data::Callback callback, void* parameter,
354 void* internal_fields[v8::kInternalFieldsInWeakCallback])
355 : node_(node), callback_(callback), parameter_(parameter) {
356 for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) {
357 internal_fields_[i] = internal_fields[i];
361 void Invoke(Isolate* isolate);
363 Node* node() { return node_; }
364 Data::Callback callback() { return callback_; }
368 Data::Callback callback_;
370 void* internal_fields_[v8::kInternalFieldsInWeakCallback];
374 class EternalHandles {
376 enum SingletonHandle {
381 NUMBER_OF_SINGLETON_HANDLES
387 int NumberOfHandles() { return size_; }
389 // Create an EternalHandle, overwriting the index.
390 void Create(Isolate* isolate, Object* object, int* index);
392 // Grab the handle for an existing EternalHandle.
393 inline Handle<Object> Get(int index) {
394 return Handle<Object>(GetLocation(index));
397 // Grab the handle for an existing SingletonHandle.
398 inline Handle<Object> GetSingleton(SingletonHandle singleton) {
399 DCHECK(Exists(singleton));
400 return Get(singleton_handles_[singleton]);
403 // Checks whether a SingletonHandle has been assigned.
404 inline bool Exists(SingletonHandle singleton) {
405 return singleton_handles_[singleton] != kInvalidIndex;
408 // Assign a SingletonHandle to an empty slot and returns the handle.
409 Handle<Object> CreateSingleton(Isolate* isolate,
411 SingletonHandle singleton) {
412 Create(isolate, object, &singleton_handles_[singleton]);
413 return Get(singleton_handles_[singleton]);
416 // Iterates over all handles.
417 void IterateAllRoots(ObjectVisitor* visitor);
418 // Iterates over all handles which might be in new space.
419 void IterateNewSpaceRoots(ObjectVisitor* visitor);
420 // Rebuilds new space list.
421 void PostGarbageCollectionProcessing(Heap* heap);
424 static const int kInvalidIndex = -1;
425 static const int kShift = 8;
426 static const int kSize = 1 << kShift;
427 static const int kMask = 0xff;
429 // Gets the slot for an index
430 inline Object** GetLocation(int index) {
431 DCHECK(index >= 0 && index < size_);
432 return &blocks_[index >> kShift][index & kMask];
436 List<Object**> blocks_;
437 List<int> new_space_indices_;
438 int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
440 DISALLOW_COPY_AND_ASSIGN(EternalHandles);
444 } } // namespace v8::internal
446 #endif // V8_GLOBAL_HANDLES_H_