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