blob: b3756d0e62035f41d980f5efbe17538414ec2eb8 [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
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400100enum WeaknessType {
101 NORMAL_WEAK, // Embedder gets a handle to the dying object.
102 PHANTOM_WEAK, // Embedder gets the parameter they passed in earlier.
103 INTERNAL_FIELDS_WEAK // Embedder gets 2 internal fields from dying object.
104};
105
106
Steve Block44f0eee2011-05-26 01:26:41 +0100107class GlobalHandles {
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100109 ~GlobalHandles();
110
Steve Blocka7e24c12009-10-30 11:49:00 +0000111 // Creates a new global handle that is alive until Destroy is called.
Steve Block44f0eee2011-05-26 01:26:41 +0100112 Handle<Object> Create(Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000113
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 // Copy a global handle
115 static Handle<Object> CopyGlobal(Object** location);
116
Steve Blocka7e24c12009-10-30 11:49:00 +0000117 // Destroy a global handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 static void Destroy(Object** location);
119
120 typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
Steve Blocka7e24c12009-10-30 11:49:00 +0000121
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400122 // For a phantom weak reference, the callback does not have access to the
123 // dying object. Phantom weak references are preferred because they allow
124 // memory to be reclaimed in one GC cycle rather than two. However, for
125 // historical reasons the default is non-phantom.
126 enum PhantomState { Nonphantom, Phantom };
127
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 // Make the global handle weak and set the callback parameter for the
129 // handle. When the garbage collector recognizes that only weak global
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400130 // handles point to an object the callback function is invoked (for each
131 // handle) with the handle and corresponding parameter as arguments. By
132 // default the handle still contains a pointer to the object that is being
133 // collected. For this reason the object is not collected until the next
134 // GC. For a phantom weak handle the handle is cleared (set to a Smi)
135 // before the callback is invoked, but the handle can still be identified
136 // in the callback by using the location() of the handle.
137 static void MakeWeak(Object** location, void* parameter,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 WeakCallback weak_callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000139
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400140 // It would be nice to template this one, but it's really hard to get
141 // the template instantiator to work right if you do.
142 static void MakePhantom(Object** location, void* parameter,
143 PhantomCallbackData<void>::Callback weak_callback);
144
145 static void MakePhantom(
146 Object** location,
147 v8::InternalFieldsCallbackData<void, void>::Callback weak_callback,
148 int16_t internal_field_index1,
149 int16_t internal_field_index2 = v8::Object::kNoInternalFieldIndex);
150
Steve Block44f0eee2011-05-26 01:26:41 +0100151 void RecordStats(HeapStats* stats);
Steve Blockd0582a62009-12-15 09:54:21 +0000152
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 // Returns the current number of weak handles.
154 int NumberOfWeakHandles();
155
Steve Blocka7e24c12009-10-30 11:49:00 +0000156 // Returns the current number of weak handles to global objects.
157 // These handles are also included in NumberOfWeakHandles().
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 int NumberOfGlobalObjectWeakHandles();
Steve Blocka7e24c12009-10-30 11:49:00 +0000159
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100160 // Returns the current number of handles to global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 int global_handles_count() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100162 return number_of_global_handles_;
163 }
164
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 // Collect up data for the weak handle callbacks after GC has completed, but
166 // before memory is reclaimed.
167 void CollectPhantomCallbackData();
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 // Clear the weakness of a global handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 static void* ClearWeakness(Object** location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000171
Ben Murdoch257744e2011-11-30 15:57:28 +0000172 // Clear the weakness of a global handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 static void MarkIndependent(Object** location);
174
175 // Mark the reference to this object externaly unreachable.
176 static void MarkPartiallyDependent(Object** location);
177
178 static bool IsIndependent(Object** location);
Ben Murdoch257744e2011-11-30 15:57:28 +0000179
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 // Tells whether global handle is near death.
181 static bool IsNearDeath(Object** location);
182
183 // Tells whether global handle is weak.
184 static bool IsWeak(Object** location);
185
John Reck59135872010-11-02 12:39:01 -0700186 // Process pending weak handles.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187 // Returns the number of freed nodes.
188 int PostGarbageCollectionProcessing(GarbageCollector collector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000189
Steve Blockd0582a62009-12-15 09:54:21 +0000190 // Iterates over all strong handles.
Steve Block44f0eee2011-05-26 01:26:41 +0100191 void IterateStrongRoots(ObjectVisitor* v);
Steve Blockd0582a62009-12-15 09:54:21 +0000192
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 // Iterates over all handles.
Steve Block44f0eee2011-05-26 01:26:41 +0100194 void IterateAllRoots(ObjectVisitor* v);
195
196 // Iterates over all handles that have embedder-assigned class ID.
197 void IterateAllRootsWithClassIds(ObjectVisitor* v);
Steve Blocka7e24c12009-10-30 11:49:00 +0000198
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 // Iterates over all handles in the new space that have embedder-assigned
200 // class ID.
201 void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
202
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 // Iterates over all weak roots in heap.
Steve Block44f0eee2011-05-26 01:26:41 +0100204 void IterateWeakRoots(ObjectVisitor* v);
Steve Blocka7e24c12009-10-30 11:49:00 +0000205
Steve Blocka7e24c12009-10-30 11:49:00 +0000206 // Find all weak handles satisfying the callback predicate, mark
207 // them as pending.
Steve Block44f0eee2011-05-26 01:26:41 +0100208 void IdentifyWeakHandles(WeakSlotCallback f);
Steve Blocka7e24c12009-10-30 11:49:00 +0000209
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000210 // NOTE: Three ...NewSpace... functions below are used during
211 // scavenge collections and iterate over sets of handles that are
212 // guaranteed to contain all handles holding new space objects (but
213 // may also include old space objects).
214
215 // Iterates over strong and dependent handles. See the node above.
216 void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
217
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 // Finds weak independent or partially independent handles satisfying
219 // the callback predicate and marks them as pending. See the note above.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000220 void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
221
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 // Iterates over weak independent or partially independent handles.
223 // See the note above.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000224 void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
Ben Murdoch257744e2011-11-30 15:57:28 +0000225
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 // Iterate over objects in object groups that have at least one object
227 // which requires visiting. The callback has to return true if objects
228 // can be skipped and false otherwise.
229 bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
230
Steve Blocka7e24c12009-10-30 11:49:00 +0000231 // Add an object group.
Steve Block44f0eee2011-05-26 01:26:41 +0100232 // Should be only used in GC callback function before a collection.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 // All groups are destroyed after a garbage collection.
Steve Block44f0eee2011-05-26 01:26:41 +0100234 void AddObjectGroup(Object*** handles,
235 size_t length,
236 v8::RetainedObjectInfo* info);
237
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 // Associates handle with the object group represented by id.
Steve Block44f0eee2011-05-26 01:26:41 +0100239 // Should be only used in GC callback function before a collection.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240 // All groups are destroyed after a garbage collection.
241 void SetObjectGroupId(Object** handle, UniqueId id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000242
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 // Set RetainedObjectInfo for an object group. Should not be called more than
244 // once for a group. Should not be called for a group which contains no
245 // handles.
246 void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
Steve Block44f0eee2011-05-26 01:26:41 +0100247
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248 // Adds an implicit reference from a group to an object. Should be only used
249 // in GC callback function before a collection. All implicit references are
250 // destroyed after a mark-compact collection.
251 void SetReferenceFromGroup(UniqueId id, Object** child);
252
253 // Adds an implicit reference from a parent object to a child object. Should
254 // be only used in GC callback function before a collection. All implicit
255 // references are destroyed after a mark-compact collection.
256 void SetReference(HeapObject** parent, Object** child);
257
258 List<ObjectGroup*>* object_groups() {
259 ComputeObjectGroupsAndImplicitReferences();
260 return &object_groups_;
261 }
262
Steve Block44f0eee2011-05-26 01:26:41 +0100263 List<ImplicitRefGroup*>* implicit_ref_groups() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 ComputeObjectGroupsAndImplicitReferences();
Steve Block44f0eee2011-05-26 01:26:41 +0100265 return &implicit_ref_groups_;
266 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000267
268 // Remove bags, this should only happen after GC.
Steve Block44f0eee2011-05-26 01:26:41 +0100269 void RemoveObjectGroups();
270 void RemoveImplicitRefGroups();
Steve Blocka7e24c12009-10-30 11:49:00 +0000271
272 // Tear down the global handle structure.
Steve Block44f0eee2011-05-26 01:26:41 +0100273 void TearDown();
274
275 Isolate* isolate() { return isolate_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000276
277#ifdef DEBUG
Steve Block44f0eee2011-05-26 01:26:41 +0100278 void PrintStats();
279 void Print();
Steve Blocka7e24c12009-10-30 11:49:00 +0000280#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000281
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100283 explicit GlobalHandles(Isolate* isolate);
284
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 // Migrates data from the internal representation (object_group_connections_,
286 // retainer_infos_ and implicit_ref_connections_) to the public and more
287 // efficient representation (object_groups_ and implicit_ref_groups_).
288 void ComputeObjectGroupsAndImplicitReferences();
289
290 // v8::internal::List is inefficient even for small number of elements, if we
291 // don't assign any initial capacity.
292 static const int kObjectGroupConnectionsCapacity = 20;
293
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294 // Helpers for PostGarbageCollectionProcessing.
295 int PostScavengeProcessing(int initial_post_gc_processing_count);
296 int PostMarkSweepProcessing(int initial_post_gc_processing_count);
297 int DispatchPendingPhantomCallbacks();
298 void UpdateListOfNewSpaceNodes();
299
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000300 // Internal node structures.
Steve Blocka7e24c12009-10-30 11:49:00 +0000301 class Node;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000302 class NodeBlock;
303 class NodeIterator;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304 class PendingPhantomCallback;
305 class PendingInternalFieldsCallback;
Steve Blocka7e24c12009-10-30 11:49:00 +0000306
Steve Block44f0eee2011-05-26 01:26:41 +0100307 Isolate* isolate_;
308
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100309 // Field always containing the number of handles to global objects.
310 int number_of_global_handles_;
311
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000312 // List of all allocated node blocks.
313 NodeBlock* first_block_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000314
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000315 // List of node blocks with used nodes.
316 NodeBlock* first_used_block_;
317
318 // Free list of nodes.
Steve Block44f0eee2011-05-26 01:26:41 +0100319 Node* first_free_;
Steve Blockd0582a62009-12-15 09:54:21 +0000320
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000321 // Contains all nodes holding new space objects. Note: when the list
322 // is accessed, some of the objects may have been promoted already.
323 List<Node*> new_space_nodes_;
Steve Block44f0eee2011-05-26 01:26:41 +0100324
Steve Block44f0eee2011-05-26 01:26:41 +0100325 int post_gc_processing_count_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000326
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 // Object groups and implicit references, public and more efficient
328 // representation.
Steve Block44f0eee2011-05-26 01:26:41 +0100329 List<ObjectGroup*> object_groups_;
330 List<ImplicitRefGroup*> implicit_ref_groups_;
331
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 // Object groups and implicit references, temporary representation while
333 // constructing the groups.
334 List<ObjectGroupConnection> object_group_connections_;
335 List<ObjectGroupRetainerInfo> retainer_infos_;
336 List<ObjectGroupConnection> implicit_ref_connections_;
337
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400338 List<PendingPhantomCallback> pending_phantom_callbacks_;
339 List<PendingInternalFieldsCallback> pending_internal_fields_callbacks_;
340
Steve Block44f0eee2011-05-26 01:26:41 +0100341 friend class Isolate;
342
343 DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
Steve Blocka7e24c12009-10-30 11:49:00 +0000344};
345
346
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400347class GlobalHandles::PendingPhantomCallback {
348 public:
349 typedef PhantomCallbackData<void> Data;
350 PendingPhantomCallback(Node* node, Data data, Data::Callback callback)
351 : node_(node), data_(data), callback_(callback) {}
352
353 void invoke();
354
355 Node* node() { return node_; }
356
357 private:
358 Node* node_;
359 Data data_;
360 Data::Callback callback_;
361};
362
363
364class GlobalHandles::PendingInternalFieldsCallback {
365 public:
366 typedef InternalFieldsCallbackData<void, void> Data;
367 PendingInternalFieldsCallback(Data data, Data::Callback callback)
368 : data_(data), callback_(callback) {}
369
370 void invoke() { callback_(data_); }
371
372 private:
373 Data data_;
374 Data::Callback callback_;
375};
376
377
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378class EternalHandles {
379 public:
380 enum SingletonHandle {
381 I18N_TEMPLATE_ONE,
382 I18N_TEMPLATE_TWO,
383 DATE_CACHE_VERSION,
384
385 NUMBER_OF_SINGLETON_HANDLES
386 };
387
388 EternalHandles();
389 ~EternalHandles();
390
391 int NumberOfHandles() { return size_; }
392
393 // Create an EternalHandle, overwriting the index.
394 void Create(Isolate* isolate, Object* object, int* index);
395
396 // Grab the handle for an existing EternalHandle.
397 inline Handle<Object> Get(int index) {
398 return Handle<Object>(GetLocation(index));
399 }
400
401 // Grab the handle for an existing SingletonHandle.
402 inline Handle<Object> GetSingleton(SingletonHandle singleton) {
403 DCHECK(Exists(singleton));
404 return Get(singleton_handles_[singleton]);
405 }
406
407 // Checks whether a SingletonHandle has been assigned.
408 inline bool Exists(SingletonHandle singleton) {
409 return singleton_handles_[singleton] != kInvalidIndex;
410 }
411
412 // Assign a SingletonHandle to an empty slot and returns the handle.
413 Handle<Object> CreateSingleton(Isolate* isolate,
414 Object* object,
415 SingletonHandle singleton) {
416 Create(isolate, object, &singleton_handles_[singleton]);
417 return Get(singleton_handles_[singleton]);
418 }
419
420 // Iterates over all handles.
421 void IterateAllRoots(ObjectVisitor* visitor);
422 // Iterates over all handles which might be in new space.
423 void IterateNewSpaceRoots(ObjectVisitor* visitor);
424 // Rebuilds new space list.
425 void PostGarbageCollectionProcessing(Heap* heap);
426
427 private:
428 static const int kInvalidIndex = -1;
429 static const int kShift = 8;
430 static const int kSize = 1 << kShift;
431 static const int kMask = 0xff;
432
433 // Gets the slot for an index
434 inline Object** GetLocation(int index) {
435 DCHECK(index >= 0 && index < size_);
436 return &blocks_[index >> kShift][index & kMask];
437 }
438
439 int size_;
440 List<Object**> blocks_;
441 List<int> new_space_indices_;
442 int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
443
444 DISALLOW_COPY_AND_ASSIGN(EternalHandles);
445};
446
447
Steve Blocka7e24c12009-10-30 11:49:00 +0000448} } // namespace v8::internal
449
450#endif // V8_GLOBAL_HANDLES_H_