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