11cb0ef41Sopenharmony_ci// Copyright 2018 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#ifndef INCLUDE_V8_INTERNAL_H_ 61cb0ef41Sopenharmony_ci#define INCLUDE_V8_INTERNAL_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <stddef.h> 91cb0ef41Sopenharmony_ci#include <stdint.h> 101cb0ef41Sopenharmony_ci#include <string.h> 111cb0ef41Sopenharmony_ci#include <type_traits> 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci#include "v8-version.h" // NOLINT(build/include_directory) 141cb0ef41Sopenharmony_ci#include "v8config.h" // NOLINT(build/include_directory) 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace v8 { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciclass Array; 191cb0ef41Sopenharmony_ciclass Context; 201cb0ef41Sopenharmony_ciclass Data; 211cb0ef41Sopenharmony_ciclass Isolate; 221cb0ef41Sopenharmony_citemplate <typename T> 231cb0ef41Sopenharmony_ciclass Local; 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_cinamespace internal { 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciclass Isolate; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_citypedef uintptr_t Address; 301cb0ef41Sopenharmony_cistatic const Address kNullAddress = 0; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ciconstexpr int KB = 1024; 331cb0ef41Sopenharmony_ciconstexpr int MB = KB * 1024; 341cb0ef41Sopenharmony_ciconstexpr int GB = MB * 1024; 351cb0ef41Sopenharmony_ci#ifdef V8_TARGET_ARCH_X64 361cb0ef41Sopenharmony_ciconstexpr size_t TB = size_t{GB} * 1024; 371cb0ef41Sopenharmony_ci#endif 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci/** 401cb0ef41Sopenharmony_ci * Configuration of tagging scheme. 411cb0ef41Sopenharmony_ci */ 421cb0ef41Sopenharmony_ciconst int kApiSystemPointerSize = sizeof(void*); 431cb0ef41Sopenharmony_ciconst int kApiDoubleSize = sizeof(double); 441cb0ef41Sopenharmony_ciconst int kApiInt32Size = sizeof(int32_t); 451cb0ef41Sopenharmony_ciconst int kApiInt64Size = sizeof(int64_t); 461cb0ef41Sopenharmony_ciconst int kApiSizetSize = sizeof(size_t); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci// Tag information for HeapObject. 491cb0ef41Sopenharmony_ciconst int kHeapObjectTag = 1; 501cb0ef41Sopenharmony_ciconst int kWeakHeapObjectTag = 3; 511cb0ef41Sopenharmony_ciconst int kHeapObjectTagSize = 2; 521cb0ef41Sopenharmony_ciconst intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1; 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci// Tag information for fowarding pointers stored in object headers. 551cb0ef41Sopenharmony_ci// 0b00 at the lowest 2 bits in the header indicates that the map word is a 561cb0ef41Sopenharmony_ci// forwarding pointer. 571cb0ef41Sopenharmony_ciconst int kForwardingTag = 0; 581cb0ef41Sopenharmony_ciconst int kForwardingTagSize = 2; 591cb0ef41Sopenharmony_ciconst intptr_t kForwardingTagMask = (1 << kForwardingTagSize) - 1; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci// Tag information for Smi. 621cb0ef41Sopenharmony_ciconst int kSmiTag = 0; 631cb0ef41Sopenharmony_ciconst int kSmiTagSize = 1; 641cb0ef41Sopenharmony_ciconst intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_citemplate <size_t tagged_ptr_size> 671cb0ef41Sopenharmony_cistruct SmiTagging; 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ciconstexpr intptr_t kIntptrAllBitsSet = intptr_t{-1}; 701cb0ef41Sopenharmony_ciconstexpr uintptr_t kUintptrAllBitsSet = 711cb0ef41Sopenharmony_ci static_cast<uintptr_t>(kIntptrAllBitsSet); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci// Smi constants for systems where tagged pointer is a 32-bit value. 741cb0ef41Sopenharmony_citemplate <> 751cb0ef41Sopenharmony_cistruct SmiTagging<4> { 761cb0ef41Sopenharmony_ci enum { kSmiShiftSize = 0, kSmiValueSize = 31 }; 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci static constexpr intptr_t kSmiMinValue = 791cb0ef41Sopenharmony_ci static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1)); 801cb0ef41Sopenharmony_ci static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci V8_INLINE static int SmiToInt(const internal::Address value) { 831cb0ef41Sopenharmony_ci int shift_bits = kSmiTagSize + kSmiShiftSize; 841cb0ef41Sopenharmony_ci // Truncate and shift down (requires >> to be sign extending). 851cb0ef41Sopenharmony_ci return static_cast<int32_t>(static_cast<uint32_t>(value)) >> shift_bits; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci V8_INLINE static constexpr bool IsValidSmi(intptr_t value) { 881cb0ef41Sopenharmony_ci // Is value in range [kSmiMinValue, kSmiMaxValue]. 891cb0ef41Sopenharmony_ci // Use unsigned operations in order to avoid undefined behaviour in case of 901cb0ef41Sopenharmony_ci // signed integer overflow. 911cb0ef41Sopenharmony_ci return (static_cast<uintptr_t>(value) - 921cb0ef41Sopenharmony_ci static_cast<uintptr_t>(kSmiMinValue)) <= 931cb0ef41Sopenharmony_ci (static_cast<uintptr_t>(kSmiMaxValue) - 941cb0ef41Sopenharmony_ci static_cast<uintptr_t>(kSmiMinValue)); 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci}; 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci// Smi constants for systems where tagged pointer is a 64-bit value. 991cb0ef41Sopenharmony_citemplate <> 1001cb0ef41Sopenharmony_cistruct SmiTagging<8> { 1011cb0ef41Sopenharmony_ci enum { kSmiShiftSize = 31, kSmiValueSize = 32 }; 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci static constexpr intptr_t kSmiMinValue = 1041cb0ef41Sopenharmony_ci static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1)); 1051cb0ef41Sopenharmony_ci static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci V8_INLINE static int SmiToInt(const internal::Address value) { 1081cb0ef41Sopenharmony_ci int shift_bits = kSmiTagSize + kSmiShiftSize; 1091cb0ef41Sopenharmony_ci // Shift down and throw away top 32 bits. 1101cb0ef41Sopenharmony_ci return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci V8_INLINE static constexpr bool IsValidSmi(intptr_t value) { 1131cb0ef41Sopenharmony_ci // To be representable as a long smi, the value must be a 32-bit integer. 1141cb0ef41Sopenharmony_ci return (value == static_cast<int32_t>(value)); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci}; 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS 1191cb0ef41Sopenharmony_ci// See v8:7703 or src/common/ptr-compr-inl.h for details about pointer 1201cb0ef41Sopenharmony_ci// compression. 1211cb0ef41Sopenharmony_ciconstexpr size_t kPtrComprCageReservationSize = size_t{1} << 32; 1221cb0ef41Sopenharmony_ciconstexpr size_t kPtrComprCageBaseAlignment = size_t{1} << 32; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_cistatic_assert( 1251cb0ef41Sopenharmony_ci kApiSystemPointerSize == kApiInt64Size, 1261cb0ef41Sopenharmony_ci "Pointer compression can be enabled only for 64-bit architectures"); 1271cb0ef41Sopenharmony_ciconst int kApiTaggedSize = kApiInt32Size; 1281cb0ef41Sopenharmony_ci#else 1291cb0ef41Sopenharmony_ciconst int kApiTaggedSize = kApiSystemPointerSize; 1301cb0ef41Sopenharmony_ci#endif 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ciconstexpr bool PointerCompressionIsEnabled() { 1331cb0ef41Sopenharmony_ci return kApiTaggedSize != kApiSystemPointerSize; 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci#ifdef V8_31BIT_SMIS_ON_64BIT_ARCH 1371cb0ef41Sopenharmony_ciusing PlatformSmiTagging = SmiTagging<kApiInt32Size>; 1381cb0ef41Sopenharmony_ci#else 1391cb0ef41Sopenharmony_ciusing PlatformSmiTagging = SmiTagging<kApiTaggedSize>; 1401cb0ef41Sopenharmony_ci#endif 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci// TODO(ishell): Consinder adding kSmiShiftBits = kSmiShiftSize + kSmiTagSize 1431cb0ef41Sopenharmony_ci// since it's used much more often than the inividual constants. 1441cb0ef41Sopenharmony_ciconst int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize; 1451cb0ef41Sopenharmony_ciconst int kSmiValueSize = PlatformSmiTagging::kSmiValueSize; 1461cb0ef41Sopenharmony_ciconst int kSmiMinValue = static_cast<int>(PlatformSmiTagging::kSmiMinValue); 1471cb0ef41Sopenharmony_ciconst int kSmiMaxValue = static_cast<int>(PlatformSmiTagging::kSmiMaxValue); 1481cb0ef41Sopenharmony_ciconstexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; } 1491cb0ef41Sopenharmony_ciconstexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ciV8_INLINE static constexpr internal::Address IntToSmi(int value) { 1521cb0ef41Sopenharmony_ci return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) | 1531cb0ef41Sopenharmony_ci kSmiTag; 1541cb0ef41Sopenharmony_ci} 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci/* 1571cb0ef41Sopenharmony_ci * Sandbox related types, constants, and functions. 1581cb0ef41Sopenharmony_ci */ 1591cb0ef41Sopenharmony_ciconstexpr bool SandboxIsEnabled() { 1601cb0ef41Sopenharmony_ci#ifdef V8_SANDBOX 1611cb0ef41Sopenharmony_ci return true; 1621cb0ef41Sopenharmony_ci#else 1631cb0ef41Sopenharmony_ci return false; 1641cb0ef41Sopenharmony_ci#endif 1651cb0ef41Sopenharmony_ci} 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ciconstexpr bool SandboxedExternalPointersAreEnabled() { 1681cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS 1691cb0ef41Sopenharmony_ci return true; 1701cb0ef41Sopenharmony_ci#else 1711cb0ef41Sopenharmony_ci return false; 1721cb0ef41Sopenharmony_ci#endif 1731cb0ef41Sopenharmony_ci} 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci// SandboxedPointers are guaranteed to point into the sandbox. This is achieved 1761cb0ef41Sopenharmony_ci// for example by storing them as offset rather than as raw pointers. 1771cb0ef41Sopenharmony_ciusing SandboxedPointer_t = Address; 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci// ExternalPointers point to objects located outside the sandbox. When sandboxed 1801cb0ef41Sopenharmony_ci// external pointers are enabled, these are stored in an external pointer table 1811cb0ef41Sopenharmony_ci// and referenced from HeapObjects through indices. 1821cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS 1831cb0ef41Sopenharmony_ciusing ExternalPointer_t = uint32_t; 1841cb0ef41Sopenharmony_ci#else 1851cb0ef41Sopenharmony_ciusing ExternalPointer_t = Address; 1861cb0ef41Sopenharmony_ci#endif 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci#ifdef V8_SANDBOX_IS_AVAILABLE 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci// Size of the sandbox, excluding the guard regions surrounding it. 1911cb0ef41Sopenharmony_ciconstexpr size_t kSandboxSizeLog2 = 40; // 1 TB 1921cb0ef41Sopenharmony_ciconstexpr size_t kSandboxSize = 1ULL << kSandboxSizeLog2; 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci// Required alignment of the sandbox. For simplicity, we require the 1951cb0ef41Sopenharmony_ci// size of the guard regions to be a multiple of this, so that this specifies 1961cb0ef41Sopenharmony_ci// the alignment of the sandbox including and excluding surrounding guard 1971cb0ef41Sopenharmony_ci// regions. The alignment requirement is due to the pointer compression cage 1981cb0ef41Sopenharmony_ci// being located at the start of the sandbox. 1991cb0ef41Sopenharmony_ciconstexpr size_t kSandboxAlignment = kPtrComprCageBaseAlignment; 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci// Sandboxed pointers are stored inside the heap as offset from the sandbox 2021cb0ef41Sopenharmony_ci// base shifted to the left. This way, it is guaranteed that the offset is 2031cb0ef41Sopenharmony_ci// smaller than the sandbox size after shifting it to the right again. This 2041cb0ef41Sopenharmony_ci// constant specifies the shift amount. 2051cb0ef41Sopenharmony_ciconstexpr uint64_t kSandboxedPointerShift = 64 - kSandboxSizeLog2; 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci// Size of the guard regions surrounding the sandbox. This assumes a worst-case 2081cb0ef41Sopenharmony_ci// scenario of a 32-bit unsigned index used to access an array of 64-bit 2091cb0ef41Sopenharmony_ci// values. 2101cb0ef41Sopenharmony_ciconstexpr size_t kSandboxGuardRegionSize = 32ULL * GB; 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_cistatic_assert((kSandboxGuardRegionSize % kSandboxAlignment) == 0, 2131cb0ef41Sopenharmony_ci "The size of the guard regions around the sandbox must be a " 2141cb0ef41Sopenharmony_ci "multiple of its required alignment."); 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci// Minimum size of the sandbox, excluding the guard regions surrounding it. If 2171cb0ef41Sopenharmony_ci// the virtual memory reservation for the sandbox fails, its size is currently 2181cb0ef41Sopenharmony_ci// halved until either the reservation succeeds or the minimum size is reached. 2191cb0ef41Sopenharmony_ci// A minimum of 32GB allows the 4GB pointer compression region as well as the 2201cb0ef41Sopenharmony_ci// ArrayBuffer partition and two 10GB Wasm memory cages to fit into the 2211cb0ef41Sopenharmony_ci// sandbox. 32GB should also be the minimum possible size of the userspace 2221cb0ef41Sopenharmony_ci// address space as there are some machine configurations with only 36 virtual 2231cb0ef41Sopenharmony_ci// address bits. 2241cb0ef41Sopenharmony_ciconstexpr size_t kSandboxMinimumSize = 32ULL * GB; 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_cistatic_assert(kSandboxMinimumSize <= kSandboxSize, 2271cb0ef41Sopenharmony_ci "The minimal size of the sandbox must be smaller or equal to the " 2281cb0ef41Sopenharmony_ci "regular size."); 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci// On OSes where reserving virtual memory is too expensive to reserve the 2311cb0ef41Sopenharmony_ci// entire address space backing the sandbox, notably Windows pre 8.1, we create 2321cb0ef41Sopenharmony_ci// a partially reserved sandbox that doesn't actually reserve most of the 2331cb0ef41Sopenharmony_ci// memory, and so doesn't have the desired security properties as unrelated 2341cb0ef41Sopenharmony_ci// memory allocations could end up inside of it, but which still ensures that 2351cb0ef41Sopenharmony_ci// objects that should be located inside the sandbox are allocated within 2361cb0ef41Sopenharmony_ci// kSandboxSize bytes from the start of the sandbox. The minimum size of the 2371cb0ef41Sopenharmony_ci// region that is actually reserved for such a sandbox is specified by this 2381cb0ef41Sopenharmony_ci// constant and should be big enough to contain the pointer compression cage as 2391cb0ef41Sopenharmony_ci// well as the ArrayBuffer partition. 2401cb0ef41Sopenharmony_ciconstexpr size_t kSandboxMinimumReservationSize = 8ULL * GB; 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_cistatic_assert(kSandboxMinimumSize > kPtrComprCageReservationSize, 2431cb0ef41Sopenharmony_ci "The sandbox must be larger than the pointer compression cage " 2441cb0ef41Sopenharmony_ci "contained within it."); 2451cb0ef41Sopenharmony_cistatic_assert(kSandboxMinimumReservationSize > kPtrComprCageReservationSize, 2461cb0ef41Sopenharmony_ci "The minimum reservation size for a sandbox must be larger than " 2471cb0ef41Sopenharmony_ci "the pointer compression cage contained within it."); 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci// For now, even if the sandbox is enabled, we still allow backing stores to be 2501cb0ef41Sopenharmony_ci// allocated outside of it as fallback. This will simplify the initial rollout. 2511cb0ef41Sopenharmony_ci// However, if sandboxed pointers are also enabled, we must always place 2521cb0ef41Sopenharmony_ci// backing stores inside the sandbox as they will be referenced though them. 2531cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_POINTERS 2541cb0ef41Sopenharmony_ciconstexpr bool kAllowBackingStoresOutsideSandbox = false; 2551cb0ef41Sopenharmony_ci#else 2561cb0ef41Sopenharmony_ciconstexpr bool kAllowBackingStoresOutsideSandbox = true; 2571cb0ef41Sopenharmony_ci#endif // V8_SANDBOXED_POINTERS 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci// The size of the virtual memory reservation for an external pointer table. 2601cb0ef41Sopenharmony_ci// This determines the maximum number of entries in a table. Using a maximum 2611cb0ef41Sopenharmony_ci// size allows omitting bounds checks on table accesses if the indices are 2621cb0ef41Sopenharmony_ci// guaranteed (e.g. through shifting) to be below the maximum index. This 2631cb0ef41Sopenharmony_ci// value must be a power of two. 2641cb0ef41Sopenharmony_cistatic const size_t kExternalPointerTableReservationSize = 128 * MB; 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci// The maximum number of entries in an external pointer table. 2671cb0ef41Sopenharmony_cistatic const size_t kMaxSandboxedExternalPointers = 2681cb0ef41Sopenharmony_ci kExternalPointerTableReservationSize / kApiSystemPointerSize; 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci// The external pointer table indices stored in HeapObjects as external 2711cb0ef41Sopenharmony_ci// pointers are shifted to the left by this amount to guarantee that they are 2721cb0ef41Sopenharmony_ci// smaller than the maximum table size. 2731cb0ef41Sopenharmony_cistatic const uint32_t kExternalPointerIndexShift = 8; 2741cb0ef41Sopenharmony_cistatic_assert((1 << (32 - kExternalPointerIndexShift)) == 2751cb0ef41Sopenharmony_ci kMaxSandboxedExternalPointers, 2761cb0ef41Sopenharmony_ci "kExternalPointerTableReservationSize and " 2771cb0ef41Sopenharmony_ci "kExternalPointerIndexShift don't match"); 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci#endif // V8_SANDBOX_IS_AVAILABLE 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci// If sandboxed external pointers are enabled, these tag values will be ORed 2821cb0ef41Sopenharmony_ci// with the external pointers in the external pointer table to prevent use of 2831cb0ef41Sopenharmony_ci// pointers of the wrong type. When a pointer is loaded, it is ANDed with the 2841cb0ef41Sopenharmony_ci// inverse of the expected type's tag. The tags are constructed in a way that 2851cb0ef41Sopenharmony_ci// guarantees that a failed type check will result in one or more of the top 2861cb0ef41Sopenharmony_ci// bits of the pointer to be set, rendering the pointer inacessible. Besides 2871cb0ef41Sopenharmony_ci// the type tag bits (48 through 62), the tags also have the GC mark bit (63) 2881cb0ef41Sopenharmony_ci// set, so that the mark bit is automatically set when a pointer is written 2891cb0ef41Sopenharmony_ci// into the external pointer table (in which case it is clearly alive) and is 2901cb0ef41Sopenharmony_ci// cleared when the pointer is loaded. The exception to this is the free entry 2911cb0ef41Sopenharmony_ci// tag, which doesn't have the mark bit set, as the entry is not alive. This 2921cb0ef41Sopenharmony_ci// construction allows performing the type check and removing GC marking bits 2931cb0ef41Sopenharmony_ci// (the MSB) from the pointer at the same time. 2941cb0ef41Sopenharmony_ci// Note: this scheme assumes a 48-bit address space and will likely break if 2951cb0ef41Sopenharmony_ci// more virtual address bits are used. 2961cb0ef41Sopenharmony_ciconstexpr uint64_t kExternalPointerTagMask = 0xffff000000000000; 2971cb0ef41Sopenharmony_ciconstexpr uint64_t kExternalPointerTagShift = 48; 2981cb0ef41Sopenharmony_ci#define MAKE_TAG(v) (static_cast<uint64_t>(v) << kExternalPointerTagShift) 2991cb0ef41Sopenharmony_ci// clang-format off 3001cb0ef41Sopenharmony_cienum ExternalPointerTag : uint64_t { 3011cb0ef41Sopenharmony_ci kExternalPointerNullTag = MAKE_TAG(0b0000000000000000), 3021cb0ef41Sopenharmony_ci kExternalPointerFreeEntryTag = MAKE_TAG(0b0111111110000000), 3031cb0ef41Sopenharmony_ci kExternalStringResourceTag = MAKE_TAG(0b1000000011111111), 3041cb0ef41Sopenharmony_ci kExternalStringResourceDataTag = MAKE_TAG(0b1000000101111111), 3051cb0ef41Sopenharmony_ci kForeignForeignAddressTag = MAKE_TAG(0b1000000110111111), 3061cb0ef41Sopenharmony_ci kNativeContextMicrotaskQueueTag = MAKE_TAG(0b1000000111011111), 3071cb0ef41Sopenharmony_ci kEmbedderDataSlotPayloadTag = MAKE_TAG(0b1000000111101111), 3081cb0ef41Sopenharmony_ci kCodeEntryPointTag = MAKE_TAG(0b1000000111110111), 3091cb0ef41Sopenharmony_ci kExternalObjectValueTag = MAKE_TAG(0b1000000111111011), 3101cb0ef41Sopenharmony_ci}; 3111cb0ef41Sopenharmony_ci// clang-format on 3121cb0ef41Sopenharmony_ci#undef MAKE_TAG 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci// Converts encoded external pointer to address. 3151cb0ef41Sopenharmony_ciV8_EXPORT Address DecodeExternalPointerImpl(const Isolate* isolate, 3161cb0ef41Sopenharmony_ci ExternalPointer_t pointer, 3171cb0ef41Sopenharmony_ci ExternalPointerTag tag); 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci// {obj} must be the raw tagged pointer representation of a HeapObject 3201cb0ef41Sopenharmony_ci// that's guaranteed to never be in ReadOnlySpace. 3211cb0ef41Sopenharmony_ciV8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj); 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci// Returns if we need to throw when an error occurs. This infers the language 3241cb0ef41Sopenharmony_ci// mode based on the current context and the closure. This returns true if the 3251cb0ef41Sopenharmony_ci// language mode is strict. 3261cb0ef41Sopenharmony_ciV8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate); 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ciV8_EXPORT bool CanHaveInternalField(int instance_type); 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci/** 3311cb0ef41Sopenharmony_ci * This class exports constants and functionality from within v8 that 3321cb0ef41Sopenharmony_ci * is necessary to implement inline functions in the v8 api. Don't 3331cb0ef41Sopenharmony_ci * depend on functions and constants defined here. 3341cb0ef41Sopenharmony_ci */ 3351cb0ef41Sopenharmony_ciclass Internals { 3361cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING 3371cb0ef41Sopenharmony_ci V8_INLINE static constexpr internal::Address UnpackMapWord( 3381cb0ef41Sopenharmony_ci internal::Address mapword) { 3391cb0ef41Sopenharmony_ci // TODO(wenyuzhao): Clear header metadata. 3401cb0ef41Sopenharmony_ci return mapword ^ kMapWordXorMask; 3411cb0ef41Sopenharmony_ci } 3421cb0ef41Sopenharmony_ci#endif 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci public: 3451cb0ef41Sopenharmony_ci // These values match non-compiler-dependent values defined within 3461cb0ef41Sopenharmony_ci // the implementation of v8. 3471cb0ef41Sopenharmony_ci static const int kHeapObjectMapOffset = 0; 3481cb0ef41Sopenharmony_ci static const int kMapInstanceTypeOffset = 1 * kApiTaggedSize + kApiInt32Size; 3491cb0ef41Sopenharmony_ci static const int kStringResourceOffset = 3501cb0ef41Sopenharmony_ci 1 * kApiTaggedSize + 2 * kApiInt32Size; 3511cb0ef41Sopenharmony_ci 3521cb0ef41Sopenharmony_ci static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize; 3531cb0ef41Sopenharmony_ci static const int kJSObjectHeaderSize = 3 * kApiTaggedSize; 3541cb0ef41Sopenharmony_ci static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize; 3551cb0ef41Sopenharmony_ci static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize; 3561cb0ef41Sopenharmony_ci static const int kEmbedderDataSlotSize = kApiSystemPointerSize; 3571cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS 3581cb0ef41Sopenharmony_ci static const int kEmbedderDataSlotRawPayloadOffset = kApiTaggedSize; 3591cb0ef41Sopenharmony_ci#endif 3601cb0ef41Sopenharmony_ci static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize; 3611cb0ef41Sopenharmony_ci static const int kStringRepresentationAndEncodingMask = 0x0f; 3621cb0ef41Sopenharmony_ci static const int kStringEncodingMask = 0x8; 3631cb0ef41Sopenharmony_ci static const int kExternalTwoByteRepresentationTag = 0x02; 3641cb0ef41Sopenharmony_ci static const int kExternalOneByteRepresentationTag = 0x0a; 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci static const uint32_t kNumIsolateDataSlots = 4; 3671cb0ef41Sopenharmony_ci static const int kStackGuardSize = 7 * kApiSystemPointerSize; 3681cb0ef41Sopenharmony_ci static const int kBuiltinTier0EntryTableSize = 10 * kApiSystemPointerSize; 3691cb0ef41Sopenharmony_ci static const int kBuiltinTier0TableSize = 10 * kApiSystemPointerSize; 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci // IsolateData layout guarantees. 3721cb0ef41Sopenharmony_ci static const int kIsolateCageBaseOffset = 0; 3731cb0ef41Sopenharmony_ci static const int kIsolateStackGuardOffset = 3741cb0ef41Sopenharmony_ci kIsolateCageBaseOffset + kApiSystemPointerSize; 3751cb0ef41Sopenharmony_ci static const int kBuiltinTier0EntryTableOffset = 3761cb0ef41Sopenharmony_ci kIsolateStackGuardOffset + kStackGuardSize; 3771cb0ef41Sopenharmony_ci static const int kBuiltinTier0TableOffset = 3781cb0ef41Sopenharmony_ci kBuiltinTier0EntryTableOffset + kBuiltinTier0EntryTableSize; 3791cb0ef41Sopenharmony_ci static const int kIsolateEmbedderDataOffset = 3801cb0ef41Sopenharmony_ci kBuiltinTier0TableOffset + kBuiltinTier0TableSize; 3811cb0ef41Sopenharmony_ci static const int kIsolateFastCCallCallerFpOffset = 3821cb0ef41Sopenharmony_ci kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize; 3831cb0ef41Sopenharmony_ci static const int kIsolateFastCCallCallerPcOffset = 3841cb0ef41Sopenharmony_ci kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize; 3851cb0ef41Sopenharmony_ci static const int kIsolateFastApiCallTargetOffset = 3861cb0ef41Sopenharmony_ci kIsolateFastCCallCallerPcOffset + kApiSystemPointerSize; 3871cb0ef41Sopenharmony_ci static const int kIsolateLongTaskStatsCounterOffset = 3881cb0ef41Sopenharmony_ci kIsolateFastApiCallTargetOffset + kApiSystemPointerSize; 3891cb0ef41Sopenharmony_ci static const int kIsolateRootsOffset = 3901cb0ef41Sopenharmony_ci kIsolateLongTaskStatsCounterOffset + kApiSizetSize; 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci static const int kExternalPointerTableBufferOffset = 0; 3931cb0ef41Sopenharmony_ci static const int kExternalPointerTableCapacityOffset = 3941cb0ef41Sopenharmony_ci kExternalPointerTableBufferOffset + kApiSystemPointerSize; 3951cb0ef41Sopenharmony_ci static const int kExternalPointerTableFreelistHeadOffset = 3961cb0ef41Sopenharmony_ci kExternalPointerTableCapacityOffset + kApiInt32Size; 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci static const int kUndefinedValueRootIndex = 4; 3991cb0ef41Sopenharmony_ci static const int kTheHoleValueRootIndex = 5; 4001cb0ef41Sopenharmony_ci static const int kNullValueRootIndex = 6; 4011cb0ef41Sopenharmony_ci static const int kTrueValueRootIndex = 7; 4021cb0ef41Sopenharmony_ci static const int kFalseValueRootIndex = 8; 4031cb0ef41Sopenharmony_ci static const int kEmptyStringRootIndex = 9; 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize; 4061cb0ef41Sopenharmony_ci static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3; 4071cb0ef41Sopenharmony_ci static const int kNodeStateMask = 0x7; 4081cb0ef41Sopenharmony_ci static const int kNodeStateIsWeakValue = 2; 4091cb0ef41Sopenharmony_ci static const int kNodeStateIsPendingValue = 3; 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci static const int kFirstNonstringType = 0x80; 4121cb0ef41Sopenharmony_ci static const int kOddballType = 0x83; 4131cb0ef41Sopenharmony_ci static const int kForeignType = 0xcc; 4141cb0ef41Sopenharmony_ci static const int kJSSpecialApiObjectType = 0x410; 4151cb0ef41Sopenharmony_ci static const int kJSObjectType = 0x421; 4161cb0ef41Sopenharmony_ci static const int kFirstJSApiObjectType = 0x422; 4171cb0ef41Sopenharmony_ci static const int kLastJSApiObjectType = 0x80A; 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci static const int kUndefinedOddballKind = 5; 4201cb0ef41Sopenharmony_ci static const int kNullOddballKind = 3; 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci // Constants used by PropertyCallbackInfo to check if we should throw when an 4231cb0ef41Sopenharmony_ci // error occurs. 4241cb0ef41Sopenharmony_ci static const int kThrowOnError = 0; 4251cb0ef41Sopenharmony_ci static const int kDontThrow = 1; 4261cb0ef41Sopenharmony_ci static const int kInferShouldThrowMode = 2; 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an 4291cb0ef41Sopenharmony_ci // incremental GC once the external memory reaches this limit. 4301cb0ef41Sopenharmony_ci static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024; 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING 4331cb0ef41Sopenharmony_ci static const uintptr_t kMapWordMetadataMask = 0xffffULL << 48; 4341cb0ef41Sopenharmony_ci // The lowest two bits of mapwords are always `0b10` 4351cb0ef41Sopenharmony_ci static const uintptr_t kMapWordSignature = 0b10; 4361cb0ef41Sopenharmony_ci // XORing a (non-compressed) map with this mask ensures that the two 4371cb0ef41Sopenharmony_ci // low-order bits are 0b10. The 0 at the end makes this look like a Smi, 4381cb0ef41Sopenharmony_ci // although real Smis have all lower 32 bits unset. We only rely on these 4391cb0ef41Sopenharmony_ci // values passing as Smis in very few places. 4401cb0ef41Sopenharmony_ci static const int kMapWordXorMask = 0b11; 4411cb0ef41Sopenharmony_ci#endif 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ci V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate); 4441cb0ef41Sopenharmony_ci V8_INLINE static void CheckInitialized(v8::Isolate* isolate) { 4451cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_CHECKS 4461cb0ef41Sopenharmony_ci CheckInitializedImpl(isolate); 4471cb0ef41Sopenharmony_ci#endif 4481cb0ef41Sopenharmony_ci } 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci V8_INLINE static bool HasHeapObjectTag(const internal::Address value) { 4511cb0ef41Sopenharmony_ci return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag); 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci V8_INLINE static int SmiValue(const internal::Address value) { 4551cb0ef41Sopenharmony_ci return PlatformSmiTagging::SmiToInt(value); 4561cb0ef41Sopenharmony_ci } 4571cb0ef41Sopenharmony_ci 4581cb0ef41Sopenharmony_ci V8_INLINE static constexpr internal::Address IntToSmi(int value) { 4591cb0ef41Sopenharmony_ci return internal::IntToSmi(value); 4601cb0ef41Sopenharmony_ci } 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci V8_INLINE static constexpr bool IsValidSmi(intptr_t value) { 4631cb0ef41Sopenharmony_ci return PlatformSmiTagging::IsValidSmi(value); 4641cb0ef41Sopenharmony_ci } 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci V8_INLINE static int GetInstanceType(const internal::Address obj) { 4671cb0ef41Sopenharmony_ci typedef internal::Address A; 4681cb0ef41Sopenharmony_ci A map = ReadTaggedPointerField(obj, kHeapObjectMapOffset); 4691cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING 4701cb0ef41Sopenharmony_ci map = UnpackMapWord(map); 4711cb0ef41Sopenharmony_ci#endif 4721cb0ef41Sopenharmony_ci return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset); 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci V8_INLINE static int GetOddballKind(const internal::Address obj) { 4761cb0ef41Sopenharmony_ci return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset)); 4771cb0ef41Sopenharmony_ci } 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci V8_INLINE static bool IsExternalTwoByteString(int instance_type) { 4801cb0ef41Sopenharmony_ci int representation = (instance_type & kStringRepresentationAndEncodingMask); 4811cb0ef41Sopenharmony_ci return representation == kExternalTwoByteRepresentationTag; 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci V8_INLINE static uint8_t GetNodeFlag(internal::Address* obj, int shift) { 4851cb0ef41Sopenharmony_ci uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; 4861cb0ef41Sopenharmony_ci return *addr & static_cast<uint8_t>(1U << shift); 4871cb0ef41Sopenharmony_ci } 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci V8_INLINE static void UpdateNodeFlag(internal::Address* obj, bool value, 4901cb0ef41Sopenharmony_ci int shift) { 4911cb0ef41Sopenharmony_ci uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; 4921cb0ef41Sopenharmony_ci uint8_t mask = static_cast<uint8_t>(1U << shift); 4931cb0ef41Sopenharmony_ci *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift)); 4941cb0ef41Sopenharmony_ci } 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ci V8_INLINE static uint8_t GetNodeState(internal::Address* obj) { 4971cb0ef41Sopenharmony_ci uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; 4981cb0ef41Sopenharmony_ci return *addr & kNodeStateMask; 4991cb0ef41Sopenharmony_ci } 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci V8_INLINE static void UpdateNodeState(internal::Address* obj, uint8_t value) { 5021cb0ef41Sopenharmony_ci uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; 5031cb0ef41Sopenharmony_ci *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value); 5041cb0ef41Sopenharmony_ci } 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot, 5071cb0ef41Sopenharmony_ci void* data) { 5081cb0ef41Sopenharmony_ci internal::Address addr = reinterpret_cast<internal::Address>(isolate) + 5091cb0ef41Sopenharmony_ci kIsolateEmbedderDataOffset + 5101cb0ef41Sopenharmony_ci slot * kApiSystemPointerSize; 5111cb0ef41Sopenharmony_ci *reinterpret_cast<void**>(addr) = data; 5121cb0ef41Sopenharmony_ci } 5131cb0ef41Sopenharmony_ci 5141cb0ef41Sopenharmony_ci V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate, 5151cb0ef41Sopenharmony_ci uint32_t slot) { 5161cb0ef41Sopenharmony_ci internal::Address addr = reinterpret_cast<internal::Address>(isolate) + 5171cb0ef41Sopenharmony_ci kIsolateEmbedderDataOffset + 5181cb0ef41Sopenharmony_ci slot * kApiSystemPointerSize; 5191cb0ef41Sopenharmony_ci return *reinterpret_cast<void* const*>(addr); 5201cb0ef41Sopenharmony_ci } 5211cb0ef41Sopenharmony_ci 5221cb0ef41Sopenharmony_ci V8_INLINE static void IncrementLongTasksStatsCounter(v8::Isolate* isolate) { 5231cb0ef41Sopenharmony_ci internal::Address addr = reinterpret_cast<internal::Address>(isolate) + 5241cb0ef41Sopenharmony_ci kIsolateLongTaskStatsCounterOffset; 5251cb0ef41Sopenharmony_ci ++(*reinterpret_cast<size_t*>(addr)); 5261cb0ef41Sopenharmony_ci } 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci V8_INLINE static internal::Address* GetRoot(v8::Isolate* isolate, int index) { 5291cb0ef41Sopenharmony_ci internal::Address addr = reinterpret_cast<internal::Address>(isolate) + 5301cb0ef41Sopenharmony_ci kIsolateRootsOffset + 5311cb0ef41Sopenharmony_ci index * kApiSystemPointerSize; 5321cb0ef41Sopenharmony_ci return reinterpret_cast<internal::Address*>(addr); 5331cb0ef41Sopenharmony_ci } 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci template <typename T> 5361cb0ef41Sopenharmony_ci V8_INLINE static T ReadRawField(internal::Address heap_object_ptr, 5371cb0ef41Sopenharmony_ci int offset) { 5381cb0ef41Sopenharmony_ci internal::Address addr = heap_object_ptr + offset - kHeapObjectTag; 5391cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS 5401cb0ef41Sopenharmony_ci if (sizeof(T) > kApiTaggedSize) { 5411cb0ef41Sopenharmony_ci // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size 5421cb0ef41Sopenharmony_ci // fields (external pointers, doubles and BigInt data) are only 5431cb0ef41Sopenharmony_ci // kTaggedSize aligned so we have to use unaligned pointer friendly way of 5441cb0ef41Sopenharmony_ci // accessing them in order to avoid undefined behavior in C++ code. 5451cb0ef41Sopenharmony_ci T r; 5461cb0ef41Sopenharmony_ci memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T)); 5471cb0ef41Sopenharmony_ci return r; 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci#endif 5501cb0ef41Sopenharmony_ci return *reinterpret_cast<const T*>(addr); 5511cb0ef41Sopenharmony_ci } 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci V8_INLINE static internal::Address ReadTaggedPointerField( 5541cb0ef41Sopenharmony_ci internal::Address heap_object_ptr, int offset) { 5551cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS 5561cb0ef41Sopenharmony_ci uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset); 5571cb0ef41Sopenharmony_ci internal::Address base = 5581cb0ef41Sopenharmony_ci GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr); 5591cb0ef41Sopenharmony_ci return base + static_cast<internal::Address>(static_cast<uintptr_t>(value)); 5601cb0ef41Sopenharmony_ci#else 5611cb0ef41Sopenharmony_ci return ReadRawField<internal::Address>(heap_object_ptr, offset); 5621cb0ef41Sopenharmony_ci#endif 5631cb0ef41Sopenharmony_ci } 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci V8_INLINE static internal::Address ReadTaggedSignedField( 5661cb0ef41Sopenharmony_ci internal::Address heap_object_ptr, int offset) { 5671cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS 5681cb0ef41Sopenharmony_ci uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset); 5691cb0ef41Sopenharmony_ci return static_cast<internal::Address>(static_cast<uintptr_t>(value)); 5701cb0ef41Sopenharmony_ci#else 5711cb0ef41Sopenharmony_ci return ReadRawField<internal::Address>(heap_object_ptr, offset); 5721cb0ef41Sopenharmony_ci#endif 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci V8_INLINE static internal::Isolate* GetIsolateForSandbox( 5761cb0ef41Sopenharmony_ci internal::Address obj) { 5771cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS 5781cb0ef41Sopenharmony_ci return internal::IsolateFromNeverReadOnlySpaceObject(obj); 5791cb0ef41Sopenharmony_ci#else 5801cb0ef41Sopenharmony_ci // Not used in non-sandbox mode. 5811cb0ef41Sopenharmony_ci return nullptr; 5821cb0ef41Sopenharmony_ci#endif 5831cb0ef41Sopenharmony_ci } 5841cb0ef41Sopenharmony_ci 5851cb0ef41Sopenharmony_ci V8_INLINE static Address DecodeExternalPointer( 5861cb0ef41Sopenharmony_ci const Isolate* isolate, ExternalPointer_t encoded_pointer, 5871cb0ef41Sopenharmony_ci ExternalPointerTag tag) { 5881cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS 5891cb0ef41Sopenharmony_ci return internal::DecodeExternalPointerImpl(isolate, encoded_pointer, tag); 5901cb0ef41Sopenharmony_ci#else 5911cb0ef41Sopenharmony_ci return encoded_pointer; 5921cb0ef41Sopenharmony_ci#endif 5931cb0ef41Sopenharmony_ci } 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_ci V8_INLINE static internal::Address ReadExternalPointerField( 5961cb0ef41Sopenharmony_ci internal::Isolate* isolate, internal::Address heap_object_ptr, int offset, 5971cb0ef41Sopenharmony_ci ExternalPointerTag tag) { 5981cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS 5991cb0ef41Sopenharmony_ci internal::ExternalPointer_t encoded_value = 6001cb0ef41Sopenharmony_ci ReadRawField<uint32_t>(heap_object_ptr, offset); 6011cb0ef41Sopenharmony_ci // We currently have to treat zero as nullptr in embedder slots. 6021cb0ef41Sopenharmony_ci return encoded_value ? DecodeExternalPointer(isolate, encoded_value, tag) 6031cb0ef41Sopenharmony_ci : 0; 6041cb0ef41Sopenharmony_ci#else 6051cb0ef41Sopenharmony_ci return ReadRawField<Address>(heap_object_ptr, offset); 6061cb0ef41Sopenharmony_ci#endif 6071cb0ef41Sopenharmony_ci } 6081cb0ef41Sopenharmony_ci 6091cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS 6101cb0ef41Sopenharmony_ci V8_INLINE static internal::Address GetPtrComprCageBaseFromOnHeapAddress( 6111cb0ef41Sopenharmony_ci internal::Address addr) { 6121cb0ef41Sopenharmony_ci return addr & -static_cast<intptr_t>(kPtrComprCageBaseAlignment); 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ci V8_INLINE static internal::Address DecompressTaggedAnyField( 6161cb0ef41Sopenharmony_ci internal::Address heap_object_ptr, uint32_t value) { 6171cb0ef41Sopenharmony_ci internal::Address base = 6181cb0ef41Sopenharmony_ci GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr); 6191cb0ef41Sopenharmony_ci return base + static_cast<internal::Address>(static_cast<uintptr_t>(value)); 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci#endif // V8_COMPRESS_POINTERS 6231cb0ef41Sopenharmony_ci}; 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci// Only perform cast check for types derived from v8::Data since 6261cb0ef41Sopenharmony_ci// other types do not implement the Cast method. 6271cb0ef41Sopenharmony_citemplate <bool PerformCheck> 6281cb0ef41Sopenharmony_cistruct CastCheck { 6291cb0ef41Sopenharmony_ci template <class T> 6301cb0ef41Sopenharmony_ci static void Perform(T* data); 6311cb0ef41Sopenharmony_ci}; 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_citemplate <> 6341cb0ef41Sopenharmony_citemplate <class T> 6351cb0ef41Sopenharmony_civoid CastCheck<true>::Perform(T* data) { 6361cb0ef41Sopenharmony_ci T::Cast(data); 6371cb0ef41Sopenharmony_ci} 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_citemplate <> 6401cb0ef41Sopenharmony_citemplate <class T> 6411cb0ef41Sopenharmony_civoid CastCheck<false>::Perform(T* data) {} 6421cb0ef41Sopenharmony_ci 6431cb0ef41Sopenharmony_citemplate <class T> 6441cb0ef41Sopenharmony_ciV8_INLINE void PerformCastCheck(T* data) { 6451cb0ef41Sopenharmony_ci CastCheck<std::is_base_of<Data, T>::value && 6461cb0ef41Sopenharmony_ci !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data); 6471cb0ef41Sopenharmony_ci} 6481cb0ef41Sopenharmony_ci 6491cb0ef41Sopenharmony_ci// A base class for backing stores, which is needed due to vagaries of 6501cb0ef41Sopenharmony_ci// how static casts work with std::shared_ptr. 6511cb0ef41Sopenharmony_ciclass BackingStoreBase {}; 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci// The maximum value in enum GarbageCollectionReason, defined in heap.h. 6541cb0ef41Sopenharmony_ci// This is needed for histograms sampling garbage collection reasons. 6551cb0ef41Sopenharmony_ciconstexpr int kGarbageCollectionReasonMaxValue = 25; 6561cb0ef41Sopenharmony_ci 6571cb0ef41Sopenharmony_ci} // namespace internal 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci} // namespace v8 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci#endif // INCLUDE_V8_INTERNAL_H_ 662