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 <type_traits>
      9 #include <vector>
     10 
     11 #include "include/v8.h"
     12 #include "include/v8-profiler.h"
     13 
     14 #include "src/handles.h"
     15 #include "src/utils.h"
     16 
     17 namespace v8 {
     18 namespace internal {
     19 
     20 class HeapStats;
     21 class RootVisitor;
     22 
     23 // Structure for tracking global handles.
     24 // A single list keeps all the allocated global handles.
     25 // Destroyed handles stay in the list but is added to the free list.
     26 // At GC the destroyed global handles are removed from the free list
     27 // and deallocated.
     28 
     29 enum WeaknessType {
     30   // Embedder gets a handle to the dying object.
     31   FINALIZER_WEAK,
     32   // In the following cases, the embedder gets the parameter they passed in
     33   // earlier, and 0 or 2 first embedder fields. Note that the internal
     34   // fields must contain aligned non-V8 pointers.  Getting pointers to V8
     35   // objects through this interface would be GC unsafe so in that case the
     36   // embedder gets a null pointer instead.
     37   PHANTOM_WEAK,
     38   PHANTOM_WEAK_2_EMBEDDER_FIELDS,
     39   // The handle is automatically reset by the garbage collector when
     40   // the object is no longer reachable.
     41   PHANTOM_WEAK_RESET_HANDLE
     42 };
     43 
     44 class GlobalHandles {
     45  public:
     46   ~GlobalHandles();
     47 
     48   // Creates a new global handle that is alive until Destroy is called.
     49   Handle<Object> Create(Object* value);
     50 
     51   template <typename T>
     52   Handle<T> Create(T* value) {
     53     static_assert(std::is_base_of<Object, T>::value, "static type violation");
     54     // The compiler should only pick this method if T is not Object.
     55     static_assert(!std::is_same<Object, T>::value, "compiler error");
     56     return Handle<T>::cast(Create(static_cast<Object*>(value)));
     57   }
     58 
     59   // Copy a global handle
     60   static Handle<Object> CopyGlobal(Object** location);
     61 
     62   // Destroy a global handle.
     63   static void Destroy(Object** location);
     64 
     65   // Make the global handle weak and set the callback parameter for the
     66   // handle.  When the garbage collector recognizes that only weak global
     67   // handles point to an object the callback function is invoked (for each
     68   // handle) with the handle and corresponding parameter as arguments.  By
     69   // default the handle still contains a pointer to the object that is being
     70   // collected.  For this reason the object is not collected until the next
     71   // GC.  For a phantom weak handle the handle is cleared (set to a Smi)
     72   // before the callback is invoked, but the handle can still be identified
     73   // in the callback by using the location() of the handle.
     74   static void MakeWeak(Object** location, void* parameter,
     75                        WeakCallbackInfo<void>::Callback weak_callback,
     76                        v8::WeakCallbackType type);
     77 
     78   static void MakeWeak(Object*** location_addr);
     79 
     80   static void AnnotateStrongRetainer(Object** location, const char* label);
     81 
     82   void RecordStats(HeapStats* stats);
     83 
     84   // Returns the current number of handles to global objects.
     85   int global_handles_count() const {
     86     return number_of_global_handles_;
     87   }
     88 
     89   size_t NumberOfPhantomHandleResets() {
     90     return number_of_phantom_handle_resets_;
     91   }
     92 
     93   void ResetNumberOfPhantomHandleResets() {
     94     number_of_phantom_handle_resets_ = 0;
     95   }
     96 
     97   size_t NumberOfNewSpaceNodes() { return new_space_nodes_.size(); }
     98 
     99   // Clear the weakness of a global handle.
    100   static void* ClearWeakness(Object** location);
    101 
    102   // Tells whether global handle is near death.
    103   static bool IsNearDeath(Object** location);
    104 
    105   // Tells whether global handle is weak.
    106   static bool IsWeak(Object** location);
    107 
    108   // Process pending weak handles.
    109   // Returns the number of freed nodes.
    110   int PostGarbageCollectionProcessing(
    111       GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
    112 
    113   void IterateStrongRoots(RootVisitor* v);
    114 
    115   void IterateWeakRoots(RootVisitor* v);
    116 
    117   void IterateAllRoots(RootVisitor* v);
    118 
    119   void IterateAllNewSpaceRoots(RootVisitor* v);
    120   void IterateNewSpaceRoots(RootVisitor* v, size_t start, size_t end);
    121 
    122   // Iterates over all handles that have embedder-assigned class ID.
    123   void IterateAllRootsWithClassIds(v8::PersistentHandleVisitor* v);
    124 
    125   // Iterates over all handles in the new space that have embedder-assigned
    126   // class ID.
    127   void IterateAllRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
    128 
    129   // Iterate over all handles in the new space that are weak, unmodified
    130   // and have class IDs
    131   void IterateWeakRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
    132 
    133   // Iterates over weak roots on the heap.
    134   void IterateWeakRootsForFinalizers(RootVisitor* v);
    135   void IterateWeakRootsForPhantomHandles(
    136       WeakSlotCallbackWithHeap should_reset_handle);
    137 
    138   // Marks all handles that should be finalized based on the predicate
    139   // |should_reset_handle| as pending.
    140   void IdentifyWeakHandles(WeakSlotCallbackWithHeap should_reset_handle);
    141 
    142   // NOTE: Five ...NewSpace... functions below are used during
    143   // scavenge collections and iterate over sets of handles that are
    144   // guaranteed to contain all handles holding new space objects (but
    145   // may also include old space objects).
    146 
    147   // Iterates over strong and dependent handles. See the note above.
    148   void IterateNewSpaceStrongAndDependentRoots(RootVisitor* v);
    149 
    150   // Iterates over strong and dependent handles. See the note above.
    151   // Also marks unmodified nodes in the same iteration.
    152   void IterateNewSpaceStrongAndDependentRootsAndIdentifyUnmodified(
    153       RootVisitor* v, size_t start, size_t end);
    154 
    155   // Marks weak unmodified handles satisfying |is_dead| as pending.
    156   void MarkNewSpaceWeakUnmodifiedObjectsPending(
    157       WeakSlotCallbackWithHeap is_dead);
    158 
    159   // Iterates over weak independent or unmodified handles.
    160   // See the note above.
    161   void IterateNewSpaceWeakUnmodifiedRootsForFinalizers(RootVisitor* v);
    162   void IterateNewSpaceWeakUnmodifiedRootsForPhantomHandles(
    163       RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle);
    164 
    165   // Identify unmodified objects that are in weak state and marks them
    166   // unmodified
    167   void IdentifyWeakUnmodifiedObjects(WeakSlotCallback is_unmodified);
    168 
    169   // Tear down the global handle structure.
    170   void TearDown();
    171 
    172   Isolate* isolate() { return isolate_; }
    173 
    174 #ifdef DEBUG
    175   void PrintStats();
    176   void Print();
    177 #endif  // DEBUG
    178 
    179   void InvokeSecondPassPhantomCallbacks();
    180 
    181  private:
    182   // Internal node structures.
    183   class Node;
    184   class NodeBlock;
    185   class NodeIterator;
    186   class PendingPhantomCallback;
    187   class PendingPhantomCallbacksSecondPassTask;
    188 
    189   explicit GlobalHandles(Isolate* isolate);
    190 
    191   void InvokeSecondPassPhantomCallbacksFromTask();
    192   int PostScavengeProcessing(int initial_post_gc_processing_count);
    193   int PostMarkSweepProcessing(int initial_post_gc_processing_count);
    194   int DispatchPendingPhantomCallbacks(bool synchronous_second_pass);
    195   void UpdateListOfNewSpaceNodes();
    196   void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor,
    197                                     Node* node);
    198 
    199   Isolate* isolate_;
    200 
    201   // Field always containing the number of handles to global objects.
    202   int number_of_global_handles_;
    203 
    204   // List of all allocated node blocks.
    205   NodeBlock* first_block_;
    206 
    207   // List of node blocks with used nodes.
    208   NodeBlock* first_used_block_;
    209 
    210   // Free list of nodes.
    211   Node* first_free_;
    212 
    213   // Contains all nodes holding new space objects. Note: when the list
    214   // is accessed, some of the objects may have been promoted already.
    215   std::vector<Node*> new_space_nodes_;
    216 
    217   int post_gc_processing_count_;
    218 
    219   size_t number_of_phantom_handle_resets_;
    220 
    221   std::vector<PendingPhantomCallback> pending_phantom_callbacks_;
    222   std::vector<PendingPhantomCallback> second_pass_callbacks_;
    223   bool second_pass_callbacks_task_posted_ = false;
    224 
    225   friend class Isolate;
    226 
    227   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
    228 };
    229 
    230 
    231 class GlobalHandles::PendingPhantomCallback {
    232  public:
    233   typedef v8::WeakCallbackInfo<void> Data;
    234   PendingPhantomCallback(
    235       Node* node, Data::Callback callback, void* parameter,
    236       void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
    237       : node_(node), callback_(callback), parameter_(parameter) {
    238     for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
    239       embedder_fields_[i] = embedder_fields[i];
    240     }
    241   }
    242 
    243   void Invoke(Isolate* isolate);
    244 
    245   Node* node() { return node_; }
    246   Data::Callback callback() { return callback_; }
    247 
    248  private:
    249   Node* node_;
    250   Data::Callback callback_;
    251   void* parameter_;
    252   void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback];
    253 };
    254 
    255 
    256 class EternalHandles {
    257  public:
    258   enum SingletonHandle {
    259     DATE_CACHE_VERSION,
    260 
    261     NUMBER_OF_SINGLETON_HANDLES
    262   };
    263 
    264   EternalHandles();
    265   ~EternalHandles();
    266 
    267   int NumberOfHandles() { return size_; }
    268 
    269   // Create an EternalHandle, overwriting the index.
    270   void Create(Isolate* isolate, Object* object, int* index);
    271 
    272   // Grab the handle for an existing EternalHandle.
    273   inline Handle<Object> Get(int index) {
    274     return Handle<Object>(GetLocation(index));
    275   }
    276 
    277   // Grab the handle for an existing SingletonHandle.
    278   inline Handle<Object> GetSingleton(SingletonHandle singleton) {
    279     DCHECK(Exists(singleton));
    280     return Get(singleton_handles_[singleton]);
    281   }
    282 
    283   // Checks whether a SingletonHandle has been assigned.
    284   inline bool Exists(SingletonHandle singleton) {
    285     return singleton_handles_[singleton] != kInvalidIndex;
    286   }
    287 
    288   // Assign a SingletonHandle to an empty slot and returns the handle.
    289   Handle<Object> CreateSingleton(Isolate* isolate,
    290                                  Object* object,
    291                                  SingletonHandle singleton) {
    292     Create(isolate, object, &singleton_handles_[singleton]);
    293     return Get(singleton_handles_[singleton]);
    294   }
    295 
    296   // Iterates over all handles.
    297   void IterateAllRoots(RootVisitor* visitor);
    298   // Iterates over all handles which might be in new space.
    299   void IterateNewSpaceRoots(RootVisitor* visitor);
    300   // Rebuilds new space list.
    301   void PostGarbageCollectionProcessing();
    302 
    303  private:
    304   static const int kInvalidIndex = -1;
    305   static const int kShift = 8;
    306   static const int kSize = 1 << kShift;
    307   static const int kMask = 0xff;
    308 
    309   // Gets the slot for an index
    310   inline Object** GetLocation(int index) {
    311     DCHECK(index >= 0 && index < size_);
    312     return &blocks_[index >> kShift][index & kMask];
    313   }
    314 
    315   int size_;
    316   std::vector<Object**> blocks_;
    317   std::vector<int> new_space_indices_;
    318   int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
    319 
    320   DISALLOW_COPY_AND_ASSIGN(EternalHandles);
    321 };
    322 
    323 
    324 }  // namespace internal
    325 }  // namespace v8
    326 
    327 #endif  // V8_GLOBAL_HANDLES_H_
    328