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