Home | History | Annotate | Download | only in src
      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 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 the number of freed nodes.
    159   int 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_
    388