11cb0ef41Sopenharmony_ci// Copyright 2009 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#include "src/handles/global-handles.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <algorithm>
81cb0ef41Sopenharmony_ci#include <atomic>
91cb0ef41Sopenharmony_ci#include <climits>
101cb0ef41Sopenharmony_ci#include <cstdint>
111cb0ef41Sopenharmony_ci#include <map>
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci#include "include/v8-traced-handle.h"
141cb0ef41Sopenharmony_ci#include "src/api/api-inl.h"
151cb0ef41Sopenharmony_ci#include "src/base/bits.h"
161cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h"
171cb0ef41Sopenharmony_ci#include "src/base/sanitizer/asan.h"
181cb0ef41Sopenharmony_ci#include "src/common/allow-deprecated.h"
191cb0ef41Sopenharmony_ci#include "src/common/globals.h"
201cb0ef41Sopenharmony_ci#include "src/execution/vm-state-inl.h"
211cb0ef41Sopenharmony_ci#include "src/heap/base/stack.h"
221cb0ef41Sopenharmony_ci#include "src/heap/embedder-tracing.h"
231cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h"
241cb0ef41Sopenharmony_ci#include "src/heap/heap-write-barrier-inl.h"
251cb0ef41Sopenharmony_ci#include "src/heap/heap-write-barrier.h"
261cb0ef41Sopenharmony_ci#include "src/init/v8.h"
271cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
281cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
291cb0ef41Sopenharmony_ci#include "src/objects/slots.h"
301cb0ef41Sopenharmony_ci#include "src/objects/visitors.h"
311cb0ef41Sopenharmony_ci#include "src/tasks/cancelable-task.h"
321cb0ef41Sopenharmony_ci#include "src/tasks/task-utils.h"
331cb0ef41Sopenharmony_ci#include "src/utils/utils.h"
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cinamespace v8 {
361cb0ef41Sopenharmony_cinamespace internal {
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cinamespace {
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciconstexpr size_t kBlockSize = 256;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci}  // namespace
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_citemplate <class _NodeType>
451cb0ef41Sopenharmony_ciclass GlobalHandles::NodeBlock final {
461cb0ef41Sopenharmony_ci public:
471cb0ef41Sopenharmony_ci  using BlockType = NodeBlock<_NodeType>;
481cb0ef41Sopenharmony_ci  using NodeType = _NodeType;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  V8_INLINE static const NodeBlock* From(const NodeType* node);
511cb0ef41Sopenharmony_ci  V8_INLINE static NodeBlock* From(NodeType* node);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  NodeBlock(GlobalHandles* global_handles,
541cb0ef41Sopenharmony_ci            GlobalHandles::NodeSpace<NodeType>* space,
551cb0ef41Sopenharmony_ci            NodeBlock* next) V8_NOEXCEPT : next_(next),
561cb0ef41Sopenharmony_ci                                           global_handles_(global_handles),
571cb0ef41Sopenharmony_ci                                           space_(space) {}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  NodeBlock(const NodeBlock&) = delete;
601cb0ef41Sopenharmony_ci  NodeBlock& operator=(const NodeBlock&) = delete;
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  NodeType* at(size_t index) { return &nodes_[index]; }
631cb0ef41Sopenharmony_ci  const NodeType* at(size_t index) const { return &nodes_[index]; }
641cb0ef41Sopenharmony_ci  GlobalHandles::NodeSpace<NodeType>* space() const { return space_; }
651cb0ef41Sopenharmony_ci  GlobalHandles* global_handles() const { return global_handles_; }
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  V8_INLINE bool IncreaseUsage();
681cb0ef41Sopenharmony_ci  V8_INLINE bool DecreaseUsage();
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  V8_INLINE void ListAdd(NodeBlock** top);
711cb0ef41Sopenharmony_ci  V8_INLINE void ListRemove(NodeBlock** top);
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  NodeBlock* next() const { return next_; }
741cb0ef41Sopenharmony_ci  NodeBlock* next_used() const { return next_used_; }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  void set_markbit(size_t index) {
771cb0ef41Sopenharmony_ci    const auto [cell, bit] = CellAndBit(index);
781cb0ef41Sopenharmony_ci    reinterpret_cast<std::atomic<CellType>&>(mark_bits_[cell])
791cb0ef41Sopenharmony_ci        .fetch_or(CellType{1} << bit, std::memory_order_relaxed);
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  void clear_markbit(size_t index) {
831cb0ef41Sopenharmony_ci    const auto [cell, bit] = CellAndBit(index);
841cb0ef41Sopenharmony_ci    mark_bits_[cell] &= ~(CellType{1} << bit);
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  bool markbit(size_t index) const {
881cb0ef41Sopenharmony_ci    const auto [cell, bit] = CellAndBit(index);
891cb0ef41Sopenharmony_ci    return mark_bits_[cell] & CellType{1} << bit;
901cb0ef41Sopenharmony_ci  }
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci private:
931cb0ef41Sopenharmony_ci  using CellType = uint32_t;
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  std::tuple<CellType, CellType> CellAndBit(size_t index) const {
961cb0ef41Sopenharmony_ci    static constexpr CellType kMarkBitCellSizeLog2 = 5;
971cb0ef41Sopenharmony_ci    static_assert(base::bits::IsPowerOfTwo(kBlockSize),
981cb0ef41Sopenharmony_ci                  "Block size must be power of two.");
991cb0ef41Sopenharmony_ci    static_assert(
1001cb0ef41Sopenharmony_ci        sizeof(CellType) * CHAR_BIT == (CellType{1} << kMarkBitCellSizeLog2),
1011cb0ef41Sopenharmony_ci        "Markbit CellType not matching defined log2 size.");
1021cb0ef41Sopenharmony_ci    static constexpr CellType kCellMask =
1031cb0ef41Sopenharmony_ci        (CellType{1} << kMarkBitCellSizeLog2) - 1;
1041cb0ef41Sopenharmony_ci    return {static_cast<CellType>(index >> kMarkBitCellSizeLog2),
1051cb0ef41Sopenharmony_ci            index & kCellMask};
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  NodeType nodes_[kBlockSize];
1091cb0ef41Sopenharmony_ci  NodeBlock* const next_;
1101cb0ef41Sopenharmony_ci  GlobalHandles* const global_handles_;
1111cb0ef41Sopenharmony_ci  GlobalHandles::NodeSpace<NodeType>* const space_;
1121cb0ef41Sopenharmony_ci  NodeBlock* next_used_ = nullptr;
1131cb0ef41Sopenharmony_ci  NodeBlock* prev_used_ = nullptr;
1141cb0ef41Sopenharmony_ci  uint32_t used_nodes_ = 0;
1151cb0ef41Sopenharmony_ci  CellType mark_bits_[kBlockSize / (sizeof(CellType) * CHAR_BIT)] = {0};
1161cb0ef41Sopenharmony_ci};
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_citemplate <class NodeType>
1191cb0ef41Sopenharmony_ciconst GlobalHandles::NodeBlock<NodeType>*
1201cb0ef41Sopenharmony_ciGlobalHandles::NodeBlock<NodeType>::From(const NodeType* node) {
1211cb0ef41Sopenharmony_ci  const NodeType* firstNode = node - node->index();
1221cb0ef41Sopenharmony_ci  const BlockType* block = reinterpret_cast<const BlockType*>(firstNode);
1231cb0ef41Sopenharmony_ci  DCHECK_EQ(node, block->at(node->index()));
1241cb0ef41Sopenharmony_ci  return block;
1251cb0ef41Sopenharmony_ci}
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_citemplate <class NodeType>
1281cb0ef41Sopenharmony_ciGlobalHandles::NodeBlock<NodeType>* GlobalHandles::NodeBlock<NodeType>::From(
1291cb0ef41Sopenharmony_ci    NodeType* node) {
1301cb0ef41Sopenharmony_ci  NodeType* firstNode = node - node->index();
1311cb0ef41Sopenharmony_ci  BlockType* block = reinterpret_cast<BlockType*>(firstNode);
1321cb0ef41Sopenharmony_ci  DCHECK_EQ(node, block->at(node->index()));
1331cb0ef41Sopenharmony_ci  return block;
1341cb0ef41Sopenharmony_ci}
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_citemplate <class NodeType>
1371cb0ef41Sopenharmony_cibool GlobalHandles::NodeBlock<NodeType>::IncreaseUsage() {
1381cb0ef41Sopenharmony_ci  DCHECK_LT(used_nodes_, kBlockSize);
1391cb0ef41Sopenharmony_ci  return used_nodes_++ == 0;
1401cb0ef41Sopenharmony_ci}
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_citemplate <class NodeType>
1431cb0ef41Sopenharmony_civoid GlobalHandles::NodeBlock<NodeType>::ListAdd(BlockType** top) {
1441cb0ef41Sopenharmony_ci  BlockType* old_top = *top;
1451cb0ef41Sopenharmony_ci  *top = this;
1461cb0ef41Sopenharmony_ci  next_used_ = old_top;
1471cb0ef41Sopenharmony_ci  prev_used_ = nullptr;
1481cb0ef41Sopenharmony_ci  if (old_top != nullptr) {
1491cb0ef41Sopenharmony_ci    old_top->prev_used_ = this;
1501cb0ef41Sopenharmony_ci  }
1511cb0ef41Sopenharmony_ci}
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_citemplate <class NodeType>
1541cb0ef41Sopenharmony_cibool GlobalHandles::NodeBlock<NodeType>::DecreaseUsage() {
1551cb0ef41Sopenharmony_ci  DCHECK_GT(used_nodes_, 0);
1561cb0ef41Sopenharmony_ci  return --used_nodes_ == 0;
1571cb0ef41Sopenharmony_ci}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_citemplate <class NodeType>
1601cb0ef41Sopenharmony_civoid GlobalHandles::NodeBlock<NodeType>::ListRemove(BlockType** top) {
1611cb0ef41Sopenharmony_ci  if (next_used_ != nullptr) next_used_->prev_used_ = prev_used_;
1621cb0ef41Sopenharmony_ci  if (prev_used_ != nullptr) prev_used_->next_used_ = next_used_;
1631cb0ef41Sopenharmony_ci  if (this == *top) {
1641cb0ef41Sopenharmony_ci    *top = next_used_;
1651cb0ef41Sopenharmony_ci  }
1661cb0ef41Sopenharmony_ci}
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_citemplate <class BlockType>
1691cb0ef41Sopenharmony_ciclass GlobalHandles::NodeIterator final {
1701cb0ef41Sopenharmony_ci public:
1711cb0ef41Sopenharmony_ci  using NodeType = typename BlockType::NodeType;
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  // Iterator traits.
1741cb0ef41Sopenharmony_ci  using iterator_category = std::forward_iterator_tag;
1751cb0ef41Sopenharmony_ci  using difference_type = std::ptrdiff_t;
1761cb0ef41Sopenharmony_ci  using value_type = NodeType*;
1771cb0ef41Sopenharmony_ci  using reference = value_type;
1781cb0ef41Sopenharmony_ci  using pointer = value_type*;
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  explicit NodeIterator(BlockType* block) V8_NOEXCEPT : block_(block) {}
1811cb0ef41Sopenharmony_ci  NodeIterator(NodeIterator&& other) V8_NOEXCEPT : block_(other.block_),
1821cb0ef41Sopenharmony_ci                                                   index_(other.index_) {}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  NodeIterator(const NodeIterator&) = delete;
1851cb0ef41Sopenharmony_ci  NodeIterator& operator=(const NodeIterator&) = delete;
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  bool operator==(const NodeIterator& other) const {
1881cb0ef41Sopenharmony_ci    return block_ == other.block_;
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci  bool operator!=(const NodeIterator& other) const {
1911cb0ef41Sopenharmony_ci    return block_ != other.block_;
1921cb0ef41Sopenharmony_ci  }
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  NodeIterator& operator++() {
1951cb0ef41Sopenharmony_ci    if (++index_ < kBlockSize) return *this;
1961cb0ef41Sopenharmony_ci    index_ = 0;
1971cb0ef41Sopenharmony_ci    block_ = block_->next_used();
1981cb0ef41Sopenharmony_ci    return *this;
1991cb0ef41Sopenharmony_ci  }
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci  NodeType* operator*() { return block_->at(index_); }
2021cb0ef41Sopenharmony_ci  NodeType* operator->() { return block_->at(index_); }
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci private:
2051cb0ef41Sopenharmony_ci  BlockType* block_ = nullptr;
2061cb0ef41Sopenharmony_ci  size_t index_ = 0;
2071cb0ef41Sopenharmony_ci};
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_citemplate <class NodeType>
2101cb0ef41Sopenharmony_ciclass GlobalHandles::NodeSpace final {
2111cb0ef41Sopenharmony_ci public:
2121cb0ef41Sopenharmony_ci  using BlockType = NodeBlock<NodeType>;
2131cb0ef41Sopenharmony_ci  using iterator = NodeIterator<BlockType>;
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  static NodeSpace* From(NodeType* node);
2161cb0ef41Sopenharmony_ci  static void Release(NodeType* node);
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  explicit NodeSpace(GlobalHandles* global_handles) V8_NOEXCEPT
2191cb0ef41Sopenharmony_ci      : global_handles_(global_handles) {}
2201cb0ef41Sopenharmony_ci  ~NodeSpace();
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  V8_INLINE NodeType* Acquire(Object object);
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  iterator begin() { return iterator(first_used_block_); }
2251cb0ef41Sopenharmony_ci  iterator end() { return iterator(nullptr); }
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  size_t TotalSize() const { return blocks_ * sizeof(NodeType) * kBlockSize; }
2281cb0ef41Sopenharmony_ci  size_t handles_count() const { return handles_count_; }
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci private:
2311cb0ef41Sopenharmony_ci  void PutNodesOnFreeList(BlockType* block);
2321cb0ef41Sopenharmony_ci  V8_INLINE void Free(NodeType* node);
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  GlobalHandles* const global_handles_;
2351cb0ef41Sopenharmony_ci  BlockType* first_block_ = nullptr;
2361cb0ef41Sopenharmony_ci  BlockType* first_used_block_ = nullptr;
2371cb0ef41Sopenharmony_ci  NodeType* first_free_ = nullptr;
2381cb0ef41Sopenharmony_ci  size_t blocks_ = 0;
2391cb0ef41Sopenharmony_ci  size_t handles_count_ = 0;
2401cb0ef41Sopenharmony_ci};
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_citemplate <class NodeType>
2431cb0ef41Sopenharmony_ciGlobalHandles::NodeSpace<NodeType>::~NodeSpace() {
2441cb0ef41Sopenharmony_ci  auto* block = first_block_;
2451cb0ef41Sopenharmony_ci  while (block != nullptr) {
2461cb0ef41Sopenharmony_ci    auto* tmp = block->next();
2471cb0ef41Sopenharmony_ci    delete block;
2481cb0ef41Sopenharmony_ci    block = tmp;
2491cb0ef41Sopenharmony_ci  }
2501cb0ef41Sopenharmony_ci}
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_citemplate <class NodeType>
2531cb0ef41Sopenharmony_ciNodeType* GlobalHandles::NodeSpace<NodeType>::Acquire(Object object) {
2541cb0ef41Sopenharmony_ci  if (first_free_ == nullptr) {
2551cb0ef41Sopenharmony_ci    first_block_ = new BlockType(global_handles_, this, first_block_);
2561cb0ef41Sopenharmony_ci    blocks_++;
2571cb0ef41Sopenharmony_ci    PutNodesOnFreeList(first_block_);
2581cb0ef41Sopenharmony_ci  }
2591cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(first_free_);
2601cb0ef41Sopenharmony_ci  NodeType* node = first_free_;
2611cb0ef41Sopenharmony_ci  first_free_ = first_free_->next_free();
2621cb0ef41Sopenharmony_ci  node->Acquire(object);
2631cb0ef41Sopenharmony_ci  BlockType* block = BlockType::From(node);
2641cb0ef41Sopenharmony_ci  if (block->IncreaseUsage()) {
2651cb0ef41Sopenharmony_ci    block->ListAdd(&first_used_block_);
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci  global_handles_->isolate()->counters()->global_handles()->Increment();
2681cb0ef41Sopenharmony_ci  handles_count_++;
2691cb0ef41Sopenharmony_ci  DCHECK(node->IsInUse());
2701cb0ef41Sopenharmony_ci  return node;
2711cb0ef41Sopenharmony_ci}
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_citemplate <class NodeType>
2741cb0ef41Sopenharmony_civoid GlobalHandles::NodeSpace<NodeType>::PutNodesOnFreeList(BlockType* block) {
2751cb0ef41Sopenharmony_ci  for (int32_t i = kBlockSize - 1; i >= 0; --i) {
2761cb0ef41Sopenharmony_ci    NodeType* node = block->at(i);
2771cb0ef41Sopenharmony_ci    const uint8_t index = static_cast<uint8_t>(i);
2781cb0ef41Sopenharmony_ci    DCHECK_EQ(i, index);
2791cb0ef41Sopenharmony_ci    node->set_index(index);
2801cb0ef41Sopenharmony_ci    node->Free(first_free_);
2811cb0ef41Sopenharmony_ci    first_free_ = node;
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_citemplate <class NodeType>
2861cb0ef41Sopenharmony_civoid GlobalHandles::NodeSpace<NodeType>::Release(NodeType* node) {
2871cb0ef41Sopenharmony_ci  BlockType* block = BlockType::From(node);
2881cb0ef41Sopenharmony_ci  block->space()->Free(node);
2891cb0ef41Sopenharmony_ci}
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_citemplate <class NodeType>
2921cb0ef41Sopenharmony_civoid GlobalHandles::NodeSpace<NodeType>::Free(NodeType* node) {
2931cb0ef41Sopenharmony_ci  node->Release(first_free_);
2941cb0ef41Sopenharmony_ci  first_free_ = node;
2951cb0ef41Sopenharmony_ci  BlockType* block = BlockType::From(node);
2961cb0ef41Sopenharmony_ci  if (block->DecreaseUsage()) {
2971cb0ef41Sopenharmony_ci    block->ListRemove(&first_used_block_);
2981cb0ef41Sopenharmony_ci  }
2991cb0ef41Sopenharmony_ci  global_handles_->isolate()->counters()->global_handles()->Decrement();
3001cb0ef41Sopenharmony_ci  handles_count_--;
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_citemplate <class Child>
3041cb0ef41Sopenharmony_ciclass NodeBase {
3051cb0ef41Sopenharmony_ci public:
3061cb0ef41Sopenharmony_ci  static const Child* FromLocation(const Address* location) {
3071cb0ef41Sopenharmony_ci    return reinterpret_cast<const Child*>(location);
3081cb0ef41Sopenharmony_ci  }
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci  static Child* FromLocation(Address* location) {
3111cb0ef41Sopenharmony_ci    return reinterpret_cast<Child*>(location);
3121cb0ef41Sopenharmony_ci  }
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci  NodeBase() {
3151cb0ef41Sopenharmony_ci    DCHECK_EQ(offsetof(NodeBase, object_), 0);
3161cb0ef41Sopenharmony_ci    DCHECK_EQ(offsetof(NodeBase, class_id_), Internals::kNodeClassIdOffset);
3171cb0ef41Sopenharmony_ci    DCHECK_EQ(offsetof(NodeBase, flags_), Internals::kNodeFlagsOffset);
3181cb0ef41Sopenharmony_ci  }
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_ci#ifdef ENABLE_HANDLE_ZAPPING
3211cb0ef41Sopenharmony_ci  ~NodeBase() {
3221cb0ef41Sopenharmony_ci    ClearFields();
3231cb0ef41Sopenharmony_ci    data_.next_free = nullptr;
3241cb0ef41Sopenharmony_ci    index_ = 0;
3251cb0ef41Sopenharmony_ci  }
3261cb0ef41Sopenharmony_ci#endif
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ci  void Free(Child* free_list) {
3291cb0ef41Sopenharmony_ci    ClearFields();
3301cb0ef41Sopenharmony_ci    AsChild()->MarkAsFree();
3311cb0ef41Sopenharmony_ci    data_.next_free = free_list;
3321cb0ef41Sopenharmony_ci  }
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci  void Acquire(Object object) {
3351cb0ef41Sopenharmony_ci    DCHECK(!AsChild()->IsInUse());
3361cb0ef41Sopenharmony_ci    CheckFieldsAreCleared();
3371cb0ef41Sopenharmony_ci    reinterpret_cast<std::atomic<Address>*>(&object_)->store(
3381cb0ef41Sopenharmony_ci        object.ptr(), std::memory_order_relaxed);
3391cb0ef41Sopenharmony_ci    AsChild()->MarkAsUsed();
3401cb0ef41Sopenharmony_ci    data_.parameter = nullptr;
3411cb0ef41Sopenharmony_ci    DCHECK(AsChild()->IsInUse());
3421cb0ef41Sopenharmony_ci  }
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  void Release(Child* free_list) {
3451cb0ef41Sopenharmony_ci    DCHECK(AsChild()->IsInUse());
3461cb0ef41Sopenharmony_ci    Free(free_list);
3471cb0ef41Sopenharmony_ci    DCHECK(!AsChild()->IsInUse());
3481cb0ef41Sopenharmony_ci  }
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci  Object object() const { return Object(object_); }
3511cb0ef41Sopenharmony_ci  FullObjectSlot location() { return FullObjectSlot(&object_); }
3521cb0ef41Sopenharmony_ci  Handle<Object> handle() { return Handle<Object>(&object_); }
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  uint8_t index() const { return index_; }
3551cb0ef41Sopenharmony_ci  void set_index(uint8_t value) { index_ = value; }
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci  uint16_t wrapper_class_id() const { return class_id_; }
3581cb0ef41Sopenharmony_ci  bool has_wrapper_class_id() const {
3591cb0ef41Sopenharmony_ci    return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId;
3601cb0ef41Sopenharmony_ci  }
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  // Accessors for next free node in the free list.
3631cb0ef41Sopenharmony_ci  Child* next_free() {
3641cb0ef41Sopenharmony_ci    DCHECK(!AsChild()->IsInUse());
3651cb0ef41Sopenharmony_ci    return data_.next_free;
3661cb0ef41Sopenharmony_ci  }
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ci  void set_parameter(void* parameter) {
3691cb0ef41Sopenharmony_ci    DCHECK(AsChild()->IsInUse());
3701cb0ef41Sopenharmony_ci    data_.parameter = parameter;
3711cb0ef41Sopenharmony_ci  }
3721cb0ef41Sopenharmony_ci  void* parameter() const {
3731cb0ef41Sopenharmony_ci    DCHECK(AsChild()->IsInUse());
3741cb0ef41Sopenharmony_ci    return data_.parameter;
3751cb0ef41Sopenharmony_ci  }
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci protected:
3781cb0ef41Sopenharmony_ci  Child* AsChild() { return reinterpret_cast<Child*>(this); }
3791cb0ef41Sopenharmony_ci  const Child* AsChild() const { return reinterpret_cast<const Child*>(this); }
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci  void ClearFields() {
3821cb0ef41Sopenharmony_ci    // Zap the values for eager trapping.
3831cb0ef41Sopenharmony_ci    object_ = kGlobalHandleZapValue;
3841cb0ef41Sopenharmony_ci    class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
3851cb0ef41Sopenharmony_ci    AsChild()->ClearImplFields();
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci  void CheckFieldsAreCleared() {
3891cb0ef41Sopenharmony_ci    DCHECK_EQ(kGlobalHandleZapValue, object_);
3901cb0ef41Sopenharmony_ci    DCHECK_EQ(v8::HeapProfiler::kPersistentHandleNoClassId, class_id_);
3911cb0ef41Sopenharmony_ci    AsChild()->CheckImplFieldsAreCleared();
3921cb0ef41Sopenharmony_ci  }
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ci  // Storage for object pointer.
3951cb0ef41Sopenharmony_ci  //
3961cb0ef41Sopenharmony_ci  // Placed first to avoid offset computation. The stored data is equivalent to
3971cb0ef41Sopenharmony_ci  // an Object. It is stored as a plain Address for convenience (smallest number
3981cb0ef41Sopenharmony_ci  // of casts), and because it is a private implementation detail: the public
3991cb0ef41Sopenharmony_ci  // interface provides type safety.
4001cb0ef41Sopenharmony_ci  Address object_;
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  // Class id set by the embedder.
4031cb0ef41Sopenharmony_ci  uint16_t class_id_;
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci  // Index in the containing handle block.
4061cb0ef41Sopenharmony_ci  uint8_t index_;
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci  uint8_t flags_;
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ci  // The meaning of this field depends on node state:
4111cb0ef41Sopenharmony_ci  // - Node in free list: Stores next free node pointer.
4121cb0ef41Sopenharmony_ci  // - Otherwise, specific to the node implementation.
4131cb0ef41Sopenharmony_ci  union {
4141cb0ef41Sopenharmony_ci    Child* next_free;
4151cb0ef41Sopenharmony_ci    void* parameter;
4161cb0ef41Sopenharmony_ci  } data_;
4171cb0ef41Sopenharmony_ci};
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_cinamespace {
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_civoid ExtractInternalFields(JSObject jsobject, void** embedder_fields, int len) {
4221cb0ef41Sopenharmony_ci  int field_count = jsobject.GetEmbedderFieldCount();
4231cb0ef41Sopenharmony_ci  Isolate* isolate = GetIsolateForSandbox(jsobject);
4241cb0ef41Sopenharmony_ci  for (int i = 0; i < len; ++i) {
4251cb0ef41Sopenharmony_ci    if (field_count == i) break;
4261cb0ef41Sopenharmony_ci    void* pointer;
4271cb0ef41Sopenharmony_ci    if (EmbedderDataSlot(jsobject, i).ToAlignedPointer(isolate, &pointer)) {
4281cb0ef41Sopenharmony_ci      embedder_fields[i] = pointer;
4291cb0ef41Sopenharmony_ci    }
4301cb0ef41Sopenharmony_ci  }
4311cb0ef41Sopenharmony_ci}
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci}  // namespace
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ciclass GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
4361cb0ef41Sopenharmony_ci public:
4371cb0ef41Sopenharmony_ci  // State transition diagram:
4381cb0ef41Sopenharmony_ci  // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE }
4391cb0ef41Sopenharmony_ci  enum State {
4401cb0ef41Sopenharmony_ci    FREE = 0,
4411cb0ef41Sopenharmony_ci    NORMAL,      // Normal global handle.
4421cb0ef41Sopenharmony_ci    WEAK,        // Flagged as weak but not yet finalized.
4431cb0ef41Sopenharmony_ci    PENDING,     // Has been recognized as only reachable by weak handles.
4441cb0ef41Sopenharmony_ci    NEAR_DEATH,  // Callback has informed the handle is near death.
4451cb0ef41Sopenharmony_ci    NUMBER_OF_NODE_STATES
4461cb0ef41Sopenharmony_ci  };
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  Node() {
4491cb0ef41Sopenharmony_ci    STATIC_ASSERT(static_cast<int>(NodeState::kMask) ==
4501cb0ef41Sopenharmony_ci                  Internals::kNodeStateMask);
4511cb0ef41Sopenharmony_ci    STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue);
4521cb0ef41Sopenharmony_ci    STATIC_ASSERT(PENDING == Internals::kNodeStateIsPendingValue);
4531cb0ef41Sopenharmony_ci    set_in_young_list(false);
4541cb0ef41Sopenharmony_ci  }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  Node(const Node&) = delete;
4571cb0ef41Sopenharmony_ci  Node& operator=(const Node&) = delete;
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  const char* label() const {
4601cb0ef41Sopenharmony_ci    return state() == NORMAL ? reinterpret_cast<char*>(data_.parameter)
4611cb0ef41Sopenharmony_ci                             : nullptr;
4621cb0ef41Sopenharmony_ci  }
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci  // State and flag accessors.
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci  State state() const { return NodeState::decode(flags_); }
4671cb0ef41Sopenharmony_ci  void set_state(State state) { flags_ = NodeState::update(flags_, state); }
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci  bool is_in_young_list() const { return IsInYoungList::decode(flags_); }
4701cb0ef41Sopenharmony_ci  void set_in_young_list(bool v) { flags_ = IsInYoungList::update(flags_, v); }
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  WeaknessType weakness_type() const {
4731cb0ef41Sopenharmony_ci    return NodeWeaknessType::decode(flags_);
4741cb0ef41Sopenharmony_ci  }
4751cb0ef41Sopenharmony_ci  void set_weakness_type(WeaknessType weakness_type) {
4761cb0ef41Sopenharmony_ci    flags_ = NodeWeaknessType::update(flags_, weakness_type);
4771cb0ef41Sopenharmony_ci  }
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  bool IsWeak() const { return state() == WEAK; }
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci  bool IsInUse() const { return state() != FREE; }
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci  bool IsPhantomCallback() const {
4841cb0ef41Sopenharmony_ci    return weakness_type() == PHANTOM_WEAK ||
4851cb0ef41Sopenharmony_ci           weakness_type() == PHANTOM_WEAK_2_EMBEDDER_FIELDS;
4861cb0ef41Sopenharmony_ci  }
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci  bool IsPhantomResetHandle() const {
4891cb0ef41Sopenharmony_ci    return weakness_type() == PHANTOM_WEAK_RESET_HANDLE;
4901cb0ef41Sopenharmony_ci  }
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci  bool IsFinalizerHandle() const { return weakness_type() == FINALIZER_WEAK; }
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci  bool IsPendingPhantomCallback() const {
4951cb0ef41Sopenharmony_ci    return state() == PENDING && IsPhantomCallback();
4961cb0ef41Sopenharmony_ci  }
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci  bool IsPendingPhantomResetHandle() const {
4991cb0ef41Sopenharmony_ci    return state() == PENDING && IsPhantomResetHandle();
5001cb0ef41Sopenharmony_ci  }
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci  bool IsPendingFinalizer() const {
5031cb0ef41Sopenharmony_ci    return state() == PENDING && weakness_type() == FINALIZER_WEAK;
5041cb0ef41Sopenharmony_ci  }
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci  bool IsPending() const { return state() == PENDING; }
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci  bool IsRetainer() const {
5091cb0ef41Sopenharmony_ci    return state() != FREE &&
5101cb0ef41Sopenharmony_ci           !(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK);
5111cb0ef41Sopenharmony_ci  }
5121cb0ef41Sopenharmony_ci
5131cb0ef41Sopenharmony_ci  bool IsStrongRetainer() const { return state() == NORMAL; }
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  bool IsWeakRetainer() const {
5161cb0ef41Sopenharmony_ci    return state() == WEAK || state() == PENDING ||
5171cb0ef41Sopenharmony_ci           (state() == NEAR_DEATH && weakness_type() == FINALIZER_WEAK);
5181cb0ef41Sopenharmony_ci  }
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ci  void MarkPending() {
5211cb0ef41Sopenharmony_ci    DCHECK(state() == WEAK);
5221cb0ef41Sopenharmony_ci    set_state(PENDING);
5231cb0ef41Sopenharmony_ci  }
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci  bool has_callback() const { return weak_callback_ != nullptr; }
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ci  // Accessors for next free node in the free list.
5281cb0ef41Sopenharmony_ci  Node* next_free() {
5291cb0ef41Sopenharmony_ci    DCHECK_EQ(FREE, state());
5301cb0ef41Sopenharmony_ci    return data_.next_free;
5311cb0ef41Sopenharmony_ci  }
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci  void MakeWeak(void* parameter,
5341cb0ef41Sopenharmony_ci                WeakCallbackInfo<void>::Callback phantom_callback,
5351cb0ef41Sopenharmony_ci                v8::WeakCallbackType type) {
5361cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(phantom_callback);
5371cb0ef41Sopenharmony_ci    DCHECK(IsInUse());
5381cb0ef41Sopenharmony_ci    CHECK_NE(object_, kGlobalHandleZapValue);
5391cb0ef41Sopenharmony_ci    set_state(WEAK);
5401cb0ef41Sopenharmony_ci    switch (type) {
5411cb0ef41Sopenharmony_ci      case v8::WeakCallbackType::kParameter:
5421cb0ef41Sopenharmony_ci        set_weakness_type(PHANTOM_WEAK);
5431cb0ef41Sopenharmony_ci        break;
5441cb0ef41Sopenharmony_ci      case v8::WeakCallbackType::kInternalFields:
5451cb0ef41Sopenharmony_ci        set_weakness_type(PHANTOM_WEAK_2_EMBEDDER_FIELDS);
5461cb0ef41Sopenharmony_ci        break;
5471cb0ef41Sopenharmony_ci        START_ALLOW_USE_DEPRECATED()
5481cb0ef41Sopenharmony_ci      case v8::WeakCallbackType::kFinalizer:
5491cb0ef41Sopenharmony_ci        set_weakness_type(FINALIZER_WEAK);
5501cb0ef41Sopenharmony_ci        break;
5511cb0ef41Sopenharmony_ci        END_ALLOW_USE_DEPRECATED()
5521cb0ef41Sopenharmony_ci    }
5531cb0ef41Sopenharmony_ci    set_parameter(parameter);
5541cb0ef41Sopenharmony_ci    weak_callback_ = phantom_callback;
5551cb0ef41Sopenharmony_ci  }
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci  void MakeWeak(Address** location_addr) {
5581cb0ef41Sopenharmony_ci    DCHECK(IsInUse());
5591cb0ef41Sopenharmony_ci    CHECK_NE(object_, kGlobalHandleZapValue);
5601cb0ef41Sopenharmony_ci    set_state(WEAK);
5611cb0ef41Sopenharmony_ci    set_weakness_type(PHANTOM_WEAK_RESET_HANDLE);
5621cb0ef41Sopenharmony_ci    set_parameter(location_addr);
5631cb0ef41Sopenharmony_ci    weak_callback_ = nullptr;
5641cb0ef41Sopenharmony_ci  }
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci  void* ClearWeakness() {
5671cb0ef41Sopenharmony_ci    DCHECK(IsInUse());
5681cb0ef41Sopenharmony_ci    void* p = parameter();
5691cb0ef41Sopenharmony_ci    set_state(NORMAL);
5701cb0ef41Sopenharmony_ci    set_parameter(nullptr);
5711cb0ef41Sopenharmony_ci    return p;
5721cb0ef41Sopenharmony_ci  }
5731cb0ef41Sopenharmony_ci
5741cb0ef41Sopenharmony_ci  void AnnotateStrongRetainer(const char* label) {
5751cb0ef41Sopenharmony_ci    DCHECK_EQ(state(), NORMAL);
5761cb0ef41Sopenharmony_ci    data_.parameter = const_cast<char*>(label);
5771cb0ef41Sopenharmony_ci  }
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ci  void CollectPhantomCallbackData(
5801cb0ef41Sopenharmony_ci      std::vector<std::pair<Node*, PendingPhantomCallback>>*
5811cb0ef41Sopenharmony_ci          pending_phantom_callbacks) {
5821cb0ef41Sopenharmony_ci    DCHECK(weakness_type() == PHANTOM_WEAK ||
5831cb0ef41Sopenharmony_ci           weakness_type() == PHANTOM_WEAK_2_EMBEDDER_FIELDS);
5841cb0ef41Sopenharmony_ci    DCHECK(state() == PENDING);
5851cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(weak_callback_);
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_ci    void* embedder_fields[v8::kEmbedderFieldsInWeakCallback] = {nullptr,
5881cb0ef41Sopenharmony_ci                                                                nullptr};
5891cb0ef41Sopenharmony_ci    if (weakness_type() != PHANTOM_WEAK && object().IsJSObject()) {
5901cb0ef41Sopenharmony_ci      ExtractInternalFields(JSObject::cast(object()), embedder_fields,
5911cb0ef41Sopenharmony_ci                            v8::kEmbedderFieldsInWeakCallback);
5921cb0ef41Sopenharmony_ci    }
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ci    // Zap with something dangerous.
5951cb0ef41Sopenharmony_ci    location().store(Object(0xCA11));
5961cb0ef41Sopenharmony_ci
5971cb0ef41Sopenharmony_ci    pending_phantom_callbacks->push_back(std::make_pair(
5981cb0ef41Sopenharmony_ci        this,
5991cb0ef41Sopenharmony_ci        PendingPhantomCallback(weak_callback_, parameter(), embedder_fields)));
6001cb0ef41Sopenharmony_ci    DCHECK(IsInUse());
6011cb0ef41Sopenharmony_ci    set_state(NEAR_DEATH);
6021cb0ef41Sopenharmony_ci  }
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci  void ResetPhantomHandle() {
6051cb0ef41Sopenharmony_ci    DCHECK_EQ(PHANTOM_WEAK_RESET_HANDLE, weakness_type());
6061cb0ef41Sopenharmony_ci    DCHECK_EQ(PENDING, state());
6071cb0ef41Sopenharmony_ci    DCHECK_NULL(weak_callback_);
6081cb0ef41Sopenharmony_ci    Address** handle = reinterpret_cast<Address**>(parameter());
6091cb0ef41Sopenharmony_ci    *handle = nullptr;
6101cb0ef41Sopenharmony_ci    NodeSpace<Node>::Release(this);
6111cb0ef41Sopenharmony_ci  }
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci  void PostGarbageCollectionProcessing(Isolate* isolate) {
6141cb0ef41Sopenharmony_ci    // This method invokes a finalizer. Updating the method name would require
6151cb0ef41Sopenharmony_ci    // adjusting CFI blocklist as weak_callback_ is invoked on the wrong type.
6161cb0ef41Sopenharmony_ci    CHECK(IsPendingFinalizer());
6171cb0ef41Sopenharmony_ci    set_state(NEAR_DEATH);
6181cb0ef41Sopenharmony_ci    // Check that we are not passing a finalized external string to
6191cb0ef41Sopenharmony_ci    // the callback.
6201cb0ef41Sopenharmony_ci    DCHECK(!object().IsExternalOneByteString() ||
6211cb0ef41Sopenharmony_ci           ExternalOneByteString::cast(object()).resource() != nullptr);
6221cb0ef41Sopenharmony_ci    DCHECK(!object().IsExternalTwoByteString() ||
6231cb0ef41Sopenharmony_ci           ExternalTwoByteString::cast(object()).resource() != nullptr);
6241cb0ef41Sopenharmony_ci    // Leaving V8.
6251cb0ef41Sopenharmony_ci    VMState<EXTERNAL> vmstate(isolate);
6261cb0ef41Sopenharmony_ci    HandleScope handle_scope(isolate);
6271cb0ef41Sopenharmony_ci    void* embedder_fields[v8::kEmbedderFieldsInWeakCallback] = {nullptr,
6281cb0ef41Sopenharmony_ci                                                                nullptr};
6291cb0ef41Sopenharmony_ci    v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate),
6301cb0ef41Sopenharmony_ci                                    parameter(), embedder_fields, nullptr);
6311cb0ef41Sopenharmony_ci    weak_callback_(data);
6321cb0ef41Sopenharmony_ci    // For finalizers the handle must have either been reset or made strong.
6331cb0ef41Sopenharmony_ci    // Both cases reset the state.
6341cb0ef41Sopenharmony_ci    CHECK_NE(NEAR_DEATH, state());
6351cb0ef41Sopenharmony_ci  }
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci  void MarkAsFree() { set_state(FREE); }
6381cb0ef41Sopenharmony_ci  void MarkAsUsed() { set_state(NORMAL); }
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci  GlobalHandles* global_handles() {
6411cb0ef41Sopenharmony_ci    return NodeBlock<Node>::From(this)->global_handles();
6421cb0ef41Sopenharmony_ci  }
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ci private:
6451cb0ef41Sopenharmony_ci  // Fields that are not used for managing node memory.
6461cb0ef41Sopenharmony_ci  void ClearImplFields() { weak_callback_ = nullptr; }
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci  void CheckImplFieldsAreCleared() { DCHECK_EQ(nullptr, weak_callback_); }
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ci  // This stores three flags (independent, partially_dependent and
6511cb0ef41Sopenharmony_ci  // in_young_list) and a State.
6521cb0ef41Sopenharmony_ci  using NodeState = base::BitField8<State, 0, 3>;
6531cb0ef41Sopenharmony_ci  using IsInYoungList = NodeState::Next<bool, 1>;
6541cb0ef41Sopenharmony_ci  using NodeWeaknessType = IsInYoungList::Next<WeaknessType, 2>;
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci  // Handle specific callback - might be a weak reference in disguise.
6571cb0ef41Sopenharmony_ci  WeakCallbackInfo<void>::Callback weak_callback_;
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci  friend class NodeBase<Node>;
6601cb0ef41Sopenharmony_ci};
6611cb0ef41Sopenharmony_ci
6621cb0ef41Sopenharmony_ciclass GlobalHandles::TracedNode final
6631cb0ef41Sopenharmony_ci    : public NodeBase<GlobalHandles::TracedNode> {
6641cb0ef41Sopenharmony_ci public:
6651cb0ef41Sopenharmony_ci  TracedNode() { set_in_young_list(false); }
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci  // Copy and move ctors are used when constructing a TracedNode when recording
6681cb0ef41Sopenharmony_ci  // a node for on-stack data structures. (Older compilers may refer to copy
6691cb0ef41Sopenharmony_ci  // instead of move ctor.)
6701cb0ef41Sopenharmony_ci  TracedNode(TracedNode&& other) V8_NOEXCEPT = default;
6711cb0ef41Sopenharmony_ci  TracedNode(const TracedNode& other) V8_NOEXCEPT = default;
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_ci  enum State { FREE = 0, NORMAL, NEAR_DEATH };
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci  State state() const { return NodeState::decode(flags_); }
6761cb0ef41Sopenharmony_ci  void set_state(State state) { flags_ = NodeState::update(flags_, state); }
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci  void MarkAsFree() { set_state(FREE); }
6791cb0ef41Sopenharmony_ci  void MarkAsUsed() { set_state(NORMAL); }
6801cb0ef41Sopenharmony_ci  bool IsInUse() const { return state() != FREE; }
6811cb0ef41Sopenharmony_ci  bool IsRetainer() const { return state() == NORMAL; }
6821cb0ef41Sopenharmony_ci
6831cb0ef41Sopenharmony_ci  bool is_in_young_list() const { return IsInYoungList::decode(flags_); }
6841cb0ef41Sopenharmony_ci  void set_in_young_list(bool v) { flags_ = IsInYoungList::update(flags_, v); }
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci  bool is_root() const { return IsRoot::decode(flags_); }
6871cb0ef41Sopenharmony_ci  void set_root(bool v) { flags_ = IsRoot::update(flags_, v); }
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_ci  void set_markbit() {
6901cb0ef41Sopenharmony_ci    NodeBlock<TracedNode>::From(this)->set_markbit(index());
6911cb0ef41Sopenharmony_ci  }
6921cb0ef41Sopenharmony_ci
6931cb0ef41Sopenharmony_ci  bool markbit() const {
6941cb0ef41Sopenharmony_ci    return NodeBlock<TracedNode>::From(this)->markbit(index());
6951cb0ef41Sopenharmony_ci  }
6961cb0ef41Sopenharmony_ci  void clear_markbit() {
6971cb0ef41Sopenharmony_ci    NodeBlock<TracedNode>::From(this)->clear_markbit(index());
6981cb0ef41Sopenharmony_ci  }
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_ci  bool is_on_stack() const { return IsOnStack::decode(flags_); }
7011cb0ef41Sopenharmony_ci  void set_is_on_stack(bool v) { flags_ = IsOnStack::update(flags_, v); }
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_ci  void clear_object() {
7041cb0ef41Sopenharmony_ci    reinterpret_cast<std::atomic<Address>*>(&object_)->store(
7051cb0ef41Sopenharmony_ci        kNullAddress, std::memory_order_relaxed);
7061cb0ef41Sopenharmony_ci  }
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_ci  void CopyObjectReference(const TracedNode& other) {
7091cb0ef41Sopenharmony_ci    reinterpret_cast<std::atomic<Address>*>(&object_)->store(
7101cb0ef41Sopenharmony_ci        other.object_, std::memory_order_relaxed);
7111cb0ef41Sopenharmony_ci  }
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_ci  void ResetPhantomHandle() {
7141cb0ef41Sopenharmony_ci    DCHECK(IsInUse());
7151cb0ef41Sopenharmony_ci    NodeSpace<TracedNode>::Release(this);
7161cb0ef41Sopenharmony_ci    DCHECK(!IsInUse());
7171cb0ef41Sopenharmony_ci  }
7181cb0ef41Sopenharmony_ci
7191cb0ef41Sopenharmony_ci  static void Verify(GlobalHandles* global_handles, const Address* const* slot);
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci protected:
7221cb0ef41Sopenharmony_ci  // Various state is managed in a bit field. Mark bits are used concurrently
7231cb0ef41Sopenharmony_ci  // and held externally in a NodeBlock.
7241cb0ef41Sopenharmony_ci  using NodeState = base::BitField8<State, 0, 2>;
7251cb0ef41Sopenharmony_ci  using IsInYoungList = NodeState::Next<bool, 1>;
7261cb0ef41Sopenharmony_ci  using IsRoot = IsInYoungList::Next<bool, 1>;
7271cb0ef41Sopenharmony_ci  using IsOnStack = IsRoot::Next<bool, 1>;
7281cb0ef41Sopenharmony_ci  void ClearImplFields() {
7291cb0ef41Sopenharmony_ci    set_root(true);
7301cb0ef41Sopenharmony_ci    set_is_on_stack(false);
7311cb0ef41Sopenharmony_ci  }
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_ci  void CheckImplFieldsAreCleared() const { DCHECK(is_root()); }
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci  friend class NodeBase<GlobalHandles::TracedNode>;
7361cb0ef41Sopenharmony_ci};
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci// Space to keep track of on-stack handles (e.g. TracedReference). Such
7391cb0ef41Sopenharmony_ci// references are treated as root for any V8 garbage collection. The data
7401cb0ef41Sopenharmony_ci// structure is self healing and pessimistally filters outdated entries on
7411cb0ef41Sopenharmony_ci// insertion and iteration.
7421cb0ef41Sopenharmony_ci//
7431cb0ef41Sopenharmony_ci// Design doc: http://bit.ly/on-stack-traced-reference
7441cb0ef41Sopenharmony_ciclass GlobalHandles::OnStackTracedNodeSpace final {
7451cb0ef41Sopenharmony_ci public:
7461cb0ef41Sopenharmony_ci  static GlobalHandles* GetGlobalHandles(const TracedNode* on_stack_node) {
7471cb0ef41Sopenharmony_ci    DCHECK(on_stack_node->is_on_stack());
7481cb0ef41Sopenharmony_ci    return reinterpret_cast<const NodeEntry*>(on_stack_node)->global_handles;
7491cb0ef41Sopenharmony_ci  }
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ci  explicit OnStackTracedNodeSpace(GlobalHandles* global_handles)
7521cb0ef41Sopenharmony_ci      : global_handles_(global_handles) {}
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci  void SetStackStart(void* stack_start) {
7551cb0ef41Sopenharmony_ci    CHECK(on_stack_nodes_.empty());
7561cb0ef41Sopenharmony_ci    stack_.SetStackStart(base::Stack::GetRealStackAddressForSlot(stack_start));
7571cb0ef41Sopenharmony_ci  }
7581cb0ef41Sopenharmony_ci
7591cb0ef41Sopenharmony_ci  V8_INLINE bool IsOnStack(uintptr_t slot) const;
7601cb0ef41Sopenharmony_ci
7611cb0ef41Sopenharmony_ci  void Iterate(RootVisitor* v);
7621cb0ef41Sopenharmony_ci  TracedNode* Acquire(Object value, uintptr_t address);
7631cb0ef41Sopenharmony_ci  void CleanupBelowCurrentStackPosition();
7641cb0ef41Sopenharmony_ci  void NotifyEmptyEmbedderStack();
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci  size_t NumberOfHandlesForTesting() const { return on_stack_nodes_.size(); }
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_ci private:
7691cb0ef41Sopenharmony_ci  struct NodeEntry {
7701cb0ef41Sopenharmony_ci    TracedNode node;
7711cb0ef41Sopenharmony_ci    // Used to find back to GlobalHandles from a Node on copy. Needs to follow
7721cb0ef41Sopenharmony_ci    // node.
7731cb0ef41Sopenharmony_ci    GlobalHandles* global_handles;
7741cb0ef41Sopenharmony_ci  };
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci  // Keeps track of registered handles. The data structure is cleaned on
7771cb0ef41Sopenharmony_ci  // iteration and when adding new references using the current stack address.
7781cb0ef41Sopenharmony_ci  // Cleaning is based on current stack address and the key of the map which is
7791cb0ef41Sopenharmony_ci  // slightly different for ASAN configs -- see below.
7801cb0ef41Sopenharmony_ci#ifdef V8_USE_ADDRESS_SANITIZER
7811cb0ef41Sopenharmony_ci  // Mapping from stack slots or real stack frames to the corresponding nodes.
7821cb0ef41Sopenharmony_ci  // In case a reference is part of a fake frame, we map it to the real stack
7831cb0ef41Sopenharmony_ci  // frame base instead of the actual stack slot. The list keeps all nodes for
7841cb0ef41Sopenharmony_ci  // a particular real frame.
7851cb0ef41Sopenharmony_ci  std::map<uintptr_t, std::list<NodeEntry>> on_stack_nodes_;
7861cb0ef41Sopenharmony_ci#else   // !V8_USE_ADDRESS_SANITIZER
7871cb0ef41Sopenharmony_ci  // Mapping from stack slots to the corresponding nodes. We don't expect
7881cb0ef41Sopenharmony_ci  // aliasing with overlapping lifetimes of nodes.
7891cb0ef41Sopenharmony_ci  std::map<uintptr_t, NodeEntry> on_stack_nodes_;
7901cb0ef41Sopenharmony_ci#endif  // !V8_USE_ADDRESS_SANITIZER
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci  ::heap::base::Stack stack_;
7931cb0ef41Sopenharmony_ci  GlobalHandles* global_handles_ = nullptr;
7941cb0ef41Sopenharmony_ci  size_t acquire_count_ = 0;
7951cb0ef41Sopenharmony_ci};
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_cibool GlobalHandles::OnStackTracedNodeSpace::IsOnStack(uintptr_t slot) const {
7981cb0ef41Sopenharmony_ci  // By the time this function is called, the stack start may not be set (i.e.
7991cb0ef41Sopenharmony_ci  // SetStackStart() was not called). In that case, assume the slot is not on
8001cb0ef41Sopenharmony_ci  // stack.
8011cb0ef41Sopenharmony_ci  if (!stack_.stack_start()) return false;
8021cb0ef41Sopenharmony_ci  return stack_.IsOnStack(reinterpret_cast<void*>(slot));
8031cb0ef41Sopenharmony_ci}
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_civoid GlobalHandles::OnStackTracedNodeSpace::NotifyEmptyEmbedderStack() {
8061cb0ef41Sopenharmony_ci  on_stack_nodes_.clear();
8071cb0ef41Sopenharmony_ci}
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_civoid GlobalHandles::OnStackTracedNodeSpace::Iterate(RootVisitor* v) {
8101cb0ef41Sopenharmony_ci#ifdef V8_USE_ADDRESS_SANITIZER
8111cb0ef41Sopenharmony_ci  for (auto& pair : on_stack_nodes_) {
8121cb0ef41Sopenharmony_ci    for (auto& node_entry : pair.second) {
8131cb0ef41Sopenharmony_ci      TracedNode& node = node_entry.node;
8141cb0ef41Sopenharmony_ci      if (node.IsRetainer()) {
8151cb0ef41Sopenharmony_ci        v->VisitRootPointer(Root::kGlobalHandles, "on-stack TracedReference",
8161cb0ef41Sopenharmony_ci                            node.location());
8171cb0ef41Sopenharmony_ci      }
8181cb0ef41Sopenharmony_ci    }
8191cb0ef41Sopenharmony_ci  }
8201cb0ef41Sopenharmony_ci#else   // !V8_USE_ADDRESS_SANITIZER
8211cb0ef41Sopenharmony_ci  // Handles have been cleaned from the GC entry point which is higher up the
8221cb0ef41Sopenharmony_ci  // stack.
8231cb0ef41Sopenharmony_ci  for (auto& pair : on_stack_nodes_) {
8241cb0ef41Sopenharmony_ci    TracedNode& node = pair.second.node;
8251cb0ef41Sopenharmony_ci    if (node.IsRetainer()) {
8261cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, "on-stack TracedReference",
8271cb0ef41Sopenharmony_ci                          node.location());
8281cb0ef41Sopenharmony_ci    }
8291cb0ef41Sopenharmony_ci  }
8301cb0ef41Sopenharmony_ci#endif  // !V8_USE_ADDRESS_SANITIZER
8311cb0ef41Sopenharmony_ci}
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_ciGlobalHandles::TracedNode* GlobalHandles::OnStackTracedNodeSpace::Acquire(
8341cb0ef41Sopenharmony_ci    Object value, uintptr_t slot) {
8351cb0ef41Sopenharmony_ci  constexpr size_t kAcquireCleanupThresholdLog2 = 8;
8361cb0ef41Sopenharmony_ci  constexpr size_t kAcquireCleanupThresholdMask =
8371cb0ef41Sopenharmony_ci      (size_t{1} << kAcquireCleanupThresholdLog2) - 1;
8381cb0ef41Sopenharmony_ci  DCHECK(IsOnStack(slot));
8391cb0ef41Sopenharmony_ci  if (((acquire_count_++) & kAcquireCleanupThresholdMask) == 0) {
8401cb0ef41Sopenharmony_ci    CleanupBelowCurrentStackPosition();
8411cb0ef41Sopenharmony_ci  }
8421cb0ef41Sopenharmony_ci  NodeEntry entry;
8431cb0ef41Sopenharmony_ci  entry.node.Free(nullptr);
8441cb0ef41Sopenharmony_ci  entry.global_handles = global_handles_;
8451cb0ef41Sopenharmony_ci#ifdef V8_USE_ADDRESS_SANITIZER
8461cb0ef41Sopenharmony_ci  auto pair = on_stack_nodes_.insert(
8471cb0ef41Sopenharmony_ci      {base::Stack::GetRealStackAddressForSlot(slot), {}});
8481cb0ef41Sopenharmony_ci  pair.first->second.push_back(std::move(entry));
8491cb0ef41Sopenharmony_ci  TracedNode* result = &(pair.first->second.back().node);
8501cb0ef41Sopenharmony_ci#else   // !V8_USE_ADDRESS_SANITIZER
8511cb0ef41Sopenharmony_ci  auto pair = on_stack_nodes_.insert(
8521cb0ef41Sopenharmony_ci      {base::Stack::GetRealStackAddressForSlot(slot), std::move(entry)});
8531cb0ef41Sopenharmony_ci  if (!pair.second) {
8541cb0ef41Sopenharmony_ci    // Insertion failed because there already was an entry present for that
8551cb0ef41Sopenharmony_ci    // stack address. This can happen because cleanup is conservative in which
8561cb0ef41Sopenharmony_ci    // stack limits it used. Reusing the entry is fine as there's no aliasing of
8571cb0ef41Sopenharmony_ci    // different references with the same stack slot.
8581cb0ef41Sopenharmony_ci    pair.first->second.node.Free(nullptr);
8591cb0ef41Sopenharmony_ci  }
8601cb0ef41Sopenharmony_ci  TracedNode* result = &(pair.first->second.node);
8611cb0ef41Sopenharmony_ci#endif  // !V8_USE_ADDRESS_SANITIZER
8621cb0ef41Sopenharmony_ci  result->Acquire(value);
8631cb0ef41Sopenharmony_ci  result->set_is_on_stack(true);
8641cb0ef41Sopenharmony_ci  return result;
8651cb0ef41Sopenharmony_ci}
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_civoid GlobalHandles::OnStackTracedNodeSpace::CleanupBelowCurrentStackPosition() {
8681cb0ef41Sopenharmony_ci  if (on_stack_nodes_.empty()) return;
8691cb0ef41Sopenharmony_ci  const uintptr_t stack_ptr = reinterpret_cast<uintptr_t>(
8701cb0ef41Sopenharmony_ci      ::heap::base::Stack::GetCurrentStackPointerForLocalVariables());
8711cb0ef41Sopenharmony_ci  const auto it = on_stack_nodes_.upper_bound(stack_ptr);
8721cb0ef41Sopenharmony_ci  on_stack_nodes_.erase(on_stack_nodes_.begin(), it);
8731cb0ef41Sopenharmony_ci}
8741cb0ef41Sopenharmony_ci
8751cb0ef41Sopenharmony_ci// static
8761cb0ef41Sopenharmony_civoid GlobalHandles::EnableMarkingBarrier(Isolate* isolate) {
8771cb0ef41Sopenharmony_ci  auto* global_handles = isolate->global_handles();
8781cb0ef41Sopenharmony_ci  DCHECK(!global_handles->is_marking_);
8791cb0ef41Sopenharmony_ci  global_handles->is_marking_ = true;
8801cb0ef41Sopenharmony_ci}
8811cb0ef41Sopenharmony_ci
8821cb0ef41Sopenharmony_ci// static
8831cb0ef41Sopenharmony_civoid GlobalHandles::DisableMarkingBarrier(Isolate* isolate) {
8841cb0ef41Sopenharmony_ci  auto* global_handles = isolate->global_handles();
8851cb0ef41Sopenharmony_ci  DCHECK(global_handles->is_marking_);
8861cb0ef41Sopenharmony_ci  global_handles->is_marking_ = false;
8871cb0ef41Sopenharmony_ci}
8881cb0ef41Sopenharmony_ci
8891cb0ef41Sopenharmony_ci// static
8901cb0ef41Sopenharmony_civoid GlobalHandles::TracedNode::Verify(GlobalHandles* global_handles,
8911cb0ef41Sopenharmony_ci                                       const Address* const* slot) {
8921cb0ef41Sopenharmony_ci#ifdef DEBUG
8931cb0ef41Sopenharmony_ci  const TracedNode* node = FromLocation(*slot);
8941cb0ef41Sopenharmony_ci  DCHECK(node->IsInUse());
8951cb0ef41Sopenharmony_ci  bool slot_on_stack = global_handles->on_stack_nodes_->IsOnStack(
8961cb0ef41Sopenharmony_ci      reinterpret_cast<uintptr_t>(slot));
8971cb0ef41Sopenharmony_ci  DCHECK_EQ(slot_on_stack, node->is_on_stack());
8981cb0ef41Sopenharmony_ci  if (!node->is_on_stack()) {
8991cb0ef41Sopenharmony_ci    // On-heap nodes have seprate lists for young generation processing.
9001cb0ef41Sopenharmony_ci    bool is_young_gen_object = ObjectInYoungGeneration(node->object());
9011cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(is_young_gen_object, node->is_in_young_list());
9021cb0ef41Sopenharmony_ci  }
9031cb0ef41Sopenharmony_ci  bool in_young_list =
9041cb0ef41Sopenharmony_ci      std::find(global_handles->traced_young_nodes_.begin(),
9051cb0ef41Sopenharmony_ci                global_handles->traced_young_nodes_.end(),
9061cb0ef41Sopenharmony_ci                node) != global_handles->traced_young_nodes_.end();
9071cb0ef41Sopenharmony_ci  DCHECK_EQ(in_young_list, node->is_in_young_list());
9081cb0ef41Sopenharmony_ci#endif  // DEBUG
9091cb0ef41Sopenharmony_ci}
9101cb0ef41Sopenharmony_ci
9111cb0ef41Sopenharmony_civoid GlobalHandles::CleanupOnStackReferencesBelowCurrentStackPosition() {
9121cb0ef41Sopenharmony_ci  on_stack_nodes_->CleanupBelowCurrentStackPosition();
9131cb0ef41Sopenharmony_ci}
9141cb0ef41Sopenharmony_ci
9151cb0ef41Sopenharmony_cisize_t GlobalHandles::NumberOfOnStackHandlesForTesting() {
9161cb0ef41Sopenharmony_ci  return on_stack_nodes_->NumberOfHandlesForTesting();
9171cb0ef41Sopenharmony_ci}
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_cisize_t GlobalHandles::TotalSize() const {
9201cb0ef41Sopenharmony_ci  return regular_nodes_->TotalSize() + traced_nodes_->TotalSize();
9211cb0ef41Sopenharmony_ci}
9221cb0ef41Sopenharmony_ci
9231cb0ef41Sopenharmony_cisize_t GlobalHandles::UsedSize() const {
9241cb0ef41Sopenharmony_ci  return regular_nodes_->handles_count() * sizeof(Node) +
9251cb0ef41Sopenharmony_ci         traced_nodes_->handles_count() * sizeof(TracedNode);
9261cb0ef41Sopenharmony_ci}
9271cb0ef41Sopenharmony_ci
9281cb0ef41Sopenharmony_cisize_t GlobalHandles::handles_count() const {
9291cb0ef41Sopenharmony_ci  return regular_nodes_->handles_count() + traced_nodes_->handles_count();
9301cb0ef41Sopenharmony_ci}
9311cb0ef41Sopenharmony_ci
9321cb0ef41Sopenharmony_civoid GlobalHandles::SetStackStart(void* stack_start) {
9331cb0ef41Sopenharmony_ci  on_stack_nodes_->SetStackStart(stack_start);
9341cb0ef41Sopenharmony_ci}
9351cb0ef41Sopenharmony_ci
9361cb0ef41Sopenharmony_civoid GlobalHandles::NotifyEmptyEmbedderStack() {
9371cb0ef41Sopenharmony_ci  on_stack_nodes_->NotifyEmptyEmbedderStack();
9381cb0ef41Sopenharmony_ci}
9391cb0ef41Sopenharmony_ci
9401cb0ef41Sopenharmony_ciGlobalHandles::GlobalHandles(Isolate* isolate)
9411cb0ef41Sopenharmony_ci    : isolate_(isolate),
9421cb0ef41Sopenharmony_ci      regular_nodes_(new NodeSpace<GlobalHandles::Node>(this)),
9431cb0ef41Sopenharmony_ci      traced_nodes_(new NodeSpace<GlobalHandles::TracedNode>(this)),
9441cb0ef41Sopenharmony_ci      on_stack_nodes_(new OnStackTracedNodeSpace(this)) {}
9451cb0ef41Sopenharmony_ci
9461cb0ef41Sopenharmony_ciGlobalHandles::~GlobalHandles() { regular_nodes_.reset(nullptr); }
9471cb0ef41Sopenharmony_ci
9481cb0ef41Sopenharmony_ciHandle<Object> GlobalHandles::Create(Object value) {
9491cb0ef41Sopenharmony_ci  GlobalHandles::Node* result = regular_nodes_->Acquire(value);
9501cb0ef41Sopenharmony_ci  if (ObjectInYoungGeneration(value) && !result->is_in_young_list()) {
9511cb0ef41Sopenharmony_ci    young_nodes_.push_back(result);
9521cb0ef41Sopenharmony_ci    result->set_in_young_list(true);
9531cb0ef41Sopenharmony_ci  }
9541cb0ef41Sopenharmony_ci  return result->handle();
9551cb0ef41Sopenharmony_ci}
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_ciHandle<Object> GlobalHandles::Create(Address value) {
9581cb0ef41Sopenharmony_ci  return Create(Object(value));
9591cb0ef41Sopenharmony_ci}
9601cb0ef41Sopenharmony_ci
9611cb0ef41Sopenharmony_ciHandle<Object> GlobalHandles::CreateTraced(Object value, Address* slot,
9621cb0ef41Sopenharmony_ci                                           GlobalHandleStoreMode store_mode) {
9631cb0ef41Sopenharmony_ci  return CreateTraced(
9641cb0ef41Sopenharmony_ci      value, slot, store_mode,
9651cb0ef41Sopenharmony_ci      on_stack_nodes_->IsOnStack(reinterpret_cast<uintptr_t>(slot)));
9661cb0ef41Sopenharmony_ci}
9671cb0ef41Sopenharmony_ci
9681cb0ef41Sopenharmony_ciHandle<Object> GlobalHandles::CreateTraced(Object value, Address* slot,
9691cb0ef41Sopenharmony_ci                                           GlobalHandleStoreMode store_mode,
9701cb0ef41Sopenharmony_ci                                           bool is_on_stack) {
9711cb0ef41Sopenharmony_ci  GlobalHandles::TracedNode* result;
9721cb0ef41Sopenharmony_ci  if (is_on_stack) {
9731cb0ef41Sopenharmony_ci    result = on_stack_nodes_->Acquire(value, reinterpret_cast<uintptr_t>(slot));
9741cb0ef41Sopenharmony_ci  } else {
9751cb0ef41Sopenharmony_ci    result = traced_nodes_->Acquire(value);
9761cb0ef41Sopenharmony_ci    if (ObjectInYoungGeneration(value) && !result->is_in_young_list()) {
9771cb0ef41Sopenharmony_ci      traced_young_nodes_.push_back(result);
9781cb0ef41Sopenharmony_ci      result->set_in_young_list(true);
9791cb0ef41Sopenharmony_ci    }
9801cb0ef41Sopenharmony_ci    // Nodes are black allocated for simplicity.
9811cb0ef41Sopenharmony_ci    result->set_markbit();
9821cb0ef41Sopenharmony_ci    if (store_mode != GlobalHandleStoreMode::kInitializingStore) {
9831cb0ef41Sopenharmony_ci      WriteBarrier::MarkingFromGlobalHandle(value);
9841cb0ef41Sopenharmony_ci    }
9851cb0ef41Sopenharmony_ci  }
9861cb0ef41Sopenharmony_ci  result->set_parameter(nullptr);
9871cb0ef41Sopenharmony_ci  return result->handle();
9881cb0ef41Sopenharmony_ci}
9891cb0ef41Sopenharmony_ci
9901cb0ef41Sopenharmony_ciHandle<Object> GlobalHandles::CreateTraced(Address value, Address* slot,
9911cb0ef41Sopenharmony_ci                                           GlobalHandleStoreMode store_mode) {
9921cb0ef41Sopenharmony_ci  return CreateTraced(Object(value), slot, store_mode);
9931cb0ef41Sopenharmony_ci}
9941cb0ef41Sopenharmony_ci
9951cb0ef41Sopenharmony_ciHandle<Object> GlobalHandles::CopyGlobal(Address* location) {
9961cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(location);
9971cb0ef41Sopenharmony_ci  GlobalHandles* global_handles =
9981cb0ef41Sopenharmony_ci      Node::FromLocation(location)->global_handles();
9991cb0ef41Sopenharmony_ci#ifdef VERIFY_HEAP
10001cb0ef41Sopenharmony_ci  if (i::FLAG_verify_heap) {
10011cb0ef41Sopenharmony_ci    Object(*location).ObjectVerify(global_handles->isolate());
10021cb0ef41Sopenharmony_ci  }
10031cb0ef41Sopenharmony_ci#endif  // VERIFY_HEAP
10041cb0ef41Sopenharmony_ci  return global_handles->Create(*location);
10051cb0ef41Sopenharmony_ci}
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_cinamespace {
10081cb0ef41Sopenharmony_civoid SetSlotThreadSafe(Address** slot, Address* val) {
10091cb0ef41Sopenharmony_ci  reinterpret_cast<std::atomic<Address*>*>(slot)->store(
10101cb0ef41Sopenharmony_ci      val, std::memory_order_relaxed);
10111cb0ef41Sopenharmony_ci}
10121cb0ef41Sopenharmony_ci}  // namespace
10131cb0ef41Sopenharmony_ci
10141cb0ef41Sopenharmony_ci// static
10151cb0ef41Sopenharmony_civoid GlobalHandles::CopyTracedReference(const Address* const* from,
10161cb0ef41Sopenharmony_ci                                        Address** to) {
10171cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(*from);
10181cb0ef41Sopenharmony_ci  DCHECK_NULL(*to);
10191cb0ef41Sopenharmony_ci  const TracedNode* node = TracedNode::FromLocation(*from);
10201cb0ef41Sopenharmony_ci  GlobalHandles* global_handles =
10211cb0ef41Sopenharmony_ci      GlobalHandles::From(const_cast<TracedNode*>(node));
10221cb0ef41Sopenharmony_ci  Handle<Object> o = global_handles->CreateTraced(
10231cb0ef41Sopenharmony_ci      node->object(), reinterpret_cast<Address*>(to),
10241cb0ef41Sopenharmony_ci      GlobalHandleStoreMode::kAssigningStore);
10251cb0ef41Sopenharmony_ci  SetSlotThreadSafe(to, o.location());
10261cb0ef41Sopenharmony_ci  TracedNode::Verify(global_handles, from);
10271cb0ef41Sopenharmony_ci  TracedNode::Verify(global_handles, to);
10281cb0ef41Sopenharmony_ci#ifdef VERIFY_HEAP
10291cb0ef41Sopenharmony_ci  if (i::FLAG_verify_heap) {
10301cb0ef41Sopenharmony_ci    Object(**to).ObjectVerify(global_handles->isolate());
10311cb0ef41Sopenharmony_ci  }
10321cb0ef41Sopenharmony_ci#endif  // VERIFY_HEAP
10331cb0ef41Sopenharmony_ci}
10341cb0ef41Sopenharmony_ci
10351cb0ef41Sopenharmony_civoid GlobalHandles::MoveGlobal(Address** from, Address** to) {
10361cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(*from);
10371cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(*to);
10381cb0ef41Sopenharmony_ci  DCHECK_EQ(*from, *to);
10391cb0ef41Sopenharmony_ci  Node* node = Node::FromLocation(*from);
10401cb0ef41Sopenharmony_ci  if (node->IsWeak() && node->IsPhantomResetHandle()) {
10411cb0ef41Sopenharmony_ci    node->set_parameter(to);
10421cb0ef41Sopenharmony_ci  }
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci  // - Strong handles do not require fixups.
10451cb0ef41Sopenharmony_ci  // - Weak handles with finalizers and callbacks are too general to fix up. For
10461cb0ef41Sopenharmony_ci  //   those the callers need to ensure consistency.
10471cb0ef41Sopenharmony_ci}
10481cb0ef41Sopenharmony_ci
10491cb0ef41Sopenharmony_civoid GlobalHandles::MoveTracedReference(Address** from, Address** to) {
10501cb0ef41Sopenharmony_ci  // Fast path for moving from an empty reference.
10511cb0ef41Sopenharmony_ci  if (!*from) {
10521cb0ef41Sopenharmony_ci    DestroyTracedReference(*to);
10531cb0ef41Sopenharmony_ci    SetSlotThreadSafe(to, nullptr);
10541cb0ef41Sopenharmony_ci    return;
10551cb0ef41Sopenharmony_ci  }
10561cb0ef41Sopenharmony_ci
10571cb0ef41Sopenharmony_ci  // Determining whether from or to are on stack.
10581cb0ef41Sopenharmony_ci  TracedNode* from_node = TracedNode::FromLocation(*from);
10591cb0ef41Sopenharmony_ci  DCHECK(from_node->IsInUse());
10601cb0ef41Sopenharmony_ci  TracedNode* to_node = TracedNode::FromLocation(*to);
10611cb0ef41Sopenharmony_ci  GlobalHandles* global_handles = nullptr;
10621cb0ef41Sopenharmony_ci#ifdef DEBUG
10631cb0ef41Sopenharmony_ci  global_handles = GlobalHandles::From(from_node);
10641cb0ef41Sopenharmony_ci#endif  // DEBUG
10651cb0ef41Sopenharmony_ci  bool from_on_stack = from_node->is_on_stack();
10661cb0ef41Sopenharmony_ci  bool to_on_stack = false;
10671cb0ef41Sopenharmony_ci  if (!to_node) {
10681cb0ef41Sopenharmony_ci    // Figure out whether stack or heap to allow fast path for heap->heap move.
10691cb0ef41Sopenharmony_ci    global_handles = GlobalHandles::From(from_node);
10701cb0ef41Sopenharmony_ci    to_on_stack = global_handles->on_stack_nodes_->IsOnStack(
10711cb0ef41Sopenharmony_ci        reinterpret_cast<uintptr_t>(to));
10721cb0ef41Sopenharmony_ci  } else {
10731cb0ef41Sopenharmony_ci    to_on_stack = to_node->is_on_stack();
10741cb0ef41Sopenharmony_ci  }
10751cb0ef41Sopenharmony_ci
10761cb0ef41Sopenharmony_ci  // Moving.
10771cb0ef41Sopenharmony_ci  if (from_on_stack || to_on_stack) {
10781cb0ef41Sopenharmony_ci    // Move involving a stack slot.
10791cb0ef41Sopenharmony_ci    if (!to_node) {
10801cb0ef41Sopenharmony_ci      DCHECK(global_handles);
10811cb0ef41Sopenharmony_ci      Handle<Object> o = global_handles->CreateTraced(
10821cb0ef41Sopenharmony_ci          from_node->object(), reinterpret_cast<Address*>(to),
10831cb0ef41Sopenharmony_ci          GlobalHandleStoreMode::kAssigningStore, to_on_stack);
10841cb0ef41Sopenharmony_ci      SetSlotThreadSafe(to, o.location());
10851cb0ef41Sopenharmony_ci      to_node = TracedNode::FromLocation(*to);
10861cb0ef41Sopenharmony_ci      DCHECK_IMPLIES(!to_node->is_on_stack(), to_node->markbit());
10871cb0ef41Sopenharmony_ci    } else {
10881cb0ef41Sopenharmony_ci      DCHECK(to_node->IsInUse());
10891cb0ef41Sopenharmony_ci      to_node->CopyObjectReference(*from_node);
10901cb0ef41Sopenharmony_ci      if (!to_node->is_on_stack() && !to_node->is_in_young_list() &&
10911cb0ef41Sopenharmony_ci          ObjectInYoungGeneration(to_node->object())) {
10921cb0ef41Sopenharmony_ci        global_handles = GlobalHandles::From(from_node);
10931cb0ef41Sopenharmony_ci        global_handles->traced_young_nodes_.push_back(to_node);
10941cb0ef41Sopenharmony_ci        to_node->set_in_young_list(true);
10951cb0ef41Sopenharmony_ci      }
10961cb0ef41Sopenharmony_ci      if (!to_on_stack) {
10971cb0ef41Sopenharmony_ci        WriteBarrier::MarkingFromGlobalHandle(to_node->object());
10981cb0ef41Sopenharmony_ci      }
10991cb0ef41Sopenharmony_ci    }
11001cb0ef41Sopenharmony_ci    DestroyTracedReference(*from);
11011cb0ef41Sopenharmony_ci    SetSlotThreadSafe(from, nullptr);
11021cb0ef41Sopenharmony_ci  } else {
11031cb0ef41Sopenharmony_ci    // Pure heap move.
11041cb0ef41Sopenharmony_ci    DestroyTracedReference(*to);
11051cb0ef41Sopenharmony_ci    SetSlotThreadSafe(to, *from);
11061cb0ef41Sopenharmony_ci    to_node = from_node;
11071cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(*from);
11081cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(*to);
11091cb0ef41Sopenharmony_ci    DCHECK_EQ(*from, *to);
11101cb0ef41Sopenharmony_ci    WriteBarrier::MarkingFromGlobalHandle(to_node->object());
11111cb0ef41Sopenharmony_ci    SetSlotThreadSafe(from, nullptr);
11121cb0ef41Sopenharmony_ci  }
11131cb0ef41Sopenharmony_ci  TracedNode::Verify(global_handles, to);
11141cb0ef41Sopenharmony_ci}
11151cb0ef41Sopenharmony_ci
11161cb0ef41Sopenharmony_ci// static
11171cb0ef41Sopenharmony_ciGlobalHandles* GlobalHandles::From(const TracedNode* node) {
11181cb0ef41Sopenharmony_ci  return node->is_on_stack()
11191cb0ef41Sopenharmony_ci             ? OnStackTracedNodeSpace::GetGlobalHandles(node)
11201cb0ef41Sopenharmony_ci             : NodeBlock<TracedNode>::From(node)->global_handles();
11211cb0ef41Sopenharmony_ci}
11221cb0ef41Sopenharmony_ci
11231cb0ef41Sopenharmony_civoid GlobalHandles::MarkTraced(Address* location) {
11241cb0ef41Sopenharmony_ci  TracedNode* node = TracedNode::FromLocation(location);
11251cb0ef41Sopenharmony_ci  DCHECK(node->IsInUse());
11261cb0ef41Sopenharmony_ci  if (node->is_on_stack()) return;
11271cb0ef41Sopenharmony_ci  node->set_markbit();
11281cb0ef41Sopenharmony_ci}
11291cb0ef41Sopenharmony_ci
11301cb0ef41Sopenharmony_civoid GlobalHandles::Destroy(Address* location) {
11311cb0ef41Sopenharmony_ci  if (location != nullptr) {
11321cb0ef41Sopenharmony_ci    NodeSpace<Node>::Release(Node::FromLocation(location));
11331cb0ef41Sopenharmony_ci  }
11341cb0ef41Sopenharmony_ci}
11351cb0ef41Sopenharmony_ci
11361cb0ef41Sopenharmony_ci// static
11371cb0ef41Sopenharmony_civoid GlobalHandles::DestroyTracedReference(Address* location) {
11381cb0ef41Sopenharmony_ci  if (location != nullptr) {
11391cb0ef41Sopenharmony_ci    TracedNode* node = TracedNode::FromLocation(location);
11401cb0ef41Sopenharmony_ci    if (node->is_on_stack()) {
11411cb0ef41Sopenharmony_ci      node->Release(nullptr);
11421cb0ef41Sopenharmony_ci      return;
11431cb0ef41Sopenharmony_ci    }
11441cb0ef41Sopenharmony_ci    DCHECK(!node->is_on_stack());
11451cb0ef41Sopenharmony_ci
11461cb0ef41Sopenharmony_ci    auto* global_handles = GlobalHandles::From(node);
11471cb0ef41Sopenharmony_ci    // When marking is off the handle may be freed immediately. Note that this
11481cb0ef41Sopenharmony_ci    // includes also the case when invoking the first pass callbacks during the
11491cb0ef41Sopenharmony_ci    // atomic pause which requires releasing a node fully.
11501cb0ef41Sopenharmony_ci    if (!global_handles->is_marking_) {
11511cb0ef41Sopenharmony_ci      NodeSpace<TracedNode>::Release(node);
11521cb0ef41Sopenharmony_ci      return;
11531cb0ef41Sopenharmony_ci    }
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci    // Incremental marking is on. This also covers the scavenge case which
11561cb0ef41Sopenharmony_ci    // prohibits eagerly reclaiming nodes when marking is on during a scavenge.
11571cb0ef41Sopenharmony_ci    //
11581cb0ef41Sopenharmony_ci    // On-heap traced nodes are released in the atomic pause in
11591cb0ef41Sopenharmony_ci    // `IterateWeakRootsForPhantomHandles()` when they are discovered as not
11601cb0ef41Sopenharmony_ci    // marked.
11611cb0ef41Sopenharmony_ci    //
11621cb0ef41Sopenharmony_ci    // Eagerly clear out the object here to avoid needlessly marking it from
11631cb0ef41Sopenharmony_ci    // this point on. Also clear out callback and backreference for the version
11641cb0ef41Sopenharmony_ci    // with callbacks to avoid calling into possibly dead memory later.
11651cb0ef41Sopenharmony_ci    //
11661cb0ef41Sopenharmony_ci    // In the case this happens during incremental marking, the node may
11671cb0ef41Sopenharmony_ci    // still be spuriously marked as live and is then only reclaimed on the
11681cb0ef41Sopenharmony_ci    // next cycle.
11691cb0ef41Sopenharmony_ci    node->clear_object();
11701cb0ef41Sopenharmony_ci    node->set_parameter(nullptr);
11711cb0ef41Sopenharmony_ci  }
11721cb0ef41Sopenharmony_ci}
11731cb0ef41Sopenharmony_ci
11741cb0ef41Sopenharmony_ciusing GenericCallback = v8::WeakCallbackInfo<void>::Callback;
11751cb0ef41Sopenharmony_ci
11761cb0ef41Sopenharmony_civoid GlobalHandles::MakeWeak(Address* location, void* parameter,
11771cb0ef41Sopenharmony_ci                             GenericCallback phantom_callback,
11781cb0ef41Sopenharmony_ci                             v8::WeakCallbackType type) {
11791cb0ef41Sopenharmony_ci  Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type);
11801cb0ef41Sopenharmony_ci}
11811cb0ef41Sopenharmony_ci
11821cb0ef41Sopenharmony_civoid GlobalHandles::MakeWeak(Address** location_addr) {
11831cb0ef41Sopenharmony_ci  Node::FromLocation(*location_addr)->MakeWeak(location_addr);
11841cb0ef41Sopenharmony_ci}
11851cb0ef41Sopenharmony_ci
11861cb0ef41Sopenharmony_civoid* GlobalHandles::ClearWeakness(Address* location) {
11871cb0ef41Sopenharmony_ci  return Node::FromLocation(location)->ClearWeakness();
11881cb0ef41Sopenharmony_ci}
11891cb0ef41Sopenharmony_ci
11901cb0ef41Sopenharmony_civoid GlobalHandles::AnnotateStrongRetainer(Address* location,
11911cb0ef41Sopenharmony_ci                                           const char* label) {
11921cb0ef41Sopenharmony_ci  Node::FromLocation(location)->AnnotateStrongRetainer(label);
11931cb0ef41Sopenharmony_ci}
11941cb0ef41Sopenharmony_ci
11951cb0ef41Sopenharmony_cibool GlobalHandles::IsWeak(Address* location) {
11961cb0ef41Sopenharmony_ci  return Node::FromLocation(location)->IsWeak();
11971cb0ef41Sopenharmony_ci}
11981cb0ef41Sopenharmony_ci
11991cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
12001cb0ef41Sopenharmony_civoid GlobalHandles::IterateWeakRootsForFinalizers(RootVisitor* v) {
12011cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
12021cb0ef41Sopenharmony_ci    if (node->IsWeakRetainer() && node->state() == Node::PENDING) {
12031cb0ef41Sopenharmony_ci      DCHECK(!node->IsPhantomCallback());
12041cb0ef41Sopenharmony_ci      DCHECK(!node->IsPhantomResetHandle());
12051cb0ef41Sopenharmony_ci      // Finalizers need to survive.
12061cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, node->label(),
12071cb0ef41Sopenharmony_ci                          node->location());
12081cb0ef41Sopenharmony_ci    }
12091cb0ef41Sopenharmony_ci  }
12101cb0ef41Sopenharmony_ci}
12111cb0ef41Sopenharmony_ci
12121cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
12131cb0ef41Sopenharmony_civoid GlobalHandles::IterateWeakRootsForPhantomHandles(
12141cb0ef41Sopenharmony_ci    WeakSlotCallbackWithHeap should_reset_handle) {
12151cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
12161cb0ef41Sopenharmony_ci    if (node->IsWeakRetainer() &&
12171cb0ef41Sopenharmony_ci        should_reset_handle(isolate()->heap(), node->location())) {
12181cb0ef41Sopenharmony_ci      if (node->IsPhantomResetHandle()) {
12191cb0ef41Sopenharmony_ci        node->MarkPending();
12201cb0ef41Sopenharmony_ci        node->ResetPhantomHandle();
12211cb0ef41Sopenharmony_ci        ++number_of_phantom_handle_resets_;
12221cb0ef41Sopenharmony_ci      } else if (node->IsPhantomCallback()) {
12231cb0ef41Sopenharmony_ci        node->MarkPending();
12241cb0ef41Sopenharmony_ci        node->CollectPhantomCallbackData(&regular_pending_phantom_callbacks_);
12251cb0ef41Sopenharmony_ci      }
12261cb0ef41Sopenharmony_ci    }
12271cb0ef41Sopenharmony_ci  }
12281cb0ef41Sopenharmony_ci  for (TracedNode* node : *traced_nodes_) {
12291cb0ef41Sopenharmony_ci    if (!node->IsInUse()) continue;
12301cb0ef41Sopenharmony_ci    // Detect unreachable nodes first.
12311cb0ef41Sopenharmony_ci    if (!node->markbit()) {
12321cb0ef41Sopenharmony_ci      // The handle itself is unreachable. We can clear it even if the target V8
12331cb0ef41Sopenharmony_ci      // object is alive.
12341cb0ef41Sopenharmony_ci      node->ResetPhantomHandle();
12351cb0ef41Sopenharmony_ci      ++number_of_phantom_handle_resets_;
12361cb0ef41Sopenharmony_ci      continue;
12371cb0ef41Sopenharmony_ci    }
12381cb0ef41Sopenharmony_ci    // Clear the markbit for the next GC.
12391cb0ef41Sopenharmony_ci    node->clear_markbit();
12401cb0ef41Sopenharmony_ci    DCHECK(node->IsInUse());
12411cb0ef41Sopenharmony_ci    // Detect nodes with unreachable target objects.
12421cb0ef41Sopenharmony_ci    if (should_reset_handle(isolate()->heap(), node->location())) {
12431cb0ef41Sopenharmony_ci      node->ResetPhantomHandle();
12441cb0ef41Sopenharmony_ci      ++number_of_phantom_handle_resets_;
12451cb0ef41Sopenharmony_ci    }
12461cb0ef41Sopenharmony_ci  }
12471cb0ef41Sopenharmony_ci}
12481cb0ef41Sopenharmony_ci
12491cb0ef41Sopenharmony_civoid GlobalHandles::IterateWeakRootsIdentifyFinalizers(
12501cb0ef41Sopenharmony_ci    WeakSlotCallbackWithHeap should_reset_handle) {
12511cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
12521cb0ef41Sopenharmony_ci    if (node->IsWeak() &&
12531cb0ef41Sopenharmony_ci        should_reset_handle(isolate()->heap(), node->location())) {
12541cb0ef41Sopenharmony_ci      if (node->IsFinalizerHandle()) {
12551cb0ef41Sopenharmony_ci        node->MarkPending();
12561cb0ef41Sopenharmony_ci      }
12571cb0ef41Sopenharmony_ci    }
12581cb0ef41Sopenharmony_ci  }
12591cb0ef41Sopenharmony_ci}
12601cb0ef41Sopenharmony_ci
12611cb0ef41Sopenharmony_civoid GlobalHandles::IdentifyWeakUnmodifiedObjects(
12621cb0ef41Sopenharmony_ci    WeakSlotCallback is_unmodified) {
12631cb0ef41Sopenharmony_ci  if (!FLAG_reclaim_unmodified_wrappers) return;
12641cb0ef41Sopenharmony_ci
12651cb0ef41Sopenharmony_ci  // Treat all objects as roots during incremental marking to avoid corrupting
12661cb0ef41Sopenharmony_ci  // marking worklists.
12671cb0ef41Sopenharmony_ci  if (isolate()->heap()->incremental_marking()->IsMarking()) return;
12681cb0ef41Sopenharmony_ci
12691cb0ef41Sopenharmony_ci  auto* const handler = isolate()->heap()->GetEmbedderRootsHandler();
12701cb0ef41Sopenharmony_ci  for (TracedNode* node : traced_young_nodes_) {
12711cb0ef41Sopenharmony_ci    if (node->IsInUse()) {
12721cb0ef41Sopenharmony_ci      DCHECK(node->is_root());
12731cb0ef41Sopenharmony_ci      if (is_unmodified(node->location())) {
12741cb0ef41Sopenharmony_ci        v8::Value* value = ToApi<v8::Value>(node->handle());
12751cb0ef41Sopenharmony_ci        node->set_root(handler->IsRoot(
12761cb0ef41Sopenharmony_ci            *reinterpret_cast<v8::TracedReference<v8::Value>*>(&value)));
12771cb0ef41Sopenharmony_ci      }
12781cb0ef41Sopenharmony_ci    }
12791cb0ef41Sopenharmony_ci  }
12801cb0ef41Sopenharmony_ci}
12811cb0ef41Sopenharmony_ci
12821cb0ef41Sopenharmony_civoid GlobalHandles::IterateYoungStrongAndDependentRoots(RootVisitor* v) {
12831cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
12841cb0ef41Sopenharmony_ci    if (node->IsStrongRetainer()) {
12851cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, node->label(),
12861cb0ef41Sopenharmony_ci                          node->location());
12871cb0ef41Sopenharmony_ci    }
12881cb0ef41Sopenharmony_ci  }
12891cb0ef41Sopenharmony_ci  for (TracedNode* node : traced_young_nodes_) {
12901cb0ef41Sopenharmony_ci    if (node->IsInUse() && node->is_root()) {
12911cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, nullptr, node->location());
12921cb0ef41Sopenharmony_ci    }
12931cb0ef41Sopenharmony_ci  }
12941cb0ef41Sopenharmony_ci}
12951cb0ef41Sopenharmony_ci
12961cb0ef41Sopenharmony_civoid GlobalHandles::MarkYoungWeakDeadObjectsPending(
12971cb0ef41Sopenharmony_ci    WeakSlotCallbackWithHeap is_dead) {
12981cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
12991cb0ef41Sopenharmony_ci    DCHECK(node->is_in_young_list());
13001cb0ef41Sopenharmony_ci    if (node->IsWeak() && is_dead(isolate_->heap(), node->location())) {
13011cb0ef41Sopenharmony_ci      if (!node->IsPhantomCallback() && !node->IsPhantomResetHandle()) {
13021cb0ef41Sopenharmony_ci        node->MarkPending();
13031cb0ef41Sopenharmony_ci      }
13041cb0ef41Sopenharmony_ci    }
13051cb0ef41Sopenharmony_ci  }
13061cb0ef41Sopenharmony_ci}
13071cb0ef41Sopenharmony_ci
13081cb0ef41Sopenharmony_civoid GlobalHandles::IterateYoungWeakDeadObjectsForFinalizers(RootVisitor* v) {
13091cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
13101cb0ef41Sopenharmony_ci    DCHECK(node->is_in_young_list());
13111cb0ef41Sopenharmony_ci    if (node->IsWeakRetainer() && (node->state() == Node::PENDING)) {
13121cb0ef41Sopenharmony_ci      DCHECK(!node->IsPhantomCallback());
13131cb0ef41Sopenharmony_ci      DCHECK(!node->IsPhantomResetHandle());
13141cb0ef41Sopenharmony_ci      // Finalizers need to survive.
13151cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, node->label(),
13161cb0ef41Sopenharmony_ci                          node->location());
13171cb0ef41Sopenharmony_ci    }
13181cb0ef41Sopenharmony_ci  }
13191cb0ef41Sopenharmony_ci}
13201cb0ef41Sopenharmony_ci
13211cb0ef41Sopenharmony_civoid GlobalHandles::IterateYoungWeakObjectsForPhantomHandles(
13221cb0ef41Sopenharmony_ci    RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle) {
13231cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
13241cb0ef41Sopenharmony_ci    DCHECK(node->is_in_young_list());
13251cb0ef41Sopenharmony_ci    if (node->IsWeakRetainer() && (node->state() != Node::PENDING)) {
13261cb0ef41Sopenharmony_ci      if (should_reset_handle(isolate_->heap(), node->location())) {
13271cb0ef41Sopenharmony_ci        DCHECK(node->IsPhantomResetHandle() || node->IsPhantomCallback());
13281cb0ef41Sopenharmony_ci        if (node->IsPhantomResetHandle()) {
13291cb0ef41Sopenharmony_ci          node->MarkPending();
13301cb0ef41Sopenharmony_ci          node->ResetPhantomHandle();
13311cb0ef41Sopenharmony_ci          ++number_of_phantom_handle_resets_;
13321cb0ef41Sopenharmony_ci        } else if (node->IsPhantomCallback()) {
13331cb0ef41Sopenharmony_ci          node->MarkPending();
13341cb0ef41Sopenharmony_ci          node->CollectPhantomCallbackData(&regular_pending_phantom_callbacks_);
13351cb0ef41Sopenharmony_ci        } else {
13361cb0ef41Sopenharmony_ci          UNREACHABLE();
13371cb0ef41Sopenharmony_ci        }
13381cb0ef41Sopenharmony_ci      } else {
13391cb0ef41Sopenharmony_ci        // Node survived and needs to be visited.
13401cb0ef41Sopenharmony_ci        v->VisitRootPointer(Root::kGlobalHandles, node->label(),
13411cb0ef41Sopenharmony_ci                            node->location());
13421cb0ef41Sopenharmony_ci      }
13431cb0ef41Sopenharmony_ci    }
13441cb0ef41Sopenharmony_ci  }
13451cb0ef41Sopenharmony_ci
13461cb0ef41Sopenharmony_ci  if (!FLAG_reclaim_unmodified_wrappers) return;
13471cb0ef41Sopenharmony_ci
13481cb0ef41Sopenharmony_ci  auto* const handler = isolate()->heap()->GetEmbedderRootsHandler();
13491cb0ef41Sopenharmony_ci  for (TracedNode* node : traced_young_nodes_) {
13501cb0ef41Sopenharmony_ci    if (!node->IsInUse()) continue;
13511cb0ef41Sopenharmony_ci
13521cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(node->is_root(),
13531cb0ef41Sopenharmony_ci                   !should_reset_handle(isolate_->heap(), node->location()));
13541cb0ef41Sopenharmony_ci    if (should_reset_handle(isolate_->heap(), node->location())) {
13551cb0ef41Sopenharmony_ci      v8::Value* value = ToApi<v8::Value>(node->handle());
13561cb0ef41Sopenharmony_ci      handler->ResetRoot(
13571cb0ef41Sopenharmony_ci          *reinterpret_cast<v8::TracedReference<v8::Value>*>(&value));
13581cb0ef41Sopenharmony_ci      // We cannot check whether a node is in use here as the reset behavior
13591cb0ef41Sopenharmony_ci      // depends on whether incremental marking is running when reclaiming
13601cb0ef41Sopenharmony_ci      // young objects.
13611cb0ef41Sopenharmony_ci      ++number_of_phantom_handle_resets_;
13621cb0ef41Sopenharmony_ci    } else {
13631cb0ef41Sopenharmony_ci      if (!node->is_root()) {
13641cb0ef41Sopenharmony_ci        node->set_root(true);
13651cb0ef41Sopenharmony_ci        v->VisitRootPointer(Root::kGlobalHandles, nullptr, node->location());
13661cb0ef41Sopenharmony_ci      }
13671cb0ef41Sopenharmony_ci    }
13681cb0ef41Sopenharmony_ci  }
13691cb0ef41Sopenharmony_ci}
13701cb0ef41Sopenharmony_ci
13711cb0ef41Sopenharmony_civoid GlobalHandles::InvokeSecondPassPhantomCallbacksFromTask() {
13721cb0ef41Sopenharmony_ci  DCHECK(second_pass_callbacks_task_posted_);
13731cb0ef41Sopenharmony_ci  second_pass_callbacks_task_posted_ = false;
13741cb0ef41Sopenharmony_ci  Heap::DevToolsTraceEventScope devtools_trace_event_scope(
13751cb0ef41Sopenharmony_ci      isolate()->heap(), "MajorGC", "invoke weak phantom callbacks");
13761cb0ef41Sopenharmony_ci  TRACE_EVENT0("v8", "V8.GCPhantomHandleProcessingCallback");
13771cb0ef41Sopenharmony_ci  isolate()->heap()->CallGCPrologueCallbacks(
13781cb0ef41Sopenharmony_ci      GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags);
13791cb0ef41Sopenharmony_ci  InvokeSecondPassPhantomCallbacks();
13801cb0ef41Sopenharmony_ci  isolate()->heap()->CallGCEpilogueCallbacks(
13811cb0ef41Sopenharmony_ci      GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags);
13821cb0ef41Sopenharmony_ci}
13831cb0ef41Sopenharmony_ci
13841cb0ef41Sopenharmony_civoid GlobalHandles::InvokeSecondPassPhantomCallbacks() {
13851cb0ef41Sopenharmony_ci  // The callbacks may execute JS, which in turn may lead to another GC run.
13861cb0ef41Sopenharmony_ci  // If we are already processing the callbacks, we do not want to start over
13871cb0ef41Sopenharmony_ci  // from within the inner GC. Newly added callbacks will always be run by the
13881cb0ef41Sopenharmony_ci  // outermost GC run only.
13891cb0ef41Sopenharmony_ci  if (running_second_pass_callbacks_) return;
13901cb0ef41Sopenharmony_ci  running_second_pass_callbacks_ = true;
13911cb0ef41Sopenharmony_ci
13921cb0ef41Sopenharmony_ci  AllowJavascriptExecution allow_js(isolate());
13931cb0ef41Sopenharmony_ci  while (!second_pass_callbacks_.empty()) {
13941cb0ef41Sopenharmony_ci    auto callback = second_pass_callbacks_.back();
13951cb0ef41Sopenharmony_ci    second_pass_callbacks_.pop_back();
13961cb0ef41Sopenharmony_ci    callback.Invoke(isolate(), PendingPhantomCallback::kSecondPass);
13971cb0ef41Sopenharmony_ci  }
13981cb0ef41Sopenharmony_ci  running_second_pass_callbacks_ = false;
13991cb0ef41Sopenharmony_ci}
14001cb0ef41Sopenharmony_ci
14011cb0ef41Sopenharmony_cisize_t GlobalHandles::PostScavengeProcessing(unsigned post_processing_count) {
14021cb0ef41Sopenharmony_ci  size_t freed_nodes = 0;
14031cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
14041cb0ef41Sopenharmony_ci    // Filter free nodes.
14051cb0ef41Sopenharmony_ci    if (!node->IsRetainer()) continue;
14061cb0ef41Sopenharmony_ci
14071cb0ef41Sopenharmony_ci    if (node->IsPending()) {
14081cb0ef41Sopenharmony_ci      DCHECK(node->has_callback());
14091cb0ef41Sopenharmony_ci      DCHECK(node->IsPendingFinalizer());
14101cb0ef41Sopenharmony_ci      node->PostGarbageCollectionProcessing(isolate_);
14111cb0ef41Sopenharmony_ci    }
14121cb0ef41Sopenharmony_ci    if (InRecursiveGC(post_processing_count)) return freed_nodes;
14131cb0ef41Sopenharmony_ci
14141cb0ef41Sopenharmony_ci    if (!node->IsRetainer()) freed_nodes++;
14151cb0ef41Sopenharmony_ci  }
14161cb0ef41Sopenharmony_ci  return freed_nodes;
14171cb0ef41Sopenharmony_ci}
14181cb0ef41Sopenharmony_ci
14191cb0ef41Sopenharmony_cisize_t GlobalHandles::PostMarkSweepProcessing(unsigned post_processing_count) {
14201cb0ef41Sopenharmony_ci  size_t freed_nodes = 0;
14211cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
14221cb0ef41Sopenharmony_ci    // Filter free nodes.
14231cb0ef41Sopenharmony_ci    if (!node->IsRetainer()) continue;
14241cb0ef41Sopenharmony_ci
14251cb0ef41Sopenharmony_ci    if (node->IsPending()) {
14261cb0ef41Sopenharmony_ci      DCHECK(node->has_callback());
14271cb0ef41Sopenharmony_ci      DCHECK(node->IsPendingFinalizer());
14281cb0ef41Sopenharmony_ci      node->PostGarbageCollectionProcessing(isolate_);
14291cb0ef41Sopenharmony_ci    }
14301cb0ef41Sopenharmony_ci    if (InRecursiveGC(post_processing_count)) return freed_nodes;
14311cb0ef41Sopenharmony_ci
14321cb0ef41Sopenharmony_ci    if (!node->IsRetainer()) freed_nodes++;
14331cb0ef41Sopenharmony_ci  }
14341cb0ef41Sopenharmony_ci  return freed_nodes;
14351cb0ef41Sopenharmony_ci}
14361cb0ef41Sopenharmony_ci
14371cb0ef41Sopenharmony_citemplate <typename T>
14381cb0ef41Sopenharmony_civoid GlobalHandles::UpdateAndCompactListOfYoungNode(
14391cb0ef41Sopenharmony_ci    std::vector<T*>* node_list) {
14401cb0ef41Sopenharmony_ci  size_t last = 0;
14411cb0ef41Sopenharmony_ci  for (T* node : *node_list) {
14421cb0ef41Sopenharmony_ci    DCHECK(node->is_in_young_list());
14431cb0ef41Sopenharmony_ci    if (node->IsInUse()) {
14441cb0ef41Sopenharmony_ci      if (ObjectInYoungGeneration(node->object())) {
14451cb0ef41Sopenharmony_ci        (*node_list)[last++] = node;
14461cb0ef41Sopenharmony_ci        isolate_->heap()->IncrementNodesCopiedInNewSpace();
14471cb0ef41Sopenharmony_ci      } else {
14481cb0ef41Sopenharmony_ci        node->set_in_young_list(false);
14491cb0ef41Sopenharmony_ci        isolate_->heap()->IncrementNodesPromoted();
14501cb0ef41Sopenharmony_ci      }
14511cb0ef41Sopenharmony_ci    } else {
14521cb0ef41Sopenharmony_ci      node->set_in_young_list(false);
14531cb0ef41Sopenharmony_ci      isolate_->heap()->IncrementNodesDiedInNewSpace();
14541cb0ef41Sopenharmony_ci    }
14551cb0ef41Sopenharmony_ci  }
14561cb0ef41Sopenharmony_ci  DCHECK_LE(last, node_list->size());
14571cb0ef41Sopenharmony_ci  node_list->resize(last);
14581cb0ef41Sopenharmony_ci  node_list->shrink_to_fit();
14591cb0ef41Sopenharmony_ci}
14601cb0ef41Sopenharmony_ci
14611cb0ef41Sopenharmony_civoid GlobalHandles::UpdateListOfYoungNodes() {
14621cb0ef41Sopenharmony_ci  UpdateAndCompactListOfYoungNode(&young_nodes_);
14631cb0ef41Sopenharmony_ci  UpdateAndCompactListOfYoungNode(&traced_young_nodes_);
14641cb0ef41Sopenharmony_ci}
14651cb0ef41Sopenharmony_ci
14661cb0ef41Sopenharmony_citemplate <typename T>
14671cb0ef41Sopenharmony_cisize_t GlobalHandles::InvokeFirstPassWeakCallbacks(
14681cb0ef41Sopenharmony_ci    std::vector<std::pair<T*, PendingPhantomCallback>>* pending) {
14691cb0ef41Sopenharmony_ci  size_t freed_nodes = 0;
14701cb0ef41Sopenharmony_ci  std::vector<std::pair<T*, PendingPhantomCallback>> pending_phantom_callbacks;
14711cb0ef41Sopenharmony_ci  pending_phantom_callbacks.swap(*pending);
14721cb0ef41Sopenharmony_ci  {
14731cb0ef41Sopenharmony_ci    // The initial pass callbacks must simply clear the nodes.
14741cb0ef41Sopenharmony_ci    for (auto& pair : pending_phantom_callbacks) {
14751cb0ef41Sopenharmony_ci      T* node = pair.first;
14761cb0ef41Sopenharmony_ci      DCHECK_EQ(T::NEAR_DEATH, node->state());
14771cb0ef41Sopenharmony_ci      pair.second.Invoke(isolate(), PendingPhantomCallback::kFirstPass);
14781cb0ef41Sopenharmony_ci
14791cb0ef41Sopenharmony_ci      // Transition to second pass. It is required that the first pass callback
14801cb0ef41Sopenharmony_ci      // resets the handle using |v8::PersistentBase::Reset|. Also see comments
14811cb0ef41Sopenharmony_ci      // on |v8::WeakCallbackInfo|.
14821cb0ef41Sopenharmony_ci      CHECK_WITH_MSG(T::FREE == node->state(),
14831cb0ef41Sopenharmony_ci                     "Handle not reset in first callback. See comments on "
14841cb0ef41Sopenharmony_ci                     "|v8::WeakCallbackInfo|.");
14851cb0ef41Sopenharmony_ci
14861cb0ef41Sopenharmony_ci      if (pair.second.callback()) second_pass_callbacks_.push_back(pair.second);
14871cb0ef41Sopenharmony_ci      freed_nodes++;
14881cb0ef41Sopenharmony_ci    }
14891cb0ef41Sopenharmony_ci  }
14901cb0ef41Sopenharmony_ci  return freed_nodes;
14911cb0ef41Sopenharmony_ci}
14921cb0ef41Sopenharmony_ci
14931cb0ef41Sopenharmony_cisize_t GlobalHandles::InvokeFirstPassWeakCallbacks() {
14941cb0ef41Sopenharmony_ci  return InvokeFirstPassWeakCallbacks(&regular_pending_phantom_callbacks_) +
14951cb0ef41Sopenharmony_ci         InvokeFirstPassWeakCallbacks(&traced_pending_phantom_callbacks_);
14961cb0ef41Sopenharmony_ci}
14971cb0ef41Sopenharmony_ci
14981cb0ef41Sopenharmony_civoid GlobalHandles::InvokeOrScheduleSecondPassPhantomCallbacks(
14991cb0ef41Sopenharmony_ci    bool synchronous_second_pass) {
15001cb0ef41Sopenharmony_ci  if (!second_pass_callbacks_.empty()) {
15011cb0ef41Sopenharmony_ci    if (FLAG_optimize_for_size || FLAG_predictable || synchronous_second_pass) {
15021cb0ef41Sopenharmony_ci      Heap::DevToolsTraceEventScope devtools_trace_event_scope(
15031cb0ef41Sopenharmony_ci          isolate()->heap(), "MajorGC", "invoke weak phantom callbacks");
15041cb0ef41Sopenharmony_ci      isolate()->heap()->CallGCPrologueCallbacks(
15051cb0ef41Sopenharmony_ci          GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags);
15061cb0ef41Sopenharmony_ci      InvokeSecondPassPhantomCallbacks();
15071cb0ef41Sopenharmony_ci      isolate()->heap()->CallGCEpilogueCallbacks(
15081cb0ef41Sopenharmony_ci          GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags);
15091cb0ef41Sopenharmony_ci    } else if (!second_pass_callbacks_task_posted_) {
15101cb0ef41Sopenharmony_ci      second_pass_callbacks_task_posted_ = true;
15111cb0ef41Sopenharmony_ci      auto taskrunner = V8::GetCurrentPlatform()->GetForegroundTaskRunner(
15121cb0ef41Sopenharmony_ci          reinterpret_cast<v8::Isolate*>(isolate()));
15131cb0ef41Sopenharmony_ci      taskrunner->PostTask(MakeCancelableTask(
15141cb0ef41Sopenharmony_ci          isolate(), [this] { InvokeSecondPassPhantomCallbacksFromTask(); }));
15151cb0ef41Sopenharmony_ci    }
15161cb0ef41Sopenharmony_ci  }
15171cb0ef41Sopenharmony_ci}
15181cb0ef41Sopenharmony_ci
15191cb0ef41Sopenharmony_civoid GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate,
15201cb0ef41Sopenharmony_ci                                                   InvocationType type) {
15211cb0ef41Sopenharmony_ci  Data::Callback* callback_addr = nullptr;
15221cb0ef41Sopenharmony_ci  if (type == kFirstPass) {
15231cb0ef41Sopenharmony_ci    callback_addr = &callback_;
15241cb0ef41Sopenharmony_ci  }
15251cb0ef41Sopenharmony_ci  Data data(reinterpret_cast<v8::Isolate*>(isolate), parameter_,
15261cb0ef41Sopenharmony_ci            embedder_fields_, callback_addr);
15271cb0ef41Sopenharmony_ci  Data::Callback callback = callback_;
15281cb0ef41Sopenharmony_ci  callback_ = nullptr;
15291cb0ef41Sopenharmony_ci  callback(data);
15301cb0ef41Sopenharmony_ci}
15311cb0ef41Sopenharmony_ci
15321cb0ef41Sopenharmony_cibool GlobalHandles::InRecursiveGC(unsigned gc_processing_counter) {
15331cb0ef41Sopenharmony_ci  return gc_processing_counter != post_gc_processing_count_;
15341cb0ef41Sopenharmony_ci}
15351cb0ef41Sopenharmony_ci
15361cb0ef41Sopenharmony_cisize_t GlobalHandles::PostGarbageCollectionProcessing(
15371cb0ef41Sopenharmony_ci    GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
15381cb0ef41Sopenharmony_ci  // Process weak global handle callbacks. This must be done after the
15391cb0ef41Sopenharmony_ci  // GC is completely done, because the callbacks may invoke arbitrary
15401cb0ef41Sopenharmony_ci  // API functions.
15411cb0ef41Sopenharmony_ci  DCHECK_EQ(Heap::NOT_IN_GC, isolate_->heap()->gc_state());
15421cb0ef41Sopenharmony_ci  const unsigned post_processing_count = ++post_gc_processing_count_;
15431cb0ef41Sopenharmony_ci  size_t freed_nodes = 0;
15441cb0ef41Sopenharmony_ci  bool synchronous_second_pass =
15451cb0ef41Sopenharmony_ci      isolate_->heap()->IsTearingDown() ||
15461cb0ef41Sopenharmony_ci      (gc_callback_flags &
15471cb0ef41Sopenharmony_ci       (kGCCallbackFlagForced | kGCCallbackFlagCollectAllAvailableGarbage |
15481cb0ef41Sopenharmony_ci        kGCCallbackFlagSynchronousPhantomCallbackProcessing)) != 0;
15491cb0ef41Sopenharmony_ci  InvokeOrScheduleSecondPassPhantomCallbacks(synchronous_second_pass);
15501cb0ef41Sopenharmony_ci  if (InRecursiveGC(post_processing_count)) return freed_nodes;
15511cb0ef41Sopenharmony_ci
15521cb0ef41Sopenharmony_ci  freed_nodes += Heap::IsYoungGenerationCollector(collector)
15531cb0ef41Sopenharmony_ci                     ? PostScavengeProcessing(post_processing_count)
15541cb0ef41Sopenharmony_ci                     : PostMarkSweepProcessing(post_processing_count);
15551cb0ef41Sopenharmony_ci  if (InRecursiveGC(post_processing_count)) return freed_nodes;
15561cb0ef41Sopenharmony_ci
15571cb0ef41Sopenharmony_ci  UpdateListOfYoungNodes();
15581cb0ef41Sopenharmony_ci  return freed_nodes;
15591cb0ef41Sopenharmony_ci}
15601cb0ef41Sopenharmony_ci
15611cb0ef41Sopenharmony_civoid GlobalHandles::IterateStrongRoots(RootVisitor* v) {
15621cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
15631cb0ef41Sopenharmony_ci    if (node->IsStrongRetainer()) {
15641cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, node->label(),
15651cb0ef41Sopenharmony_ci                          node->location());
15661cb0ef41Sopenharmony_ci    }
15671cb0ef41Sopenharmony_ci  }
15681cb0ef41Sopenharmony_ci}
15691cb0ef41Sopenharmony_ci
15701cb0ef41Sopenharmony_civoid GlobalHandles::IterateStrongStackRoots(RootVisitor* v) {
15711cb0ef41Sopenharmony_ci  on_stack_nodes_->Iterate(v);
15721cb0ef41Sopenharmony_ci}
15731cb0ef41Sopenharmony_ci
15741cb0ef41Sopenharmony_civoid GlobalHandles::IterateWeakRoots(RootVisitor* v) {
15751cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
15761cb0ef41Sopenharmony_ci    if (node->IsWeak()) {
15771cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, node->label(),
15781cb0ef41Sopenharmony_ci                          node->location());
15791cb0ef41Sopenharmony_ci    }
15801cb0ef41Sopenharmony_ci  }
15811cb0ef41Sopenharmony_ci  for (TracedNode* node : *traced_nodes_) {
15821cb0ef41Sopenharmony_ci    if (node->IsInUse()) {
15831cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, nullptr, node->location());
15841cb0ef41Sopenharmony_ci    }
15851cb0ef41Sopenharmony_ci  }
15861cb0ef41Sopenharmony_ci}
15871cb0ef41Sopenharmony_ci
15881cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
15891cb0ef41Sopenharmony_civoid GlobalHandles::IterateAllRoots(RootVisitor* v) {
15901cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
15911cb0ef41Sopenharmony_ci    if (node->IsRetainer()) {
15921cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, node->label(),
15931cb0ef41Sopenharmony_ci                          node->location());
15941cb0ef41Sopenharmony_ci    }
15951cb0ef41Sopenharmony_ci  }
15961cb0ef41Sopenharmony_ci  for (TracedNode* node : *traced_nodes_) {
15971cb0ef41Sopenharmony_ci    if (node->IsRetainer()) {
15981cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, nullptr, node->location());
15991cb0ef41Sopenharmony_ci    }
16001cb0ef41Sopenharmony_ci  }
16011cb0ef41Sopenharmony_ci  on_stack_nodes_->Iterate(v);
16021cb0ef41Sopenharmony_ci}
16031cb0ef41Sopenharmony_ci
16041cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
16051cb0ef41Sopenharmony_civoid GlobalHandles::IterateAllYoungRoots(RootVisitor* v) {
16061cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
16071cb0ef41Sopenharmony_ci    if (node->IsRetainer()) {
16081cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, node->label(),
16091cb0ef41Sopenharmony_ci                          node->location());
16101cb0ef41Sopenharmony_ci    }
16111cb0ef41Sopenharmony_ci  }
16121cb0ef41Sopenharmony_ci  for (TracedNode* node : traced_young_nodes_) {
16131cb0ef41Sopenharmony_ci    if (node->IsRetainer()) {
16141cb0ef41Sopenharmony_ci      v->VisitRootPointer(Root::kGlobalHandles, nullptr, node->location());
16151cb0ef41Sopenharmony_ci    }
16161cb0ef41Sopenharmony_ci  }
16171cb0ef41Sopenharmony_ci  on_stack_nodes_->Iterate(v);
16181cb0ef41Sopenharmony_ci}
16191cb0ef41Sopenharmony_ci
16201cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
16211cb0ef41Sopenharmony_civoid GlobalHandles::ApplyPersistentHandleVisitor(
16221cb0ef41Sopenharmony_ci    v8::PersistentHandleVisitor* visitor, GlobalHandles::Node* node) {
16231cb0ef41Sopenharmony_ci  v8::Value* value = ToApi<v8::Value>(node->handle());
16241cb0ef41Sopenharmony_ci  visitor->VisitPersistentHandle(
16251cb0ef41Sopenharmony_ci      reinterpret_cast<v8::Persistent<v8::Value>*>(&value),
16261cb0ef41Sopenharmony_ci      node->wrapper_class_id());
16271cb0ef41Sopenharmony_ci}
16281cb0ef41Sopenharmony_ci
16291cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
16301cb0ef41Sopenharmony_civoid GlobalHandles::IterateAllRootsWithClassIds(
16311cb0ef41Sopenharmony_ci    v8::PersistentHandleVisitor* visitor) {
16321cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
16331cb0ef41Sopenharmony_ci    if (node->IsRetainer() && node->has_wrapper_class_id()) {
16341cb0ef41Sopenharmony_ci      ApplyPersistentHandleVisitor(visitor, node);
16351cb0ef41Sopenharmony_ci    }
16361cb0ef41Sopenharmony_ci  }
16371cb0ef41Sopenharmony_ci}
16381cb0ef41Sopenharmony_ci
16391cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
16401cb0ef41Sopenharmony_civoid GlobalHandles::IterateTracedNodes(
16411cb0ef41Sopenharmony_ci    v8::EmbedderHeapTracer::TracedGlobalHandleVisitor* visitor) {
16421cb0ef41Sopenharmony_ci  for (TracedNode* node : *traced_nodes_) {
16431cb0ef41Sopenharmony_ci    if (node->IsInUse()) {
16441cb0ef41Sopenharmony_ci      v8::Value* value = ToApi<v8::Value>(node->handle());
16451cb0ef41Sopenharmony_ci      visitor->VisitTracedReference(
16461cb0ef41Sopenharmony_ci          *reinterpret_cast<v8::TracedReference<v8::Value>*>(&value));
16471cb0ef41Sopenharmony_ci    }
16481cb0ef41Sopenharmony_ci  }
16491cb0ef41Sopenharmony_ci}
16501cb0ef41Sopenharmony_ci
16511cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
16521cb0ef41Sopenharmony_civoid GlobalHandles::IterateAllYoungRootsWithClassIds(
16531cb0ef41Sopenharmony_ci    v8::PersistentHandleVisitor* visitor) {
16541cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
16551cb0ef41Sopenharmony_ci    if (node->IsRetainer() && node->has_wrapper_class_id()) {
16561cb0ef41Sopenharmony_ci      ApplyPersistentHandleVisitor(visitor, node);
16571cb0ef41Sopenharmony_ci    }
16581cb0ef41Sopenharmony_ci  }
16591cb0ef41Sopenharmony_ci}
16601cb0ef41Sopenharmony_ci
16611cb0ef41Sopenharmony_ciDISABLE_CFI_PERF
16621cb0ef41Sopenharmony_civoid GlobalHandles::IterateYoungWeakRootsWithClassIds(
16631cb0ef41Sopenharmony_ci    v8::PersistentHandleVisitor* visitor) {
16641cb0ef41Sopenharmony_ci  for (Node* node : young_nodes_) {
16651cb0ef41Sopenharmony_ci    if (node->has_wrapper_class_id() && node->IsWeak()) {
16661cb0ef41Sopenharmony_ci      ApplyPersistentHandleVisitor(visitor, node);
16671cb0ef41Sopenharmony_ci    }
16681cb0ef41Sopenharmony_ci  }
16691cb0ef41Sopenharmony_ci}
16701cb0ef41Sopenharmony_ci
16711cb0ef41Sopenharmony_civoid GlobalHandles::RecordStats(HeapStats* stats) {
16721cb0ef41Sopenharmony_ci  *stats->global_handle_count = 0;
16731cb0ef41Sopenharmony_ci  *stats->weak_global_handle_count = 0;
16741cb0ef41Sopenharmony_ci  *stats->pending_global_handle_count = 0;
16751cb0ef41Sopenharmony_ci  *stats->near_death_global_handle_count = 0;
16761cb0ef41Sopenharmony_ci  *stats->free_global_handle_count = 0;
16771cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
16781cb0ef41Sopenharmony_ci    *stats->global_handle_count += 1;
16791cb0ef41Sopenharmony_ci    if (node->state() == Node::WEAK) {
16801cb0ef41Sopenharmony_ci      *stats->weak_global_handle_count += 1;
16811cb0ef41Sopenharmony_ci    } else if (node->state() == Node::PENDING) {
16821cb0ef41Sopenharmony_ci      *stats->pending_global_handle_count += 1;
16831cb0ef41Sopenharmony_ci    } else if (node->state() == Node::NEAR_DEATH) {
16841cb0ef41Sopenharmony_ci      *stats->near_death_global_handle_count += 1;
16851cb0ef41Sopenharmony_ci    } else if (node->state() == Node::FREE) {
16861cb0ef41Sopenharmony_ci      *stats->free_global_handle_count += 1;
16871cb0ef41Sopenharmony_ci    }
16881cb0ef41Sopenharmony_ci  }
16891cb0ef41Sopenharmony_ci}
16901cb0ef41Sopenharmony_ci
16911cb0ef41Sopenharmony_ci#ifdef DEBUG
16921cb0ef41Sopenharmony_ci
16931cb0ef41Sopenharmony_civoid GlobalHandles::PrintStats() {
16941cb0ef41Sopenharmony_ci  int total = 0;
16951cb0ef41Sopenharmony_ci  int weak = 0;
16961cb0ef41Sopenharmony_ci  int pending = 0;
16971cb0ef41Sopenharmony_ci  int near_death = 0;
16981cb0ef41Sopenharmony_ci  int destroyed = 0;
16991cb0ef41Sopenharmony_ci
17001cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
17011cb0ef41Sopenharmony_ci    total++;
17021cb0ef41Sopenharmony_ci    if (node->state() == Node::WEAK) weak++;
17031cb0ef41Sopenharmony_ci    if (node->state() == Node::PENDING) pending++;
17041cb0ef41Sopenharmony_ci    if (node->state() == Node::NEAR_DEATH) near_death++;
17051cb0ef41Sopenharmony_ci    if (node->state() == Node::FREE) destroyed++;
17061cb0ef41Sopenharmony_ci  }
17071cb0ef41Sopenharmony_ci
17081cb0ef41Sopenharmony_ci  PrintF("Global Handle Statistics:\n");
17091cb0ef41Sopenharmony_ci  PrintF("  allocated memory = %zuB\n", total * sizeof(Node));
17101cb0ef41Sopenharmony_ci  PrintF("  # weak       = %d\n", weak);
17111cb0ef41Sopenharmony_ci  PrintF("  # pending    = %d\n", pending);
17121cb0ef41Sopenharmony_ci  PrintF("  # near_death = %d\n", near_death);
17131cb0ef41Sopenharmony_ci  PrintF("  # free       = %d\n", destroyed);
17141cb0ef41Sopenharmony_ci  PrintF("  # total      = %d\n", total);
17151cb0ef41Sopenharmony_ci}
17161cb0ef41Sopenharmony_ci
17171cb0ef41Sopenharmony_civoid GlobalHandles::Print() {
17181cb0ef41Sopenharmony_ci  PrintF("Global handles:\n");
17191cb0ef41Sopenharmony_ci  for (Node* node : *regular_nodes_) {
17201cb0ef41Sopenharmony_ci    PrintF("  handle %p to %p%s\n", node->location().ToVoidPtr(),
17211cb0ef41Sopenharmony_ci           reinterpret_cast<void*>(node->object().ptr()),
17221cb0ef41Sopenharmony_ci           node->IsWeak() ? " (weak)" : "");
17231cb0ef41Sopenharmony_ci  }
17241cb0ef41Sopenharmony_ci}
17251cb0ef41Sopenharmony_ci
17261cb0ef41Sopenharmony_ci#endif
17271cb0ef41Sopenharmony_ci
17281cb0ef41Sopenharmony_ciEternalHandles::~EternalHandles() {
17291cb0ef41Sopenharmony_ci  for (Address* block : blocks_) delete[] block;
17301cb0ef41Sopenharmony_ci}
17311cb0ef41Sopenharmony_ci
17321cb0ef41Sopenharmony_civoid EternalHandles::IterateAllRoots(RootVisitor* visitor) {
17331cb0ef41Sopenharmony_ci  int limit = size_;
17341cb0ef41Sopenharmony_ci  for (Address* block : blocks_) {
17351cb0ef41Sopenharmony_ci    DCHECK_GT(limit, 0);
17361cb0ef41Sopenharmony_ci    visitor->VisitRootPointers(
17371cb0ef41Sopenharmony_ci        Root::kEternalHandles, nullptr, FullObjectSlot(block),
17381cb0ef41Sopenharmony_ci        FullObjectSlot(block + std::min({limit, kSize})));
17391cb0ef41Sopenharmony_ci    limit -= kSize;
17401cb0ef41Sopenharmony_ci  }
17411cb0ef41Sopenharmony_ci}
17421cb0ef41Sopenharmony_ci
17431cb0ef41Sopenharmony_civoid EternalHandles::IterateYoungRoots(RootVisitor* visitor) {
17441cb0ef41Sopenharmony_ci  for (int index : young_node_indices_) {
17451cb0ef41Sopenharmony_ci    visitor->VisitRootPointer(Root::kEternalHandles, nullptr,
17461cb0ef41Sopenharmony_ci                              FullObjectSlot(GetLocation(index)));
17471cb0ef41Sopenharmony_ci  }
17481cb0ef41Sopenharmony_ci}
17491cb0ef41Sopenharmony_ci
17501cb0ef41Sopenharmony_civoid EternalHandles::PostGarbageCollectionProcessing() {
17511cb0ef41Sopenharmony_ci  size_t last = 0;
17521cb0ef41Sopenharmony_ci  for (int index : young_node_indices_) {
17531cb0ef41Sopenharmony_ci    if (ObjectInYoungGeneration(Object(*GetLocation(index)))) {
17541cb0ef41Sopenharmony_ci      young_node_indices_[last++] = index;
17551cb0ef41Sopenharmony_ci    }
17561cb0ef41Sopenharmony_ci  }
17571cb0ef41Sopenharmony_ci  DCHECK_LE(last, young_node_indices_.size());
17581cb0ef41Sopenharmony_ci  young_node_indices_.resize(last);
17591cb0ef41Sopenharmony_ci}
17601cb0ef41Sopenharmony_ci
17611cb0ef41Sopenharmony_civoid EternalHandles::Create(Isolate* isolate, Object object, int* index) {
17621cb0ef41Sopenharmony_ci  DCHECK_EQ(kInvalidIndex, *index);
17631cb0ef41Sopenharmony_ci  if (object == Object()) return;
17641cb0ef41Sopenharmony_ci  Object the_hole = ReadOnlyRoots(isolate).the_hole_value();
17651cb0ef41Sopenharmony_ci  DCHECK_NE(the_hole, object);
17661cb0ef41Sopenharmony_ci  int block = size_ >> kShift;
17671cb0ef41Sopenharmony_ci  int offset = size_ & kMask;
17681cb0ef41Sopenharmony_ci  // Need to resize.
17691cb0ef41Sopenharmony_ci  if (offset == 0) {
17701cb0ef41Sopenharmony_ci    Address* next_block = new Address[kSize];
17711cb0ef41Sopenharmony_ci    MemsetPointer(FullObjectSlot(next_block), the_hole, kSize);
17721cb0ef41Sopenharmony_ci    blocks_.push_back(next_block);
17731cb0ef41Sopenharmony_ci  }
17741cb0ef41Sopenharmony_ci  DCHECK_EQ(the_hole.ptr(), blocks_[block][offset]);
17751cb0ef41Sopenharmony_ci  blocks_[block][offset] = object.ptr();
17761cb0ef41Sopenharmony_ci  if (ObjectInYoungGeneration(object)) {
17771cb0ef41Sopenharmony_ci    young_node_indices_.push_back(size_);
17781cb0ef41Sopenharmony_ci  }
17791cb0ef41Sopenharmony_ci  *index = size_++;
17801cb0ef41Sopenharmony_ci}
17811cb0ef41Sopenharmony_ci
17821cb0ef41Sopenharmony_ci}  // namespace internal
17831cb0ef41Sopenharmony_ci}  // namespace v8
1784