Upstream version 7.36.149.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 "handles.h"
12 #include "list.h"
13 #include "utils.h"
14
15 namespace v8 {
16 namespace internal {
17
18 class GCTracer;
19 class HeapStats;
20 class ObjectVisitor;
21
22 // Structure for tracking global handles.
23 // A single list keeps all the allocated global handles.
24 // Destroyed handles stay in the list but is added to the free list.
25 // At GC the destroyed global handles are removed from the free list
26 // and deallocated.
27
28 // Data structures for tracking object groups and implicit references.
29
30 // An object group is treated like a single JS object: if one of object in
31 // the group is alive, all objects in the same group are considered alive.
32 // An object group is used to simulate object relationship in a DOM tree.
33
34 // An implicit references group consists of two parts: a parent object and a
35 // list of children objects.  If the parent is alive, all the children are alive
36 // too.
37
38 struct ObjectGroup {
39   explicit ObjectGroup(size_t length)
40       : info(NULL), length(length) {
41     ASSERT(length > 0);
42     objects = new Object**[length];
43   }
44   ~ObjectGroup();
45
46   v8::RetainedObjectInfo* info;
47   Object*** objects;
48   size_t length;
49 };
50
51
52 struct ImplicitRefGroup {
53   ImplicitRefGroup(HeapObject** parent, size_t length)
54       : parent(parent), length(length) {
55     ASSERT(length > 0);
56     children = new Object**[length];
57   }
58   ~ImplicitRefGroup();
59
60   HeapObject** parent;
61   Object*** children;
62   size_t length;
63 };
64
65
66 // For internal bookkeeping.
67 struct ObjectGroupConnection {
68   ObjectGroupConnection(UniqueId id, Object** object)
69       : id(id), object(object) {}
70
71   bool operator==(const ObjectGroupConnection& other) const {
72     return id == other.id;
73   }
74
75   bool operator<(const ObjectGroupConnection& other) const {
76     return id < other.id;
77   }
78
79   UniqueId id;
80   Object** object;
81 };
82
83
84 struct ObjectGroupRetainerInfo {
85   ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info)
86       : id(id), info(info) {}
87
88   bool operator==(const ObjectGroupRetainerInfo& other) const {
89     return id == other.id;
90   }
91
92   bool operator<(const ObjectGroupRetainerInfo& other) const {
93     return id < other.id;
94   }
95
96   UniqueId id;
97   RetainedObjectInfo* info;
98 };
99
100
101 class GlobalHandles {
102  public:
103   ~GlobalHandles();
104
105   // Creates a new global handle that is alive until Destroy is called.
106   Handle<Object> Create(Object* value);
107
108   // Copy a global handle
109   static Handle<Object> CopyGlobal(Object** location);
110
111   // Destroy a global handle.
112   static void Destroy(Object** location);
113
114   typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
115
116   // Make the global handle weak and set the callback parameter for the
117   // handle.  When the garbage collector recognizes that only weak global
118   // handles point to an object the handles are cleared and the callback
119   // function is invoked (for each handle) with the handle and corresponding
120   // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
121   // reason is that Smi::FromInt(0) does not change during garage collection.
122   static void MakeWeak(Object** location,
123                        void* parameter,
124                        WeakCallback weak_callback);
125
126   void RecordStats(HeapStats* stats);
127
128   // Returns the current number of weak handles.
129   int NumberOfWeakHandles();
130
131   // Returns the current number of weak handles to global objects.
132   // These handles are also included in NumberOfWeakHandles().
133   int NumberOfGlobalObjectWeakHandles();
134
135   // Returns the current number of handles to global objects.
136   int global_handles_count() const {
137     return number_of_global_handles_;
138   }
139
140   // Clear the weakness of a global handle.
141   static void* ClearWeakness(Object** location);
142
143   // Clear the weakness of a global handle.
144   static void MarkIndependent(Object** location);
145
146   // Mark the reference to this object externaly unreachable.
147   static void MarkPartiallyDependent(Object** location);
148
149   static bool IsIndependent(Object** location);
150
151   // Tells whether global handle is near death.
152   static bool IsNearDeath(Object** location);
153
154   // Tells whether global handle is weak.
155   static bool IsWeak(Object** location);
156
157   // Process pending weak handles.
158   // Returns true if next major GC is likely to collect more garbage.
159   bool PostGarbageCollectionProcessing(GarbageCollector collector,
160                                        GCTracer* tracer);
161
162   // Iterates over all strong handles.
163   void IterateStrongRoots(ObjectVisitor* v);
164
165   // Iterates over all handles.
166   void IterateAllRoots(ObjectVisitor* v);
167
168   // Iterates over all handles that have embedder-assigned class ID.
169   void IterateAllRootsWithClassIds(ObjectVisitor* v);
170
171   // Iterates over all handles in the new space that have embedder-assigned
172   // class ID.
173   void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
174
175   // Iterates over all weak roots in heap.
176   void IterateWeakRoots(ObjectVisitor* v);
177
178   // Find all weak handles satisfying the callback predicate, mark
179   // them as pending.
180   void IdentifyWeakHandles(WeakSlotCallback f);
181
182   // NOTE: Three ...NewSpace... functions below are used during
183   // scavenge collections and iterate over sets of handles that are
184   // guaranteed to contain all handles holding new space objects (but
185   // may also include old space objects).
186
187   // Iterates over strong and dependent handles. See the node above.
188   void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
189
190   // Finds weak independent or partially independent handles satisfying
191   // the callback predicate and marks them as pending. See the note above.
192   void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
193
194   // Iterates over weak independent or partially independent handles.
195   // See the note above.
196   void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
197
198   // Iterate over objects in object groups that have at least one object
199   // which requires visiting. The callback has to return true if objects
200   // can be skipped and false otherwise.
201   bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
202
203   // Add an object group.
204   // Should be only used in GC callback function before a collection.
205   // All groups are destroyed after a garbage collection.
206   void AddObjectGroup(Object*** handles,
207                       size_t length,
208                       v8::RetainedObjectInfo* info);
209
210   // Associates handle with the object group represented by id.
211   // Should be only used in GC callback function before a collection.
212   // All groups are destroyed after a garbage collection.
213   void SetObjectGroupId(Object** handle, UniqueId id);
214
215   // Set RetainedObjectInfo for an object group. Should not be called more than
216   // once for a group. Should not be called for a group which contains no
217   // handles.
218   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
219
220   // Add an implicit references' group.
221   // Should be only used in GC callback function before a collection.
222   // All groups are destroyed after a mark-compact collection.
223   void AddImplicitReferences(HeapObject** parent,
224                              Object*** children,
225                              size_t length);
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     ASSERT(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     ASSERT(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_