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