blob: a06cba0856487f625be72721819fb1342341e46a [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_GLOBAL_HANDLES_H_
6#define V8_GLOBAL_HANDLES_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "include/v8.h"
9#include "include/v8-profiler.h"
Ben Murdoch8b112d22011-06-08 16:22:53 +010010
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/handles.h"
12#include "src/list.h"
13#include "src/utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000014
15namespace v8 {
16namespace internal {
17
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018class HeapStats;
19class ObjectVisitor;
20
Steve Blocka7e24c12009-10-30 11:49:00 +000021// 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
25// and deallocated.
26
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027// Data structures for tracking object groups and implicit references.
28
Steve Blocka7e24c12009-10-30 11:49:00 +000029// 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.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032
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
35// too.
36
37struct ObjectGroup {
38 explicit ObjectGroup(size_t length)
39 : info(NULL), length(length) {
40 DCHECK(length > 0);
41 objects = new Object**[length];
Ben Murdoch8b112d22011-06-08 16:22:53 +010042 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010043 ~ObjectGroup();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044
45 v8::RetainedObjectInfo* info;
46 Object*** objects;
47 size_t length;
Steve Block44f0eee2011-05-26 01:26:41 +010048};
49
50
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051struct ImplicitRefGroup {
52 ImplicitRefGroup(HeapObject** parent, size_t length)
53 : parent(parent), length(length) {
54 DCHECK(length > 0);
55 children = new Object**[length];
Ben Murdoch8b112d22011-06-08 16:22:53 +010056 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010057 ~ImplicitRefGroup();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058
59 HeapObject** parent;
60 Object*** children;
61 size_t length;
Steve Blocka7e24c12009-10-30 11:49:00 +000062};
63
64
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065// For internal bookkeeping.
66struct ObjectGroupConnection {
67 ObjectGroupConnection(UniqueId id, Object** object)
68 : id(id), object(object) {}
69
70 bool operator==(const ObjectGroupConnection& other) const {
71 return id == other.id;
72 }
73
74 bool operator<(const ObjectGroupConnection& other) const {
75 return id < other.id;
76 }
77
78 UniqueId id;
79 Object** object;
80};
81
82
83struct ObjectGroupRetainerInfo {
84 ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info)
85 : id(id), info(info) {}
86
87 bool operator==(const ObjectGroupRetainerInfo& other) const {
88 return id == other.id;
89 }
90
91 bool operator<(const ObjectGroupRetainerInfo& other) const {
92 return id < other.id;
93 }
94
95 UniqueId id;
96 RetainedObjectInfo* info;
97};
98
Steve Block3ce2e202009-11-05 08:53:23 +000099
Steve Block44f0eee2011-05-26 01:26:41 +0100100class GlobalHandles {
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100102 ~GlobalHandles();
103
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 // Creates a new global handle that is alive until Destroy is called.
Steve Block44f0eee2011-05-26 01:26:41 +0100105 Handle<Object> Create(Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000106
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 // Copy a global handle
108 static Handle<Object> CopyGlobal(Object** location);
109
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 // Destroy a global handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111 static void Destroy(Object** location);
112
113 typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
Steve Blocka7e24c12009-10-30 11:49:00 +0000114
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.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 static void MakeWeak(Object** location,
122 void* parameter,
123 WeakCallback weak_callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000124
Steve Block44f0eee2011-05-26 01:26:41 +0100125 void RecordStats(HeapStats* stats);
Steve Blockd0582a62009-12-15 09:54:21 +0000126
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 // Returns the current number of weak handles.
128 int NumberOfWeakHandles();
129
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 // Returns the current number of weak handles to global objects.
131 // These handles are also included in NumberOfWeakHandles().
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132 int NumberOfGlobalObjectWeakHandles();
Steve Blocka7e24c12009-10-30 11:49:00 +0000133
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100134 // Returns the current number of handles to global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000135 int global_handles_count() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100136 return number_of_global_handles_;
137 }
138
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 // Clear the weakness of a global handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 static void* ClearWeakness(Object** location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000141
Ben Murdoch257744e2011-11-30 15:57:28 +0000142 // Clear the weakness of a global handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 static void MarkIndependent(Object** location);
144
145 // Mark the reference to this object externaly unreachable.
146 static void MarkPartiallyDependent(Object** location);
147
148 static bool IsIndependent(Object** location);
Ben Murdoch257744e2011-11-30 15:57:28 +0000149
Steve Blocka7e24c12009-10-30 11:49:00 +0000150 // Tells whether global handle is near death.
151 static bool IsNearDeath(Object** location);
152
153 // Tells whether global handle is weak.
154 static bool IsWeak(Object** location);
155
John Reck59135872010-11-02 12:39:01 -0700156 // Process pending weak handles.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 // Returns the number of freed nodes.
158 int PostGarbageCollectionProcessing(GarbageCollector collector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000159
Steve Blockd0582a62009-12-15 09:54:21 +0000160 // Iterates over all strong handles.
Steve Block44f0eee2011-05-26 01:26:41 +0100161 void IterateStrongRoots(ObjectVisitor* v);
Steve Blockd0582a62009-12-15 09:54:21 +0000162
Steve Blocka7e24c12009-10-30 11:49:00 +0000163 // Iterates over all handles.
Steve Block44f0eee2011-05-26 01:26:41 +0100164 void IterateAllRoots(ObjectVisitor* v);
165
166 // Iterates over all handles that have embedder-assigned class ID.
167 void IterateAllRootsWithClassIds(ObjectVisitor* v);
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 // Iterates over all handles in the new space that have embedder-assigned
170 // class ID.
171 void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
172
Steve Blocka7e24c12009-10-30 11:49:00 +0000173 // Iterates over all weak roots in heap.
Steve Block44f0eee2011-05-26 01:26:41 +0100174 void IterateWeakRoots(ObjectVisitor* v);
Steve Blocka7e24c12009-10-30 11:49:00 +0000175
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 // Find all weak handles satisfying the callback predicate, mark
177 // them as pending.
Steve Block44f0eee2011-05-26 01:26:41 +0100178 void IdentifyWeakHandles(WeakSlotCallback f);
Steve Blocka7e24c12009-10-30 11:49:00 +0000179
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000180 // 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).
184
185 // Iterates over strong and dependent handles. See the node above.
186 void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
187
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 // Finds weak independent or partially independent handles satisfying
189 // the callback predicate and marks them as pending. See the note above.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000190 void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
191
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 // Iterates over weak independent or partially independent handles.
193 // See the note above.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000194 void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
Ben Murdoch257744e2011-11-30 15:57:28 +0000195
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 // 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);
200
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 // Add an object group.
Steve Block44f0eee2011-05-26 01:26:41 +0100202 // Should be only used in GC callback function before a collection.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 // All groups are destroyed after a garbage collection.
Steve Block44f0eee2011-05-26 01:26:41 +0100204 void AddObjectGroup(Object*** handles,
205 size_t length,
206 v8::RetainedObjectInfo* info);
207
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 // Associates handle with the object group represented by id.
Steve Block44f0eee2011-05-26 01:26:41 +0100209 // Should be only used in GC callback function before a collection.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 // All groups are destroyed after a garbage collection.
211 void SetObjectGroupId(Object** handle, UniqueId id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000212
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 // 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
215 // handles.
216 void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
Steve Block44f0eee2011-05-26 01:26:41 +0100217
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 // Adds an implicit reference from a group to an object. Should be only used
219 // in GC callback function before a collection. All implicit references are
220 // destroyed after a mark-compact collection.
221 void SetReferenceFromGroup(UniqueId id, Object** child);
222
223 // Adds an implicit reference from a parent object to a child object. Should
224 // be only used in GC callback function before a collection. All implicit
225 // references are destroyed after a mark-compact collection.
226 void SetReference(HeapObject** parent, Object** child);
227
228 List<ObjectGroup*>* object_groups() {
229 ComputeObjectGroupsAndImplicitReferences();
230 return &object_groups_;
231 }
232
Steve Block44f0eee2011-05-26 01:26:41 +0100233 List<ImplicitRefGroup*>* implicit_ref_groups() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234 ComputeObjectGroupsAndImplicitReferences();
Steve Block44f0eee2011-05-26 01:26:41 +0100235 return &implicit_ref_groups_;
236 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000237
238 // Remove bags, this should only happen after GC.
Steve Block44f0eee2011-05-26 01:26:41 +0100239 void RemoveObjectGroups();
240 void RemoveImplicitRefGroups();
Steve Blocka7e24c12009-10-30 11:49:00 +0000241
242 // Tear down the global handle structure.
Steve Block44f0eee2011-05-26 01:26:41 +0100243 void TearDown();
244
245 Isolate* isolate() { return isolate_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000246
247#ifdef DEBUG
Steve Block44f0eee2011-05-26 01:26:41 +0100248 void PrintStats();
249 void Print();
Steve Blocka7e24c12009-10-30 11:49:00 +0000250#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000251
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100253 explicit GlobalHandles(Isolate* isolate);
254
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 // Migrates data from the internal representation (object_group_connections_,
256 // retainer_infos_ and implicit_ref_connections_) to the public and more
257 // efficient representation (object_groups_ and implicit_ref_groups_).
258 void ComputeObjectGroupsAndImplicitReferences();
259
260 // v8::internal::List is inefficient even for small number of elements, if we
261 // don't assign any initial capacity.
262 static const int kObjectGroupConnectionsCapacity = 20;
263
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000264 // Internal node structures.
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 class Node;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000266 class NodeBlock;
267 class NodeIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000268
Steve Block44f0eee2011-05-26 01:26:41 +0100269 Isolate* isolate_;
270
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100271 // Field always containing the number of handles to global objects.
272 int number_of_global_handles_;
273
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000274 // List of all allocated node blocks.
275 NodeBlock* first_block_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000276
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000277 // List of node blocks with used nodes.
278 NodeBlock* first_used_block_;
279
280 // Free list of nodes.
Steve Block44f0eee2011-05-26 01:26:41 +0100281 Node* first_free_;
Steve Blockd0582a62009-12-15 09:54:21 +0000282
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000283 // Contains all nodes holding new space objects. Note: when the list
284 // is accessed, some of the objects may have been promoted already.
285 List<Node*> new_space_nodes_;
Steve Block44f0eee2011-05-26 01:26:41 +0100286
Steve Block44f0eee2011-05-26 01:26:41 +0100287 int post_gc_processing_count_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000288
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 // Object groups and implicit references, public and more efficient
290 // representation.
Steve Block44f0eee2011-05-26 01:26:41 +0100291 List<ObjectGroup*> object_groups_;
292 List<ImplicitRefGroup*> implicit_ref_groups_;
293
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 // Object groups and implicit references, temporary representation while
295 // constructing the groups.
296 List<ObjectGroupConnection> object_group_connections_;
297 List<ObjectGroupRetainerInfo> retainer_infos_;
298 List<ObjectGroupConnection> implicit_ref_connections_;
299
Steve Block44f0eee2011-05-26 01:26:41 +0100300 friend class Isolate;
301
302 DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
Steve Blocka7e24c12009-10-30 11:49:00 +0000303};
304
305
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306class EternalHandles {
307 public:
308 enum SingletonHandle {
309 I18N_TEMPLATE_ONE,
310 I18N_TEMPLATE_TWO,
311 DATE_CACHE_VERSION,
312
313 NUMBER_OF_SINGLETON_HANDLES
314 };
315
316 EternalHandles();
317 ~EternalHandles();
318
319 int NumberOfHandles() { return size_; }
320
321 // Create an EternalHandle, overwriting the index.
322 void Create(Isolate* isolate, Object* object, int* index);
323
324 // Grab the handle for an existing EternalHandle.
325 inline Handle<Object> Get(int index) {
326 return Handle<Object>(GetLocation(index));
327 }
328
329 // Grab the handle for an existing SingletonHandle.
330 inline Handle<Object> GetSingleton(SingletonHandle singleton) {
331 DCHECK(Exists(singleton));
332 return Get(singleton_handles_[singleton]);
333 }
334
335 // Checks whether a SingletonHandle has been assigned.
336 inline bool Exists(SingletonHandle singleton) {
337 return singleton_handles_[singleton] != kInvalidIndex;
338 }
339
340 // Assign a SingletonHandle to an empty slot and returns the handle.
341 Handle<Object> CreateSingleton(Isolate* isolate,
342 Object* object,
343 SingletonHandle singleton) {
344 Create(isolate, object, &singleton_handles_[singleton]);
345 return Get(singleton_handles_[singleton]);
346 }
347
348 // Iterates over all handles.
349 void IterateAllRoots(ObjectVisitor* visitor);
350 // Iterates over all handles which might be in new space.
351 void IterateNewSpaceRoots(ObjectVisitor* visitor);
352 // Rebuilds new space list.
353 void PostGarbageCollectionProcessing(Heap* heap);
354
355 private:
356 static const int kInvalidIndex = -1;
357 static const int kShift = 8;
358 static const int kSize = 1 << kShift;
359 static const int kMask = 0xff;
360
361 // Gets the slot for an index
362 inline Object** GetLocation(int index) {
363 DCHECK(index >= 0 && index < size_);
364 return &blocks_[index >> kShift][index & kMask];
365 }
366
367 int size_;
368 List<Object**> blocks_;
369 List<int> new_space_indices_;
370 int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
371
372 DISALLOW_COPY_AND_ASSIGN(EternalHandles);
373};
374
375
Steve Blocka7e24c12009-10-30 11:49:00 +0000376} } // namespace v8::internal
377
378#endif // V8_GLOBAL_HANDLES_H_