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-profiler.h"
     32 
     33 #include "list.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 // Structure for tracking global handles.
     39 // A single list keeps all the allocated global handles.
     40 // Destroyed handles stay in the list but is added to the free list.
     41 // At GC the destroyed global handles are removed from the free list
     42 // and deallocated.
     43 
     44 // An object group is treated like a single JS object: if one of object in
     45 // the group is alive, all objects in the same group are considered alive.
     46 // An object group is used to simulate object relationship in a DOM tree.
     47 class ObjectGroup {
     48  public:
     49   static ObjectGroup* New(Object*** handles,
     50                           size_t length,
     51                           v8::RetainedObjectInfo* info) {
     52     ASSERT(length > 0);
     53     ObjectGroup* group = reinterpret_cast<ObjectGroup*>(
     54         malloc(OFFSET_OF(ObjectGroup, objects_[length])));
     55     group->length_ = length;
     56     group->info_ = info;
     57     CopyWords(group->objects_, handles, static_cast<int>(length));
     58     return group;
     59   }
     60 
     61   void Dispose() {
     62     if (info_ != NULL) info_->Dispose();
     63     free(this);
     64   }
     65 
     66   size_t length_;
     67   v8::RetainedObjectInfo* info_;
     68   Object** objects_[1];  // Variable sized array.
     69 
     70  private:
     71   void* operator new(size_t size);
     72   void operator delete(void* p);
     73   ~ObjectGroup();
     74   DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectGroup);
     75 };
     76 
     77 
     78 // An implicit references group consists of two parts: a parent object and
     79 // a list of children objects.  If the parent is alive, all the children
     80 // are alive too.
     81 class ImplicitRefGroup {
     82  public:
     83   static ImplicitRefGroup* New(HeapObject** parent,
     84                                Object*** children,
     85                                size_t length) {
     86     ASSERT(length > 0);
     87     ImplicitRefGroup* group = reinterpret_cast<ImplicitRefGroup*>(
     88         malloc(OFFSET_OF(ImplicitRefGroup, children_[length])));
     89     group->parent_ = parent;
     90     group->length_ = length;
     91     CopyWords(group->children_, children, static_cast<int>(length));
     92     return group;
     93   }
     94 
     95   void Dispose() {
     96     free(this);
     97   }
     98 
     99   HeapObject** parent_;
    100   size_t length_;
    101   Object** children_[1];  // Variable sized array.
    102 
    103  private:
    104   void* operator new(size_t size);
    105   void operator delete(void* p);
    106   ~ImplicitRefGroup();
    107   DISALLOW_IMPLICIT_CONSTRUCTORS(ImplicitRefGroup);
    108 };
    109 
    110 
    111 typedef void (*WeakReferenceGuest)(Object* object, void* parameter);
    112 
    113 class GlobalHandles {
    114  public:
    115   ~GlobalHandles();
    116 
    117   // Creates a new global handle that is alive until Destroy is called.
    118   Handle<Object> Create(Object* value);
    119 
    120   // Destroy a global handle.
    121   void Destroy(Object** location);
    122 
    123   // Make the global handle weak and set the callback parameter for the
    124   // handle.  When the garbage collector recognizes that only weak global
    125   // handles point to an object the handles are cleared and the callback
    126   // function is invoked (for each handle) with the handle and corresponding
    127   // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
    128   // reason is that Smi::FromInt(0) does not change during garage collection.
    129   void MakeWeak(Object** location,
    130                 void* parameter,
    131                 WeakReferenceCallback callback);
    132 
    133   static void SetWrapperClassId(Object** location, uint16_t class_id);
    134 
    135   // Returns the current number of weak handles.
    136   int NumberOfWeakHandles() { return number_of_weak_handles_; }
    137 
    138   void RecordStats(HeapStats* stats);
    139 
    140   // Returns the current number of weak handles to global objects.
    141   // These handles are also included in NumberOfWeakHandles().
    142   int NumberOfGlobalObjectWeakHandles() {
    143     return number_of_global_object_weak_handles_;
    144   }
    145 
    146   // Returns the current number of handles to global objects.
    147   int NumberOfGlobalHandles() {
    148     return number_of_global_handles_;
    149   }
    150 
    151   // Clear the weakness of a global handle.
    152   void ClearWeakness(Object** location);
    153 
    154   // Clear the weakness of a global handle.
    155   void MarkIndependent(Object** location);
    156 
    157   // Tells whether global handle is near death.
    158   static bool IsNearDeath(Object** location);
    159 
    160   // Tells whether global handle is weak.
    161   static bool IsWeak(Object** location);
    162 
    163   // Process pending weak handles.
    164   // Returns true if next major GC is likely to collect more garbage.
    165   bool PostGarbageCollectionProcessing(GarbageCollector collector);
    166 
    167   // Iterates over all strong handles.
    168   void IterateStrongRoots(ObjectVisitor* v);
    169 
    170   // Iterates over all handles.
    171   void IterateAllRoots(ObjectVisitor* v);
    172 
    173   // Iterates over all handles that have embedder-assigned class ID.
    174   void IterateAllRootsWithClassIds(ObjectVisitor* v);
    175 
    176   // Iterates over all weak roots in heap.
    177   void IterateWeakRoots(ObjectVisitor* v);
    178 
    179   // Iterates over weak roots that are bound to a given callback.
    180   void IterateWeakRoots(WeakReferenceGuest f,
    181                         WeakReferenceCallback callback);
    182 
    183   // Find all weak handles satisfying the callback predicate, mark
    184   // them as pending.
    185   void IdentifyWeakHandles(WeakSlotCallback f);
    186 
    187   // NOTE: Three ...NewSpace... functions below are used during
    188   // scavenge collections and iterate over sets of handles that are
    189   // guaranteed to contain all handles holding new space objects (but
    190   // may also include old space objects).
    191 
    192   // Iterates over strong and dependent handles. See the node above.
    193   void IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v);
    194 
    195   // Finds weak independent handles satisfying the callback predicate
    196   // and marks them as pending. See the note above.
    197   void IdentifyNewSpaceWeakIndependentHandles(WeakSlotCallbackWithHeap f);
    198 
    199   // Iterates over weak independent handles. See the note above.
    200   void IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v);
    201 
    202   // Add an object group.
    203   // Should be only used in GC callback function before a collection.
    204   // All groups are destroyed after a mark-compact collection.
    205   void AddObjectGroup(Object*** handles,
    206                       size_t length,
    207                       v8::RetainedObjectInfo* info);
    208 
    209   // Add an implicit references' group.
    210   // Should be only used in GC callback function before a collection.
    211   // All groups are destroyed after a mark-compact collection.
    212   void AddImplicitReferences(HeapObject** parent,
    213                              Object*** children,
    214                              size_t length);
    215 
    216   // Returns the object groups.
    217   List<ObjectGroup*>* object_groups() { return &object_groups_; }
    218 
    219   // Returns the implicit references' groups.
    220   List<ImplicitRefGroup*>* implicit_ref_groups() {
    221     return &implicit_ref_groups_;
    222   }
    223 
    224   // Remove bags, this should only happen after GC.
    225   void RemoveObjectGroups();
    226   void RemoveImplicitRefGroups();
    227 
    228   // Tear down the global handle structure.
    229   void TearDown();
    230 
    231   Isolate* isolate() { return isolate_; }
    232 
    233 #ifdef DEBUG
    234   void PrintStats();
    235   void Print();
    236 #endif
    237 
    238  private:
    239   explicit GlobalHandles(Isolate* isolate);
    240 
    241   // Internal node structures.
    242   class Node;
    243   class NodeBlock;
    244   class NodeIterator;
    245 
    246   Isolate* isolate_;
    247 
    248   // Field always containing the number of weak and near-death handles.
    249   int number_of_weak_handles_;
    250 
    251   // Field always containing the number of weak and near-death handles
    252   // to global objects.  These objects are also included in
    253   // number_of_weak_handles_.
    254   int number_of_global_object_weak_handles_;
    255 
    256   // Field always containing the number of handles to global objects.
    257   int number_of_global_handles_;
    258 
    259   // List of all allocated node blocks.
    260   NodeBlock* first_block_;
    261 
    262   // List of node blocks with used nodes.
    263   NodeBlock* first_used_block_;
    264 
    265   // Free list of nodes.
    266   Node* first_free_;
    267 
    268   // Contains all nodes holding new space objects. Note: when the list
    269   // is accessed, some of the objects may have been promoted already.
    270   List<Node*> new_space_nodes_;
    271 
    272   int post_gc_processing_count_;
    273 
    274   List<ObjectGroup*> object_groups_;
    275   List<ImplicitRefGroup*> implicit_ref_groups_;
    276 
    277   friend class Isolate;
    278 
    279   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
    280 };
    281 
    282 
    283 } }  // namespace v8::internal
    284 
    285 #endif  // V8_GLOBAL_HANDLES_H_
    286