11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_HEAP_CPPGC_GC_INFO_TABLE_H_
61cb0ef41Sopenharmony_ci#define V8_HEAP_CPPGC_GC_INFO_TABLE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <stdint.h>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "include/cppgc/internal/gc-info.h"
111cb0ef41Sopenharmony_ci#include "include/cppgc/platform.h"
121cb0ef41Sopenharmony_ci#include "include/v8config.h"
131cb0ef41Sopenharmony_ci#include "src/base/logging.h"
141cb0ef41Sopenharmony_ci#include "src/base/macros.h"
151cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h"
161cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace cppgc {
191cb0ef41Sopenharmony_cinamespace internal {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci// GCInfo contains metadata for objects that are instantiated from classes that
221cb0ef41Sopenharmony_ci// inherit from GarbageCollected.
231cb0ef41Sopenharmony_cistruct GCInfo final {
241cb0ef41Sopenharmony_ci  FinalizationCallback finalize;
251cb0ef41Sopenharmony_ci  TraceCallback trace;
261cb0ef41Sopenharmony_ci  NameCallback name;
271cb0ef41Sopenharmony_ci  bool has_v_table;
281cb0ef41Sopenharmony_ci};
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciclass V8_EXPORT GCInfoTable final {
311cb0ef41Sopenharmony_ci public:
321cb0ef41Sopenharmony_ci  // At maximum |kMaxIndex - 1| indices are supported.
331cb0ef41Sopenharmony_ci  //
341cb0ef41Sopenharmony_ci  // We assume that 14 bits are enough to represent all possible types.
351cb0ef41Sopenharmony_ci  //
361cb0ef41Sopenharmony_ci  // For Blink during telemetry runs, we see about 1,000 different types;
371cb0ef41Sopenharmony_ci  // looking at the output of the Oilpan GC clang plugin, there appear to be at
381cb0ef41Sopenharmony_ci  // most about 6,000 types. Thus 14 bits should be more than twice as many bits
391cb0ef41Sopenharmony_ci  // as we will ever need. Different contexts may require adjusting this limit.
401cb0ef41Sopenharmony_ci  static constexpr GCInfoIndex kMaxIndex = 1 << 14;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  // Minimum index returned. Values smaller |kMinIndex| may be used as
431cb0ef41Sopenharmony_ci  // sentinels.
441cb0ef41Sopenharmony_ci  static constexpr GCInfoIndex kMinIndex = 1;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  // (Light) experimentation suggests that Blink doesn't need more than this
471cb0ef41Sopenharmony_ci  // while handling content on popular web properties.
481cb0ef41Sopenharmony_ci  static constexpr GCInfoIndex kInitialWantedLimit = 512;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  // Refer through GlobalGCInfoTable for retrieving the global table outside
511cb0ef41Sopenharmony_ci  // of testing code.
521cb0ef41Sopenharmony_ci  explicit GCInfoTable(PageAllocator* page_allocator);
531cb0ef41Sopenharmony_ci  ~GCInfoTable();
541cb0ef41Sopenharmony_ci  GCInfoTable(const GCInfoTable&) = delete;
551cb0ef41Sopenharmony_ci  GCInfoTable& operator=(const GCInfoTable&) = delete;
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  GCInfoIndex RegisterNewGCInfo(std::atomic<uint16_t>&, const GCInfo& info);
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  const GCInfo& GCInfoFromIndex(GCInfoIndex index) const {
601cb0ef41Sopenharmony_ci    DCHECK_GE(index, kMinIndex);
611cb0ef41Sopenharmony_ci    DCHECK_LT(index, kMaxIndex);
621cb0ef41Sopenharmony_ci    DCHECK(table_);
631cb0ef41Sopenharmony_ci    return table_[index];
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  GCInfoIndex NumberOfGCInfos() const { return current_index_; }
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  GCInfoIndex LimitForTesting() const { return limit_; }
691cb0ef41Sopenharmony_ci  GCInfo& TableSlotForTesting(GCInfoIndex index) { return table_[index]; }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  PageAllocator* allocator() const { return page_allocator_; }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci private:
741cb0ef41Sopenharmony_ci  void Resize();
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  GCInfoIndex InitialTableLimit() const;
771cb0ef41Sopenharmony_ci  size_t MaxTableSize() const;
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  void CheckMemoryIsZeroed(uintptr_t* base, size_t len);
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  PageAllocator* page_allocator_;
821cb0ef41Sopenharmony_ci  // Holds the per-class GCInfo descriptors; each HeapObjectHeader keeps an
831cb0ef41Sopenharmony_ci  // index into this table.
841cb0ef41Sopenharmony_ci  GCInfo* table_;
851cb0ef41Sopenharmony_ci  uint8_t* read_only_table_end_;
861cb0ef41Sopenharmony_ci  // Current index used when requiring a new GCInfo object.
871cb0ef41Sopenharmony_ci  GCInfoIndex current_index_ = kMinIndex;
881cb0ef41Sopenharmony_ci  // The limit (exclusive) of the currently allocated table.
891cb0ef41Sopenharmony_ci  GCInfoIndex limit_ = 0;
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  v8::base::Mutex table_mutex_;
921cb0ef41Sopenharmony_ci};
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ciclass V8_EXPORT GlobalGCInfoTable final {
951cb0ef41Sopenharmony_ci public:
961cb0ef41Sopenharmony_ci  GlobalGCInfoTable(const GlobalGCInfoTable&) = delete;
971cb0ef41Sopenharmony_ci  GlobalGCInfoTable& operator=(const GlobalGCInfoTable&) = delete;
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  // Sets up the table with the provided `page_allocator`. Will use an internal
1001cb0ef41Sopenharmony_ci  // allocator in case no PageAllocator is provided. May be called multiple
1011cb0ef41Sopenharmony_ci  // times with the same `page_allocator` argument.
1021cb0ef41Sopenharmony_ci  static void Initialize(PageAllocator* page_allocator);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  // Accessors for the singleton table.
1051cb0ef41Sopenharmony_ci  static GCInfoTable& GetMutable() { return *global_table_; }
1061cb0ef41Sopenharmony_ci  static const GCInfoTable& Get() { return *global_table_; }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  static const GCInfo& GCInfoFromIndex(GCInfoIndex index) {
1091cb0ef41Sopenharmony_ci    return Get().GCInfoFromIndex(index);
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci private:
1131cb0ef41Sopenharmony_ci  // Singleton for each process. Retrieved through Get().
1141cb0ef41Sopenharmony_ci  static GCInfoTable* global_table_;
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  DISALLOW_NEW_AND_DELETE()
1171cb0ef41Sopenharmony_ci};
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci}  // namespace internal
1201cb0ef41Sopenharmony_ci}  // namespace cppgc
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci#endif  // V8_HEAP_CPPGC_GC_INFO_TABLE_H_
123