libv8-node 23.6.1.0-x86_64-linux → 24.1.0.0-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/libv8/node/version.rb +3 -3
- data/vendor/v8/include/cppgc/allocation.h +1 -2
- data/vendor/v8/include/cppgc/default-platform.h +3 -2
- data/vendor/v8/include/cppgc/heap-consistency.h +1 -1
- data/vendor/v8/include/cppgc/internal/api-constants.h +0 -17
- data/vendor/v8/include/cppgc/internal/base-page-handle.h +2 -4
- data/vendor/v8/include/cppgc/internal/caged-heap-local-data.h +0 -4
- data/vendor/v8/include/cppgc/internal/caged-heap.h +0 -4
- data/vendor/v8/include/cppgc/internal/conditional-stack-allocated.h +41 -0
- data/vendor/v8/include/cppgc/internal/logging.h +3 -3
- data/vendor/v8/include/cppgc/internal/member-storage.h +63 -20
- data/vendor/v8/include/cppgc/internal/persistent-node.h +8 -3
- data/vendor/v8/include/cppgc/internal/pointer-policies.h +48 -11
- data/vendor/v8/include/cppgc/macros.h +21 -0
- data/vendor/v8/include/cppgc/member.h +70 -36
- data/vendor/v8/include/cppgc/name-provider.h +3 -0
- data/vendor/v8/include/cppgc/platform.h +11 -0
- data/vendor/v8/include/cppgc/type-traits.h +1 -0
- data/vendor/v8/include/cppgc/visitor.h +25 -1
- data/vendor/v8/include/libplatform/libplatform-export.h +2 -2
- data/vendor/v8/include/libplatform/v8-tracing.h +0 -1
- data/vendor/v8/include/v8-array-buffer.h +111 -34
- data/vendor/v8/include/v8-callbacks.h +84 -26
- data/vendor/v8/include/v8-context.h +7 -6
- data/vendor/v8/include/v8-cppgc.h +2 -1
- data/vendor/v8/include/v8-data.h +5 -0
- data/vendor/v8/include/v8-debug.h +11 -0
- data/vendor/v8/include/v8-embedder-heap.h +1 -32
- data/vendor/v8/include/v8-exception.h +2 -0
- data/vendor/v8/include/v8-external-memory-accounter.h +60 -0
- data/vendor/v8/include/v8-fast-api-calls.h +17 -175
- data/vendor/v8/include/v8-function-callback.h +4 -33
- data/vendor/v8/include/v8-function.h +7 -0
- data/vendor/v8/include/v8-handle-base.h +18 -0
- data/vendor/v8/include/v8-initialization.h +9 -1
- data/vendor/v8/include/v8-inspector.h +8 -4
- data/vendor/v8/include/v8-internal.h +477 -399
- data/vendor/v8/include/v8-isolate.h +218 -151
- data/vendor/v8/include/v8-local-handle.h +56 -28
- data/vendor/v8/include/v8-maybe.h +2 -1
- data/vendor/v8/include/v8-memory-span.h +149 -24
- data/vendor/v8/include/v8-message.h +9 -1
- data/vendor/v8/include/v8-metrics.h +10 -0
- data/vendor/v8/include/v8-object.h +7 -2
- data/vendor/v8/include/v8-persistent-handle.h +17 -17
- data/vendor/v8/include/v8-platform.h +48 -13
- data/vendor/v8/include/v8-primitive.h +131 -6
- data/vendor/v8/include/v8-profiler.h +13 -1
- data/vendor/v8/include/v8-proxy.h +0 -1
- data/vendor/v8/include/v8-regexp.h +0 -1
- data/vendor/v8/include/v8-sandbox.h +3 -3
- data/vendor/v8/include/v8-script.h +21 -3
- data/vendor/v8/include/v8-source-location.h +6 -1
- data/vendor/v8/include/v8-template.h +8 -2
- data/vendor/v8/include/v8-trace-categories.h +23 -0
- data/vendor/v8/include/v8-traced-handle.h +16 -17
- data/vendor/v8/include/v8-typed-array.h +6 -10
- data/vendor/v8/include/v8-unwinder-state.h +2 -3
- data/vendor/v8/include/v8-value-serializer-version.h +3 -3
- data/vendor/v8/include/v8-value.h +18 -0
- data/vendor/v8/include/v8-version.h +4 -4
- data/vendor/v8/include/v8-wasm.h +24 -0
- data/vendor/v8/include/v8-weak-callback-info.h +20 -12
- data/vendor/v8/include/v8.h +3 -3
- data/vendor/v8/include/v8config.h +34 -40
- data/vendor/v8/x86_64-linux/libv8/obj/libv8_monolith.a +0 -0
- metadata +5 -3
- data/vendor/v8/include/cppgc/ephemeron-pair.h +0 -30
@@ -18,6 +18,22 @@
|
|
18
18
|
|
19
19
|
#include "v8config.h" // NOLINT(build/include_directory)
|
20
20
|
|
21
|
+
// TODO(pkasting): Use <compare>/spaceship unconditionally after dropping
|
22
|
+
// support for old libstdc++ versions.
|
23
|
+
#if __has_include(<version>)
|
24
|
+
#include <version>
|
25
|
+
#endif
|
26
|
+
#if defined(__cpp_lib_three_way_comparison) && \
|
27
|
+
__cpp_lib_three_way_comparison >= 201711L && \
|
28
|
+
defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L
|
29
|
+
#include <compare>
|
30
|
+
#include <concepts>
|
31
|
+
|
32
|
+
#define V8_HAVE_SPACESHIP_OPERATOR 1
|
33
|
+
#else
|
34
|
+
#define V8_HAVE_SPACESHIP_OPERATOR 0
|
35
|
+
#endif
|
36
|
+
|
21
37
|
namespace v8 {
|
22
38
|
|
23
39
|
class Array;
|
@@ -28,7 +44,10 @@ class Isolate;
|
|
28
44
|
namespace internal {
|
29
45
|
|
30
46
|
class Heap;
|
47
|
+
class LocalHeap;
|
31
48
|
class Isolate;
|
49
|
+
class IsolateGroup;
|
50
|
+
class LocalIsolate;
|
32
51
|
|
33
52
|
typedef uintptr_t Address;
|
34
53
|
static constexpr Address kNullAddress = 0;
|
@@ -144,15 +163,15 @@ struct SmiTagging<8> {
|
|
144
163
|
std::is_signed_v<T>>* = nullptr>
|
145
164
|
V8_INLINE static constexpr bool IsValidSmi(T value) {
|
146
165
|
// To be representable as a long smi, the value must be a 32-bit integer.
|
147
|
-
return (
|
166
|
+
return std::numeric_limits<int32_t>::min() <= value &&
|
167
|
+
value <= std::numeric_limits<int32_t>::max();
|
148
168
|
}
|
149
169
|
|
150
170
|
template <class T,
|
151
171
|
typename std::enable_if_t<std::is_integral_v<T> &&
|
152
172
|
std::is_unsigned_v<T>>* = nullptr>
|
153
173
|
V8_INLINE static constexpr bool IsValidSmi(T value) {
|
154
|
-
return
|
155
|
-
static_cast<uintptr_t>(static_cast<int32_t>(value)));
|
174
|
+
return value <= std::numeric_limits<int32_t>::max();
|
156
175
|
}
|
157
176
|
};
|
158
177
|
|
@@ -218,10 +237,6 @@ using SandboxedPointer_t = Address;
|
|
218
237
|
// virtual address space for userspace. As such, limit the sandbox to 128GB (a
|
219
238
|
// quarter of the total available address space).
|
220
239
|
constexpr size_t kSandboxSizeLog2 = 37; // 128 GB
|
221
|
-
#elif defined(V8_TARGET_ARCH_LOONG64)
|
222
|
-
// Some Linux distros on LoongArch64 configured with only 40 bits of virtual
|
223
|
-
// address space for userspace. Limit the sandbox to 256GB here.
|
224
|
-
constexpr size_t kSandboxSizeLog2 = 38; // 256 GB
|
225
240
|
#else
|
226
241
|
// Everywhere else use a 1TB sandbox.
|
227
242
|
constexpr size_t kSandboxSizeLog2 = 40; // 1 TB
|
@@ -242,9 +257,12 @@ constexpr size_t kSandboxAlignment = kPtrComprCageBaseAlignment;
|
|
242
257
|
constexpr uint64_t kSandboxedPointerShift = 64 - kSandboxSizeLog2;
|
243
258
|
|
244
259
|
// Size of the guard regions surrounding the sandbox. This assumes a worst-case
|
245
|
-
// scenario of a 32-bit unsigned index used to access an array of 64-bit
|
246
|
-
//
|
247
|
-
|
260
|
+
// scenario of a 32-bit unsigned index used to access an array of 64-bit values
|
261
|
+
// with an additional 4GB (compressed pointer) offset. In particular, accesses
|
262
|
+
// to TypedArrays are effectively computed as
|
263
|
+
// `entry_pointer = array->base + array->offset + index * array->element_size`.
|
264
|
+
// See also https://crbug.com/40070746 for more details.
|
265
|
+
constexpr size_t kSandboxGuardRegionSize = 32ULL * GB + 4ULL * GB;
|
248
266
|
|
249
267
|
static_assert((kSandboxGuardRegionSize % kSandboxAlignment) == 0,
|
250
268
|
"The size of the guard regions around the sandbox must be a "
|
@@ -295,7 +313,8 @@ constexpr size_t kExternalPointerTableReservationSize = 256 * MB;
|
|
295
313
|
|
296
314
|
// The external pointer table indices stored in HeapObjects as external
|
297
315
|
// pointers are shifted to the left by this amount to guarantee that they are
|
298
|
-
// smaller than the maximum table size
|
316
|
+
// smaller than the maximum table size even after the C++ compiler multiplies
|
317
|
+
// them by 8 to be used as indexes into a table of 64 bit pointers.
|
299
318
|
constexpr uint32_t kExternalPointerIndexShift = 7;
|
300
319
|
#else
|
301
320
|
constexpr size_t kExternalPointerTableReservationSize = 512 * MB;
|
@@ -318,6 +337,16 @@ constexpr size_t kMaxExternalPointers = 0;
|
|
318
337
|
|
319
338
|
#endif // V8_COMPRESS_POINTERS
|
320
339
|
|
340
|
+
constexpr uint64_t kExternalPointerMarkBit = 1ULL << 48;
|
341
|
+
constexpr uint64_t kExternalPointerTagShift = 49;
|
342
|
+
constexpr uint64_t kExternalPointerTagMask = 0x00fe000000000000ULL;
|
343
|
+
constexpr uint64_t kExternalPointerShiftedTagMask =
|
344
|
+
kExternalPointerTagMask >> kExternalPointerTagShift;
|
345
|
+
static_assert(kExternalPointerShiftedTagMask << kExternalPointerTagShift ==
|
346
|
+
kExternalPointerTagMask);
|
347
|
+
constexpr uint64_t kExternalPointerTagAndMarkbitMask = 0x00ff000000000000ULL;
|
348
|
+
constexpr uint64_t kExternalPointerPayloadMask = 0xff00ffffffffffffULL;
|
349
|
+
|
321
350
|
// A ExternalPointerHandle represents a (opaque) reference to an external
|
322
351
|
// pointer that can be stored inside the sandbox. A ExternalPointerHandle has
|
323
352
|
// meaning only in combination with an (active) Isolate as it references an
|
@@ -386,47 +415,76 @@ constexpr size_t kMaxCppHeapPointers = 0;
|
|
386
415
|
|
387
416
|
#endif // V8_COMPRESS_POINTERS
|
388
417
|
|
389
|
-
//
|
390
|
-
//
|
391
|
-
//
|
392
|
-
//
|
393
|
-
|
418
|
+
// Generic tag range struct to represent ranges of type tags.
|
419
|
+
//
|
420
|
+
// When referencing external objects via pointer tables, type tags are
|
421
|
+
// frequently necessary to guarantee type safety for the external objects. When
|
422
|
+
// support for subtyping is necessary, range-based type checks are used in
|
423
|
+
// which all subtypes of a given supertype use contiguous tags. This struct can
|
424
|
+
// then be used to represent such a type range.
|
425
|
+
//
|
426
|
+
// In addition, there is an option for performance tweaks: if the size of the
|
427
|
+
// type range corresponding to a supertype is a power of two and starts at a
|
428
|
+
// power of two (e.g. [0x100, 0x13f]), then the compiler can often optimize
|
429
|
+
// the type check to use even fewer instructions (essentially replace a AND +
|
430
|
+
// SUB with a single AND).
|
431
|
+
//
|
432
|
+
template <typename Tag>
|
433
|
+
struct TagRange {
|
434
|
+
static_assert(std::is_enum_v<Tag> &&
|
435
|
+
std::is_same_v<std::underlying_type_t<Tag>, uint16_t>,
|
436
|
+
"Tag parameter must be an enum with base type uint16_t");
|
437
|
+
|
438
|
+
// Construct the inclusive tag range [first, last].
|
439
|
+
constexpr TagRange(Tag first, Tag last) : first(first), last(last) {}
|
440
|
+
|
441
|
+
// Construct a tag range consisting of a single tag.
|
442
|
+
//
|
443
|
+
// A single tag is always implicitly convertible to a tag range. This greatly
|
444
|
+
// increases readability as most of the time, the exact tag of a field is
|
445
|
+
// known and so no tag range needs to explicitly be created for it.
|
446
|
+
constexpr TagRange(Tag tag) // NOLINT(runtime/explicit)
|
447
|
+
: first(tag), last(tag) {}
|
448
|
+
|
449
|
+
// Construct an empty tag range.
|
450
|
+
constexpr TagRange() : TagRange(static_cast<Tag>(0)) {}
|
451
|
+
|
452
|
+
// A tag range is considered empty if it only contains the null tag.
|
453
|
+
constexpr bool IsEmpty() const { return first == 0 && last == 0; }
|
454
|
+
|
455
|
+
constexpr size_t Size() const {
|
456
|
+
if (IsEmpty()) {
|
457
|
+
return 0;
|
458
|
+
} else {
|
459
|
+
return last - first + 1;
|
460
|
+
}
|
461
|
+
}
|
394
462
|
|
395
|
-
|
396
|
-
//
|
397
|
-
//
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
#endif
|
463
|
+
constexpr bool Contains(Tag tag) const {
|
464
|
+
// Need to perform the math with uint32_t. Otherwise, the uint16_ts would
|
465
|
+
// be promoted to (signed) int, allowing the compiler to (wrongly) assume
|
466
|
+
// that an underflow cannot happen as that would be undefined behavior.
|
467
|
+
return static_cast<uint32_t>(tag) - first <=
|
468
|
+
static_cast<uint32_t>(last) - first;
|
469
|
+
}
|
403
470
|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
// shifted indices allows omitting bounds checks.
|
408
|
-
constexpr size_t kExternalBufferTableReservationSize = 64 * MB;
|
471
|
+
constexpr bool Contains(TagRange tag_range) const {
|
472
|
+
return tag_range.first >= first && tag_range.last <= last;
|
473
|
+
}
|
409
474
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
#else
|
414
|
-
constexpr size_t kExternalBufferTableReservationSize = 128 * MB;
|
415
|
-
constexpr uint32_t kExternalBufferHandleShift = 9;
|
416
|
-
#endif // V8_TARGET_OS_ANDROID
|
475
|
+
constexpr bool operator==(const TagRange other) const {
|
476
|
+
return first == other.first && last == other.last;
|
477
|
+
}
|
417
478
|
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
kMaxExternalBufferPointers,
|
428
|
-
"kExternalBufferTableReservationSize and "
|
429
|
-
"kExternalBufferHandleShift don't match");
|
479
|
+
constexpr size_t hash_value() const {
|
480
|
+
static_assert(std::is_same_v<std::underlying_type_t<Tag>, uint16_t>);
|
481
|
+
return (static_cast<size_t>(first) << 16) | last;
|
482
|
+
}
|
483
|
+
|
484
|
+
// Internally we represent tag ranges as half-open ranges [first, last).
|
485
|
+
const Tag first;
|
486
|
+
const Tag last;
|
487
|
+
};
|
430
488
|
|
431
489
|
//
|
432
490
|
// External Pointers.
|
@@ -435,41 +493,12 @@ static_assert((1 << (32 - kExternalBufferHandleShift)) ==
|
|
435
493
|
// pointer table and are referenced from HeapObjects through an index (a
|
436
494
|
// "handle"). When stored in the table, the pointers are tagged with per-type
|
437
495
|
// tags to prevent type confusion attacks between different external objects.
|
438
|
-
// Besides type information bits, these tags also contain the GC marking bit
|
439
|
-
// which indicates whether the pointer table entry is currently alive. When a
|
440
|
-
// pointer is written into the table, the tag is ORed into the top bits. When
|
441
|
-
// that pointer is later loaded from the table, it is ANDed with the inverse of
|
442
|
-
// the expected tag. If the expected and actual type differ, this will leave
|
443
|
-
// some of the top bits of the pointer set, rendering the pointer inaccessible.
|
444
|
-
// The AND operation also removes the GC marking bit from the pointer.
|
445
496
|
//
|
446
|
-
//
|
447
|
-
//
|
448
|
-
// that all
|
449
|
-
//
|
450
|
-
//
|
451
|
-
// the marking bit is automatically set when a pointer is written into the
|
452
|
-
// external pointer table (in which case it is clearly alive) and is cleared
|
453
|
-
// when the pointer is loaded. The exception to this is the free entry tag,
|
454
|
-
// which doesn't have the mark bit set, as the entry is not alive. This
|
455
|
-
// construction allows performing the type check and removing GC marking bits
|
456
|
-
// from the pointer in one efficient operation (bitwise AND). The number of
|
457
|
-
// available bits is limited in the following way: on x64, bits [47, 64) are
|
458
|
-
// generally available for tagging (userspace has 47 address bits available).
|
459
|
-
// On Arm64, userspace typically has a 40 or 48 bit address space. However, due
|
460
|
-
// to top-byte ignore (TBI) and memory tagging (MTE), the top byte is unusable
|
461
|
-
// for type checks as type-check failures would go unnoticed or collide with
|
462
|
-
// MTE bits. Some bits of the top byte can, however, still be used for the GC
|
463
|
-
// marking bit. The bits available for the type tags are therefore limited to
|
464
|
-
// [48, 56), i.e. (8 choose 4) = 70 different types.
|
465
|
-
// The following options exist to increase the number of possible types:
|
466
|
-
// - Using multiple ExternalPointerTables since tags can safely be reused
|
467
|
-
// across different tables
|
468
|
-
// - Using "extended" type checks, where additional type information is stored
|
469
|
-
// either in an adjacent pointer table entry or at the pointed-to location
|
470
|
-
// - Using a different tagging scheme, for example based on XOR which would
|
471
|
-
// allow for 2**8 different tags but require a separate operation to remove
|
472
|
-
// the marking bit
|
497
|
+
// When loading an external pointer, a range of allowed tags can be specified.
|
498
|
+
// This way, type hierarchies can be supported. The main requirement for that
|
499
|
+
// is that all (transitive) child classes of a given parent class have type ids
|
500
|
+
// in the same range, and that there are no unrelated types in that range. For
|
501
|
+
// more details about how to assign type tags to types, see the TagRange class.
|
473
502
|
//
|
474
503
|
// The external pointer sandboxing mechanism ensures that every access to an
|
475
504
|
// external pointer field will result in a valid pointer of the expected type
|
@@ -498,167 +527,136 @@ static_assert((1 << (32 - kExternalBufferHandleShift)) ==
|
|
498
527
|
// for this purpose, instead of using the ExternalPointer accessors one needs to
|
499
528
|
// use ExternalPointerHandles directly and use them to access the pointers in an
|
500
529
|
// ExternalPointerTable.
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
//
|
509
|
-
//
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
//
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
V(kIcuDateIntervalFormatTag, TAG(60)) \
|
601
|
-
V(kIcuRelativeDateTimeFormatterTag, TAG(61)) \
|
602
|
-
V(kIcuLocalizedNumberFormatterTag, TAG(62)) \
|
603
|
-
V(kIcuPluralRulesTag, TAG(63)) \
|
604
|
-
V(kIcuCollatorTag, TAG(64)) \
|
605
|
-
V(kDisplayNamesInternalTag, TAG(65)) \
|
606
|
-
/* External resources whose lifetime is tied to */ \
|
607
|
-
/* their entry in the external pointer table but */ \
|
608
|
-
/* which are not referenced via a Managed */ \
|
609
|
-
V(kArrayBufferExtensionTag, TAG(66)) \
|
610
|
-
V(kLastManagedResourceTag, TAG(66)) \
|
611
|
-
|
612
|
-
// All external pointer tags.
|
613
|
-
#define ALL_EXTERNAL_POINTER_TAGS(V) \
|
614
|
-
SHARED_EXTERNAL_POINTER_TAGS(V) \
|
615
|
-
PER_ISOLATE_EXTERNAL_POINTER_TAGS(V)
|
616
|
-
|
617
|
-
#define EXTERNAL_POINTER_TAG_ENUM(Name, Tag) Name = Tag,
|
618
|
-
#define MAKE_TAG(HasMarkBit, TypeTag) \
|
619
|
-
((static_cast<uint64_t>(TypeTag) << kExternalPointerTagShift) | \
|
620
|
-
(HasMarkBit ? kExternalPointerMarkBit : 0))
|
621
|
-
enum ExternalPointerTag : uint64_t {
|
622
|
-
// Empty tag value. Mostly used as placeholder.
|
623
|
-
kExternalPointerNullTag = MAKE_TAG(1, 0b00000000),
|
624
|
-
// External pointer tag that will match any external pointer. Use with care!
|
625
|
-
kAnyExternalPointerTag = MAKE_TAG(1, 0b11111111),
|
626
|
-
// External pointer tag that will match any external pointer in a Foreign.
|
627
|
-
// Use with care! If desired, this could be made more fine-granular.
|
628
|
-
kAnyForeignTag = kAnyExternalPointerTag,
|
629
|
-
// The free entry tag has all type bits set so every type check with a
|
630
|
-
// different type fails. It also doesn't have the mark bit set as free
|
631
|
-
// entries are (by definition) not alive.
|
632
|
-
kExternalPointerFreeEntryTag = MAKE_TAG(0, 0b11111111),
|
633
|
-
// Evacuation entries are used during external pointer table compaction.
|
634
|
-
kExternalPointerEvacuationEntryTag = MAKE_TAG(1, 0b11111110),
|
635
|
-
// Tag for zapped/invalidated entries. Those are considered to no longer be
|
636
|
-
// in use and so have the marking bit cleared.
|
637
|
-
kExternalPointerZappedEntryTag = MAKE_TAG(0, 0b11111101),
|
638
|
-
|
639
|
-
ALL_EXTERNAL_POINTER_TAGS(EXTERNAL_POINTER_TAG_ENUM)
|
530
|
+
//
|
531
|
+
// The tag is currently in practice limited to 15 bits since it needs to fit
|
532
|
+
// together with a marking bit into the unused parts of a pointer.
|
533
|
+
enum ExternalPointerTag : uint16_t {
|
534
|
+
kFirstExternalPointerTag = 0,
|
535
|
+
kExternalPointerNullTag = 0,
|
536
|
+
|
537
|
+
// When adding new tags, please ensure that the code using these tags is
|
538
|
+
// "substitution-safe", i.e. still operate safely if external pointers of the
|
539
|
+
// same type are swapped by an attacker. See comment above for more details.
|
540
|
+
|
541
|
+
// Shared external pointers are owned by the shared Isolate and stored in the
|
542
|
+
// shared external pointer table associated with that Isolate, where they can
|
543
|
+
// be accessed from multiple threads at the same time. The objects referenced
|
544
|
+
// in this way must therefore always be thread-safe.
|
545
|
+
kFirstSharedExternalPointerTag,
|
546
|
+
kWaiterQueueNodeTag = kFirstSharedExternalPointerTag,
|
547
|
+
kExternalStringResourceTag,
|
548
|
+
kExternalStringResourceDataTag,
|
549
|
+
kLastSharedExternalPointerTag = kExternalStringResourceDataTag,
|
550
|
+
|
551
|
+
// External pointers using these tags are kept in a per-Isolate external
|
552
|
+
// pointer table and can only be accessed when this Isolate is active.
|
553
|
+
kNativeContextMicrotaskQueueTag,
|
554
|
+
kEmbedderDataSlotPayloadTag,
|
555
|
+
// This tag essentially stands for a `void*` pointer in the V8 API, and it is
|
556
|
+
// the Embedder's responsibility to ensure type safety (against substitution)
|
557
|
+
// and lifetime validity of these objects.
|
558
|
+
kExternalObjectValueTag,
|
559
|
+
kFirstMaybeReadOnlyExternalPointerTag,
|
560
|
+
kFunctionTemplateInfoCallbackTag = kFirstMaybeReadOnlyExternalPointerTag,
|
561
|
+
kAccessorInfoGetterTag,
|
562
|
+
kAccessorInfoSetterTag,
|
563
|
+
kLastMaybeReadOnlyExternalPointerTag = kAccessorInfoSetterTag,
|
564
|
+
kWasmInternalFunctionCallTargetTag,
|
565
|
+
kWasmTypeInfoNativeTypeTag,
|
566
|
+
kWasmExportedFunctionDataSignatureTag,
|
567
|
+
kWasmStackMemoryTag,
|
568
|
+
kWasmIndirectFunctionTargetTag,
|
569
|
+
|
570
|
+
// Foreigns
|
571
|
+
kFirstForeignExternalPointerTag,
|
572
|
+
kGenericForeignTag = kFirstForeignExternalPointerTag,
|
573
|
+
kApiNamedPropertyQueryCallbackTag,
|
574
|
+
kApiNamedPropertyGetterCallbackTag,
|
575
|
+
kApiNamedPropertySetterCallbackTag,
|
576
|
+
kApiNamedPropertyDescriptorCallbackTag,
|
577
|
+
kApiNamedPropertyDefinerCallbackTag,
|
578
|
+
kApiNamedPropertyDeleterCallbackTag,
|
579
|
+
kApiIndexedPropertyQueryCallbackTag,
|
580
|
+
kApiIndexedPropertyGetterCallbackTag,
|
581
|
+
kApiIndexedPropertySetterCallbackTag,
|
582
|
+
kApiIndexedPropertyDescriptorCallbackTag,
|
583
|
+
kApiIndexedPropertyDefinerCallbackTag,
|
584
|
+
kApiIndexedPropertyDeleterCallbackTag,
|
585
|
+
kApiIndexedPropertyEnumeratorCallbackTag,
|
586
|
+
kApiAccessCheckCallbackTag,
|
587
|
+
kApiAbortScriptExecutionCallbackTag,
|
588
|
+
kSyntheticModuleTag,
|
589
|
+
kMicrotaskCallbackTag,
|
590
|
+
kMicrotaskCallbackDataTag,
|
591
|
+
kCFunctionTag,
|
592
|
+
kCFunctionInfoTag,
|
593
|
+
kMessageListenerTag,
|
594
|
+
kWaiterQueueForeignTag,
|
595
|
+
|
596
|
+
// Managed
|
597
|
+
kFirstManagedResourceTag,
|
598
|
+
kFirstManagedExternalPointerTag = kFirstManagedResourceTag,
|
599
|
+
kGenericManagedTag = kFirstManagedExternalPointerTag,
|
600
|
+
kWasmWasmStreamingTag,
|
601
|
+
kWasmFuncDataTag,
|
602
|
+
kWasmManagedDataTag,
|
603
|
+
kWasmNativeModuleTag,
|
604
|
+
kIcuBreakIteratorTag,
|
605
|
+
kIcuUnicodeStringTag,
|
606
|
+
kIcuListFormatterTag,
|
607
|
+
kIcuLocaleTag,
|
608
|
+
kIcuSimpleDateFormatTag,
|
609
|
+
kIcuDateIntervalFormatTag,
|
610
|
+
kIcuRelativeDateTimeFormatterTag,
|
611
|
+
kIcuLocalizedNumberFormatterTag,
|
612
|
+
kIcuPluralRulesTag,
|
613
|
+
kIcuCollatorTag,
|
614
|
+
kDisplayNamesInternalTag,
|
615
|
+
kD8WorkerTag,
|
616
|
+
kD8ModuleEmbedderDataTag,
|
617
|
+
kLastForeignExternalPointerTag = kD8ModuleEmbedderDataTag,
|
618
|
+
kLastManagedExternalPointerTag = kLastForeignExternalPointerTag,
|
619
|
+
// External resources whose lifetime is tied to their entry in the external
|
620
|
+
// pointer table but which are not referenced via a Managed
|
621
|
+
kArrayBufferExtensionTag,
|
622
|
+
kLastManagedResourceTag = kArrayBufferExtensionTag,
|
623
|
+
|
624
|
+
kExternalPointerZappedEntryTag = 0x7d,
|
625
|
+
kExternalPointerEvacuationEntryTag = 0x7e,
|
626
|
+
kExternalPointerFreeEntryTag = 0x7f,
|
627
|
+
// The tags are limited to 7 bits, so the last tag is 0x7f.
|
628
|
+
kLastExternalPointerTag = 0x7f,
|
640
629
|
};
|
641
630
|
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
631
|
+
using ExternalPointerTagRange = TagRange<ExternalPointerTag>;
|
632
|
+
|
633
|
+
constexpr ExternalPointerTagRange kAnyExternalPointerTagRange(
|
634
|
+
kFirstExternalPointerTag, kLastExternalPointerTag);
|
635
|
+
constexpr ExternalPointerTagRange kAnySharedExternalPointerTagRange(
|
636
|
+
kFirstSharedExternalPointerTag, kLastSharedExternalPointerTag);
|
637
|
+
constexpr ExternalPointerTagRange kAnyForeignExternalPointerTagRange(
|
638
|
+
kFirstForeignExternalPointerTag, kLastForeignExternalPointerTag);
|
639
|
+
constexpr ExternalPointerTagRange kAnyManagedExternalPointerTagRange(
|
640
|
+
kFirstManagedExternalPointerTag, kLastManagedExternalPointerTag);
|
641
|
+
constexpr ExternalPointerTagRange kAnyMaybeReadOnlyExternalPointerTagRange(
|
642
|
+
kFirstMaybeReadOnlyExternalPointerTag,
|
643
|
+
kLastMaybeReadOnlyExternalPointerTag);
|
644
|
+
constexpr ExternalPointerTagRange kAnyManagedResourceExternalPointerTag(
|
645
|
+
kFirstManagedResourceTag, kLastManagedResourceTag);
|
647
646
|
|
648
647
|
// True if the external pointer must be accessed from the shared isolate's
|
649
648
|
// external pointer table.
|
650
649
|
V8_INLINE static constexpr bool IsSharedExternalPointerType(
|
651
|
-
|
652
|
-
return
|
650
|
+
ExternalPointerTagRange tag_range) {
|
651
|
+
return kAnySharedExternalPointerTagRange.Contains(tag_range);
|
653
652
|
}
|
654
653
|
|
655
654
|
// True if the external pointer may live in a read-only object, in which case
|
656
655
|
// the table entry will be in the shared read-only segment of the external
|
657
656
|
// pointer table.
|
658
657
|
V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
|
659
|
-
|
660
|
-
return
|
661
|
-
tag == kFunctionTemplateInfoCallbackTag;
|
658
|
+
ExternalPointerTagRange tag_range) {
|
659
|
+
return kAnyMaybeReadOnlyExternalPointerTagRange.Contains(tag_range);
|
662
660
|
}
|
663
661
|
|
664
662
|
// True if the external pointer references an external object whose lifetime is
|
@@ -666,26 +664,23 @@ V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
|
|
666
664
|
// In this case, the entry in the ExternalPointerTable always points to an
|
667
665
|
// object derived from ExternalPointerTable::ManagedResource.
|
668
666
|
V8_INLINE static constexpr bool IsManagedExternalPointerType(
|
669
|
-
|
670
|
-
return
|
667
|
+
ExternalPointerTagRange tag_range) {
|
668
|
+
return kAnyManagedResourceExternalPointerTag.Contains(tag_range);
|
671
669
|
}
|
672
670
|
|
673
|
-
//
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
#undef SHARED_EXTERNAL_POINTER_TAGS
|
686
|
-
#undef EXTERNAL_POINTER_TAGS
|
671
|
+
// When an external poiner field can contain the null external pointer handle,
|
672
|
+
// the type checking mechanism needs to also check for null.
|
673
|
+
// TODO(saelo): this is mostly a temporary workaround to introduce range-based
|
674
|
+
// type checks. In the future, we should either (a) change the type tagging
|
675
|
+
// scheme so that null always passes or (b) (more likely) introduce dedicated
|
676
|
+
// null entries for those tags that need them (similar to other well-known
|
677
|
+
// empty value constants such as the empty fixed array).
|
678
|
+
V8_INLINE static constexpr bool ExternalPointerCanBeEmpty(
|
679
|
+
ExternalPointerTagRange tag_range) {
|
680
|
+
return tag_range.Contains(kArrayBufferExtensionTag) ||
|
681
|
+
tag_range.Contains(kEmbedderDataSlotPayloadTag);
|
682
|
+
}
|
687
683
|
|
688
|
-
//
|
689
684
|
// Indirect Pointers.
|
690
685
|
//
|
691
686
|
// When the sandbox is enabled, indirect pointers are used to reference
|
@@ -729,7 +724,7 @@ using TrustedPointerHandle = IndirectPointerHandle;
|
|
729
724
|
// shifted indices allows omitting bounds checks.
|
730
725
|
constexpr size_t kTrustedPointerTableReservationSize = 64 * MB;
|
731
726
|
|
732
|
-
// The trusted pointer handles are
|
727
|
+
// The trusted pointer handles are stored shifted to the left by this amount
|
733
728
|
// to guarantee that they are smaller than the maximum table size.
|
734
729
|
constexpr uint32_t kTrustedPointerHandleShift = 9;
|
735
730
|
|
@@ -805,29 +800,6 @@ constexpr bool kAllCodeObjectsLiveInTrustedSpace =
|
|
805
800
|
kRuntimeGeneratedCodeObjectsLiveInTrustedSpace &&
|
806
801
|
kBuiltinCodeObjectsLiveInTrustedSpace;
|
807
802
|
|
808
|
-
//
|
809
|
-
// JavaScript Dispatch Table
|
810
|
-
//
|
811
|
-
// A JSDispatchHandle represents a 32-bit index into a JSDispatchTable.
|
812
|
-
using JSDispatchHandle = uint32_t;
|
813
|
-
|
814
|
-
constexpr JSDispatchHandle kNullJSDispatchHandle = 0;
|
815
|
-
|
816
|
-
// The size of the virtual memory reservation for the JSDispatchTable.
|
817
|
-
// As with the other tables, a maximum table size in combination with shifted
|
818
|
-
// indices allows omitting bounds checks.
|
819
|
-
constexpr size_t kJSDispatchTableReservationSize = 128 * MB;
|
820
|
-
constexpr uint32_t kJSDispatchHandleShift = 9;
|
821
|
-
|
822
|
-
// The maximum number of entries in a JSDispatchTable.
|
823
|
-
constexpr int kJSDispatchTableEntrySize = 16;
|
824
|
-
constexpr int kJSDispatchTableEntrySizeLog2 = 4;
|
825
|
-
constexpr size_t kMaxJSDispatchEntries =
|
826
|
-
kJSDispatchTableReservationSize / kJSDispatchTableEntrySize;
|
827
|
-
static_assert((1 << (32 - kJSDispatchHandleShift)) == kMaxJSDispatchEntries,
|
828
|
-
"kJSDispatchTableReservationSize and kJSDispatchEntryHandleShift "
|
829
|
-
"don't match");
|
830
|
-
|
831
803
|
// {obj} must be the raw tagged pointer representation of a HeapObject
|
832
804
|
// that's guaranteed to never be in ReadOnlySpace.
|
833
805
|
V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
|
@@ -885,6 +857,7 @@ class Internals {
|
|
885
857
|
static const int kNumberOfBooleanFlags = 6;
|
886
858
|
static const int kErrorMessageParamSize = 1;
|
887
859
|
static const int kTablesAlignmentPaddingSize = 1;
|
860
|
+
static const int kRegExpStaticResultOffsetsVectorSize = kApiSystemPointerSize;
|
888
861
|
static const int kBuiltinTier0EntryTableSize = 7 * kApiSystemPointerSize;
|
889
862
|
static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize;
|
890
863
|
static const int kLinearAllocationAreaSize = 3 * kApiSystemPointerSize;
|
@@ -895,7 +868,6 @@ class Internals {
|
|
895
868
|
// ExternalPointerTable and TrustedPointerTable layout guarantees.
|
896
869
|
static const int kExternalPointerTableBasePointerOffset = 0;
|
897
870
|
static const int kExternalPointerTableSize = 2 * kApiSystemPointerSize;
|
898
|
-
static const int kExternalBufferTableSize = 2 * kApiSystemPointerSize;
|
899
871
|
static const int kTrustedPointerTableSize = 2 * kApiSystemPointerSize;
|
900
872
|
static const int kTrustedPointerTableBasePointerOffset = 0;
|
901
873
|
|
@@ -907,9 +879,9 @@ class Internals {
|
|
907
879
|
kIsolateStackGuardOffset + kStackGuardSize;
|
908
880
|
static const int kErrorMessageParamOffset =
|
909
881
|
kVariousBooleanFlagsOffset + kNumberOfBooleanFlags;
|
910
|
-
static const int kBuiltinTier0EntryTableOffset =
|
911
|
-
|
912
|
-
|
882
|
+
static const int kBuiltinTier0EntryTableOffset =
|
883
|
+
kErrorMessageParamOffset + kErrorMessageParamSize +
|
884
|
+
kTablesAlignmentPaddingSize + kRegExpStaticResultOffsetsVectorSize;
|
913
885
|
static const int kBuiltinTier0TableOffset =
|
914
886
|
kBuiltinTier0EntryTableOffset + kBuiltinTier0EntryTableSize;
|
915
887
|
static const int kNewAllocationInfoOffset =
|
@@ -918,14 +890,15 @@ class Internals {
|
|
918
890
|
kNewAllocationInfoOffset + kLinearAllocationAreaSize;
|
919
891
|
|
920
892
|
static const int kFastCCallAlignmentPaddingSize =
|
921
|
-
kApiSystemPointerSize == 8 ?
|
922
|
-
|
893
|
+
kApiSystemPointerSize == 8 ? 5 * kApiSystemPointerSize
|
894
|
+
: 1 * kApiSystemPointerSize;
|
895
|
+
static const int kIsolateFastCCallCallerPcOffset =
|
923
896
|
kOldAllocationInfoOffset + kLinearAllocationAreaSize +
|
924
897
|
kFastCCallAlignmentPaddingSize;
|
925
|
-
static const int
|
926
|
-
kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize;
|
927
|
-
static const int kIsolateFastApiCallTargetOffset =
|
898
|
+
static const int kIsolateFastCCallCallerFpOffset =
|
928
899
|
kIsolateFastCCallCallerPcOffset + kApiSystemPointerSize;
|
900
|
+
static const int kIsolateFastApiCallTargetOffset =
|
901
|
+
kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize;
|
929
902
|
static const int kIsolateLongTaskStatsCounterOffset =
|
930
903
|
kIsolateFastApiCallTargetOffset + kApiSystemPointerSize;
|
931
904
|
static const int kIsolateThreadLocalTopOffset =
|
@@ -946,8 +919,14 @@ class Internals {
|
|
946
919
|
kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
|
947
920
|
static const int kIsolateTrustedPointerTableOffset =
|
948
921
|
kIsolateTrustedCageBaseOffset + kApiSystemPointerSize;
|
949
|
-
static const int
|
922
|
+
static const int kIsolateSharedTrustedPointerTableAddressOffset =
|
950
923
|
kIsolateTrustedPointerTableOffset + kTrustedPointerTableSize;
|
924
|
+
static const int kIsolateTrustedPointerPublishingScopeOffset =
|
925
|
+
kIsolateSharedTrustedPointerTableAddressOffset + kApiSystemPointerSize;
|
926
|
+
static const int kIsolateCodePointerTableBaseAddressOffset =
|
927
|
+
kIsolateTrustedPointerPublishingScopeOffset + kApiSystemPointerSize;
|
928
|
+
static const int kIsolateApiCallbackThunkArgumentOffset =
|
929
|
+
kIsolateCodePointerTableBaseAddressOffset + kApiSystemPointerSize;
|
951
930
|
#else
|
952
931
|
static const int kIsolateApiCallbackThunkArgumentOffset =
|
953
932
|
kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
|
@@ -956,8 +935,10 @@ class Internals {
|
|
956
935
|
static const int kIsolateApiCallbackThunkArgumentOffset =
|
957
936
|
kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
|
958
937
|
#endif // V8_COMPRESS_POINTERS
|
959
|
-
static const int
|
938
|
+
static const int kIsolateRegexpExecVectorArgumentOffset =
|
960
939
|
kIsolateApiCallbackThunkArgumentOffset + kApiSystemPointerSize;
|
940
|
+
static const int kContinuationPreservedEmbedderDataOffset =
|
941
|
+
kIsolateRegexpExecVectorArgumentOffset + kApiSystemPointerSize;
|
961
942
|
static const int kIsolateRootsOffset =
|
962
943
|
kContinuationPreservedEmbedderDataOffset + kApiSystemPointerSize;
|
963
944
|
|
@@ -969,12 +950,12 @@ class Internals {
|
|
969
950
|
|
970
951
|
// These constants are copied from static-roots.h and guarded by static asserts.
|
971
952
|
#define EXPORTED_STATIC_ROOTS_PTR_LIST(V) \
|
972
|
-
V(UndefinedValue,
|
973
|
-
V(NullValue,
|
974
|
-
V(TrueValue,
|
975
|
-
V(FalseValue,
|
976
|
-
V(EmptyString,
|
977
|
-
V(TheHoleValue,
|
953
|
+
V(UndefinedValue, 0x11) \
|
954
|
+
V(NullValue, 0x2d) \
|
955
|
+
V(TrueValue, 0x71) \
|
956
|
+
V(FalseValue, 0x55) \
|
957
|
+
V(EmptyString, 0x49) \
|
958
|
+
V(TheHoleValue, 0x761)
|
978
959
|
|
979
960
|
using Tagged_t = uint32_t;
|
980
961
|
struct StaticReadOnlyRoot {
|
@@ -984,7 +965,7 @@ class Internals {
|
|
984
965
|
|
985
966
|
// Use 0 for kStringMapLowerBound since string maps are the first maps.
|
986
967
|
static constexpr Tagged_t kStringMapLowerBound = 0;
|
987
|
-
static constexpr Tagged_t kStringMapUpperBound =
|
968
|
+
static constexpr Tagged_t kStringMapUpperBound = 0x425;
|
988
969
|
|
989
970
|
#define PLUSONE(...) +1
|
990
971
|
static constexpr size_t kNumberOfExportedStaticRoots =
|
@@ -1030,7 +1011,7 @@ class Internals {
|
|
1030
1011
|
|
1031
1012
|
// Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
|
1032
1013
|
// incremental GC once the external memory reaches this limit.
|
1033
|
-
static constexpr
|
1014
|
+
static constexpr size_t kExternalAllocationSoftLimit = 64 * 1024 * 1024;
|
1034
1015
|
|
1035
1016
|
#ifdef V8_MAP_PACKING
|
1036
1017
|
static const uintptr_t kMapWordMetadataMask = 0xffffULL << 48;
|
@@ -1272,15 +1253,15 @@ class Internals {
|
|
1272
1253
|
#endif
|
1273
1254
|
}
|
1274
1255
|
|
1275
|
-
template <
|
1256
|
+
template <ExternalPointerTagRange tag_range>
|
1276
1257
|
V8_INLINE static Address ReadExternalPointerField(v8::Isolate* isolate,
|
1277
1258
|
Address heap_object_ptr,
|
1278
1259
|
int offset) {
|
1279
1260
|
#ifdef V8_ENABLE_SANDBOX
|
1280
|
-
static_assert(
|
1281
|
-
// See src/sandbox/external-pointer-table
|
1261
|
+
static_assert(!tag_range.IsEmpty());
|
1262
|
+
// See src/sandbox/external-pointer-table.h. Logic duplicated here so
|
1282
1263
|
// it can be inlined and doesn't require an additional call.
|
1283
|
-
Address* table = IsSharedExternalPointerType(
|
1264
|
+
Address* table = IsSharedExternalPointerType(tag_range)
|
1284
1265
|
? GetSharedExternalPointerTableBase(isolate)
|
1285
1266
|
: GetExternalPointerTableBase(isolate);
|
1286
1267
|
internal::ExternalPointerHandle handle =
|
@@ -1289,7 +1270,14 @@ class Internals {
|
|
1289
1270
|
std::atomic<Address>* ptr =
|
1290
1271
|
reinterpret_cast<std::atomic<Address>*>(&table[index]);
|
1291
1272
|
Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
|
1292
|
-
|
1273
|
+
ExternalPointerTag actual_tag = static_cast<ExternalPointerTag>(
|
1274
|
+
(entry & kExternalPointerTagMask) >> kExternalPointerTagShift);
|
1275
|
+
if (V8_LIKELY(tag_range.Contains(actual_tag))) {
|
1276
|
+
return entry & kExternalPointerPayloadMask;
|
1277
|
+
} else {
|
1278
|
+
return 0;
|
1279
|
+
}
|
1280
|
+
return entry;
|
1293
1281
|
#else
|
1294
1282
|
return ReadRawField<Address>(heap_object_ptr, offset);
|
1295
1283
|
#endif // V8_ENABLE_SANDBOX
|
@@ -1343,7 +1331,7 @@ class BackingStoreBase {};
|
|
1343
1331
|
|
1344
1332
|
// The maximum value in enum GarbageCollectionReason, defined in heap.h.
|
1345
1333
|
// This is needed for histograms sampling garbage collection reasons.
|
1346
|
-
constexpr int kGarbageCollectionReasonMaxValue =
|
1334
|
+
constexpr int kGarbageCollectionReasonMaxValue = 29;
|
1347
1335
|
|
1348
1336
|
// Base class for the address block allocator compatible with standard
|
1349
1337
|
// containers, which registers its allocated range as strong roots.
|
@@ -1351,16 +1339,19 @@ class V8_EXPORT StrongRootAllocatorBase {
|
|
1351
1339
|
public:
|
1352
1340
|
Heap* heap() const { return heap_; }
|
1353
1341
|
|
1354
|
-
bool operator==(const StrongRootAllocatorBase&
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
return heap_
|
1342
|
+
friend bool operator==(const StrongRootAllocatorBase& a,
|
1343
|
+
const StrongRootAllocatorBase& b) {
|
1344
|
+
// TODO(pkasting): Replace this body with `= default` after dropping support
|
1345
|
+
// for old gcc versions.
|
1346
|
+
return a.heap_ == b.heap_;
|
1359
1347
|
}
|
1360
1348
|
|
1361
1349
|
protected:
|
1362
1350
|
explicit StrongRootAllocatorBase(Heap* heap) : heap_(heap) {}
|
1351
|
+
explicit StrongRootAllocatorBase(LocalHeap* heap);
|
1363
1352
|
explicit StrongRootAllocatorBase(Isolate* isolate);
|
1353
|
+
explicit StrongRootAllocatorBase(v8::Isolate* isolate);
|
1354
|
+
explicit StrongRootAllocatorBase(LocalIsolate* isolate);
|
1364
1355
|
|
1365
1356
|
// Allocate/deallocate a range of n elements of type internal::Address.
|
1366
1357
|
Address* allocate_impl(size_t n);
|
@@ -1380,9 +1371,8 @@ class StrongRootAllocator : private std::allocator<T> {
|
|
1380
1371
|
public:
|
1381
1372
|
using value_type = T;
|
1382
1373
|
|
1383
|
-
|
1384
|
-
explicit StrongRootAllocator(
|
1385
|
-
explicit StrongRootAllocator(v8::Isolate* isolate) {}
|
1374
|
+
template <typename HeapOrIsolateT>
|
1375
|
+
explicit StrongRootAllocator(HeapOrIsolateT*) {}
|
1386
1376
|
template <typename U>
|
1387
1377
|
StrongRootAllocator(const StrongRootAllocator<U>& other) noexcept {}
|
1388
1378
|
|
@@ -1390,22 +1380,61 @@ class StrongRootAllocator : private std::allocator<T> {
|
|
1390
1380
|
using std::allocator<T>::deallocate;
|
1391
1381
|
};
|
1392
1382
|
|
1383
|
+
// TODO(pkasting): Replace with `requires` clauses after dropping support for
|
1384
|
+
// old gcc versions.
|
1385
|
+
template <typename Iterator, typename = void>
|
1386
|
+
inline constexpr bool kHaveIteratorConcept = false;
|
1387
|
+
template <typename Iterator>
|
1388
|
+
inline constexpr bool kHaveIteratorConcept<
|
1389
|
+
Iterator, std::void_t<typename Iterator::iterator_concept>> = true;
|
1390
|
+
|
1391
|
+
template <typename Iterator, typename = void>
|
1392
|
+
inline constexpr bool kHaveIteratorCategory = false;
|
1393
|
+
template <typename Iterator>
|
1394
|
+
inline constexpr bool kHaveIteratorCategory<
|
1395
|
+
Iterator, std::void_t<typename Iterator::iterator_category>> = true;
|
1396
|
+
|
1397
|
+
// Helper struct that contains an `iterator_concept` type alias only when either
|
1398
|
+
// `Iterator` or `std::iterator_traits<Iterator>` do.
|
1399
|
+
// Default: no alias.
|
1400
|
+
template <typename Iterator, typename = void>
|
1401
|
+
struct MaybeDefineIteratorConcept {};
|
1402
|
+
// Use `Iterator::iterator_concept` if available.
|
1403
|
+
template <typename Iterator>
|
1404
|
+
struct MaybeDefineIteratorConcept<
|
1405
|
+
Iterator, std::enable_if_t<kHaveIteratorConcept<Iterator>>> {
|
1406
|
+
using iterator_concept = typename Iterator::iterator_concept;
|
1407
|
+
};
|
1408
|
+
// Otherwise fall back to `std::iterator_traits<Iterator>` if possible.
|
1409
|
+
template <typename Iterator>
|
1410
|
+
struct MaybeDefineIteratorConcept<
|
1411
|
+
Iterator, std::enable_if_t<kHaveIteratorCategory<Iterator> &&
|
1412
|
+
!kHaveIteratorConcept<Iterator>>> {
|
1413
|
+
// There seems to be no feature-test macro covering this, so use the
|
1414
|
+
// presence of `<ranges>` as a crude proxy, since it was added to the
|
1415
|
+
// standard as part of the Ranges papers.
|
1416
|
+
// TODO(pkasting): Add this unconditionally after dropping support for old
|
1417
|
+
// libstdc++ versions.
|
1418
|
+
#if __has_include(<ranges>)
|
1419
|
+
using iterator_concept =
|
1420
|
+
typename std::iterator_traits<Iterator>::iterator_concept;
|
1421
|
+
#endif
|
1422
|
+
};
|
1423
|
+
|
1393
1424
|
// A class of iterators that wrap some different iterator type.
|
1394
1425
|
// If specified, ElementType is the type of element accessed by the wrapper
|
1395
1426
|
// iterator; in this case, the actual reference and pointer types of Iterator
|
1396
1427
|
// must be convertible to ElementType& and ElementType*, respectively.
|
1397
1428
|
template <typename Iterator, typename ElementType = void>
|
1398
|
-
class WrappedIterator {
|
1429
|
+
class WrappedIterator : public MaybeDefineIteratorConcept<Iterator> {
|
1399
1430
|
public:
|
1400
1431
|
static_assert(
|
1401
|
-
|
1432
|
+
std::is_void_v<ElementType> ||
|
1402
1433
|
(std::is_convertible_v<typename std::iterator_traits<Iterator>::pointer,
|
1403
|
-
ElementType
|
1434
|
+
std::add_pointer_t<ElementType>> &&
|
1404
1435
|
std::is_convertible_v<typename std::iterator_traits<Iterator>::reference,
|
1405
|
-
ElementType
|
1436
|
+
std::add_lvalue_reference_t<ElementType>>));
|
1406
1437
|
|
1407
|
-
using iterator_category =
|
1408
|
-
typename std::iterator_traits<Iterator>::iterator_category;
|
1409
1438
|
using difference_type =
|
1410
1439
|
typename std::iterator_traits<Iterator>::difference_type;
|
1411
1440
|
using value_type =
|
@@ -1415,24 +1444,100 @@ class WrappedIterator {
|
|
1415
1444
|
using pointer =
|
1416
1445
|
std::conditional_t<std::is_void_v<ElementType>,
|
1417
1446
|
typename std::iterator_traits<Iterator>::pointer,
|
1418
|
-
ElementType
|
1447
|
+
std::add_pointer_t<ElementType>>;
|
1419
1448
|
using reference =
|
1420
1449
|
std::conditional_t<std::is_void_v<ElementType>,
|
1421
1450
|
typename std::iterator_traits<Iterator>::reference,
|
1422
|
-
ElementType
|
1451
|
+
std::add_lvalue_reference_t<ElementType>>;
|
1452
|
+
using iterator_category =
|
1453
|
+
typename std::iterator_traits<Iterator>::iterator_category;
|
1423
1454
|
|
1424
|
-
constexpr WrappedIterator() noexcept
|
1455
|
+
constexpr WrappedIterator() noexcept = default;
|
1425
1456
|
constexpr explicit WrappedIterator(Iterator it) noexcept : it_(it) {}
|
1426
1457
|
|
1458
|
+
// TODO(pkasting): Switch to `requires` and concepts after dropping support
|
1459
|
+
// for old gcc and libstdc++ versions.
|
1427
1460
|
template <typename OtherIterator, typename OtherElementType,
|
1428
|
-
std::enable_if_t<
|
1429
|
-
|
1461
|
+
typename = std::enable_if_t<
|
1462
|
+
std::is_convertible_v<OtherIterator, Iterator>>>
|
1430
1463
|
constexpr WrappedIterator(
|
1431
|
-
const WrappedIterator<OtherIterator, OtherElementType>&
|
1432
|
-
: it_(
|
1464
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other) noexcept
|
1465
|
+
: it_(other.base()) {}
|
1466
|
+
|
1467
|
+
[[nodiscard]] constexpr reference operator*() const noexcept { return *it_; }
|
1468
|
+
[[nodiscard]] constexpr pointer operator->() const noexcept {
|
1469
|
+
if constexpr (std::is_pointer_v<Iterator>) {
|
1470
|
+
return it_;
|
1471
|
+
} else {
|
1472
|
+
return it_.operator->();
|
1473
|
+
}
|
1474
|
+
}
|
1475
|
+
|
1476
|
+
template <typename OtherIterator, typename OtherElementType>
|
1477
|
+
[[nodiscard]] constexpr bool operator==(
|
1478
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1479
|
+
const noexcept {
|
1480
|
+
return it_ == other.base();
|
1481
|
+
}
|
1482
|
+
#if V8_HAVE_SPACESHIP_OPERATOR
|
1483
|
+
template <typename OtherIterator, typename OtherElementType>
|
1484
|
+
[[nodiscard]] constexpr auto operator<=>(
|
1485
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1486
|
+
const noexcept {
|
1487
|
+
if constexpr (std::three_way_comparable_with<Iterator, OtherIterator>) {
|
1488
|
+
return it_ <=> other.base();
|
1489
|
+
} else if constexpr (std::totally_ordered_with<Iterator, OtherIterator>) {
|
1490
|
+
if (it_ < other.base()) {
|
1491
|
+
return std::strong_ordering::less;
|
1492
|
+
}
|
1493
|
+
return (it_ > other.base()) ? std::strong_ordering::greater
|
1494
|
+
: std::strong_ordering::equal;
|
1495
|
+
} else {
|
1496
|
+
if (it_ < other.base()) {
|
1497
|
+
return std::partial_ordering::less;
|
1498
|
+
}
|
1499
|
+
if (other.base() < it_) {
|
1500
|
+
return std::partial_ordering::greater;
|
1501
|
+
}
|
1502
|
+
return (it_ == other.base()) ? std::partial_ordering::equivalent
|
1503
|
+
: std::partial_ordering::unordered;
|
1504
|
+
}
|
1505
|
+
}
|
1506
|
+
#else
|
1507
|
+
// Assume that if spaceship isn't present, operator rewriting might not be
|
1508
|
+
// either.
|
1509
|
+
template <typename OtherIterator, typename OtherElementType>
|
1510
|
+
[[nodiscard]] constexpr bool operator!=(
|
1511
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1512
|
+
const noexcept {
|
1513
|
+
return it_ != other.base();
|
1514
|
+
}
|
1433
1515
|
|
1434
|
-
|
1435
|
-
constexpr
|
1516
|
+
template <typename OtherIterator, typename OtherElementType>
|
1517
|
+
[[nodiscard]] constexpr bool operator<(
|
1518
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1519
|
+
const noexcept {
|
1520
|
+
return it_ < other.base();
|
1521
|
+
}
|
1522
|
+
template <typename OtherIterator, typename OtherElementType>
|
1523
|
+
[[nodiscard]] constexpr bool operator<=(
|
1524
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1525
|
+
const noexcept {
|
1526
|
+
return it_ <= other.base();
|
1527
|
+
}
|
1528
|
+
template <typename OtherIterator, typename OtherElementType>
|
1529
|
+
[[nodiscard]] constexpr bool operator>(
|
1530
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1531
|
+
const noexcept {
|
1532
|
+
return it_ > other.base();
|
1533
|
+
}
|
1534
|
+
template <typename OtherIterator, typename OtherElementType>
|
1535
|
+
[[nodiscard]] constexpr bool operator>=(
|
1536
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1537
|
+
const noexcept {
|
1538
|
+
return it_ >= other.base();
|
1539
|
+
}
|
1540
|
+
#endif
|
1436
1541
|
|
1437
1542
|
constexpr WrappedIterator& operator++() noexcept {
|
1438
1543
|
++it_;
|
@@ -1453,116 +1558,68 @@ class WrappedIterator {
|
|
1453
1558
|
--(*this);
|
1454
1559
|
return result;
|
1455
1560
|
}
|
1456
|
-
constexpr WrappedIterator operator+(
|
1561
|
+
[[nodiscard]] constexpr WrappedIterator operator+(
|
1562
|
+
difference_type n) const noexcept {
|
1457
1563
|
WrappedIterator result(*this);
|
1458
1564
|
result += n;
|
1459
1565
|
return result;
|
1460
1566
|
}
|
1567
|
+
[[nodiscard]] friend constexpr WrappedIterator operator+(
|
1568
|
+
difference_type n, const WrappedIterator& x) noexcept {
|
1569
|
+
return x + n;
|
1570
|
+
}
|
1461
1571
|
constexpr WrappedIterator& operator+=(difference_type n) noexcept {
|
1462
1572
|
it_ += n;
|
1463
1573
|
return *this;
|
1464
1574
|
}
|
1465
|
-
constexpr WrappedIterator operator-(
|
1466
|
-
|
1575
|
+
[[nodiscard]] constexpr WrappedIterator operator-(
|
1576
|
+
difference_type n) const noexcept {
|
1577
|
+
return *this + -n;
|
1467
1578
|
}
|
1468
1579
|
constexpr WrappedIterator& operator-=(difference_type n) noexcept {
|
1469
|
-
*this += -n;
|
1470
|
-
return *this;
|
1580
|
+
return *this += -n;
|
1471
1581
|
}
|
1472
|
-
|
1582
|
+
template <typename OtherIterator, typename OtherElementType>
|
1583
|
+
[[nodiscard]] constexpr auto operator-(
|
1584
|
+
const WrappedIterator<OtherIterator, OtherElementType>& other)
|
1585
|
+
const noexcept {
|
1586
|
+
return it_ - other.base();
|
1587
|
+
}
|
1588
|
+
[[nodiscard]] constexpr reference operator[](
|
1589
|
+
difference_type n) const noexcept {
|
1473
1590
|
return it_[n];
|
1474
1591
|
}
|
1475
1592
|
|
1476
|
-
constexpr Iterator base() const noexcept { return it_; }
|
1477
|
-
|
1478
|
-
private:
|
1479
|
-
template <typename OtherIterator, typename OtherElementType>
|
1480
|
-
friend class WrappedIterator;
|
1593
|
+
[[nodiscard]] constexpr const Iterator& base() const noexcept { return it_; }
|
1481
1594
|
|
1482
1595
|
private:
|
1483
1596
|
Iterator it_;
|
1484
1597
|
};
|
1485
1598
|
|
1486
|
-
template <typename Iterator, typename ElementType, typename OtherIterator,
|
1487
|
-
typename OtherElementType>
|
1488
|
-
constexpr bool operator==(
|
1489
|
-
const WrappedIterator<Iterator, ElementType>& x,
|
1490
|
-
const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
|
1491
|
-
return x.base() == y.base();
|
1492
|
-
}
|
1493
|
-
|
1494
|
-
template <typename Iterator, typename ElementType, typename OtherIterator,
|
1495
|
-
typename OtherElementType>
|
1496
|
-
constexpr bool operator<(
|
1497
|
-
const WrappedIterator<Iterator, ElementType>& x,
|
1498
|
-
const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
|
1499
|
-
return x.base() < y.base();
|
1500
|
-
}
|
1501
|
-
|
1502
|
-
template <typename Iterator, typename ElementType, typename OtherIterator,
|
1503
|
-
typename OtherElementType>
|
1504
|
-
constexpr bool operator!=(
|
1505
|
-
const WrappedIterator<Iterator, ElementType>& x,
|
1506
|
-
const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
|
1507
|
-
return !(x == y);
|
1508
|
-
}
|
1509
|
-
|
1510
|
-
template <typename Iterator, typename ElementType, typename OtherIterator,
|
1511
|
-
typename OtherElementType>
|
1512
|
-
constexpr bool operator>(
|
1513
|
-
const WrappedIterator<Iterator, ElementType>& x,
|
1514
|
-
const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
|
1515
|
-
return y < x;
|
1516
|
-
}
|
1517
|
-
|
1518
|
-
template <typename Iterator, typename ElementType, typename OtherIterator,
|
1519
|
-
typename OtherElementType>
|
1520
|
-
constexpr bool operator>=(
|
1521
|
-
const WrappedIterator<Iterator, ElementType>& x,
|
1522
|
-
const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
|
1523
|
-
return !(x < y);
|
1524
|
-
}
|
1525
|
-
|
1526
|
-
template <typename Iterator, typename ElementType, typename OtherIterator,
|
1527
|
-
typename OtherElementType>
|
1528
|
-
constexpr bool operator<=(
|
1529
|
-
const WrappedIterator<Iterator, ElementType>& x,
|
1530
|
-
const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
|
1531
|
-
return !(y < x);
|
1532
|
-
}
|
1533
|
-
|
1534
|
-
template <typename Iterator, typename ElementType, typename OtherIterator,
|
1535
|
-
typename OtherElementType>
|
1536
|
-
constexpr auto operator-(
|
1537
|
-
const WrappedIterator<Iterator, ElementType>& x,
|
1538
|
-
const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept
|
1539
|
-
-> decltype(x.base() - y.base()) {
|
1540
|
-
return x.base() - y.base();
|
1541
|
-
}
|
1542
|
-
|
1543
|
-
template <typename Iterator, typename ElementType>
|
1544
|
-
constexpr WrappedIterator<Iterator> operator+(
|
1545
|
-
typename WrappedIterator<Iterator, ElementType>::difference_type n,
|
1546
|
-
const WrappedIterator<Iterator, ElementType>& x) noexcept {
|
1547
|
-
x += n;
|
1548
|
-
return x;
|
1549
|
-
}
|
1550
|
-
|
1551
1599
|
// Helper functions about values contained in handles.
|
1552
1600
|
// A value is either an indirect pointer or a direct pointer, depending on
|
1553
1601
|
// whether direct local support is enabled.
|
1554
1602
|
class ValueHelper final {
|
1555
1603
|
public:
|
1604
|
+
// ValueHelper::InternalRepresentationType is an abstract type that
|
1605
|
+
// corresponds to the internal representation of v8::Local and essentially
|
1606
|
+
// to what T* really is (these two are always in sync). This type is used in
|
1607
|
+
// methods like GetDataFromSnapshotOnce that need access to a handle's
|
1608
|
+
// internal representation. In particular, if `x` is a `v8::Local<T>`, then
|
1609
|
+
// `v8::Local<T>::FromRepr(x.repr())` gives exactly the same handle as `x`.
|
1556
1610
|
#ifdef V8_ENABLE_DIRECT_HANDLE
|
1557
1611
|
static constexpr Address kTaggedNullAddress = 1;
|
1558
|
-
|
1612
|
+
|
1613
|
+
using InternalRepresentationType = internal::Address;
|
1614
|
+
static constexpr InternalRepresentationType kEmpty = kTaggedNullAddress;
|
1559
1615
|
#else
|
1560
|
-
|
1616
|
+
using InternalRepresentationType = internal::Address*;
|
1617
|
+
static constexpr InternalRepresentationType kEmpty = nullptr;
|
1561
1618
|
#endif // V8_ENABLE_DIRECT_HANDLE
|
1562
1619
|
|
1563
1620
|
template <typename T>
|
1564
1621
|
V8_INLINE static bool IsEmpty(T* value) {
|
1565
|
-
return
|
1622
|
+
return ValueAsRepr(value) == kEmpty;
|
1566
1623
|
}
|
1567
1624
|
|
1568
1625
|
// Returns a handle's "value" for all kinds of abstract handles. For Local,
|
@@ -1589,6 +1646,16 @@ class ValueHelper final {
|
|
1589
1646
|
return *reinterpret_cast<T**>(slot);
|
1590
1647
|
}
|
1591
1648
|
|
1649
|
+
template <typename T>
|
1650
|
+
V8_INLINE static InternalRepresentationType ValueAsRepr(const T* value) {
|
1651
|
+
return reinterpret_cast<InternalRepresentationType>(value);
|
1652
|
+
}
|
1653
|
+
|
1654
|
+
template <typename T>
|
1655
|
+
V8_INLINE static T* ReprAsValue(InternalRepresentationType repr) {
|
1656
|
+
return reinterpret_cast<T*>(repr);
|
1657
|
+
}
|
1658
|
+
|
1592
1659
|
#else // !V8_ENABLE_DIRECT_HANDLE
|
1593
1660
|
|
1594
1661
|
template <typename T>
|
@@ -1601,6 +1668,17 @@ class ValueHelper final {
|
|
1601
1668
|
return reinterpret_cast<T*>(slot);
|
1602
1669
|
}
|
1603
1670
|
|
1671
|
+
template <typename T>
|
1672
|
+
V8_INLINE static InternalRepresentationType ValueAsRepr(const T* value) {
|
1673
|
+
return const_cast<InternalRepresentationType>(
|
1674
|
+
reinterpret_cast<const Address*>(value));
|
1675
|
+
}
|
1676
|
+
|
1677
|
+
template <typename T>
|
1678
|
+
V8_INLINE static T* ReprAsValue(InternalRepresentationType repr) {
|
1679
|
+
return reinterpret_cast<T*>(repr);
|
1680
|
+
}
|
1681
|
+
|
1604
1682
|
#endif // V8_ENABLE_DIRECT_HANDLE
|
1605
1683
|
};
|
1606
1684
|
|