Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_GLOBAL_HANDLES_H_
     29 #define V8_GLOBAL_HANDLES_H_
     30 
     31 #include "../include/v8.h"
     32 #include "../include/v8-profiler.h"
     33 
     34 #include "handles.h"
     35 #include "list.h"
     36 #include "v8utils.h"
     37 
     38 namespace v8 {
     39 namespace internal {
     40 
     41 class GCTracer;
     42 class HeapStats;
     43 class ObjectVisitor;
     44 
     45 // Structure for tracking global handles.
     46 // A single list keeps all the allocated global handles.
     47 // Destroyed handles stay in the list but is added to the free list.
     48 // At GC the destroyed global handles are removed from the free list
     49 // and deallocated.
     50 
     51 // Data structures for tracking object groups and implicit references.
     52 
     53 // An object group is treated like a single JS object: if one of object in
     54 // the group is alive, all objects in the same group are considered alive.
     55 // An object group is used to simulate object relationship in a DOM tree.
     56 
     57 // An implicit references group consists of two parts: a parent object and a
     58 // list of children objects.  If the parent is alive, all the children are alive
     59 // too.
     60 
     61 struct ObjectGroup {
     62   explicit ObjectGroup(size_t length)
     63       : info(NULL), length(length) {
     64     ASSERT(length > 0);
     65     objects = new Object**[length];
     66   }
     67   ~ObjectGroup();
     68 
     69   v8::RetainedObjectInfo* info;
     70   Object*** objects;
     71   size_t length;
     72 };
     73 
     74 
     75 struct ImplicitRefGroup {
     76   ImplicitRefGroup(HeapObject** parent, size_t length)
     77       : parent(parent), length(length) {
     78     ASSERT(length > 0);
     79     children = new Object**[length];
     80   }
     81   ~ImplicitRefGroup();
     82 
     83   HeapObject** parent;
     84   Object*** children;
     85   size_t length;
     86 };
     87 
     88 
     89 // For internal bookkeeping.
     90 struct ObjectGroupConnection {
     91   ObjectGroupConnection(UniqueId id, Object** object)
     92       : id(id), object(object) {}
     93 
     94   bool operator==(const ObjectGroupConnection& other) const {
     95     return id == other.id;
     96   }
     97 
     98   bool operator<(const ObjectGroupConnection& other) const {
     99     return id < other.id;
    100   }
    101 
    102   UniqueId id;
    103   Object** object;
    104 };
    105 
    106 
    107 struct ObjectGroupRetainerInfo {
    108   ObjectGroupRetainerInfo(UniqueId id, RetainedObjectInfo* info)
    109       : id(id), info(info) {}
    110 
    111   bool operator==(const ObjectGroupRetainerInfo& other) const {
    112     return id == other.id;
    113   }
    114 
    115   bool operator<(const ObjectGroupRetainerInfo& other) const {
    116     return id < other.id;
    117   }
    118 
    119   UniqueId id;
    120   RetainedObjectInfo* info;
    121 };
    122 
    123 
    124 class GlobalHandles {
    125  public:
    126   ~GlobalHandles();
    127 
    128   // Creates a new global handle that is alive until Destroy is called.
    129   Handle<Object> Create(Object* value);
    130 
    131   // Copy a global handle
    132   static Handle<Object> CopyGlobal(Object** location);
    133 
    134   // Destroy a global handle.
    135   static void Destroy(Object** location);
    136 
    137   typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
    138   typedef WeakReferenceCallbacks<v8::Value, void>::Revivable RevivableCallback;
    139 
    140   // Make the global handle weak and set the callback parameter for the
    141   // handle.  When the garbage collector recognizes that only weak global
    142   // handles point to an object the handles are cleared and the callback
    143   // function is invoked (for each handle) with the handle and corresponding
    144   // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
    145   // reason is that Smi::FromInt(0) does not change during garage collection.
    146   static void MakeWeak(Object** location,
    147                        void* parameter,
    148                        WeakCallback weak_callback,
    149                        RevivableCallback revivable_callback);
    150 
    151   static inline void MakeWeak(Object** location,
    152                               void* parameter,
    153                               RevivableCallback revivable_callback) {
    154     MakeWeak(location, parameter, NULL, revivable_callback);
    155   }
    156 
    157   void RecordStats(HeapStats* stats);
    158 
    159   // Returns the current number of weak handles.
    160   int NumberOfWeakHandles();
    161 
    162   // Returns the current number of weak handles to global objects.
    163   // These handles are also included in NumberOfWeakHandles().
    164   int NumberOfGlobalObjectWeakHandles();
    165 
    166   // Returns the current number of handles to global objects.
    167   int global_handles_count() const {
    168     return number_of_global_handles_;
    169   }
    170 
    171   // Clear the weakness of a global handle.
    172   static void ClearWeakness(Object** location);
    173 
    174   // Clear the weakness of a global handle.
    175   static void MarkIndependent(Object** location);
    176 
    177   // Mark the reference to this object externaly unreachable.
    178   static void MarkPartiallyDependent(Object** location);
    179 
    180   static bool IsIndependent(Object** location);
    181 
    182   // Tells whether global handle is near death.
    183   static bool IsNearDeath(Object** location);
    184 
    185   // Tells whether global handle is weak.
    186   static bool IsWeak(Object** location);
    187 
    188   // Process pending weak handles.
    189   // Returns true if next major GC is likely to collect more garbage.
    190   bool PostGarbageCollectionProcessing(GarbageCollector collector,
    191                                        GCTracer* tracer);
    192 
    193   // Iterates over all strong handles.
    194   void IterateStrongRoots(ObjectVisitor* v);
    195 
    196   // Iterates over all handles.
    197   void IterateAllRoots(ObjectVisitor* v);
    198 
    199   // Iterates over all handles that have embedder-assigned class ID.
    200   void IterateAllRootsWithClassIds(ObjectVisitor* v);
    201 
    202   // Iterates over all handles in the new space that have embedder-assigned
    203   // class ID.
    204   void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
    205 
    206   // Iterates over all weak roots in heap.
    207   void IterateWeakRoots(ObjectVisitor* v);
    208 
    209   // Find all weak handles satisfying the callback predicate, mark
    210   // them as pending.
    211   void IdentifyWeakHandles(WeakSlotCallback f);
    212 
    213   // NOTE: Three ...NewSpace... functions below are used during
    214   // scavenge collections and iterate over sets of handles that are
    215   // guaranteed to contain all handles holding new space objects (but
    216   // may also include old space objects).
    217 
    218   // Iterates over strong and dependent handles. See the node above.
    219   void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
    220 
    221   // Finds weak independent or partially independent handles satisfying
    222   // the callback predicate and marks them as pending. See the note above.
    223   void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
    224 
    225   // Iterates over weak independent or partially independent handles.
    226   // See the note above.
    227   void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
    228 
    229   // Iterate over objects in object groups that have at least one object
    230   // which requires visiting. The callback has to return true if objects
    231   // can be skipped and false otherwise.
    232   bool IterateObjectGroups(ObjectVisitor* v, WeakSlotCallbackWithHeap can_skip);
    233 
    234   // Add an object group.
    235   // Should be only used in GC callback function before a collection.
    236   // All groups are destroyed after a garbage collection.
    237   void AddObjectGroup(Object*** handles,
    238                       size_t length,
    239                       v8::RetainedObjectInfo* info);
    240 
    241   // Associates handle with the object group represented by id.
    242   // Should be only used in GC callback function before a collection.
    243   // All groups are destroyed after a garbage collection.
    244   void SetObjectGroupId(Object** handle, UniqueId id);
    245 
    246   // Set RetainedObjectInfo for an object group. Should not be called more than
    247   // once for a group. Should not be called for a group which contains no
    248   // handles.
    249   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
    250 
    251   // Add an implicit references' group.
    252   // Should be only used in GC callback function before a collection.
    253   // All groups are destroyed after a mark-compact collection.
    254   void AddImplicitReferences(HeapObject** parent,
    255                              Object*** children,
    256                              size_t length);
    257 
    258   // Adds an implicit reference from a group to an object. Should be only used
    259   // in GC callback function before a collection. All implicit references are
    260   // destroyed after a mark-compact collection.
    261   void SetReferenceFromGroup(UniqueId id, Object** child);
    262 
    263   // Adds an implicit reference from a parent object to a child object. Should
    264   // be only used in GC callback function before a collection. All implicit
    265   // references are destroyed after a mark-compact collection.
    266   void SetReference(HeapObject** parent, Object** child);
    267 
    268   List<ObjectGroup*>* object_groups() {
    269     ComputeObjectGroupsAndImplicitReferences();
    270     return &object_groups_;
    271   }
    272 
    273   List<ImplicitRefGroup*>* implicit_ref_groups() {
    274     ComputeObjectGroupsAndImplicitReferences();
    275     return &implicit_ref_groups_;
    276   }
    277 
    278   // Remove bags, this should only happen after GC.
    279   void RemoveObjectGroups();
    280   void RemoveImplicitRefGroups();
    281 
    282   // Tear down the global handle structure.
    283   void TearDown();
    284 
    285   Isolate* isolate() { return isolate_; }
    286 
    287 #ifdef DEBUG
    288   void PrintStats();
    289   void Print();
    290 #endif
    291 
    292  private:
    293   explicit GlobalHandles(Isolate* isolate);
    294 
    295   // Migrates data from the internal representation (object_group_connections_,
    296   // retainer_infos_ and implicit_ref_connections_) to the public and more
    297   // efficient representation (object_groups_ and implicit_ref_groups_).
    298   void ComputeObjectGroupsAndImplicitReferences();
    299 
    300   // v8::internal::List is inefficient even for small number of elements, if we
    301   // don't assign any initial capacity.
    302   static const int kObjectGroupConnectionsCapacity = 20;
    303 
    304   // Internal node structures.
    305   class Node;
    306   class NodeBlock;
    307   class NodeIterator;
    308 
    309   Isolate* isolate_;
    310 
    311   // Field always containing the number of handles to global objects.
    312   int number_of_global_handles_;
    313 
    314   // List of all allocated node blocks.
    315   NodeBlock* first_block_;
    316 
    317   // List of node blocks with used nodes.
    318   NodeBlock* first_used_block_;
    319 
    320   // Free list of nodes.
    321   Node* first_free_;
    322 
    323   // Contains all nodes holding new space objects. Note: when the list
    324   // is accessed, some of the objects may have been promoted already.
    325   List<Node*> new_space_nodes_;
    326 
    327   int post_gc_processing_count_;
    328 
    329   // Object groups and implicit references, public and more efficient
    330   // representation.
    331   List<ObjectGroup*> object_groups_;
    332   List<ImplicitRefGroup*> implicit_ref_groups_;
    333 
    334   // Object groups and implicit references, temporary representation while
    335   // constructing the groups.
    336   List<ObjectGroupConnection> object_group_connections_;
    337   List<ObjectGroupRetainerInfo> retainer_infos_;
    338   List<ObjectGroupConnection> implicit_ref_connections_;
    339 
    340   friend class Isolate;
    341 
    342   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
    343 };
    344 
    345 
    346 class EternalHandles {
    347  public:
    348   enum SingletonHandle {
    349     I18N_TEMPLATE_ONE,
    350     I18N_TEMPLATE_TWO,
    351 
    352     NUMBER_OF_SINGLETON_HANDLES
    353   };
    354 
    355   EternalHandles();
    356   ~EternalHandles();
    357 
    358   int NumberOfHandles() { return size_; }
    359 
    360   // Create an EternalHandle, overwriting the index.
    361   void Create(Isolate* isolate, Object* object, int* index);
    362 
    363   // Grab the handle for an existing EternalHandle.
    364   inline Handle<Object> Get(int index) {
    365     return Handle<Object>(GetLocation(index));
    366   }
    367 
    368   // Grab the handle for an existing SingletonHandle.
    369   inline Handle<Object> GetSingleton(SingletonHandle singleton) {
    370     ASSERT(Exists(singleton));
    371     return Get(singleton_handles_[singleton]);
    372   }
    373 
    374   // Checks whether a SingletonHandle has been assigned.
    375   inline bool Exists(SingletonHandle singleton) {
    376     return singleton_handles_[singleton] != kInvalidIndex;
    377   }
    378 
    379   // Assign a SingletonHandle to an empty slot and returns the handle.
    380   Handle<Object> CreateSingleton(Isolate* isolate,
    381                                  Object* object,
    382                                  SingletonHandle singleton) {
    383     Create(isolate, object, &singleton_handles_[singleton]);
    384     return Get(singleton_handles_[singleton]);
    385   }
    386 
    387   // Iterates over all handles.
    388   void IterateAllRoots(ObjectVisitor* visitor);
    389   // Iterates over all handles which might be in new space.
    390   void IterateNewSpaceRoots(ObjectVisitor* visitor);
    391   // Rebuilds new space list.
    392   void PostGarbageCollectionProcessing(Heap* heap);
    393 
    394  private:
    395   static const int kInvalidIndex = -1;
    396   static const int kShift = 8;
    397   static const int kSize = 1 << kShift;
    398   static const int kMask = 0xff;
    399 
    400   // Gets the slot for an index
    401   inline Object** GetLocation(int index) {
    402     ASSERT(index >= 0 && index < size_);
    403     return &blocks_[index >> kShift][index & kMask];
    404   }
    405 
    406   int size_;
    407   List<Object**> blocks_;
    408   List<int> new_space_indices_;
    409   int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
    410 
    411   DISALLOW_COPY_AND_ASSIGN(EternalHandles);
    412 };
    413 
    414 
    415 } }  // namespace v8::internal
    416 
    417 #endif  // V8_GLOBAL_HANDLES_H_
    418