blob: 40211b3ffed2d8c0219d7f4f28dbb95af69c073c [file] [log] [blame]
// Copyright 2024 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_SANDBOX_EXTERNAL_BUFFER_INL_H_
#define V8_SANDBOX_EXTERNAL_BUFFER_INL_H_
#include "include/v8-internal.h"
#include "src/base/atomic-utils.h"
#include "src/objects/slots-inl.h"
#include "src/sandbox/external-buffer-table-inl.h"
#include "src/sandbox/external-buffer.h"
#include "src/sandbox/isolate-inl.h"
#include "src/sandbox/isolate.h"
namespace v8 {
namespace internal {
template <ExternalBufferTag tag>
inline void ExternalBufferMember<tag>::Init(Address host_address,
IsolateForSandbox isolate,
std::pair<Address, size_t> value) {
InitExternalBufferField<tag>(
host_address, reinterpret_cast<Address>(storage_), isolate, value);
}
template <ExternalBufferTag tag>
inline std::pair<Address, size_t> ExternalBufferMember<tag>::load(
const IsolateForSandbox isolate) const {
return ReadExternalBufferField<tag>(reinterpret_cast<Address>(storage_),
isolate);
}
template <ExternalBufferTag tag>
V8_INLINE void InitExternalBufferField(Address host_address,
Address field_address,
IsolateForSandbox isolate,
std::pair<Address, size_t> value) {
#ifdef V8_ENABLE_SANDBOX
static_assert(tag != kExternalBufferNullTag);
ExternalBufferTable& table = isolate.GetExternalBufferTableFor(tag);
ExternalBufferHandle handle = table.AllocateAndInitializeEntry(
isolate.GetExternalBufferTableSpaceFor(tag, host_address), value, tag);
// Use a Release_Store to ensure that the store of the pointer into the
// table is not reordered after the store of the handle. Otherwise, other
// threads may access an uninitialized table entry and crash.
auto location = reinterpret_cast<ExternalBufferHandle*>(field_address);
base::AsAtomic32::Release_Store(location, handle);
#else
UNREACHABLE();
#endif // V8_ENABLE_SANDBOX
}
template <ExternalBufferTag tag>
V8_INLINE std::pair<Address, size_t> ReadExternalBufferField(
Address field_address, IsolateForSandbox isolate) {
#ifdef V8_ENABLE_SANDBOX
static_assert(tag != kExternalBufferNullTag);
// Handles may be written to objects from other threads so the handle needs
// to be loaded atomically. We assume that the load from the table cannot
// be reordered before the load of the handle due to the data dependency
// between the two loads and therefore use relaxed memory ordering, but
// technically we should use memory_order_consume here.
auto location = reinterpret_cast<ExternalBufferHandle*>(field_address);
ExternalBufferHandle handle = base::AsAtomic32::Relaxed_Load(location);
return isolate.GetExternalBufferTableFor(tag).Get(handle, tag);
#else
UNREACHABLE();
#endif // V8_ENABLE_SANDBOX
}
} // namespace internal
} // namespace v8
#endif // V8_SANDBOX_EXTERNAL_BUFFER_INL_H_