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 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   // Make the global handle weak and set the callback parameter for the
    116   // handle.  When the garbage collector recognizes that only weak global
    117   // handles point to an object the handles are cleared and the callback
    118   // function is invoked (for each handle) with the handle and corresponding
    119   // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
    120   // reason is that Smi::FromInt(0) does not change during garage collection.
    121   static void MakeWeak(Object** location,
    122                        void* parameter,
    123                        WeakCallback weak_callback);
    124 
    125   void RecordStats(HeapStats* stats);
    126 
    127   // Returns the current number of weak handles.
    128   int NumberOfWeakHandles();
    129 
    130   // Returns the current number of weak handles to global objects.
    131   // These handles are also included in NumberOfWeakHandles().
    132   int NumberOfGlobalObjectWeakHandles();
    133 
    134   // Returns the current number of handles to global objects.
    135   int global_handles_count() const {
    136     return number_of_global_handles_;
    137   }
    138 
    139   // Clear the weakness of a global handle.
    140   static void* ClearWeakness(Object** location);
    141 
    142   // Clear the weakness of a global handle.
    143   static void MarkIndependent(Object** location);
    144 
    145   // Mark the reference to this object externaly unreachable.
    146   static void MarkPartiallyDependent(Object** location);
    147 
    148   static bool IsIndependent(Object** location);
    149 
    150   // Tells whether global handle is near death.
    151   static bool IsNearDeath(Object** location);
    152 
    153   // Tells whether global handle is weak.
    154   static bool IsWeak(Object** location);
    155 
    156   // Process pending weak handles.
    157   // Returns the number of freed nodes.
    158   int PostGarbageCollectionProcessing(GarbageCollector collector);
    159 
    160   // Iterates over all strong handles.
    161   void IterateStrongRoots(ObjectVisitor* v);
    162 
    163   // Iterates over all handles.
    164   void IterateAllRoots(ObjectVisitor* v);
    165 
    166   // Iterates over all handles that have embedder-assigned class ID.
    167   void IterateAllRootsWithClassIds(ObjectVisitor* v);
    168 
    169   // Iterates over all handles in the new space that have embedder-assigned
    170   // class ID.
    171   void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
    172 
    173   // Iterates over all weak roots in heap.
    174   void IterateWeakRoots(ObjectVisitor* v);
    175 
    176   // Find all weak handles satisfying the callback predicate, mark
    177   // them as pending.
    178   void IdentifyWeakHandles(WeakSlotCallback f);
    179 
    180   // NOTE: Three ...NewSpace... functions below are used during
    181   // scavenge collections and iterate over sets of handles that are
    182   // guaranteed to contain all handles holding new space objects (but
    183   // may also include old space objects).
    184 
    185   // Iterates over strong and dependent handles. See the node above.
    186   void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
    187 
    188   // Finds weak independent or partially independent handles satisfying
    189   // the callback predicate and marks them as pending. See the note above.
    190   void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
    191 
    192   // Iterates over weak independent or partially independent handles.
    193   // See the note above.
    194   void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
    195 
    196   // Iterate over objects in object groups that have at least one object
    197   // which requires visiting. The callback has to return true if objects
    198   // can be skipped and false otherwise.
    199   bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
    200 
    201   // Add an object group.
    202   // Should be only used in GC callback function before a collection.
    203   // All groups are destroyed after a garbage collection.
    204   void AddObjectGroup(Object*** handles,
    205                       size_t length,
    206                       v8::RetainedObjectInfo* info);
    207 
    208   // Associates handle with the object group represented by id.
    209   // Should be only used in GC callback function before a collection.
    210   // All groups are destroyed after a garbage collection.
    211   void SetObjectGroupId(Object** handle, UniqueId id);
    212 
    213   // Set RetainedObjectInfo for an object group. Should not be called more than
    214   // once for a group. Should not be called for a group which contains no
    215   // handles.
    216   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
    217 
    218   // Adds an implicit reference from a group to an object. Should be only used
    219   // in GC callback function before a collection. All implicit references are
    220   // destroyed after a mark-compact collection.
    221   void SetReferenceFromGroup(UniqueId id, Object** child);
    222 
    223   // Adds an implicit reference from a parent object to a child object. Should
    224   // be only used in GC callback function before a collection. All implicit
    225   // references are destroyed after a mark-compact collection.
    226   void SetReference(HeapObject** parent, Object** child);
    227 
    228   List<ObjectGroup*>* object_groups() {
    229     ComputeObjectGroupsAndImplicitReferences();
    230     return &object_groups_;
    231   }
    232 
    233   List<ImplicitRefGroup*>* implicit_ref_groups() {
    234     ComputeObjectGroupsAndImplicitReferences();
    235     return &implicit_ref_groups_;
    236   }
    237 
    238   // Remove bags, this should only happen after GC.
    239   void RemoveObjectGroups();
    240   void RemoveImplicitRefGroups();
    241 
    242   // Tear down the global handle structure.
    243   void TearDown();
    244 
    245   Isolate* isolate() { return isolate_; }
    246 
    247 #ifdef DEBUG
    248   void PrintStats();
    249   void Print();
    250 #endif
    251 
    252  private:
    253   explicit GlobalHandles(Isolate* isolate);
    254 
    255   // Migrates data from the internal representation (object_group_connections_,
    256   // retainer_infos_ and implicit_ref_connections_) to the public and more
    257   // efficient representation (object_groups_ and implicit_ref_groups_).
    258   void ComputeObjectGroupsAndImplicitReferences();
    259 
    260   // v8::internal::List is inefficient even for small number of elements, if we
    261   // don't assign any initial capacity.
    262   static const int kObjectGroupConnectionsCapacity = 20;
    263 
    264   // Internal node structures.
    265   class Node;
    266   class NodeBlock;
    267   class NodeIterator;
    268 
    269   Isolate* isolate_;
    270 
    271   // Field always containing the number of handles to global objects.
    272   int number_of_global_handles_;
    273 
    274   // List of all allocated node blocks.
    275   NodeBlock* first_block_;
    276 
    277   // List of node blocks with used nodes.
    278   NodeBlock* first_used_block_;
    279 
    280   // Free list of nodes.
    281   Node* first_free_;
    282 
    283   // Contains all nodes holding new space objects. Note: when the list
    284   // is accessed, some of the objects may have been promoted already.
    285   List<Node*> new_space_nodes_;
    286 
    287   int post_gc_processing_count_;
    288 
    289   // Object groups and implicit references, public and more efficient
    290   // representation.
    291   List<ObjectGroup*> object_groups_;
    292   List<ImplicitRefGroup*> implicit_ref_groups_;
    293 
    294   // Object groups and implicit references, temporary representation while
    295   // constructing the groups.
    296   List<ObjectGroupConnection> object_group_connections_;
    297   List<ObjectGroupRetainerInfo> retainer_infos_;
    298   List<ObjectGroupConnection> implicit_ref_connections_;
    299 
    300   friend class Isolate;
    301 
    302   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
    303 };
    304 
    305 
    306 class EternalHandles {
    307  public:
    308   enum SingletonHandle {
    309     I18N_TEMPLATE_ONE,
    310     I18N_TEMPLATE_TWO,
    311     DATE_CACHE_VERSION,
    312 
    313     NUMBER_OF_SINGLETON_HANDLES
    314   };
    315 
    316   EternalHandles();
    317   ~EternalHandles();
    318 
    319   int NumberOfHandles() { return size_; }
    320 
    321   // Create an EternalHandle, overwriting the index.
    322   void Create(Isolate* isolate, Object* object, int* index);
    323 
    324   // Grab the handle for an existing EternalHandle.
    325   inline Handle<Object> Get(int index) {
    326     return Handle<Object>(GetLocation(index));
    327   }
    328 
    329   // Grab the handle for an existing SingletonHandle.
    330   inline Handle<Object> GetSingleton(SingletonHandle singleton) {
    331     DCHECK(Exists(singleton));
    332     return Get(singleton_handles_[singleton]);
    333   }
    334 
    335   // Checks whether a SingletonHandle has been assigned.
    336   inline bool Exists(SingletonHandle singleton) {
    337     return singleton_handles_[singleton] != kInvalidIndex;
    338   }
    339 
    340   // Assign a SingletonHandle to an empty slot and returns the handle.
    341   Handle<Object> CreateSingleton(Isolate* isolate,
    342                                  Object* object,
    343                                  SingletonHandle singleton) {
    344     Create(isolate, object, &singleton_handles_[singleton]);
    345     return Get(singleton_handles_[singleton]);
    346   }
    347 
    348   // Iterates over all handles.
    349   void IterateAllRoots(ObjectVisitor* visitor);
    350   // Iterates over all handles which might be in new space.
    351   void IterateNewSpaceRoots(ObjectVisitor* visitor);
    352   // Rebuilds new space list.
    353   void PostGarbageCollectionProcessing(Heap* heap);
    354 
    355  private:
    356   static const int kInvalidIndex = -1;
    357   static const int kShift = 8;
    358   static const int kSize = 1 << kShift;
    359   static const int kMask = 0xff;
    360 
    361   // Gets the slot for an index
    362   inline Object** GetLocation(int index) {
    363     DCHECK(index >= 0 && index < size_);
    364     return &blocks_[index >> kShift][index & kMask];
    365   }
    366 
    367   int size_;
    368   List<Object**> blocks_;
    369   List<int> new_space_indices_;
    370   int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
    371 
    372   DISALLOW_COPY_AND_ASSIGN(EternalHandles);
    373 };
    374 
    375 
    376 } }  // namespace v8::internal
    377 
    378 #endif  // V8_GLOBAL_HANDLES_H_
    379