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