|  | // Copyright 2020 the V8 project authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef V8_HEAP_CPPGC_GC_INFO_TABLE_H_ | 
|  | #define V8_HEAP_CPPGC_GC_INFO_TABLE_H_ | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include "include/cppgc/internal/gc-info.h" | 
|  | #include "include/cppgc/platform.h" | 
|  | #include "include/v8config.h" | 
|  | #include "src/base/logging.h" | 
|  | #include "src/base/macros.h" | 
|  | #include "src/base/platform/mutex.h" | 
|  | #include "src/base/platform/platform.h" | 
|  |  | 
|  | namespace cppgc { | 
|  | namespace internal { | 
|  |  | 
|  | // GCInfo contains metadata for objects that are instantiated from classes that | 
|  | // inherit from GarbageCollected. | 
|  | struct GCInfo final { | 
|  | FinalizationCallback finalize; | 
|  | TraceCallback trace; | 
|  | NameCallback name; | 
|  | bool has_v_table; | 
|  | }; | 
|  |  | 
|  | class V8_EXPORT GCInfoTable final { | 
|  | public: | 
|  | // At maximum |kMaxIndex - 1| indices are supported. | 
|  | // | 
|  | // We assume that 14 bits are enough to represent all possible types. | 
|  | // | 
|  | // For Blink during telemetry runs, we see about 1,000 different types; | 
|  | // looking at the output of the Oilpan GC clang plugin, there appear to be at | 
|  | // most about 6,000 types. Thus 14 bits should be more than twice as many bits | 
|  | // as we will ever need. Different contexts may require adjusting this limit. | 
|  | static constexpr GCInfoIndex kMaxIndex = 1 << 14; | 
|  |  | 
|  | // Minimum index returned. Values smaller |kMinIndex| may be used as | 
|  | // sentinels. | 
|  | static constexpr GCInfoIndex kMinIndex = 1; | 
|  |  | 
|  | // (Light) experimentation suggests that Blink doesn't need more than this | 
|  | // while handling content on popular web properties. | 
|  | static constexpr GCInfoIndex kInitialWantedLimit = 512; | 
|  |  | 
|  | // Refer through GlobalGCInfoTable for retrieving the global table outside | 
|  | // of testing code. | 
|  | explicit GCInfoTable(PageAllocator* page_allocator); | 
|  | ~GCInfoTable(); | 
|  |  | 
|  | GCInfoIndex RegisterNewGCInfo(const GCInfo& info); | 
|  |  | 
|  | const GCInfo& GCInfoFromIndex(GCInfoIndex index) const { | 
|  | DCHECK_GE(index, kMinIndex); | 
|  | DCHECK_LT(index, kMaxIndex); | 
|  | DCHECK(table_); | 
|  | return table_[index]; | 
|  | } | 
|  |  | 
|  | GCInfoIndex NumberOfGCInfosForTesting() const { return current_index_; } | 
|  | GCInfoIndex LimitForTesting() const { return limit_; } | 
|  | GCInfo& TableSlotForTesting(GCInfoIndex index) { return table_[index]; } | 
|  |  | 
|  | private: | 
|  | void Resize(); | 
|  |  | 
|  | GCInfoIndex InitialTableLimit() const; | 
|  | size_t MaxTableSize() const; | 
|  |  | 
|  | void CheckMemoryIsZeroed(uintptr_t* base, size_t len); | 
|  |  | 
|  | PageAllocator* page_allocator_; | 
|  | // Holds the per-class GCInfo descriptors; each HeapObjectHeader keeps an | 
|  | // index into this table. | 
|  | GCInfo* table_; | 
|  | uint8_t* read_only_table_end_; | 
|  | // Current index used when requiring a new GCInfo object. | 
|  | GCInfoIndex current_index_ = kMinIndex; | 
|  | // The limit (exclusive) of the currently allocated table. | 
|  | GCInfoIndex limit_ = 0; | 
|  |  | 
|  | v8::base::Mutex table_mutex_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(GCInfoTable); | 
|  | }; | 
|  |  | 
|  | class V8_EXPORT GlobalGCInfoTable final { | 
|  | public: | 
|  | // Sets up a singleton table that can be acquired using Get(). | 
|  | static void Create(PageAllocator* page_allocator); | 
|  |  | 
|  | // Accessors for the singleton table. | 
|  | static GCInfoTable& GetMutable() { return *global_table_; } | 
|  | static const GCInfoTable& Get() { return *global_table_; } | 
|  |  | 
|  | static const GCInfo& GCInfoFromIndex(GCInfoIndex index) { | 
|  | return Get().GCInfoFromIndex(index); | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Singleton for each process. Retrieved through Get(). | 
|  | static GCInfoTable* global_table_; | 
|  |  | 
|  | DISALLOW_NEW_AND_DELETE() | 
|  | DISALLOW_COPY_AND_ASSIGN(GlobalGCInfoTable); | 
|  | }; | 
|  |  | 
|  | }  // namespace internal | 
|  | }  // namespace cppgc | 
|  |  | 
|  | #endif  // V8_HEAP_CPPGC_GC_INFO_TABLE_H_ |