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