0ee8c20a375adaea6803c11034686b08d806f9d8
[platform/upstream/v8.git] / src / global-handles.h
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.
4
5 #ifndef V8_GLOBAL_HANDLES_H_
6 #define V8_GLOBAL_HANDLES_H_
7
8 #include "include/v8.h"
9 #include "include/v8-profiler.h"
10
11 #include "src/handles.h"
12 #include "src/list.h"
13 #include "src/utils.h"
14
15 namespace v8 {
16 namespace internal {
17
18 class HeapStats;
19 class ObjectVisitor;
20
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
25 // and deallocated.
26
27 // Data structures for tracking object groups and implicit references.
28
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.
32
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
37 struct ObjectGroup {
38   explicit ObjectGroup(size_t length)
39       : info(NULL), length(length) {
40     DCHECK(length > 0);
41     objects = new Object**[length];
42   }
43   ~ObjectGroup();
44
45   v8::RetainedObjectInfo* info;
46   Object*** objects;
47   size_t length;
48 };
49
50
51 struct ImplicitRefGroup {
52   ImplicitRefGroup(HeapObject** parent, size_t length)
53       : parent(parent), length(length) {
54     DCHECK(length > 0);
55     children = new Object**[length];
56   }
57   ~ImplicitRefGroup();
58
59   HeapObject** parent;
60   Object*** children;
61   size_t length;
62 };
63
64
65 // For internal bookkeeping.
66 struct 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
83 struct 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
99
100 enum WeaknessType {
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.
107   PHANTOM_WEAK,
108   PHANTOM_WEAK_2_INTERNAL_FIELDS
109 };
110
111
112 class GlobalHandles {
113  public:
114   ~GlobalHandles();
115
116   // Creates a new global handle that is alive until Destroy is called.
117   Handle<Object> Create(Object* value);
118
119   // Copy a global handle
120   static Handle<Object> CopyGlobal(Object** location);
121
122   // Destroy a global handle.
123   static void Destroy(Object** location);
124
125   typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
126
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 };
132
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);
144
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);
150
151   void RecordStats(HeapStats* stats);
152
153   // Returns the current number of weak handles.
154   int NumberOfWeakHandles();
155
156   // Returns the current number of weak handles to global objects.
157   // These handles are also included in NumberOfWeakHandles().
158   int NumberOfGlobalObjectWeakHandles();
159
160   // Returns the current number of handles to global objects.
161   int global_handles_count() const {
162     return number_of_global_handles_;
163   }
164
165   // Clear the weakness of a global handle.
166   static void* ClearWeakness(Object** location);
167
168   // Clear the weakness of a global handle.
169   static void MarkIndependent(Object** location);
170
171   // Mark the reference to this object externaly unreachable.
172   static void MarkPartiallyDependent(Object** location);
173
174   static bool IsIndependent(Object** location);
175
176   // Tells whether global handle is near death.
177   static bool IsNearDeath(Object** location);
178
179   // Tells whether global handle is weak.
180   static bool IsWeak(Object** location);
181
182   // Process pending weak handles.
183   // Returns the number of freed nodes.
184   int PostGarbageCollectionProcessing(
185       GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
186
187   // Iterates over all strong handles.
188   void IterateStrongRoots(ObjectVisitor* v);
189
190   // Iterates over all handles.
191   void IterateAllRoots(ObjectVisitor* v);
192
193   // Iterates over all handles that have embedder-assigned class ID.
194   void IterateAllRootsWithClassIds(ObjectVisitor* v);
195
196   // Iterates over all handles in the new space that have embedder-assigned
197   // class ID.
198   void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
199
200   // Iterates over all weak roots in heap.
201   void IterateWeakRoots(ObjectVisitor* v);
202
203   // Find all weak handles satisfying the callback predicate, mark
204   // them as pending.
205   void IdentifyWeakHandles(WeakSlotCallback f);
206
207   // NOTE: Three ...NewSpace... functions below are used during
208   // scavenge collections and iterate over sets of handles that are
209   // guaranteed to contain all handles holding new space objects (but
210   // may also include old space objects).
211
212   // Iterates over strong and dependent handles. See the node above.
213   void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
214
215   // Finds weak independent or partially independent handles satisfying
216   // the callback predicate and marks them as pending. See the note above.
217   void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
218
219   // Iterates over weak independent or partially independent handles.
220   // See the note above.
221   void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
222
223   // Iterate over objects in object groups that have at least one object
224   // which requires visiting. The callback has to return true if objects
225   // can be skipped and false otherwise.
226   bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
227
228   // Add an object group.
229   // Should be only used in GC callback function before a collection.
230   // All groups are destroyed after a garbage collection.
231   void AddObjectGroup(Object*** handles,
232                       size_t length,
233                       v8::RetainedObjectInfo* info);
234
235   // Associates handle with the object group represented by id.
236   // Should be only used in GC callback function before a collection.
237   // All groups are destroyed after a garbage collection.
238   void SetObjectGroupId(Object** handle, UniqueId id);
239
240   // Set RetainedObjectInfo for an object group. Should not be called more than
241   // once for a group. Should not be called for a group which contains no
242   // handles.
243   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
244
245   // Adds an implicit reference from a group to an object. Should be only used
246   // in GC callback function before a collection. All implicit references are
247   // destroyed after a mark-compact collection.
248   void SetReferenceFromGroup(UniqueId id, Object** child);
249
250   // Adds an implicit reference from a parent object to a child object. Should
251   // be only used in GC callback function before a collection. All implicit
252   // references are destroyed after a mark-compact collection.
253   void SetReference(HeapObject** parent, Object** child);
254
255   List<ObjectGroup*>* object_groups() {
256     ComputeObjectGroupsAndImplicitReferences();
257     return &object_groups_;
258   }
259
260   List<ImplicitRefGroup*>* implicit_ref_groups() {
261     ComputeObjectGroupsAndImplicitReferences();
262     return &implicit_ref_groups_;
263   }
264
265   // Remove bags, this should only happen after GC.
266   void RemoveObjectGroups();
267   void RemoveImplicitRefGroups();
268
269   // Tear down the global handle structure.
270   void TearDown();
271
272   Isolate* isolate() { return isolate_; }
273
274 #ifdef DEBUG
275   void PrintStats();
276   void Print();
277 #endif
278
279  private:
280   explicit GlobalHandles(Isolate* isolate);
281
282   // Migrates data from the internal representation (object_group_connections_,
283   // retainer_infos_ and implicit_ref_connections_) to the public and more
284   // efficient representation (object_groups_ and implicit_ref_groups_).
285   void ComputeObjectGroupsAndImplicitReferences();
286
287   // v8::internal::List is inefficient even for small number of elements, if we
288   // don't assign any initial capacity.
289   static const int kObjectGroupConnectionsCapacity = 20;
290
291   class PendingPhantomCallback;
292
293   // Helpers for PostGarbageCollectionProcessing.
294   static void InvokeSecondPassPhantomCallbacks(
295       List<PendingPhantomCallback>* callbacks, Isolate* isolate);
296   int PostScavengeProcessing(int initial_post_gc_processing_count);
297   int PostMarkSweepProcessing(int initial_post_gc_processing_count);
298   int DispatchPendingPhantomCallbacks(bool synchronous_second_pass);
299   void UpdateListOfNewSpaceNodes();
300
301   // Internal node structures.
302   class Node;
303   class NodeBlock;
304   class NodeIterator;
305   class PendingPhantomCallbacksSecondPassTask;
306
307   Isolate* isolate_;
308
309   // Field always containing the number of handles to global objects.
310   int number_of_global_handles_;
311
312   // List of all allocated node blocks.
313   NodeBlock* first_block_;
314
315   // List of node blocks with used nodes.
316   NodeBlock* first_used_block_;
317
318   // Free list of nodes.
319   Node* first_free_;
320
321   // 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_;
324
325   int post_gc_processing_count_;
326
327   // Object groups and implicit references, public and more efficient
328   // representation.
329   List<ObjectGroup*> object_groups_;
330   List<ImplicitRefGroup*> implicit_ref_groups_;
331
332   // 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
338   List<PendingPhantomCallback> pending_phantom_callbacks_;
339
340   friend class Isolate;
341
342   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
343 };
344
345
346 class GlobalHandles::PendingPhantomCallback {
347  public:
348   typedef v8::WeakCallbackInfo<void> Data;
349   PendingPhantomCallback(
350       Node* node, Data::Callback callback, void* parameter,
351       void* internal_fields[v8::kInternalFieldsInWeakCallback])
352       : node_(node), callback_(callback), parameter_(parameter) {
353     for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) {
354       internal_fields_[i] = internal_fields[i];
355     }
356   }
357
358   void Invoke(Isolate* isolate);
359
360   Node* node() { return node_; }
361   Data::Callback callback() { return callback_; }
362
363  private:
364   Node* node_;
365   Data::Callback callback_;
366   void* parameter_;
367   void* internal_fields_[v8::kInternalFieldsInWeakCallback];
368 };
369
370
371 class EternalHandles {
372  public:
373   enum SingletonHandle {
374     I18N_TEMPLATE_ONE,
375     I18N_TEMPLATE_TWO,
376     DATE_CACHE_VERSION,
377
378     NUMBER_OF_SINGLETON_HANDLES
379   };
380
381   EternalHandles();
382   ~EternalHandles();
383
384   int NumberOfHandles() { return size_; }
385
386   // Create an EternalHandle, overwriting the index.
387   void Create(Isolate* isolate, Object* object, int* index);
388
389   // Grab the handle for an existing EternalHandle.
390   inline Handle<Object> Get(int index) {
391     return Handle<Object>(GetLocation(index));
392   }
393
394   // Grab the handle for an existing SingletonHandle.
395   inline Handle<Object> GetSingleton(SingletonHandle singleton) {
396     DCHECK(Exists(singleton));
397     return Get(singleton_handles_[singleton]);
398   }
399
400   // Checks whether a SingletonHandle has been assigned.
401   inline bool Exists(SingletonHandle singleton) {
402     return singleton_handles_[singleton] != kInvalidIndex;
403   }
404
405   // Assign a SingletonHandle to an empty slot and returns the handle.
406   Handle<Object> CreateSingleton(Isolate* isolate,
407                                  Object* object,
408                                  SingletonHandle singleton) {
409     Create(isolate, object, &singleton_handles_[singleton]);
410     return Get(singleton_handles_[singleton]);
411   }
412
413   // Iterates over all handles.
414   void IterateAllRoots(ObjectVisitor* visitor);
415   // Iterates over all handles which might be in new space.
416   void IterateNewSpaceRoots(ObjectVisitor* visitor);
417   // Rebuilds new space list.
418   void PostGarbageCollectionProcessing(Heap* heap);
419
420  private:
421   static const int kInvalidIndex = -1;
422   static const int kShift = 8;
423   static const int kSize = 1 << kShift;
424   static const int kMask = 0xff;
425
426   // Gets the slot for an index
427   inline Object** GetLocation(int index) {
428     DCHECK(index >= 0 && index < size_);
429     return &blocks_[index >> kShift][index & kMask];
430   }
431
432   int size_;
433   List<Object**> blocks_;
434   List<int> new_space_indices_;
435   int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
436
437   DISALLOW_COPY_AND_ASSIGN(EternalHandles);
438 };
439
440
441 } }  // namespace v8::internal
442
443 #endif  // V8_GLOBAL_HANDLES_H_