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 enum WeaknessType {
    100   // Embedder gets a handle to the dying object.
    101   FINALIZER_WEAK,
    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   // The handle is automatically reset by the garbage collector when
    110   // the object is no longer reachable.
    111   PHANTOM_WEAK_RESET_HANDLE
    112 };
    113 
    114 class GlobalHandles {
    115  public:
    116   ~GlobalHandles();
    117 
    118   // Creates a new global handle that is alive until Destroy is called.
    119   Handle<Object> Create(Object* value);
    120 
    121   // Copy a global handle
    122   static Handle<Object> CopyGlobal(Object** location);
    123 
    124   // Destroy a global handle.
    125   static void Destroy(Object** location);
    126 
    127   // Make the global handle weak and set the callback parameter for the
    128   // handle.  When the garbage collector recognizes that only weak global
    129   // handles point to an object the callback function is invoked (for each
    130   // handle) with the handle and corresponding parameter as arguments.  By
    131   // default the handle still contains a pointer to the object that is being
    132   // collected.  For this reason the object is not collected until the next
    133   // GC.  For a phantom weak handle the handle is cleared (set to a Smi)
    134   // before the callback is invoked, but the handle can still be identified
    135   // in the callback by using the location() of the handle.
    136   static void MakeWeak(Object** location, void* parameter,
    137                        WeakCallbackInfo<void>::Callback weak_callback,
    138                        v8::WeakCallbackType type);
    139 
    140   static void MakeWeak(Object*** location_addr);
    141 
    142   void RecordStats(HeapStats* stats);
    143 
    144   // Returns the current number of weak handles.
    145   int NumberOfWeakHandles();
    146 
    147   // Returns the current number of weak handles to global objects.
    148   // These handles are also included in NumberOfWeakHandles().
    149   int NumberOfGlobalObjectWeakHandles();
    150 
    151   // Returns the current number of handles to global objects.
    152   int global_handles_count() const {
    153     return number_of_global_handles_;
    154   }
    155 
    156   size_t NumberOfPhantomHandleResets() {
    157     return number_of_phantom_handle_resets_;
    158   }
    159 
    160   void ResetNumberOfPhantomHandleResets() {
    161     number_of_phantom_handle_resets_ = 0;
    162   }
    163 
    164   // Clear the weakness of a global handle.
    165   static void* ClearWeakness(Object** location);
    166 
    167   // Mark the reference to this object independent of any object group.
    168   static void MarkIndependent(Object** location);
    169 
    170   static bool IsIndependent(Object** location);
    171 
    172   // Tells whether global handle is near death.
    173   static bool IsNearDeath(Object** location);
    174 
    175   // Tells whether global handle is weak.
    176   static bool IsWeak(Object** location);
    177 
    178   // Process pending weak handles.
    179   // Returns the number of freed nodes.
    180   int PostGarbageCollectionProcessing(
    181       GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
    182 
    183   // Iterates over all strong handles.
    184   void IterateStrongRoots(ObjectVisitor* v);
    185 
    186   // Iterates over all handles.
    187   void IterateAllRoots(ObjectVisitor* v);
    188 
    189   // Iterates over all handles that have embedder-assigned class ID.
    190   void IterateAllRootsWithClassIds(ObjectVisitor* v);
    191 
    192   // Iterates over all handles in the new space that have embedder-assigned
    193   // class ID.
    194   void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
    195 
    196   // Iterate over all handles in the new space that are weak, unmodified
    197   // and have class IDs
    198   void IterateWeakRootsInNewSpaceWithClassIds(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: Five ...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   // Finds weak independent or unmodified handles satisfying
    224   // the callback predicate and marks them as pending. See the note above.
    225   void MarkNewSpaceWeakUnmodifiedObjectsPending(
    226       WeakSlotCallbackWithHeap is_unscavenged);
    227 
    228   // Iterates over weak independent or unmodified handles.
    229   // See the note above.
    230   void IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v);
    231 
    232   // Identify unmodified objects that are in weak state and marks them
    233   // unmodified
    234   void IdentifyWeakUnmodifiedObjects(WeakSlotCallback is_unmodified);
    235 
    236   // Iterate over objects in object groups that have at least one object
    237   // which requires visiting. The callback has to return true if objects
    238   // can be skipped and false otherwise.
    239   bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
    240 
    241   // Print all objects in object groups
    242   void PrintObjectGroups();
    243 
    244   // Add an object group.
    245   // Should be only used in GC callback function before a collection.
    246   // All groups are destroyed after a garbage collection.
    247   void AddObjectGroup(Object*** handles,
    248                       size_t length,
    249                       v8::RetainedObjectInfo* info);
    250 
    251   // Associates handle with the object group represented by id.
    252   // Should be only used in GC callback function before a collection.
    253   // All groups are destroyed after a garbage collection.
    254   void SetObjectGroupId(Object** handle, UniqueId id);
    255 
    256   // Set RetainedObjectInfo for an object group. Should not be called more than
    257   // once for a group. Should not be called for a group which contains no
    258   // handles.
    259   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
    260 
    261   // Adds an implicit reference from a group to an object. Should be only used
    262   // in GC callback function before a collection. All implicit references are
    263   // destroyed after a mark-compact collection.
    264   void SetReferenceFromGroup(UniqueId id, Object** child);
    265 
    266   // Adds an implicit reference from a parent object to a child object. Should
    267   // be only used in GC callback function before a collection. All implicit
    268   // references are destroyed after a mark-compact collection.
    269   void SetReference(HeapObject** parent, Object** child);
    270 
    271   List<ObjectGroup*>* object_groups() {
    272     ComputeObjectGroupsAndImplicitReferences();
    273     return &object_groups_;
    274   }
    275 
    276   List<ImplicitRefGroup*>* implicit_ref_groups() {
    277     ComputeObjectGroupsAndImplicitReferences();
    278     return &implicit_ref_groups_;
    279   }
    280 
    281   // Remove bags, this should only happen after GC.
    282   void RemoveObjectGroups();
    283   void RemoveImplicitRefGroups();
    284 
    285   // Tear down the global handle structure.
    286   void TearDown();
    287 
    288   Isolate* isolate() { return isolate_; }
    289 
    290 #ifdef DEBUG
    291   void PrintStats();
    292   void Print();
    293 #endif
    294 
    295  private:
    296   explicit GlobalHandles(Isolate* isolate);
    297 
    298   // Migrates data from the internal representation (object_group_connections_,
    299   // retainer_infos_ and implicit_ref_connections_) to the public and more
    300   // efficient representation (object_groups_ and implicit_ref_groups_).
    301   void ComputeObjectGroupsAndImplicitReferences();
    302 
    303   // v8::internal::List is inefficient even for small number of elements, if we
    304   // don't assign any initial capacity.
    305   static const int kObjectGroupConnectionsCapacity = 20;
    306 
    307   class PendingPhantomCallback;
    308 
    309   // Helpers for PostGarbageCollectionProcessing.
    310   static void InvokeSecondPassPhantomCallbacks(
    311       List<PendingPhantomCallback>* callbacks, Isolate* isolate);
    312   int PostScavengeProcessing(int initial_post_gc_processing_count);
    313   int PostMarkSweepProcessing(int initial_post_gc_processing_count);
    314   int DispatchPendingPhantomCallbacks(bool synchronous_second_pass);
    315   void UpdateListOfNewSpaceNodes();
    316 
    317   // Internal node structures.
    318   class Node;
    319   class NodeBlock;
    320   class NodeIterator;
    321   class PendingPhantomCallbacksSecondPassTask;
    322 
    323   Isolate* isolate_;
    324 
    325   // Field always containing the number of handles to global objects.
    326   int number_of_global_handles_;
    327 
    328   // List of all allocated node blocks.
    329   NodeBlock* first_block_;
    330 
    331   // List of node blocks with used nodes.
    332   NodeBlock* first_used_block_;
    333 
    334   // Free list of nodes.
    335   Node* first_free_;
    336 
    337   // Contains all nodes holding new space objects. Note: when the list
    338   // is accessed, some of the objects may have been promoted already.
    339   List<Node*> new_space_nodes_;
    340 
    341   int post_gc_processing_count_;
    342 
    343   size_t number_of_phantom_handle_resets_;
    344 
    345   // Object groups and implicit references, public and more efficient
    346   // representation.
    347   List<ObjectGroup*> object_groups_;
    348   List<ImplicitRefGroup*> implicit_ref_groups_;
    349 
    350   // Object groups and implicit references, temporary representation while
    351   // constructing the groups.
    352   List<ObjectGroupConnection> object_group_connections_;
    353   List<ObjectGroupRetainerInfo> retainer_infos_;
    354   List<ObjectGroupConnection> implicit_ref_connections_;
    355 
    356   List<PendingPhantomCallback> pending_phantom_callbacks_;
    357 
    358   friend class Isolate;
    359 
    360   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
    361 };
    362 
    363 
    364 class GlobalHandles::PendingPhantomCallback {
    365  public:
    366   typedef v8::WeakCallbackInfo<void> Data;
    367   PendingPhantomCallback(
    368       Node* node, Data::Callback callback, void* parameter,
    369       void* internal_fields[v8::kInternalFieldsInWeakCallback])
    370       : node_(node), callback_(callback), parameter_(parameter) {
    371     for (int i = 0; i < v8::kInternalFieldsInWeakCallback; ++i) {
    372       internal_fields_[i] = internal_fields[i];
    373     }
    374   }
    375 
    376   void Invoke(Isolate* isolate);
    377 
    378   Node* node() { return node_; }
    379   Data::Callback callback() { return callback_; }
    380 
    381  private:
    382   Node* node_;
    383   Data::Callback callback_;
    384   void* parameter_;
    385   void* internal_fields_[v8::kInternalFieldsInWeakCallback];
    386 };
    387 
    388 
    389 class EternalHandles {
    390  public:
    391   enum SingletonHandle {
    392     I18N_TEMPLATE_ONE,
    393     I18N_TEMPLATE_TWO,
    394     DATE_CACHE_VERSION,
    395 
    396     NUMBER_OF_SINGLETON_HANDLES
    397   };
    398 
    399   EternalHandles();
    400   ~EternalHandles();
    401 
    402   int NumberOfHandles() { return size_; }
    403 
    404   // Create an EternalHandle, overwriting the index.
    405   void Create(Isolate* isolate, Object* object, int* index);
    406 
    407   // Grab the handle for an existing EternalHandle.
    408   inline Handle<Object> Get(int index) {
    409     return Handle<Object>(GetLocation(index));
    410   }
    411 
    412   // Grab the handle for an existing SingletonHandle.
    413   inline Handle<Object> GetSingleton(SingletonHandle singleton) {
    414     DCHECK(Exists(singleton));
    415     return Get(singleton_handles_[singleton]);
    416   }
    417 
    418   // Checks whether a SingletonHandle has been assigned.
    419   inline bool Exists(SingletonHandle singleton) {
    420     return singleton_handles_[singleton] != kInvalidIndex;
    421   }
    422 
    423   // Assign a SingletonHandle to an empty slot and returns the handle.
    424   Handle<Object> CreateSingleton(Isolate* isolate,
    425                                  Object* object,
    426                                  SingletonHandle singleton) {
    427     Create(isolate, object, &singleton_handles_[singleton]);
    428     return Get(singleton_handles_[singleton]);
    429   }
    430 
    431   // Iterates over all handles.
    432   void IterateAllRoots(ObjectVisitor* visitor);
    433   // Iterates over all handles which might be in new space.
    434   void IterateNewSpaceRoots(ObjectVisitor* visitor);
    435   // Rebuilds new space list.
    436   void PostGarbageCollectionProcessing(Heap* heap);
    437 
    438  private:
    439   static const int kInvalidIndex = -1;
    440   static const int kShift = 8;
    441   static const int kSize = 1 << kShift;
    442   static const int kMask = 0xff;
    443 
    444   // Gets the slot for an index
    445   inline Object** GetLocation(int index) {
    446     DCHECK(index >= 0 && index < size_);
    447     return &blocks_[index >> kShift][index & kMask];
    448   }
    449 
    450   int size_;
    451   List<Object**> blocks_;
    452   List<int> new_space_indices_;
    453   int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
    454 
    455   DISALLOW_COPY_AND_ASSIGN(EternalHandles);
    456 };
    457 
    458 
    459 }  // namespace internal
    460 }  // namespace v8
    461 
    462 #endif  // V8_GLOBAL_HANDLES_H_
    463