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