Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / 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 class GlobalHandles {
101  public:
102   ~GlobalHandles();
103
104   // Creates a new global handle that is alive until Destroy is called.
105   Handle<Object> Create(Object* value);
106
107   // Copy a global handle
108   static Handle<Object> CopyGlobal(Object** location);
109
110   // Destroy a global handle.
111   static void Destroy(Object** location);
112
113   typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
114
115   // For a phantom weak reference, the callback does not have access to the
116   // dying object.  Phantom weak references are preferred because they allow
117   // memory to be reclaimed in one GC cycle rather than two.  However, for
118   // historical reasons the default is non-phantom.
119   enum PhantomState { Nonphantom, Phantom };
120
121   // Make the global handle weak and set the callback parameter for the
122   // handle.  When the garbage collector recognizes that only weak global
123   // handles point to an object the callback function is invoked (for each
124   // handle) with the handle and corresponding parameter as arguments.  By
125   // default the handle still contains a pointer to the object that is being
126   // collected.  For this reason the object is not collected until the next
127   // GC.  For a phantom weak handle the handle is cleared (set to a Smi)
128   // before the callback is invoked, but the handle can still be identified
129   // in the callback by using the location() of the handle.
130   static void MakeWeak(Object** location, void* parameter,
131                        WeakCallback weak_callback,
132                        PhantomState phantom = Nonphantom);
133
134   void RecordStats(HeapStats* stats);
135
136   // Returns the current number of weak handles.
137   int NumberOfWeakHandles();
138
139   // Returns the current number of weak handles to global objects.
140   // These handles are also included in NumberOfWeakHandles().
141   int NumberOfGlobalObjectWeakHandles();
142
143   // Returns the current number of handles to global objects.
144   int global_handles_count() const {
145     return number_of_global_handles_;
146   }
147
148   // Clear the weakness of a global handle.
149   static void* ClearWeakness(Object** location);
150
151   // Clear the weakness of a global handle.
152   static void MarkIndependent(Object** location);
153
154   // Mark the reference to this object externaly unreachable.
155   static void MarkPartiallyDependent(Object** location);
156
157   static bool IsIndependent(Object** location);
158
159   // Tells whether global handle is near death.
160   static bool IsNearDeath(Object** location);
161
162   // Tells whether global handle is weak.
163   static bool IsWeak(Object** location);
164
165   // Process pending weak handles.
166   // Returns the number of freed nodes.
167   int PostGarbageCollectionProcessing(GarbageCollector collector);
168
169   // Iterates over all strong handles.
170   void IterateStrongRoots(ObjectVisitor* v);
171
172   // Iterates over all handles.
173   void IterateAllRoots(ObjectVisitor* v);
174
175   // Iterates over all handles that have embedder-assigned class ID.
176   void IterateAllRootsWithClassIds(ObjectVisitor* v);
177
178   // Iterates over all handles in the new space that have embedder-assigned
179   // class ID.
180   void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
181
182   // Iterates over all weak roots in heap.
183   void IterateWeakRoots(ObjectVisitor* v);
184
185   // Find all weak handles satisfying the callback predicate, mark
186   // them as pending.
187   void IdentifyWeakHandles(WeakSlotCallback f);
188
189   // NOTE: Three ...NewSpace... functions below are used during
190   // scavenge collections and iterate over sets of handles that are
191   // guaranteed to contain all handles holding new space objects (but
192   // may also include old space objects).
193
194   // Iterates over strong and dependent handles. See the node above.
195   void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
196
197   // Finds weak independent or partially independent handles satisfying
198   // the callback predicate and marks them as pending. See the note above.
199   void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
200
201   // Iterates over weak independent or partially independent handles.
202   // See the note above.
203   void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
204
205   // Iterate over objects in object groups that have at least one object
206   // which requires visiting. The callback has to return true if objects
207   // can be skipped and false otherwise.
208   bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
209
210   // Add an object group.
211   // Should be only used in GC callback function before a collection.
212   // All groups are destroyed after a garbage collection.
213   void AddObjectGroup(Object*** handles,
214                       size_t length,
215                       v8::RetainedObjectInfo* info);
216
217   // Associates handle with the object group represented by id.
218   // Should be only used in GC callback function before a collection.
219   // All groups are destroyed after a garbage collection.
220   void SetObjectGroupId(Object** handle, UniqueId id);
221
222   // Set RetainedObjectInfo for an object group. Should not be called more than
223   // once for a group. Should not be called for a group which contains no
224   // handles.
225   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
226
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);
231
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);
236
237   List<ObjectGroup*>* object_groups() {
238     ComputeObjectGroupsAndImplicitReferences();
239     return &object_groups_;
240   }
241
242   List<ImplicitRefGroup*>* implicit_ref_groups() {
243     ComputeObjectGroupsAndImplicitReferences();
244     return &implicit_ref_groups_;
245   }
246
247   // Remove bags, this should only happen after GC.
248   void RemoveObjectGroups();
249   void RemoveImplicitRefGroups();
250
251   // Tear down the global handle structure.
252   void TearDown();
253
254   Isolate* isolate() { return isolate_; }
255
256 #ifdef DEBUG
257   void PrintStats();
258   void Print();
259 #endif
260
261  private:
262   explicit GlobalHandles(Isolate* isolate);
263
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();
268
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;
272
273   // Internal node structures.
274   class Node;
275   class NodeBlock;
276   class NodeIterator;
277
278   Isolate* isolate_;
279
280   // Field always containing the number of handles to global objects.
281   int number_of_global_handles_;
282
283   // List of all allocated node blocks.
284   NodeBlock* first_block_;
285
286   // List of node blocks with used nodes.
287   NodeBlock* first_used_block_;
288
289   // Free list of nodes.
290   Node* first_free_;
291
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_;
295
296   int post_gc_processing_count_;
297
298   // Object groups and implicit references, public and more efficient
299   // representation.
300   List<ObjectGroup*> object_groups_;
301   List<ImplicitRefGroup*> implicit_ref_groups_;
302
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_;
308
309   friend class Isolate;
310
311   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
312 };
313
314
315 class EternalHandles {
316  public:
317   enum SingletonHandle {
318     I18N_TEMPLATE_ONE,
319     I18N_TEMPLATE_TWO,
320     DATE_CACHE_VERSION,
321
322     NUMBER_OF_SINGLETON_HANDLES
323   };
324
325   EternalHandles();
326   ~EternalHandles();
327
328   int NumberOfHandles() { return size_; }
329
330   // Create an EternalHandle, overwriting the index.
331   void Create(Isolate* isolate, Object* object, int* index);
332
333   // Grab the handle for an existing EternalHandle.
334   inline Handle<Object> Get(int index) {
335     return Handle<Object>(GetLocation(index));
336   }
337
338   // Grab the handle for an existing SingletonHandle.
339   inline Handle<Object> GetSingleton(SingletonHandle singleton) {
340     DCHECK(Exists(singleton));
341     return Get(singleton_handles_[singleton]);
342   }
343
344   // Checks whether a SingletonHandle has been assigned.
345   inline bool Exists(SingletonHandle singleton) {
346     return singleton_handles_[singleton] != kInvalidIndex;
347   }
348
349   // Assign a SingletonHandle to an empty slot and returns the handle.
350   Handle<Object> CreateSingleton(Isolate* isolate,
351                                  Object* object,
352                                  SingletonHandle singleton) {
353     Create(isolate, object, &singleton_handles_[singleton]);
354     return Get(singleton_handles_[singleton]);
355   }
356
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);
363
364  private:
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;
369
370   // Gets the slot for an index
371   inline Object** GetLocation(int index) {
372     DCHECK(index >= 0 && index < size_);
373     return &blocks_[index >> kShift][index & kMask];
374   }
375
376   int size_;
377   List<Object**> blocks_;
378   List<int> new_space_indices_;
379   int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
380
381   DISALLOW_COPY_AND_ASSIGN(EternalHandles);
382 };
383
384
385 } }  // namespace v8::internal
386
387 #endif  // V8_GLOBAL_HANDLES_H_