1 // Copyright 2020 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_HEAP_CPPGC_GC_INFO_TABLE_H_ 6 #define V8_HEAP_CPPGC_GC_INFO_TABLE_H_ 7 8 #include <stdint.h> 9 10 #include "include/cppgc/internal/gc-info.h" 11 #include "include/cppgc/platform.h" 12 #include "include/v8config.h" 13 #include "src/base/logging.h" 14 #include "src/base/macros.h" 15 #include "src/base/platform/mutex.h" 16 #include "src/base/platform/platform.h" 17 18 namespace cppgc { 19 namespace internal { 20 21 // GCInfo contains metadata for objects that are instantiated from classes that 22 // inherit from GarbageCollected. 23 struct GCInfo final { 24 FinalizationCallback finalize; 25 TraceCallback trace; 26 NameCallback name; 27 bool has_v_table; 28 }; 29 30 class V8_EXPORT GCInfoTable final { 31 public: 32 // At maximum |kMaxIndex - 1| indices are supported. 33 // 34 // We assume that 14 bits are enough to represent all possible types. 35 // 36 // For Blink during telemetry runs, we see about 1,000 different types; 37 // looking at the output of the Oilpan GC clang plugin, there appear to be at 38 // most about 6,000 types. Thus 14 bits should be more than twice as many bits 39 // as we will ever need. Different contexts may require adjusting this limit. 40 static constexpr GCInfoIndex kMaxIndex = 1 << 14; 41 42 // Minimum index returned. Values smaller |kMinIndex| may be used as 43 // sentinels. 44 static constexpr GCInfoIndex kMinIndex = 1; 45 46 // (Light) experimentation suggests that Blink doesn't need more than this 47 // while handling content on popular web properties. 48 static constexpr GCInfoIndex kInitialWantedLimit = 512; 49 50 // Refer through GlobalGCInfoTable for retrieving the global table outside 51 // of testing code. 52 explicit GCInfoTable(PageAllocator* page_allocator); 53 ~GCInfoTable(); 54 55 GCInfoIndex RegisterNewGCInfo(const GCInfo& info); 56 GCInfoFromIndex(GCInfoIndex index)57 const GCInfo& GCInfoFromIndex(GCInfoIndex index) const { 58 DCHECK_GE(index, kMinIndex); 59 DCHECK_LT(index, kMaxIndex); 60 DCHECK(table_); 61 return table_[index]; 62 } 63 NumberOfGCInfosForTesting()64 GCInfoIndex NumberOfGCInfosForTesting() const { return current_index_; } LimitForTesting()65 GCInfoIndex LimitForTesting() const { return limit_; } TableSlotForTesting(GCInfoIndex index)66 GCInfo& TableSlotForTesting(GCInfoIndex index) { return table_[index]; } 67 68 private: 69 void Resize(); 70 71 GCInfoIndex InitialTableLimit() const; 72 size_t MaxTableSize() const; 73 74 void CheckMemoryIsZeroed(uintptr_t* base, size_t len); 75 76 PageAllocator* page_allocator_; 77 // Holds the per-class GCInfo descriptors; each HeapObjectHeader keeps an 78 // index into this table. 79 GCInfo* table_; 80 uint8_t* read_only_table_end_; 81 // Current index used when requiring a new GCInfo object. 82 GCInfoIndex current_index_ = kMinIndex; 83 // The limit (exclusive) of the currently allocated table. 84 GCInfoIndex limit_ = 0; 85 86 v8::base::Mutex table_mutex_; 87 88 DISALLOW_COPY_AND_ASSIGN(GCInfoTable); 89 }; 90 91 class V8_EXPORT GlobalGCInfoTable final { 92 public: 93 // Sets up a singleton table that can be acquired using Get(). 94 static void Create(PageAllocator* page_allocator); 95 96 // Accessors for the singleton table. GetMutable()97 static GCInfoTable& GetMutable() { return *global_table_; } Get()98 static const GCInfoTable& Get() { return *global_table_; } 99 GCInfoFromIndex(GCInfoIndex index)100 static const GCInfo& GCInfoFromIndex(GCInfoIndex index) { 101 return Get().GCInfoFromIndex(index); 102 } 103 104 private: 105 // Singleton for each process. Retrieved through Get(). 106 static GCInfoTable* global_table_; 107 108 DISALLOW_NEW_AND_DELETE() 109 DISALLOW_COPY_AND_ASSIGN(GlobalGCInfoTable); 110 }; 111 112 } // namespace internal 113 } // namespace cppgc 114 115 #endif // V8_HEAP_CPPGC_GC_INFO_TABLE_H_ 116