@ 261106.4
current
// Copyright 2025 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_TRUSTED_POINTER_H_
#define V8_OBJECTS_TRUSTED_POINTER_H_

#include "src/common/globals.h"
#include "src/objects/heap-object.h"
#include "src/objects/objects.h"
#include "src/objects/tagged-field.h"
#include "src/objects/tagged.h"
#include "src/sandbox/indirect-pointer-tag.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

class IsolateForSandbox;
class Code;
class BytecodeArray;
class InterpreterData;
class UncompiledData;
class RegExpData;
class WasmDispatchTable;
class WasmTrustedInstanceData;
class WasmInternalFunction;
class WasmSuspenderObject;
class WasmFunctionData;
class WasmExportedFunctionData;
class WasmCapiFunctionData;

template <typename T, IndirectPointerTagRange kTagRange>
class TrustedPointerMember;

namespace detail {

#define TRUSTED_POINTER_TAG_TO_TYPE_MAP(V)                                  \
  V(kCodeIndirectPointerTag, Code)                                          \
  V(kBytecodeArrayIndirectPointerTag, BytecodeArray)                        \
  V(kInterpreterDataIndirectPointerTag, InterpreterData)                    \
  V(kUncompiledDataIndirectPointerTag, UncompiledData)                      \
  V(kRegExpDataIndirectPointerTag, RegExpData)                              \
  IF_WASM(V, kWasmDispatchTableIndirectPointerTag, WasmDispatchTable)       \
  IF_WASM(V, kSharedWasmDispatchTableIndirectPointerTag, WasmDispatchTable) \
  IF_WASM(V, kWasmTrustedInstanceDataIndirectPointerTag,                    \
          WasmTrustedInstanceData)                                          \
  IF_WASM(V, kSharedWasmTrustedInstanceDataIndirectPointerTag,              \
          WasmTrustedInstanceData)                                          \
  IF_WASM(V, kWasmInternalFunctionIndirectPointerTag, WasmInternalFunction) \
  IF_WASM(V, kWasmSuspenderIndirectPointerTag, WasmSuspenderObject)         \
  IF_WASM(V, kWasmFunctionDataIndirectPointerTagRange, WasmFunctionData)    \
  IF_WASM(V, kWasmExportedFunctionDataIndirectPointerTag,                   \
          WasmExportedFunctionData)                                         \
  IF_WASM(V, kWasmCapiFunctionDataIndirectPointerTag, WasmCapiFunctionData)

template <IndirectPointerTagRange tag_range>
struct TrustedPointerType {
  using type = ExposedTrustedObject;
};

#define DEFINE_TRUSTED_POINTER_TYPE(Tag, Type) \
  template <>                                  \
  struct TrustedPointerType<Tag> {             \
    using type = Type;                         \
  };

TRUSTED_POINTER_TAG_TO_TYPE_MAP(DEFINE_TRUSTED_POINTER_TYPE)
#undef DEFINE_TRUSTED_POINTER_TYPE

}  // namespace detail

template <IndirectPointerTagRange tag_range>
using TrustedTypeFor = typename detail::TrustedPointerType<tag_range>::type;

// TrustedPointerField provides static methods for reading and writing trusted
// pointers from HeapObjects.
//
// A pointer to a trusted object. When the sandbox is enabled, these are
// indirect pointers using the TrustedPointerTable (TPT). When the sandbox
// is disabled, they are regular tagged pointers. They must always point to an
// ExposedTrustedObject as (only) these objects can be referenced through the
// trusted pointer table.
class TrustedPointerField {
 public:
  template <IndirectPointerTagRange tag_range>
  static inline Tagged<TrustedTypeFor<tag_range>> ReadTrustedPointerField(
      Tagged<HeapObject> host, size_t offset, IsolateForSandbox isolate);

  template <IndirectPointerTagRange tag_range>
  static inline Tagged<TrustedTypeFor<tag_range>> ReadTrustedPointerField(
      Tagged<HeapObject> host, size_t offset, IsolateForSandbox isolate,
      AcquireLoadTag acquire_load);

  // Like ReadTrustedPointerField, but if the field is cleared, this will
  // return Smi::zero().
  template <IndirectPointerTagRange tag_range>
  static inline Tagged<Union<Smi, TrustedTypeFor<tag_range>>>
  ReadMaybeEmptyTrustedPointerField(Tagged<HeapObject> host, size_t offset,
                                    IsolateForSandbox isolate, AcquireLoadTag);

  template <IndirectPointerTagRange tag_range>
  static inline void WriteTrustedPointerField(
      Tagged<HeapObject> host, size_t offset,
      Tagged<ExposedTrustedObject> value);

  // Trusted pointer fields can be cleared/empty, in which case they no longer
  // point to any object. When the sandbox is enabled, this will set the fields
  // indirect pointer handle to the null handle (referencing the zeroth entry
  // in the TrustedPointerTable which just contains nullptr). When the sandbox
  // is disabled, this will set the field to Smi::zero().
  static inline bool IsTrustedPointerFieldEmpty(Tagged<HeapObject> host,
                                                size_t offset);

  template <typename IsolateT>
  static inline bool IsTrustedPointerFieldUnpublished(
      Tagged<HeapObject> host, size_t offset, IndirectPointerTagRange tag_range,
      IsolateT isolate);

  static inline void ClearTrustedPointerField(Tagged<HeapObject> host,
                                              size_t offset);

  static inline void ClearTrustedPointerField(Tagged<HeapObject> host,
                                              size_t offset, ReleaseStoreTag);
};

// TrustedPointerMember is a type wrapping a trusted pointer.
//
// This is a member version of TrustedPointerField, similar to TaggedMember vs.
// TaggedField.
//
// TODO(leszeks): Remove TrustedPointerField (and update these comments) when
// all objects are ported.
template <typename T, IndirectPointerTagRange kTagRange>
class TrustedPointerMember
#ifndef V8_ENABLE_SANDBOX
    // On non-sandbox builds, TrustedPointerMember is just a TaggedMember with
    // custom accessors, which allows it to be passed to Slots same as a
    // TaggedMember.
    : public TaggedMember<T>
#endif
{
 public:
  constexpr TrustedPointerMember() = default;

  inline Tagged<T> load(IsolateForSandbox isolate) const;
  inline Tagged<Object> load_maybe_empty(IsolateForSandbox isolate) const;
  inline void store(HeapObject* host, Tagged<T> value,
                    WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
  inline void store_no_write_barrier(HeapObject* host, Tagged<T> value);

  inline Tagged<T> Acquire_Load(IsolateForSandbox isolate) const;
  inline Tagged<Object> Acquire_Load_maybe_empty(
      IsolateForSandbox isolate) const;
  inline void Release_Store(HeapObject* host, Tagged<T> value,
                            WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
  inline void Release_Store_no_write_barrier(HeapObject* host, Tagged<T> value);

  inline bool is_empty() const;
  inline bool is_unpublished(IsolateForSandbox isolate) const;
  inline void clear(HeapObject* host);

 private:
#ifdef V8_ENABLE_SANDBOX
  friend class IndirectPointerSlot;

  inline Address storage_address() const;

  std::atomic<IndirectPointerHandle> handle_;
#else
  using Base = TaggedMember<T>;
#endif
};

using CodePointerMember = TrustedPointerMember<Code, kCodeIndirectPointerTag>;

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_TRUSTED_POINTER_H_