diff --git a/V8_DEFAULT_VERSION.txt b/V8_DEFAULT_VERSION.txt index 9753bdb..ff45d2b 100644 --- a/V8_DEFAULT_VERSION.txt +++ b/V8_DEFAULT_VERSION.txt @@ -1 +1 @@ -11.8.172.17 +11.9.169.6 diff --git a/v8_c_api/src/v8include/js_protocol.pdl b/v8_c_api/src/v8include/js_protocol.pdl index ed62263..4754f17 100644 --- a/v8_c_api/src/v8include/js_protocol.pdl +++ b/v8_c_api/src/v8include/js_protocol.pdl @@ -1014,8 +1014,7 @@ domain Runtime # Unique script identifier. type ScriptId extends string - # Represents options for serialization. Overrides `generatePreview`, `returnByValue` and - # `generateWebDriverValue`. + # Represents options for serialization. Overrides `generatePreview` and `returnByValue`. type SerializationOptions extends object properties enum serialization @@ -1027,8 +1026,7 @@ domain Runtime # `returnByValue: true`. Overrides `returnByValue`. json # Only remote object id is put in the result. Same bahaviour as if no - # `serializationOptions`, `generatePreview`, `returnByValue` nor `generateWebDriverValue` - # are provided. + # `serializationOptions`, `generatePreview` nor `returnByValue` are provided. idOnly # Deep serialization depth. Default is full depth. Respected only in `deep` serialization mode. @@ -1066,6 +1064,7 @@ domain Runtime arraybuffer node window + generator optional any value optional string objectId # Set if value reference met more then once during serialization. In such @@ -1125,8 +1124,6 @@ domain Runtime optional UnserializableValue unserializableValue # String representation of the object. optional string description - # Deprecated. Use `deepSerializedValue` instead. WebDriver BiDi representation of the value. - deprecated optional DeepSerializedValue webDriverValue # Deep serialized value. experimental optional DeepSerializedValue deepSerializedValue # Unique object identifier (for non-primitive values). @@ -1442,13 +1439,8 @@ domain Runtime # boundaries). # This is mutually exclusive with `executionContextId`. experimental optional string uniqueContextId - # Deprecated. Use `serializationOptions: {serialization:"deep"}` instead. - # Whether the result should contain `webDriverValue`, serialized according to - # https://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but - # resulting `objectId` is still provided. - deprecated optional boolean generateWebDriverValue # Specifies the result serialization. If provided, overrides - # `generatePreview`, `returnByValue` and `generateWebDriverValue`. + # `generatePreview` and `returnByValue`. experimental optional SerializationOptions serializationOptions returns @@ -1536,14 +1528,8 @@ domain Runtime # boundaries). # This is mutually exclusive with `contextId`. experimental optional string uniqueContextId - # Deprecated. Use `serializationOptions: {serialization:"deep"}` instead. - # Whether the result should contain `webDriverValue`, serialized - # according to - # https://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but - # resulting `objectId` is still provided. - deprecated optional boolean generateWebDriverValue # Specifies the result serialization. If provided, overrides - # `generatePreview`, `returnByValue` and `generateWebDriverValue`. + # `generatePreview` and `returnByValue`. experimental optional SerializationOptions serializationOptions returns # Evaluation result. diff --git a/v8_c_api/src/v8include/v8-container.h b/v8_c_api/src/v8include/v8-container.h index ce06860..1d9e72c 100644 --- a/v8_c_api/src/v8include/v8-container.h +++ b/v8_c_api/src/v8include/v8-container.h @@ -43,6 +43,42 @@ class V8_EXPORT Array : public Object { return static_cast(value); } + enum class CallbackResult { + kException, + kBreak, + kContinue, + }; + using IterationCallback = CallbackResult (*)(uint32_t index, + Local element, + void* data); + + /** + * Calls {callback} for every element of this array, passing {callback_data} + * as its {data} parameter. + * This function will typically be faster than calling {Get()} repeatedly. + * As a consequence of being optimized for low overhead, the provided + * callback must adhere to the following restrictions: + * - It must not allocate any V8 objects and continue iterating; it may + * allocate (e.g. an error message/object) and then immediately terminate + * the iteration. + * - It must not modify the array being iterated. + * - It must not call back into V8 (unless it can guarantee that such a + * call does not violate the above restrictions, which is difficult). + * - The {Local element} must not "escape", i.e. must not be assigned + * to any other {Local}. Creating a {Global} from it, or updating a + * v8::TypecheckWitness with it, is safe. + * These restrictions may be lifted in the future if use cases arise that + * justify a slower but more robust implementation. + * + * Returns {Nothing} on exception; use a {TryCatch} to catch and handle this + * exception. + * When the {callback} returns {kException}, iteration is terminated + * immediately, returning {Nothing}. By returning {kBreak}, the callback + * can request non-exceptional early termination of the iteration. + */ + Maybe Iterate(Local context, IterationCallback callback, + void* callback_data); + private: Array(); static void CheckCast(Value* obj); diff --git a/v8_c_api/src/v8include/v8-exception.h b/v8_c_api/src/v8include/v8-exception.h index bc058e3..3b76636 100644 --- a/v8_c_api/src/v8include/v8-exception.h +++ b/v8_c_api/src/v8include/v8-exception.h @@ -30,14 +30,21 @@ class ThreadLocalTop; */ class V8_EXPORT Exception { public: - static Local RangeError(Local message); - static Local ReferenceError(Local message); - static Local SyntaxError(Local message); - static Local TypeError(Local message); - static Local WasmCompileError(Local message); - static Local WasmLinkError(Local message); - static Local WasmRuntimeError(Local message); - static Local Error(Local message); + static Local RangeError(Local message, + Local options = {}); + static Local ReferenceError(Local message, + Local options = {}); + static Local SyntaxError(Local message, + Local options = {}); + static Local TypeError(Local message, + Local options = {}); + static Local WasmCompileError(Local message, + Local options = {}); + static Local WasmLinkError(Local message, + Local options = {}); + static Local WasmRuntimeError(Local message, + Local options = {}); + static Local Error(Local message, Local options = {}); /** * Creates an error message for the given exception. diff --git a/v8_c_api/src/v8include/v8-inspector.h b/v8_c_api/src/v8include/v8-inspector.h index 68b1972..cfdd5db 100644 --- a/v8_c_api/src/v8include/v8-inspector.h +++ b/v8_c_api/src/v8include/v8-inspector.h @@ -217,17 +217,6 @@ class V8_EXPORT V8InspectorSession { virtual void stop() = 0; }; -// Deprecated. -// TODO(crbug.com/1420968): remove. -class V8_EXPORT WebDriverValue { - public: - explicit WebDriverValue(std::unique_ptr type, - v8::MaybeLocal value = {}) - : type(std::move(type)), value(value) {} - std::unique_ptr type; - v8::MaybeLocal value; -}; - struct V8_EXPORT DeepSerializedValue { explicit DeepSerializedValue(std::unique_ptr type, v8::MaybeLocal value = {}) @@ -266,12 +255,6 @@ class V8_EXPORT V8InspectorClient { virtual void beginUserGesture() {} virtual void endUserGesture() {} - // Deprecated. Use `deepSerialize` instead. - // TODO(crbug.com/1420968): remove. - virtual std::unique_ptr serializeToWebDriverValue( - v8::Local v8Value, int maxDepth) { - return nullptr; - } virtual std::unique_ptr deepSerialize( v8::Local v8Value, int maxDepth, v8::Local additionalParameters) { diff --git a/v8_c_api/src/v8include/v8-internal.h b/v8_c_api/src/v8include/v8-internal.h index d29a303..d04af44 100644 --- a/v8_c_api/src/v8include/v8-internal.h +++ b/v8_c_api/src/v8include/v8-internal.h @@ -484,65 +484,74 @@ PER_ISOLATE_EXTERNAL_POINTER_TAGS(CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS) // Indirect Pointers. // // When the sandbox is enabled, indirect pointers are used to reference -// HeapObjects that live outside of the sandbox (but are still managed through -// the GC). When object A references an object B through an indirect pointer, -// object A will contain a IndirectPointerHandle, i.e. a shifted 32-bit index, -// which identifies an entry in a pointer table (such as the CodePointerTable). +// HeapObjects that live outside of the sandbox (but are still managed by V8's +// garbage collector). When object A references an object B through an indirect +// pointer, object A will contain a IndirectPointerHandle, i.e. a shifted +// 32-bit index, which identifies an entry in a pointer table (generally an +// indirect pointer table, or the code pointer table if it is a Code object). // This table entry then contains the actual pointer to object B. Further, // object B owns this pointer table entry, and it is responsible for updating // the "self-pointer" in the entry when it is relocated in memory. This way, in // contrast to "normal" pointers, indirect pointers never need to be tracked by // the GC (i.e. there is no remembered set for them). -// Currently there is only one type of object referenced through indirect -// pointers (Code objects), but once there are different types of such objects, -// the pointer table entry would probably also contain the type of the target -// object (e.g. by XORing the instance type into the top bits of the pointer). // An IndirectPointerHandle represents a 32-bit index into a pointer table. using IndirectPointerHandle = uint32_t; +// The size of the virtual memory reservation for the indirect pointer table. +// As with the external pointer table, a maximum table size in combination with +// shifted indices allows omitting bounds checks. +constexpr size_t kIndirectPointerTableReservationSize = 8 * MB; + // The indirect pointer handles are stores shifted to the left by this amount // to guarantee that they are smaller than the maximum table size. -constexpr uint32_t kIndirectPointerHandleShift = 6; +constexpr uint32_t kIndirectPointerHandleShift = 12; // A null handle always references an entry that contains nullptr. constexpr IndirectPointerHandle kNullIndirectPointerHandle = 0; -// Currently only Code objects can be referenced through indirect pointers and -// various places rely on that assumption. They will all static_assert against -// this constant to make them easy to find and fix once we reference other types -// of objects indirectly. -constexpr bool kAllIndirectPointerObjectsAreCode = true; +// The maximum number of entries in an indirect pointer table. +constexpr int kIndirectPointerTableEntrySize = 8; +constexpr int kIndirectPointerTableEntrySizeLog2 = 3; +constexpr size_t kMaxIndirectPointers = + kIndirectPointerTableReservationSize / kIndirectPointerTableEntrySize; +static_assert((1 << (32 - kIndirectPointerHandleShift)) == kMaxIndirectPointers, + "kIndirectPointerTableReservationSize and " + "kIndirectPointerHandleShift don't match"); // // Code Pointers. // // When the sandbox is enabled, Code objects are referenced from inside the // sandbox through indirect pointers that reference entries in the code pointer -// table (CPT). Each entry in the CPT contains both a pointer to a Code object -// as well as a pointer to the Code's entrypoint. This allows calling/jumping -// into Code with one fewer memory access (compared to the case where the -// entrypoint pointer needs to be loaded from the Code object). -// As such, a CodePointerHandle can be used both to obtain the referenced Code -// object and to directly load its entrypoint pointer. +// table (CPT) instead of the indirect pointer table (IPT). Each entry in the +// CPT contains both a pointer to a Code object as well as a pointer to the +// Code's entrypoint. This allows calling/jumping into Code with one fewer +// memory access (compared to the case where the entrypoint pointer needs to be +// loaded from the Code object). As such, a CodePointerHandle can be used both +// to obtain the referenced Code object and to directly load its entrypoint +// pointer. using CodePointerHandle = IndirectPointerHandle; -constexpr uint32_t kCodePointerHandleShift = kIndirectPointerHandleShift; -constexpr CodePointerHandle kNullCodePointerHandle = 0; -// The size of the virtual memory reservation for code pointer table. -// This determines the maximum number of entries in a table. Using a maximum -// size allows omitting bounds checks on table accesses if the indices are -// guaranteed (e.g. through shifting) to be below the maximum index. This -// value must be a power of two. +// The size of the virtual memory reservation for the code pointer table. +// As with the other tables, a maximum table size in combination with shifted +// indices allows omitting bounds checks. constexpr size_t kCodePointerTableReservationSize = 1 * GB; -// The maximum number of entries in an external pointer table. +// Code pointer handles are shifted by a different amount than indirect pointer +// handles as the tables have a different maximum size. +constexpr uint32_t kCodePointerHandleShift = 6; + +// A null handle always references an entry that contains nullptr. +constexpr CodePointerHandle kNullCodePointerHandle = 0; + +// The maximum number of entries in a code pointer table. constexpr int kCodePointerTableEntrySize = 16; constexpr int kCodePointerTableEntrySizeLog2 = 4; constexpr size_t kMaxCodePointers = kCodePointerTableReservationSize / kCodePointerTableEntrySize; static_assert( - (1 << (32 - kIndirectPointerHandleShift)) == kMaxCodePointers, + (1 << (32 - kCodePointerHandleShift)) == kMaxCodePointers, "kCodePointerTableReservationSize and kCodePointerHandleShift don't match"); constexpr int kCodePointerTableEntryEntrypointOffset = 0; @@ -602,9 +611,11 @@ class Internals { static const int kHandleScopeDataSize = 2 * kApiSystemPointerSize + 2 * kApiInt32Size; - // ExternalPointerTable layout guarantees. + // ExternalPointerTable and IndirectPointerTable layout guarantees. static const int kExternalPointerTableBasePointerOffset = 0; static const int kExternalPointerTableSize = 2 * kApiSystemPointerSize; + static const int kIndirectPointerTableSize = 2 * kApiSystemPointerSize; + static const int kIndirectPointerTableBasePointerOffset = 0; // IsolateData layout guarantees. static const int kIsolateCageBaseOffset = 0; @@ -639,8 +650,10 @@ class Internals { kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize; static const int kIsolateSharedExternalPointerTableAddressOffset = kIsolateExternalPointerTableOffset + kExternalPointerTableSize; - static const int kIsolateApiCallbackThunkArgumentOffset = + static const int kIsolateIndirectPointerTableOffset = kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize; + static const int kIsolateApiCallbackThunkArgumentOffset = + kIsolateIndirectPointerTableOffset + kIndirectPointerTableSize; #else static const int kIsolateApiCallbackThunkArgumentOffset = kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize; @@ -763,6 +776,15 @@ class Internals { return ReadRawField(map, kMapInstanceTypeOffset); } + V8_INLINE static Address LoadMap(Address obj) { + if (!HasHeapObjectTag(obj)) return kNullAddress; + Address map = ReadTaggedPointerField(obj, kHeapObjectMapOffset); +#ifdef V8_MAP_PACKING + map = UnpackMapWord(map); +#endif + return map; + } + V8_INLINE static int GetOddballKind(Address obj) { return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset)); } diff --git a/v8_c_api/src/v8include/v8-isolate.h b/v8_c_api/src/v8include/v8-isolate.h index f6b64db..86bde11 100644 --- a/v8_c_api/src/v8include/v8-isolate.h +++ b/v8_c_api/src/v8include/v8-isolate.h @@ -421,36 +421,36 @@ class V8_EXPORT Isolate { enum UseCounterFeature { kUseAsm = 0, kBreakIterator = 1, - kLegacyConst V8_DEPRECATE_SOON("unused") = 2, - kMarkDequeOverflow V8_DEPRECATE_SOON("unused") = 3, - kStoreBufferOverflow V8_DEPRECATE_SOON("unused") = 4, - kSlotsBufferOverflow V8_DEPRECATE_SOON("unused") = 5, - kObjectObserve V8_DEPRECATE_SOON("unused") = 6, + kLegacyConst V8_DEPRECATED("unused") = 2, + kMarkDequeOverflow V8_DEPRECATED("unused") = 3, + kStoreBufferOverflow V8_DEPRECATED("unused") = 4, + kSlotsBufferOverflow V8_DEPRECATED("unused") = 5, + kObjectObserve V8_DEPRECATED("unused") = 6, kForcedGC = 7, kSloppyMode = 8, kStrictMode = 9, - kStrongMode V8_DEPRECATE_SOON("unused") = 10, + kStrongMode V8_DEPRECATED("unused") = 10, kRegExpPrototypeStickyGetter = 11, kRegExpPrototypeToString = 12, kRegExpPrototypeUnicodeGetter = 13, - kIntlV8Parse V8_DEPRECATE_SOON("unused") = 14, - kIntlPattern V8_DEPRECATE_SOON("unused") = 15, - kIntlResolved V8_DEPRECATE_SOON("unused") = 16, - kPromiseChain V8_DEPRECATE_SOON("unused") = 17, - kPromiseAccept V8_DEPRECATE_SOON("unused") = 18, - kPromiseDefer V8_DEPRECATE_SOON("unused") = 19, + kIntlV8Parse V8_DEPRECATED("unused") = 14, + kIntlPattern V8_DEPRECATED("unused") = 15, + kIntlResolved V8_DEPRECATED("unused") = 16, + kPromiseChain V8_DEPRECATED("unused") = 17, + kPromiseAccept V8_DEPRECATED("unused") = 18, + kPromiseDefer V8_DEPRECATED("unused") = 19, kHtmlCommentInExternalScript = 20, kHtmlComment = 21, kSloppyModeBlockScopedFunctionRedefinition = 22, kForInInitializer = 23, - kArrayProtectorDirtied V8_DEPRECATE_SOON("unused") = 24, + kArrayProtectorDirtied V8_DEPRECATED("unused") = 24, kArraySpeciesModified = 25, kArrayPrototypeConstructorModified = 26, - kArrayInstanceProtoModified V8_DEPRECATE_SOON("unused") = 27, + kArrayInstanceProtoModified V8_DEPRECATED("unused") = 27, kArrayInstanceConstructorModified = 28, - kLegacyFunctionDeclaration V8_DEPRECATE_SOON("unused") = 29, - kRegExpPrototypeSourceGetter V8_DEPRECATE_SOON("unused") = 30, - kRegExpPrototypeOldFlagGetter V8_DEPRECATE_SOON("unused") = 31, + kLegacyFunctionDeclaration V8_DEPRECATED("unused") = 29, + kRegExpPrototypeSourceGetter V8_DEPRECATED("unused") = 30, + kRegExpPrototypeOldFlagGetter V8_DEPRECATED("unused") = 31, kDecimalWithLeadingZeroInStrictMode = 32, kLegacyDateParser = 33, kDefineGetterOrSetterWouldThrow = 34, @@ -458,22 +458,21 @@ class V8_EXPORT Isolate { kAssigmentExpressionLHSIsCallInSloppy = 36, kAssigmentExpressionLHSIsCallInStrict = 37, kPromiseConstructorReturnedUndefined = 38, - kConstructorNonUndefinedPrimitiveReturn V8_DEPRECATE_SOON("unused") = 39, - kLabeledExpressionStatement V8_DEPRECATE_SOON("unused") = 40, - kLineOrParagraphSeparatorAsLineTerminator V8_DEPRECATE_SOON("unused") = 41, + kConstructorNonUndefinedPrimitiveReturn V8_DEPRECATED("unused") = 39, + kLabeledExpressionStatement V8_DEPRECATED("unused") = 40, + kLineOrParagraphSeparatorAsLineTerminator V8_DEPRECATED("unused") = 41, kIndexAccessor = 42, kErrorCaptureStackTrace = 43, kErrorPrepareStackTrace = 44, kErrorStackTraceLimit = 45, kWebAssemblyInstantiation = 46, kDeoptimizerDisableSpeculation = 47, - kArrayPrototypeSortJSArrayModifiedPrototype V8_DEPRECATE_SOON("unused") = - 48, + kArrayPrototypeSortJSArrayModifiedPrototype V8_DEPRECATED("unused") = 48, kFunctionTokenOffsetTooLongForToString = 49, kWasmSharedMemory = 50, kWasmThreadOpcodes = 51, - kAtomicsNotify V8_DEPRECATE_SOON("unused") = 52, - kAtomicsWake V8_DEPRECATE_SOON("unused") = 53, + kAtomicsNotify V8_DEPRECATED("unused") = 52, + kAtomicsWake V8_DEPRECATED("unused") = 53, kCollator = 54, kNumberFormat = 55, kDateTimeFormat = 56, @@ -483,7 +482,7 @@ class V8_EXPORT Isolate { kListFormat = 60, kSegmenter = 61, kStringLocaleCompare = 62, - kStringToLocaleUpperCase V8_DEPRECATE_SOON("unused") = 63, + kStringToLocaleUpperCase V8_DEPRECATED("unused") = 63, kStringToLocaleLowerCase = 64, kNumberToLocaleString = 65, kDateToLocaleString = 66, @@ -491,14 +490,14 @@ class V8_EXPORT Isolate { kDateToLocaleTimeString = 68, kAttemptOverrideReadOnlyOnPrototypeSloppy = 69, kAttemptOverrideReadOnlyOnPrototypeStrict = 70, - kOptimizedFunctionWithOneShotBytecode V8_DEPRECATE_SOON("unused") = 71, + kOptimizedFunctionWithOneShotBytecode V8_DEPRECATED("unused") = 71, kRegExpMatchIsTrueishOnNonJSRegExp = 72, kRegExpMatchIsFalseishOnJSRegExp = 73, - kDateGetTimezoneOffset V8_DEPRECATE_SOON("unused") = 74, + kDateGetTimezoneOffset V8_DEPRECATED("unused") = 74, kStringNormalize = 75, kCallSiteAPIGetFunctionSloppyCall = 76, kCallSiteAPIGetThisSloppyCall = 77, - kRegExpMatchAllWithNonGlobalRegExp V8_DEPRECATE_SOON("unused") = 78, + kRegExpMatchAllWithNonGlobalRegExp V8_DEPRECATED("unused") = 78, kRegExpExecCalledOnSlowRegExp = 79, kRegExpReplaceCalledOnSlowRegExp = 80, kDisplayNames = 81, @@ -529,9 +528,9 @@ class V8_EXPORT Isolate { kWasmSimdOpcodes = 106, kVarRedeclaredCatchBinding = 107, kWasmRefTypes = 108, - kWasmBulkMemory V8_DEPRECATE_SOON( + kWasmBulkMemory V8_DEPRECATED( "Unused since 2021 (https://crrev.com/c/2622913)") = 109, - kWasmMultiValue V8_DEPRECATE_SOON( + kWasmMultiValue V8_DEPRECATED( "Unused since 2021 (https://crrev.com/c/2817790)") = 110, kWasmExceptionHandling = 111, kInvalidatedMegaDOMProtector = 112, @@ -541,8 +540,8 @@ class V8_EXPORT Isolate { kAsyncStackTaggingCreateTaskCall = 116, kDurationFormat = 117, kInvalidatedNumberStringNotRegexpLikeProtector = 118, - kRegExpUnicodeSetIncompatibilitiesWithUnicodeMode V8_DEPRECATE_SOON( - "unused") = 119, + kRegExpUnicodeSetIncompatibilitiesWithUnicodeMode V8_DEPRECATED("unused") = + 119, kImportAssertionDeprecatedSyntax = 120, kLocaleInfoObsoletedGetters = 121, kLocaleInfoFunctions = 122, @@ -551,6 +550,7 @@ class V8_EXPORT Isolate { kWasmMemory64 = 125, kWasmMultiMemory = 126, kWasmGC = 127, + kWasmImportedStrings = 128, // If you add new values here, you'll also need to update Chromium's: // web_feature.mojom, use_counter_callback.cc, and enums.xml. V8 changes to diff --git a/v8_c_api/src/v8include/v8-memory-span.h b/v8_c_api/src/v8include/v8-memory-span.h index b26af4f..c18edb1 100644 --- a/v8_c_api/src/v8include/v8-memory-span.h +++ b/v8_c_api/src/v8include/v8-memory-span.h @@ -7,12 +7,16 @@ #include +#include +#include +#include + #include "v8config.h" // NOLINT(build/include_directory) namespace v8 { /** - * Points to an unowned continous buffer holding a known number of elements. + * Points to an unowned contiguous buffer holding a known number of elements. * * This is similar to std::span (under consideration for C++20), but does not * require advanced C++ support. In the (far) future, this may be replaced with @@ -23,21 +27,167 @@ namespace v8 { */ template class V8_EXPORT MemorySpan { + private: + /** Some C++ machinery, brought from the future. */ + template + using is_array_convertible = std::is_convertible; + template + static constexpr bool is_array_convertible_v = + is_array_convertible::value; + + template + using iter_reference_t = decltype(*std::declval()); + + template + struct is_compatible_iterator : std::false_type {}; + template + struct is_compatible_iterator< + It, + std::void_t< + std::is_base_of::iterator_category>, + is_array_convertible>, + T>>> : std::true_type {}; + template + static constexpr bool is_compatible_iterator_v = + is_compatible_iterator::value; + + template + static constexpr U* to_address(U* p) noexcept { + return p; + } + + template ().operator->())>> + static constexpr auto to_address(It it) noexcept { + return it.operator->(); + } + public: /** The default constructor creates an empty span. */ constexpr MemorySpan() = default; - constexpr MemorySpan(T* data, size_t size) : data_(data), size_(size) {} + /** Constructor from nullptr and count, for backwards compatibility. + * This is not compatible with C++20 std::span. + */ + constexpr MemorySpan(std::nullptr_t, size_t) {} + + /** Constructor from "iterator" and count. */ + template , bool> = true> + constexpr MemorySpan(Iterator first, + size_t count) // NOLINT(runtime/explicit) + : data_(to_address(first)), size_(count) {} + + /** Constructor from two "iterators". */ + template && + !std::is_convertible_v, + bool> = true> + constexpr MemorySpan(Iterator first, + Iterator last) // NOLINT(runtime/explicit) + : data_(to_address(first)), size_(last - first) {} + + /** Implicit conversion from C-style array. */ + template + constexpr MemorySpan(T (&a)[N]) noexcept // NOLINT(runtime/explicit) + : data_(a), size_(N) {} + + /** Implicit conversion from std::array. */ + template , bool> = true> + constexpr MemorySpan( + std::array& a) noexcept // NOLINT(runtime/explicit) + : data_(a.data()), size_{N} {} + + /** Implicit conversion from const std::array. */ + template , bool> = true> + constexpr MemorySpan( + const std::array& a) noexcept // NOLINT(runtime/explicit) + : data_(a.data()), size_{N} {} /** Returns a pointer to the beginning of the buffer. */ constexpr T* data() const { return data_; } /** Returns the number of elements that the buffer holds. */ constexpr size_t size() const { return size_; } + constexpr T& operator[](size_t i) const { return data_[i]; } + + class Iterator { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + + bool operator==(Iterator other) const { return ptr_ == other.ptr_; } + bool operator!=(Iterator other) const { return !(*this == other); } + + Iterator& operator++() { + ++ptr_; + return *this; + } + + Iterator operator++(int) { + Iterator temp(*this); + ++(*this); + return temp; + } + + private: + explicit Iterator(T* ptr) : ptr_(ptr) {} + + T* ptr_ = nullptr; + }; + + Iterator begin() const { return Iterator(data_); } + Iterator end() const { return Iterator(data_ + size_); } + private: T* data_ = nullptr; size_t size_ = 0; }; +/** + * Helper function template to create an array of fixed length, initialized by + * the provided initializer list, without explicitly specifying the array size, + * e.g. + * + * auto arr = v8::to_array>({v8_str("one"), v8_str("two")}); + * + * In the future, this may be replaced with or aliased to std::to_array (under + * consideration for C++20). + */ + +namespace detail { +template +constexpr std::array, N> to_array_lvalue_impl( + T (&a)[N], std::index_sequence) { + return {{a[I]...}}; +} + +template +constexpr std::array, N> to_array_rvalue_impl( + T (&&a)[N], std::index_sequence) { + return {{std::move(a[I])...}}; +} +} // namespace detail + +template +constexpr std::array, N> to_array(T (&a)[N]) { + return detail::to_array_lvalue_impl(a, std::make_index_sequence{}); +} + +template +constexpr std::array, N> to_array(T (&&a)[N]) { + return detail::to_array_rvalue_impl(std::move(a), + std::make_index_sequence{}); +} + } // namespace v8 #endif // INCLUDE_V8_MEMORY_SPAN_H_ diff --git a/v8_c_api/src/v8include/v8-metrics.h b/v8_c_api/src/v8include/v8-metrics.h index 5c6c1c4..46bc467 100644 --- a/v8_c_api/src/v8include/v8-metrics.h +++ b/v8_c_api/src/v8include/v8-metrics.h @@ -55,6 +55,7 @@ struct GarbageCollectionFullCycle { double efficiency_cpp_in_bytes_per_us = -1.0; double main_thread_efficiency_in_bytes_per_us = -1.0; double main_thread_efficiency_cpp_in_bytes_per_us = -1.0; + int64_t incremental_marking_start_stop_wall_clock_duration_in_us = -1; }; struct GarbageCollectionFullMainThreadIncrementalMark { diff --git a/v8_c_api/src/v8include/v8-object.h b/v8_c_api/src/v8include/v8-object.h index 3b50651..f78d404 100644 --- a/v8_c_api/src/v8include/v8-object.h +++ b/v8_c_api/src/v8include/v8-object.h @@ -174,7 +174,7 @@ enum AccessControl { DEFAULT = 0, ALL_CAN_READ = 1, ALL_CAN_WRITE = 1 << 1, - PROHIBITS_OVERWRITING V8_ENUM_DEPRECATE_SOON("unused") = 1 << 2 + PROHIBITS_OVERWRITING V8_ENUM_DEPRECATED("unused") = 1 << 2 }; /** @@ -483,11 +483,20 @@ class V8_EXPORT Object : public Value { return object.template value()->InternalFieldCount(); } - /** Gets the value from an internal field. */ - V8_INLINE Local GetInternalField(int index); + /** + * Gets the data from an internal field. + * To cast the return value into v8::Value subtypes, it needs to be + * casted to a v8::Value first. For example, to cast it into v8::External: + * + * object->GetInternalField(index).As().As(); + * + * The embedder should make sure that the internal field being retrieved + * using this method has already been set with SetInternalField() before. + **/ + V8_INLINE Local GetInternalField(int index); - /** Sets the value in an internal field. */ - void SetInternalField(int index, Local value); + /** Sets the data in an internal field. */ + void SetInternalField(int index, Local data); /** * Gets a 2-byte-aligned native pointer from an internal field. This field @@ -725,13 +734,13 @@ class V8_EXPORT Object : public Value { private: Object(); static void CheckCast(Value* obj); - Local SlowGetInternalField(int index); + Local SlowGetInternalField(int index); void* SlowGetAlignedPointerFromInternalField(int index); }; // --- Implementation --- -Local Object::GetInternalField(int index) { +Local Object::GetInternalField(int index) { #ifndef V8_ENABLE_CHECKS using A = internal::Address; using I = internal::Internals; @@ -750,7 +759,7 @@ Local Object::GetInternalField(int index) { auto isolate = reinterpret_cast( internal::IsolateFromNeverReadOnlySpaceObject(obj)); - return Local::New(isolate, value); + return Local::New(isolate, value); } #endif return SlowGetInternalField(index); diff --git a/v8_c_api/src/v8include/v8-script.h b/v8_c_api/src/v8include/v8-script.h index aa1447c..759bd75 100644 --- a/v8_c_api/src/v8include/v8-script.h +++ b/v8_c_api/src/v8include/v8-script.h @@ -16,6 +16,7 @@ #include "v8-data.h" // NOLINT(build/include_directory) #include "v8-local-handle.h" // NOLINT(build/include_directory) #include "v8-maybe.h" // NOLINT(build/include_directory) +#include "v8-memory-span.h" // NOLINT(build/include_directory) #include "v8-message.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory) @@ -285,10 +286,15 @@ class V8_EXPORT Module : public Data { * module_name is used solely for logging/debugging and doesn't affect module * behavior. */ + V8_DEPRECATE_SOON("Please use the version that takes a MemorySpan") static Local CreateSyntheticModule( Isolate* isolate, Local module_name, const std::vector>& export_names, SyntheticModuleEvaluationSteps evaluation_steps); + static Local CreateSyntheticModule( + Isolate* isolate, Local module_name, + const MemorySpan>& export_names, + SyntheticModuleEvaluationSteps evaluation_steps); /** * Set this module's exported value for the name export_name to the specified diff --git a/v8_c_api/src/v8include/v8-typed-array.h b/v8_c_api/src/v8include/v8-typed-array.h index 483b4f7..ba031cd 100644 --- a/v8_c_api/src/v8include/v8-typed-array.h +++ b/v8_c_api/src/v8include/v8-typed-array.h @@ -5,14 +5,14 @@ #ifndef INCLUDE_V8_TYPED_ARRAY_H_ #define INCLUDE_V8_TYPED_ARRAY_H_ +#include + #include "v8-array-buffer.h" // NOLINT(build/include_directory) #include "v8-local-handle.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory) namespace v8 { -class SharedArrayBuffer; - /** * A base class for an instance of TypedArray series of constructors * (ES6 draft 15.13.6). @@ -20,12 +20,25 @@ class SharedArrayBuffer; class V8_EXPORT TypedArray : public ArrayBufferView { public: /* - * The largest typed array size that can be constructed using New. + * The largest supported typed array byte size. Each subclass defines a + * type-specific kMaxLength for the maximum length that can be passed to New. */ - static constexpr size_t kMaxLength = - internal::kApiSystemPointerSize == 4 - ? internal::kSmiMaxValue - : static_cast(uint64_t{1} << 32); +#if V8_ENABLE_SANDBOX + static constexpr size_t kMaxByteLength = + internal::kMaxSafeBufferSizeForSandbox; +#elif V8_HOST_ARCH_32_BIT + static constexpr size_t kMaxByteLength = std::numeric_limits::max(); +#else + // The maximum safe integer (2^53 - 1). + static constexpr size_t kMaxByteLength = + static_cast((uint64_t{1} << 53) - 1); +#endif + + /* + * Deprecated: Use |kMaxByteLength| or the type-specific |kMaxLength| fields. + */ + V8_DEPRECATE_SOON("Use kMaxByteLength") + static constexpr size_t kMaxLength = kMaxByteLength; /** * Number of elements in this typed array @@ -50,6 +63,13 @@ class V8_EXPORT TypedArray : public ArrayBufferView { */ class V8_EXPORT Uint8Array : public TypedArray { public: + /* + * The largest Uint8Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(uint8_t); + static_assert(sizeof(uint8_t) == 1); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -71,6 +91,13 @@ class V8_EXPORT Uint8Array : public TypedArray { */ class V8_EXPORT Uint8ClampedArray : public TypedArray { public: + /* + * The largest Uint8ClampedArray size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(uint8_t); + static_assert(sizeof(uint8_t) == 1); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New( @@ -93,6 +120,13 @@ class V8_EXPORT Uint8ClampedArray : public TypedArray { */ class V8_EXPORT Int8Array : public TypedArray { public: + /* + * The largest Int8Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(int8_t); + static_assert(sizeof(int8_t) == 1); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -114,6 +148,13 @@ class V8_EXPORT Int8Array : public TypedArray { */ class V8_EXPORT Uint16Array : public TypedArray { public: + /* + * The largest Uint16Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(uint16_t); + static_assert(sizeof(uint16_t) == 2); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -135,6 +176,13 @@ class V8_EXPORT Uint16Array : public TypedArray { */ class V8_EXPORT Int16Array : public TypedArray { public: + /* + * The largest Int16Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(int16_t); + static_assert(sizeof(int16_t) == 2); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -156,6 +204,13 @@ class V8_EXPORT Int16Array : public TypedArray { */ class V8_EXPORT Uint32Array : public TypedArray { public: + /* + * The largest Uint32Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(uint32_t); + static_assert(sizeof(uint32_t) == 4); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -177,6 +232,13 @@ class V8_EXPORT Uint32Array : public TypedArray { */ class V8_EXPORT Int32Array : public TypedArray { public: + /* + * The largest Int32Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(int32_t); + static_assert(sizeof(int32_t) == 4); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -198,6 +260,13 @@ class V8_EXPORT Int32Array : public TypedArray { */ class V8_EXPORT Float32Array : public TypedArray { public: + /* + * The largest Float32Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(float); + static_assert(sizeof(float) == 4); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -219,6 +288,13 @@ class V8_EXPORT Float32Array : public TypedArray { */ class V8_EXPORT Float64Array : public TypedArray { public: + /* + * The largest Float64Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(double); + static_assert(sizeof(double) == 8); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -240,6 +316,13 @@ class V8_EXPORT Float64Array : public TypedArray { */ class V8_EXPORT BigInt64Array : public TypedArray { public: + /* + * The largest BigInt64Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(int64_t); + static_assert(sizeof(int64_t) == 8); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, @@ -261,6 +344,13 @@ class V8_EXPORT BigInt64Array : public TypedArray { */ class V8_EXPORT BigUint64Array : public TypedArray { public: + /* + * The largest BigUint64Array size that can be constructed using New. + */ + static constexpr size_t kMaxLength = + TypedArray::kMaxByteLength / sizeof(uint64_t); + static_assert(sizeof(uint64_t) == 8); + static Local New(Local array_buffer, size_t byte_offset, size_t length); static Local New(Local shared_array_buffer, diff --git a/v8_c_api/src/v8include/v8-value.h b/v8_c_api/src/v8include/v8-value.h index 19ecf71..110b695 100644 --- a/v8_c_api/src/v8include/v8-value.h +++ b/v8_c_api/src/v8include/v8-value.h @@ -391,7 +391,7 @@ class V8_EXPORT Value : public Data { V8_WARN_UNUSED_RESULT MaybeLocal ToDetailString( Local context) const; /** - * Perform the equivalent of `Object(value)` in JS. + * Perform the equivalent of `Tagged(value)` in JS. */ V8_WARN_UNUSED_RESULT MaybeLocal ToObject( Local context) const; @@ -469,6 +469,41 @@ class V8_EXPORT Value : public Data { static void CheckCast(Data* that); }; +/** + * Can be used to avoid repeated expensive type checks for groups of objects + * that are expected to be similar (e.g. when Blink converts a bunch of + * JavaScript objects to "ScriptWrappable" after a "HasInstance" check) by + * making use of V8-internal "hidden classes". An object that has passed the + * full check can be remembered via {Update}; further objects can be queried + * using {Matches}. + * Note that the answer will be conservative/"best-effort": when {Matches} + * returns true, then the {candidate} can be relied upon to have the same + * shape/constructor/prototype/etc. as the {baseline}. Otherwise, no reliable + * statement can be made (the objects might still have indistinguishable shapes + * for all intents and purposes, but this mechanism, being optimized for speed, + * couldn't determine that quickly). + */ +class V8_EXPORT TypecheckWitness { + public: + explicit TypecheckWitness(Isolate* isolate); + + /** + * Checks whether {candidate} can cheaply be identified as being "similar" + * to the {baseline} that was passed to {Update} earlier. + * It's safe to call this on an uninitialized {TypecheckWitness} instance: + * it will then return {false} for any input. + */ + V8_INLINE bool Matches(Local candidate) const; + + /** + * Remembers a new baseline for future {Matches} queries. + */ + void Update(Local baseline); + + private: + Local cached_map_; +}; + template <> V8_INLINE Value* Value::Cast(Data* value) { #ifdef V8_ENABLE_CHECKS @@ -562,6 +597,14 @@ bool Value::QuickIsString() const { #endif // V8_STATIC_ROOTS_BOOL } +bool TypecheckWitness::Matches(Local candidate) const { + internal::Address obj = internal::ValueHelper::ValueAsAddress(*candidate); + internal::Address obj_map = internal::Internals::LoadMap(obj); + internal::Address cached = + internal::ValueHelper::ValueAsAddress(*cached_map_); + return obj_map == cached; +} + } // namespace v8 #endif // INCLUDE_V8_VALUE_H_ diff --git a/v8_c_api/src/v8include/v8-version.h b/v8_c_api/src/v8include/v8-version.h index 074d0e9..a8017d8 100644 --- a/v8_c_api/src/v8include/v8-version.h +++ b/v8_c_api/src/v8include/v8-version.h @@ -9,9 +9,9 @@ // NOTE these macros are used by some of the tool scripts and the build // system so their names cannot be changed without changing the scripts. #define V8_MAJOR_VERSION 11 -#define V8_MINOR_VERSION 8 -#define V8_BUILD_NUMBER 172 -#define V8_PATCH_LEVEL 17 +#define V8_MINOR_VERSION 9 +#define V8_BUILD_NUMBER 169 +#define V8_PATCH_LEVEL 6 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.)