diff --git a/build.rs b/build.rs index b11fc85..09ddda0 100644 --- a/build.rs +++ b/build.rs @@ -24,7 +24,7 @@ lazy_static::lazy_static! { static ref PROFILE: String = env::var("PROFILE").expect("PROFILE env var was not given"); - static ref V8_DEFAULT_VERSION: &'static str = "11.6.189.20"; + static ref V8_DEFAULT_VERSION: &'static str = "11.7.439.17"; static ref V8_VERSION: String = env::var("V8_VERSION").map(|v| if v == "default" {V8_DEFAULT_VERSION.to_string()} else {v}).unwrap_or(V8_DEFAULT_VERSION.to_string()); static ref V8_HEADERS_PATH: String = env::var("V8_HEADERS_PATH").unwrap_or("v8_c_api/libv8.include.zip".into()); static ref V8_HEADERS_URL: String = env::var("V8_HEADERS_URL").unwrap_or(format!("http://redismodules.s3.amazonaws.com/redisgears/dependencies/libv8.{}.include.zip", *V8_VERSION)); diff --git a/v8_c_api/src/v8include/cppgc/persistent.h b/v8_c_api/src/v8include/cppgc/persistent.h index 709f3fd..6eb1c65 100644 --- a/v8_c_api/src/v8include/cppgc/persistent.h +++ b/v8_c_api/src/v8include/cppgc/persistent.h @@ -92,6 +92,7 @@ class BasicPersistent final : public PersistentBase, template ::value>> + // NOLINTNEXTLINE BasicPersistent( const BasicPersistent& other, @@ -116,6 +117,7 @@ class BasicPersistent final : public PersistentBase, typename MemberWeaknessTag, typename MemberCheckingPolicy, typename MemberStorageType, typename = std::enable_if_t::value>> + // NOLINTNEXTLINE BasicPersistent(const internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy, MemberStorageType>& member, @@ -180,6 +182,8 @@ class BasicPersistent final : public PersistentBase, } explicit operator bool() const { return Get(); } + // Historically we allow implicit conversions to T*. + // NOLINTNEXTLINE operator T*() const { return Get(); } T* operator->() const { return Get(); } T& operator*() const { return *Get(); } diff --git a/v8_c_api/src/v8include/js_protocol.pdl b/v8_c_api/src/v8include/js_protocol.pdl index 7a3c772..ed62263 100644 --- a/v8_c_api/src/v8include/js_protocol.pdl +++ b/v8_c_api/src/v8include/js_protocol.pdl @@ -1034,6 +1034,11 @@ domain Runtime # Deep serialization depth. Default is full depth. Respected only in `deep` serialization mode. optional integer maxDepth + # Embedder-specific parameters. For example if connected to V8 in Chrome these control DOM + # serialization via `maxNodeDepth: integer` and `includeShadowTree: "none" | "open" | "all"`. + # Values can be only of type string or integer. + optional object additionalParameters + # Represents deep serialized value. type DeepSerializedValue extends object properties diff --git a/v8_c_api/src/v8include/libplatform/libplatform.h b/v8_c_api/src/v8include/libplatform/libplatform.h index 9ec60c0..6a34f43 100644 --- a/v8_c_api/src/v8include/libplatform/libplatform.h +++ b/v8_c_api/src/v8include/libplatform/libplatform.h @@ -23,6 +23,8 @@ enum class MessageLoopBehavior : bool { kWaitForWork = true }; +enum class PriorityMode : bool { kDontApply, kApply }; + /** * Returns a new instance of the default v8::Platform implementation. * @@ -35,13 +37,17 @@ enum class MessageLoopBehavior : bool { * calling v8::platform::RunIdleTasks to process the idle tasks. * If |tracing_controller| is nullptr, the default platform will create a * v8::platform::TracingController instance and use it. + * If |priority_mode| is PriorityMode::kApply, the default platform will use + * multiple task queues executed by threads different system-level priorities + * (where available) to schedule tasks. */ V8_PLATFORM_EXPORT std::unique_ptr NewDefaultPlatform( int thread_pool_size = 0, IdleTaskSupport idle_task_support = IdleTaskSupport::kDisabled, InProcessStackDumping in_process_stack_dumping = InProcessStackDumping::kDisabled, - std::unique_ptr tracing_controller = {}); + std::unique_ptr tracing_controller = {}, + PriorityMode priority_mode = PriorityMode::kDontApply); /** * The same as NewDefaultPlatform but disables the worker thread pool. diff --git a/v8_c_api/src/v8include/v8-callbacks.h b/v8_c_api/src/v8include/v8-callbacks.h index 12588c6..897b1b0 100644 --- a/v8_c_api/src/v8include/v8-callbacks.h +++ b/v8_c_api/src/v8include/v8-callbacks.h @@ -147,14 +147,18 @@ using JitCodeEventHandler = void (*)(const JitCodeEvent* event); * the callback functions, you therefore cannot manipulate objects (set or * delete properties for example) since it is possible such operations will * result in the allocation of objects. + * TODO(v8:12612): Deprecate kGCTypeMinorMarkSweep after updating blink. */ enum GCType { kGCTypeScavenge = 1 << 0, - kGCTypeMinorMarkCompact = 1 << 1, + kGCTypeMinorMarkSweep = 1 << 1, + kGCTypeMinorMarkCompact V8_DEPRECATE_SOON( + "Use kGCTypeMinorMarkSweep instead of kGCTypeMinorMarkCompact.") = + kGCTypeMinorMarkSweep, kGCTypeMarkSweepCompact = 1 << 2, kGCTypeIncrementalMarking = 1 << 3, kGCTypeProcessWeakCallbacks = 1 << 4, - kGCTypeAll = kGCTypeScavenge | kGCTypeMinorMarkCompact | + kGCTypeAll = kGCTypeScavenge | kGCTypeMinorMarkSweep | kGCTypeMarkSweepCompact | kGCTypeIncrementalMarking | kGCTypeProcessWeakCallbacks }; @@ -327,6 +331,9 @@ using WasmLoadSourceMapCallback = Local (*)(Isolate* isolate, // If the callback returns true, it will also enable Wasm stringrefs. using WasmGCEnabledCallback = bool (*)(Local context); +// --- Callback for checking if WebAssembly imported strings are enabled --- +using WasmImportedStringsEnabledCallback = bool (*)(Local context); + // --- Callback for checking if the SharedArrayBuffer constructor is enabled --- using SharedArrayBufferConstructorEnabledCallback = bool (*)(Local context); diff --git a/v8_c_api/src/v8include/v8-context.h b/v8_c_api/src/v8include/v8-context.h index 36cd43c..50c7e6f 100644 --- a/v8_c_api/src/v8include/v8-context.h +++ b/v8_c_api/src/v8include/v8-context.h @@ -438,7 +438,8 @@ template MaybeLocal Context::GetDataFromSnapshotOnce(size_t index) { auto slot = GetDataFromSnapshotOnce(index); if (slot) { - internal::PerformCastCheck(internal::ValueHelper::SlotAsValue(slot)); + internal::PerformCastCheck( + internal::ValueHelper::SlotAsValue(slot)); } return Local::FromSlot(slot); } diff --git a/v8_c_api/src/v8include/v8-cppgc.h b/v8_c_api/src/v8include/v8-cppgc.h index 4a45702..e0d76f4 100644 --- a/v8_c_api/src/v8include/v8-cppgc.h +++ b/v8_c_api/src/v8include/v8-cppgc.h @@ -177,6 +177,11 @@ class V8_EXPORT CppHeap { void CollectGarbageInYoungGenerationForTesting( cppgc::EmbedderStackState stack_state); + /** + * \returns the wrapper descriptor of this CppHeap. + */ + v8::WrapperDescriptor wrapper_descriptor() const; + private: CppHeap() = default; diff --git a/v8_c_api/src/v8include/v8-function-callback.h b/v8_c_api/src/v8include/v8-function-callback.h index 49c102b..17b37cd 100644 --- a/v8_c_api/src/v8include/v8-function-callback.h +++ b/v8_c_api/src/v8include/v8-function-callback.h @@ -126,7 +126,6 @@ class FunctionCallbackInfo { friend class internal::FunctionCallbackArguments; friend class internal::CustomArguments; friend class debug::ConsoleCallArguments; - friend class internal::Builtins; static constexpr int kHolderIndex = 0; static constexpr int kIsolateIndex = 1; diff --git a/v8_c_api/src/v8include/v8-function.h b/v8_c_api/src/v8include/v8-function.h index 1e35bfc..30a9fcf 100644 --- a/v8_c_api/src/v8include/v8-function.h +++ b/v8_c_api/src/v8include/v8-function.h @@ -87,6 +87,12 @@ class V8_EXPORT Function : public Object { */ int GetScriptColumnNumber() const; + /** + * Returns zero based start position (character offset) of function body and + * kLineOffsetNotFound if no information available. + */ + int GetScriptStartPosition() const; + /** * Returns scriptId. */ diff --git a/v8_c_api/src/v8include/v8-handle-base.h b/v8_c_api/src/v8include/v8-handle-base.h index da19db7..d346a80 100644 --- a/v8_c_api/src/v8include/v8-handle-base.h +++ b/v8_c_api/src/v8include/v8-handle-base.h @@ -44,8 +44,11 @@ class ValueHelper final { return reinterpret_cast
(value); } - template + template V8_INLINE static T* SlotAsValue(S* slot) { + if (check_null && slot == nullptr) { + return reinterpret_cast(kTaggedNullAddress); + } return *reinterpret_cast(slot); } @@ -56,7 +59,7 @@ class ValueHelper final { return *reinterpret_cast(value); } - template + template V8_INLINE static T* SlotAsValue(S* slot) { return reinterpret_cast(slot); } @@ -85,6 +88,8 @@ class HandleHelper final { if (rhs.IsEmpty()) return false; return lhs.ptr() == rhs.ptr(); } + + static V8_EXPORT void VerifyOnStack(const void* ptr); }; } // namespace internal @@ -126,7 +131,7 @@ class IndirectHandleBase { // whether direct local support is enabled). template V8_INLINE T* value() const { - return internal::ValueHelper::SlotAsValue(slot()); + return internal::ValueHelper::SlotAsValue(slot()); } private: diff --git a/v8_c_api/src/v8include/v8-inspector.h b/v8_c_api/src/v8include/v8-inspector.h index 96643bb..68b1972 100644 --- a/v8_c_api/src/v8include/v8-inspector.h +++ b/v8_c_api/src/v8include/v8-inspector.h @@ -217,6 +217,8 @@ 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, @@ -226,6 +228,27 @@ class V8_EXPORT WebDriverValue { v8::MaybeLocal value; }; +struct V8_EXPORT DeepSerializedValue { + explicit DeepSerializedValue(std::unique_ptr type, + v8::MaybeLocal value = {}) + : type(std::move(type)), value(value) {} + std::unique_ptr type; + v8::MaybeLocal value; +}; + +struct V8_EXPORT DeepSerializationResult { + explicit DeepSerializationResult( + std::unique_ptr serializedValue) + : serializedValue(std::move(serializedValue)), isSuccess(true) {} + explicit DeepSerializationResult(std::unique_ptr errorMessage) + : errorMessage(std::move(errorMessage)), isSuccess(false) {} + + // Use std::variant when available. + std::unique_ptr serializedValue; + std::unique_ptr errorMessage; + bool isSuccess; +}; + class V8_EXPORT V8InspectorClient { public: virtual ~V8InspectorClient() = default; @@ -243,10 +266,17 @@ 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) { + return nullptr; + } virtual std::unique_ptr valueSubtype(v8::Local) { return nullptr; } diff --git a/v8_c_api/src/v8include/v8-internal.h b/v8_c_api/src/v8include/v8-internal.h index 9d163de..75165f3 100644 --- a/v8_c_api/src/v8include/v8-internal.h +++ b/v8_c_api/src/v8include/v8-internal.h @@ -246,21 +246,21 @@ static_assert(1ULL << (64 - kBoundedSizeShift) == // 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. -static const size_t kExternalPointerTableReservationSize = 512 * MB; +constexpr size_t kExternalPointerTableReservationSize = 512 * MB; // The external pointer table indices stored in HeapObjects as external // pointers are shifted to the left by this amount to guarantee that they are // smaller than the maximum table size. -static const uint32_t kExternalPointerIndexShift = 6; +constexpr uint32_t kExternalPointerIndexShift = 6; #else -static const size_t kExternalPointerTableReservationSize = 1024 * MB; -static const uint32_t kExternalPointerIndexShift = 5; +constexpr size_t kExternalPointerTableReservationSize = 1024 * MB; +constexpr uint32_t kExternalPointerIndexShift = 5; #endif // V8_TARGET_OS_ANDROID // The maximum number of entries in an external pointer table. -static const int kExternalPointerTableEntrySize = 8; -static const int kExternalPointerTableEntrySizeLog2 = 3; -static const size_t kMaxExternalPointers = +constexpr int kExternalPointerTableEntrySize = 8; +constexpr int kExternalPointerTableEntrySizeLog2 = 3; +constexpr size_t kMaxExternalPointers = kExternalPointerTableReservationSize / kExternalPointerTableEntrySize; static_assert((1 << (32 - kExternalPointerIndexShift)) == kMaxExternalPointers, "kExternalPointerTableReservationSize and " @@ -269,7 +269,7 @@ static_assert((1 << (32 - kExternalPointerIndexShift)) == kMaxExternalPointers, #else // !V8_COMPRESS_POINTERS // Needed for the V8.SandboxedExternalPointersCount histogram. -static const size_t kMaxExternalPointers = 0; +constexpr size_t kMaxExternalPointers = 0; #endif // V8_COMPRESS_POINTERS @@ -294,6 +294,9 @@ using ExternalPointer_t = Address; constexpr ExternalPointer_t kNullExternalPointer = 0; constexpr ExternalPointerHandle kNullExternalPointerHandle = 0; +// +// External Pointers. +// // When the sandbox is enabled, external pointers are stored in an external // pointer table and are referenced from HeapObjects through an index (a // "handle"). When stored in the table, the pointers are tagged with per-type @@ -421,7 +424,8 @@ constexpr uint64_t kAllExternalPointerTypeTags[] = { V(kWasmTypeInfoNativeTypeTag, TAG(18)) \ V(kWasmExportedFunctionDataSignatureTag, TAG(19)) \ V(kWasmContinuationJmpbufTag, TAG(20)) \ - V(kArrayBufferExtensionTag, TAG(21)) + V(kWasmIndirectFunctionTargetTag, TAG(21)) \ + V(kArrayBufferExtensionTag, TAG(22)) // All external pointer tags. #define ALL_EXTERNAL_POINTER_TAGS(V) \ @@ -475,19 +479,53 @@ PER_ISOLATE_EXTERNAL_POINTER_TAGS(CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS) #undef SHARED_EXTERNAL_POINTER_TAGS #undef EXTERNAL_POINTER_TAGS -// A handle to a code pointer stored in a code pointer table. -using CodePointerHandle = uint32_t; - -// CodePointers point to machine code (JIT or AOT compiled). When -// the V8 sandbox is enabled, these are stored as CodePointerHandles on the heap -// (i.e. as index into a code pointer table). Otherwise, they are simply raw -// pointers. -#ifdef V8_CODE_POINTER_SANDBOXING -using CodePointer_t = CodePointerHandle; -#else -using CodePointer_t = Address; -#endif +// +// 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). +// 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 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; + +// 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; +// +// 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. +using CodePointerHandle = IndirectPointerHandle; +constexpr uint32_t kCodePointerHandleShift = kIndirectPointerHandleShift; constexpr CodePointerHandle kNullCodePointerHandle = 0; // The size of the virtual memory reservation for code pointer table. @@ -495,21 +533,19 @@ constexpr CodePointerHandle kNullCodePointerHandle = 0; // 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. -static const size_t kCodePointerTableReservationSize = 512 * MB; - -// The code pointer table indices stored in HeapObjects as external -// pointers are shifted to the left by this amount to guarantee that they are -// smaller than the maximum table size. -static const uint32_t kCodePointerIndexShift = 6; +constexpr size_t kCodePointerTableReservationSize = 1 * GB; // The maximum number of entries in an external pointer table. -static const int kCodePointerTableEntrySize = 8; -static const int kCodePointerTableEntrySizeLog2 = 3; -static const size_t kMaxCodePointers = +constexpr int kCodePointerTableEntrySize = 16; +constexpr int kCodePointerTableEntrySizeLog2 = 4; +constexpr size_t kMaxCodePointers = kCodePointerTableReservationSize / kCodePointerTableEntrySize; static_assert( - (1 << (32 - kCodePointerIndexShift)) == kMaxCodePointers, - "kCodePointerTableReservationSize and kCodePointerIndexShift don't match"); + (1 << (32 - kIndirectPointerHandleShift)) == kMaxCodePointers, + "kCodePointerTableReservationSize and kCodePointerHandleShift don't match"); + +constexpr int kCodePointerTableEntryEntrypointOffset = 0; +constexpr int kCodePointerTableEntryCodeObjectOffset = 8; // {obj} must be the raw tagged pointer representation of a HeapObject // that's guaranteed to never be in ReadOnlySpace. @@ -561,13 +597,13 @@ class Internals { static const int kBuiltinTier0EntryTableSize = 7 * kApiSystemPointerSize; static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize; static const int kLinearAllocationAreaSize = 3 * kApiSystemPointerSize; - static const int kThreadLocalTopSize = 25 * kApiSystemPointerSize; + static const int kThreadLocalTopSize = 30 * kApiSystemPointerSize; static const int kHandleScopeDataSize = 2 * kApiSystemPointerSize + 2 * kApiInt32Size; // ExternalPointerTable layout guarantees. - static const int kExternalPointerTableBufferOffset = 0; - static const int kExternalPointerTableSize = 4 * kApiSystemPointerSize; + static const int kExternalPointerTableBasePointerOffset = 0; + static const int kExternalPointerTableSize = 2 * kApiSystemPointerSize; // IsolateData layout guarantees. static const int kIsolateCageBaseOffset = 0; @@ -816,7 +852,7 @@ class Internals { V8_INLINE static Address* GetExternalPointerTableBase(v8::Isolate* isolate) { Address addr = reinterpret_cast
(isolate) + kIsolateExternalPointerTableOffset + - kExternalPointerTableBufferOffset; + kExternalPointerTableBasePointerOffset; return *reinterpret_cast(addr); } @@ -825,7 +861,7 @@ class Internals { Address addr = reinterpret_cast
(isolate) + kIsolateSharedExternalPointerTableAddressOffset; addr = *reinterpret_cast(addr); - addr += kExternalPointerTableBufferOffset; + addr += kExternalPointerTableBasePointerOffset; return *reinterpret_cast(addr); } #endif diff --git a/v8_c_api/src/v8include/v8-isolate.h b/v8_c_api/src/v8include/v8-isolate.h index 18855b7..02bdd6e 100644 --- a/v8_c_api/src/v8include/v8-isolate.h +++ b/v8_c_api/src/v8include/v8-isolate.h @@ -414,6 +414,9 @@ class V8_EXPORT Isolate { * Features reported via the SetUseCounterCallback callback. Do not change * assigned numbers of existing items; add new features to the end of this * list. + * Dead features can be marked `V8_DEPRECATE_SOON`, then `V8_DEPRECATED`, and + * then finally be renamed to `kOBSOLETE_...` to stop embedders from using + * them. */ enum UseCounterFeature { kUseAsm = 0, @@ -525,8 +528,10 @@ class V8_EXPORT Isolate { kWasmSimdOpcodes = 106, kVarRedeclaredCatchBinding = 107, kWasmRefTypes = 108, - kWasmBulkMemory = 109, // Unused. - kWasmMultiValue = 110, + kWasmBulkMemory V8_DEPRECATE_SOON( + "Unused since 2021 (https://crrev.com/c/2622913)") = 109, + kWasmMultiValue V8_DEPRECATE_SOON( + "Unused since 2021 (https://crrev.com/c/2817790)") = 110, kWasmExceptionHandling = 111, kInvalidatedMegaDOMProtector = 112, kFunctionPrototypeArguments = 113, @@ -540,6 +545,10 @@ class V8_EXPORT Isolate { kLocaleInfoObsoletedGetters = 121, kLocaleInfoFunctions = 122, kCompileHintsMagicAll = 123, + kInvalidatedNoProfilingProtector = 124, + kWasmMemory64 = 125, + kWasmMultiMemory = 126, + kWasmGC = 127, // 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 @@ -908,25 +917,73 @@ class V8_EXPORT Isolate { /** * Enables the host application to receive a notification before a - * garbage collection. Allocations are allowed in the callback function, - * but the callback is not re-entrant: if the allocation inside it will - * trigger the garbage collection, the callback won't be called again. - * It is possible to specify the GCType filter for your callback. But it is - * not possible to register the same callback function two times with - * different GCType filters. + * garbage collection. + * + * \param callback The callback to be invoked. The callback is allowed to + * allocate but invocation is not re-entrant: a callback triggering + * garbage collection will not be called again. JS execution is prohibited + * from these callbacks. A single callback may only be registered once. + * \param gc_type_filter A filter in case it should be applied. */ - void AddGCPrologueCallback(GCCallbackWithData callback, void* data = nullptr, - GCType gc_type_filter = kGCTypeAll); void AddGCPrologueCallback(GCCallback callback, GCType gc_type_filter = kGCTypeAll); /** - * This function removes callback which was installed by - * AddGCPrologueCallback function. + * \copydoc AddGCPrologueCallback(GCCallback, GCType) + * + * \param data Additional data that should be passed to the callback. + */ + void AddGCPrologueCallback(GCCallbackWithData callback, void* data = nullptr, + GCType gc_type_filter = kGCTypeAll); + + /** + * This function removes a callback which was added by + * `AddGCPrologueCallback`. + * + * \param callback the callback to remove. */ - void RemoveGCPrologueCallback(GCCallbackWithData, void* data = nullptr); void RemoveGCPrologueCallback(GCCallback callback); + /** + * \copydoc AddGCPrologueCallback(GCCallback) + * + * \param data Additional data that was used to install the callback. + */ + void RemoveGCPrologueCallback(GCCallbackWithData, void* data = nullptr); + + /** + * Enables the host application to receive a notification after a + * garbage collection. + * + * \copydetails AddGCPrologueCallback(GCCallback, GCType) + */ + void AddGCEpilogueCallback(GCCallback callback, + GCType gc_type_filter = kGCTypeAll); + + /** + * \copydoc AddGCEpilogueCallback(GCCallback, GCType) + * + * \param data Additional data that should be passed to the callback. + */ + void AddGCEpilogueCallback(GCCallbackWithData callback, void* data = nullptr, + GCType gc_type_filter = kGCTypeAll); + + /** + * This function removes a callback which was added by + * `AddGCEpilogueCallback`. + * + * \param callback the callback to remove. + */ + void RemoveGCEpilogueCallback(GCCallback callback); + + /** + * \copydoc RemoveGCEpilogueCallback(GCCallback) + * + * \param data Additional data that was used to install the callback. + */ + void RemoveGCEpilogueCallback(GCCallbackWithData callback, + void* data = nullptr); + /** * Sets an embedder roots handle that V8 should consider when performing * non-unified heap garbage collections. The intended use case is for setting @@ -1036,28 +1093,6 @@ class V8_EXPORT Isolate { */ void SetAtomicsWaitCallback(AtomicsWaitCallback callback, void* data); - /** - * Enables the host application to receive a notification after a - * garbage collection. Allocations are allowed in the callback function, - * but the callback is not re-entrant: if the allocation inside it will - * trigger the garbage collection, the callback won't be called again. - * It is possible to specify the GCType filter for your callback. But it is - * not possible to register the same callback function two times with - * different GCType filters. - */ - void AddGCEpilogueCallback(GCCallbackWithData callback, void* data = nullptr, - GCType gc_type_filter = kGCTypeAll); - void AddGCEpilogueCallback(GCCallback callback, - GCType gc_type_filter = kGCTypeAll); - - /** - * This function removes callback which was installed by - * AddGCEpilogueCallback function. - */ - void RemoveGCEpilogueCallback(GCCallbackWithData callback, - void* data = nullptr); - void RemoveGCEpilogueCallback(GCCallback callback); - using GetExternallyAllocatedMemoryInBytesCallback = size_t (*)(); /** @@ -1325,20 +1360,6 @@ class V8_EXPORT Isolate { */ void IsolateInBackgroundNotification(); - /** - * Optional notification which will enable the memory savings mode. - * V8 uses this notification to guide heuristics which may result in a - * smaller memory footprint at the cost of reduced runtime performance. - */ - V8_DEPRECATED("Use IsolateInBackgroundNotification() instead") - void EnableMemorySavingsMode(); - - /** - * Optional notification which will disable the memory savings mode. - */ - V8_DEPRECATED("Use IsolateInBackgroundNotification() instead") - void DisableMemorySavingsMode(); - /** * Optional notification to tell V8 the current performance requirements * of the embedder based on RAIL. @@ -1511,12 +1532,15 @@ class V8_EXPORT Isolate { void SetWasmLoadSourceMapCallback(WasmLoadSourceMapCallback callback); /** - * Register callback to control whehter Wasm GC is enabled. + * Register callback to control whether Wasm GC is enabled. * The callback overwrites the value of the flag. * If the callback returns true, it will also enable Wasm stringrefs. */ void SetWasmGCEnabledCallback(WasmGCEnabledCallback callback); + void SetWasmImportedStringsEnabledCallback( + WasmImportedStringsEnabledCallback callback); + void SetSharedArrayBufferConstructorEnabledCallback( SharedArrayBufferConstructorEnabledCallback callback); @@ -1588,6 +1612,7 @@ class V8_EXPORT Isolate { * heap. GC is not invoked prior to iterating, therefore there is no * guarantee that visited objects are still alive. */ + V8_DEPRECATE_SOON("Will be removed without replacement. crbug.com/v8/14172") void VisitExternalResources(ExternalResourceVisitor* visitor); /** @@ -1680,7 +1705,8 @@ template MaybeLocal Isolate::GetDataFromSnapshotOnce(size_t index) { auto slot = GetDataFromSnapshotOnce(index); if (slot) { - internal::PerformCastCheck(internal::ValueHelper::SlotAsValue(slot)); + internal::PerformCastCheck( + internal::ValueHelper::SlotAsValue(slot)); } return Local::FromSlot(slot); } diff --git a/v8_c_api/src/v8include/v8-local-handle.h b/v8_c_api/src/v8include/v8-local-handle.h index 9c28be2..fab4a59 100644 --- a/v8_c_api/src/v8include/v8-local-handle.h +++ b/v8_c_api/src/v8include/v8-local-handle.h @@ -382,6 +382,12 @@ class Local : public LocalBase { return Local(LocalBase::FromSlot(slot)); } +#ifdef V8_ENABLE_DIRECT_LOCAL + V8_INLINE static Local FromAddress(internal::Address ptr) { + return Local(LocalBase(ptr)); + } +#endif // V8_ENABLE_DIRECT_LOCAL + V8_INLINE static Local New(Isolate* isolate, internal::Address value) { return Local(LocalBase::New(isolate, value)); } diff --git a/v8_c_api/src/v8include/v8-platform.h b/v8_c_api/src/v8include/v8-platform.h index 9811c6e..0d82f4b 100644 --- a/v8_c_api/src/v8include/v8-platform.h +++ b/v8_c_api/src/v8include/v8-platform.h @@ -40,6 +40,7 @@ enum class TaskPriority : uint8_t { * possible. */ kUserBlocking, + kMaxPriority = kUserBlocking }; /** @@ -597,6 +598,14 @@ class ThreadIsolatedAllocator { * Return the pkey used to implement the thread isolation if Type == kPkey. */ virtual int Pkey() const { return -1; } + + /** + * Per-thread permissions can be reset on signal handler entry. Even reading + * ThreadIsolated memory will segfault in that case. + * Call this function on signal handler entry to ensure that read permissions + * are restored. + */ + static void SetDefaultPermissionsForSignalHandler(); }; // Opaque type representing a handle to a shared memory region. @@ -1043,9 +1052,24 @@ class Platform { * Returns a TaskRunner which can be used to post a task on the foreground. * The TaskRunner's NonNestableTasksEnabled() must be true. This function * should only be called from a foreground thread. + * TODO(chromium:1448758): Deprecate once |GetForegroundTaskRunner(Isolate*, + * TaskPriority)| is ready. + */ + virtual std::shared_ptr GetForegroundTaskRunner( + Isolate* isolate) { + return GetForegroundTaskRunner(isolate, TaskPriority::kUserBlocking); + } + + /** + * Returns a TaskRunner with a specific |priority| which can be used to post a + * task on the foreground thread. The TaskRunner's NonNestableTasksEnabled() + * must be true. This function should only be called from a foreground thread. + * TODO(chromium:1448758): Make pure virtual once embedders implement it. */ virtual std::shared_ptr GetForegroundTaskRunner( - Isolate* isolate) = 0; + Isolate* isolate, TaskPriority priority) { + return nullptr; + } /** * Schedules a task to be invoked on a worker thread. @@ -1070,7 +1094,8 @@ class Platform { virtual void CallBlockingTaskOnWorkerThread(std::unique_ptr task) { // Embedders may optionally override this to process these tasks in a high // priority pool. - CallOnWorkerThread(std::move(task)); + PostTaskOnWorkerThreadImpl(TaskPriority::kUserBlocking, std::move(task), + SourceLocation::Current()); } /** @@ -1083,7 +1108,8 @@ class Platform { virtual void CallLowPriorityTaskOnWorkerThread(std::unique_ptr task) { // Embedders may optionally override this to process these tasks in a low // priority pool. - CallOnWorkerThread(std::move(task)); + PostTaskOnWorkerThreadImpl(TaskPriority::kBestEffort, std::move(task), + SourceLocation::Current()); } /** @@ -1276,7 +1302,9 @@ class Platform { */ virtual void PostTaskOnWorkerThreadImpl(TaskPriority priority, std::unique_ptr task, - const SourceLocation& location) {} + const SourceLocation& location) { + CallOnWorkerThread(std::move(task)); + } /** * Schedules a task with |priority| to be invoked on a worker thread after diff --git a/v8_c_api/src/v8include/v8-primitive.h b/v8_c_api/src/v8include/v8-primitive.h index 80ebe94..eb0a791 100644 --- a/v8_c_api/src/v8include/v8-primitive.h +++ b/v8_c_api/src/v8include/v8-primitive.h @@ -638,10 +638,20 @@ class V8_EXPORT Symbol : public Name { static void CheckCast(Data* that); }; +/** + * A JavaScript numeric value (either Number or BigInt). + * https://tc39.es/ecma262/#sec-numeric-types + */ +class V8_EXPORT Numeric : public Primitive { + private: + Numeric(); + static void CheckCast(v8::Data* that); +}; + /** * A JavaScript number value (ECMA-262, 4.3.20) */ -class V8_EXPORT Number : public Primitive { +class V8_EXPORT Number : public Numeric { public: double Value() const; static Local New(Isolate* isolate, double value); @@ -716,7 +726,7 @@ class V8_EXPORT Uint32 : public Integer { /** * A JavaScript BigInt value (https://tc39.github.io/proposal-bigint) */ -class V8_EXPORT BigInt : public Primitive { +class V8_EXPORT BigInt : public Numeric { public: static Local New(Isolate* isolate, int64_t value); static Local NewFromUnsigned(Isolate* isolate, uint64_t value); diff --git a/v8_c_api/src/v8include/v8-script.h b/v8_c_api/src/v8include/v8-script.h index bca7897..2b45518 100644 --- a/v8_c_api/src/v8include/v8-script.h +++ b/v8_c_api/src/v8include/v8-script.h @@ -143,10 +143,9 @@ class V8_EXPORT ModuleRequest : public Data { * * All assertions present in the module request will be supplied in this * list, regardless of whether they are supported by the host. Per - * https://tc39.es/proposal-import-assertions/#sec-hostgetsupportedimportassertions, - * hosts are expected to ignore assertions that they do not support (as - * opposed to, for example, triggering an error if an unsupported assertion is - * present). + * https://tc39.es/proposal-import-attributes/#sec-hostgetsupportedimportattributes, + * hosts are expected to throw for assertions that they do not support (as + * opposed to, for example, ignoring them). */ Local GetImportAssertions() const; diff --git a/v8_c_api/src/v8include/v8-statistics.h b/v8_c_api/src/v8include/v8-statistics.h index ca20bc9..0b76117 100644 --- a/v8_c_api/src/v8include/v8-statistics.h +++ b/v8_c_api/src/v8include/v8-statistics.h @@ -46,6 +46,10 @@ enum class MeasureMemoryExecution { kDefault, kEager, kLazy }; * * It specifies the contexts that need to be measured and gets called when * the measurement is completed to report the results. + * + * Both MeasurementComplete() callbacks will be invoked on completion. + * Each implementation of this class should hence implement only one of them, + * and leave the other empty. */ class V8_EXPORT MeasureMemoryDelegate { public: @@ -66,10 +70,41 @@ class V8_EXPORT MeasureMemoryDelegate { * \param unattributed_size_in_bytes total size of objects that were not * attributed to any context (i.e. are likely shared objects). */ + V8_DEPRECATE_SOON("Please use the version that takes a result struct") virtual void MeasurementComplete( const std::vector, size_t>>& context_sizes_in_bytes, - size_t unattributed_size_in_bytes) = 0; + size_t unattributed_size_in_bytes) {} + + /** Holds the result of a memory measurement request. */ + struct Result { + /** + * a vector of (context, size) pairs that includes each context for + * which ShouldMeasure returned true and that was not garbage collected + * while the memory measurement was in progress. + */ + const std::vector, size_t>>& + context_sizes_in_bytes; + + /** + * total size of objects that were not attributed to any context (i.e. are + * likely shared objects). + */ + size_t unattributed_size_in_bytes; + + /** total size of generated code for Wasm (shared across contexts). */ + size_t wasm_code_size_in_bytes; + + /** total size of Wasm metadata (except code; shared across contexts). */ + size_t wasm_metadata_size_in_bytes; + }; + + /** + * This function is called when memory measurement finishes. + * + * \param result the result of the measurement. + */ + virtual void MeasurementComplete(Result result) {} /** * Returns a default delegate that resolves the given promise when diff --git a/v8_c_api/src/v8include/v8-value.h b/v8_c_api/src/v8include/v8-value.h index c80ae06..19ecf71 100644 --- a/v8_c_api/src/v8include/v8-value.h +++ b/v8_c_api/src/v8include/v8-value.h @@ -16,6 +16,8 @@ */ namespace v8 { +class Primiitive; +class Numeric; class BigInt; class Int32; class Integer; @@ -354,6 +356,18 @@ class V8_EXPORT Value : public Data { */ bool IsModuleNamespaceObject() const; + /** + * Perform `ToPrimitive(value)` as specified in: + * https://tc39.es/ecma262/#sec-toprimitive. + */ + V8_WARN_UNUSED_RESULT MaybeLocal ToPrimitive( + Local context) const; + /** + * Perform `ToNumeric(value)` as specified in: + * https://tc39.es/ecma262/#sec-tonumeric. + */ + V8_WARN_UNUSED_RESULT MaybeLocal ToNumeric( + Local context) const; /** * Perform the equivalent of `BigInt(value)` in JS. */ diff --git a/v8_c_api/src/v8include/v8-version.h b/v8_c_api/src/v8include/v8-version.h index b42f136..8255fbf 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 6 -#define V8_BUILD_NUMBER 189 -#define V8_PATCH_LEVEL 20 +#define V8_MINOR_VERSION 7 +#define V8_BUILD_NUMBER 439 +#define V8_PATCH_LEVEL 17 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.)