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_COMMON_GLOBALS_H_
6 #define V8_COMMON_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/enum-set.h"
18 #include "src/base/flags.h"
19 #include "src/base/logging.h"
20 #include "src/base/macros.h"
21 
22 #define V8_INFINITY std::numeric_limits<double>::infinity()
23 
24 namespace v8 {
25 
26 namespace base {
27 class Mutex;
28 class RecursiveMutex;
29 }  // namespace base
30 
31 namespace internal {
32 
33 constexpr int KB = 1024;
34 constexpr int MB = KB * 1024;
35 constexpr int GB = MB * 1024;
36 
37 // Determine whether we are running in a simulated environment.
38 // Setting USE_SIMULATOR explicitly from the build script will force
39 // the use of a simulated environment.
40 #if !defined(USE_SIMULATOR)
41 #if (V8_TARGET_ARCH_ARM64 && !V8_HOST_ARCH_ARM64)
42 #define USE_SIMULATOR 1
43 #endif
44 #if (V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM)
45 #define USE_SIMULATOR 1
46 #endif
47 #if (V8_TARGET_ARCH_PPC && !V8_HOST_ARCH_PPC)
48 #define USE_SIMULATOR 1
49 #endif
50 #if (V8_TARGET_ARCH_PPC64 && !V8_HOST_ARCH_PPC64)
51 #define USE_SIMULATOR 1
52 #endif
53 #if (V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS)
54 #define USE_SIMULATOR 1
55 #endif
56 #if (V8_TARGET_ARCH_MIPS64 && !V8_HOST_ARCH_MIPS64)
57 #define USE_SIMULATOR 1
58 #endif
59 #if (V8_TARGET_ARCH_S390 && !V8_HOST_ARCH_S390)
60 #define USE_SIMULATOR 1
61 #endif
62 #if (V8_TARGET_ARCH_RISCV64 && !V8_HOST_ARCH_RISCV64)
63 #define USE_SIMULATOR 1
64 #endif
65 #if (V8_TARGET_ARCH_LOONG64 && !V8_HOST_ARCH_LOONG64)
66 #define USE_SIMULATOR 1
67 #endif
68 #endif
69 
70 // Determine whether the architecture uses an embedded constant pool
71 // (contiguous constant pool embedded in code object).
72 #if V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
73 #define V8_EMBEDDED_CONSTANT_POOL true
74 #else
75 #define V8_EMBEDDED_CONSTANT_POOL false
76 #endif
77 
78 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64
79 // Set stack limit lower for ARM and ARM64 than for other architectures because:
80 //  - on Arm stack allocating MacroAssembler takes 120K bytes.
81 //    See issue crbug.com/405338
82 //  - on Arm64 when running in single-process mode for Android WebView, when
83 //    initializing V8 we already have a large stack and so have to set the
84 //    limit lower. See issue crbug.com/v8/10575
85 #define V8_DEFAULT_STACK_SIZE_KB 864
86 #else
87 // Slightly less than 1MB, since Windows' default stack size for
88 // the main execution thread is 1MB for both 32 and 64-bit.
89 #define V8_DEFAULT_STACK_SIZE_KB 984
90 #endif
91 
92 // Minimum stack size in KB required by compilers.
93 constexpr int kStackSpaceRequiredForCompilation = 40;
94 
95 // In order to emit more efficient stack checks in optimized code,
96 // deoptimization may implicitly exceed the V8 stack limit by this many bytes.
97 // Stack checks in functions with `difference between optimized and unoptimized
98 // stack frame sizes <= slack` can simply emit the simple stack check.
99 constexpr int kStackLimitSlackForDeoptimizationInBytes = 256;
100 
101 // Sanity-check, assuming that we aim for a real OS stack size of at least 1MB.
102 STATIC_ASSERT(V8_DEFAULT_STACK_SIZE_KB* KB +
103                   kStackLimitSlackForDeoptimizationInBytes <=
104               MB);
105 
106 // Determine whether the short builtin calls optimization is enabled.
107 #ifdef V8_SHORT_BUILTIN_CALLS
108 #ifndef V8_COMPRESS_POINTERS
109 // TODO(11527): Fix this by passing Isolate* to Code::OffHeapInstructionStart()
110 // and friends.
111 #error Short builtin calls feature requires pointer compression
112 #endif
113 #endif
114 
115 // This constant is used for detecting whether the machine has >= 4GB of
116 // physical memory by checking the max old space size.
117 const size_t kShortBuiltinCallsOldSpaceSizeThreshold = size_t{2} * GB;
118 
119 // Determine whether dict mode prototypes feature is enabled.
120 #ifdef V8_ENABLE_SWISS_NAME_DICTIONARY
121 #define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL true
122 #else
123 #define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL false
124 #endif
125 
126 // Determine whether dict property constness tracking feature is enabled.
127 #ifdef V8_DICT_PROPERTY_CONST_TRACKING
128 #define V8_DICT_PROPERTY_CONST_TRACKING_BOOL true
129 #else
130 #define V8_DICT_PROPERTY_CONST_TRACKING_BOOL false
131 #endif
132 
133 #ifdef V8_EXTERNAL_CODE_SPACE
134 #define V8_EXTERNAL_CODE_SPACE_BOOL true
135 class CodeDataContainer;
136 using CodeT = CodeDataContainer;
137 #else
138 #define V8_EXTERNAL_CODE_SPACE_BOOL false
139 class Code;
140 using CodeT = Code;
141 #endif
142 
143 // Determine whether tagged pointers are 8 bytes (used in Torque layouts for
144 // choosing where to insert padding).
145 #if V8_TARGET_ARCH_64_BIT && !defined(V8_COMPRESS_POINTERS)
146 #define TAGGED_SIZE_8_BYTES true
147 #else
148 #define TAGGED_SIZE_8_BYTES false
149 #endif
150 
151 // Some types of tracing require the SFI to store a unique ID.
152 #if defined(V8_TRACE_MAPS) || defined(V8_TRACE_UNOPTIMIZED)
153 #define V8_SFI_HAS_UNIQUE_ID true
154 #else
155 #define V8_SFI_HAS_UNIQUE_ID false
156 #endif
157 
158 #if defined(V8_OS_WIN) && defined(V8_TARGET_ARCH_X64)
159 #define V8_OS_WIN_X64 true
160 #endif
161 
162 #if defined(V8_OS_WIN) && defined(V8_TARGET_ARCH_ARM64)
163 #define V8_OS_WIN_ARM64 true
164 #endif
165 
166 #if defined(V8_OS_WIN_X64) || defined(V8_OS_WIN_ARM64)
167 #define V8_OS_WIN64 true
168 #endif
169 
170 // Superclass for classes only using static method functions.
171 // The subclass of AllStatic cannot be instantiated at all.
172 class AllStatic {
173 #ifdef DEBUG
174  public:
175   AllStatic() = delete;
176 #endif
177 };
178 
179 using byte = uint8_t;
180 
181 // -----------------------------------------------------------------------------
182 // Constants
183 
184 constexpr int kMaxInt = 0x7FFFFFFF;
185 constexpr int kMinInt = -kMaxInt - 1;
186 constexpr int kMaxInt8 = (1 << 7) - 1;
187 constexpr int kMinInt8 = -(1 << 7);
188 constexpr int kMaxUInt8 = (1 << 8) - 1;
189 constexpr int kMinUInt8 = 0;
190 constexpr int kMaxInt16 = (1 << 15) - 1;
191 constexpr int kMinInt16 = -(1 << 15);
192 constexpr int kMaxUInt16 = (1 << 16) - 1;
193 constexpr int kMinUInt16 = 0;
194 constexpr int kMaxInt31 = kMaxInt / 2;
195 constexpr int kMinInt31 = kMinInt / 2;
196 
197 constexpr uint32_t kMaxUInt32 = 0xFFFFFFFFu;
198 constexpr int kMinUInt32 = 0;
199 
200 constexpr int kInt8Size = sizeof(int8_t);
201 constexpr int kUInt8Size = sizeof(uint8_t);
202 constexpr int kByteSize = sizeof(byte);
203 constexpr int kCharSize = sizeof(char);
204 constexpr int kShortSize = sizeof(short);  // NOLINT
205 constexpr int kInt16Size = sizeof(int16_t);
206 constexpr int kUInt16Size = sizeof(uint16_t);
207 constexpr int kIntSize = sizeof(int);
208 constexpr int kInt32Size = sizeof(int32_t);
209 constexpr int kInt64Size = sizeof(int64_t);
210 constexpr int kUInt32Size = sizeof(uint32_t);
211 constexpr int kSizetSize = sizeof(size_t);
212 constexpr int kFloatSize = sizeof(float);
213 constexpr int kDoubleSize = sizeof(double);
214 constexpr int kIntptrSize = sizeof(intptr_t);
215 constexpr int kUIntptrSize = sizeof(uintptr_t);
216 constexpr int kSystemPointerSize = sizeof(void*);
217 constexpr int kSystemPointerHexDigits = kSystemPointerSize == 4 ? 8 : 12;
218 constexpr int kPCOnStackSize = kSystemPointerSize;
219 constexpr int kFPOnStackSize = kSystemPointerSize;
220 
221 #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
222 constexpr int kElidedFrameSlots = kPCOnStackSize / kSystemPointerSize;
223 #else
224 constexpr int kElidedFrameSlots = 0;
225 #endif
226 
227 constexpr int kDoubleSizeLog2 = 3;
228 // The maximal length of the string representation for a double value
229 // (e.g. "-2.2250738585072020E-308"). It is composed as follows:
230 // - 17 decimal digits, see base::kBase10MaximalLength (dtoa.h)
231 // - 1 sign
232 // - 1 decimal point
233 // - 1 E or e
234 // - 1 exponent sign
235 // - 3 exponent
236 constexpr int kMaxDoubleStringLength = 24;
237 
238 // Total wasm code space per engine (i.e. per process) is limited to make
239 // certain attacks that rely on heap spraying harder.
240 // Just below 4GB, such that {kMaxWasmCodeMemory} fits in a 32-bit size_t.
241 constexpr size_t kMaxWasmCodeMB = 4095;
242 constexpr size_t kMaxWasmCodeMemory = kMaxWasmCodeMB * MB;
243 
244 #if V8_HOST_ARCH_64_BIT
245 constexpr int kSystemPointerSizeLog2 = 3;
246 constexpr intptr_t kIntptrSignBit =
247     static_cast<intptr_t>(uintptr_t{0x8000000000000000});
248 constexpr bool kPlatformRequiresCodeRange = true;
249 #if (V8_HOST_ARCH_PPC || V8_HOST_ARCH_PPC64) && \
250     (V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64) && V8_OS_LINUX
251 constexpr size_t kMaximalCodeRangeSize = 512 * MB;
252 constexpr size_t kMinExpectedOSPageSize = 64 * KB;  // OS page on PPC Linux
253 #elif V8_TARGET_ARCH_ARM64
254 constexpr size_t kMaximalCodeRangeSize = 128 * MB;
255 constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
256 #else
257 constexpr size_t kMaximalCodeRangeSize = 128 * MB;
258 constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
259 #endif
260 #if V8_OS_WIN
261 constexpr size_t kMinimumCodeRangeSize = 4 * MB;
262 constexpr size_t kReservedCodeRangePages = 1;
263 #else
264 constexpr size_t kMinimumCodeRangeSize = 3 * MB;
265 constexpr size_t kReservedCodeRangePages = 0;
266 #endif
267 #else
268 constexpr int kSystemPointerSizeLog2 = 2;
269 constexpr intptr_t kIntptrSignBit = 0x80000000;
270 #if (V8_HOST_ARCH_PPC || V8_HOST_ARCH_PPC64) && \
271     (V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64) && V8_OS_LINUX
272 constexpr bool kPlatformRequiresCodeRange = false;
273 constexpr size_t kMaximalCodeRangeSize = 0 * MB;
274 constexpr size_t kMinimumCodeRangeSize = 0 * MB;
275 constexpr size_t kMinExpectedOSPageSize = 64 * KB;  // OS page on PPC Linux
276 #elif V8_TARGET_ARCH_MIPS
277 constexpr bool kPlatformRequiresCodeRange = false;
278 constexpr size_t kMaximalCodeRangeSize = 2048LL * MB;
279 constexpr size_t kMinimumCodeRangeSize = 0 * MB;
280 constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
281 #else
282 constexpr bool kPlatformRequiresCodeRange = false;
283 constexpr size_t kMaximalCodeRangeSize = 0 * MB;
284 constexpr size_t kMinimumCodeRangeSize = 0 * MB;
285 constexpr size_t kMinExpectedOSPageSize = 4 * KB;  // OS page.
286 #endif
287 constexpr size_t kReservedCodeRangePages = 0;
288 #endif
289 
290 STATIC_ASSERT(kSystemPointerSize == (1 << kSystemPointerSizeLog2));
291 
292 #ifdef V8_COMPRESS_ZONES
293 #define COMPRESS_ZONES_BOOL true
294 #else
295 #define COMPRESS_ZONES_BOOL false
296 #endif  // V8_COMPRESS_ZONES
297 
298 // The flag controls whether zones pointer compression should be enabled for
299 // TurboFan graphs or not.
300 static constexpr bool kCompressGraphZone = COMPRESS_ZONES_BOOL;
301 
302 #ifdef V8_COMPRESS_POINTERS
303 static_assert(
304     kSystemPointerSize == kInt64Size,
305     "Pointer compression can be enabled only for 64-bit architectures");
306 
307 constexpr int kTaggedSize = kInt32Size;
308 constexpr int kTaggedSizeLog2 = 2;
309 
310 // These types define raw and atomic storage types for tagged values stored
311 // on V8 heap.
312 using Tagged_t = uint32_t;
313 using AtomicTagged_t = base::Atomic32;
314 
315 #else
316 
317 constexpr int kTaggedSize = kSystemPointerSize;
318 constexpr int kTaggedSizeLog2 = kSystemPointerSizeLog2;
319 
320 // These types define raw and atomic storage types for tagged values stored
321 // on V8 heap.
322 using Tagged_t = Address;
323 using AtomicTagged_t = base::AtomicWord;
324 
325 #endif  // V8_COMPRESS_POINTERS
326 
327 STATIC_ASSERT(kTaggedSize == (1 << kTaggedSizeLog2));
328 STATIC_ASSERT((kTaggedSize == 8) == TAGGED_SIZE_8_BYTES);
329 
330 using AsAtomicTagged = base::AsAtomicPointerImpl<AtomicTagged_t>;
331 STATIC_ASSERT(sizeof(Tagged_t) == kTaggedSize);
332 STATIC_ASSERT(sizeof(AtomicTagged_t) == kTaggedSize);
333 
334 STATIC_ASSERT(kTaggedSize == kApiTaggedSize);
335 
336 // TODO(ishell): use kTaggedSize or kSystemPointerSize instead.
337 #ifndef V8_COMPRESS_POINTERS
338 constexpr int kPointerSize = kSystemPointerSize;
339 constexpr int kPointerSizeLog2 = kSystemPointerSizeLog2;
340 STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
341 #endif
342 
343 // This type defines raw storage type for external (or off-V8 heap) pointers
344 // stored on V8 heap.
345 constexpr int kExternalPointerSize = sizeof(ExternalPointer_t);
346 
347 constexpr int kEmbedderDataSlotSize = kSystemPointerSize;
348 
349 constexpr int kEmbedderDataSlotSizeInTaggedSlots =
350     kEmbedderDataSlotSize / kTaggedSize;
351 STATIC_ASSERT(kEmbedderDataSlotSize >= kSystemPointerSize);
352 
353 constexpr int kExternalAllocationSoftLimit =
354     internal::Internals::kExternalAllocationSoftLimit;
355 
356 // Maximum object size that gets allocated into regular pages. Objects larger
357 // than that size are allocated in large object space and are never moved in
358 // memory. This also applies to new space allocation, since objects are never
359 // migrated from new space to large object space. Takes double alignment into
360 // account.
361 //
362 // Current value: half of the page size.
363 constexpr int kMaxRegularHeapObjectSize = (1 << (kPageSizeBits - 1));
364 
365 constexpr int kBitsPerByte = 8;
366 constexpr int kBitsPerByteLog2 = 3;
367 constexpr int kBitsPerSystemPointer = kSystemPointerSize * kBitsPerByte;
368 constexpr int kBitsPerSystemPointerLog2 =
369     kSystemPointerSizeLog2 + kBitsPerByteLog2;
370 constexpr int kBitsPerInt = kIntSize * kBitsPerByte;
371 
372 // IEEE 754 single precision floating point number bit layout.
373 constexpr uint32_t kBinary32SignMask = 0x80000000u;
374 constexpr uint32_t kBinary32ExponentMask = 0x7f800000u;
375 constexpr uint32_t kBinary32MantissaMask = 0x007fffffu;
376 constexpr int kBinary32ExponentBias = 127;
377 constexpr int kBinary32MaxExponent = 0xFE;
378 constexpr int kBinary32MinExponent = 0x01;
379 constexpr int kBinary32MantissaBits = 23;
380 constexpr int kBinary32ExponentShift = 23;
381 
382 // Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
383 // other bits set.
384 constexpr uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
385 
386 constexpr int kOneByteSize = kCharSize;
387 
388 // 128 bit SIMD value size.
389 constexpr int kSimd128Size = 16;
390 
391 // Maximum ordinal used for tracking asynchronous module evaluation order.
392 constexpr unsigned kMaxModuleAsyncEvaluatingOrdinal = (1 << 30) - 1;
393 
394 // FUNCTION_ADDR(f) gets the address of a C function f.
395 #define FUNCTION_ADDR(f) (reinterpret_cast<v8::internal::Address>(f))
396 
397 // FUNCTION_CAST<F>(addr) casts an address into a function
398 // of type F. Used to invoke generated code from within C.
399 template <typename F>
FUNCTION_CAST(byte * addr)400 F FUNCTION_CAST(byte* addr) {
401   return reinterpret_cast<F>(reinterpret_cast<Address>(addr));
402 }
403 
404 template <typename F>
FUNCTION_CAST(Address addr)405 F FUNCTION_CAST(Address addr) {
406   return reinterpret_cast<F>(addr);
407 }
408 
409 // Determine whether the architecture uses function descriptors
410 // which provide a level of indirection between the function pointer
411 // and the function entrypoint.
412 #if (V8_HOST_ARCH_PPC || V8_HOST_ARCH_PPC64) &&                    \
413     (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN && \
414                    (!defined(_CALL_ELF) || _CALL_ELF == 1)))
415 #define USES_FUNCTION_DESCRIPTORS 1
416 #define FUNCTION_ENTRYPOINT_ADDRESS(f)       \
417   (reinterpret_cast<v8::internal::Address*>( \
418       &(reinterpret_cast<intptr_t*>(f)[0])))
419 #else
420 #define USES_FUNCTION_DESCRIPTORS 0
421 #endif
422 
423 // -----------------------------------------------------------------------------
424 // Declarations for use in both the preparser and the rest of V8.
425 
426 // The Strict Mode (ECMA-262 5th edition, 4.2.2).
427 
428 enum class LanguageMode : bool { kSloppy, kStrict };
429 static const size_t LanguageModeSize = 2;
430 
hash_value(LanguageMode mode)431 inline size_t hash_value(LanguageMode mode) {
432   return static_cast<size_t>(mode);
433 }
434 
LanguageMode2String(LanguageMode mode)435 inline const char* LanguageMode2String(LanguageMode mode) {
436   switch (mode) {
437     case LanguageMode::kSloppy:
438       return "sloppy";
439     case LanguageMode::kStrict:
440       return "strict";
441   }
442   UNREACHABLE();
443 }
444 
445 inline std::ostream& operator<<(std::ostream& os, LanguageMode mode) {
446   return os << LanguageMode2String(mode);
447 }
448 
is_sloppy(LanguageMode language_mode)449 inline bool is_sloppy(LanguageMode language_mode) {
450   return language_mode == LanguageMode::kSloppy;
451 }
452 
is_strict(LanguageMode language_mode)453 inline bool is_strict(LanguageMode language_mode) {
454   return language_mode != LanguageMode::kSloppy;
455 }
456 
is_valid_language_mode(int language_mode)457 inline bool is_valid_language_mode(int language_mode) {
458   return language_mode == static_cast<int>(LanguageMode::kSloppy) ||
459          language_mode == static_cast<int>(LanguageMode::kStrict);
460 }
461 
construct_language_mode(bool strict_bit)462 inline LanguageMode construct_language_mode(bool strict_bit) {
463   return static_cast<LanguageMode>(strict_bit);
464 }
465 
466 // Return kStrict if either of the language modes is kStrict, or kSloppy
467 // otherwise.
stricter_language_mode(LanguageMode mode1,LanguageMode mode2)468 inline LanguageMode stricter_language_mode(LanguageMode mode1,
469                                            LanguageMode mode2) {
470   STATIC_ASSERT(LanguageModeSize == 2);
471   return static_cast<LanguageMode>(static_cast<int>(mode1) |
472                                    static_cast<int>(mode2));
473 }
474 
475 // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
476 // a keyed store is of the form a[expression] = foo.
477 enum class StoreOrigin { kMaybeKeyed, kNamed };
478 
479 enum class TypeofMode { kInside, kNotInside };
480 
481 // Use by RecordWrite stubs.
482 enum class RememberedSetAction { kOmit, kEmit };
483 // Enums used by CEntry.
484 enum class SaveFPRegsMode { kIgnore, kSave };
485 enum class ArgvMode { kStack, kRegister };
486 
487 // This constant is used as an undefined value when passing source positions.
488 constexpr int kNoSourcePosition = -1;
489 
490 // This constant is used to signal the function entry implicit stack check
491 // bytecode offset.
492 constexpr int kFunctionEntryBytecodeOffset = -1;
493 
494 // This constant is used to signal the function exit interrupt budget handling
495 // bytecode offset.
496 constexpr int kFunctionExitBytecodeOffset = -1;
497 
498 // This constant is used to indicate missing deoptimization information.
499 constexpr int kNoDeoptimizationId = -1;
500 
501 // Deoptimize bailout kind:
502 // - Eager: a check failed in the optimized code and deoptimization happens
503 //   immediately.
504 // - Lazy: the code has been marked as dependent on some assumption which
505 //   is checked elsewhere and can trigger deoptimization the next time the
506 //   code is executed.
507 // - Soft: similar to lazy deoptimization, but does not contribute to the
508 //   total deopt count which can lead to disabling optimization for a function.
509 // - Bailout: a check failed in the optimized code but we don't
510 //   deoptimize the code, but try to heal the feedback and try to rerun
511 //   the optimized code again.
512 // - EagerWithResume: a check failed in the optimized code, but we can execute
513 //   a more expensive check in a builtin that might either result in us resuming
514 //   execution in the optimized code, or deoptimizing immediately.
515 enum class DeoptimizeKind : uint8_t {
516   kEager,
517   kSoft,
518   kBailout,
519   kLazy,
520   kEagerWithResume,
521 };
522 constexpr DeoptimizeKind kFirstDeoptimizeKind = DeoptimizeKind::kEager;
523 constexpr DeoptimizeKind kLastDeoptimizeKind = DeoptimizeKind::kEagerWithResume;
524 STATIC_ASSERT(static_cast<int>(kFirstDeoptimizeKind) == 0);
525 constexpr int kDeoptimizeKindCount = static_cast<int>(kLastDeoptimizeKind) + 1;
hash_value(DeoptimizeKind kind)526 inline size_t hash_value(DeoptimizeKind kind) {
527   return static_cast<size_t>(kind);
528 }
529 inline std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) {
530   switch (kind) {
531     case DeoptimizeKind::kEager:
532       return os << "Eager";
533     case DeoptimizeKind::kSoft:
534       return os << "Soft";
535     case DeoptimizeKind::kLazy:
536       return os << "Lazy";
537     case DeoptimizeKind::kBailout:
538       return os << "Bailout";
539     case DeoptimizeKind::kEagerWithResume:
540       return os << "EagerMaybeResume";
541   }
542 }
543 
544 // Indicates whether the lookup is related to sloppy-mode block-scoped
545 // function hoisting, and is a synthetic assignment for that.
546 enum class LookupHoistingMode { kNormal, kLegacySloppy };
547 
548 inline std::ostream& operator<<(std::ostream& os,
549                                 const LookupHoistingMode& mode) {
550   switch (mode) {
551     case LookupHoistingMode::kNormal:
552       return os << "normal hoisting";
553     case LookupHoistingMode::kLegacySloppy:
554       return os << "legacy sloppy hoisting";
555   }
556   UNREACHABLE();
557 }
558 
559 static_assert(kSmiValueSize <= 32, "Unsupported Smi tagging scheme");
560 // Smi sign bit position must be 32-bit aligned so we can use sign extension
561 // instructions on 64-bit architectures without additional shifts.
562 static_assert((kSmiValueSize + kSmiShiftSize + kSmiTagSize) % 32 == 0,
563               "Unsupported Smi tagging scheme");
564 
565 constexpr bool kIsSmiValueInUpper32Bits =
566     (kSmiValueSize + kSmiShiftSize + kSmiTagSize) == 64;
567 constexpr bool kIsSmiValueInLower32Bits =
568     (kSmiValueSize + kSmiShiftSize + kSmiTagSize) == 32;
569 static_assert(!SmiValuesAre32Bits() == SmiValuesAre31Bits(),
570               "Unsupported Smi tagging scheme");
571 static_assert(SmiValuesAre32Bits() == kIsSmiValueInUpper32Bits,
572               "Unsupported Smi tagging scheme");
573 static_assert(SmiValuesAre31Bits() == kIsSmiValueInLower32Bits,
574               "Unsupported Smi tagging scheme");
575 
576 // Mask for the sign bit in a smi.
577 constexpr intptr_t kSmiSignMask = static_cast<intptr_t>(
578     uintptr_t{1} << (kSmiValueSize + kSmiShiftSize + kSmiTagSize - 1));
579 
580 // Desired alignment for tagged pointers.
581 constexpr int kObjectAlignmentBits = kTaggedSizeLog2;
582 constexpr intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
583 constexpr intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
584 
585 // Desired alignment for system pointers.
586 constexpr intptr_t kPointerAlignment = (1 << kSystemPointerSizeLog2);
587 constexpr intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
588 
589 // Desired alignment for double values.
590 constexpr intptr_t kDoubleAlignment = 8;
591 constexpr intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1;
592 
593 // Desired alignment for generated code is 64 bytes on x64 (to allow 64-bytes
594 // loop header alignment) and 32 bytes (to improve cache line utilization) on
595 // other architectures.
596 #if V8_TARGET_ARCH_X64
597 constexpr int kCodeAlignmentBits = 6;
598 #else
599 constexpr int kCodeAlignmentBits = 5;
600 #endif
601 constexpr intptr_t kCodeAlignment = 1 << kCodeAlignmentBits;
602 constexpr intptr_t kCodeAlignmentMask = kCodeAlignment - 1;
603 
604 const Address kWeakHeapObjectMask = 1 << 1;
605 
606 // The lower 32 bits of the cleared weak reference value is always equal to
607 // the |kClearedWeakHeapObjectLower32| constant but on 64-bit architectures
608 // the value of the upper 32 bits part may be
609 // 1) zero when pointer compression is disabled,
610 // 2) upper 32 bits of the isolate root value when pointer compression is
611 //    enabled.
612 // This is necessary to make pointer decompression computation also suitable
613 // for cleared weak reference.
614 // Note, that real heap objects can't have lower 32 bits equal to 3 because
615 // this offset belongs to page header. So, in either case it's enough to
616 // compare only the lower 32 bits of a MaybeObject value in order to figure
617 // out if it's a cleared reference or not.
618 const uint32_t kClearedWeakHeapObjectLower32 = 3;
619 
620 // Zap-value: The value used for zapping dead objects.
621 // Should be a recognizable hex value tagged as a failure.
622 #ifdef V8_HOST_ARCH_64_BIT
623 constexpr uint64_t kClearedFreeMemoryValue = 0;
624 constexpr uint64_t kZapValue = uint64_t{0xdeadbeedbeadbeef};
625 constexpr uint64_t kHandleZapValue = uint64_t{0x1baddead0baddeaf};
626 constexpr uint64_t kGlobalHandleZapValue = uint64_t{0x1baffed00baffedf};
627 constexpr uint64_t kFromSpaceZapValue = uint64_t{0x1beefdad0beefdaf};
628 constexpr uint64_t kDebugZapValue = uint64_t{0xbadbaddbbadbaddb};
629 constexpr uint64_t kSlotsZapValue = uint64_t{0xbeefdeadbeefdeef};
630 constexpr uint64_t kFreeListZapValue = 0xfeed1eaffeed1eaf;
631 #else
632 constexpr uint32_t kClearedFreeMemoryValue = 0;
633 constexpr uint32_t kZapValue = 0xdeadbeef;
634 constexpr uint32_t kHandleZapValue = 0xbaddeaf;
635 constexpr uint32_t kGlobalHandleZapValue = 0xbaffedf;
636 constexpr uint32_t kFromSpaceZapValue = 0xbeefdaf;
637 constexpr uint32_t kSlotsZapValue = 0xbeefdeef;
638 constexpr uint32_t kDebugZapValue = 0xbadbaddb;
639 constexpr uint32_t kFreeListZapValue = 0xfeed1eaf;
640 #endif
641 
642 constexpr int kCodeZapValue = 0xbadc0de;
643 constexpr uint32_t kPhantomReferenceZap = 0xca11bac;
644 
645 // Page constants.
646 static const intptr_t kPageAlignmentMask = (intptr_t{1} << kPageSizeBits) - 1;
647 
648 // On Intel architecture, cache line size is 64 bytes.
649 // On ARM it may be less (32 bytes), but as far this constant is
650 // used for aligning data, it doesn't hurt to align on a greater value.
651 #define PROCESSOR_CACHE_LINE_SIZE 64
652 
653 // Constants relevant to double precision floating point numbers.
654 // If looking only at the top 32 bits, the QNaN mask is bits 19 to 30.
655 constexpr uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32);
656 
657 enum class HeapObjectReferenceType {
658   WEAK,
659   STRONG,
660 };
661 
662 enum class ArgumentsType {
663   kRuntime,
664   kJS,
665 };
666 
667 // -----------------------------------------------------------------------------
668 // Forward declarations for frequently used classes
669 
670 class AccessorInfo;
671 template <ArgumentsType>
672 class Arguments;
673 using RuntimeArguments = Arguments<ArgumentsType::kRuntime>;
674 using JavaScriptArguments = Arguments<ArgumentsType::kJS>;
675 class Assembler;
676 class ClassScope;
677 class Code;
678 class CodeDataContainer;
679 class CodeSpace;
680 class Context;
681 class DeclarationScope;
682 class Debug;
683 class DebugInfo;
684 class Descriptor;
685 class DescriptorArray;
686 class TransitionArray;
687 class ExternalReference;
688 class FeedbackVector;
689 class FixedArray;
690 class Foreign;
691 class FreeStoreAllocationPolicy;
692 class FunctionTemplateInfo;
693 class GlobalDictionary;
694 template <typename T>
695 class Handle;
696 class Heap;
697 class HeapObject;
698 class HeapObjectReference;
699 class IC;
700 class InterceptorInfo;
701 class Isolate;
702 class JSReceiver;
703 class JSArray;
704 class JSFunction;
705 class JSObject;
706 class LocalIsolate;
707 class MacroAssembler;
708 class Map;
709 class MapSpace;
710 class MarkCompactCollector;
711 template <typename T>
712 class MaybeHandle;
713 class MaybeObject;
714 class MemoryChunk;
715 class MessageLocation;
716 class ModuleScope;
717 class Name;
718 class NameDictionary;
719 class NativeContext;
720 class NewSpace;
721 class NewLargeObjectSpace;
722 class NumberDictionary;
723 class Object;
724 class OldLargeObjectSpace;
725 template <HeapObjectReferenceType kRefType, typename StorageType>
726 class TaggedImpl;
727 class StrongTaggedValue;
728 class TaggedValue;
729 class CompressedObjectSlot;
730 class CompressedMaybeObjectSlot;
731 class CompressedMapWordSlot;
732 class CompressedHeapObjectSlot;
733 class OffHeapCompressedObjectSlot;
734 class FullObjectSlot;
735 class FullMaybeObjectSlot;
736 class FullHeapObjectSlot;
737 class OffHeapFullObjectSlot;
738 class OldSpace;
739 class ReadOnlySpace;
740 class RelocInfo;
741 class Scope;
742 class ScopeInfo;
743 class Script;
744 class SimpleNumberDictionary;
745 class Smi;
746 template <typename Config, class Allocator = FreeStoreAllocationPolicy>
747 class SplayTree;
748 class String;
749 class StringStream;
750 class Struct;
751 class Symbol;
752 class Variable;
753 
754 // Slots are either full-pointer slots or compressed slots depending on whether
755 // pointer compression is enabled or not.
756 struct SlotTraits {
757 #ifdef V8_COMPRESS_POINTERS
758   using TObjectSlot = CompressedObjectSlot;
759   using TMaybeObjectSlot = CompressedMaybeObjectSlot;
760   using THeapObjectSlot = CompressedHeapObjectSlot;
761   using TOffHeapObjectSlot = OffHeapCompressedObjectSlot;
762   // TODO(v8:11880): switch to OffHeapCompressedObjectSlot.
763   using TCodeObjectSlot = CompressedObjectSlot;
764 #else
765   using TObjectSlot = FullObjectSlot;
766   using TMaybeObjectSlot = FullMaybeObjectSlot;
767   using THeapObjectSlot = FullHeapObjectSlot;
768   using TOffHeapObjectSlot = OffHeapFullObjectSlot;
769   // TODO(v8:11880): switch to OffHeapFullObjectSlot.
770   using TCodeObjectSlot = FullObjectSlot;
771 #endif
772 };
773 
774 // An ObjectSlot instance describes a kTaggedSize-sized on-heap field ("slot")
775 // holding an Object value (smi or strong heap object).
776 using ObjectSlot = SlotTraits::TObjectSlot;
777 
778 // A MaybeObjectSlot instance describes a kTaggedSize-sized on-heap field
779 // ("slot") holding MaybeObject (smi or weak heap object or strong heap object).
780 using MaybeObjectSlot = SlotTraits::TMaybeObjectSlot;
781 
782 // A HeapObjectSlot instance describes a kTaggedSize-sized field ("slot")
783 // holding a weak or strong pointer to a heap object (think:
784 // HeapObjectReference).
785 using HeapObjectSlot = SlotTraits::THeapObjectSlot;
786 
787 // An OffHeapObjectSlot instance describes a kTaggedSize-sized field ("slot")
788 // holding an Object value (smi or strong heap object), whose slot location is
789 // off-heap.
790 using OffHeapObjectSlot = SlotTraits::TOffHeapObjectSlot;
791 
792 // A CodeObjectSlot instance describes a kTaggedSize-sized field ("slot")
793 // holding a strong pointer to a Code object. The Code object slots might be
794 // compressed and since code space might be allocated off the main heap
795 // the load operations require explicit cage base value for code space.
796 using CodeObjectSlot = SlotTraits::TCodeObjectSlot;
797 
798 using WeakSlotCallback = bool (*)(FullObjectSlot pointer);
799 
800 using WeakSlotCallbackWithHeap = bool (*)(Heap* heap, FullObjectSlot pointer);
801 
802 // -----------------------------------------------------------------------------
803 // Miscellaneous
804 
805 // NOTE: SpaceIterator depends on AllocationSpace enumeration values being
806 // consecutive.
807 enum AllocationSpace {
808   RO_SPACE,       // Immortal, immovable and immutable objects,
809   OLD_SPACE,      // Old generation regular object space.
810   CODE_SPACE,     // Old generation code object space, marked executable.
811   MAP_SPACE,      // Old generation map object space, non-movable.
812   LO_SPACE,       // Old generation large object space.
813   CODE_LO_SPACE,  // Old generation large code object space.
814   NEW_LO_SPACE,   // Young generation large object space.
815   NEW_SPACE,  // Young generation semispaces for regular objects collected with
816               // Scavenger.
817 
818   FIRST_SPACE = RO_SPACE,
819   LAST_SPACE = NEW_SPACE,
820   FIRST_MUTABLE_SPACE = OLD_SPACE,
821   LAST_MUTABLE_SPACE = NEW_SPACE,
822   FIRST_GROWABLE_PAGED_SPACE = OLD_SPACE,
823   LAST_GROWABLE_PAGED_SPACE = MAP_SPACE
824 };
825 constexpr int kSpaceTagSize = 4;
826 STATIC_ASSERT(FIRST_SPACE == 0);
827 
828 enum class AllocationType : uint8_t {
829   kYoung,      // Regular object allocated in NEW_SPACE or NEW_LO_SPACE
830   kOld,        // Regular object allocated in OLD_SPACE or LO_SPACE
831   kCode,       // Code object allocated in CODE_SPACE or CODE_LO_SPACE
832   kMap,        // Map object allocated in MAP_SPACE
833   kReadOnly,   // Object allocated in RO_SPACE
834   kSharedOld,  // Regular object allocated in SHARED_OLD_SPACE or
835                // SHARED_LO_SPACE
836   kSharedMap,  // Map object in SHARED_MAP_SPACE
837 };
838 
hash_value(AllocationType kind)839 inline size_t hash_value(AllocationType kind) {
840   return static_cast<uint8_t>(kind);
841 }
842 
843 inline std::ostream& operator<<(std::ostream& os, AllocationType kind) {
844   switch (kind) {
845     case AllocationType::kYoung:
846       return os << "Young";
847     case AllocationType::kOld:
848       return os << "Old";
849     case AllocationType::kCode:
850       return os << "Code";
851     case AllocationType::kMap:
852       return os << "Map";
853     case AllocationType::kReadOnly:
854       return os << "ReadOnly";
855     case AllocationType::kSharedOld:
856       return os << "SharedOld";
857     case AllocationType::kSharedMap:
858       return os << "SharedMap";
859   }
860   UNREACHABLE();
861 }
862 
IsSharedAllocationType(AllocationType kind)863 inline constexpr bool IsSharedAllocationType(AllocationType kind) {
864   return kind == AllocationType::kSharedOld ||
865          kind == AllocationType::kSharedMap;
866 }
867 
868 // TODO(ishell): review and rename kWordAligned to kTaggedAligned.
869 enum AllocationAlignment { kWordAligned, kDoubleAligned, kDoubleUnaligned };
870 
871 enum class AccessMode { ATOMIC, NON_ATOMIC };
872 
873 enum class AllowLargeObjects { kFalse, kTrue };
874 
875 enum MinimumCapacity {
876   USE_DEFAULT_MINIMUM_CAPACITY,
877   USE_CUSTOM_MINIMUM_CAPACITY
878 };
879 
880 enum class GarbageCollector { SCAVENGER, MARK_COMPACTOR, MINOR_MARK_COMPACTOR };
881 
882 enum class CompactionSpaceKind {
883   kNone,
884   kCompactionSpaceForScavenge,
885   kCompactionSpaceForMarkCompact,
886   kCompactionSpaceForMinorMarkCompact,
887 };
888 
889 enum Executability { NOT_EXECUTABLE, EXECUTABLE };
890 
891 enum class CodeFlushMode {
892   kFlushBytecode,
893   kFlushBaselineCode,
894   kStressFlushCode,
895 };
896 
IsBaselineCodeFlushingEnabled(base::EnumSet<CodeFlushMode> mode)897 bool inline IsBaselineCodeFlushingEnabled(base::EnumSet<CodeFlushMode> mode) {
898   return mode.contains(CodeFlushMode::kFlushBaselineCode);
899 }
900 
IsByteCodeFlushingEnabled(base::EnumSet<CodeFlushMode> mode)901 bool inline IsByteCodeFlushingEnabled(base::EnumSet<CodeFlushMode> mode) {
902   return mode.contains(CodeFlushMode::kFlushBytecode);
903 }
904 
IsStressFlushingEnabled(base::EnumSet<CodeFlushMode> mode)905 bool inline IsStressFlushingEnabled(base::EnumSet<CodeFlushMode> mode) {
906   return mode.contains(CodeFlushMode::kStressFlushCode);
907 }
908 
IsFlushingDisabled(base::EnumSet<CodeFlushMode> mode)909 bool inline IsFlushingDisabled(base::EnumSet<CodeFlushMode> mode) {
910   return mode.empty();
911 }
912 
913 // Indicates whether a script should be parsed and compiled in REPL mode.
914 enum class REPLMode {
915   kYes,
916   kNo,
917 };
918 
construct_repl_mode(bool is_repl_mode)919 inline REPLMode construct_repl_mode(bool is_repl_mode) {
920   return is_repl_mode ? REPLMode::kYes : REPLMode::kNo;
921 }
922 
923 // Flag indicating whether code is built into the VM (one of the natives files).
924 enum NativesFlag { NOT_NATIVES_CODE, EXTENSION_CODE, INSPECTOR_CODE };
925 
926 // ParseRestriction is used to restrict the set of valid statements in a
927 // unit of compilation.  Restriction violations cause a syntax error.
928 enum ParseRestriction : bool {
929   NO_PARSE_RESTRICTION,         // All expressions are allowed.
930   ONLY_SINGLE_FUNCTION_LITERAL  // Only a single FunctionLiteral expression.
931 };
932 
933 // State for inline cache call sites. Aliased as IC::State.
934 enum InlineCacheState {
935   // No feedback will be collected.
936   NO_FEEDBACK,
937   // Has never been executed.
938   UNINITIALIZED,
939   // Has been executed and only one receiver type has been seen.
940   MONOMORPHIC,
941   // Check failed due to prototype (or map deprecation).
942   RECOMPUTE_HANDLER,
943   // Multiple receiver types have been seen.
944   POLYMORPHIC,
945   // Many DOM receiver types have been seen for the same accessor.
946   MEGADOM,
947   // Many receiver types have been seen.
948   MEGAMORPHIC,
949   // A generic handler is installed and no extra typefeedback is recorded.
950   GENERIC,
951 };
952 
953 // Printing support.
InlineCacheState2String(InlineCacheState state)954 inline const char* InlineCacheState2String(InlineCacheState state) {
955   switch (state) {
956     case NO_FEEDBACK:
957       return "NOFEEDBACK";
958     case UNINITIALIZED:
959       return "UNINITIALIZED";
960     case MONOMORPHIC:
961       return "MONOMORPHIC";
962     case RECOMPUTE_HANDLER:
963       return "RECOMPUTE_HANDLER";
964     case POLYMORPHIC:
965       return "POLYMORPHIC";
966     case MEGAMORPHIC:
967       return "MEGAMORPHIC";
968     case MEGADOM:
969       return "MEGADOM";
970     case GENERIC:
971       return "GENERIC";
972   }
973   UNREACHABLE();
974 }
975 
976 enum WhereToStart { kStartAtReceiver, kStartAtPrototype };
977 
978 enum ResultSentinel { kNotFound = -1, kUnsupported = -2 };
979 
980 enum ShouldThrow {
981   kThrowOnError = Internals::kThrowOnError,
982   kDontThrow = Internals::kDontThrow
983 };
984 
985 enum class ThreadKind { kMain, kBackground };
986 
987 // Union used for customized checking of the IEEE double types
988 // inlined within v8 runtime, rather than going to the underlying
989 // platform headers and libraries
990 union IeeeDoubleLittleEndianArchType {
991   double d;
992   struct {
993     unsigned int man_low : 32;
994     unsigned int man_high : 20;
995     unsigned int exp : 11;
996     unsigned int sign : 1;
997   } bits;
998 };
999 
1000 union IeeeDoubleBigEndianArchType {
1001   double d;
1002   struct {
1003     unsigned int sign : 1;
1004     unsigned int exp : 11;
1005     unsigned int man_high : 20;
1006     unsigned int man_low : 32;
1007   } bits;
1008 };
1009 
1010 #if V8_TARGET_LITTLE_ENDIAN
1011 using IeeeDoubleArchType = IeeeDoubleLittleEndianArchType;
1012 constexpr int kIeeeDoubleMantissaWordOffset = 0;
1013 constexpr int kIeeeDoubleExponentWordOffset = 4;
1014 #else
1015 using IeeeDoubleArchType = IeeeDoubleBigEndianArchType;
1016 constexpr int kIeeeDoubleMantissaWordOffset = 4;
1017 constexpr int kIeeeDoubleExponentWordOffset = 0;
1018 #endif
1019 
1020 // -----------------------------------------------------------------------------
1021 // Macros
1022 
1023 // Testers for test.
1024 
1025 #define HAS_SMI_TAG(value) \
1026   ((static_cast<i::Tagged_t>(value) & ::i::kSmiTagMask) == ::i::kSmiTag)
1027 
1028 #define HAS_STRONG_HEAP_OBJECT_TAG(value)                          \
1029   (((static_cast<i::Tagged_t>(value) & ::i::kHeapObjectTagMask) == \
1030     ::i::kHeapObjectTag))
1031 
1032 #define HAS_WEAK_HEAP_OBJECT_TAG(value)                            \
1033   (((static_cast<i::Tagged_t>(value) & ::i::kHeapObjectTagMask) == \
1034     ::i::kWeakHeapObjectTag))
1035 
1036 // OBJECT_POINTER_ALIGN returns the value aligned as a HeapObject pointer
1037 #define OBJECT_POINTER_ALIGN(value) \
1038   (((value) + ::i::kObjectAlignmentMask) & ~::i::kObjectAlignmentMask)
1039 
1040 // OBJECT_POINTER_PADDING returns the padding size required to align value
1041 // as a HeapObject pointer
1042 #define OBJECT_POINTER_PADDING(value) (OBJECT_POINTER_ALIGN(value) - (value))
1043 
1044 // POINTER_SIZE_ALIGN returns the value aligned as a system pointer.
1045 #define POINTER_SIZE_ALIGN(value) \
1046   (((value) + ::i::kPointerAlignmentMask) & ~::i::kPointerAlignmentMask)
1047 
1048 // POINTER_SIZE_PADDING returns the padding size required to align value
1049 // as a system pointer.
1050 #define POINTER_SIZE_PADDING(value) (POINTER_SIZE_ALIGN(value) - (value))
1051 
1052 // CODE_POINTER_ALIGN returns the value aligned as a generated code segment.
1053 #define CODE_POINTER_ALIGN(value) \
1054   (((value) + ::i::kCodeAlignmentMask) & ~::i::kCodeAlignmentMask)
1055 
1056 // CODE_POINTER_PADDING returns the padding size required to align value
1057 // as a generated code segment.
1058 #define CODE_POINTER_PADDING(value) (CODE_POINTER_ALIGN(value) - (value))
1059 
1060 // DOUBLE_POINTER_ALIGN returns the value algined for double pointers.
1061 #define DOUBLE_POINTER_ALIGN(value) \
1062   (((value) + ::i::kDoubleAlignmentMask) & ~::i::kDoubleAlignmentMask)
1063 
1064 // Defines hints about receiver values based on structural knowledge.
1065 enum class ConvertReceiverMode : unsigned {
1066   kNullOrUndefined,     // Guaranteed to be null or undefined.
1067   kNotNullOrUndefined,  // Guaranteed to never be null or undefined.
1068   kAny                  // No specific knowledge about receiver.
1069 };
1070 
hash_value(ConvertReceiverMode mode)1071 inline size_t hash_value(ConvertReceiverMode mode) {
1072   return bit_cast<unsigned>(mode);
1073 }
1074 
1075 inline std::ostream& operator<<(std::ostream& os, ConvertReceiverMode mode) {
1076   switch (mode) {
1077     case ConvertReceiverMode::kNullOrUndefined:
1078       return os << "NULL_OR_UNDEFINED";
1079     case ConvertReceiverMode::kNotNullOrUndefined:
1080       return os << "NOT_NULL_OR_UNDEFINED";
1081     case ConvertReceiverMode::kAny:
1082       return os << "ANY";
1083   }
1084   UNREACHABLE();
1085 }
1086 
1087 // Valid hints for the abstract operation OrdinaryToPrimitive,
1088 // implemented according to ES6, section 7.1.1.
1089 enum class OrdinaryToPrimitiveHint { kNumber, kString };
1090 
1091 // Valid hints for the abstract operation ToPrimitive,
1092 // implemented according to ES6, section 7.1.1.
1093 enum class ToPrimitiveHint { kDefault, kNumber, kString };
1094 
1095 // Defines specifics about arguments object or rest parameter creation.
1096 enum class CreateArgumentsType : uint8_t {
1097   kMappedArguments,
1098   kUnmappedArguments,
1099   kRestParameter
1100 };
1101 
hash_value(CreateArgumentsType type)1102 inline size_t hash_value(CreateArgumentsType type) {
1103   return bit_cast<uint8_t>(type);
1104 }
1105 
1106 inline std::ostream& operator<<(std::ostream& os, CreateArgumentsType type) {
1107   switch (type) {
1108     case CreateArgumentsType::kMappedArguments:
1109       return os << "MAPPED_ARGUMENTS";
1110     case CreateArgumentsType::kUnmappedArguments:
1111       return os << "UNMAPPED_ARGUMENTS";
1112     case CreateArgumentsType::kRestParameter:
1113       return os << "REST_PARAMETER";
1114   }
1115   UNREACHABLE();
1116 }
1117 
1118 enum ScopeType : uint8_t {
1119   CLASS_SCOPE,     // The scope introduced by a class.
1120   EVAL_SCOPE,      // The top-level scope for an eval source.
1121   FUNCTION_SCOPE,  // The top-level scope for a function.
1122   MODULE_SCOPE,    // The scope introduced by a module literal
1123   SCRIPT_SCOPE,    // The top-level scope for a script or a top-level eval.
1124   CATCH_SCOPE,     // The scope introduced by catch.
1125   BLOCK_SCOPE,     // The scope introduced by a new block.
1126   WITH_SCOPE       // The scope introduced by with.
1127 };
1128 
1129 inline std::ostream& operator<<(std::ostream& os, ScopeType type) {
1130   switch (type) {
1131     case ScopeType::EVAL_SCOPE:
1132       return os << "EVAL_SCOPE";
1133     case ScopeType::FUNCTION_SCOPE:
1134       return os << "FUNCTION_SCOPE";
1135     case ScopeType::MODULE_SCOPE:
1136       return os << "MODULE_SCOPE";
1137     case ScopeType::SCRIPT_SCOPE:
1138       return os << "SCRIPT_SCOPE";
1139     case ScopeType::CATCH_SCOPE:
1140       return os << "CATCH_SCOPE";
1141     case ScopeType::BLOCK_SCOPE:
1142       return os << "BLOCK_SCOPE";
1143     case ScopeType::CLASS_SCOPE:
1144       return os << "CLASS_SCOPE";
1145     case ScopeType::WITH_SCOPE:
1146       return os << "WITH_SCOPE";
1147   }
1148   UNREACHABLE();
1149 }
1150 
1151 // AllocationSiteMode controls whether allocations are tracked by an allocation
1152 // site.
1153 enum AllocationSiteMode {
1154   DONT_TRACK_ALLOCATION_SITE,
1155   TRACK_ALLOCATION_SITE,
1156   LAST_ALLOCATION_SITE_MODE = TRACK_ALLOCATION_SITE
1157 };
1158 
1159 enum class AllocationSiteUpdateMode { kUpdate, kCheckOnly };
1160 
1161 // The mips architecture prior to revision 5 has inverted encoding for sNaN.
1162 #if (V8_TARGET_ARCH_MIPS && !defined(_MIPS_ARCH_MIPS32R6) &&           \
1163      (!defined(USE_SIMULATOR) || !defined(_MIPS_TARGET_SIMULATOR))) || \
1164     (V8_TARGET_ARCH_MIPS64 && !defined(_MIPS_ARCH_MIPS64R6) &&         \
1165      (!defined(USE_SIMULATOR) || !defined(_MIPS_TARGET_SIMULATOR)))
1166 constexpr uint32_t kHoleNanUpper32 = 0xFFFF7FFF;
1167 constexpr uint32_t kHoleNanLower32 = 0xFFFF7FFF;
1168 #else
1169 constexpr uint32_t kHoleNanUpper32 = 0xFFF7FFFF;
1170 constexpr uint32_t kHoleNanLower32 = 0xFFF7FFFF;
1171 #endif
1172 
1173 constexpr uint64_t kHoleNanInt64 =
1174     (static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
1175 
1176 // ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER
1177 constexpr uint64_t kMaxSafeIntegerUint64 = 9007199254740991;  // 2^53-1
1178 constexpr double kMaxSafeInteger = static_cast<double>(kMaxSafeIntegerUint64);
1179 // ES6 section 21.1.2.8 Number.MIN_SAFE_INTEGER
1180 constexpr double kMinSafeInteger = -kMaxSafeInteger;
1181 
1182 constexpr double kMaxUInt32Double = double{kMaxUInt32};
1183 
1184 // The order of this enum has to be kept in sync with the predicates below.
1185 enum class VariableMode : uint8_t {
1186   // User declared variables:
1187   kLet,  // declared via 'let' declarations (first lexical)
1188 
1189   kConst,  // declared via 'const' declarations (last lexical)
1190 
1191   kVar,  // declared via 'var', and 'function' declarations
1192 
1193   // Variables introduced by the compiler:
1194   kTemporary,  // temporary variables (not user-visible), stack-allocated
1195                // unless the scope as a whole has forced context allocation
1196 
1197   kDynamic,  // always require dynamic lookup (we don't know
1198              // the declaration)
1199 
1200   kDynamicGlobal,  // requires dynamic lookup, but we know that the
1201                    // variable is global unless it has been shadowed
1202                    // by an eval-introduced variable
1203 
1204   kDynamicLocal,  // requires dynamic lookup, but we know that the
1205                   // variable is local and where it is unless it
1206                   // has been shadowed by an eval-introduced
1207                   // variable
1208 
1209   // Variables for private methods or accessors whose access require
1210   // brand check. Declared only in class scopes by the compiler
1211   // and allocated only in class contexts:
1212   kPrivateMethod,  // Does not coexist with any other variable with the same
1213                    // name in the same scope.
1214 
1215   kPrivateSetterOnly,  // Incompatible with variables with the same name but
1216                        // any mode other than kPrivateGetterOnly. Transition to
1217                        // kPrivateGetterAndSetter if a later declaration for the
1218                        // same name with kPrivateGetterOnly is made.
1219 
1220   kPrivateGetterOnly,  // Incompatible with variables with the same name but
1221                        // any mode other than kPrivateSetterOnly. Transition to
1222                        // kPrivateGetterAndSetter if a later declaration for the
1223                        // same name with kPrivateSetterOnly is made.
1224 
1225   kPrivateGetterAndSetter,  // Does not coexist with any other variable with the
1226                             // same name in the same scope.
1227 
1228   kLastLexicalVariableMode = kConst,
1229 };
1230 
1231 // Printing support
1232 #ifdef DEBUG
VariableMode2String(VariableMode mode)1233 inline const char* VariableMode2String(VariableMode mode) {
1234   switch (mode) {
1235     case VariableMode::kVar:
1236       return "VAR";
1237     case VariableMode::kLet:
1238       return "LET";
1239     case VariableMode::kPrivateGetterOnly:
1240       return "PRIVATE_GETTER_ONLY";
1241     case VariableMode::kPrivateSetterOnly:
1242       return "PRIVATE_SETTER_ONLY";
1243     case VariableMode::kPrivateMethod:
1244       return "PRIVATE_METHOD";
1245     case VariableMode::kPrivateGetterAndSetter:
1246       return "PRIVATE_GETTER_AND_SETTER";
1247     case VariableMode::kConst:
1248       return "CONST";
1249     case VariableMode::kDynamic:
1250       return "DYNAMIC";
1251     case VariableMode::kDynamicGlobal:
1252       return "DYNAMIC_GLOBAL";
1253     case VariableMode::kDynamicLocal:
1254       return "DYNAMIC_LOCAL";
1255     case VariableMode::kTemporary:
1256       return "TEMPORARY";
1257   }
1258   UNREACHABLE();
1259 }
1260 #endif
1261 
1262 enum VariableKind : uint8_t {
1263   NORMAL_VARIABLE,
1264   PARAMETER_VARIABLE,
1265   THIS_VARIABLE,
1266   SLOPPY_BLOCK_FUNCTION_VARIABLE,
1267   SLOPPY_FUNCTION_NAME_VARIABLE
1268 };
1269 
IsDynamicVariableMode(VariableMode mode)1270 inline bool IsDynamicVariableMode(VariableMode mode) {
1271   return mode >= VariableMode::kDynamic && mode <= VariableMode::kDynamicLocal;
1272 }
1273 
IsDeclaredVariableMode(VariableMode mode)1274 inline bool IsDeclaredVariableMode(VariableMode mode) {
1275   STATIC_ASSERT(static_cast<uint8_t>(VariableMode::kLet) ==
1276                 0);  // Implies that mode >= VariableMode::kLet.
1277   return mode <= VariableMode::kVar;
1278 }
1279 
IsPrivateMethodOrAccessorVariableMode(VariableMode mode)1280 inline bool IsPrivateMethodOrAccessorVariableMode(VariableMode mode) {
1281   return mode >= VariableMode::kPrivateMethod &&
1282          mode <= VariableMode::kPrivateGetterAndSetter;
1283 }
1284 
IsSerializableVariableMode(VariableMode mode)1285 inline bool IsSerializableVariableMode(VariableMode mode) {
1286   return IsDeclaredVariableMode(mode) ||
1287          IsPrivateMethodOrAccessorVariableMode(mode);
1288 }
1289 
IsConstVariableMode(VariableMode mode)1290 inline bool IsConstVariableMode(VariableMode mode) {
1291   return mode == VariableMode::kConst ||
1292          IsPrivateMethodOrAccessorVariableMode(mode);
1293 }
1294 
IsLexicalVariableMode(VariableMode mode)1295 inline bool IsLexicalVariableMode(VariableMode mode) {
1296   STATIC_ASSERT(static_cast<uint8_t>(VariableMode::kLet) ==
1297                 0);  // Implies that mode >= VariableMode::kLet.
1298   return mode <= VariableMode::kLastLexicalVariableMode;
1299 }
1300 
1301 enum VariableLocation : uint8_t {
1302   // Before and during variable allocation, a variable whose location is
1303   // not yet determined.  After allocation, a variable looked up as a
1304   // property on the global object (and possibly absent).  name() is the
1305   // variable name, index() is invalid.
1306   UNALLOCATED,
1307 
1308   // A slot in the parameter section on the stack.  index() is the
1309   // parameter index, counting left-to-right.  The receiver is index -1;
1310   // the first parameter is index 0.
1311   PARAMETER,
1312 
1313   // A slot in the local section on the stack.  index() is the variable
1314   // index in the stack frame, starting at 0.
1315   LOCAL,
1316 
1317   // An indexed slot in a heap context.  index() is the variable index in
1318   // the context object on the heap, starting at 0.  scope() is the
1319   // corresponding scope.
1320   CONTEXT,
1321 
1322   // A named slot in a heap context.  name() is the variable name in the
1323   // context object on the heap, with lookup starting at the current
1324   // context.  index() is invalid.
1325   LOOKUP,
1326 
1327   // A named slot in a module's export table.
1328   MODULE,
1329 
1330   // An indexed slot in a script context. index() is the variable
1331   // index in the context object on the heap, starting at 0.
1332   // Important: REPL_GLOBAL variables from different scripts with the
1333   //            same name share a single script context slot. Every
1334   //            script context will reserve a slot, but only one will be used.
1335   // REPL_GLOBAL variables are stored in script contexts, but accessed like
1336   // globals, i.e. they always require a lookup at runtime to find the right
1337   // script context.
1338   REPL_GLOBAL,
1339 
1340   kLastVariableLocation = REPL_GLOBAL
1341 };
1342 
1343 // ES6 specifies declarative environment records with mutable and immutable
1344 // bindings that can be in two states: initialized and uninitialized.
1345 // When accessing a binding, it needs to be checked for initialization.
1346 // However in the following cases the binding is initialized immediately
1347 // after creation so the initialization check can always be skipped:
1348 //
1349 // 1. Var declared local variables.
1350 //      var foo;
1351 // 2. A local variable introduced by a function declaration.
1352 //      function foo() {}
1353 // 3. Parameters
1354 //      function x(foo) {}
1355 // 4. Catch bound variables.
1356 //      try {} catch (foo) {}
1357 // 6. Function name variables of named function expressions.
1358 //      var x = function foo() {}
1359 // 7. Implicit binding of 'this'.
1360 // 8. Implicit binding of 'arguments' in functions.
1361 //
1362 // The following enum specifies a flag that indicates if the binding needs a
1363 // distinct initialization step (kNeedsInitialization) or if the binding is
1364 // immediately initialized upon creation (kCreatedInitialized).
1365 enum InitializationFlag : uint8_t { kNeedsInitialization, kCreatedInitialized };
1366 
1367 // Static variables can only be used with the class in the closest
1368 // class scope as receivers.
1369 enum class IsStaticFlag : uint8_t { kNotStatic, kStatic };
1370 
1371 enum MaybeAssignedFlag : uint8_t { kNotAssigned, kMaybeAssigned };
1372 
1373 enum class InterpreterPushArgsMode : unsigned {
1374   kArrayFunction,
1375   kWithFinalSpread,
1376   kOther
1377 };
1378 
hash_value(InterpreterPushArgsMode mode)1379 inline size_t hash_value(InterpreterPushArgsMode mode) {
1380   return bit_cast<unsigned>(mode);
1381 }
1382 
1383 inline std::ostream& operator<<(std::ostream& os,
1384                                 InterpreterPushArgsMode mode) {
1385   switch (mode) {
1386     case InterpreterPushArgsMode::kArrayFunction:
1387       return os << "ArrayFunction";
1388     case InterpreterPushArgsMode::kWithFinalSpread:
1389       return os << "WithFinalSpread";
1390     case InterpreterPushArgsMode::kOther:
1391       return os << "Other";
1392   }
1393   UNREACHABLE();
1394 }
1395 
ObjectHash(Address address)1396 inline uint32_t ObjectHash(Address address) {
1397   // All objects are at least pointer aligned, so we can remove the trailing
1398   // zeros.
1399   return static_cast<uint32_t>(address >> kTaggedSizeLog2);
1400 }
1401 
1402 // Type feedback is encoded in such a way that, we can combine the feedback
1403 // at different points by performing an 'OR' operation. Type feedback moves
1404 // to a more generic type when we combine feedback.
1405 //
1406 //   kSignedSmall -> kSignedSmallInputs -> kNumber  -> kNumberOrOddball -> kAny
1407 //                                                     kString          -> kAny
1408 //                                                     kBigInt          -> kAny
1409 //
1410 // Technically we wouldn't need the separation between the kNumber and the
1411 // kNumberOrOddball values here, since for binary operations, we always
1412 // truncate oddballs to numbers. In practice though it causes TurboFan to
1413 // generate quite a lot of unused code though if we always handle numbers
1414 // and oddballs everywhere, although in 99% of the use sites they are only
1415 // used with numbers.
1416 class BinaryOperationFeedback {
1417  public:
1418   enum {
1419     kNone = 0x0,
1420     kSignedSmall = 0x1,
1421     kSignedSmallInputs = 0x3,
1422     kNumber = 0x7,
1423     kNumberOrOddball = 0xF,
1424     kString = 0x10,
1425     kBigInt = 0x20,
1426     kAny = 0x7F
1427   };
1428 };
1429 
1430 // Type feedback is encoded in such a way that, we can combine the feedback
1431 // at different points by performing an 'OR' operation.
1432 // This is distinct from BinaryOperationFeedback on purpose, because the
1433 // feedback that matters differs greatly as well as the way it is consumed.
1434 class CompareOperationFeedback {
1435   enum {
1436     kSignedSmallFlag = 1 << 0,
1437     kOtherNumberFlag = 1 << 1,
1438     kBooleanFlag = 1 << 2,
1439     kNullOrUndefinedFlag = 1 << 3,
1440     kInternalizedStringFlag = 1 << 4,
1441     kOtherStringFlag = 1 << 5,
1442     kSymbolFlag = 1 << 6,
1443     kBigIntFlag = 1 << 7,
1444     kReceiverFlag = 1 << 8,
1445     kAnyMask = 0x1FF,
1446   };
1447 
1448  public:
1449   enum Type {
1450     kNone = 0,
1451 
1452     kBoolean = kBooleanFlag,
1453     kNullOrUndefined = kNullOrUndefinedFlag,
1454     kOddball = kBoolean | kNullOrUndefined,
1455 
1456     kSignedSmall = kSignedSmallFlag,
1457     kNumber = kSignedSmall | kOtherNumberFlag,
1458     kNumberOrBoolean = kNumber | kBoolean,
1459     kNumberOrOddball = kNumber | kOddball,
1460 
1461     kInternalizedString = kInternalizedStringFlag,
1462     kString = kInternalizedString | kOtherStringFlag,
1463 
1464     kReceiver = kReceiverFlag,
1465     kReceiverOrNullOrUndefined = kReceiver | kNullOrUndefined,
1466 
1467     kBigInt = kBigIntFlag,
1468     kSymbol = kSymbolFlag,
1469 
1470     kAny = kAnyMask,
1471   };
1472 };
1473 
1474 enum class Operation {
1475   // Binary operations.
1476   kAdd,
1477   kSubtract,
1478   kMultiply,
1479   kDivide,
1480   kModulus,
1481   kExponentiate,
1482   kBitwiseAnd,
1483   kBitwiseOr,
1484   kBitwiseXor,
1485   kShiftLeft,
1486   kShiftRight,
1487   kShiftRightLogical,
1488   // Unary operations.
1489   kBitwiseNot,
1490   kNegate,
1491   kIncrement,
1492   kDecrement,
1493   // Compare operations.
1494   kEqual,
1495   kStrictEqual,
1496   kLessThan,
1497   kLessThanOrEqual,
1498   kGreaterThan,
1499   kGreaterThanOrEqual,
1500 };
1501 
1502 // Type feedback is encoded in such a way that, we can combine the feedback
1503 // at different points by performing an 'OR' operation. Type feedback moves
1504 // to a more generic type when we combine feedback.
1505 // kNone -> kEnumCacheKeysAndIndices -> kEnumCacheKeys -> kAny
1506 enum class ForInFeedback : uint8_t {
1507   kNone = 0x0,
1508   kEnumCacheKeysAndIndices = 0x1,
1509   kEnumCacheKeys = 0x3,
1510   kAny = 0x7
1511 };
1512 STATIC_ASSERT((static_cast<int>(ForInFeedback::kNone) |
1513                static_cast<int>(ForInFeedback::kEnumCacheKeysAndIndices)) ==
1514               static_cast<int>(ForInFeedback::kEnumCacheKeysAndIndices));
1515 STATIC_ASSERT((static_cast<int>(ForInFeedback::kEnumCacheKeysAndIndices) |
1516                static_cast<int>(ForInFeedback::kEnumCacheKeys)) ==
1517               static_cast<int>(ForInFeedback::kEnumCacheKeys));
1518 STATIC_ASSERT((static_cast<int>(ForInFeedback::kEnumCacheKeys) |
1519                static_cast<int>(ForInFeedback::kAny)) ==
1520               static_cast<int>(ForInFeedback::kAny));
1521 
1522 enum class UnicodeEncoding : uint8_t {
1523   // Different unicode encodings in a |word32|:
1524   UTF16,  // hi 16bits -> trailing surrogate or 0, low 16bits -> lead surrogate
1525   UTF32,  // full UTF32 code unit / Unicode codepoint
1526 };
1527 
hash_value(UnicodeEncoding encoding)1528 inline size_t hash_value(UnicodeEncoding encoding) {
1529   return static_cast<uint8_t>(encoding);
1530 }
1531 
1532 inline std::ostream& operator<<(std::ostream& os, UnicodeEncoding encoding) {
1533   switch (encoding) {
1534     case UnicodeEncoding::UTF16:
1535       return os << "UTF16";
1536     case UnicodeEncoding::UTF32:
1537       return os << "UTF32";
1538   }
1539   UNREACHABLE();
1540 }
1541 
1542 enum class IterationKind { kKeys, kValues, kEntries };
1543 
1544 inline std::ostream& operator<<(std::ostream& os, IterationKind kind) {
1545   switch (kind) {
1546     case IterationKind::kKeys:
1547       return os << "IterationKind::kKeys";
1548     case IterationKind::kValues:
1549       return os << "IterationKind::kValues";
1550     case IterationKind::kEntries:
1551       return os << "IterationKind::kEntries";
1552   }
1553   UNREACHABLE();
1554 }
1555 
1556 enum class CollectionKind { kMap, kSet };
1557 
1558 inline std::ostream& operator<<(std::ostream& os, CollectionKind kind) {
1559   switch (kind) {
1560     case CollectionKind::kMap:
1561       return os << "CollectionKind::kMap";
1562     case CollectionKind::kSet:
1563       return os << "CollectionKind::kSet";
1564   }
1565   UNREACHABLE();
1566 }
1567 
1568 // Flags for the runtime function kDefineDataPropertyInLiteral. A property can
1569 // be enumerable or not, and, in case of functions, the function name
1570 // can be set or not.
1571 enum class DataPropertyInLiteralFlag {
1572   kNoFlags = 0,
1573   kDontEnum = 1 << 0,
1574   kSetFunctionName = 1 << 1
1575 };
1576 using DataPropertyInLiteralFlags = base::Flags<DataPropertyInLiteralFlag>;
1577 DEFINE_OPERATORS_FOR_FLAGS(DataPropertyInLiteralFlags)
1578 
1579 enum ExternalArrayType {
1580   kExternalInt8Array = 1,
1581   kExternalUint8Array,
1582   kExternalInt16Array,
1583   kExternalUint16Array,
1584   kExternalInt32Array,
1585   kExternalUint32Array,
1586   kExternalFloat32Array,
1587   kExternalFloat64Array,
1588   kExternalUint8ClampedArray,
1589   kExternalBigInt64Array,
1590   kExternalBigUint64Array,
1591 };
1592 
1593 struct AssemblerDebugInfo {
AssemblerDebugInfoAssemblerDebugInfo1594   AssemblerDebugInfo(const char* name, const char* file, int line)
1595       : name(name), file(file), line(line) {}
1596   const char* name;
1597   const char* file;
1598   int line;
1599 };
1600 
1601 inline std::ostream& operator<<(std::ostream& os,
1602                                 const AssemblerDebugInfo& info) {
1603   os << "(" << info.name << ":" << info.file << ":" << info.line << ")";
1604   return os;
1605 }
1606 
1607 using FileAndLine = std::pair<const char*, int>;
1608 
1609 enum OptimizationMarker : int32_t {
1610   // These values are set so that it is easy to check if there is a marker where
1611   // some processing needs to be done.
1612   kNone = 0b000,
1613   kInOptimizationQueue = 0b001,
1614   kCompileOptimized = 0b010,
1615   kCompileOptimizedConcurrent = 0b011,
1616   kLogFirstExecution = 0b100,
1617   kLastOptimizationMarker = kLogFirstExecution
1618 };
1619 // For kNone or kInOptimizationQueue we don't need any special processing.
1620 // To check both cases using a single mask, we expect the kNone to be 0 and
1621 // kInOptimizationQueue to be 1 so that we can mask off the lsb for checking.
1622 STATIC_ASSERT(kNone == 0b000 && kInOptimizationQueue == 0b001);
1623 STATIC_ASSERT(kLastOptimizationMarker <= 0b111);
1624 static constexpr uint32_t kNoneOrInOptimizationQueueMask = 0b110;
1625 
IsInOptimizationQueueMarker(OptimizationMarker marker)1626 inline bool IsInOptimizationQueueMarker(OptimizationMarker marker) {
1627   return marker == OptimizationMarker::kInOptimizationQueue;
1628 }
1629 
IsCompileOptimizedMarker(OptimizationMarker marker)1630 inline bool IsCompileOptimizedMarker(OptimizationMarker marker) {
1631   return marker == OptimizationMarker::kCompileOptimized ||
1632          marker == OptimizationMarker::kCompileOptimizedConcurrent;
1633 }
1634 
1635 inline std::ostream& operator<<(std::ostream& os,
1636                                 const OptimizationMarker& marker) {
1637   switch (marker) {
1638     case OptimizationMarker::kLogFirstExecution:
1639       return os << "OptimizationMarker::kLogFirstExecution";
1640     case OptimizationMarker::kNone:
1641       return os << "OptimizationMarker::kNone";
1642     case OptimizationMarker::kCompileOptimized:
1643       return os << "OptimizationMarker::kCompileOptimized";
1644     case OptimizationMarker::kCompileOptimizedConcurrent:
1645       return os << "OptimizationMarker::kCompileOptimizedConcurrent";
1646     case OptimizationMarker::kInOptimizationQueue:
1647       return os << "OptimizationMarker::kInOptimizationQueue";
1648   }
1649 }
1650 
1651 enum class OptimizationTier {
1652   kNone = 0b00,
1653   kMidTier = 0b01,
1654   kTopTier = 0b10,
1655   kLastOptimizationTier = kTopTier
1656 };
1657 static constexpr uint32_t kNoneOrMidTierMask = 0b10;
1658 static constexpr uint32_t kNoneMask = 0b11;
1659 
1660 inline std::ostream& operator<<(std::ostream& os,
1661                                 const OptimizationTier& tier) {
1662   switch (tier) {
1663     case OptimizationTier::kNone:
1664       return os << "OptimizationTier::kNone";
1665     case OptimizationTier::kMidTier:
1666       return os << "OptimizationTier::kMidTier";
1667     case OptimizationTier::kTopTier:
1668       return os << "OptimizationTier::kTopTier";
1669   }
1670 }
1671 
1672 enum class SpeculationMode { kAllowSpeculation, kDisallowSpeculation };
1673 enum class CallFeedbackContent { kTarget, kReceiver };
1674 
1675 inline std::ostream& operator<<(std::ostream& os,
1676                                 SpeculationMode speculation_mode) {
1677   switch (speculation_mode) {
1678     case SpeculationMode::kAllowSpeculation:
1679       return os << "SpeculationMode::kAllowSpeculation";
1680     case SpeculationMode::kDisallowSpeculation:
1681       return os << "SpeculationMode::kDisallowSpeculation";
1682   }
1683   UNREACHABLE();
1684   return os;
1685 }
1686 
1687 enum class BlockingBehavior { kBlock, kDontBlock };
1688 
1689 enum class ConcurrencyMode { kNotConcurrent, kConcurrent };
1690 
1691 #define FOR_EACH_ISOLATE_ADDRESS_NAME(C)                       \
1692   C(Handler, handler)                                          \
1693   C(CEntryFP, c_entry_fp)                                      \
1694   C(CFunction, c_function)                                     \
1695   C(Context, context)                                          \
1696   C(PendingException, pending_exception)                       \
1697   C(PendingHandlerContext, pending_handler_context)            \
1698   C(PendingHandlerEntrypoint, pending_handler_entrypoint)      \
1699   C(PendingHandlerConstantPool, pending_handler_constant_pool) \
1700   C(PendingHandlerFP, pending_handler_fp)                      \
1701   C(PendingHandlerSP, pending_handler_sp)                      \
1702   C(ExternalCaughtException, external_caught_exception)        \
1703   C(JSEntrySP, js_entry_sp)
1704 
1705 enum IsolateAddressId {
1706 #define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
1707   FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
1708 #undef DECLARE_ENUM
1709       kIsolateAddressCount
1710 };
1711 
1712 // The reason for a WebAssembly trap.
1713 #define FOREACH_WASM_TRAPREASON(V) \
1714   V(TrapUnreachable)               \
1715   V(TrapMemOutOfBounds)            \
1716   V(TrapUnalignedAccess)           \
1717   V(TrapDivByZero)                 \
1718   V(TrapDivUnrepresentable)        \
1719   V(TrapRemByZero)                 \
1720   V(TrapFloatUnrepresentable)      \
1721   V(TrapFuncSigMismatch)           \
1722   V(TrapDataSegmentDropped)        \
1723   V(TrapElemSegmentDropped)        \
1724   V(TrapTableOutOfBounds)          \
1725   V(TrapRethrowNull)               \
1726   V(TrapNullDereference)           \
1727   V(TrapIllegalCast)               \
1728   V(TrapArrayOutOfBounds)          \
1729   V(TrapArrayTooLarge)
1730 
1731 enum WasmRttSubMode { kCanonicalize, kFresh };
1732 
1733 enum KeyedAccessLoadMode {
1734   STANDARD_LOAD,
1735   LOAD_IGNORE_OUT_OF_BOUNDS,
1736 };
1737 
1738 enum KeyedAccessStoreMode {
1739   STANDARD_STORE,
1740   STORE_AND_GROW_HANDLE_COW,
1741   STORE_IGNORE_OUT_OF_BOUNDS,
1742   STORE_HANDLE_COW
1743 };
1744 
1745 enum MutableMode { MUTABLE, IMMUTABLE };
1746 
IsCOWHandlingStoreMode(KeyedAccessStoreMode store_mode)1747 inline bool IsCOWHandlingStoreMode(KeyedAccessStoreMode store_mode) {
1748   return store_mode == STORE_HANDLE_COW ||
1749          store_mode == STORE_AND_GROW_HANDLE_COW;
1750 }
1751 
IsGrowStoreMode(KeyedAccessStoreMode store_mode)1752 inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) {
1753   return store_mode == STORE_AND_GROW_HANDLE_COW;
1754 }
1755 
1756 enum IcCheckType { ELEMENT, PROPERTY };
1757 
1758 // Helper stubs can be called in different ways depending on where the target
1759 // code is located and how the call sequence is expected to look like:
1760 //  - CodeObject: Call on-heap {Code} object via {RelocInfo::CODE_TARGET}.
1761 //  - WasmRuntimeStub: Call native {WasmCode} stub via
1762 //    {RelocInfo::WASM_STUB_CALL}.
1763 //  - BuiltinPointer: Call a builtin based on a builtin pointer with dynamic
1764 //    contents. If builtins are embedded, we call directly into off-heap code
1765 //    without going through the on-heap Code trampoline.
1766 enum class StubCallMode {
1767   kCallCodeObject,
1768 #if V8_ENABLE_WEBASSEMBLY
1769   kCallWasmRuntimeStub,
1770 #endif  // V8_ENABLE_WEBASSEMBLY
1771   kCallBuiltinPointer,
1772 };
1773 
1774 constexpr int kFunctionLiteralIdInvalid = -1;
1775 constexpr int kFunctionLiteralIdTopLevel = 0;
1776 
1777 constexpr int kSwissNameDictionaryInitialCapacity = 4;
1778 
1779 constexpr int kSmallOrderedHashSetMinCapacity = 4;
1780 constexpr int kSmallOrderedHashMapMinCapacity = 4;
1781 
1782 #ifdef V8_INCLUDE_RECEIVER_IN_ARGC
1783 constexpr bool kJSArgcIncludesReceiver = true;
1784 constexpr int kJSArgcReceiverSlots = 1;
1785 constexpr uint16_t kDontAdaptArgumentsSentinel = 0;
1786 #else
1787 constexpr bool kJSArgcIncludesReceiver = false;
1788 constexpr int kJSArgcReceiverSlots = 0;
1789 constexpr uint16_t kDontAdaptArgumentsSentinel = static_cast<uint16_t>(-1);
1790 #endif
1791 
1792 // Helper to get the parameter count for functions with JS linkage.
JSParameterCount(int param_count_without_receiver)1793 inline constexpr int JSParameterCount(int param_count_without_receiver) {
1794   return param_count_without_receiver + kJSArgcReceiverSlots;
1795 }
1796 
1797 // Opaque data type for identifying stack frames. Used extensively
1798 // by the debugger.
1799 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
1800 // has correct value range (see Issue 830 for more details).
1801 enum StackFrameId { ID_MIN_VALUE = kMinInt, ID_MAX_VALUE = kMaxInt, NO_ID = 0 };
1802 
1803 enum class ExceptionStatus : bool { kException = false, kSuccess = true };
1804 V8_INLINE bool operator!(ExceptionStatus status) {
1805   return !static_cast<bool>(status);
1806 }
1807 
1808 enum class TraceRetainingPathMode { kEnabled, kDisabled };
1809 
1810 // Used in the ScopeInfo flags fields for the function name variable for named
1811 // function expressions, and for the receiver. Must be declared here so that it
1812 // can be used in Torque.
1813 enum class VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED };
1814 
1815 enum class DynamicCheckMapsStatus : uint8_t {
1816   kSuccess = 0,
1817   kBailout = 1,
1818   kDeopt = 2
1819 };
1820 
1821 #ifdef V8_COMPRESS_POINTERS
1822 class PtrComprCageBase {
1823  public:
PtrComprCageBase(Address address)1824   explicit constexpr PtrComprCageBase(Address address) : address_(address) {}
1825   // NOLINTNEXTLINE
1826   inline PtrComprCageBase(const Isolate* isolate);
1827   // NOLINTNEXTLINE
1828   inline PtrComprCageBase(const LocalIsolate* isolate);
1829 
1830   inline Address address() const;
1831 
1832   bool operator==(const PtrComprCageBase& other) const {
1833     return address_ == other.address_;
1834   }
1835 
1836  private:
1837   Address address_;
1838 };
1839 #else
1840 class PtrComprCageBase {
1841  public:
1842   PtrComprCageBase() = default;
1843   // NOLINTNEXTLINE
PtrComprCageBase(const Isolate * isolate)1844   PtrComprCageBase(const Isolate* isolate) {}
1845   // NOLINTNEXTLINE
PtrComprCageBase(const LocalIsolate * isolate)1846   PtrComprCageBase(const LocalIsolate* isolate) {}
1847 };
1848 #endif
1849 
1850 class int31_t {
1851  public:
int31_t()1852   constexpr int31_t() : value_(0) {}
int31_t(int value)1853   constexpr int31_t(int value) : value_(value) {  // NOLINT(runtime/explicit)
1854     DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
1855   }
1856   int31_t& operator=(int value) {
1857     DCHECK_EQ((value & 0x80000000) != 0, (value & 0x40000000) != 0);
1858     value_ = value;
1859     return *this;
1860   }
value()1861   int32_t value() const { return value_; }
int32_t()1862   operator int32_t() const { return value_; }
1863 
1864  private:
1865   int32_t value_;
1866 };
1867 
1868 enum PropertiesEnumerationMode {
1869   // String and then Symbol properties according to the spec
1870   // ES#sec-object.assign
1871   kEnumerationOrder,
1872   // Order of property addition
1873   kPropertyAdditionOrder,
1874 };
1875 
1876 }  // namespace internal
1877 
1878 // Tag dispatching support for acquire loads and release stores.
1879 struct AcquireLoadTag {};
1880 struct RelaxedLoadTag {};
1881 struct ReleaseStoreTag {};
1882 struct RelaxedStoreTag {};
1883 static constexpr AcquireLoadTag kAcquireLoad;
1884 static constexpr RelaxedLoadTag kRelaxedLoad;
1885 static constexpr ReleaseStoreTag kReleaseStore;
1886 static constexpr RelaxedStoreTag kRelaxedStore;
1887 
1888 }  // namespace v8
1889 
1890 namespace i = v8::internal;
1891 
1892 #endif  // V8_COMMON_GLOBALS_H_
1893