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