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 : #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.
96 : class AllStatic {
97 : #ifdef DEBUG
98 : public:
99 : AllStatic() = delete;
100 : #endif
101 : };
102 :
103 : typedef uint8_t byte;
104 :
105 : // -----------------------------------------------------------------------------
106 : // Constants
107 :
108 : constexpr int KB = 1024;
109 : constexpr int MB = KB * KB;
110 : constexpr int GB = KB * KB * KB;
111 : constexpr int kMaxInt = 0x7FFFFFFF;
112 : constexpr int kMinInt = -kMaxInt - 1;
113 : constexpr int kMaxInt8 = (1 << 7) - 1;
114 : constexpr int kMinInt8 = -(1 << 7);
115 : constexpr int kMaxUInt8 = (1 << 8) - 1;
116 : constexpr int kMinUInt8 = 0;
117 : constexpr int kMaxInt16 = (1 << 15) - 1;
118 : constexpr int kMinInt16 = -(1 << 15);
119 : constexpr int kMaxUInt16 = (1 << 16) - 1;
120 : constexpr int kMinUInt16 = 0;
121 :
122 : constexpr uint32_t kMaxUInt32 = 0xFFFFFFFFu;
123 : constexpr int kMinUInt32 = 0;
124 :
125 : constexpr int kUInt8Size = sizeof(uint8_t);
126 : constexpr int kByteSize = sizeof(byte);
127 : constexpr int kCharSize = sizeof(char);
128 : constexpr int kShortSize = sizeof(short); // NOLINT
129 : constexpr int kUInt16Size = sizeof(uint16_t);
130 : constexpr int kIntSize = sizeof(int);
131 : constexpr int kInt32Size = sizeof(int32_t);
132 : constexpr int kInt64Size = sizeof(int64_t);
133 : constexpr int kUInt32Size = sizeof(uint32_t);
134 : constexpr int kSizetSize = sizeof(size_t);
135 : constexpr int kFloatSize = sizeof(float);
136 : constexpr int kDoubleSize = sizeof(double);
137 : constexpr int kIntptrSize = sizeof(intptr_t);
138 : constexpr int kUIntptrSize = sizeof(uintptr_t);
139 : constexpr int kSystemPointerSize = sizeof(void*);
140 : constexpr int kSystemPointerHexDigits = kSystemPointerSize == 4 ? 8 : 12;
141 : constexpr int kPCOnStackSize = kSystemPointerSize;
142 : constexpr int kFPOnStackSize = kSystemPointerSize;
143 :
144 : #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
145 : constexpr int kElidedFrameSlots = kPCOnStackSize / kSystemPointerSize;
146 : #else
147 : constexpr int kElidedFrameSlots = 0;
148 : #endif
149 :
150 : constexpr int kDoubleSizeLog2 = 3;
151 : #if V8_TARGET_ARCH_ARM64
152 : // ARM64 only supports direct calls within a 128 MB range.
153 : constexpr size_t kMaxWasmCodeMB = 128;
154 : #else
155 : constexpr size_t kMaxWasmCodeMB = 1024;
156 : #endif
157 : constexpr size_t kMaxWasmCodeMemory = kMaxWasmCodeMB * MB;
158 :
159 : #if V8_HOST_ARCH_64_BIT
160 : constexpr int kSystemPointerSizeLog2 = 3;
161 : constexpr intptr_t kIntptrSignBit =
162 : static_cast<intptr_t>(uintptr_t{0x8000000000000000});
163 : constexpr uintptr_t kUintptrAllBitsSet = uintptr_t{0xFFFFFFFFFFFFFFFF};
164 : constexpr bool kRequiresCodeRange = true;
165 : #if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
166 : constexpr size_t kMaximalCodeRangeSize = 512 * MB;
167 : constexpr size_t kMinExpectedOSPageSize = 64 * KB; // OS page on PPC Linux
168 : #elif V8_TARGET_ARCH_ARM64
169 : constexpr size_t kMaximalCodeRangeSize = 128 * MB;
170 : constexpr size_t kMinExpectedOSPageSize = 4 * KB; // OS page.
171 : #else
172 : constexpr size_t kMaximalCodeRangeSize = 128 * MB;
173 : constexpr size_t kMinExpectedOSPageSize = 4 * KB; // OS page.
174 : #endif
175 : #if V8_OS_WIN
176 : constexpr size_t kMinimumCodeRangeSize = 4 * MB;
177 : constexpr size_t kReservedCodeRangePages = 1;
178 : #else
179 : constexpr size_t kMinimumCodeRangeSize = 3 * MB;
180 : constexpr size_t kReservedCodeRangePages = 0;
181 : #endif
182 : #else
183 : constexpr int kSystemPointerSizeLog2 = 2;
184 : constexpr intptr_t kIntptrSignBit = 0x80000000;
185 : constexpr uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
186 : #if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
187 : constexpr bool kRequiresCodeRange = false;
188 : constexpr size_t kMaximalCodeRangeSize = 0 * MB;
189 : constexpr size_t kMinimumCodeRangeSize = 0 * MB;
190 : constexpr size_t kMinExpectedOSPageSize = 64 * KB; // OS page on PPC Linux
191 : #elif V8_TARGET_ARCH_MIPS
192 : constexpr bool kRequiresCodeRange = false;
193 : constexpr size_t kMaximalCodeRangeSize = 2048LL * MB;
194 : constexpr size_t kMinimumCodeRangeSize = 0 * MB;
195 : constexpr size_t kMinExpectedOSPageSize = 4 * KB; // OS page.
196 : #else
197 : constexpr bool kRequiresCodeRange = false;
198 : constexpr size_t kMaximalCodeRangeSize = 0 * MB;
199 : constexpr size_t kMinimumCodeRangeSize = 0 * MB;
200 : constexpr size_t kMinExpectedOSPageSize = 4 * KB; // OS page.
201 : #endif
202 : constexpr size_t kReservedCodeRangePages = 0;
203 : #endif
204 :
205 : STATIC_ASSERT(kSystemPointerSize == (1 << kSystemPointerSizeLog2));
206 :
207 : #ifdef V8_COMPRESS_POINTERS
208 : static_assert(
209 : kSystemPointerSize == kInt64Size,
210 : "Pointer compression can be enabled only for 64-bit architectures");
211 :
212 : constexpr int kTaggedSize = kInt32Size;
213 : constexpr int kTaggedSizeLog2 = 2;
214 :
215 : // These types define raw and atomic storage types for tagged values stored
216 : // on V8 heap.
217 : using Tagged_t = int32_t;
218 : using AtomicTagged_t = base::Atomic32;
219 :
220 : #else
221 :
222 : constexpr int kTaggedSize = kSystemPointerSize;
223 : constexpr int kTaggedSizeLog2 = kSystemPointerSizeLog2;
224 :
225 : // These types define raw and atomic storage types for tagged values stored
226 : // on V8 heap.
227 : using Tagged_t = Address;
228 : using 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.
234 : constexpr bool kUseBranchlessPtrDecompression = true;
235 :
236 : STATIC_ASSERT(kTaggedSize == (1 << kTaggedSizeLog2));
237 :
238 : using AsAtomicTagged = base::AsAtomicPointerImpl<AtomicTagged_t>;
239 : STATIC_ASSERT(sizeof(Tagged_t) == kTaggedSize);
240 : STATIC_ASSERT(sizeof(AtomicTagged_t) == kTaggedSize);
241 :
242 : STATIC_ASSERT(kTaggedSize == kApiTaggedSize);
243 :
244 : // TODO(ishell): use kTaggedSize or kSystemPointerSize instead.
245 : #ifndef V8_COMPRESS_POINTERS
246 : constexpr int kPointerSize = kSystemPointerSize;
247 : constexpr int kPointerSizeLog2 = kSystemPointerSizeLog2;
248 : STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
249 : #endif
250 :
251 : constexpr int kEmbedderDataSlotSize = kSystemPointerSize;
252 :
253 : constexpr int kEmbedderDataSlotSizeInTaggedSlots =
254 : kEmbedderDataSlotSize / kTaggedSize;
255 : STATIC_ASSERT(kEmbedderDataSlotSize >= kSystemPointerSize);
256 :
257 : constexpr 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.
267 : constexpr int kMaxRegularHeapObjectSize = (1 << (kPageSizeBits - 1));
268 :
269 : constexpr int kBitsPerByte = 8;
270 : constexpr int kBitsPerByteLog2 = 3;
271 : constexpr int kBitsPerSystemPointer = kSystemPointerSize * kBitsPerByte;
272 : constexpr int kBitsPerInt = kIntSize * kBitsPerByte;
273 :
274 : // IEEE 754 single precision floating point number bit layout.
275 : constexpr uint32_t kBinary32SignMask = 0x80000000u;
276 : constexpr uint32_t kBinary32ExponentMask = 0x7f800000u;
277 : constexpr uint32_t kBinary32MantissaMask = 0x007fffffu;
278 : constexpr int kBinary32ExponentBias = 127;
279 : constexpr int kBinary32MaxExponent = 0xFE;
280 : constexpr int kBinary32MinExponent = 0x01;
281 : constexpr int kBinary32MantissaBits = 23;
282 : constexpr int kBinary32ExponentShift = 23;
283 :
284 : // Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
285 : // other bits set.
286 : constexpr 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.
291 : typedef uint16_t uc16;
292 : typedef int32_t uc32;
293 : constexpr int kOneByteSize = kCharSize;
294 : constexpr int kUC16Size = sizeof(uc16); // NOLINT
295 :
296 : // 128 bit SIMD value size.
297 : constexpr 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.
304 : template <typename F>
305 : F FUNCTION_CAST(byte* addr) {
306 : return reinterpret_cast<F>(reinterpret_cast<Address>(addr));
307 : }
308 :
309 : template <typename F>
310 : F FUNCTION_CAST(Address addr) {
311 7378 : 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 :
335 : enum class LanguageMode : bool { kSloppy, kStrict };
336 : static const size_t LanguageModeSize = 2;
337 :
338 : inline size_t hash_value(LanguageMode mode) {
339 0 : return static_cast<size_t>(mode);
340 : }
341 :
342 : inline const char* LanguageMode2String(LanguageMode mode) {
343 0 : switch (mode) {
344 : case LanguageMode::kSloppy:
345 : return "sloppy";
346 : case LanguageMode::kStrict:
347 : return "strict";
348 : }
349 : UNREACHABLE();
350 : }
351 :
352 : inline std::ostream& operator<<(std::ostream& os, LanguageMode mode) {
353 0 : return os << LanguageMode2String(mode);
354 : }
355 :
356 : inline bool is_sloppy(LanguageMode language_mode) {
357 26473553 : return language_mode == LanguageMode::kSloppy;
358 : }
359 :
360 : inline bool is_strict(LanguageMode language_mode) {
361 : return language_mode != LanguageMode::kSloppy;
362 : }
363 :
364 : inline 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 :
369 : inline 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.
375 : inline LanguageMode stricter_language_mode(LanguageMode mode1,
376 : LanguageMode mode2) {
377 : STATIC_ASSERT(LanguageModeSize == 2);
378 : return static_cast<LanguageMode>(static_cast<int>(mode1) |
379 170512 : 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.
384 : enum class StoreOrigin { kMaybeKeyed, kNamed };
385 :
386 : enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
387 :
388 : // Enums used by CEntry.
389 : enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
390 : enum ArgvMode { kArgvOnStack, kArgvInRegister };
391 :
392 : // This constant is used as an undefined value when passing source positions.
393 : constexpr int kNoSourcePosition = -1;
394 :
395 : // This constant is used to indicate missing deoptimization information.
396 : constexpr 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.
406 : enum class DeoptimizeKind : uint8_t {
407 : kEager,
408 : kSoft,
409 : kLazy,
410 : kLastDeoptimizeKind = kLazy
411 : };
412 : inline size_t hash_value(DeoptimizeKind kind) {
413 0 : return static_cast<size_t>(kind);
414 : }
415 72 : inline std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) {
416 72 : switch (kind) {
417 : case DeoptimizeKind::kEager:
418 72 : return os << "Eager";
419 : case DeoptimizeKind::kSoft:
420 0 : return os << "Soft";
421 : case DeoptimizeKind::kLazy:
422 0 : return os << "Lazy";
423 : }
424 0 : UNREACHABLE();
425 : }
426 :
427 : enum 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.
443 : enum class LookupHoistingMode { kNormal, kLegacySloppy };
444 :
445 : inline 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 :
456 : static_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.
459 : static_assert((kSmiValueSize + kSmiShiftSize + kSmiTagSize) % 32 == 0,
460 : "Unsupported Smi tagging scheme");
461 :
462 : constexpr bool kIsSmiValueInUpper32Bits =
463 : (kSmiValueSize + kSmiShiftSize + kSmiTagSize) == 64;
464 : constexpr bool kIsSmiValueInLower32Bits =
465 : (kSmiValueSize + kSmiShiftSize + kSmiTagSize) == 32;
466 : static_assert(!SmiValuesAre32Bits() == SmiValuesAre31Bits(),
467 : "Unsupported Smi tagging scheme");
468 : static_assert(SmiValuesAre32Bits() == kIsSmiValueInUpper32Bits,
469 : "Unsupported Smi tagging scheme");
470 : static_assert(SmiValuesAre31Bits() == kIsSmiValueInLower32Bits,
471 : "Unsupported Smi tagging scheme");
472 :
473 : // Mask for the sign bit in a smi.
474 : constexpr intptr_t kSmiSignMask = static_cast<intptr_t>(
475 : uintptr_t{1} << (kSmiValueSize + kSmiShiftSize + kSmiTagSize - 1));
476 :
477 : // Desired alignment for tagged pointers.
478 : constexpr int kObjectAlignmentBits = kTaggedSizeLog2;
479 : constexpr intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
480 : constexpr intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
481 :
482 : // Desired alignment for system pointers.
483 : constexpr intptr_t kPointerAlignment = (1 << kSystemPointerSizeLog2);
484 : constexpr intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
485 :
486 : // Desired alignment for double values.
487 : constexpr intptr_t kDoubleAlignment = 8;
488 : constexpr intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1;
489 :
490 : // Desired alignment for generated code is 32 bytes (to improve cache line
491 : // utilization).
492 : constexpr int kCodeAlignmentBits = 5;
493 : constexpr intptr_t kCodeAlignment = 1 << kCodeAlignmentBits;
494 : constexpr intptr_t kCodeAlignmentMask = kCodeAlignment - 1;
495 :
496 : const 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.
510 : const 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
515 : constexpr uint64_t kClearedFreeMemoryValue = 0;
516 : constexpr uint64_t kZapValue = uint64_t{0xdeadbeedbeadbeef};
517 : constexpr uint64_t kHandleZapValue = uint64_t{0x1baddead0baddeaf};
518 : constexpr uint64_t kGlobalHandleZapValue = uint64_t{0x1baffed00baffedf};
519 : constexpr uint64_t kFromSpaceZapValue = uint64_t{0x1beefdad0beefdaf};
520 : constexpr uint64_t kDebugZapValue = uint64_t{0xbadbaddbbadbaddb};
521 : constexpr uint64_t kSlotsZapValue = uint64_t{0xbeefdeadbeefdeef};
522 : constexpr uint64_t kFreeListZapValue = 0xfeed1eaffeed1eaf;
523 : #else
524 : constexpr uint32_t kClearedFreeMemoryValue = 0;
525 : constexpr uint32_t kZapValue = 0xdeadbeef;
526 : constexpr uint32_t kHandleZapValue = 0xbaddeaf;
527 : constexpr uint32_t kGlobalHandleZapValue = 0xbaffedf;
528 : constexpr uint32_t kFromSpaceZapValue = 0xbeefdaf;
529 : constexpr uint32_t kSlotsZapValue = 0xbeefdeef;
530 : constexpr uint32_t kDebugZapValue = 0xbadbaddb;
531 : constexpr uint32_t kFreeListZapValue = 0xfeed1eaf;
532 : #endif
533 :
534 : constexpr int kCodeZapValue = 0xbadc0de;
535 : constexpr uint32_t kPhantomReferenceZap = 0xca11bac;
536 :
537 : // Page constants.
538 : static 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.
547 : constexpr uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32);
548 :
549 : // -----------------------------------------------------------------------------
550 : // Forward declarations for frequently used classes
551 :
552 : class AccessorInfo;
553 : class Arguments;
554 : class Assembler;
555 : class ClassScope;
556 : class Code;
557 : class CodeSpace;
558 : class Context;
559 : class DeclarationScope;
560 : class Debug;
561 : class DebugInfo;
562 : class Descriptor;
563 : class DescriptorArray;
564 : class TransitionArray;
565 : class ExternalReference;
566 : class FeedbackVector;
567 : class FixedArray;
568 : class Foreign;
569 : class FreeStoreAllocationPolicy;
570 : class FunctionTemplateInfo;
571 : class GlobalDictionary;
572 : template <typename T> class Handle;
573 : class Heap;
574 : class HeapObject;
575 : class HeapObjectReference;
576 : class IC;
577 : class InterceptorInfo;
578 : class Isolate;
579 : class JSReceiver;
580 : class JSArray;
581 : class JSFunction;
582 : class JSObject;
583 : class LargeObjectSpace;
584 : class MacroAssembler;
585 : class Map;
586 : class MapSpace;
587 : class MarkCompactCollector;
588 : template <typename T>
589 : class MaybeHandle;
590 : class MaybeObject;
591 : class MemoryChunk;
592 : class MessageLocation;
593 : class ModuleScope;
594 : class Name;
595 : class NameDictionary;
596 : class NativeContext;
597 : class NewSpace;
598 : class NewLargeObjectSpace;
599 : class NumberDictionary;
600 : class Object;
601 : class CompressedObjectSlot;
602 : class CompressedMaybeObjectSlot;
603 : class CompressedMapWordSlot;
604 : class CompressedHeapObjectSlot;
605 : class FullObjectSlot;
606 : class FullMaybeObjectSlot;
607 : class FullHeapObjectSlot;
608 : class OldSpace;
609 : class ParameterCount;
610 : class ReadOnlySpace;
611 : class RelocInfo;
612 : class Scope;
613 : class ScopeInfo;
614 : class Script;
615 : class SimpleNumberDictionary;
616 : class Smi;
617 : template <typename Config, class Allocator = FreeStoreAllocationPolicy>
618 : class SplayTree;
619 : class String;
620 : class Struct;
621 : class Symbol;
622 : class Variable;
623 :
624 : enum class SlotLocation { kOnHeap, kOffHeap };
625 :
626 : template <SlotLocation slot_location>
627 : struct SlotTraits;
628 :
629 : // Off-heap slots are always full-pointer slots.
630 : template <>
631 : struct 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.
640 : template <>
641 : struct 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).
657 : using 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.
661 : using 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).
665 : using 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).
670 : using HeapObjectSlot = SlotTraits<SlotLocation::kOnHeap>::THeapObjectSlot;
671 :
672 : typedef bool (*WeakSlotCallback)(FullObjectSlot pointer);
673 :
674 : typedef bool (*WeakSlotCallbackWithHeap)(Heap* heap, FullObjectSlot pointer);
675 :
676 : // -----------------------------------------------------------------------------
677 : // Miscellaneous
678 :
679 : // NOTE: SpaceIterator depends on AllocationSpace enumeration values being
680 : // consecutive.
681 : enum 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 : };
699 : constexpr int kSpaceTagSize = 4;
700 : STATIC_ASSERT(FIRST_SPACE == 0);
701 :
702 : enum 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 :
710 : inline size_t hash_value(AllocationType kind) {
711 0 : return static_cast<uint8_t>(kind);
712 : }
713 :
714 0 : inline std::ostream& operator<<(std::ostream& os, AllocationType kind) {
715 0 : switch (kind) {
716 : case AllocationType::kYoung:
717 0 : return os << "Young";
718 : case AllocationType::kOld:
719 0 : return os << "Old";
720 : case AllocationType::kCode:
721 0 : return os << "Code";
722 : case AllocationType::kMap:
723 0 : return os << "Map";
724 : case AllocationType::kReadOnly:
725 0 : return os << "ReadOnly";
726 : }
727 0 : UNREACHABLE();
728 : }
729 :
730 : // TODO(ishell): review and rename kWordAligned to kTaggedAligned.
731 : enum AllocationAlignment { kWordAligned, kDoubleAligned, kDoubleUnaligned };
732 :
733 : enum class AccessMode { ATOMIC, NON_ATOMIC };
734 :
735 : // Supported write barrier modes.
736 : enum WriteBarrierKind : uint8_t {
737 : kNoWriteBarrier,
738 : kMapWriteBarrier,
739 : kPointerWriteBarrier,
740 : kEphemeronKeyWriteBarrier,
741 : kFullWriteBarrier
742 : };
743 :
744 : inline size_t hash_value(WriteBarrierKind kind) {
745 0 : return static_cast<uint8_t>(kind);
746 : }
747 :
748 487904 : inline std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
749 487904 : switch (kind) {
750 : case kNoWriteBarrier:
751 308800 : return os << "NoWriteBarrier";
752 : case kMapWriteBarrier:
753 0 : return os << "MapWriteBarrier";
754 : case kPointerWriteBarrier:
755 0 : return os << "PointerWriteBarrier";
756 : case kEphemeronKeyWriteBarrier:
757 0 : return os << "EphemeronKeyWriteBarrier";
758 : case kFullWriteBarrier:
759 179104 : return os << "FullWriteBarrier";
760 : }
761 0 : UNREACHABLE();
762 : }
763 :
764 : enum MinimumCapacity {
765 : USE_DEFAULT_MINIMUM_CAPACITY,
766 : USE_CUSTOM_MINIMUM_CAPACITY
767 : };
768 :
769 : enum GarbageCollector { SCAVENGER, MARK_COMPACTOR, MINOR_MARK_COMPACTOR };
770 :
771 : enum Executability { NOT_EXECUTABLE, EXECUTABLE };
772 :
773 : enum Movability { kMovable, kImmovable };
774 :
775 : enum 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 :
785 : enum 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).
792 : enum 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.
800 : enum 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.
806 : enum 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.
826 304 : inline const char* InlineCacheState2String(InlineCacheState state) {
827 304 : switch (state) {
828 : case NO_FEEDBACK:
829 : return "NOFEEDBACK";
830 : case UNINITIALIZED:
831 304 : return "UNINITIALIZED";
832 : case PREMONOMORPHIC:
833 0 : return "PREMONOMORPHIC";
834 : case MONOMORPHIC:
835 0 : return "MONOMORPHIC";
836 : case RECOMPUTE_HANDLER:
837 0 : return "RECOMPUTE_HANDLER";
838 : case POLYMORPHIC:
839 0 : return "POLYMORPHIC";
840 : case MEGAMORPHIC:
841 0 : return "MEGAMORPHIC";
842 : case GENERIC:
843 0 : return "GENERIC";
844 : }
845 0 : UNREACHABLE();
846 : }
847 :
848 : enum WhereToStart { kStartAtReceiver, kStartAtPrototype };
849 :
850 : enum ResultSentinel { kNotFound = -1, kUnsupported = -2 };
851 :
852 : enum ShouldThrow {
853 : kThrowOnError = Internals::kThrowOnError,
854 : kDontThrow = Internals::kDontThrow
855 : };
856 :
857 : // The Store Buffer (GC).
858 : typedef enum {
859 : kStoreBufferFullEvent,
860 : kStoreBufferStartScanningPagesEvent,
861 : kStoreBufferScanningPageEvent
862 : } StoreBufferEvent;
863 :
864 :
865 : typedef 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
872 : union 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 :
883 : union 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
894 : typedef IeeeDoubleLittleEndianArchType IeeeDoubleArchType;
895 : constexpr int kIeeeDoubleMantissaWordOffset = 0;
896 : constexpr int kIeeeDoubleExponentWordOffset = 4;
897 : #else
898 : typedef IeeeDoubleBigEndianArchType IeeeDoubleArchType;
899 : constexpr int kIeeeDoubleMantissaWordOffset = 4;
900 : constexpr 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.
944 : enum 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 :
950 : inline size_t hash_value(ConvertReceiverMode mode) {
951 0 : return bit_cast<unsigned>(mode);
952 : }
953 :
954 0 : inline std::ostream& operator<<(std::ostream& os, ConvertReceiverMode mode) {
955 0 : switch (mode) {
956 : case ConvertReceiverMode::kNullOrUndefined:
957 0 : return os << "NULL_OR_UNDEFINED";
958 : case ConvertReceiverMode::kNotNullOrUndefined:
959 0 : return os << "NOT_NULL_OR_UNDEFINED";
960 : case ConvertReceiverMode::kAny:
961 0 : return os << "ANY";
962 : }
963 0 : UNREACHABLE();
964 : }
965 :
966 : // Valid hints for the abstract operation OrdinaryToPrimitive,
967 : // implemented according to ES6, section 7.1.1.
968 : enum class OrdinaryToPrimitiveHint { kNumber, kString };
969 :
970 : // Valid hints for the abstract operation ToPrimitive,
971 : // implemented according to ES6, section 7.1.1.
972 : enum class ToPrimitiveHint { kDefault, kNumber, kString };
973 :
974 : // Defines specifics about arguments object or rest parameter creation.
975 : enum class CreateArgumentsType : uint8_t {
976 : kMappedArguments,
977 : kUnmappedArguments,
978 : kRestParameter
979 : };
980 :
981 : inline size_t hash_value(CreateArgumentsType type) {
982 7891 : return bit_cast<uint8_t>(type);
983 : }
984 :
985 0 : inline std::ostream& operator<<(std::ostream& os, CreateArgumentsType type) {
986 0 : switch (type) {
987 : case CreateArgumentsType::kMappedArguments:
988 0 : return os << "MAPPED_ARGUMENTS";
989 : case CreateArgumentsType::kUnmappedArguments:
990 0 : return os << "UNMAPPED_ARGUMENTS";
991 : case CreateArgumentsType::kRestParameter:
992 0 : return os << "REST_PARAMETER";
993 : }
994 0 : UNREACHABLE();
995 : }
996 :
997 : enum 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 :
1008 0 : inline std::ostream& operator<<(std::ostream& os, ScopeType type) {
1009 0 : switch (type) {
1010 : case ScopeType::EVAL_SCOPE:
1011 0 : return os << "EVAL_SCOPE";
1012 : case ScopeType::FUNCTION_SCOPE:
1013 0 : return os << "FUNCTION_SCOPE";
1014 : case ScopeType::MODULE_SCOPE:
1015 0 : return os << "MODULE_SCOPE";
1016 : case ScopeType::SCRIPT_SCOPE:
1017 0 : return os << "SCRIPT_SCOPE";
1018 : case ScopeType::CATCH_SCOPE:
1019 0 : return os << "CATCH_SCOPE";
1020 : case ScopeType::BLOCK_SCOPE:
1021 0 : return os << "BLOCK_SCOPE";
1022 : case ScopeType::CLASS_SCOPE:
1023 0 : return os << "CLASS_SCOPE";
1024 : case ScopeType::WITH_SCOPE:
1025 0 : return os << "WITH_SCOPE";
1026 : }
1027 0 : UNREACHABLE();
1028 : }
1029 :
1030 : // AllocationSiteMode controls whether allocations are tracked by an allocation
1031 : // site.
1032 : enum AllocationSiteMode {
1033 : DONT_TRACK_ALLOCATION_SITE,
1034 : TRACK_ALLOCATION_SITE,
1035 : LAST_ALLOCATION_SITE_MODE = TRACK_ALLOCATION_SITE
1036 : };
1037 :
1038 : enum 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)))
1045 : constexpr uint32_t kHoleNanUpper32 = 0xFFFF7FFF;
1046 : constexpr uint32_t kHoleNanLower32 = 0xFFFF7FFF;
1047 : #else
1048 : constexpr uint32_t kHoleNanUpper32 = 0xFFF7FFFF;
1049 : constexpr uint32_t kHoleNanLower32 = 0xFFF7FFFF;
1050 : #endif
1051 :
1052 : constexpr uint64_t kHoleNanInt64 =
1053 : (static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
1054 :
1055 : // ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER
1056 : constexpr double kMaxSafeInteger = 9007199254740991.0; // 2^53-1
1057 :
1058 : // The order of this enum has to be kept in sync with the predicates below.
1059 : enum 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
1088 : inline 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 :
1109 : enum VariableKind : uint8_t {
1110 : NORMAL_VARIABLE,
1111 : PARAMETER_VARIABLE,
1112 : THIS_VARIABLE,
1113 : SLOPPY_BLOCK_FUNCTION_VARIABLE,
1114 : SLOPPY_FUNCTION_NAME_VARIABLE
1115 : };
1116 :
1117 : inline bool IsDynamicVariableMode(VariableMode mode) {
1118 29146366 : return mode >= VariableMode::kDynamic && mode <= VariableMode::kDynamicLocal;
1119 : }
1120 :
1121 : inline 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 :
1127 : inline bool IsLexicalVariableMode(VariableMode mode) {
1128 : STATIC_ASSERT(static_cast<uint8_t>(VariableMode::kLet) ==
1129 : 0); // Implies that mode >= VariableMode::kLet.
1130 3179648 : return mode <= VariableMode::kLastLexicalVariableMode;
1131 : }
1132 :
1133 : enum 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).
1187 : enum InitializationFlag : uint8_t { kNeedsInitialization, kCreatedInitialized };
1188 :
1189 : enum MaybeAssignedFlag : uint8_t { kNotAssigned, kMaybeAssigned };
1190 :
1191 : enum ParseErrorType { kSyntaxError = 0, kReferenceError = 1 };
1192 :
1193 :
1194 : enum class InterpreterPushArgsMode : unsigned {
1195 : kArrayFunction,
1196 : kWithFinalSpread,
1197 : kOther
1198 : };
1199 :
1200 : inline size_t hash_value(InterpreterPushArgsMode mode) {
1201 : return bit_cast<unsigned>(mode);
1202 : }
1203 :
1204 : inline 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 :
1217 : inline 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.
1237 : class 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.
1266 : class 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 :
1283 : enum 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
1315 : class ForInFeedback {
1316 : public:
1317 : enum {
1318 : kNone = 0x0,
1319 : kEnumCacheKeysAndIndices = 0x1,
1320 : kEnumCacheKeys = 0x3,
1321 : kAny = 0x7
1322 : };
1323 : };
1324 : STATIC_ASSERT((ForInFeedback::kNone |
1325 : ForInFeedback::kEnumCacheKeysAndIndices) ==
1326 : ForInFeedback::kEnumCacheKeysAndIndices);
1327 : STATIC_ASSERT((ForInFeedback::kEnumCacheKeysAndIndices |
1328 : ForInFeedback::kEnumCacheKeys) == ForInFeedback::kEnumCacheKeys);
1329 : STATIC_ASSERT((ForInFeedback::kEnumCacheKeys | ForInFeedback::kAny) ==
1330 : ForInFeedback::kAny);
1331 :
1332 : enum 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 :
1338 : inline size_t hash_value(UnicodeEncoding encoding) {
1339 945 : return static_cast<uint8_t>(encoding);
1340 : }
1341 :
1342 0 : inline std::ostream& operator<<(std::ostream& os, UnicodeEncoding encoding) {
1343 0 : switch (encoding) {
1344 : case UnicodeEncoding::UTF16:
1345 0 : return os << "UTF16";
1346 : case UnicodeEncoding::UTF32:
1347 0 : return os << "UTF32";
1348 : }
1349 0 : UNREACHABLE();
1350 : }
1351 :
1352 : enum class IterationKind { kKeys, kValues, kEntries };
1353 :
1354 0 : inline std::ostream& operator<<(std::ostream& os, IterationKind kind) {
1355 0 : switch (kind) {
1356 : case IterationKind::kKeys:
1357 0 : return os << "IterationKind::kKeys";
1358 : case IterationKind::kValues:
1359 0 : return os << "IterationKind::kValues";
1360 : case IterationKind::kEntries:
1361 0 : return os << "IterationKind::kEntries";
1362 : }
1363 0 : UNREACHABLE();
1364 : }
1365 :
1366 : enum class CollectionKind { kMap, kSet };
1367 :
1368 0 : inline std::ostream& operator<<(std::ostream& os, CollectionKind kind) {
1369 0 : switch (kind) {
1370 : case CollectionKind::kMap:
1371 0 : return os << "CollectionKind::kMap";
1372 : case CollectionKind::kSet:
1373 0 : return os << "CollectionKind::kSet";
1374 : }
1375 0 : 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.
1381 : enum class DataPropertyInLiteralFlag {
1382 : kNoFlags = 0,
1383 : kDontEnum = 1 << 0,
1384 : kSetFunctionName = 1 << 1
1385 : };
1386 : typedef base::Flags<DataPropertyInLiteralFlag> DataPropertyInLiteralFlags;
1387 : DEFINE_OPERATORS_FOR_FLAGS(DataPropertyInLiteralFlags)
1388 :
1389 : enum 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 :
1403 : struct 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 :
1411 : inline std::ostream& operator<<(std::ostream& os,
1412 : const AssemblerDebugInfo& info) {
1413 : os << "(" << info.name << ":" << info.file << ":" << info.line << ")";
1414 : return os;
1415 : }
1416 :
1417 : enum class OptimizationMarker {
1418 : kLogFirstExecution,
1419 : kNone,
1420 : kCompileOptimized,
1421 : kCompileOptimizedConcurrent,
1422 : kInOptimizationQueue
1423 : };
1424 :
1425 : inline 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 :
1443 : enum class SpeculationMode { kAllowSpeculation, kDisallowSpeculation };
1444 :
1445 : inline 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 :
1457 : enum class BlockingBehavior { kBlock, kDontBlock };
1458 :
1459 : enum 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 :
1475 : enum 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 :
1482 : V8_INLINE static bool HasWeakHeapObjectTag(Address value) {
1483 : // TODO(jkummerow): Consolidate integer types here.
1484 812120689 : return ((static_cast<intptr_t>(value) & kHeapObjectTagMask) ==
1485 : kWeakHeapObjectTag);
1486 : }
1487 :
1488 : enum class HeapObjectReferenceType {
1489 : WEAK,
1490 : STRONG,
1491 : };
1492 :
1493 : enum class PoisoningMitigationLevel {
1494 : kPoisonAll,
1495 : kDontPoison,
1496 : kPoisonCriticalOnly
1497 : };
1498 :
1499 : enum 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 :
1522 : enum KeyedAccessLoadMode {
1523 : STANDARD_LOAD,
1524 : LOAD_IGNORE_OUT_OF_BOUNDS,
1525 : };
1526 :
1527 : enum 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 :
1538 : enum MutableMode { MUTABLE, IMMUTABLE };
1539 :
1540 : static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) {
1541 15373 : return store_mode == STORE_TRANSITION_TO_OBJECT ||
1542 15373 : store_mode == STORE_TRANSITION_TO_DOUBLE ||
1543 33237 : store_mode == STORE_AND_GROW_TRANSITION_TO_OBJECT ||
1544 : store_mode == STORE_AND_GROW_TRANSITION_TO_DOUBLE;
1545 : }
1546 :
1547 : static inline bool IsCOWHandlingStoreMode(KeyedAccessStoreMode store_mode) {
1548 6826 : return store_mode == STORE_NO_TRANSITION_HANDLE_COW ||
1549 6826 : store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW;
1550 : }
1551 :
1552 : static inline KeyedAccessStoreMode GetNonTransitioningStoreMode(
1553 : KeyedAccessStoreMode store_mode, bool receiver_was_cow) {
1554 278434 : 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 257212 : 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 :
1575 : static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) {
1576 24274 : return store_mode >= STORE_AND_GROW_NO_TRANSITION_HANDLE_COW &&
1577 : store_mode <= STORE_AND_GROW_TRANSITION_TO_DOUBLE;
1578 : }
1579 :
1580 : enum 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.
1590 : enum class StubCallMode {
1591 : kCallCodeObject,
1592 : kCallWasmRuntimeStub,
1593 : kCallBuiltinPointer,
1594 : };
1595 :
1596 : constexpr int kFunctionLiteralIdInvalid = -1;
1597 : constexpr int kFunctionLiteralIdTopLevel = 0;
1598 :
1599 : constexpr int kSmallOrderedHashSetMinCapacity = 4;
1600 : constexpr int kSmallOrderedHashMapMinCapacity = 4;
1601 :
1602 : } // namespace internal
1603 : } // namespace v8
1604 :
1605 : namespace i = v8::internal;
1606 :
1607 : #endif // V8_GLOBALS_H_
|