LCOV - code coverage report
Current view: top level - src - globals.h (source / functions) Hit Total Coverage
Test: app.info Lines: 33 102 32.4 %
Date: 2019-02-19 Functions: 9 22 40.9 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_GLOBALS_H_
       6             : #define V8_GLOBALS_H_
       7             : 
       8             : #include <stddef.h>
       9             : #include <stdint.h>
      10             : 
      11             : #include <limits>
      12             : #include <ostream>
      13             : 
      14             : #include "include/v8-internal.h"
      15             : #include "src/base/atomic-utils.h"
      16             : #include "src/base/build_config.h"
      17             : #include "src/base/flags.h"
      18             : #include "src/base/logging.h"
      19             : #include "src/base/macros.h"
      20             : 
      21             : #define V8_INFINITY std::numeric_limits<double>::infinity()
      22             : 
      23             : namespace v8 {
      24             : 
      25             : namespace base {
      26             : class Mutex;
      27             : class RecursiveMutex;
      28             : }
      29             : 
      30             : namespace internal {
      31             : 
      32             : // Determine whether we are running in a simulated environment.
      33             : // Setting USE_SIMULATOR explicitly from the build script will force
      34             : // the use of a simulated environment.
      35             : #if !defined(USE_SIMULATOR)
      36             : #if (V8_TARGET_ARCH_ARM64 && !V8_HOST_ARCH_ARM64)
      37             : #define USE_SIMULATOR 1
      38             : #endif
      39             : #if (V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM)
      40             : #define USE_SIMULATOR 1
      41             : #endif
      42             : #if (V8_TARGET_ARCH_PPC && !V8_HOST_ARCH_PPC)
      43             : #define USE_SIMULATOR 1
      44             : #endif
      45             : #if (V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS)
      46             : #define USE_SIMULATOR 1
      47             : #endif
      48             : #if (V8_TARGET_ARCH_MIPS64 && !V8_HOST_ARCH_MIPS64)
      49             : #define USE_SIMULATOR 1
      50             : #endif
      51             : #if (V8_TARGET_ARCH_S390 && !V8_HOST_ARCH_S390)
      52             : #define USE_SIMULATOR 1
      53             : #endif
      54             : #endif
      55             : 
      56             : // Determine whether the architecture uses an embedded constant pool
      57             : // (contiguous constant pool embedded in code object).
      58             : #if V8_TARGET_ARCH_PPC
      59             : #define V8_EMBEDDED_CONSTANT_POOL true
      60             : #else
      61             : #define V8_EMBEDDED_CONSTANT_POOL false
      62             : #endif
      63             : 
      64             : #ifdef V8_TARGET_ARCH_ARM
      65             : // Set stack limit lower for ARM than for other architectures because
      66             : // stack allocating MacroAssembler takes 120K bytes.
      67             : // See issue crbug.com/405338
      68             : #define V8_DEFAULT_STACK_SIZE_KB 864
      69             : #else
      70             : // Slightly less than 1MB, since Windows' default stack size for
      71             : // the main execution thread is 1MB for both 32 and 64-bit.
      72             : #define V8_DEFAULT_STACK_SIZE_KB 984
      73             : #endif
      74             : 
      75             : // Minimum stack size in KB required by compilers.
      76             : constexpr int kStackSpaceRequiredForCompilation = 40;
      77             : 
      78             : // Determine whether double field unboxing feature is enabled.
      79             : #if V8_TARGET_ARCH_64_BIT
      80             : #define V8_DOUBLE_FIELDS_UNBOXING true
      81             : #else
      82             : #define V8_DOUBLE_FIELDS_UNBOXING false
      83             : #endif
      84             : 
      85             : // Some types of tracing require the SFI to store a unique ID.
      86             : #if defined(V8_TRACE_MAPS) || defined(V8_TRACE_IGNITION)
      87             : #define V8_SFI_HAS_UNIQUE_ID true
      88             : #endif
      89             : 
      90             : // Superclass for classes only using static method functions.
      91             : // The subclass of AllStatic cannot be instantiated at all.
      92             : class AllStatic {
      93             : #ifdef DEBUG
      94             :  public:
      95             :   AllStatic() = delete;
      96             : #endif
      97             : };
      98             : 
      99             : typedef uint8_t byte;
     100             : 
     101             : // -----------------------------------------------------------------------------
     102             : // Constants
     103             : 
     104             : constexpr int KB = 1024;
     105             : constexpr int MB = KB * KB;
     106             : constexpr int GB = KB * KB * KB;
     107             : constexpr int kMaxInt = 0x7FFFFFFF;
     108             : constexpr int kMinInt = -kMaxInt - 1;
     109             : constexpr int kMaxInt8 = (1 << 7) - 1;
     110             : constexpr int kMinInt8 = -(1 << 7);
     111             : constexpr int kMaxUInt8 = (1 << 8) - 1;
     112             : constexpr int kMinUInt8 = 0;
     113             : constexpr int kMaxInt16 = (1 << 15) - 1;
     114             : constexpr int kMinInt16 = -(1 << 15);
     115             : constexpr int kMaxUInt16 = (1 << 16) - 1;
     116             : constexpr int kMinUInt16 = 0;
     117             : 
     118             : constexpr uint32_t kMaxUInt32 = 0xFFFFFFFFu;
     119             : constexpr int kMinUInt32 = 0;
     120             : 
     121             : constexpr int kUInt8Size = sizeof(uint8_t);
     122             : constexpr int kByteSize = sizeof(byte);
     123             : constexpr int kCharSize = sizeof(char);
     124             : constexpr int kShortSize = sizeof(short);  // NOLINT
     125             : constexpr int kUInt16Size = sizeof(uint16_t);
     126             : constexpr int kIntSize = sizeof(int);
     127             : constexpr int kInt32Size = sizeof(int32_t);
     128             : constexpr int kInt64Size = sizeof(int64_t);
     129             : constexpr int kUInt32Size = sizeof(uint32_t);
     130             : constexpr int kSizetSize = sizeof(size_t);
     131             : constexpr int kFloatSize = sizeof(float);
     132             : constexpr int kDoubleSize = sizeof(double);
     133             : constexpr int kIntptrSize = sizeof(intptr_t);
     134             : constexpr int kUIntptrSize = sizeof(uintptr_t);
     135             : constexpr int kSystemPointerSize = sizeof(void*);
     136             : constexpr int kSystemPointerHexDigits = kSystemPointerSize == 4 ? 8 : 12;
     137             : constexpr int kPCOnStackSize = kSystemPointerSize;
     138             : constexpr int kFPOnStackSize = kSystemPointerSize;
     139             : 
     140             : #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
     141             : constexpr int kElidedFrameSlots = kPCOnStackSize / kSystemPointerSize;
     142             : #else
     143             : constexpr int kElidedFrameSlots = 0;
     144             : #endif
     145             : 
     146             : constexpr int kDoubleSizeLog2 = 3;
     147             : #if V8_TARGET_ARCH_ARM64
     148             : // ARM64 only supports direct calls within a 128 MB range.
     149             : constexpr size_t kMaxWasmCodeMB = 128;
     150             : #else
     151             : constexpr size_t kMaxWasmCodeMB = 1024;
     152             : #endif
     153             : constexpr size_t kMaxWasmCodeMemory = kMaxWasmCodeMB * MB;
     154             : 
     155             : #if V8_HOST_ARCH_64_BIT
     156             : constexpr int kSystemPointerSizeLog2 = 3;
     157             : constexpr intptr_t kIntptrSignBit =
     158             :     static_cast<intptr_t>(uintptr_t{0x8000000000000000});
     159             : constexpr uintptr_t kUintptrAllBitsSet = uintptr_t{0xFFFFFFFFFFFFFFFF};
     160             : constexpr bool kRequiresCodeRange = true;
     161             : #if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
     162             : constexpr size_t kMaximalCodeRangeSize = 512 * MB;
     163             : constexpr size_t kMinExpectedOSPageSize = 64 * KB;  // OS page on PPC Linux
     164             : #elif V8_TARGET_ARCH_ARM64
     165             : constexpr size_t kMaximalCodeRangeSize = 128 * MB;
     166             : constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
     167             : #else
     168             : constexpr size_t kMaximalCodeRangeSize = 128 * MB;
     169             : constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
     170             : #endif
     171             : #if V8_OS_WIN
     172             : constexpr size_t kMinimumCodeRangeSize = 4 * MB;
     173             : constexpr size_t kReservedCodeRangePages = 1;
     174             : #else
     175             : constexpr size_t kMinimumCodeRangeSize = 3 * MB;
     176             : constexpr size_t kReservedCodeRangePages = 0;
     177             : #endif
     178             : #else
     179             : constexpr int kSystemPointerSizeLog2 = 2;
     180             : constexpr intptr_t kIntptrSignBit = 0x80000000;
     181             : constexpr uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
     182             : #if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
     183             : constexpr bool kRequiresCodeRange = false;
     184             : constexpr size_t kMaximalCodeRangeSize = 0 * MB;
     185             : constexpr size_t kMinimumCodeRangeSize = 0 * MB;
     186             : constexpr size_t kMinExpectedOSPageSize = 64 * KB;  // OS page on PPC Linux
     187             : #elif V8_TARGET_ARCH_MIPS
     188             : constexpr bool kRequiresCodeRange = false;
     189             : constexpr size_t kMaximalCodeRangeSize = 2048LL * MB;
     190             : constexpr size_t kMinimumCodeRangeSize = 0 * MB;
     191             : constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
     192             : #else
     193             : constexpr bool kRequiresCodeRange = false;
     194             : constexpr size_t kMaximalCodeRangeSize = 0 * MB;
     195             : constexpr size_t kMinimumCodeRangeSize = 0 * MB;
     196             : constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
     197             : #endif
     198             : constexpr size_t kReservedCodeRangePages = 0;
     199             : #endif
     200             : 
     201             : STATIC_ASSERT(kSystemPointerSize == (1 << kSystemPointerSizeLog2));
     202             : 
     203             : constexpr int kTaggedSize = kSystemPointerSize;
     204             : constexpr int kTaggedSizeLog2 = kSystemPointerSizeLog2;
     205             : STATIC_ASSERT(kTaggedSize == (1 << kTaggedSizeLog2));
     206             : 
     207             : // These types define raw and atomic storage types for tagged values stored
     208             : // on V8 heap.
     209             : using Tagged_t = Address;
     210             : using AtomicTagged_t = base::AtomicWord;
     211             : using AsAtomicTagged = base::AsAtomicPointerImpl<AtomicTagged_t>;
     212             : STATIC_ASSERT(sizeof(Tagged_t) == kTaggedSize);
     213             : STATIC_ASSERT(sizeof(AtomicTagged_t) == kTaggedSize);
     214             : 
     215             : // TODO(ishell): use kTaggedSize or kSystemPointerSize instead.
     216             : constexpr int kPointerSize = kSystemPointerSize;
     217             : constexpr int kPointerSizeLog2 = kSystemPointerSizeLog2;
     218             : STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
     219             : 
     220             : constexpr int kEmbedderDataSlotSize =
     221             : #ifdef V8_COMPRESS_POINTERS
     222             :     kTaggedSize +
     223             : #endif
     224             :     kTaggedSize;
     225             : 
     226             : constexpr int kEmbedderDataSlotSizeInTaggedSlots =
     227             :     kEmbedderDataSlotSize / kTaggedSize;
     228             : STATIC_ASSERT(kEmbedderDataSlotSize >= kSystemPointerSize);
     229             : 
     230             : constexpr int kExternalAllocationSoftLimit =
     231             :     internal::Internals::kExternalAllocationSoftLimit;
     232             : 
     233             : // Maximum object size that gets allocated into regular pages. Objects larger
     234             : // than that size are allocated in large object space and are never moved in
     235             : // memory. This also applies to new space allocation, since objects are never
     236             : // migrated from new space to large object space. Takes double alignment into
     237             : // account.
     238             : //
     239             : // Current value: Page::kAllocatableMemory (on 32-bit arch) - 512 (slack).
     240             : #ifdef V8_HOST_ARCH_PPC
     241             : // Reduced kMaxRegularHeapObjectSize due to larger page size(64k) on ppc64le
     242             : constexpr int kMaxRegularHeapObjectSize = 327680;
     243             : #else
     244             : constexpr int kMaxRegularHeapObjectSize = 507136;
     245             : #endif
     246             : 
     247             : constexpr int kBitsPerByte = 8;
     248             : constexpr int kBitsPerByteLog2 = 3;
     249             : constexpr int kBitsPerSystemPointer = kSystemPointerSize * kBitsPerByte;
     250             : constexpr int kBitsPerInt = kIntSize * kBitsPerByte;
     251             : 
     252             : // IEEE 754 single precision floating point number bit layout.
     253             : constexpr uint32_t kBinary32SignMask = 0x80000000u;
     254             : constexpr uint32_t kBinary32ExponentMask = 0x7f800000u;
     255             : constexpr uint32_t kBinary32MantissaMask = 0x007fffffu;
     256             : constexpr int kBinary32ExponentBias = 127;
     257             : constexpr int kBinary32MaxExponent = 0xFE;
     258             : constexpr int kBinary32MinExponent = 0x01;
     259             : constexpr int kBinary32MantissaBits = 23;
     260             : constexpr int kBinary32ExponentShift = 23;
     261             : 
     262             : // Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
     263             : // other bits set.
     264             : constexpr uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
     265             : 
     266             : // Latin1/UTF-16 constants
     267             : // Code-point values in Unicode 4.0 are 21 bits wide.
     268             : // Code units in UTF-16 are 16 bits wide.
     269             : typedef uint16_t uc16;
     270             : typedef int32_t uc32;
     271             : constexpr int kOneByteSize = kCharSize;
     272             : constexpr int kUC16Size = sizeof(uc16);  // NOLINT
     273             : 
     274             : // 128 bit SIMD value size.
     275             : constexpr int kSimd128Size = 16;
     276             : 
     277             : // FUNCTION_ADDR(f) gets the address of a C function f.
     278             : #define FUNCTION_ADDR(f) (reinterpret_cast<v8::internal::Address>(f))
     279             : 
     280             : // FUNCTION_CAST<F>(addr) casts an address into a function
     281             : // of type F. Used to invoke generated code from within C.
     282             : template <typename F>
     283             : F FUNCTION_CAST(byte* addr) {
     284             :   return reinterpret_cast<F>(reinterpret_cast<Address>(addr));
     285             : }
     286             : 
     287             : template <typename F>
     288             : F FUNCTION_CAST(Address addr) {
     289        7237 :   return reinterpret_cast<F>(addr);
     290             : }
     291             : 
     292             : 
     293             : // Determine whether the architecture uses function descriptors
     294             : // which provide a level of indirection between the function pointer
     295             : // and the function entrypoint.
     296             : #if V8_HOST_ARCH_PPC && \
     297             :     (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN))
     298             : #define USES_FUNCTION_DESCRIPTORS 1
     299             : #define FUNCTION_ENTRYPOINT_ADDRESS(f)       \
     300             :   (reinterpret_cast<v8::internal::Address*>( \
     301             :       &(reinterpret_cast<intptr_t*>(f)[0])))
     302             : #else
     303             : #define USES_FUNCTION_DESCRIPTORS 0
     304             : #endif
     305             : 
     306             : 
     307             : // -----------------------------------------------------------------------------
     308             : // Declarations for use in both the preparser and the rest of V8.
     309             : 
     310             : // The Strict Mode (ECMA-262 5th edition, 4.2.2).
     311             : 
     312             : enum class LanguageMode : bool { kSloppy, kStrict };
     313             : static const size_t LanguageModeSize = 2;
     314             : 
     315           0 : inline size_t hash_value(LanguageMode mode) {
     316           0 :   return static_cast<size_t>(mode);
     317             : }
     318             : 
     319           0 : inline std::ostream& operator<<(std::ostream& os, const LanguageMode& mode) {
     320           0 :   switch (mode) {
     321             :     case LanguageMode::kSloppy:
     322           0 :       return os << "sloppy";
     323             :     case LanguageMode::kStrict:
     324           0 :       return os << "strict";
     325             :   }
     326             :   UNREACHABLE();
     327             : }
     328             : 
     329       85133 : inline bool is_sloppy(LanguageMode language_mode) {
     330      594109 :   return language_mode == LanguageMode::kSloppy;
     331             : }
     332             : 
     333             : inline bool is_strict(LanguageMode language_mode) {
     334             :   return language_mode != LanguageMode::kSloppy;
     335             : }
     336             : 
     337             : inline bool is_valid_language_mode(int language_mode) {
     338             :   return language_mode == static_cast<int>(LanguageMode::kSloppy) ||
     339             :          language_mode == static_cast<int>(LanguageMode::kStrict);
     340             : }
     341             : 
     342             : inline LanguageMode construct_language_mode(bool strict_bit) {
     343             :   return static_cast<LanguageMode>(strict_bit);
     344             : }
     345             : 
     346             : // Return kStrict if either of the language modes is kStrict, or kSloppy
     347             : // otherwise.
     348             : inline LanguageMode stricter_language_mode(LanguageMode mode1,
     349             :                                            LanguageMode mode2) {
     350             :   STATIC_ASSERT(LanguageModeSize == 2);
     351             :   return static_cast<LanguageMode>(static_cast<int>(mode1) |
     352      168145 :                                    static_cast<int>(mode2));
     353             : }
     354             : 
     355             : // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
     356             : // a keyed store is of the form a[expression] = foo.
     357             : enum class StoreOrigin { kMaybeKeyed, kNamed };
     358             : 
     359             : enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
     360             : 
     361             : // Enums used by CEntry.
     362             : enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
     363             : enum ArgvMode { kArgvOnStack, kArgvInRegister };
     364             : 
     365             : // This constant is used as an undefined value when passing source positions.
     366             : constexpr int kNoSourcePosition = -1;
     367             : 
     368             : // This constant is used to indicate missing deoptimization information.
     369             : constexpr int kNoDeoptimizationId = -1;
     370             : 
     371             : // Deoptimize bailout kind:
     372             : // - Eager: a check failed in the optimized code and deoptimization happens
     373             : //   immediately.
     374             : // - Lazy: the code has been marked as dependent on some assumption which
     375             : //   is checked elsewhere and can trigger deoptimization the next time the
     376             : //   code is executed.
     377             : // - Soft: similar to lazy deoptimization, but does not contribute to the
     378             : //   total deopt count which can lead to disabling optimization for a function.
     379             : enum class DeoptimizeKind : uint8_t {
     380             :   kEager,
     381             :   kSoft,
     382             :   kLazy,
     383             :   kLastDeoptimizeKind = kLazy
     384             : };
     385           0 : inline size_t hash_value(DeoptimizeKind kind) {
     386           0 :   return static_cast<size_t>(kind);
     387             : }
     388          63 : inline std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) {
     389          63 :   switch (kind) {
     390             :     case DeoptimizeKind::kEager:
     391          63 :       return os << "Eager";
     392             :     case DeoptimizeKind::kSoft:
     393           0 :       return os << "Soft";
     394             :     case DeoptimizeKind::kLazy:
     395           0 :       return os << "Lazy";
     396             :   }
     397           0 :   UNREACHABLE();
     398             : }
     399             : 
     400             : enum class IsolateAllocationMode {
     401             :   // Allocate Isolate in C++ heap using default new/delete operators.
     402             :   kInCppHeap,
     403             : 
     404             :   // Allocate Isolate in a committed region inside V8 heap reservation.
     405             :   kInV8Heap,
     406             : 
     407             : #ifdef V8_COMPRESS_POINTERS
     408             :   kDefault = kInV8Heap,
     409             : #else
     410             :   kDefault = kInCppHeap,
     411             : #endif
     412             : };
     413             : 
     414             : // Indicates whether the lookup is related to sloppy-mode block-scoped
     415             : // function hoisting, and is a synthetic assignment for that.
     416             : enum class LookupHoistingMode { kNormal, kLegacySloppy };
     417             : 
     418             : inline std::ostream& operator<<(std::ostream& os,
     419             :                                 const LookupHoistingMode& mode) {
     420             :   switch (mode) {
     421             :     case LookupHoistingMode::kNormal:
     422             :       return os << "normal hoisting";
     423             :     case LookupHoistingMode::kLegacySloppy:
     424             :       return os << "legacy sloppy hoisting";
     425             :   }
     426             :   UNREACHABLE();
     427             : }
     428             : 
     429             : static_assert(kSmiValueSize <= 32, "Unsupported Smi tagging scheme");
     430             : // Smi sign bit position must be 32-bit aligned so we can use sign extension
     431             : // instructions on 64-bit architectures without additional shifts.
     432             : static_assert((kSmiValueSize + kSmiShiftSize + kSmiTagSize) % 32 == 0,
     433             :               "Unsupported Smi tagging scheme");
     434             : 
     435             : constexpr bool kIsSmiValueInUpper32Bits =
     436             :     (kSmiValueSize + kSmiShiftSize + kSmiTagSize) == 64;
     437             : constexpr bool kIsSmiValueInLower32Bits =
     438             :     (kSmiValueSize + kSmiShiftSize + kSmiTagSize) == 32;
     439             : static_assert(!SmiValuesAre32Bits() == SmiValuesAre31Bits(),
     440             :               "Unsupported Smi tagging scheme");
     441             : static_assert(SmiValuesAre32Bits() == kIsSmiValueInUpper32Bits,
     442             :               "Unsupported Smi tagging scheme");
     443             : static_assert(SmiValuesAre31Bits() == kIsSmiValueInLower32Bits,
     444             :               "Unsupported Smi tagging scheme");
     445             : 
     446             : // Mask for the sign bit in a smi.
     447             : constexpr intptr_t kSmiSignMask = static_cast<intptr_t>(
     448             :     uintptr_t{1} << (kSmiValueSize + kSmiShiftSize + kSmiTagSize - 1));
     449             : 
     450             : // Desired alignment for tagged pointers.
     451             : constexpr int kObjectAlignmentBits = kTaggedSizeLog2;
     452             : constexpr intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
     453             : constexpr intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
     454             : 
     455             : // Desired alignment for system pointers.
     456             : constexpr intptr_t kPointerAlignment = (1 << kSystemPointerSizeLog2);
     457             : constexpr intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
     458             : 
     459             : // Desired alignment for double values.
     460             : constexpr intptr_t kDoubleAlignment = 8;
     461             : constexpr intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1;
     462             : 
     463             : // Desired alignment for generated code is 32 bytes (to improve cache line
     464             : // utilization).
     465             : constexpr int kCodeAlignmentBits = 5;
     466             : constexpr intptr_t kCodeAlignment = 1 << kCodeAlignmentBits;
     467             : constexpr intptr_t kCodeAlignmentMask = kCodeAlignment - 1;
     468             : 
     469             : const Address kWeakHeapObjectMask = 1 << 1;
     470             : 
     471             : // The lower 32 bits of the cleared weak reference value is always equal to
     472             : // the |kClearedWeakHeapObjectLower32| constant but on 64-bit architectures
     473             : // the value of the upper 32 bits part may be
     474             : // 1) zero when pointer compression is disabled,
     475             : // 2) upper 32 bits of the isolate root value when pointer compression is
     476             : //    enabled.
     477             : // This is necessary to make pointer decompression computation also suitable
     478             : // for cleared weak reference.
     479             : // Note, that real heap objects can't have lower 32 bits equal to 3 because
     480             : // this offset belongs to page header. So, in either case it's enough to
     481             : // compare only the lower 32 bits of a MaybeObject value in order to figure
     482             : // out if it's a cleared reference or not.
     483             : const uint32_t kClearedWeakHeapObjectLower32 = 3;
     484             : 
     485             : // Zap-value: The value used for zapping dead objects.
     486             : // Should be a recognizable hex value tagged as a failure.
     487             : #ifdef V8_HOST_ARCH_64_BIT
     488             : constexpr uint64_t kClearedFreeMemoryValue = 0;
     489             : constexpr uint64_t kZapValue = uint64_t{0xdeadbeedbeadbeef};
     490             : constexpr uint64_t kHandleZapValue = uint64_t{0x1baddead0baddeaf};
     491             : constexpr uint64_t kGlobalHandleZapValue = uint64_t{0x1baffed00baffedf};
     492             : constexpr uint64_t kFromSpaceZapValue = uint64_t{0x1beefdad0beefdaf};
     493             : constexpr uint64_t kDebugZapValue = uint64_t{0xbadbaddbbadbaddb};
     494             : constexpr uint64_t kSlotsZapValue = uint64_t{0xbeefdeadbeefdeef};
     495             : constexpr uint64_t kFreeListZapValue = 0xfeed1eaffeed1eaf;
     496             : #else
     497             : constexpr uint32_t kClearedFreeMemoryValue = 0;
     498             : constexpr uint32_t kZapValue = 0xdeadbeef;
     499             : constexpr uint32_t kHandleZapValue = 0xbaddeaf;
     500             : constexpr uint32_t kGlobalHandleZapValue = 0xbaffedf;
     501             : constexpr uint32_t kFromSpaceZapValue = 0xbeefdaf;
     502             : constexpr uint32_t kSlotsZapValue = 0xbeefdeef;
     503             : constexpr uint32_t kDebugZapValue = 0xbadbaddb;
     504             : constexpr uint32_t kFreeListZapValue = 0xfeed1eaf;
     505             : #endif
     506             : 
     507             : constexpr int kCodeZapValue = 0xbadc0de;
     508             : constexpr uint32_t kPhantomReferenceZap = 0xca11bac;
     509             : 
     510             : // Page constants.
     511             : static const intptr_t kPageAlignmentMask = (intptr_t{1} << kPageSizeBits) - 1;
     512             : 
     513             : // On Intel architecture, cache line size is 64 bytes.
     514             : // On ARM it may be less (32 bytes), but as far this constant is
     515             : // used for aligning data, it doesn't hurt to align on a greater value.
     516             : #define PROCESSOR_CACHE_LINE_SIZE 64
     517             : 
     518             : // Constants relevant to double precision floating point numbers.
     519             : // If looking only at the top 32 bits, the QNaN mask is bits 19 to 30.
     520             : constexpr uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32);
     521             : 
     522             : // -----------------------------------------------------------------------------
     523             : // Forward declarations for frequently used classes
     524             : 
     525             : class AccessorInfo;
     526             : class Arguments;
     527             : class Assembler;
     528             : class Code;
     529             : class CodeSpace;
     530             : class Context;
     531             : class DeclarationScope;
     532             : class Debug;
     533             : class DebugInfo;
     534             : class Descriptor;
     535             : class DescriptorArray;
     536             : class TransitionArray;
     537             : class ExternalReference;
     538             : class FeedbackVector;
     539             : class FixedArray;
     540             : class Foreign;
     541             : class FreeStoreAllocationPolicy;
     542             : class FunctionTemplateInfo;
     543             : class GlobalDictionary;
     544             : template <typename T> class Handle;
     545             : class Heap;
     546             : class HeapObject;
     547             : class HeapObjectReference;
     548             : class IC;
     549             : class InterceptorInfo;
     550             : class Isolate;
     551             : class JSReceiver;
     552             : class JSArray;
     553             : class JSFunction;
     554             : class JSObject;
     555             : class LargeObjectSpace;
     556             : class MacroAssembler;
     557             : class Map;
     558             : class MapSpace;
     559             : class MarkCompactCollector;
     560             : template <typename T>
     561             : class MaybeHandle;
     562             : class MaybeObject;
     563             : class MemoryChunk;
     564             : class MessageLocation;
     565             : class ModuleScope;
     566             : class Name;
     567             : class NameDictionary;
     568             : class NativeContext;
     569             : class NewSpace;
     570             : class NewLargeObjectSpace;
     571             : class NumberDictionary;
     572             : class Object;
     573             : class CompressedObjectSlot;
     574             : class CompressedMaybeObjectSlot;
     575             : class CompressedMapWordSlot;
     576             : class CompressedHeapObjectSlot;
     577             : class FullObjectSlot;
     578             : class FullMaybeObjectSlot;
     579             : class FullHeapObjectSlot;
     580             : class OldSpace;
     581             : class ParameterCount;
     582             : class ReadOnlySpace;
     583             : class RelocInfo;
     584             : class Scope;
     585             : class ScopeInfo;
     586             : class Script;
     587             : class SimpleNumberDictionary;
     588             : class Smi;
     589             : template <typename Config, class Allocator = FreeStoreAllocationPolicy>
     590             : class SplayTree;
     591             : class String;
     592             : class Struct;
     593             : class Symbol;
     594             : class Variable;
     595             : 
     596             : enum class SlotLocation { kOnHeap, kOffHeap };
     597             : 
     598             : template <SlotLocation slot_location>
     599             : struct SlotTraits;
     600             : 
     601             : // Off-heap slots are always full-pointer slots.
     602             : template <>
     603             : struct SlotTraits<SlotLocation::kOffHeap> {
     604             :   using TObjectSlot = FullObjectSlot;
     605             :   using TMapWordSlot = FullObjectSlot;
     606             :   using TMaybeObjectSlot = FullMaybeObjectSlot;
     607             :   using THeapObjectSlot = FullHeapObjectSlot;
     608             : };
     609             : 
     610             : // On-heap slots are either full-pointer slots or compressed slots depending
     611             : // on whether the pointer compression is enabled or not.
     612             : template <>
     613             : struct SlotTraits<SlotLocation::kOnHeap> {
     614             : #ifdef V8_COMPRESS_POINTERS
     615             :   using TObjectSlot = CompressedObjectSlot;
     616             :   using TMapWordSlot = CompressedMapWordSlot;
     617             :   using TMaybeObjectSlot = CompressedMaybeObjectSlot;
     618             :   using THeapObjectSlot = CompressedHeapObjectSlot;
     619             : #else
     620             :   using TObjectSlot = FullObjectSlot;
     621             :   using TMapWordSlot = FullObjectSlot;
     622             :   using TMaybeObjectSlot = FullMaybeObjectSlot;
     623             :   using THeapObjectSlot = FullHeapObjectSlot;
     624             : #endif
     625             : };
     626             : 
     627             : // An ObjectSlot instance describes a kTaggedSize-sized on-heap field ("slot")
     628             : // holding Object value (smi or strong heap object).
     629             : using ObjectSlot = SlotTraits<SlotLocation::kOnHeap>::TObjectSlot;
     630             : 
     631             : // An MapWordSlot instance describes a kTaggedSize-sized on-heap field ("slot")
     632             : // holding HeapObject (strong heap object) value or a forwarding pointer.
     633             : using MapWordSlot = SlotTraits<SlotLocation::kOnHeap>::TMapWordSlot;
     634             : 
     635             : // A MaybeObjectSlot instance describes a kTaggedSize-sized on-heap field
     636             : // ("slot") holding MaybeObject (smi or weak heap object or strong heap object).
     637             : using MaybeObjectSlot = SlotTraits<SlotLocation::kOnHeap>::TMaybeObjectSlot;
     638             : 
     639             : // A HeapObjectSlot instance describes a kTaggedSize-sized field ("slot")
     640             : // holding a weak or strong pointer to a heap object (think:
     641             : // HeapObjectReference).
     642             : using HeapObjectSlot = SlotTraits<SlotLocation::kOnHeap>::THeapObjectSlot;
     643             : 
     644             : typedef bool (*WeakSlotCallback)(FullObjectSlot pointer);
     645             : 
     646             : typedef bool (*WeakSlotCallbackWithHeap)(Heap* heap, FullObjectSlot pointer);
     647             : 
     648             : // -----------------------------------------------------------------------------
     649             : // Miscellaneous
     650             : 
     651             : // NOTE: SpaceIterator depends on AllocationSpace enumeration values being
     652             : // consecutive.
     653             : enum AllocationSpace {
     654             :   RO_SPACE,    // Immortal, immovable and immutable objects,
     655             :   NEW_SPACE,   // Young generation semispaces for regular objects collected with
     656             :                // Scavenger.
     657             :   OLD_SPACE,   // Old generation regular object space.
     658             :   CODE_SPACE,  // Old generation code object space, marked executable.
     659             :   MAP_SPACE,   // Old generation map object space, non-movable.
     660             :   LO_SPACE,    // Old generation large object space.
     661             :   CODE_LO_SPACE,  // Old generation large code object space.
     662             :   NEW_LO_SPACE,   // Young generation large object space.
     663             : 
     664             :   FIRST_SPACE = RO_SPACE,
     665             :   LAST_SPACE = NEW_LO_SPACE,
     666             :   FIRST_GROWABLE_PAGED_SPACE = OLD_SPACE,
     667             :   LAST_GROWABLE_PAGED_SPACE = MAP_SPACE
     668             : };
     669             : constexpr int kSpaceTagSize = 4;
     670             : STATIC_ASSERT(FIRST_SPACE == 0);
     671             : 
     672             : // TODO(ishell): review and rename kWordAligned to kTaggedAligned.
     673             : enum AllocationAlignment { kWordAligned, kDoubleAligned, kDoubleUnaligned };
     674             : 
     675             : enum class AccessMode { ATOMIC, NON_ATOMIC };
     676             : 
     677             : // Supported write barrier modes.
     678             : enum WriteBarrierKind : uint8_t {
     679             :   kNoWriteBarrier,
     680             :   kMapWriteBarrier,
     681             :   kPointerWriteBarrier,
     682             :   kFullWriteBarrier
     683             : };
     684             : 
     685           0 : inline size_t hash_value(WriteBarrierKind kind) {
     686           0 :   return static_cast<uint8_t>(kind);
     687             : }
     688             : 
     689      479864 : inline std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
     690      479864 :   switch (kind) {
     691             :     case kNoWriteBarrier:
     692      303718 :       return os << "NoWriteBarrier";
     693             :     case kMapWriteBarrier:
     694           0 :       return os << "MapWriteBarrier";
     695             :     case kPointerWriteBarrier:
     696           0 :       return os << "PointerWriteBarrier";
     697             :     case kFullWriteBarrier:
     698      176146 :       return os << "FullWriteBarrier";
     699             :   }
     700           0 :   UNREACHABLE();
     701             : }
     702             : 
     703             : // A flag that indicates whether objects should be pretenured when
     704             : // allocated (allocated directly into either the old generation or read-only
     705             : // space), or not (allocated in the young generation if the object size and type
     706             : // allows).
     707             : enum PretenureFlag { NOT_TENURED, TENURED, TENURED_READ_ONLY };
     708             : 
     709           0 : inline std::ostream& operator<<(std::ostream& os, const PretenureFlag& flag) {
     710           0 :   switch (flag) {
     711             :     case NOT_TENURED:
     712           0 :       return os << "NotTenured";
     713             :     case TENURED:
     714           0 :       return os << "Tenured";
     715             :     case TENURED_READ_ONLY:
     716           0 :       return os << "TenuredReadOnly";
     717             :   }
     718           0 :   UNREACHABLE();
     719             : }
     720             : 
     721             : enum MinimumCapacity {
     722             :   USE_DEFAULT_MINIMUM_CAPACITY,
     723             :   USE_CUSTOM_MINIMUM_CAPACITY
     724             : };
     725             : 
     726             : enum GarbageCollector { SCAVENGER, MARK_COMPACTOR, MINOR_MARK_COMPACTOR };
     727             : 
     728             : enum Executability { NOT_EXECUTABLE, EXECUTABLE };
     729             : 
     730             : enum Movability { kMovable, kImmovable };
     731             : 
     732             : enum VisitMode {
     733             :   VISIT_ALL,
     734             :   VISIT_ALL_IN_MINOR_MC_MARK,
     735             :   VISIT_ALL_IN_MINOR_MC_UPDATE,
     736             :   VISIT_ALL_IN_SCAVENGE,
     737             :   VISIT_ALL_IN_SWEEP_NEWSPACE,
     738             :   VISIT_ONLY_STRONG,
     739             :   VISIT_FOR_SERIALIZATION,
     740             : };
     741             : 
     742             : // Flag indicating whether code is built into the VM (one of the natives files).
     743             : enum NativesFlag {
     744             :   NOT_NATIVES_CODE,
     745             :   EXTENSION_CODE,
     746             :   NATIVES_CODE,
     747             :   INSPECTOR_CODE
     748             : };
     749             : 
     750             : // ParseRestriction is used to restrict the set of valid statements in a
     751             : // unit of compilation.  Restriction violations cause a syntax error.
     752             : enum ParseRestriction {
     753             :   NO_PARSE_RESTRICTION,         // All expressions are allowed.
     754             :   ONLY_SINGLE_FUNCTION_LITERAL  // Only a single FunctionLiteral expression.
     755             : };
     756             : 
     757             : // State for inline cache call sites. Aliased as IC::State.
     758             : enum InlineCacheState {
     759             :   // No feedback will be collected.
     760             :   NO_FEEDBACK,
     761             :   // Has never been executed.
     762             :   UNINITIALIZED,
     763             :   // Has been executed but monomorphic state has been delayed.
     764             :   PREMONOMORPHIC,
     765             :   // Has been executed and only one receiver type has been seen.
     766             :   MONOMORPHIC,
     767             :   // Check failed due to prototype (or map deprecation).
     768             :   RECOMPUTE_HANDLER,
     769             :   // Multiple receiver types have been seen.
     770             :   POLYMORPHIC,
     771             :   // Many receiver types have been seen.
     772             :   MEGAMORPHIC,
     773             :   // A generic handler is installed and no extra typefeedback is recorded.
     774             :   GENERIC,
     775             : };
     776             : 
     777             : // Printing support.
     778         266 : inline const char* InlineCacheState2String(InlineCacheState state) {
     779         266 :   switch (state) {
     780             :     case NO_FEEDBACK:
     781             :       return "NOFEEDBACK";
     782             :     case UNINITIALIZED:
     783         266 :       return "UNINITIALIZED";
     784             :     case PREMONOMORPHIC:
     785           0 :       return "PREMONOMORPHIC";
     786             :     case MONOMORPHIC:
     787           0 :       return "MONOMORPHIC";
     788             :     case RECOMPUTE_HANDLER:
     789           0 :       return "RECOMPUTE_HANDLER";
     790             :     case POLYMORPHIC:
     791           0 :       return "POLYMORPHIC";
     792             :     case MEGAMORPHIC:
     793           0 :       return "MEGAMORPHIC";
     794             :     case GENERIC:
     795           0 :       return "GENERIC";
     796             :   }
     797           0 :   UNREACHABLE();
     798             : }
     799             : 
     800             : enum WhereToStart { kStartAtReceiver, kStartAtPrototype };
     801             : 
     802             : enum ResultSentinel { kNotFound = -1, kUnsupported = -2 };
     803             : 
     804             : enum ShouldThrow {
     805             :   kThrowOnError = Internals::kThrowOnError,
     806             :   kDontThrow = Internals::kDontThrow
     807             : };
     808             : 
     809             : // The Store Buffer (GC).
     810             : typedef enum {
     811             :   kStoreBufferFullEvent,
     812             :   kStoreBufferStartScanningPagesEvent,
     813             :   kStoreBufferScanningPageEvent
     814             : } StoreBufferEvent;
     815             : 
     816             : 
     817             : typedef void (*StoreBufferCallback)(Heap* heap,
     818             :                                     MemoryChunk* page,
     819             :                                     StoreBufferEvent event);
     820             : 
     821             : // Union used for customized checking of the IEEE double types
     822             : // inlined within v8 runtime, rather than going to the underlying
     823             : // platform headers and libraries
     824             : union IeeeDoubleLittleEndianArchType {
     825             :   double d;
     826             :   struct {
     827             :     unsigned int man_low  :32;
     828             :     unsigned int man_high :20;
     829             :     unsigned int exp      :11;
     830             :     unsigned int sign     :1;
     831             :   } bits;
     832             : };
     833             : 
     834             : 
     835             : union IeeeDoubleBigEndianArchType {
     836             :   double d;
     837             :   struct {
     838             :     unsigned int sign     :1;
     839             :     unsigned int exp      :11;
     840             :     unsigned int man_high :20;
     841             :     unsigned int man_low  :32;
     842             :   } bits;
     843             : };
     844             : 
     845             : #if V8_TARGET_LITTLE_ENDIAN
     846             : typedef IeeeDoubleLittleEndianArchType IeeeDoubleArchType;
     847             : constexpr int kIeeeDoubleMantissaWordOffset = 0;
     848             : constexpr int kIeeeDoubleExponentWordOffset = 4;
     849             : #else
     850             : typedef IeeeDoubleBigEndianArchType IeeeDoubleArchType;
     851             : constexpr int kIeeeDoubleMantissaWordOffset = 4;
     852             : constexpr int kIeeeDoubleExponentWordOffset = 0;
     853             : #endif
     854             : 
     855             : // -----------------------------------------------------------------------------
     856             : // Macros
     857             : 
     858             : // Testers for test.
     859             : 
     860             : #define HAS_SMI_TAG(value) \
     861             :   ((static_cast<intptr_t>(value) & ::i::kSmiTagMask) == ::i::kSmiTag)
     862             : 
     863             : #define HAS_HEAP_OBJECT_TAG(value)                              \
     864             :   (((static_cast<intptr_t>(value) & ::i::kHeapObjectTagMask) == \
     865             :     ::i::kHeapObjectTag))
     866             : 
     867             : // OBJECT_POINTER_ALIGN returns the value aligned as a HeapObject pointer
     868             : #define OBJECT_POINTER_ALIGN(value)                             \
     869             :   (((value) + kObjectAlignmentMask) & ~kObjectAlignmentMask)
     870             : 
     871             : // OBJECT_POINTER_PADDING returns the padding size required to align value
     872             : // as a HeapObject pointer
     873             : #define OBJECT_POINTER_PADDING(value) (OBJECT_POINTER_ALIGN(value) - (value))
     874             : 
     875             : // POINTER_SIZE_ALIGN returns the value aligned as a system pointer.
     876             : #define POINTER_SIZE_ALIGN(value)                               \
     877             :   (((value) + kPointerAlignmentMask) & ~kPointerAlignmentMask)
     878             : 
     879             : // POINTER_SIZE_PADDING returns the padding size required to align value
     880             : // as a system pointer.
     881             : #define POINTER_SIZE_PADDING(value) (POINTER_SIZE_ALIGN(value) - (value))
     882             : 
     883             : // CODE_POINTER_ALIGN returns the value aligned as a generated code segment.
     884             : #define CODE_POINTER_ALIGN(value)                               \
     885             :   (((value) + kCodeAlignmentMask) & ~kCodeAlignmentMask)
     886             : 
     887             : // CODE_POINTER_PADDING returns the padding size required to align value
     888             : // as a generated code segment.
     889             : #define CODE_POINTER_PADDING(value) (CODE_POINTER_ALIGN(value) - (value))
     890             : 
     891             : // DOUBLE_POINTER_ALIGN returns the value algined for double pointers.
     892             : #define DOUBLE_POINTER_ALIGN(value) \
     893             :   (((value) + kDoubleAlignmentMask) & ~kDoubleAlignmentMask)
     894             : 
     895             : 
     896             : // Defines hints about receiver values based on structural knowledge.
     897             : enum class ConvertReceiverMode : unsigned {
     898             :   kNullOrUndefined,     // Guaranteed to be null or undefined.
     899             :   kNotNullOrUndefined,  // Guaranteed to never be null or undefined.
     900             :   kAny                  // No specific knowledge about receiver.
     901             : };
     902             : 
     903           0 : inline size_t hash_value(ConvertReceiverMode mode) {
     904           0 :   return bit_cast<unsigned>(mode);
     905             : }
     906             : 
     907           0 : inline std::ostream& operator<<(std::ostream& os, ConvertReceiverMode mode) {
     908           0 :   switch (mode) {
     909             :     case ConvertReceiverMode::kNullOrUndefined:
     910           0 :       return os << "NULL_OR_UNDEFINED";
     911             :     case ConvertReceiverMode::kNotNullOrUndefined:
     912           0 :       return os << "NOT_NULL_OR_UNDEFINED";
     913             :     case ConvertReceiverMode::kAny:
     914           0 :       return os << "ANY";
     915             :   }
     916           0 :   UNREACHABLE();
     917             : }
     918             : 
     919             : // Valid hints for the abstract operation OrdinaryToPrimitive,
     920             : // implemented according to ES6, section 7.1.1.
     921             : enum class OrdinaryToPrimitiveHint { kNumber, kString };
     922             : 
     923             : // Valid hints for the abstract operation ToPrimitive,
     924             : // implemented according to ES6, section 7.1.1.
     925             : enum class ToPrimitiveHint { kDefault, kNumber, kString };
     926             : 
     927             : // Defines specifics about arguments object or rest parameter creation.
     928             : enum class CreateArgumentsType : uint8_t {
     929             :   kMappedArguments,
     930             :   kUnmappedArguments,
     931             :   kRestParameter
     932             : };
     933             : 
     934        6245 : inline size_t hash_value(CreateArgumentsType type) {
     935        6245 :   return bit_cast<uint8_t>(type);
     936             : }
     937             : 
     938           0 : inline std::ostream& operator<<(std::ostream& os, CreateArgumentsType type) {
     939           0 :   switch (type) {
     940             :     case CreateArgumentsType::kMappedArguments:
     941           0 :       return os << "MAPPED_ARGUMENTS";
     942             :     case CreateArgumentsType::kUnmappedArguments:
     943           0 :       return os << "UNMAPPED_ARGUMENTS";
     944             :     case CreateArgumentsType::kRestParameter:
     945           0 :       return os << "REST_PARAMETER";
     946             :   }
     947           0 :   UNREACHABLE();
     948             : }
     949             : 
     950             : enum ScopeType : uint8_t {
     951             :   EVAL_SCOPE,      // The top-level scope for an eval source.
     952             :   FUNCTION_SCOPE,  // The top-level scope for a function.
     953             :   MODULE_SCOPE,    // The scope introduced by a module literal
     954             :   SCRIPT_SCOPE,    // The top-level scope for a script or a top-level eval.
     955             :   CATCH_SCOPE,     // The scope introduced by catch.
     956             :   BLOCK_SCOPE,     // The scope introduced by a new block.
     957             :   WITH_SCOPE       // The scope introduced by with.
     958             : };
     959             : 
     960           0 : inline std::ostream& operator<<(std::ostream& os, ScopeType type) {
     961           0 :   switch (type) {
     962             :     case ScopeType::EVAL_SCOPE:
     963           0 :       return os << "EVAL_SCOPE";
     964             :     case ScopeType::FUNCTION_SCOPE:
     965           0 :       return os << "FUNCTION_SCOPE";
     966             :     case ScopeType::MODULE_SCOPE:
     967           0 :       return os << "MODULE_SCOPE";
     968             :     case ScopeType::SCRIPT_SCOPE:
     969           0 :       return os << "SCRIPT_SCOPE";
     970             :     case ScopeType::CATCH_SCOPE:
     971           0 :       return os << "CATCH_SCOPE";
     972             :     case ScopeType::BLOCK_SCOPE:
     973           0 :       return os << "BLOCK_SCOPE";
     974             :     case ScopeType::WITH_SCOPE:
     975           0 :       return os << "WITH_SCOPE";
     976             :   }
     977           0 :   UNREACHABLE();
     978             : }
     979             : 
     980             : // AllocationSiteMode controls whether allocations are tracked by an allocation
     981             : // site.
     982             : enum AllocationSiteMode {
     983             :   DONT_TRACK_ALLOCATION_SITE,
     984             :   TRACK_ALLOCATION_SITE,
     985             :   LAST_ALLOCATION_SITE_MODE = TRACK_ALLOCATION_SITE
     986             : };
     987             : 
     988             : enum class AllocationSiteUpdateMode { kUpdate, kCheckOnly };
     989             : 
     990             : // The mips architecture prior to revision 5 has inverted encoding for sNaN.
     991             : #if (V8_TARGET_ARCH_MIPS && !defined(_MIPS_ARCH_MIPS32R6) &&           \
     992             :      (!defined(USE_SIMULATOR) || !defined(_MIPS_TARGET_SIMULATOR))) || \
     993             :     (V8_TARGET_ARCH_MIPS64 && !defined(_MIPS_ARCH_MIPS64R6) &&         \
     994             :      (!defined(USE_SIMULATOR) || !defined(_MIPS_TARGET_SIMULATOR)))
     995             : constexpr uint32_t kHoleNanUpper32 = 0xFFFF7FFF;
     996             : constexpr uint32_t kHoleNanLower32 = 0xFFFF7FFF;
     997             : #else
     998             : constexpr uint32_t kHoleNanUpper32 = 0xFFF7FFFF;
     999             : constexpr uint32_t kHoleNanLower32 = 0xFFF7FFFF;
    1000             : #endif
    1001             : 
    1002             : constexpr uint64_t kHoleNanInt64 =
    1003             :     (static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
    1004             : 
    1005             : // ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER
    1006             : constexpr double kMaxSafeInteger = 9007199254740991.0;  // 2^53-1
    1007             : 
    1008             : // The order of this enum has to be kept in sync with the predicates below.
    1009             : enum class VariableMode : uint8_t {
    1010             :   // User declared variables:
    1011             :   kLet,  // declared via 'let' declarations (first lexical)
    1012             : 
    1013             :   kConst,  // declared via 'const' declarations (last lexical)
    1014             : 
    1015             :   kVar,  // declared via 'var', and 'function' declarations
    1016             : 
    1017             :   // Variables introduced by the compiler:
    1018             :   kTemporary,  // temporary variables (not user-visible), stack-allocated
    1019             :                // unless the scope as a whole has forced context allocation
    1020             : 
    1021             :   kDynamic,  // always require dynamic lookup (we don't know
    1022             :              // the declaration)
    1023             : 
    1024             :   kDynamicGlobal,  // requires dynamic lookup, but we know that the
    1025             :                    // variable is global unless it has been shadowed
    1026             :                    // by an eval-introduced variable
    1027             : 
    1028             :   kDynamicLocal,  // requires dynamic lookup, but we know that the
    1029             :                   // variable is local and where it is unless it
    1030             :                   // has been shadowed by an eval-introduced
    1031             :                   // variable
    1032             : 
    1033             :   kLastLexicalVariableMode = kConst,
    1034             : };
    1035             : 
    1036             : // Printing support
    1037             : #ifdef DEBUG
    1038             : inline const char* VariableMode2String(VariableMode mode) {
    1039             :   switch (mode) {
    1040             :     case VariableMode::kVar:
    1041             :       return "VAR";
    1042             :     case VariableMode::kLet:
    1043             :       return "LET";
    1044             :     case VariableMode::kConst:
    1045             :       return "CONST";
    1046             :     case VariableMode::kDynamic:
    1047             :       return "DYNAMIC";
    1048             :     case VariableMode::kDynamicGlobal:
    1049             :       return "DYNAMIC_GLOBAL";
    1050             :     case VariableMode::kDynamicLocal:
    1051             :       return "DYNAMIC_LOCAL";
    1052             :     case VariableMode::kTemporary:
    1053             :       return "TEMPORARY";
    1054             :   }
    1055             :   UNREACHABLE();
    1056             : }
    1057             : #endif
    1058             : 
    1059             : enum VariableKind : uint8_t {
    1060             :   NORMAL_VARIABLE,
    1061             :   PARAMETER_VARIABLE,
    1062             :   THIS_VARIABLE,
    1063             :   SLOPPY_BLOCK_FUNCTION_VARIABLE,
    1064             :   SLOPPY_FUNCTION_NAME_VARIABLE
    1065             : };
    1066             : 
    1067             : inline bool IsDynamicVariableMode(VariableMode mode) {
    1068    28717707 :   return mode >= VariableMode::kDynamic && mode <= VariableMode::kDynamicLocal;
    1069             : }
    1070             : 
    1071             : inline bool IsDeclaredVariableMode(VariableMode mode) {
    1072             :   STATIC_ASSERT(static_cast<uint8_t>(VariableMode::kLet) ==
    1073             :                 0);  // Implies that mode >= VariableMode::kLet.
    1074             :   return mode <= VariableMode::kVar;
    1075             : }
    1076             : 
    1077      109777 : inline bool IsLexicalVariableMode(VariableMode mode) {
    1078             :   STATIC_ASSERT(static_cast<uint8_t>(VariableMode::kLet) ==
    1079             :                 0);  // Implies that mode >= VariableMode::kLet.
    1080      109777 :   return mode <= VariableMode::kLastLexicalVariableMode;
    1081             : }
    1082             : 
    1083             : enum VariableLocation : uint8_t {
    1084             :   // Before and during variable allocation, a variable whose location is
    1085             :   // not yet determined.  After allocation, a variable looked up as a
    1086             :   // property on the global object (and possibly absent).  name() is the
    1087             :   // variable name, index() is invalid.
    1088             :   UNALLOCATED,
    1089             : 
    1090             :   // A slot in the parameter section on the stack.  index() is the
    1091             :   // parameter index, counting left-to-right.  The receiver is index -1;
    1092             :   // the first parameter is index 0.
    1093             :   PARAMETER,
    1094             : 
    1095             :   // A slot in the local section on the stack.  index() is the variable
    1096             :   // index in the stack frame, starting at 0.
    1097             :   LOCAL,
    1098             : 
    1099             :   // An indexed slot in a heap context.  index() is the variable index in
    1100             :   // the context object on the heap, starting at 0.  scope() is the
    1101             :   // corresponding scope.
    1102             :   CONTEXT,
    1103             : 
    1104             :   // A named slot in a heap context.  name() is the variable name in the
    1105             :   // context object on the heap, with lookup starting at the current
    1106             :   // context.  index() is invalid.
    1107             :   LOOKUP,
    1108             : 
    1109             :   // A named slot in a module's export table.
    1110             :   MODULE,
    1111             : 
    1112             :   kLastVariableLocation = MODULE
    1113             : };
    1114             : 
    1115             : // ES6 specifies declarative environment records with mutable and immutable
    1116             : // bindings that can be in two states: initialized and uninitialized.
    1117             : // When accessing a binding, it needs to be checked for initialization.
    1118             : // However in the following cases the binding is initialized immediately
    1119             : // after creation so the initialization check can always be skipped:
    1120             : //
    1121             : // 1. Var declared local variables.
    1122             : //      var foo;
    1123             : // 2. A local variable introduced by a function declaration.
    1124             : //      function foo() {}
    1125             : // 3. Parameters
    1126             : //      function x(foo) {}
    1127             : // 4. Catch bound variables.
    1128             : //      try {} catch (foo) {}
    1129             : // 6. Function name variables of named function expressions.
    1130             : //      var x = function foo() {}
    1131             : // 7. Implicit binding of 'this'.
    1132             : // 8. Implicit binding of 'arguments' in functions.
    1133             : //
    1134             : // The following enum specifies a flag that indicates if the binding needs a
    1135             : // distinct initialization step (kNeedsInitialization) or if the binding is
    1136             : // immediately initialized upon creation (kCreatedInitialized).
    1137             : enum InitializationFlag : uint8_t { kNeedsInitialization, kCreatedInitialized };
    1138             : 
    1139             : enum MaybeAssignedFlag : uint8_t { kNotAssigned, kMaybeAssigned };
    1140             : 
    1141             : enum ParseErrorType { kSyntaxError = 0, kReferenceError = 1 };
    1142             : 
    1143             : 
    1144             : enum class InterpreterPushArgsMode : unsigned {
    1145             :   kArrayFunction,
    1146             :   kWithFinalSpread,
    1147             :   kOther
    1148             : };
    1149             : 
    1150             : inline size_t hash_value(InterpreterPushArgsMode mode) {
    1151             :   return bit_cast<unsigned>(mode);
    1152             : }
    1153             : 
    1154             : inline std::ostream& operator<<(std::ostream& os,
    1155             :                                 InterpreterPushArgsMode mode) {
    1156             :   switch (mode) {
    1157             :     case InterpreterPushArgsMode::kArrayFunction:
    1158             :       return os << "ArrayFunction";
    1159             :     case InterpreterPushArgsMode::kWithFinalSpread:
    1160             :       return os << "WithFinalSpread";
    1161             :     case InterpreterPushArgsMode::kOther:
    1162             :       return os << "Other";
    1163             :   }
    1164             :   UNREACHABLE();
    1165             : }
    1166             : 
    1167             : inline uint32_t ObjectHash(Address address) {
    1168             :   // All objects are at least pointer aligned, so we can remove the trailing
    1169             :   // zeros.
    1170             :   return static_cast<uint32_t>(address >> kTaggedSizeLog2);
    1171             : }
    1172             : 
    1173             : // Type feedback is encoded in such a way that, we can combine the feedback
    1174             : // at different points by performing an 'OR' operation. Type feedback moves
    1175             : // to a more generic type when we combine feedback.
    1176             : //
    1177             : //   kSignedSmall -> kSignedSmallInputs -> kNumber  -> kNumberOrOddball -> kAny
    1178             : //                                                     kString          -> kAny
    1179             : //                                                     kBigInt          -> kAny
    1180             : //
    1181             : // Technically we wouldn't need the separation between the kNumber and the
    1182             : // kNumberOrOddball values here, since for binary operations, we always
    1183             : // truncate oddballs to numbers. In practice though it causes TurboFan to
    1184             : // generate quite a lot of unused code though if we always handle numbers
    1185             : // and oddballs everywhere, although in 99% of the use sites they are only
    1186             : // used with numbers.
    1187             : class BinaryOperationFeedback {
    1188             :  public:
    1189             :   enum {
    1190             :     kNone = 0x0,
    1191             :     kSignedSmall = 0x1,
    1192             :     kSignedSmallInputs = 0x3,
    1193             :     kNumber = 0x7,
    1194             :     kNumberOrOddball = 0xF,
    1195             :     kString = 0x10,
    1196             :     kBigInt = 0x20,
    1197             :     kAny = 0x7F
    1198             :   };
    1199             : };
    1200             : 
    1201             : // Type feedback is encoded in such a way that, we can combine the feedback
    1202             : // at different points by performing an 'OR' operation. Type feedback moves
    1203             : // to a more generic type when we combine feedback.
    1204             : //
    1205             : //   kSignedSmall -> kNumber             -> kNumberOrOddball           -> kAny
    1206             : //                   kReceiver           -> kReceiverOrNullOrUndefined -> kAny
    1207             : //                   kInternalizedString -> kString                    -> kAny
    1208             : //                                          kSymbol                    -> kAny
    1209             : //                                          kBigInt                    -> kAny
    1210             : //
    1211             : // This is distinct from BinaryOperationFeedback on purpose, because the
    1212             : // feedback that matters differs greatly as well as the way it is consumed.
    1213             : class CompareOperationFeedback {
    1214             :  public:
    1215             :   enum {
    1216             :     kNone = 0x000,
    1217             :     kSignedSmall = 0x001,
    1218             :     kNumber = 0x003,
    1219             :     kNumberOrOddball = 0x007,
    1220             :     kInternalizedString = 0x008,
    1221             :     kString = 0x018,
    1222             :     kSymbol = 0x020,
    1223             :     kBigInt = 0x040,
    1224             :     kReceiver = 0x080,
    1225             :     kReceiverOrNullOrUndefined = 0x180,
    1226             :     kAny = 0x1ff
    1227             :   };
    1228             : };
    1229             : 
    1230             : enum class Operation {
    1231             :   // Binary operations.
    1232             :   kAdd,
    1233             :   kSubtract,
    1234             :   kMultiply,
    1235             :   kDivide,
    1236             :   kModulus,
    1237             :   kExponentiate,
    1238             :   kBitwiseAnd,
    1239             :   kBitwiseOr,
    1240             :   kBitwiseXor,
    1241             :   kShiftLeft,
    1242             :   kShiftRight,
    1243             :   kShiftRightLogical,
    1244             :   // Unary operations.
    1245             :   kBitwiseNot,
    1246             :   kNegate,
    1247             :   kIncrement,
    1248             :   kDecrement,
    1249             :   // Compare operations.
    1250             :   kEqual,
    1251             :   kStrictEqual,
    1252             :   kLessThan,
    1253             :   kLessThanOrEqual,
    1254             :   kGreaterThan,
    1255             :   kGreaterThanOrEqual,
    1256             : };
    1257             : 
    1258             : // Type feedback is encoded in such a way that, we can combine the feedback
    1259             : // at different points by performing an 'OR' operation. Type feedback moves
    1260             : // to a more generic type when we combine feedback.
    1261             : // kNone -> kEnumCacheKeysAndIndices -> kEnumCacheKeys -> kAny
    1262             : class ForInFeedback {
    1263             :  public:
    1264             :   enum {
    1265             :     kNone = 0x0,
    1266             :     kEnumCacheKeysAndIndices = 0x1,
    1267             :     kEnumCacheKeys = 0x3,
    1268             :     kAny = 0x7
    1269             :   };
    1270             : };
    1271             : STATIC_ASSERT((ForInFeedback::kNone |
    1272             :                ForInFeedback::kEnumCacheKeysAndIndices) ==
    1273             :               ForInFeedback::kEnumCacheKeysAndIndices);
    1274             : STATIC_ASSERT((ForInFeedback::kEnumCacheKeysAndIndices |
    1275             :                ForInFeedback::kEnumCacheKeys) == ForInFeedback::kEnumCacheKeys);
    1276             : STATIC_ASSERT((ForInFeedback::kEnumCacheKeys | ForInFeedback::kAny) ==
    1277             :               ForInFeedback::kAny);
    1278             : 
    1279             : enum class UnicodeEncoding : uint8_t {
    1280             :   // Different unicode encodings in a |word32|:
    1281             :   UTF16,  // hi 16bits -> trailing surrogate or 0, low 16bits -> lead surrogate
    1282             :   UTF32,  // full UTF32 code unit / Unicode codepoint
    1283             : };
    1284             : 
    1285         945 : inline size_t hash_value(UnicodeEncoding encoding) {
    1286         945 :   return static_cast<uint8_t>(encoding);
    1287             : }
    1288             : 
    1289           0 : inline std::ostream& operator<<(std::ostream& os, UnicodeEncoding encoding) {
    1290           0 :   switch (encoding) {
    1291             :     case UnicodeEncoding::UTF16:
    1292           0 :       return os << "UTF16";
    1293             :     case UnicodeEncoding::UTF32:
    1294           0 :       return os << "UTF32";
    1295             :   }
    1296           0 :   UNREACHABLE();
    1297             : }
    1298             : 
    1299             : enum class IterationKind { kKeys, kValues, kEntries };
    1300             : 
    1301           0 : inline std::ostream& operator<<(std::ostream& os, IterationKind kind) {
    1302           0 :   switch (kind) {
    1303             :     case IterationKind::kKeys:
    1304           0 :       return os << "IterationKind::kKeys";
    1305             :     case IterationKind::kValues:
    1306           0 :       return os << "IterationKind::kValues";
    1307             :     case IterationKind::kEntries:
    1308           0 :       return os << "IterationKind::kEntries";
    1309             :   }
    1310           0 :   UNREACHABLE();
    1311             : }
    1312             : 
    1313             : enum class CollectionKind { kMap, kSet };
    1314             : 
    1315           0 : inline std::ostream& operator<<(std::ostream& os, CollectionKind kind) {
    1316           0 :   switch (kind) {
    1317             :     case CollectionKind::kMap:
    1318           0 :       return os << "CollectionKind::kMap";
    1319             :     case CollectionKind::kSet:
    1320           0 :       return os << "CollectionKind::kSet";
    1321             :   }
    1322           0 :   UNREACHABLE();
    1323             : }
    1324             : 
    1325             : // Flags for the runtime function kDefineDataPropertyInLiteral. A property can
    1326             : // be enumerable or not, and, in case of functions, the function name
    1327             : // can be set or not.
    1328             : enum class DataPropertyInLiteralFlag {
    1329             :   kNoFlags = 0,
    1330             :   kDontEnum = 1 << 0,
    1331             :   kSetFunctionName = 1 << 1
    1332             : };
    1333             : typedef base::Flags<DataPropertyInLiteralFlag> DataPropertyInLiteralFlags;
    1334             : DEFINE_OPERATORS_FOR_FLAGS(DataPropertyInLiteralFlags)
    1335             : 
    1336             : enum ExternalArrayType {
    1337             :   kExternalInt8Array = 1,
    1338             :   kExternalUint8Array,
    1339             :   kExternalInt16Array,
    1340             :   kExternalUint16Array,
    1341             :   kExternalInt32Array,
    1342             :   kExternalUint32Array,
    1343             :   kExternalFloat32Array,
    1344             :   kExternalFloat64Array,
    1345             :   kExternalUint8ClampedArray,
    1346             :   kExternalBigInt64Array,
    1347             :   kExternalBigUint64Array,
    1348             : };
    1349             : 
    1350             : struct AssemblerDebugInfo {
    1351             :   AssemblerDebugInfo(const char* name, const char* file, int line)
    1352             :       : name(name), file(file), line(line) {}
    1353             :   const char* name;
    1354             :   const char* file;
    1355             :   int line;
    1356             : };
    1357             : 
    1358             : inline std::ostream& operator<<(std::ostream& os,
    1359             :                                 const AssemblerDebugInfo& info) {
    1360             :   os << "(" << info.name << ":" << info.file << ":" << info.line << ")";
    1361             :   return os;
    1362             : }
    1363             : 
    1364             : enum class OptimizationMarker {
    1365             :   kLogFirstExecution,
    1366             :   kNone,
    1367             :   kCompileOptimized,
    1368             :   kCompileOptimizedConcurrent,
    1369             :   kInOptimizationQueue
    1370             : };
    1371             : 
    1372             : inline std::ostream& operator<<(std::ostream& os,
    1373             :                                 const OptimizationMarker& marker) {
    1374             :   switch (marker) {
    1375             :     case OptimizationMarker::kLogFirstExecution:
    1376             :       return os << "OptimizationMarker::kLogFirstExecution";
    1377             :     case OptimizationMarker::kNone:
    1378             :       return os << "OptimizationMarker::kNone";
    1379             :     case OptimizationMarker::kCompileOptimized:
    1380             :       return os << "OptimizationMarker::kCompileOptimized";
    1381             :     case OptimizationMarker::kCompileOptimizedConcurrent:
    1382             :       return os << "OptimizationMarker::kCompileOptimizedConcurrent";
    1383             :     case OptimizationMarker::kInOptimizationQueue:
    1384             :       return os << "OptimizationMarker::kInOptimizationQueue";
    1385             :   }
    1386             :   UNREACHABLE();
    1387             :   return os;
    1388             : }
    1389             : 
    1390             : enum class SpeculationMode { kAllowSpeculation, kDisallowSpeculation };
    1391             : 
    1392             : inline std::ostream& operator<<(std::ostream& os,
    1393             :                                 SpeculationMode speculation_mode) {
    1394             :   switch (speculation_mode) {
    1395             :     case SpeculationMode::kAllowSpeculation:
    1396             :       return os << "SpeculationMode::kAllowSpeculation";
    1397             :     case SpeculationMode::kDisallowSpeculation:
    1398             :       return os << "SpeculationMode::kDisallowSpeculation";
    1399             :   }
    1400             :   UNREACHABLE();
    1401             :   return os;
    1402             : }
    1403             : 
    1404             : enum class BlockingBehavior { kBlock, kDontBlock };
    1405             : 
    1406             : enum class ConcurrencyMode { kNotConcurrent, kConcurrent };
    1407             : 
    1408             : #define FOR_EACH_ISOLATE_ADDRESS_NAME(C)                       \
    1409             :   C(Handler, handler)                                          \
    1410             :   C(CEntryFP, c_entry_fp)                                      \
    1411             :   C(CFunction, c_function)                                     \
    1412             :   C(Context, context)                                          \
    1413             :   C(PendingException, pending_exception)                       \
    1414             :   C(PendingHandlerContext, pending_handler_context)            \
    1415             :   C(PendingHandlerEntrypoint, pending_handler_entrypoint)      \
    1416             :   C(PendingHandlerConstantPool, pending_handler_constant_pool) \
    1417             :   C(PendingHandlerFP, pending_handler_fp)                      \
    1418             :   C(PendingHandlerSP, pending_handler_sp)                      \
    1419             :   C(ExternalCaughtException, external_caught_exception)        \
    1420             :   C(JSEntrySP, js_entry_sp)
    1421             : 
    1422             : enum IsolateAddressId {
    1423             : #define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
    1424             :   FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
    1425             : #undef DECLARE_ENUM
    1426             :       kIsolateAddressCount
    1427             : };
    1428             : 
    1429             : V8_INLINE static bool HasWeakHeapObjectTag(Address value) {
    1430             :   // TODO(jkummerow): Consolidate integer types here.
    1431  1465708597 :   return ((static_cast<intptr_t>(value) & kHeapObjectTagMask) ==
    1432             :           kWeakHeapObjectTag);
    1433             : }
    1434             : 
    1435             : enum class HeapObjectReferenceType {
    1436             :   WEAK,
    1437             :   STRONG,
    1438             : };
    1439             : 
    1440             : enum class PoisoningMitigationLevel {
    1441             :   kPoisonAll,
    1442             :   kDontPoison,
    1443             :   kPoisonCriticalOnly
    1444             : };
    1445             : 
    1446             : enum class LoadSensitivity {
    1447             :   kCritical,  // Critical loads are poisoned whenever we can run untrusted
    1448             :               // code (i.e., when --untrusted-code-mitigations is on).
    1449             :   kUnsafe,    // Unsafe loads are poisoned when full poisoning is on
    1450             :               // (--branch-load-poisoning).
    1451             :   kSafe       // Safe loads are never poisoned.
    1452             : };
    1453             : 
    1454             : // The reason for a WebAssembly trap.
    1455             : #define FOREACH_WASM_TRAPREASON(V) \
    1456             :   V(TrapUnreachable)               \
    1457             :   V(TrapMemOutOfBounds)            \
    1458             :   V(TrapUnalignedAccess)           \
    1459             :   V(TrapDivByZero)                 \
    1460             :   V(TrapDivUnrepresentable)        \
    1461             :   V(TrapRemByZero)                 \
    1462             :   V(TrapFloatUnrepresentable)      \
    1463             :   V(TrapFuncInvalid)               \
    1464             :   V(TrapFuncSigMismatch)           \
    1465             :   V(TrapDataSegmentDropped)        \
    1466             :   V(TrapElemSegmentDropped)        \
    1467             :   V(TrapTableOutOfBounds)
    1468             : 
    1469             : enum KeyedAccessLoadMode {
    1470             :   STANDARD_LOAD,
    1471             :   LOAD_IGNORE_OUT_OF_BOUNDS,
    1472             : };
    1473             : 
    1474             : enum KeyedAccessStoreMode {
    1475             :   STANDARD_STORE,
    1476             :   STORE_TRANSITION_TO_OBJECT,
    1477             :   STORE_TRANSITION_TO_DOUBLE,
    1478             :   STORE_AND_GROW_NO_TRANSITION_HANDLE_COW,
    1479             :   STORE_AND_GROW_TRANSITION_TO_OBJECT,
    1480             :   STORE_AND_GROW_TRANSITION_TO_DOUBLE,
    1481             :   STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS,
    1482             :   STORE_NO_TRANSITION_HANDLE_COW
    1483             : };
    1484             : 
    1485             : enum MutableMode { MUTABLE, IMMUTABLE };
    1486             : 
    1487             : static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) {
    1488       15093 :   return store_mode == STORE_TRANSITION_TO_OBJECT ||
    1489       15093 :          store_mode == STORE_TRANSITION_TO_DOUBLE ||
    1490       32654 :          store_mode == STORE_AND_GROW_TRANSITION_TO_OBJECT ||
    1491             :          store_mode == STORE_AND_GROW_TRANSITION_TO_DOUBLE;
    1492             : }
    1493             : 
    1494        5376 : static inline bool IsCOWHandlingStoreMode(KeyedAccessStoreMode store_mode) {
    1495        6834 :   return store_mode == STORE_NO_TRANSITION_HANDLE_COW ||
    1496        6834 :          store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW;
    1497             : }
    1498             : 
    1499             : static inline KeyedAccessStoreMode GetNonTransitioningStoreMode(
    1500             :     KeyedAccessStoreMode store_mode, bool receiver_was_cow) {
    1501      203312 :   switch (store_mode) {
    1502             :     case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW:
    1503             :     case STORE_AND_GROW_TRANSITION_TO_OBJECT:
    1504             :     case STORE_AND_GROW_TRANSITION_TO_DOUBLE:
    1505             :       store_mode = STORE_AND_GROW_NO_TRANSITION_HANDLE_COW;
    1506             :       break;
    1507             :     case STANDARD_STORE:
    1508             :     case STORE_TRANSITION_TO_OBJECT:
    1509             :     case STORE_TRANSITION_TO_DOUBLE:
    1510             :       store_mode =
    1511      190989 :           receiver_was_cow ? STORE_NO_TRANSITION_HANDLE_COW : STANDARD_STORE;
    1512             :       break;
    1513             :     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
    1514             :     case STORE_NO_TRANSITION_HANDLE_COW:
    1515             :       break;
    1516             :   }
    1517             :   DCHECK(!IsTransitionStoreMode(store_mode));
    1518             :   DCHECK_IMPLIES(receiver_was_cow, IsCOWHandlingStoreMode(store_mode));
    1519             :   return store_mode;
    1520             : }
    1521             : 
    1522        4032 : static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) {
    1523       26872 :   return store_mode >= STORE_AND_GROW_NO_TRANSITION_HANDLE_COW &&
    1524        7056 :          store_mode <= STORE_AND_GROW_TRANSITION_TO_DOUBLE;
    1525             : }
    1526             : 
    1527             : enum IcCheckType { ELEMENT, PROPERTY };
    1528             : 
    1529             : // Helper stubs can be called in different ways depending on where the target
    1530             : // code is located and how the call sequence is expected to look like:
    1531             : //  - CodeObject: Call on-heap {Code} object via {RelocInfo::CODE_TARGET}.
    1532             : //  - WasmRuntimeStub: Call native {WasmCode} stub via
    1533             : //    {RelocInfo::WASM_STUB_CALL}.
    1534             : //  - BuiltinPointer: Call a builtin based on a builtin pointer with dynamic
    1535             : //    contents. If builtins are embedded, we call directly into off-heap code
    1536             : //    without going through the on-heap Code trampoline.
    1537             : enum class StubCallMode {
    1538             :   kCallCodeObject,
    1539             :   kCallWasmRuntimeStub,
    1540             :   kCallBuiltinPointer,
    1541             : };
    1542             : 
    1543             : }  // namespace internal
    1544             : }  // namespace v8
    1545             : 
    1546             : namespace i = v8::internal;
    1547             : 
    1548             : #endif  // V8_GLOBALS_H_

Generated by: LCOV version 1.10