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