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