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 "src/base/build_config.h"
15 : #include "src/base/flags.h"
16 : #include "src/base/logging.h"
17 : #include "src/base/macros.h"
18 :
19 : #ifdef V8_OS_WIN
20 :
21 : // Setup for Windows shared library export.
22 : #ifdef BUILDING_V8_SHARED
23 : #define V8_EXPORT_PRIVATE __declspec(dllexport)
24 : #elif USING_V8_SHARED
25 : #define V8_EXPORT_PRIVATE __declspec(dllimport)
26 : #else
27 : #define V8_EXPORT_PRIVATE
28 : #endif // BUILDING_V8_SHARED
29 :
30 : #else // V8_OS_WIN
31 :
32 : // Setup for Linux shared library export.
33 : #if V8_HAS_ATTRIBUTE_VISIBILITY
34 : #ifdef BUILDING_V8_SHARED
35 : #define V8_EXPORT_PRIVATE __attribute__((visibility("default")))
36 : #else
37 : #define V8_EXPORT_PRIVATE
38 : #endif
39 : #else
40 : #define V8_EXPORT_PRIVATE
41 : #endif
42 :
43 : #endif // V8_OS_WIN
44 :
45 : #define V8_INFINITY std::numeric_limits<double>::infinity()
46 :
47 : namespace v8 {
48 :
49 : namespace base {
50 : class Mutex;
51 : class RecursiveMutex;
52 : class VirtualMemory;
53 : }
54 :
55 : namespace internal {
56 :
57 : // Determine whether we are running in a simulated environment.
58 : // Setting USE_SIMULATOR explicitly from the build script will force
59 : // the use of a simulated environment.
60 : #if !defined(USE_SIMULATOR)
61 : #if (V8_TARGET_ARCH_ARM64 && !V8_HOST_ARCH_ARM64)
62 : #define USE_SIMULATOR 1
63 : #endif
64 : #if (V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM)
65 : #define USE_SIMULATOR 1
66 : #endif
67 : #if (V8_TARGET_ARCH_PPC && !V8_HOST_ARCH_PPC)
68 : #define USE_SIMULATOR 1
69 : #endif
70 : #if (V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS)
71 : #define USE_SIMULATOR 1
72 : #endif
73 : #if (V8_TARGET_ARCH_MIPS64 && !V8_HOST_ARCH_MIPS64)
74 : #define USE_SIMULATOR 1
75 : #endif
76 : #if (V8_TARGET_ARCH_S390 && !V8_HOST_ARCH_S390)
77 : #define USE_SIMULATOR 1
78 : #endif
79 : #endif
80 :
81 : // Determine whether the architecture uses an embedded constant pool
82 : // (contiguous constant pool embedded in code object).
83 : #if V8_TARGET_ARCH_PPC
84 : #define V8_EMBEDDED_CONSTANT_POOL 1
85 : #else
86 : #define V8_EMBEDDED_CONSTANT_POOL 0
87 : #endif
88 :
89 : #ifdef V8_TARGET_ARCH_ARM
90 : // Set stack limit lower for ARM than for other architectures because
91 : // stack allocating MacroAssembler takes 120K bytes.
92 : // See issue crbug.com/405338
93 : #define V8_DEFAULT_STACK_SIZE_KB 864
94 : #else
95 : // Slightly less than 1MB, since Windows' default stack size for
96 : // the main execution thread is 1MB for both 32 and 64-bit.
97 : #define V8_DEFAULT_STACK_SIZE_KB 984
98 : #endif
99 :
100 : // Minimum stack size in KB required by compilers.
101 : const int kStackSpaceRequiredForCompilation = 40;
102 :
103 : // Determine whether double field unboxing feature is enabled.
104 : #if V8_TARGET_ARCH_64_BIT
105 : #define V8_DOUBLE_FIELDS_UNBOXING 1
106 : #else
107 : #define V8_DOUBLE_FIELDS_UNBOXING 0
108 : #endif
109 :
110 : // Some types of tracing require the SFI to store a unique ID.
111 : #if defined(V8_TRACE_MAPS) || defined(V8_TRACE_IGNITION)
112 : #define V8_SFI_HAS_UNIQUE_ID 1
113 : #endif
114 :
115 : // Superclass for classes only using static method functions.
116 : // The subclass of AllStatic cannot be instantiated at all.
117 : class AllStatic {
118 : #ifdef DEBUG
119 : public:
120 : AllStatic() = delete;
121 : #endif
122 : };
123 :
124 : // DEPRECATED
125 : // TODO(leszeks): Delete this during a quiet period
126 : #define BASE_EMBEDDED
127 :
128 : typedef uint8_t byte;
129 : typedef byte* Address;
130 :
131 : // -----------------------------------------------------------------------------
132 : // Constants
133 :
134 : const int KB = 1024;
135 : const int MB = KB * KB;
136 : const int GB = KB * KB * KB;
137 : const int kMaxInt = 0x7FFFFFFF;
138 : const int kMinInt = -kMaxInt - 1;
139 : const int kMaxInt8 = (1 << 7) - 1;
140 : const int kMinInt8 = -(1 << 7);
141 : const int kMaxUInt8 = (1 << 8) - 1;
142 : const int kMinUInt8 = 0;
143 : const int kMaxInt16 = (1 << 15) - 1;
144 : const int kMinInt16 = -(1 << 15);
145 : const int kMaxUInt16 = (1 << 16) - 1;
146 : const int kMinUInt16 = 0;
147 :
148 : const uint32_t kMaxUInt32 = 0xFFFFFFFFu;
149 : const int kMinUInt32 = 0;
150 :
151 : const int kCharSize = sizeof(char);
152 : const int kShortSize = sizeof(short); // NOLINT
153 : const int kIntSize = sizeof(int);
154 : const int kInt32Size = sizeof(int32_t);
155 : const int kInt64Size = sizeof(int64_t);
156 : const int kUInt32Size = sizeof(uint32_t);
157 : const int kSizetSize = sizeof(size_t);
158 : const int kFloatSize = sizeof(float);
159 : const int kDoubleSize = sizeof(double);
160 : const int kIntptrSize = sizeof(intptr_t);
161 : const int kUIntptrSize = sizeof(uintptr_t);
162 : const int kPointerSize = sizeof(void*);
163 : #if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
164 : const int kRegisterSize = kPointerSize + kPointerSize;
165 : #else
166 : const int kRegisterSize = kPointerSize;
167 : #endif
168 : const int kPCOnStackSize = kRegisterSize;
169 : const int kFPOnStackSize = kRegisterSize;
170 :
171 : #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
172 : const int kElidedFrameSlots = kPCOnStackSize / kPointerSize;
173 : #else
174 : const int kElidedFrameSlots = 0;
175 : #endif
176 :
177 : const int kDoubleSizeLog2 = 3;
178 :
179 : #if V8_HOST_ARCH_64_BIT
180 : const int kPointerSizeLog2 = 3;
181 : const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000);
182 : const uintptr_t kUintptrAllBitsSet = V8_UINT64_C(0xFFFFFFFFFFFFFFFF);
183 : const bool kRequiresCodeRange = true;
184 : #if V8_TARGET_ARCH_MIPS64
185 : // To use pseudo-relative jumps such as j/jal instructions which have 28-bit
186 : // encoded immediate, the addresses have to be in range of 256MB aligned
187 : // region. Used only for large object space.
188 : const size_t kMaximalCodeRangeSize = 256 * MB;
189 : const size_t kCodeRangeAreaAlignment = 256 * MB;
190 : #elif V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
191 : const size_t kMaximalCodeRangeSize = 512 * MB;
192 : const size_t kCodeRangeAreaAlignment = 64 * KB; // OS page on PPC Linux
193 : #else
194 : const size_t kMaximalCodeRangeSize = 512 * MB;
195 : const size_t kCodeRangeAreaAlignment = 4 * KB; // OS page.
196 : #endif
197 : #if V8_OS_WIN
198 : const size_t kMinimumCodeRangeSize = 4 * MB;
199 : const size_t kReservedCodeRangePages = 1;
200 : #else
201 : const size_t kMinimumCodeRangeSize = 3 * MB;
202 : const size_t kReservedCodeRangePages = 0;
203 : #endif
204 : #else
205 : const int kPointerSizeLog2 = 2;
206 : const intptr_t kIntptrSignBit = 0x80000000;
207 : const uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
208 : #if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
209 : // x32 port also requires code range.
210 : const bool kRequiresCodeRange = true;
211 : const size_t kMaximalCodeRangeSize = 256 * MB;
212 : const size_t kMinimumCodeRangeSize = 3 * MB;
213 : const size_t kCodeRangeAreaAlignment = 4 * KB; // OS page.
214 : #elif V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
215 : const bool kRequiresCodeRange = false;
216 : const size_t kMaximalCodeRangeSize = 0 * MB;
217 : const size_t kMinimumCodeRangeSize = 0 * MB;
218 : const size_t kCodeRangeAreaAlignment = 64 * KB; // OS page on PPC Linux
219 : #else
220 : const bool kRequiresCodeRange = false;
221 : const size_t kMaximalCodeRangeSize = 0 * MB;
222 : const size_t kMinimumCodeRangeSize = 0 * MB;
223 : const size_t kCodeRangeAreaAlignment = 4 * KB; // OS page.
224 : #endif
225 : const size_t kReservedCodeRangePages = 0;
226 : #endif
227 :
228 : // Trigger an incremental GCs once the external memory reaches this limit.
229 : const int kExternalAllocationSoftLimit = 64 * MB;
230 :
231 : // Maximum object size that gets allocated into regular pages. Objects larger
232 : // than that size are allocated in large object space and are never moved in
233 : // memory. This also applies to new space allocation, since objects are never
234 : // migrated from new space to large object space. Takes double alignment into
235 : // account.
236 : //
237 : // Current value: Page::kAllocatableMemory (on 32-bit arch) - 512 (slack).
238 : const int kMaxRegularHeapObjectSize = 507136;
239 :
240 : STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
241 :
242 : const int kBitsPerByte = 8;
243 : const int kBitsPerByteLog2 = 3;
244 : const int kBitsPerPointer = kPointerSize * kBitsPerByte;
245 : const int kBitsPerInt = kIntSize * kBitsPerByte;
246 :
247 : // IEEE 754 single precision floating point number bit layout.
248 : const uint32_t kBinary32SignMask = 0x80000000u;
249 : const uint32_t kBinary32ExponentMask = 0x7f800000u;
250 : const uint32_t kBinary32MantissaMask = 0x007fffffu;
251 : const int kBinary32ExponentBias = 127;
252 : const int kBinary32MaxExponent = 0xFE;
253 : const int kBinary32MinExponent = 0x01;
254 : const int kBinary32MantissaBits = 23;
255 : const int kBinary32ExponentShift = 23;
256 :
257 : // Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
258 : // other bits set.
259 : const uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
260 :
261 : // Latin1/UTF-16 constants
262 : // Code-point values in Unicode 4.0 are 21 bits wide.
263 : // Code units in UTF-16 are 16 bits wide.
264 : typedef uint16_t uc16;
265 : typedef int32_t uc32;
266 : const int kOneByteSize = kCharSize;
267 : const int kUC16Size = sizeof(uc16); // NOLINT
268 :
269 : // 128 bit SIMD value size.
270 : const int kSimd128Size = 16;
271 :
272 : // Round up n to be a multiple of sz, where sz is a power of 2.
273 : #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
274 :
275 :
276 : // FUNCTION_ADDR(f) gets the address of a C function f.
277 : #define FUNCTION_ADDR(f) \
278 : (reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(f)))
279 :
280 :
281 : // FUNCTION_CAST<F>(addr) casts an address into a function
282 : // of type F. Used to invoke generated code from within C.
283 : template <typename F>
284 634477 : F FUNCTION_CAST(Address addr) {
285 96806652 : return reinterpret_cast<F>(reinterpret_cast<intptr_t>(addr));
286 : }
287 :
288 :
289 : // Determine whether the architecture uses function descriptors
290 : // which provide a level of indirection between the function pointer
291 : // and the function entrypoint.
292 : #if V8_HOST_ARCH_PPC && \
293 : (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN))
294 : #define USES_FUNCTION_DESCRIPTORS 1
295 : #define FUNCTION_ENTRYPOINT_ADDRESS(f) \
296 : (reinterpret_cast<v8::internal::Address*>( \
297 : &(reinterpret_cast<intptr_t*>(f)[0])))
298 : #else
299 : #define USES_FUNCTION_DESCRIPTORS 0
300 : #endif
301 :
302 :
303 : // -----------------------------------------------------------------------------
304 : // Forward declarations for frequently used classes
305 : // (sorted alphabetically)
306 :
307 : class FreeStoreAllocationPolicy;
308 : template <typename T, class P = FreeStoreAllocationPolicy> class List;
309 :
310 : // -----------------------------------------------------------------------------
311 : // Declarations for use in both the preparser and the rest of V8.
312 :
313 : // The Strict Mode (ECMA-262 5th edition, 4.2.2).
314 :
315 : enum class LanguageMode : bool { kSloppy, kStrict };
316 : static const size_t LanguageModeSize = 2;
317 :
318 0 : inline size_t hash_value(LanguageMode mode) {
319 0 : return static_cast<size_t>(mode);
320 : }
321 :
322 0 : inline std::ostream& operator<<(std::ostream& os, const LanguageMode& mode) {
323 0 : switch (mode) {
324 : case LanguageMode::kSloppy:
325 0 : return os << "sloppy";
326 : case LanguageMode::kStrict:
327 0 : return os << "strict";
328 : }
329 : UNREACHABLE();
330 : }
331 :
332 634477 : inline bool is_sloppy(LanguageMode language_mode) {
333 1170243 : return language_mode == LanguageMode::kSloppy;
334 : }
335 :
336 : inline bool is_strict(LanguageMode language_mode) {
337 : return language_mode != LanguageMode::kSloppy;
338 : }
339 :
340 12403897 : inline bool is_valid_language_mode(int language_mode) {
341 12403897 : return language_mode == static_cast<int>(LanguageMode::kSloppy) ||
342 12403897 : language_mode == static_cast<int>(LanguageMode::kStrict);
343 : }
344 :
345 : inline LanguageMode construct_language_mode(bool strict_bit) {
346 : return static_cast<LanguageMode>(strict_bit);
347 : }
348 :
349 : // Return kStrict if either of the language modes is kStrict, or kSloppy
350 : // otherwise.
351 : inline LanguageMode stricter_language_mode(LanguageMode mode1,
352 : LanguageMode mode2) {
353 : STATIC_ASSERT(LanguageModeSize == 2);
354 : return static_cast<LanguageMode>(static_cast<int>(mode1) |
355 145133 : static_cast<int>(mode2));
356 : }
357 :
358 : enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
359 :
360 : // This constant is used as an undefined value when passing source positions.
361 : const int kNoSourcePosition = -1;
362 :
363 : // This constant is used to indicate missing deoptimization information.
364 : const int kNoDeoptimizationId = -1;
365 :
366 : // Deoptimize bailout kind.
367 : enum class DeoptimizeKind : uint8_t { kEager, kSoft, kLazy };
368 0 : inline size_t hash_value(DeoptimizeKind kind) {
369 0 : return static_cast<size_t>(kind);
370 : }
371 0 : inline std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) {
372 0 : switch (kind) {
373 : case DeoptimizeKind::kEager:
374 0 : return os << "Eager";
375 : case DeoptimizeKind::kSoft:
376 0 : return os << "Soft";
377 : case DeoptimizeKind::kLazy:
378 0 : return os << "Lazy";
379 : }
380 0 : UNREACHABLE();
381 : }
382 :
383 : // Indicates whether the lookup is related to sloppy-mode block-scoped
384 : // function hoisting, and is a synthetic assignment for that.
385 : enum class LookupHoistingMode { kNormal, kLegacySloppy };
386 :
387 : inline std::ostream& operator<<(std::ostream& os,
388 : const LookupHoistingMode& mode) {
389 : switch (mode) {
390 : case LookupHoistingMode::kNormal:
391 : return os << "normal hoisting";
392 : case LookupHoistingMode::kLegacySloppy:
393 : return os << "legacy sloppy hoisting";
394 : }
395 : UNREACHABLE();
396 : }
397 :
398 : // Mask for the sign bit in a smi.
399 : const intptr_t kSmiSignMask = kIntptrSignBit;
400 :
401 : const int kObjectAlignmentBits = kPointerSizeLog2;
402 : const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
403 : const intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
404 :
405 : // Desired alignment for pointers.
406 : const intptr_t kPointerAlignment = (1 << kPointerSizeLog2);
407 : const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
408 :
409 : // Desired alignment for double values.
410 : const intptr_t kDoubleAlignment = 8;
411 : const intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1;
412 :
413 : // Desired alignment for generated code is 32 bytes (to improve cache line
414 : // utilization).
415 : const int kCodeAlignmentBits = 5;
416 : const intptr_t kCodeAlignment = 1 << kCodeAlignmentBits;
417 : const intptr_t kCodeAlignmentMask = kCodeAlignment - 1;
418 :
419 : // The owner field of a page is tagged with the page header tag. We need that
420 : // to find out if a slot is part of a large object. If we mask out the lower
421 : // 0xfffff bits (1M pages), go to the owner offset, and see that this field
422 : // is tagged with the page header tag, we can just look up the owner.
423 : // Otherwise, we know that we are somewhere (not within the first 1M) in a
424 : // large object.
425 : const int kPageHeaderTag = 3;
426 : const int kPageHeaderTagSize = 2;
427 : const intptr_t kPageHeaderTagMask = (1 << kPageHeaderTagSize) - 1;
428 :
429 :
430 : // Zap-value: The value used for zapping dead objects.
431 : // Should be a recognizable hex value tagged as a failure.
432 : #ifdef V8_HOST_ARCH_64_BIT
433 : const Address kZapValue =
434 : reinterpret_cast<Address>(V8_UINT64_C(0xdeadbeedbeadbeef));
435 : const Address kHandleZapValue =
436 : reinterpret_cast<Address>(V8_UINT64_C(0x1baddead0baddeaf));
437 : const Address kGlobalHandleZapValue =
438 : reinterpret_cast<Address>(V8_UINT64_C(0x1baffed00baffedf));
439 : const Address kFromSpaceZapValue =
440 : reinterpret_cast<Address>(V8_UINT64_C(0x1beefdad0beefdaf));
441 : const uint64_t kDebugZapValue = V8_UINT64_C(0xbadbaddbbadbaddb);
442 : const uint64_t kSlotsZapValue = V8_UINT64_C(0xbeefdeadbeefdeef);
443 : const uint64_t kFreeListZapValue = 0xfeed1eaffeed1eaf;
444 : #else
445 : const Address kZapValue = reinterpret_cast<Address>(0xdeadbeef);
446 : const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddeaf);
447 : const Address kGlobalHandleZapValue = reinterpret_cast<Address>(0xbaffedf);
448 : const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdaf);
449 : const uint32_t kSlotsZapValue = 0xbeefdeef;
450 : const uint32_t kDebugZapValue = 0xbadbaddb;
451 : const uint32_t kFreeListZapValue = 0xfeed1eaf;
452 : #endif
453 :
454 : const int kCodeZapValue = 0xbadc0de;
455 : const uint32_t kPhantomReferenceZap = 0xca11bac;
456 :
457 : // On Intel architecture, cache line size is 64 bytes.
458 : // On ARM it may be less (32 bytes), but as far this constant is
459 : // used for aligning data, it doesn't hurt to align on a greater value.
460 : #define PROCESSOR_CACHE_LINE_SIZE 64
461 :
462 : // Constants relevant to double precision floating point numbers.
463 : // If looking only at the top 32 bits, the QNaN mask is bits 19 to 30.
464 : const uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32);
465 :
466 :
467 : // -----------------------------------------------------------------------------
468 : // Forward declarations for frequently used classes
469 :
470 : class AccessorInfo;
471 : class Allocation;
472 : class Arguments;
473 : class Assembler;
474 : class Code;
475 : class CodeGenerator;
476 : class CodeStub;
477 : class Context;
478 : class Debug;
479 : class DebugInfo;
480 : class Descriptor;
481 : class DescriptorArray;
482 : class TransitionArray;
483 : class ExternalReference;
484 : class FixedArray;
485 : class FunctionTemplateInfo;
486 : class MemoryChunk;
487 : class SeededNumberDictionary;
488 : class UnseededNumberDictionary;
489 : class NameDictionary;
490 : class GlobalDictionary;
491 : template <typename T> class MaybeHandle;
492 : template <typename T> class Handle;
493 : class Heap;
494 : class HeapObject;
495 : class IC;
496 : class InterceptorInfo;
497 : class Isolate;
498 : class JSReceiver;
499 : class JSArray;
500 : class JSFunction;
501 : class JSObject;
502 : class LargeObjectSpace;
503 : class MacroAssembler;
504 : class Map;
505 : class MapSpace;
506 : class MarkCompactCollector;
507 : class NewSpace;
508 : class Object;
509 : class OldSpace;
510 : class ParameterCount;
511 : class Foreign;
512 : class Scope;
513 : class DeclarationScope;
514 : class ModuleScope;
515 : class ScopeInfo;
516 : class Script;
517 : class Smi;
518 : template <typename Config, class Allocator = FreeStoreAllocationPolicy>
519 : class SplayTree;
520 : class String;
521 : class Symbol;
522 : class Name;
523 : class Struct;
524 : class FeedbackVector;
525 : class Variable;
526 : class RelocInfo;
527 : class MessageLocation;
528 :
529 : typedef bool (*WeakSlotCallback)(Object** pointer);
530 :
531 : typedef bool (*WeakSlotCallbackWithHeap)(Heap* heap, Object** pointer);
532 :
533 : // -----------------------------------------------------------------------------
534 : // Miscellaneous
535 :
536 : // NOTE: SpaceIterator depends on AllocationSpace enumeration values being
537 : // consecutive.
538 : // Keep this enum in sync with the ObjectSpace enum in v8.h
539 : enum AllocationSpace {
540 : NEW_SPACE, // Semispaces collected with copying collector.
541 : OLD_SPACE, // May contain pointers to new space.
542 : CODE_SPACE, // No pointers to new space, marked executable.
543 : MAP_SPACE, // Only and all map objects.
544 : LO_SPACE, // Promoted large objects.
545 :
546 : FIRST_SPACE = NEW_SPACE,
547 : LAST_SPACE = LO_SPACE,
548 : FIRST_PAGED_SPACE = OLD_SPACE,
549 : LAST_PAGED_SPACE = MAP_SPACE
550 : };
551 : const int kSpaceTagSize = 3;
552 : const int kSpaceTagMask = (1 << kSpaceTagSize) - 1;
553 :
554 : enum AllocationAlignment { kWordAligned, kDoubleAligned, kDoubleUnaligned };
555 :
556 : enum class AccessMode { ATOMIC, NON_ATOMIC };
557 :
558 : // Possible outcomes for decisions.
559 : enum class Decision : uint8_t { kUnknown, kTrue, kFalse };
560 :
561 : inline size_t hash_value(Decision decision) {
562 : return static_cast<uint8_t>(decision);
563 : }
564 :
565 : inline std::ostream& operator<<(std::ostream& os, Decision decision) {
566 : switch (decision) {
567 : case Decision::kUnknown:
568 : return os << "Unknown";
569 : case Decision::kTrue:
570 : return os << "True";
571 : case Decision::kFalse:
572 : return os << "False";
573 : }
574 : UNREACHABLE();
575 : }
576 :
577 : // Supported write barrier modes.
578 : enum WriteBarrierKind : uint8_t {
579 : kNoWriteBarrier,
580 : kMapWriteBarrier,
581 : kPointerWriteBarrier,
582 : kFullWriteBarrier
583 : };
584 :
585 0 : inline size_t hash_value(WriteBarrierKind kind) {
586 0 : return static_cast<uint8_t>(kind);
587 : }
588 :
589 415698 : inline std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
590 415698 : switch (kind) {
591 : case kNoWriteBarrier:
592 263100 : return os << "NoWriteBarrier";
593 : case kMapWriteBarrier:
594 0 : return os << "MapWriteBarrier";
595 : case kPointerWriteBarrier:
596 0 : return os << "PointerWriteBarrier";
597 : case kFullWriteBarrier:
598 152598 : return os << "FullWriteBarrier";
599 : }
600 0 : UNREACHABLE();
601 : }
602 :
603 : // A flag that indicates whether objects should be pretenured when
604 : // allocated (allocated directly into the old generation) or not
605 : // (allocated in the young generation if the object size and type
606 : // allows).
607 : enum PretenureFlag { NOT_TENURED, TENURED };
608 :
609 93 : inline std::ostream& operator<<(std::ostream& os, const PretenureFlag& flag) {
610 93 : switch (flag) {
611 : case NOT_TENURED:
612 93 : return os << "NotTenured";
613 : case TENURED:
614 0 : return os << "Tenured";
615 : }
616 0 : UNREACHABLE();
617 : }
618 :
619 : enum MinimumCapacity {
620 : USE_DEFAULT_MINIMUM_CAPACITY,
621 : USE_CUSTOM_MINIMUM_CAPACITY
622 : };
623 :
624 : enum GarbageCollector { SCAVENGER, MARK_COMPACTOR, MINOR_MARK_COMPACTOR };
625 :
626 : enum Executability { NOT_EXECUTABLE, EXECUTABLE };
627 :
628 : enum VisitMode {
629 : VISIT_ALL,
630 : VISIT_ALL_IN_MINOR_MC_MARK,
631 : VISIT_ALL_IN_MINOR_MC_UPDATE,
632 : VISIT_ALL_IN_SCAVENGE,
633 : VISIT_ALL_IN_SWEEP_NEWSPACE,
634 : VISIT_ONLY_STRONG,
635 : VISIT_ONLY_STRONG_FOR_SERIALIZATION,
636 : VISIT_ONLY_STRONG_ROOT_LIST,
637 : };
638 :
639 : // Flag indicating whether code is built into the VM (one of the natives files).
640 : enum NativesFlag {
641 : NOT_NATIVES_CODE,
642 : EXTENSION_CODE,
643 : NATIVES_CODE,
644 : INSPECTOR_CODE
645 : };
646 :
647 : // JavaScript defines two kinds of 'nil'.
648 : enum NilValue { kNullValue, kUndefinedValue };
649 :
650 : // ParseRestriction is used to restrict the set of valid statements in a
651 : // unit of compilation. Restriction violations cause a syntax error.
652 : enum ParseRestriction {
653 : NO_PARSE_RESTRICTION, // All expressions are allowed.
654 : ONLY_SINGLE_FUNCTION_LITERAL // Only a single FunctionLiteral expression.
655 : };
656 :
657 : // A CodeDesc describes a buffer holding instructions and relocation
658 : // information. The instructions start at the beginning of the buffer
659 : // and grow forward, the relocation information starts at the end of
660 : // the buffer and grows backward. A constant pool may exist at the
661 : // end of the instructions.
662 : //
663 : // |<--------------- buffer_size ----------------------------------->|
664 : // |<------------- instr_size ---------->| |<-- reloc_size -->|
665 : // | |<- const_pool_size ->| |
666 : // +=====================================+========+==================+
667 : // | instructions | data | free | reloc info |
668 : // +=====================================+========+==================+
669 : // ^
670 : // |
671 : // buffer
672 :
673 : struct CodeDesc {
674 : byte* buffer;
675 : int buffer_size;
676 : int instr_size;
677 : int reloc_size;
678 : int constant_pool_size;
679 : byte* unwinding_info;
680 : int unwinding_info_size;
681 : Assembler* origin;
682 : };
683 :
684 :
685 : // Callback function used for checking constraints when copying/relocating
686 : // objects. Returns true if an object can be copied/relocated from its
687 : // old_addr to a new_addr.
688 : typedef bool (*ConstraintCallback)(Address new_addr, Address old_addr);
689 :
690 :
691 : // Callback function on inline caches, used for iterating over inline caches
692 : // in compiled code.
693 : typedef void (*InlineCacheCallback)(Code* code, Address ic);
694 :
695 :
696 : // State for inline cache call sites. Aliased as IC::State.
697 : enum InlineCacheState {
698 : // Has never been executed.
699 : UNINITIALIZED,
700 : // Has been executed but monomorhic state has been delayed.
701 : PREMONOMORPHIC,
702 : // Has been executed and only one receiver type has been seen.
703 : MONOMORPHIC,
704 : // Check failed due to prototype (or map deprecation).
705 : RECOMPUTE_HANDLER,
706 : // Multiple receiver types have been seen.
707 : POLYMORPHIC,
708 : // Many receiver types have been seen.
709 : MEGAMORPHIC,
710 : // A generic handler is installed and no extra typefeedback is recorded.
711 : GENERIC,
712 : };
713 :
714 : enum WhereToStart { kStartAtReceiver, kStartAtPrototype };
715 :
716 : enum ResultSentinel { kNotFound = -1, kUnsupported = -2 };
717 :
718 : // The Store Buffer (GC).
719 : typedef enum {
720 : kStoreBufferFullEvent,
721 : kStoreBufferStartScanningPagesEvent,
722 : kStoreBufferScanningPageEvent
723 : } StoreBufferEvent;
724 :
725 :
726 : typedef void (*StoreBufferCallback)(Heap* heap,
727 : MemoryChunk* page,
728 : StoreBufferEvent event);
729 :
730 : // Union used for customized checking of the IEEE double types
731 : // inlined within v8 runtime, rather than going to the underlying
732 : // platform headers and libraries
733 : union IeeeDoubleLittleEndianArchType {
734 : double d;
735 : struct {
736 : unsigned int man_low :32;
737 : unsigned int man_high :20;
738 : unsigned int exp :11;
739 : unsigned int sign :1;
740 : } bits;
741 : };
742 :
743 :
744 : union IeeeDoubleBigEndianArchType {
745 : double d;
746 : struct {
747 : unsigned int sign :1;
748 : unsigned int exp :11;
749 : unsigned int man_high :20;
750 : unsigned int man_low :32;
751 : } bits;
752 : };
753 :
754 : #if V8_TARGET_LITTLE_ENDIAN
755 : typedef IeeeDoubleLittleEndianArchType IeeeDoubleArchType;
756 : const int kIeeeDoubleMantissaWordOffset = 0;
757 : const int kIeeeDoubleExponentWordOffset = 4;
758 : #else
759 : typedef IeeeDoubleBigEndianArchType IeeeDoubleArchType;
760 : const int kIeeeDoubleMantissaWordOffset = 4;
761 : const int kIeeeDoubleExponentWordOffset = 0;
762 : #endif
763 :
764 : // AccessorCallback
765 : struct AccessorDescriptor {
766 : Object* (*getter)(Isolate* isolate, Object* object, void* data);
767 : Object* (*setter)(
768 : Isolate* isolate, JSObject* object, Object* value, void* data);
769 : void* data;
770 : };
771 :
772 :
773 : // -----------------------------------------------------------------------------
774 : // Macros
775 :
776 : // Testers for test.
777 :
778 : #define HAS_SMI_TAG(value) \
779 : ((reinterpret_cast<intptr_t>(value) & ::i::kSmiTagMask) == ::i::kSmiTag)
780 :
781 : #define HAS_HEAP_OBJECT_TAG(value) \
782 : (((reinterpret_cast<intptr_t>(value) & ::i::kHeapObjectTagMask) == \
783 : ::i::kHeapObjectTag))
784 :
785 : // OBJECT_POINTER_ALIGN returns the value aligned as a HeapObject pointer
786 : #define OBJECT_POINTER_ALIGN(value) \
787 : (((value) + kObjectAlignmentMask) & ~kObjectAlignmentMask)
788 :
789 : // POINTER_SIZE_ALIGN returns the value aligned as a pointer.
790 : #define POINTER_SIZE_ALIGN(value) \
791 : (((value) + kPointerAlignmentMask) & ~kPointerAlignmentMask)
792 :
793 : // CODE_POINTER_ALIGN returns the value aligned as a generated code segment.
794 : #define CODE_POINTER_ALIGN(value) \
795 : (((value) + kCodeAlignmentMask) & ~kCodeAlignmentMask)
796 :
797 : // DOUBLE_POINTER_ALIGN returns the value algined for double pointers.
798 : #define DOUBLE_POINTER_ALIGN(value) \
799 : (((value) + kDoubleAlignmentMask) & ~kDoubleAlignmentMask)
800 :
801 :
802 : // CPU feature flags.
803 : enum CpuFeature {
804 : // x86
805 : SSE4_1,
806 : SSSE3,
807 : SSE3,
808 : SAHF,
809 : AVX,
810 : FMA3,
811 : BMI1,
812 : BMI2,
813 : LZCNT,
814 : POPCNT,
815 : ATOM,
816 : // ARM
817 : // - Standard configurations. The baseline is ARMv6+VFPv2.
818 : ARMv7, // ARMv7-A + VFPv3-D32 + NEON
819 : ARMv7_SUDIV, // ARMv7-A + VFPv4-D32 + NEON + SUDIV
820 : ARMv8, // ARMv8-A (+ all of the above)
821 : // MIPS, MIPS64
822 : FPU,
823 : FP64FPU,
824 : MIPSr1,
825 : MIPSr2,
826 : MIPSr6,
827 : MIPS_SIMD, // MSA instructions
828 : // ARM64
829 : ALWAYS_ALIGN_CSP,
830 : // PPC
831 : FPR_GPR_MOV,
832 : LWSYNC,
833 : ISELECT,
834 : VSX,
835 : MODULO,
836 : // S390
837 : DISTINCT_OPS,
838 : GENERAL_INSTR_EXT,
839 : FLOATING_POINT_EXT,
840 : VECTOR_FACILITY,
841 : MISC_INSTR_EXT2,
842 :
843 : NUMBER_OF_CPU_FEATURES,
844 :
845 : // ARM feature aliases (based on the standard configurations above).
846 : VFPv3 = ARMv7,
847 : NEON = ARMv7,
848 : VFP32DREGS = ARMv7,
849 : SUDIV = ARMv7_SUDIV
850 : };
851 :
852 : // Defines hints about receiver values based on structural knowledge.
853 : enum class ConvertReceiverMode : unsigned {
854 : kNullOrUndefined, // Guaranteed to be null or undefined.
855 : kNotNullOrUndefined, // Guaranteed to never be null or undefined.
856 : kAny // No specific knowledge about receiver.
857 : };
858 :
859 0 : inline size_t hash_value(ConvertReceiverMode mode) {
860 0 : return bit_cast<unsigned>(mode);
861 : }
862 :
863 0 : inline std::ostream& operator<<(std::ostream& os, ConvertReceiverMode mode) {
864 0 : switch (mode) {
865 : case ConvertReceiverMode::kNullOrUndefined:
866 0 : return os << "NULL_OR_UNDEFINED";
867 : case ConvertReceiverMode::kNotNullOrUndefined:
868 0 : return os << "NOT_NULL_OR_UNDEFINED";
869 : case ConvertReceiverMode::kAny:
870 0 : return os << "ANY";
871 : }
872 0 : UNREACHABLE();
873 : }
874 :
875 : // Valid hints for the abstract operation OrdinaryToPrimitive,
876 : // implemented according to ES6, section 7.1.1.
877 : enum class OrdinaryToPrimitiveHint { kNumber, kString };
878 :
879 : // Valid hints for the abstract operation ToPrimitive,
880 : // implemented according to ES6, section 7.1.1.
881 : enum class ToPrimitiveHint { kDefault, kNumber, kString };
882 :
883 : // Defines specifics about arguments object or rest parameter creation.
884 : enum class CreateArgumentsType : uint8_t {
885 : kMappedArguments,
886 : kUnmappedArguments,
887 : kRestParameter
888 : };
889 :
890 6237 : inline size_t hash_value(CreateArgumentsType type) {
891 6237 : return bit_cast<uint8_t>(type);
892 : }
893 :
894 0 : inline std::ostream& operator<<(std::ostream& os, CreateArgumentsType type) {
895 0 : switch (type) {
896 : case CreateArgumentsType::kMappedArguments:
897 0 : return os << "MAPPED_ARGUMENTS";
898 : case CreateArgumentsType::kUnmappedArguments:
899 0 : return os << "UNMAPPED_ARGUMENTS";
900 : case CreateArgumentsType::kRestParameter:
901 0 : return os << "REST_PARAMETER";
902 : }
903 0 : UNREACHABLE();
904 : }
905 :
906 : // Used to specify if a macro instruction must perform a smi check on tagged
907 : // values.
908 : enum SmiCheckType {
909 : DONT_DO_SMI_CHECK,
910 : DO_SMI_CHECK
911 : };
912 :
913 : enum ScopeType : uint8_t {
914 : EVAL_SCOPE, // The top-level scope for an eval source.
915 : FUNCTION_SCOPE, // The top-level scope for a function.
916 : MODULE_SCOPE, // The scope introduced by a module literal
917 : SCRIPT_SCOPE, // The top-level scope for a script or a top-level eval.
918 : CATCH_SCOPE, // The scope introduced by catch.
919 : BLOCK_SCOPE, // The scope introduced by a new block.
920 : WITH_SCOPE // The scope introduced by with.
921 : };
922 :
923 : // AllocationSiteMode controls whether allocations are tracked by an allocation
924 : // site.
925 : enum AllocationSiteMode {
926 : DONT_TRACK_ALLOCATION_SITE,
927 : TRACK_ALLOCATION_SITE,
928 : LAST_ALLOCATION_SITE_MODE = TRACK_ALLOCATION_SITE
929 : };
930 :
931 : // The mips architecture prior to revision 5 has inverted encoding for sNaN.
932 : #if (V8_TARGET_ARCH_MIPS && !defined(_MIPS_ARCH_MIPS32R6) && \
933 : (!defined(USE_SIMULATOR) || !defined(_MIPS_TARGET_SIMULATOR))) || \
934 : (V8_TARGET_ARCH_MIPS64 && !defined(_MIPS_ARCH_MIPS64R6) && \
935 : (!defined(USE_SIMULATOR) || !defined(_MIPS_TARGET_SIMULATOR)))
936 : const uint32_t kHoleNanUpper32 = 0xFFFF7FFF;
937 : const uint32_t kHoleNanLower32 = 0xFFFF7FFF;
938 : #else
939 : const uint32_t kHoleNanUpper32 = 0xFFF7FFFF;
940 : const uint32_t kHoleNanLower32 = 0xFFF7FFFF;
941 : #endif
942 :
943 : const uint64_t kHoleNanInt64 =
944 : (static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
945 :
946 :
947 : // ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER
948 : const double kMaxSafeInteger = 9007199254740991.0; // 2^53-1
949 :
950 :
951 : // The order of this enum has to be kept in sync with the predicates below.
952 : enum VariableMode : uint8_t {
953 : // User declared variables:
954 : LET, // declared via 'let' declarations (first lexical)
955 :
956 : CONST, // declared via 'const' declarations (last lexical)
957 :
958 : VAR, // declared via 'var', and 'function' declarations
959 :
960 : // Variables introduced by the compiler:
961 : TEMPORARY, // temporary variables (not user-visible), stack-allocated
962 : // unless the scope as a whole has forced context allocation
963 :
964 : DYNAMIC, // always require dynamic lookup (we don't know
965 : // the declaration)
966 :
967 : DYNAMIC_GLOBAL, // requires dynamic lookup, but we know that the
968 : // variable is global unless it has been shadowed
969 : // by an eval-introduced variable
970 :
971 : DYNAMIC_LOCAL // requires dynamic lookup, but we know that the
972 : // variable is local and where it is unless it
973 : // has been shadowed by an eval-introduced
974 : // variable
975 : };
976 :
977 : // Printing support
978 : #ifdef DEBUG
979 : inline const char* VariableMode2String(VariableMode mode) {
980 : switch (mode) {
981 : case VAR:
982 : return "VAR";
983 : case LET:
984 : return "LET";
985 : case CONST:
986 : return "CONST";
987 : case DYNAMIC:
988 : return "DYNAMIC";
989 : case DYNAMIC_GLOBAL:
990 : return "DYNAMIC_GLOBAL";
991 : case DYNAMIC_LOCAL:
992 : return "DYNAMIC_LOCAL";
993 : case TEMPORARY:
994 : return "TEMPORARY";
995 : }
996 : UNREACHABLE();
997 : }
998 : #endif
999 :
1000 : enum VariableKind : uint8_t {
1001 : NORMAL_VARIABLE,
1002 : FUNCTION_VARIABLE,
1003 : THIS_VARIABLE,
1004 : SLOPPY_FUNCTION_NAME_VARIABLE
1005 : };
1006 :
1007 : inline bool IsDynamicVariableMode(VariableMode mode) {
1008 54444534 : return mode >= DYNAMIC && mode <= DYNAMIC_LOCAL;
1009 : }
1010 :
1011 :
1012 : inline bool IsDeclaredVariableMode(VariableMode mode) {
1013 : STATIC_ASSERT(LET == 0); // Implies that mode >= LET.
1014 : return mode <= VAR;
1015 : }
1016 :
1017 :
1018 117890 : inline bool IsLexicalVariableMode(VariableMode mode) {
1019 : STATIC_ASSERT(LET == 0); // Implies that mode >= LET.
1020 122070 : return mode <= CONST;
1021 : }
1022 :
1023 : enum VariableLocation : uint8_t {
1024 : // Before and during variable allocation, a variable whose location is
1025 : // not yet determined. After allocation, a variable looked up as a
1026 : // property on the global object (and possibly absent). name() is the
1027 : // variable name, index() is invalid.
1028 : UNALLOCATED,
1029 :
1030 : // A slot in the parameter section on the stack. index() is the
1031 : // parameter index, counting left-to-right. The receiver is index -1;
1032 : // the first parameter is index 0.
1033 : PARAMETER,
1034 :
1035 : // A slot in the local section on the stack. index() is the variable
1036 : // index in the stack frame, starting at 0.
1037 : LOCAL,
1038 :
1039 : // An indexed slot in a heap context. index() is the variable index in
1040 : // the context object on the heap, starting at 0. scope() is the
1041 : // corresponding scope.
1042 : CONTEXT,
1043 :
1044 : // A named slot in a heap context. name() is the variable name in the
1045 : // context object on the heap, with lookup starting at the current
1046 : // context. index() is invalid.
1047 : LOOKUP,
1048 :
1049 : // A named slot in a module's export table.
1050 : MODULE,
1051 :
1052 : kLastVariableLocation = MODULE
1053 : };
1054 :
1055 : // ES6 specifies declarative environment records with mutable and immutable
1056 : // bindings that can be in two states: initialized and uninitialized.
1057 : // When accessing a binding, it needs to be checked for initialization.
1058 : // However in the following cases the binding is initialized immediately
1059 : // after creation so the initialization check can always be skipped:
1060 : //
1061 : // 1. Var declared local variables.
1062 : // var foo;
1063 : // 2. A local variable introduced by a function declaration.
1064 : // function foo() {}
1065 : // 3. Parameters
1066 : // function x(foo) {}
1067 : // 4. Catch bound variables.
1068 : // try {} catch (foo) {}
1069 : // 6. Function name variables of named function expressions.
1070 : // var x = function foo() {}
1071 : // 7. Implicit binding of 'this'.
1072 : // 8. Implicit binding of 'arguments' in functions.
1073 : //
1074 : // The following enum specifies a flag that indicates if the binding needs a
1075 : // distinct initialization step (kNeedsInitialization) or if the binding is
1076 : // immediately initialized upon creation (kCreatedInitialized).
1077 : enum InitializationFlag : uint8_t { kNeedsInitialization, kCreatedInitialized };
1078 :
1079 : enum class HoleCheckMode { kRequired, kElided };
1080 :
1081 : enum MaybeAssignedFlag : uint8_t { kNotAssigned, kMaybeAssigned };
1082 :
1083 : // Serialized in PreparseData, so numeric values should not be changed.
1084 : enum ParseErrorType { kSyntaxError = 0, kReferenceError = 1 };
1085 :
1086 :
1087 : enum MinusZeroMode {
1088 : TREAT_MINUS_ZERO_AS_ZERO,
1089 : FAIL_ON_MINUS_ZERO
1090 : };
1091 :
1092 :
1093 : enum Signedness { kSigned, kUnsigned };
1094 :
1095 : enum FunctionKind : uint16_t {
1096 : kNormalFunction = 0,
1097 : kArrowFunction = 1 << 0,
1098 : kGeneratorFunction = 1 << 1,
1099 : kConciseMethod = 1 << 2,
1100 : kConciseGeneratorMethod = kGeneratorFunction | kConciseMethod,
1101 : kDefaultConstructor = 1 << 3,
1102 : kDerivedConstructor = 1 << 4,
1103 : kBaseConstructor = 1 << 5,
1104 : kGetterFunction = 1 << 6,
1105 : kSetterFunction = 1 << 7,
1106 : kAsyncFunction = 1 << 8,
1107 : kModule = 1 << 9,
1108 : kAccessorFunction = kGetterFunction | kSetterFunction,
1109 : kDefaultBaseConstructor = kDefaultConstructor | kBaseConstructor,
1110 : kDefaultDerivedConstructor = kDefaultConstructor | kDerivedConstructor,
1111 : kClassConstructor =
1112 : kBaseConstructor | kDerivedConstructor | kDefaultConstructor,
1113 : kAsyncArrowFunction = kArrowFunction | kAsyncFunction,
1114 : kAsyncConciseMethod = kAsyncFunction | kConciseMethod,
1115 :
1116 : // https://tc39.github.io/proposal-async-iteration/
1117 : kAsyncConciseGeneratorMethod = kAsyncFunction | kConciseGeneratorMethod,
1118 : kAsyncGeneratorFunction = kAsyncFunction | kGeneratorFunction
1119 : };
1120 :
1121 : inline bool IsValidFunctionKind(FunctionKind kind) {
1122 : return kind == FunctionKind::kNormalFunction ||
1123 : kind == FunctionKind::kArrowFunction ||
1124 : kind == FunctionKind::kGeneratorFunction ||
1125 : kind == FunctionKind::kModule ||
1126 : kind == FunctionKind::kConciseMethod ||
1127 : kind == FunctionKind::kConciseGeneratorMethod ||
1128 : kind == FunctionKind::kGetterFunction ||
1129 : kind == FunctionKind::kSetterFunction ||
1130 : kind == FunctionKind::kAccessorFunction ||
1131 : kind == FunctionKind::kDefaultBaseConstructor ||
1132 : kind == FunctionKind::kDefaultDerivedConstructor ||
1133 : kind == FunctionKind::kBaseConstructor ||
1134 : kind == FunctionKind::kDerivedConstructor ||
1135 : kind == FunctionKind::kAsyncFunction ||
1136 : kind == FunctionKind::kAsyncArrowFunction ||
1137 : kind == FunctionKind::kAsyncConciseMethod ||
1138 : kind == FunctionKind::kAsyncConciseGeneratorMethod ||
1139 : kind == FunctionKind::kAsyncGeneratorFunction;
1140 : }
1141 :
1142 :
1143 : inline bool IsArrowFunction(FunctionKind kind) {
1144 : DCHECK(IsValidFunctionKind(kind));
1145 52647251 : return (kind & FunctionKind::kArrowFunction) != 0;
1146 : }
1147 :
1148 :
1149 : inline bool IsGeneratorFunction(FunctionKind kind) {
1150 : DCHECK(IsValidFunctionKind(kind));
1151 39827071 : return (kind & FunctionKind::kGeneratorFunction) != 0;
1152 : }
1153 :
1154 : inline bool IsModule(FunctionKind kind) {
1155 : DCHECK(IsValidFunctionKind(kind));
1156 4171660 : return (kind & FunctionKind::kModule) != 0;
1157 : }
1158 :
1159 : inline bool IsAsyncFunction(FunctionKind kind) {
1160 : DCHECK(IsValidFunctionKind(kind));
1161 103696705 : return (kind & FunctionKind::kAsyncFunction) != 0;
1162 : }
1163 :
1164 : inline bool IsAsyncGeneratorFunction(FunctionKind kind) {
1165 : DCHECK(IsValidFunctionKind(kind));
1166 : const FunctionKind kMask = FunctionKind::kAsyncGeneratorFunction;
1167 7835149 : return (kind & kMask) == kMask;
1168 : }
1169 :
1170 11215 : inline bool IsResumableFunction(FunctionKind kind) {
1171 12678693 : return IsGeneratorFunction(kind) || IsAsyncFunction(kind) || IsModule(kind);
1172 : }
1173 :
1174 : inline bool IsConciseMethod(FunctionKind kind) {
1175 : DCHECK(IsValidFunctionKind(kind));
1176 40377018 : return (kind & FunctionKind::kConciseMethod) != 0;
1177 : }
1178 :
1179 : inline bool IsGetterFunction(FunctionKind kind) {
1180 : DCHECK(IsValidFunctionKind(kind));
1181 5532248 : return (kind & FunctionKind::kGetterFunction) != 0;
1182 : }
1183 :
1184 : inline bool IsSetterFunction(FunctionKind kind) {
1185 : DCHECK(IsValidFunctionKind(kind));
1186 5497606 : return (kind & FunctionKind::kSetterFunction) != 0;
1187 : }
1188 :
1189 : inline bool IsAccessorFunction(FunctionKind kind) {
1190 : DCHECK(IsValidFunctionKind(kind));
1191 34473287 : return (kind & FunctionKind::kAccessorFunction) != 0;
1192 : }
1193 :
1194 :
1195 : inline bool IsDefaultConstructor(FunctionKind kind) {
1196 : DCHECK(IsValidFunctionKind(kind));
1197 836041 : return (kind & FunctionKind::kDefaultConstructor) != 0;
1198 : }
1199 :
1200 :
1201 : inline bool IsBaseConstructor(FunctionKind kind) {
1202 : DCHECK(IsValidFunctionKind(kind));
1203 : return (kind & FunctionKind::kBaseConstructor) != 0;
1204 : }
1205 :
1206 : inline bool IsDerivedConstructor(FunctionKind kind) {
1207 : DCHECK(IsValidFunctionKind(kind));
1208 12373876 : return (kind & FunctionKind::kDerivedConstructor) != 0;
1209 : }
1210 :
1211 :
1212 8284 : inline bool IsClassConstructor(FunctionKind kind) {
1213 : DCHECK(IsValidFunctionKind(kind));
1214 26632058 : return (kind & FunctionKind::kClassConstructor) != 0;
1215 : }
1216 :
1217 10335659 : inline bool IsConstructable(FunctionKind kind) {
1218 10335659 : if (IsAccessorFunction(kind)) return false;
1219 10308779 : if (IsConciseMethod(kind)) return false;
1220 9512627 : if (IsArrowFunction(kind)) return false;
1221 9019654 : if (IsGeneratorFunction(kind)) return false;
1222 9010894 : if (IsAsyncFunction(kind)) return false;
1223 9000392 : return true;
1224 : }
1225 :
1226 : enum class InterpreterPushArgsMode : unsigned {
1227 : kJSFunction,
1228 : kWithFinalSpread,
1229 : kOther
1230 : };
1231 :
1232 : inline size_t hash_value(InterpreterPushArgsMode mode) {
1233 : return bit_cast<unsigned>(mode);
1234 : }
1235 :
1236 : inline std::ostream& operator<<(std::ostream& os,
1237 : InterpreterPushArgsMode mode) {
1238 : switch (mode) {
1239 : case InterpreterPushArgsMode::kJSFunction:
1240 : return os << "JSFunction";
1241 : case InterpreterPushArgsMode::kWithFinalSpread:
1242 : return os << "WithFinalSpread";
1243 : case InterpreterPushArgsMode::kOther:
1244 : return os << "Other";
1245 : }
1246 : UNREACHABLE();
1247 : }
1248 :
1249 : inline uint32_t ObjectHash(Address address) {
1250 : // All objects are at least pointer aligned, so we can remove the trailing
1251 : // zeros.
1252 : return static_cast<uint32_t>(bit_cast<uintptr_t>(address) >>
1253 : kPointerSizeLog2);
1254 : }
1255 :
1256 : // Type feedback is encoded in such a way that, we can combine the feedback
1257 : // at different points by performing an 'OR' operation. Type feedback moves
1258 : // to a more generic type when we combine feedback.
1259 : // kSignedSmall -> kSignedSmallInputs -> kNumber -> kNumberOrOddball -> kAny
1260 : // kString -> kAny
1261 : // kBigInt -> kAny
1262 : // TODO(mythria): Remove kNumber type when crankshaft can handle Oddballs
1263 : // similar to Numbers. We don't need kNumber feedback for Turbofan. Extra
1264 : // information about Number might reduce few instructions but causes more
1265 : // deopts. We collect Number only because crankshaft does not handle all
1266 : // cases of oddballs.
1267 : class BinaryOperationFeedback {
1268 : public:
1269 : enum {
1270 : kNone = 0x0,
1271 : kSignedSmall = 0x1,
1272 : kSignedSmallInputs = 0x3,
1273 : kNumber = 0x7,
1274 : kNumberOrOddball = 0xF,
1275 : kString = 0x10,
1276 : kBigInt = 0x20,
1277 : kAny = 0x7F
1278 : };
1279 : };
1280 :
1281 : // Type feedback is encoded in such a way that, we can combine the feedback
1282 : // at different points by performing an 'OR' operation. Type feedback moves
1283 : // to a more generic type when we combine feedback.
1284 : // kSignedSmall -> kNumber -> kAny
1285 : // kInternalizedString -> kString -> kAny
1286 : // kSymbol -> kAny
1287 : // kReceiver -> kAny
1288 : // TODO(epertoso): consider unifying this with BinaryOperationFeedback.
1289 : class CompareOperationFeedback {
1290 : public:
1291 : enum {
1292 : kNone = 0x00,
1293 : kSignedSmall = 0x01,
1294 : kNumber = 0x3,
1295 : kNumberOrOddball = 0x7,
1296 : kInternalizedString = 0x8,
1297 : kString = 0x18,
1298 : kSymbol = 0x20,
1299 : kReceiver = 0x40,
1300 : kAny = 0xff
1301 : };
1302 : };
1303 :
1304 : // Type feedback is encoded in such a way that, we can combine the feedback
1305 : // at different points by performing an 'OR' operation. Type feedback moves
1306 : // to a more generic type when we combine feedback.
1307 : // kNone -> kEnumCacheKeysAndIndices -> kEnumCacheKeys -> kAny
1308 : class ForInFeedback {
1309 : public:
1310 : enum {
1311 : kNone = 0x0,
1312 : kEnumCacheKeysAndIndices = 0x1,
1313 : kEnumCacheKeys = 0x3,
1314 : kAny = 0x7
1315 : };
1316 : };
1317 : STATIC_ASSERT((ForInFeedback::kNone |
1318 : ForInFeedback::kEnumCacheKeysAndIndices) ==
1319 : ForInFeedback::kEnumCacheKeysAndIndices);
1320 : STATIC_ASSERT((ForInFeedback::kEnumCacheKeysAndIndices |
1321 : ForInFeedback::kEnumCacheKeys) == ForInFeedback::kEnumCacheKeys);
1322 : STATIC_ASSERT((ForInFeedback::kEnumCacheKeys | ForInFeedback::kAny) ==
1323 : ForInFeedback::kAny);
1324 :
1325 : enum class UnicodeEncoding : uint8_t {
1326 : // Different unicode encodings in a |word32|:
1327 : UTF16, // hi 16bits -> trailing surrogate or 0, low 16bits -> lead surrogate
1328 : UTF32, // full UTF32 code unit / Unicode codepoint
1329 : };
1330 :
1331 78 : inline size_t hash_value(UnicodeEncoding encoding) {
1332 78 : return static_cast<uint8_t>(encoding);
1333 : }
1334 :
1335 0 : inline std::ostream& operator<<(std::ostream& os, UnicodeEncoding encoding) {
1336 0 : switch (encoding) {
1337 : case UnicodeEncoding::UTF16:
1338 0 : return os << "UTF16";
1339 : case UnicodeEncoding::UTF32:
1340 0 : return os << "UTF32";
1341 : }
1342 0 : UNREACHABLE();
1343 : }
1344 :
1345 : enum class IterationKind { kKeys, kValues, kEntries };
1346 :
1347 : inline std::ostream& operator<<(std::ostream& os, IterationKind kind) {
1348 : switch (kind) {
1349 : case IterationKind::kKeys:
1350 : return os << "IterationKind::kKeys";
1351 : case IterationKind::kValues:
1352 : return os << "IterationKind::kValues";
1353 : case IterationKind::kEntries:
1354 : return os << "IterationKind::kEntries";
1355 : }
1356 : UNREACHABLE();
1357 : }
1358 :
1359 : // Flags for the runtime function kDefineDataPropertyInLiteral. A property can
1360 : // be enumerable or not, and, in case of functions, the function name
1361 : // can be set or not.
1362 : enum class DataPropertyInLiteralFlag {
1363 : kNoFlags = 0,
1364 : kDontEnum = 1 << 0,
1365 : kSetFunctionName = 1 << 1
1366 : };
1367 : typedef base::Flags<DataPropertyInLiteralFlag> DataPropertyInLiteralFlags;
1368 : DEFINE_OPERATORS_FOR_FLAGS(DataPropertyInLiteralFlags)
1369 :
1370 : enum ExternalArrayType {
1371 : kExternalInt8Array = 1,
1372 : kExternalUint8Array,
1373 : kExternalInt16Array,
1374 : kExternalUint16Array,
1375 : kExternalInt32Array,
1376 : kExternalUint32Array,
1377 : kExternalFloat32Array,
1378 : kExternalFloat64Array,
1379 : kExternalUint8ClampedArray,
1380 : };
1381 :
1382 : struct AssemblerDebugInfo {
1383 : AssemblerDebugInfo(const char* name, const char* file, int line)
1384 : : name(name), file(file), line(line) {}
1385 : const char* name;
1386 : const char* file;
1387 : int line;
1388 : };
1389 :
1390 : inline std::ostream& operator<<(std::ostream& os,
1391 : const AssemblerDebugInfo& info) {
1392 : os << "(" << info.name << ":" << info.file << ":" << info.line << ")";
1393 : return os;
1394 : }
1395 :
1396 : enum class OptimizationMarker {
1397 : kNone,
1398 : kCompileOptimized,
1399 : kCompileOptimizedConcurrent,
1400 : kInOptimizationQueue
1401 : };
1402 :
1403 : inline std::ostream& operator<<(std::ostream& os,
1404 : const OptimizationMarker& marker) {
1405 : switch (marker) {
1406 : case OptimizationMarker::kNone:
1407 : return os << "OptimizationMarker::kNone";
1408 : case OptimizationMarker::kCompileOptimized:
1409 : return os << "OptimizationMarker::kCompileOptimized";
1410 : case OptimizationMarker::kCompileOptimizedConcurrent:
1411 : return os << "OptimizationMarker::kCompileOptimizedConcurrent";
1412 : case OptimizationMarker::kInOptimizationQueue:
1413 : return os << "OptimizationMarker::kInOptimizationQueue";
1414 : }
1415 : UNREACHABLE();
1416 : return os;
1417 : }
1418 :
1419 : enum class ConcurrencyMode { kNotConcurrent, kConcurrent };
1420 :
1421 : #define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \
1422 : C(Handler, handler) \
1423 : C(CEntryFP, c_entry_fp) \
1424 : C(CFunction, c_function) \
1425 : C(Context, context) \
1426 : C(PendingException, pending_exception) \
1427 : C(PendingHandlerContext, pending_handler_context) \
1428 : C(PendingHandlerCode, pending_handler_code) \
1429 : C(PendingHandlerOffset, pending_handler_offset) \
1430 : C(PendingHandlerFP, pending_handler_fp) \
1431 : C(PendingHandlerSP, pending_handler_sp) \
1432 : C(ExternalCaughtException, external_caught_exception) \
1433 : C(JSEntrySP, js_entry_sp)
1434 :
1435 : enum IsolateAddressId {
1436 : #define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
1437 : FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
1438 : #undef DECLARE_ENUM
1439 : kIsolateAddressCount
1440 : };
1441 :
1442 : } // namespace internal
1443 : } // namespace v8
1444 :
1445 : namespace i = v8::internal;
1446 :
1447 : #endif // V8_GLOBALS_H_
|