current commit
261004.7 · deps: update V8 to 15.2.124.38
// 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_INL_H_
#define V8_OBJECTS_TRUSTED_POINTER_INL_H_

#include "src/objects/trusted-pointer.h"
// Include the non-inl header before the rest of the headers.

#include <atomic>

#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/heap-object.h"
#include "src/objects/tagged-field-inl.h"
#include "src/objects/trusted-object.h"
#include "src/sandbox/indirect-pointer-inl.h"
#include "src/sandbox/trusted-pointer-table-inl.h"

namespace v8 {
namespace internal {

template <IndirectPointerTagRange tag_range>
Tagged<TrustedTypeFor<tag_range>> TrustedPointerField::ReadTrustedPointerField(
    Tagged<HeapObject> host, size_t offset, IsolateForSandbox isolate) {
  // Currently, trusted pointer loads always use acquire semantics as the
  // under-the-hood indirect pointer loads use acquire loads anyway.
  return ReadTrustedPointerField<tag_range>(host, offset, isolate,
                                            kAcquireLoad);
}

template <IndirectPointerTagRange tag_range>
Tagged<TrustedTypeFor<tag_range>> TrustedPointerField::ReadTrustedPointerField(
    Tagged<HeapObject> host, size_t offset, IsolateForSandbox isolate,
    AcquireLoadTag acquire_load) {
  Tagged<Object> object = ReadMaybeEmptyTrustedPointerField<tag_range>(
      host, offset, isolate, acquire_load);
  using ReturnType = TrustedTypeFor<tag_range>;
  return TrustedCast<ReturnType>(object);
}

template <IndirectPointerTagRange tag_range>
Tagged<Union<Smi, TrustedTypeFor<tag_range>>>
TrustedPointerField::ReadMaybeEmptyTrustedPointerField(
    Tagged<HeapObject> host, size_t offset, IsolateForSandbox isolate,
    AcquireLoadTag) {
#ifdef V8_ENABLE_SANDBOX
  // Reading a TrustedPointer field is just a ReadIndirectPointerField with the
  // proper tag.
  Address field_address = host->ptr() + offset - kHeapObjectTag;
  Tagged<Object> object =
      ReadIndirectPointerField<tag_range>(field_address, isolate, kAcquireLoad);
#else
  Tagged<Object> object =
      TaggedField<Object>::Acquire_Load(host, static_cast<int>(offset));
#endif
  return TrustedCast<Union<Smi, TrustedTypeFor<tag_range>>>(object);
}

template <IndirectPointerTagRange tag_range>
void TrustedPointerField::WriteTrustedPointerField(
    Tagged<HeapObject> host, size_t offset,
    Tagged<ExposedTrustedObject> value) {
#ifdef V8_ENABLE_SANDBOX
  Address field_address = host->ptr() + offset - kHeapObjectTag;
  WriteIndirectPointerField<tag_range>(field_address, value, kReleaseStore);
#else
  TaggedField<ExposedTrustedObject>::Release_Store(
      host, static_cast<int>(offset), value);
#endif
}

bool TrustedPointerField::IsTrustedPointerFieldEmpty(Tagged<HeapObject> host,
                                                     size_t offset) {
#ifdef V8_ENABLE_SANDBOX
  Address field_address = host->ptr() + offset - kHeapObjectTag;
  IndirectPointerHandle handle = base::AsAtomic32::Acquire_Load(
      reinterpret_cast<IndirectPointerHandle*>(field_address));
  return handle == kNullIndirectPointerHandle;
#else
  return IsSmi(
      TaggedField<Object>::Acquire_Load(host, static_cast<int>(offset)));
#endif
}

template <typename IsolateT>
bool TrustedPointerField::IsTrustedPointerFieldUnpublished(
    Tagged<HeapObject> host, size_t offset, IndirectPointerTagRange tag_range,
    IsolateT isolate) {
#ifdef V8_ENABLE_SANDBOX
  IndirectPointerHandle handle =
      base::AsAtomic32::Acquire_Load(reinterpret_cast<IndirectPointerHandle*>(
          host->ptr() + offset - kHeapObjectTag));
  if (handle == kNullIndirectPointerHandle) return false;
  const TrustedPointerTable& table =
      isolate.GetTrustedPointerTableFor(tag_range);
  return table.IsUnpublished(handle);
#else
  return false;
#endif
}

void TrustedPointerField::ClearTrustedPointerField(Tagged<HeapObject> host,
                                                   size_t offset) {
  ClearTrustedPointerField(host, offset, kReleaseStore);
}

void TrustedPointerField::ClearTrustedPointerField(Tagged<HeapObject> host,
                                                   size_t offset,
                                                   ReleaseStoreTag) {
#ifdef V8_ENABLE_SANDBOX
  Address field_address = host->ptr() + offset - kHeapObjectTag;
  base::AsAtomic32::Release_Store(
      reinterpret_cast<IndirectPointerHandle*>(field_address),
      kNullIndirectPointerHandle);
#else
  TaggedField<Smi>::Release_Store(host, static_cast<int>(offset), Smi::zero());
#endif
}

// Currently, trusted pointer loads/stores always use acquire/release
// semantics as the under-the-hood indirect pointer loads/stores use
// acquire/release loads/stores anyway.
template <typename T, IndirectPointerTagRange kTagRange>
Tagged<T> TrustedPointerMember<T, kTagRange>::load(
    IsolateForSandbox isolate) const {
  return Acquire_Load(isolate);
}
template <typename T, IndirectPointerTagRange kTagRange>
Tagged<Object> TrustedPointerMember<T, kTagRange>::load_maybe_empty(
    IsolateForSandbox isolate) const {
  return Acquire_Load_maybe_empty(isolate);
}
template <typename T, IndirectPointerTagRange kTagRange>
void TrustedPointerMember<T, kTagRange>::store(HeapObject* host,
                                               Tagged<T> value,
                                               WriteBarrierMode mode) {
  Release_Store(host, value, mode);
}
template <typename T, IndirectPointerTagRange kTagRange>
void TrustedPointerMember<T, kTagRange>::store_no_write_barrier(
    HeapObject* host, Tagged<T> value) {
  Release_Store_no_write_barrier(host, value);
}

template <typename T, IndirectPointerTagRange kTagRange>
Tagged<T> TrustedPointerMember<T, kTagRange>::Acquire_Load(
    IsolateForSandbox isolate) const {
#ifdef V8_ENABLE_SANDBOX
  return TrustedCast<T>(ReadIndirectPointerHandle<kTagRange>(
      handle_.load(std::memory_order::acquire), isolate));
#else
  return Base::Acquire_Load();
#endif
}

template <typename T, IndirectPointerTagRange kTagRange>
Tagged<Object> TrustedPointerMember<T, kTagRange>::Acquire_Load_maybe_empty(
    IsolateForSandbox isolate) const {
#ifdef V8_ENABLE_SANDBOX
  IndirectPointerHandle handle = handle_.load(std::memory_order::acquire);
  if (handle == kNullIndirectPointerHandle) return Smi::zero();
  return ReadIndirectPointerHandle<kTagRange>(handle, isolate);
#else
  return Base::Acquire_Load();
#endif
}

template <typename T, IndirectPointerTagRange kTagRange>
void TrustedPointerMember<T, kTagRange>::Release_Store(HeapObject* host,
                                                       Tagged<T> value,
                                                       WriteBarrierMode mode) {
#ifdef V8_ENABLE_SANDBOX
  handle_.store(
      Cast<ExposedTrustedObject>(value)->self_indirect_pointer_handle(),
      std::memory_order_release);
  WriteBarrier::ForIndirectPointer(host, this, value, mode);
#else
  Base::Release_Store(host, value, mode);
#endif
}

template <typename T, IndirectPointerTagRange kTagRange>
void TrustedPointerMember<T, kTagRange>::Release_Store_no_write_barrier(
    HeapObject* host, Tagged<T> value) {
#ifdef V8_ENABLE_SANDBOX
  store(host, value, SKIP_WRITE_BARRIER);
#else
  Base::Release_Store_no_write_barrier(value);
#endif
}

template <typename T, IndirectPointerTagRange kTagRange>
bool TrustedPointerMember<T, kTagRange>::is_empty() const {
#ifdef V8_ENABLE_SANDBOX
  return handle_.load(std::memory_order_acquire) == kNullIndirectPointerHandle;
#else
  return Base::Acquire_Load().is_null();
#endif
}

template <typename T, IndirectPointerTagRange kTagRange>
bool TrustedPointerMember<T, kTagRange>::is_unpublished(
    IsolateForSandbox isolate) const {
#ifdef V8_ENABLE_SANDBOX
  IndirectPointerHandle handle = handle_.load(std::memory_order_acquire);
  if (handle == kNullIndirectPointerHandle) return false;
  const TrustedPointerTable& table =
      isolate.GetTrustedPointerTableFor(kTagRange);
  return table.IsUnpublished(handle);
#else
  return false;
#endif
}

template <typename T, IndirectPointerTagRange kTagRange>
void TrustedPointerMember<T, kTagRange>::clear(HeapObject* host) {
#ifdef V8_ENABLE_SANDBOX
  handle_.store(kNullIndirectPointerHandle, std::memory_order_release);
#else
  Base::Release_Store_no_write_barrier(Tagged<T>());
#endif
}

#ifdef V8_ENABLE_SANDBOX
template <typename T, IndirectPointerTagRange kTagRange>
Address TrustedPointerMember<T, kTagRange>::storage_address() const {
  return reinterpret_cast<Address>(&handle_);
}
#endif

}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_TRUSTED_POINTER_INL_H_