#ifndef V8_EXECUTION_ISOLATE_DATA_H_
#define V8_EXECUTION_ISOLATE_DATA_H_
#include "src/builtins/builtins.h"
#include "src/codegen/constants-arch.h"
#include "src/codegen/external-reference-table.h"
#include "src/execution/stack-guard.h"
#include "src/execution/thread-local-top.h"
#include "src/heap/linear-allocation-area.h"
#include "src/roots/roots.h"
#include "src/sandbox/external-pointer-table.h"
#include "src/utils/utils.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
namespace v8 {
namespace internal {
class Isolate;
#define ISOLATE_DATA_FIELDS(V) \
\
V(kCageBaseOffset, kSystemPointerSize, cage_base) \
V(kStackGuardOffset, StackGuard::kSizeInBytes, stack_guard) \
\
V(kBuiltinTier0EntryTableOffset, \
Builtins::kBuiltinTier0Count* kSystemPointerSize, \
builtin_tier0_entry_table) \
V(kBuiltinsTier0TableOffset, \
Builtins::kBuiltinTier0Count* kSystemPointerSize, builtin_tier0_table) \
\
V(kEmbedderDataOffset, Internals::kNumIsolateDataSlots* kSystemPointerSize, \
embedder_data) \
V(kFastCCallCallerFPOffset, kSystemPointerSize, fast_c_call_caller_fp) \
V(kFastCCallCallerPCOffset, kSystemPointerSize, fast_c_call_caller_pc) \
V(kFastApiCallTargetOffset, kSystemPointerSize, fast_api_call_target) \
V(kLongTaskStatsCounterOffset, kSizetSize, long_task_stats_counter) \
\
V(kRootsTableOffset, RootsTable::kEntriesCount* kSystemPointerSize, \
roots_table) \
V(kExternalReferenceTableOffset, ExternalReferenceTable::kSizeInBytes, \
external_reference_table) \
V(kThreadLocalTopOffset, ThreadLocalTop::kSizeInBytes, thread_local_top) \
V(kBuiltinEntryTableOffset, Builtins::kBuiltinCount* kSystemPointerSize, \
builtin_entry_table) \
V(kBuiltinTableOffset, Builtins::kBuiltinCount* kSystemPointerSize, \
builtin_table) \
\
V(kNewAllocationInfo, LinearAllocationArea::kSize, new_allocation_info) \
V(kOldAllocationInfo, LinearAllocationArea::kSize, old_allocation_info) \
ISOLATE_DATA_FIELDS_HEAP_SANDBOX(V) \
V(kStackIsIterableOffset, kUInt8Size, stack_is_iterable)
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
#define ISOLATE_DATA_FIELDS_HEAP_SANDBOX(V) \
V(kExternalPointerTableOffset, kSystemPointerSize * 3, external_pointer_table)
#else
#define ISOLATE_DATA_FIELDS_HEAP_SANDBOX(V)
#endif
class IsolateData final {
public:
IsolateData(Isolate* isolate, Address cage_base)
: cage_base_(cage_base), stack_guard_(isolate) {}
IsolateData(const IsolateData&) = delete;
IsolateData& operator=(const IsolateData&) = delete;
static constexpr intptr_t kIsolateRootBias = kRootRegisterBias;
Address isolate_root() const {
return reinterpret_cast<Address>(this) + kIsolateRootBias;
}
#define V(Offset, Size, Name) \
static constexpr int Name##_offset() { return Offset - kIsolateRootBias; }
ISOLATE_DATA_FIELDS(V)
#undef V
static constexpr int root_slot_offset(RootIndex root_index) {
return roots_table_offset() + RootsTable::offset_of(root_index);
}
static constexpr int BuiltinEntrySlotOffset(Builtin id) {
DCHECK(Builtins::IsBuiltinId(id));
return (Builtins::IsTier0(id) ? builtin_tier0_entry_table_offset()
: builtin_entry_table_offset()) +
Builtins::ToInt(id) * kSystemPointerSize;
}
static constexpr int builtin_slot_offset(int builtin_index) {
return BuiltinSlotOffset(Builtins::FromInt(builtin_index));
}
static constexpr int BuiltinSlotOffset(Builtin id) {
return (Builtins::IsTier0(id) ? builtin_tier0_table_offset()
: builtin_table_offset()) +
Builtins::ToInt(id) * kSystemPointerSize;
}
#define V(Offset, Size, Name) \
Address Name##_address() { return reinterpret_cast<Address>(&Name##_); }
ISOLATE_DATA_FIELDS(V)
#undef V
Address fast_c_call_caller_fp() const { return fast_c_call_caller_fp_; }
Address fast_c_call_caller_pc() const { return fast_c_call_caller_pc_; }
Address fast_api_call_target() const { return fast_api_call_target_; }
Address cage_base() const { return cage_base_; }
StackGuard* stack_guard() { return &stack_guard_; }
Address* builtin_tier0_entry_table() { return builtin_tier0_entry_table_; }
Address* builtin_tier0_table() { return builtin_tier0_table_; }
RootsTable& roots() { return roots_table_; }
const RootsTable& roots() const { return roots_table_; }
ExternalReferenceTable* external_reference_table() {
return &external_reference_table_;
}
ThreadLocalTop& thread_local_top() { return thread_local_top_; }
ThreadLocalTop const& thread_local_top() const { return thread_local_top_; }
Address* builtin_entry_table() { return builtin_entry_table_; }
Address* builtin_table() { return builtin_table_; }
uint8_t stack_is_iterable() const { return stack_is_iterable_; }
bool contains(Address address) const {
STATIC_ASSERT(std::is_unsigned<Address>::value);
Address start = reinterpret_cast<Address>(this);
return (address - start) < sizeof(*this);
}
private:
#define FIELDS(V) \
ISOLATE_DATA_FIELDS(V) \
\
V(kPaddingOffset, \
8 + RoundUp<8>(static_cast<int>(kPaddingOffset)) - kPaddingOffset) \
\
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(0, FIELDS)
#undef FIELDS
const Address cage_base_;
StackGuard stack_guard_;
Address builtin_tier0_entry_table_[Builtins::kBuiltinTier0Count] = {};
Address builtin_tier0_table_[Builtins::kBuiltinTier0Count] = {};
void* embedder_data_[Internals::kNumIsolateDataSlots] = {};
Address fast_c_call_caller_fp_ = kNullAddress;
Address fast_c_call_caller_pc_ = kNullAddress;
Address fast_api_call_target_ = kNullAddress;
size_t long_task_stats_counter_ = 0;
RootsTable roots_table_;
ExternalReferenceTable external_reference_table_;
ThreadLocalTop thread_local_top_;
Address builtin_entry_table_[Builtins::kBuiltinCount] = {};
Address builtin_table_[Builtins::kBuiltinCount] = {};
LinearAllocationArea new_allocation_info_;
LinearAllocationArea old_allocation_info_;
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
ExternalPointerTable external_pointer_table_;
#endif
uint8_t stack_is_iterable_ = 1;
STATIC_ASSERT(kPaddingOffsetEnd + 1 - kPaddingOffset >= 8);
char padding_[kPaddingOffsetEnd + 1 - kPaddingOffset];
V8_INLINE static void AssertPredictableLayout();
friend class Isolate;
friend class Heap;
FRIEND_TEST(HeapTest, ExternalLimitDefault);
FRIEND_TEST(HeapTest, ExternalLimitStaysAboveDefaultForExplicitHandling);
};
void IsolateData::AssertPredictableLayout() {
STATIC_ASSERT(std::is_standard_layout<RootsTable>::value);
STATIC_ASSERT(std::is_standard_layout<ThreadLocalTop>::value);
STATIC_ASSERT(std::is_standard_layout<ExternalReferenceTable>::value);
STATIC_ASSERT(std::is_standard_layout<IsolateData>::value);
#define V(Offset, Size, Name) \
STATIC_ASSERT(offsetof(IsolateData, Name##_) == Offset);
ISOLATE_DATA_FIELDS(V)
#undef V
STATIC_ASSERT(sizeof(IsolateData) == IsolateData::kSize);
}
#undef ISOLATE_DATA_FIELDS_HEAP_SANDBOX
#undef ISOLATE_DATA_FIELDS
}
}
#endif