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

Generated by: LCOV version 1.10