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