diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e43b0f98 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/android/Android.mk b/android/Android.mk index dc854aea..c0d8d081 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -78,30 +78,6 @@ LOCAL_EXPORT_CPPFLAGS := -D__STDC_LIMIT_MACROS=1 include $(PREBUILT_STATIC_LIBRARY) -#====================================== -include $(CLEAR_VARS) -LOCAL_MODULE := v8_libbase -LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/v8/libv8_libbase.a -include $(PREBUILT_STATIC_LIBRARY) - -#====================================== -include $(CLEAR_VARS) -LOCAL_MODULE := v8_libplatform -LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/v8/libv8_libplatform.a -include $(PREBUILT_STATIC_LIBRARY) - -#====================================== -include $(CLEAR_VARS) -LOCAL_MODULE := v8_libsampler -LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/v8/libv8_libsampler.a -include $(PREBUILT_STATIC_LIBRARY) - -#====================================== -include $(CLEAR_VARS) -LOCAL_MODULE := v8_snapshot -LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/v8/libv8_snapshot.a -include $(PREBUILT_STATIC_LIBRARY) - #====================================== include $(CLEAR_VARS) LOCAL_MODULE := v8_inspector @@ -110,18 +86,13 @@ include $(PREBUILT_STATIC_LIBRARY) #====================================== include $(CLEAR_VARS) -LOCAL_MODULE := v8_compiler -LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/v8/libv8_compiler.a -include $(PREBUILT_STATIC_LIBRARY) - -#====================================== -include $(CLEAR_VARS) - LOCAL_MODULE := v8_static -LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/v8/libv8_base_without_compiler.a +LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/v8/libv8_monolith.a LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(TARGET_ARCH_ABI)/include/v8 -LOCAL_WHOLE_STATIC_LIBRARIES += v8_libbase v8_libplatform v8_libsampler v8_snapshot v8_compiler - +ifeq ($(TARGET_ARCH),arm64) + LOCAL_EXPORT_CPPFLAGS := -DV8_COMPRESS_POINTERS + LOCAL_EXPORT_CFLAGS := -DV8_COMPRESS_POINTERS +endif include $(PREBUILT_STATIC_LIBRARY) #====================================== diff --git a/android/arm64-v8a/include/v8/APIDesign.md b/android/arm64-v8a/include/v8/APIDesign.md index 8830fff7..fe42c8ed 100644 --- a/android/arm64-v8a/include/v8/APIDesign.md +++ b/android/arm64-v8a/include/v8/APIDesign.md @@ -67,3 +67,6 @@ which in turn guarantees long-term stability of the API. # The V8 inspector All debugging capabilities of V8 should be exposed via the inspector protocol. +The exception to this are profiling features exposed via v8-profiler.h. +Changes to the inspector protocol need to ensure backwards compatibility and +commitment to maintain. diff --git a/android/arm64-v8a/include/v8/OWNERS b/android/arm64-v8a/include/v8/OWNERS index 7953cfe1..1e0794df 100644 --- a/android/arm64-v8a/include/v8/OWNERS +++ b/android/arm64-v8a/include/v8/OWNERS @@ -1,16 +1,18 @@ -set noparent - adamk@chromium.org danno@chromium.org ulan@chromium.org +verwaest@chromium.org yangguo@chromium.org -per-file v8-internal.h=file://OWNERS +per-file *DEPS=file:../COMMON_OWNERS +per-file v8-internal.h=file:../COMMON_OWNERS per-file v8-inspector.h=dgozman@chromium.org per-file v8-inspector.h=pfeldman@chromium.org per-file v8-inspector.h=kozyatinskiy@chromium.org per-file v8-inspector-protocol.h=dgozman@chromium.org per-file v8-inspector-protocol.h=pfeldman@chromium.org per-file v8-inspector-protocol.h=kozyatinskiy@chromium.org +per-file js_protocol.pdl=dgozman@chromium.org +per-file js_protocol.pdl=pfeldman@chromium.org # COMPONENT: Blink>JavaScript>API diff --git a/android/arm64-v8a/include/v8/libplatform/libplatform.h b/android/arm64-v8a/include/v8/libplatform/libplatform.h index 6908aeaa..18d585d6 100644 --- a/android/arm64-v8a/include/v8/libplatform/libplatform.h +++ b/android/arm64-v8a/include/v8/libplatform/libplatform.h @@ -5,6 +5,8 @@ #ifndef V8_LIBPLATFORM_LIBPLATFORM_H_ #define V8_LIBPLATFORM_LIBPLATFORM_H_ +#include + #include "libplatform/libplatform-export.h" #include "libplatform/v8-tracing.h" #include "v8-platform.h" // NOLINT(build/include) @@ -70,11 +72,10 @@ V8_PLATFORM_EXPORT void RunIdleTasks(v8::Platform* platform, * The |platform| has to be created using |NewDefaultPlatform|. * */ -V8_PLATFORM_EXPORT V8_DEPRECATE_SOON( - "Access the DefaultPlatform directly", - void SetTracingController( - v8::Platform* platform, - v8::platform::tracing::TracingController* tracing_controller)); +V8_DEPRECATE_SOON("Access the DefaultPlatform directly") +V8_PLATFORM_EXPORT void SetTracingController( + v8::Platform* platform, + v8::platform::tracing::TracingController* tracing_controller); } // namespace platform } // namespace v8 diff --git a/android/arm64-v8a/include/v8/libplatform/v8-tracing.h b/android/arm64-v8a/include/v8/libplatform/v8-tracing.h index bc249cb9..79e6f62d 100644 --- a/android/arm64-v8a/include/v8/libplatform/v8-tracing.h +++ b/android/arm64-v8a/include/v8/libplatform/v8-tracing.h @@ -14,6 +14,10 @@ #include "libplatform/libplatform-export.h" #include "v8-platform.h" // NOLINT(build/include) +namespace perfetto { +class TracingSession; +} + namespace v8 { namespace base { @@ -23,12 +27,15 @@ class Mutex; namespace platform { namespace tracing { +class TraceEventListener; +class JSONTraceEventListener; + const int kTraceMaxNumArgs = 2; class V8_PLATFORM_EXPORT TraceObject { public: union ArgValue { - bool as_bool; + V8_DEPRECATED("use as_uint ? true : false") bool as_bool; uint64_t as_uint; int64_t as_int; double as_double; @@ -237,7 +244,17 @@ class V8_PLATFORM_EXPORT TracingController TracingController(); ~TracingController() override; + + // Takes ownership of |trace_buffer|. void Initialize(TraceBuffer* trace_buffer); +#ifdef V8_USE_PERFETTO + // Must be called before StartTracing() if V8_USE_PERFETTO is true. Provides + // the output stream for the JSON trace data. + void InitializeForPerfetto(std::ostream* output_stream); + // Provide an optional listener for testing that will receive trace events. + // Must be called before StartTracing(). + void SetTraceEventListenerForTesting(TraceEventListener* listener); +#endif // v8::TracingController implementation. const uint8_t* GetCategoryGroupEnabled(const char* category_group) override; @@ -280,6 +297,12 @@ class V8_PLATFORM_EXPORT TracingController std::unique_ptr mutex_; std::unordered_set observers_; std::atomic_bool recording_{false}; +#ifdef V8_USE_PERFETTO + std::ostream* output_stream_ = nullptr; + std::unique_ptr json_listener_; + TraceEventListener* listener_for_testing_ = nullptr; + std::unique_ptr tracing_session_; +#endif // Disallow copy and assign TracingController(const TracingController&) = delete; diff --git a/android/arm64-v8a/include/v8/v8-inspector.h b/android/arm64-v8a/include/v8/v8-inspector.h index 70201358..3ec13256 100644 --- a/android/arm64-v8a/include/v8/v8-inspector.h +++ b/android/arm64-v8a/include/v8/v8-inspector.h @@ -9,6 +9,7 @@ #include #include +#include #include "v8.h" // NOLINT(build/include) @@ -24,6 +25,7 @@ namespace Runtime { namespace API { class RemoteObject; class StackTrace; +class StackTraceId; } } namespace Schema { @@ -87,7 +89,6 @@ class V8_EXPORT V8ContextInfo { static int executionContextId(v8::Local context); - private: // Disallow copying and allocating this one. enum NotNullTagEnum { NotNullLiteral }; void* operator new(size_t) = delete; @@ -110,6 +111,8 @@ class V8_EXPORT V8StackTrace { virtual ~V8StackTrace() = default; virtual std::unique_ptr buildInspectorObject() const = 0; + virtual std::unique_ptr + buildInspectorObject(int maxAsyncDepth) const = 0; virtual std::unique_ptr toString() const = 0; // Safe to pass between threads, drops async chain. @@ -131,7 +134,7 @@ class V8_EXPORT V8InspectorSession { // Dispatching protocol messages. static bool canDispatchMethod(const StringView& method); virtual void dispatchProtocolMessage(const StringView& message) = 0; - virtual std::unique_ptr stateJSON() = 0; + virtual std::vector state() = 0; virtual std::vector> supportedDomains() = 0; @@ -228,12 +231,20 @@ class V8_EXPORT V8InspectorClient { struct V8_EXPORT V8StackTraceId { uintptr_t id; std::pair debugger_id; + bool should_pause = false; V8StackTraceId(); + V8StackTraceId(const V8StackTraceId&) = default; V8StackTraceId(uintptr_t id, const std::pair debugger_id); + V8StackTraceId(uintptr_t id, const std::pair debugger_id, + bool should_pause); + explicit V8StackTraceId(const StringView&); + V8StackTraceId& operator=(const V8StackTraceId&) = default; + V8StackTraceId& operator=(V8StackTraceId&&) noexcept = default; ~V8StackTraceId() = default; bool IsInvalid() const; + std::unique_ptr ToString(); }; class V8_EXPORT V8Inspector { @@ -289,6 +300,24 @@ class V8_EXPORT V8Inspector { virtual std::unique_ptr createStackTrace( v8::Local) = 0; virtual std::unique_ptr captureStackTrace(bool fullStack) = 0; + + // Performance counters. + class V8_EXPORT Counters : public std::enable_shared_from_this { + public: + explicit Counters(v8::Isolate* isolate); + ~Counters(); + const std::unordered_map& getCountersMap() const { + return m_countersMap; + } + + private: + static int* getCounterPtr(const char* name); + + v8::Isolate* m_isolate; + std::unordered_map m_countersMap; + }; + + virtual std::shared_ptr enableCounters() = 0; }; } // namespace v8_inspector diff --git a/android/arm64-v8a/include/v8/v8-internal.h b/android/arm64-v8a/include/v8/v8-internal.h index 8e700a4d..ee363382 100644 --- a/android/arm64-v8a/include/v8/v8-internal.h +++ b/android/arm64-v8a/include/v8/v8-internal.h @@ -48,28 +48,32 @@ const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1; template struct SmiTagging; +constexpr intptr_t kIntptrAllBitsSet = intptr_t{-1}; +constexpr uintptr_t kUintptrAllBitsSet = + static_cast(kIntptrAllBitsSet); + // Smi constants for systems where tagged pointer is a 32-bit value. template <> struct SmiTagging<4> { enum { kSmiShiftSize = 0, kSmiValueSize = 31 }; + + static constexpr intptr_t kSmiMinValue = + static_cast(kUintptrAllBitsSet << (kSmiValueSize - 1)); + static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1); + V8_INLINE static int SmiToInt(const internal::Address value) { int shift_bits = kSmiTagSize + kSmiShiftSize; - // Shift down (requires >> to be sign extending). - return static_cast(static_cast(value)) >> shift_bits; + // Truncate and shift down (requires >> to be sign extending). + return static_cast(static_cast(value)) >> shift_bits; } V8_INLINE static constexpr bool IsValidSmi(intptr_t value) { - // To be representable as an tagged small integer, the two - // most-significant bits of 'value' must be either 00 or 11 due to - // sign-extension. To check this we add 01 to the two - // most-significant bits, and check if the most-significant bit is 0. - // - // CAUTION: The original code below: - // bool result = ((value + 0x40000000) & 0x80000000) == 0; - // may lead to incorrect results according to the C language spec, and - // in fact doesn't work correctly with gcc4.1.1 in some cases: The - // compiler may produce undefined results in case of signed integer - // overflow. The computation must be done w/ unsigned ints. - return static_cast(value) + 0x40000000U < 0x80000000U; + // Is value in range [kSmiMinValue, kSmiMaxValue]. + // Use unsigned operations in order to avoid undefined behaviour in case of + // signed integer overflow. + return (static_cast(value) - + static_cast(kSmiMinValue)) <= + (static_cast(kSmiMaxValue) - + static_cast(kSmiMinValue)); } }; @@ -77,6 +81,11 @@ struct SmiTagging<4> { template <> struct SmiTagging<8> { enum { kSmiShiftSize = 31, kSmiValueSize = 32 }; + + static constexpr intptr_t kSmiMinValue = + static_cast(kUintptrAllBitsSet << (kSmiValueSize - 1)); + static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1); + V8_INLINE static int SmiToInt(const internal::Address value) { int shift_bits = kSmiTagSize + kSmiShiftSize; // Shift down and throw away top 32 bits. @@ -98,15 +107,17 @@ const int kApiTaggedSize = kApiSystemPointerSize; #endif #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH -typedef SmiTagging PlatformSmiTagging; +using PlatformSmiTagging = SmiTagging; #else -typedef SmiTagging PlatformSmiTagging; +using PlatformSmiTagging = SmiTagging; #endif +// TODO(ishell): Consinder adding kSmiShiftBits = kSmiShiftSize + kSmiTagSize +// since it's used much more often than the inividual constants. const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize; const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize; -const int kSmiMinValue = (static_cast(-1)) << (kSmiValueSize - 1); -const int kSmiMaxValue = -(kSmiMinValue + 1); +const int kSmiMinValue = static_cast(PlatformSmiTagging::kSmiMinValue); +const int kSmiMaxValue = static_cast(PlatformSmiTagging::kSmiMaxValue); constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; } constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; } @@ -135,7 +146,7 @@ class Internals { static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize; static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize; static const int kEmbedderDataSlotSize = kApiSystemPointerSize; - static const int kNativeContextEmbedderDataOffset = 7 * kApiTaggedSize; + static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize; static const int kFullStringRepresentationMask = 0x0f; static const int kStringEncodingMask = 0x8; static const int kExternalTwoByteRepresentationTag = 0x02; @@ -143,6 +154,7 @@ class Internals { static const uint32_t kNumIsolateDataSlots = 4; + // IsolateData layout guarantees. static const int kIsolateEmbedderDataOffset = 0; static const int kExternalMemoryOffset = kNumIsolateDataSlots * kApiSystemPointerSize; @@ -150,8 +162,14 @@ class Internals { kExternalMemoryOffset + kApiInt64Size; static const int kExternalMemoryAtLastMarkCompactOffset = kExternalMemoryLimitOffset + kApiInt64Size; - static const int kIsolateRootsOffset = + static const int kIsolateFastCCallCallerFpOffset = kExternalMemoryAtLastMarkCompactOffset + kApiInt64Size; + static const int kIsolateFastCCallCallerPcOffset = + kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize; + static const int kIsolateStackGuardOffset = + kIsolateFastCCallCallerPcOffset + kApiSystemPointerSize; + static const int kIsolateRootsOffset = + kIsolateStackGuardOffset + 7 * kApiSystemPointerSize; static const int kUndefinedValueRootIndex = 4; static const int kTheHoleValueRootIndex = 5; @@ -165,12 +183,10 @@ class Internals { static const int kNodeStateMask = 0x7; static const int kNodeStateIsWeakValue = 2; static const int kNodeStateIsPendingValue = 3; - static const int kNodeIsIndependentShift = 3; - static const int kNodeIsActiveShift = 4; static const int kFirstNonstringType = 0x40; static const int kOddballType = 0x43; - static const int kForeignType = 0x47; + static const int kForeignType = 0x46; static const int kJSSpecialApiObjectType = 0x410; static const int kJSApiObjectType = 0x420; static const int kJSObjectType = 0x421; @@ -313,14 +329,11 @@ class Internals { #ifdef V8_COMPRESS_POINTERS // See v8:7703 or src/ptr-compr.* for details about pointer compression. static constexpr size_t kPtrComprHeapReservationSize = size_t{1} << 32; - static constexpr size_t kPtrComprIsolateRootBias = - kPtrComprHeapReservationSize / 2; static constexpr size_t kPtrComprIsolateRootAlignment = size_t{1} << 32; V8_INLINE static internal::Address GetRootFromOnHeapAddress( internal::Address addr) { - return (addr + kPtrComprIsolateRootBias) & - -static_cast(kPtrComprIsolateRootAlignment); + return addr & -static_cast(kPtrComprIsolateRootAlignment); } V8_INLINE static internal::Address DecompressTaggedAnyField( @@ -367,6 +380,10 @@ V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj); // language mode is strict. V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate); +// A base class for backing stores, which is needed due to vagaries of +// how static casts work with std::shared_ptr. +class BackingStoreBase {}; + } // namespace internal } // namespace v8 diff --git a/android/arm64-v8a/include/v8/v8-platform.h b/android/arm64-v8a/include/v8/v8-platform.h index 556407d8..534d73e3 100644 --- a/android/arm64-v8a/include/v8/v8-platform.h +++ b/android/arm64-v8a/include/v8/v8-platform.h @@ -109,7 +109,6 @@ class TaskRunner { TaskRunner() = default; virtual ~TaskRunner() = default; - private: TaskRunner(const TaskRunner&) = delete; TaskRunner& operator=(const TaskRunner&) = delete; }; @@ -368,9 +367,8 @@ class Platform { * |isolate|. Tasks posted for the same isolate should be execute in order of * scheduling. The definition of "foreground" is opaque to V8. */ - V8_DEPRECATE_SOON( - "Use a taskrunner acquired by GetForegroundTaskRunner instead.", - virtual void CallOnForegroundThread(Isolate* isolate, Task* task)) = 0; + V8_DEPRECATED("Use a taskrunner acquired by GetForegroundTaskRunner instead.") + virtual void CallOnForegroundThread(Isolate* isolate, Task* task) { abort(); } /** * Schedules a task to be invoked on a foreground thread wrt a specific @@ -378,10 +376,11 @@ class Platform { * Tasks posted for the same isolate should be execute in order of * scheduling. The definition of "foreground" is opaque to V8. */ - V8_DEPRECATE_SOON( - "Use a taskrunner acquired by GetForegroundTaskRunner instead.", - virtual void CallDelayedOnForegroundThread(Isolate* isolate, Task* task, - double delay_in_seconds)) = 0; + V8_DEPRECATED("Use a taskrunner acquired by GetForegroundTaskRunner instead.") + virtual void CallDelayedOnForegroundThread(Isolate* isolate, Task* task, + double delay_in_seconds) { + abort(); + } /** * Schedules a task to be invoked on a foreground thread wrt a specific @@ -391,20 +390,15 @@ class Platform { * starved for an arbitrarily long time if no idle time is available. * The definition of "foreground" is opaque to V8. */ - V8_DEPRECATE_SOON( - "Use a taskrunner acquired by GetForegroundTaskRunner instead.", - virtual void CallIdleOnForegroundThread(Isolate* isolate, - IdleTask* task)) { - // This must be overriden if |IdleTasksEnabled()|. + V8_DEPRECATED("Use a taskrunner acquired by GetForegroundTaskRunner instead.") + virtual void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) { abort(); } /** * Returns true if idle tasks are enabled for the given |isolate|. */ - virtual bool IdleTasksEnabled(Isolate* isolate) { - return false; - } + virtual bool IdleTasksEnabled(Isolate* isolate) { return false; } /** * Monotonically increasing time in seconds from an arbitrary fixed point in diff --git a/android/arm64-v8a/include/v8/v8-profiler.h b/android/arm64-v8a/include/v8/v8-profiler.h index 672a694e..767973c4 100644 --- a/android/arm64-v8a/include/v8/v8-profiler.h +++ b/android/arm64-v8a/include/v8/v8-profiler.h @@ -5,8 +5,11 @@ #ifndef V8_V8_PROFILER_H_ #define V8_V8_PROFILER_H_ +#include +#include #include #include + #include "v8.h" // NOLINT(build/include) /** @@ -17,14 +20,18 @@ namespace v8 { class HeapGraphNode; struct HeapStatsUpdate; -typedef uint32_t SnapshotObjectId; - +using NativeObject = void*; +using SnapshotObjectId = uint32_t; struct CpuProfileDeoptFrame { int script_id; size_t position; }; +namespace internal { +class CpuProfile; +} // namespace internal + } // namespace v8 #ifdef V8_OS_WIN @@ -47,75 +54,6 @@ template class V8_EXPORT std::vector; namespace v8 { -// TickSample captures the information collected for each sample. -struct V8_EXPORT TickSample { - // Internal profiling (with --prof + tools/$OS-tick-processor) wants to - // include the runtime function we're calling. Externally exposed tick - // samples don't care. - enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame }; - - TickSample() - : state(OTHER), - pc(nullptr), - external_callback_entry(nullptr), - frames_count(0), - has_external_callback(false), - update_stats(true) {} - - /** - * Initialize a tick sample from the isolate. - * \param isolate The isolate. - * \param state Execution state. - * \param record_c_entry_frame Include or skip the runtime function. - * \param update_stats Whether update the sample to the aggregated stats. - * \param use_simulator_reg_state When set to true and V8 is running under a - * simulator, the method will use the simulator - * register state rather than the one provided - * with |state| argument. Otherwise the method - * will use provided register |state| as is. - */ - void Init(Isolate* isolate, const v8::RegisterState& state, - RecordCEntryFrame record_c_entry_frame, bool update_stats, - bool use_simulator_reg_state = true); - /** - * Get a call stack sample from the isolate. - * \param isolate The isolate. - * \param state Register state. - * \param record_c_entry_frame Include or skip the runtime function. - * \param frames Caller allocated buffer to store stack frames. - * \param frames_limit Maximum number of frames to capture. The buffer must - * be large enough to hold the number of frames. - * \param sample_info The sample info is filled up by the function - * provides number of actual captured stack frames and - * the current VM state. - * \param use_simulator_reg_state When set to true and V8 is running under a - * simulator, the method will use the simulator - * register state rather than the one provided - * with |state| argument. Otherwise the method - * will use provided register |state| as is. - * \note GetStackSample is thread and signal safe and should only be called - * when the JS thread is paused or interrupted. - * Otherwise the behavior is undefined. - */ - static bool GetStackSample(Isolate* isolate, v8::RegisterState* state, - RecordCEntryFrame record_c_entry_frame, - void** frames, size_t frames_limit, - v8::SampleInfo* sample_info, - bool use_simulator_reg_state = true); - StateTag state; // The state of the VM. - void* pc; // Instruction pointer. - union { - void* tos; // Top stack value (*sp). - void* external_callback_entry; - }; - static const unsigned kMaxFramesCountLog2 = 8; - static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1; - void* stack[kMaxFramesCount]; // Call stack. - unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames. - bool has_external_callback : 1; - bool update_stats : 1; // Whether the sample should update aggregated stats. -}; - /** * CpuProfileNode represents a node in a call graph. */ @@ -206,11 +144,6 @@ class V8_EXPORT CpuProfileNode { */ unsigned GetHitCount() const; - /** Returns function entry UID. */ - V8_DEPRECATE_SOON( - "Use GetScriptId, GetLineNumber, and GetColumnNumber instead.", - unsigned GetCallUid() const); - /** Returns id of the node. The id is unique within the tree */ unsigned GetNodeId() const; @@ -297,6 +230,66 @@ enum CpuProfilingMode { kCallerLineNumbers, }; +// Determines how names are derived for functions sampled. +enum CpuProfilingNamingMode { + // Use the immediate name of functions at compilation time. + kStandardNaming, + // Use more verbose naming for functions without names, inferred from scope + // where possible. + kDebugNaming, +}; + +enum CpuProfilingLoggingMode { + // Enables logging when a profile is active, and disables logging when all + // profiles are detached. + kLazyLogging, + // Enables logging for the lifetime of the CpuProfiler. Calls to + // StartRecording are faster, at the expense of runtime overhead. + kEagerLogging, +}; + +/** + * Optional profiling attributes. + */ +class V8_EXPORT CpuProfilingOptions { + public: + // Indicates that the sample buffer size should not be explicitly limited. + static const unsigned kNoSampleLimit = UINT_MAX; + + /** + * \param mode Type of computation of stack frame line numbers. + * \param max_samples The maximum number of samples that should be recorded by + * the profiler. Samples obtained after this limit will be + * discarded. + * \param sampling_interval_us controls the profile-specific target + * sampling interval. The provided sampling + * interval will be snapped to the next lowest + * non-zero multiple of the profiler's sampling + * interval, set via SetSamplingInterval(). If + * zero, the sampling interval will be equal to + * the profiler's sampling interval. + */ + CpuProfilingOptions( + CpuProfilingMode mode = kLeafNodeLineNumbers, + unsigned max_samples = kNoSampleLimit, int sampling_interval_us = 0, + MaybeLocal filter_context = MaybeLocal()); + + CpuProfilingMode mode() const { return mode_; } + unsigned max_samples() const { return max_samples_; } + int sampling_interval_us() const { return sampling_interval_us_; } + + private: + friend class internal::CpuProfile; + + bool has_filter_context() const { return !filter_context_.IsEmpty(); } + void* raw_filter_context() const; + + CpuProfilingMode mode_; + unsigned max_samples_; + int sampling_interval_us_; + CopyablePersistentTraits::CopyablePersistent filter_context_; +}; + /** * Interface for controlling CPU profiling. Instance of the * profiler can be created using v8::CpuProfiler::New method. @@ -308,7 +301,9 @@ class V8_EXPORT CpuProfiler { * initialized. The profiler object must be disposed after use by calling * |Dispose| method. */ - static CpuProfiler* New(Isolate* isolate); + static CpuProfiler* New(Isolate* isolate, + CpuProfilingNamingMode = kDebugNaming, + CpuProfilingLoggingMode = kLazyLogging); /** * Synchronously collect current stack sample in all profilers attached to @@ -339,18 +334,26 @@ class V8_EXPORT CpuProfiler { void SetUsePreciseSampling(bool); /** - * Starts collecting CPU profile. Title may be an empty string. It - * is allowed to have several profiles being collected at - * once. Attempts to start collecting several profiles with the same - * title are silently ignored. While collecting a profile, functions - * from all security contexts are included in it. The token-based - * filtering is only performed when querying for a profile. + * Starts collecting a CPU profile. Title may be an empty string. Several + * profiles may be collected at once. Attempts to start collecting several + * profiles with the same title are silently ignored. + */ + void StartProfiling(Local title, CpuProfilingOptions options); + + /** + * Starts profiling with the same semantics as above, except with expanded + * parameters. * * |record_samples| parameter controls whether individual samples should * be recorded in addition to the aggregated tree. + * + * |max_samples| controls the maximum number of samples that should be + * recorded by the profiler. Samples obtained after this limit will be + * discarded. */ - void StartProfiling(Local title, CpuProfilingMode mode, - bool record_samples = false); + void StartProfiling( + Local title, CpuProfilingMode mode, bool record_samples = false, + unsigned max_samples = CpuProfilingOptions::kNoSampleLimit); /** * The same as StartProfiling above, but the CpuProfilingMode defaults to * kLeafNodeLineNumbers mode, which was the previous default behavior of the @@ -364,20 +367,6 @@ class V8_EXPORT CpuProfiler { */ CpuProfile* StopProfiling(Local title); - /** - * Force collection of a sample. Must be called on the VM thread. - * Recording the forced sample does not contribute to the aggregated - * profile statistics. - */ - V8_DEPRECATED("Use static CollectSample(Isolate*) instead.", - void CollectSample()); - - /** - * Tells the profiler whether the embedder is idle. - */ - V8_DEPRECATED("Use Isolate::SetIdle(bool) instead.", - void SetIdle(bool is_idle)); - /** * Generate more detailed source positions to code objects. This results in * better results when mapping profiling samples to script source. @@ -391,7 +380,6 @@ class V8_EXPORT CpuProfiler { CpuProfiler& operator=(const CpuProfiler&); }; - /** * HeapSnapshotEdge represents a directed connection between heap * graph nodes: from retainers to retained nodes. @@ -742,7 +730,12 @@ class V8_EXPORT EmbedderGraph { */ virtual const char* NamePrefix() { return nullptr; } - private: + /** + * Returns the NativeObject that can be used for querying the + * |HeapSnapshot|. + */ + virtual NativeObject GetNativeObject() { return nullptr; } + Node(const Node&) = delete; Node& operator=(const Node&) = delete; }; @@ -805,6 +798,12 @@ class V8_EXPORT HeapProfiler { */ SnapshotObjectId GetObjectId(Local value); + /** + * Returns SnapshotObjectId for a native object referenced by |value| if it + * has been seen by the heap profiler, kUnknownObjectId otherwise. + */ + SnapshotObjectId GetObjectId(NativeObject value); + /** * Returns heap object with given SnapshotObjectId if the object is alive, * otherwise empty handle is returned. @@ -973,7 +972,8 @@ struct HeapStatsUpdate { V(LazyCompile) \ V(RegExp) \ V(Script) \ - V(Stub) + V(Stub) \ + V(Relocation) /** * Note that this enum may be extended in the future. Please include a default @@ -1006,10 +1006,12 @@ class V8_EXPORT CodeEvent { const char* GetComment(); static const char* GetCodeEventTypeName(CodeEventType code_event_type); + + uintptr_t GetPreviousCodeStartAddress(); }; /** - * Interface to listen to code creation events. + * Interface to listen to code creation and code relocation events. */ class V8_EXPORT CodeEventHandler { public: @@ -1021,9 +1023,26 @@ class V8_EXPORT CodeEventHandler { explicit CodeEventHandler(Isolate* isolate); virtual ~CodeEventHandler(); + /** + * Handle is called every time a code object is created or moved. Information + * about each code event will be available through the `code_event` + * parameter. + * + * When the CodeEventType is kRelocationType, the code for this CodeEvent has + * moved from `GetPreviousCodeStartAddress()` to `GetCodeStartAddress()`. + */ virtual void Handle(CodeEvent* code_event) = 0; + /** + * Call `Enable()` to starts listening to code creation and code relocation + * events. These events will be handled by `Handle()`. + */ void Enable(); + + /** + * Call `Disable()` to stop listening to code creation and code relocation + * events. + */ void Disable(); private: diff --git a/android/arm64-v8a/include/v8/v8-testing.h b/android/arm64-v8a/include/v8/v8-testing.h index f67bf253..3b6a9731 100644 --- a/android/arm64-v8a/include/v8/v8-testing.h +++ b/android/arm64-v8a/include/v8/v8-testing.h @@ -11,10 +11,9 @@ * Testing support for the V8 JavaScript engine. */ namespace v8 { - class V8_EXPORT Testing { public: - enum StressType { + enum V8_DEPRECATED("Don't use this (d8-specific testing logic).") StressType { kStressTypeOpt, kStressTypeDeopt }; @@ -22,27 +21,30 @@ class V8_EXPORT Testing { /** * Set the type of stressing to do. The default if not set is kStressTypeOpt. */ + V8_DEPRECATED("Don't use this (d8-specific testing logic).") static void SetStressRunType(StressType type); /** * Get the number of runs of a given test that is required to get the full * stress coverage. */ + V8_DEPRECATED("Don't use this (d8-specific testing logic).") static int GetStressRuns(); /** * Indicate the number of the run which is about to start. The value of run * should be between 0 and one less than the result from GetStressRuns() */ + V8_DEPRECATED("Don't use this (d8-specific testing logic).") static void PrepareStressRun(int run); /** * Force deoptimization of all functions. */ + V8_DEPRECATED("Don't use this (d8-specific testing logic).") static void DeoptimizeAll(Isolate* isolate); }; - } // namespace v8 #endif // V8_V8_TEST_H_ diff --git a/android/arm64-v8a/include/v8/v8-util.h b/android/arm64-v8a/include/v8/v8-util.h index 24962607..29d813e4 100644 --- a/android/arm64-v8a/include/v8/v8-util.h +++ b/android/arm64-v8a/include/v8/v8-util.h @@ -194,14 +194,6 @@ class PersistentValueMapBase { return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key)); } - /** - * Call V8::RegisterExternallyReferencedObject with the map value for given - * key. - */ - V8_DEPRECATED( - "Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference", - inline void RegisterExternallyReferencedObject(K& key)); - /** * Return value for key and remove it from the map. */ @@ -352,16 +344,6 @@ class PersistentValueMapBase { const char* label_; }; -template -inline void -PersistentValueMapBase::RegisterExternallyReferencedObject( - K& key) { - assert(Contains(key)); - V8::RegisterExternallyReferencedObject( - reinterpret_cast(FromVal(Traits::Get(&impl_, key))), - reinterpret_cast(GetIsolate())); -} - template class PersistentValueMap : public PersistentValueMapBase { public: diff --git a/android/arm64-v8a/include/v8/v8-version.h b/android/arm64-v8a/include/v8/v8-version.h index 04df4987..08ab8fd8 100644 --- a/android/arm64-v8a/include/v8/v8-version.h +++ b/android/arm64-v8a/include/v8/v8-version.h @@ -8,10 +8,10 @@ // These macros define the version number for the current version. // 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 7 -#define V8_MINOR_VERSION 5 -#define V8_BUILD_NUMBER 288 -#define V8_PATCH_LEVEL 30 +#define V8_MAJOR_VERSION 8 +#define V8_MINOR_VERSION 0 +#define V8_BUILD_NUMBER 426 +#define V8_PATCH_LEVEL 16 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/android/arm64-v8a/include/v8/v8.h b/android/arm64-v8a/include/v8/v8.h index b4b92055..692e53b8 100644 --- a/android/arm64-v8a/include/v8/v8.h +++ b/android/arm64-v8a/include/v8/v8.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -95,6 +97,10 @@ template class Global; template class TracedGlobal; +template +class TracedReference; +template +class TracedReferenceBase; template class PersistentValueMap; template class PersistentValueMapBase; @@ -122,13 +128,13 @@ class ExternalString; class Isolate; class LocalEmbedderHeapTracer; class MicrotaskQueue; -class NeverReadOnlySpaceObject; struct ScriptStreamingData; template class CustomArguments; class PropertyCallbackArguments; class FunctionCallbackArguments; class GlobalHandles; class ScopedExternalStringLock; +class ThreadLocalTop; namespace wasm { class NativeModule; @@ -280,7 +286,8 @@ class Local { V8_INLINE static Local New(Isolate* isolate, Local that); V8_INLINE static Local New(Isolate* isolate, const PersistentBase& that); - V8_INLINE static Local New(Isolate* isolate, const TracedGlobal& that); + V8_INLINE static Local New(Isolate* isolate, + const TracedReferenceBase& that); private: friend class Utils; @@ -310,7 +317,13 @@ class Local { template friend class ReturnValue; template + friend class Traced; + template friend class TracedGlobal; + template + friend class TracedReferenceBase; + template + friend class TracedReference; explicit V8_INLINE Local(T* that) : val_(that) {} V8_INLINE static Local New(Isolate* isolate, T* that); @@ -545,38 +558,6 @@ template class PersistentBase { */ V8_INLINE void AnnotateStrongRetainer(const char* label); - /** - * Allows the embedder to tell the v8 garbage collector that a certain object - * is alive. Only allowed when the embedder is asked to trace its heap by - * EmbedderHeapTracer. - */ - V8_DEPRECATED( - "Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference", - V8_INLINE void RegisterExternalReference(Isolate* isolate) const); - - /** - * Marks the reference to this object independent. Garbage collector is free - * to ignore any object groups containing this object. Weak callback for an - * independent handle should not assume that it will be preceded by a global - * GC prologue callback or followed by a global GC epilogue callback. - */ - V8_DEPRECATED( - "Weak objects are always considered independent. " - "Use TracedGlobal when trying to use EmbedderHeapTracer. " - "Use a strong handle when trying to keep an object alive.", - V8_INLINE void MarkIndependent()); - - /** - * Marks the reference to this object as active. The scavenge garbage - * collection should not reclaim the objects marked as active, even if the - * object held by the handle is otherwise unreachable. - * - * This bit is cleared after the each garbage collection pass. - */ - V8_DEPRECATED("Use TracedGlobal.", V8_INLINE void MarkActive()); - - V8_DEPRECATED("See MarkIndependent.", V8_INLINE bool IsIndependent() const); - /** Returns true if the handle's reference is weak. */ V8_INLINE bool IsWeak() const; @@ -823,57 +804,32 @@ template using UniquePersistent = Global; /** - * A traced handle with move semantics, similar to std::unique_ptr. The handle - * is to be used together with |v8::EmbedderHeapTracer| and specifies edges from - * the embedder into V8's heap. + * Deprecated. Use |TracedReference| instead. + */ +template +struct TracedGlobalTrait {}; + +/** + * A traced handle with copy and move semantics. The handle is to be used + * together with |v8::EmbedderHeapTracer| and specifies edges from the embedder + * into V8's heap. * * The exact semantics are: * - Tracing garbage collections use |v8::EmbedderHeapTracer|. * - Non-tracing garbage collections refer to * |v8::EmbedderHeapTracer::IsRootForNonTracingGC()| whether the handle should * be treated as root or not. + * + * Note that the base class cannot be instantiated itself. Choose from + * - TracedGlobal + * - TracedReference */ template -class V8_EXPORT TracedGlobal { +class TracedReferenceBase { public: /** - * An empty TracedGlobal without storage cell. - */ - TracedGlobal() = default; - ~TracedGlobal() { Reset(); } - - /** - * Construct a TracedGlobal from a Local. - * - * When the Local is non-empty, a new storage cell is created - * pointing to the same object. - */ - template - TracedGlobal(Isolate* isolate, Local that) - : val_(New(isolate, *that, &val_)) { - TYPE_CHECK(T, S); - } - - /** - * Move constructor initializing TracedGlobal from an existing one. - */ - V8_INLINE TracedGlobal(TracedGlobal&& other); - - /** - * Move assignment operator initializing TracedGlobal from an existing one. - */ - template - V8_INLINE TracedGlobal& operator=(TracedGlobal&& rhs); - - /** - * TracedGlobal only supports move semantics and forbids copying. - */ - TracedGlobal(const TracedGlobal&) = delete; - void operator=(const TracedGlobal&) = delete; - - /** - * Returns true if this TracedGlobal is empty, i.e., has not been assigned an - * object. + * Returns true if this TracedReferenceBase is empty, i.e., has not been + * assigned an object. */ bool IsEmpty() const { return val_ == nullptr; } @@ -883,27 +839,14 @@ class V8_EXPORT TracedGlobal { */ V8_INLINE void Reset(); - /** - * If non-empty, destroy the underlying storage cell and create a new one with - * the contents of other if other is non empty - */ - template - V8_INLINE void Reset(Isolate* isolate, const Local& other); - /** * Construct a Local from this handle. */ Local Get(Isolate* isolate) const { return Local::New(isolate, *this); } template - V8_INLINE TracedGlobal& As() const { - return reinterpret_cast&>( - const_cast&>(*this)); - } - - template - V8_INLINE bool operator==(const TracedGlobal& that) const { - internal::Address* a = reinterpret_cast(this->val_); + V8_INLINE bool operator==(const TracedReferenceBase& that) const { + internal::Address* a = reinterpret_cast(val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; @@ -912,7 +855,7 @@ class V8_EXPORT TracedGlobal { template V8_INLINE bool operator==(const Local& that) const { - internal::Address* a = reinterpret_cast(this->val_); + internal::Address* a = reinterpret_cast(val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; @@ -920,7 +863,7 @@ class V8_EXPORT TracedGlobal { } template - V8_INLINE bool operator!=(const TracedGlobal& that) const { + V8_INLINE bool operator!=(const TracedReferenceBase& that) const { return !operator==(that); } @@ -940,6 +883,144 @@ class V8_EXPORT TracedGlobal { */ V8_INLINE uint16_t WrapperClassId() const; + template + V8_INLINE TracedReferenceBase& As() const { + return reinterpret_cast&>( + const_cast&>(*this)); + } + + private: + enum DestructionMode { kWithDestructor, kWithoutDestructor }; + + /** + * An empty TracedReferenceBase without storage cell. + */ + TracedReferenceBase() = default; + + V8_INLINE static T* New(Isolate* isolate, T* that, void* slot, + DestructionMode destruction_mode); + + T* val_ = nullptr; + + friend class EmbedderHeapTracer; + template + friend class Local; + friend class Object; + template + friend class TracedGlobal; + template + friend class TracedReference; + template + friend class ReturnValue; +}; + +/** + * A traced handle with destructor that clears the handle. For more details see + * TracedReferenceBase. + */ +template +class TracedGlobal : public TracedReferenceBase { + public: + using TracedReferenceBase::Reset; + + /** + * Destructor resetting the handle. + */ + ~TracedGlobal() { this->Reset(); } + + /** + * An empty TracedGlobal without storage cell. + */ + TracedGlobal() : TracedReferenceBase() {} + + /** + * Construct a TracedGlobal from a Local. + * + * When the Local is non-empty, a new storage cell is created + * pointing to the same object. + */ + template + TracedGlobal(Isolate* isolate, Local that) : TracedReferenceBase() { + this->val_ = this->New(isolate, that.val_, &this->val_, + TracedReferenceBase::kWithDestructor); + TYPE_CHECK(T, S); + } + + /** + * Move constructor initializing TracedGlobal from an existing one. + */ + V8_INLINE TracedGlobal(TracedGlobal&& other) { + // Forward to operator=. + *this = std::move(other); + } + + /** + * Move constructor initializing TracedGlobal from an existing one. + */ + template + V8_INLINE TracedGlobal(TracedGlobal&& other) { + // Forward to operator=. + *this = std::move(other); + } + + /** + * Copy constructor initializing TracedGlobal from an existing one. + */ + V8_INLINE TracedGlobal(const TracedGlobal& other) { + // Forward to operator=; + *this = other; + } + + /** + * Copy constructor initializing TracedGlobal from an existing one. + */ + template + V8_INLINE TracedGlobal(const TracedGlobal& other) { + // Forward to operator=; + *this = other; + } + + /** + * Move assignment operator initializing TracedGlobal from an existing one. + */ + V8_INLINE TracedGlobal& operator=(TracedGlobal&& rhs); + + /** + * Move assignment operator initializing TracedGlobal from an existing one. + */ + template + V8_INLINE TracedGlobal& operator=(TracedGlobal&& rhs); + + /** + * Copy assignment operator initializing TracedGlobal from an existing one. + * + * Note: Prohibited when |other| has a finalization callback set through + * |SetFinalizationCallback|. + */ + V8_INLINE TracedGlobal& operator=(const TracedGlobal& rhs); + + /** + * Copy assignment operator initializing TracedGlobal from an existing one. + * + * Note: Prohibited when |other| has a finalization callback set through + * |SetFinalizationCallback|. + */ + template + V8_INLINE TracedGlobal& operator=(const TracedGlobal& rhs); + + /** + * If non-empty, destroy the underlying storage cell and create a new one with + * the contents of other if other is non empty + */ + template + V8_INLINE void Reset(Isolate* isolate, const Local& other); + + template + V8_INLINE TracedGlobal& As() const { + return reinterpret_cast&>( + const_cast&>(*this)); + } + /** * Adds a finalization callback to the handle. The type of this callback is * similar to WeakCallbackType::kInternalFields, i.e., it will pass the @@ -952,20 +1033,129 @@ class V8_EXPORT TracedGlobal { */ V8_INLINE void SetFinalizationCallback( void* parameter, WeakCallbackInfo::Callback callback); +}; - private: - V8_INLINE static T* New(Isolate* isolate, T* that, T** slot); +/** + * A traced handle without destructor that clears the handle. The embedder needs + * to ensure that the handle is not accessed once the V8 object has been + * reclaimed. This can happen when the handle is not passed through the + * EmbedderHeapTracer. For more details see TracedReferenceBase. + */ +template +class TracedReference : public TracedReferenceBase { + public: + using TracedReferenceBase::Reset; - T* operator*() const { return this->val_; } + /** + * An empty TracedReference without storage cell. + */ + TracedReference() : TracedReferenceBase() {} - T* val_ = nullptr; + /** + * Construct a TracedReference from a Local. + * + * When the Local is non-empty, a new storage cell is created + * pointing to the same object. + */ + template + TracedReference(Isolate* isolate, Local that) : TracedReferenceBase() { + this->val_ = this->New(isolate, that.val_, &this->val_, + TracedReferenceBase::kWithoutDestructor); + TYPE_CHECK(T, S); + } - friend class EmbedderHeapTracer; - template - friend class Local; - friend class Object; - template - friend class ReturnValue; + /** + * Move constructor initializing TracedReference from an + * existing one. + */ + V8_INLINE TracedReference(TracedReference&& other) { + // Forward to operator=. + *this = std::move(other); + } + + /** + * Move constructor initializing TracedReference from an + * existing one. + */ + template + V8_INLINE TracedReference(TracedReference&& other) { + // Forward to operator=. + *this = std::move(other); + } + + /** + * Copy constructor initializing TracedReference from an + * existing one. + */ + V8_INLINE TracedReference(const TracedReference& other) { + // Forward to operator=; + *this = other; + } + + /** + * Copy constructor initializing TracedReference from an + * existing one. + */ + template + V8_INLINE TracedReference(const TracedReference& other) { + // Forward to operator=; + *this = other; + } + + /** + * Move assignment operator initializing TracedGlobal from an existing one. + */ + V8_INLINE TracedReference& operator=(TracedReference&& rhs); + + /** + * Move assignment operator initializing TracedGlobal from an existing one. + */ + template + V8_INLINE TracedReference& operator=(TracedReference&& rhs); + + /** + * Copy assignment operator initializing TracedGlobal from an existing one. + * + * Note: Prohibited when |other| has a finalization callback set through + * |SetFinalizationCallback|. + */ + V8_INLINE TracedReference& operator=(const TracedReference& rhs); + + /** + * Copy assignment operator initializing TracedGlobal from an existing one. + * + * Note: Prohibited when |other| has a finalization callback set through + * |SetFinalizationCallback|. + */ + template + V8_INLINE TracedReference& operator=(const TracedReference& rhs); + + /** + * If non-empty, destroy the underlying storage cell and create a new one with + * the contents of other if other is non empty + */ + template + V8_INLINE void Reset(Isolate* isolate, const Local& other); + + template + V8_INLINE TracedReference& As() const { + return reinterpret_cast&>( + const_cast&>(*this)); + } + + /** + * Adds a finalization callback to the handle. The type of this callback is + * similar to WeakCallbackType::kInternalFields, i.e., it will pass the + * parameter and the first two internal fields of the object. + * + * The callback is then supposed to reset the handle in the callback. No + * further V8 API may be called in this callback. In case additional work + * involving V8 needs to be done, a second callback can be scheduled using + * WeakCallbackInfo::SetSecondPassCallback. + */ + V8_DEPRECATE_SOON("Use TracedGlobal<> if callbacks are required.") + V8_INLINE void SetFinalizationCallback( + void* parameter, WeakCallbackInfo::Callback callback); }; /** @@ -1099,9 +1289,8 @@ class V8_EXPORT SealHandleScope { // --- Special objects --- - /** - * The superclass of values and API object templates. + * The superclass of objects that can reside on V8's heap. */ class V8_EXPORT Data { private: @@ -1248,7 +1437,7 @@ class V8_EXPORT UnboundScript { /** * A compiled JavaScript module, not yet tied to a Context. */ -class V8_EXPORT UnboundModuleScript { +class V8_EXPORT UnboundModuleScript : public Data { // Only used as a container for code caching. }; @@ -1271,7 +1460,7 @@ class V8_EXPORT Location { /** * A compiled JavaScript module. */ -class V8_EXPORT Module { +class V8_EXPORT Module : public Data { public: /** * The different states a module can be in. @@ -1359,6 +1548,45 @@ class V8_EXPORT Module { * kEvaluated or kErrored. */ Local GetUnboundModuleScript(); + + /* + * Callback defined in the embedder. This is responsible for setting + * the module's exported values with calls to SetSyntheticModuleExport(). + * The callback must return a Value to indicate success (where no + * exception was thrown) and return an empy MaybeLocal to indicate falure + * (where an exception was thrown). + */ + typedef MaybeLocal (*SyntheticModuleEvaluationSteps)( + Local context, Local module); + + /** + * Creates a new SyntheticModule with the specified export names, where + * evaluation_steps will be executed upon module evaluation. + * export_names must not contain duplicates. + * module_name is used solely for logging/debugging and doesn't affect module + * behavior. + */ + static Local CreateSyntheticModule( + Isolate* isolate, Local module_name, + const std::vector>& export_names, + SyntheticModuleEvaluationSteps evaluation_steps); + + /** + * Set this module's exported value for the name export_name to the specified + * export_value. This method must be called only on Modules created via + * CreateSyntheticModule. An error will be thrown if export_name is not one + * of the export_names that were passed in that CreateSyntheticModule call. + * Returns Just(true) on success, Nothing() if an error was thrown. + */ + V8_WARN_UNUSED_RESULT Maybe SetSyntheticModuleExport( + Isolate* isolate, Local export_name, Local export_value); + V8_DEPRECATE_SOON( + "Use the preceding SetSyntheticModuleExport with an Isolate parameter, " + "instead of the one that follows. The former will throw a runtime " + "error if called for an export that doesn't exist (as per spec); " + "the latter will crash with a failed CHECK().") + void SetSyntheticModuleExport(Local export_name, + Local export_value); }; /** @@ -1534,8 +1762,8 @@ class V8_EXPORT ScriptCompiler { V8_DEPRECATE_SOON( "This class takes ownership of source_stream, so use the constructor " - "taking a unique_ptr to make these semantics clearer", - StreamedSource(ExternalSourceStream* source_stream, Encoding encoding)); + "taking a unique_ptr to make these semantics clearer") + StreamedSource(ExternalSourceStream* source_stream, Encoding encoding); StreamedSource(std::unique_ptr source_stream, Encoding encoding); ~StreamedSource(); @@ -1701,7 +1929,8 @@ class V8_EXPORT ScriptCompiler { Local arguments[], size_t context_extension_count, Local context_extensions[], CompileOptions options = kNoCompileOptions, - NoCacheReason no_cache_reason = kNoCacheNoReason); + NoCacheReason no_cache_reason = kNoCacheNoReason, + Local* script_or_module_out = nullptr); /** * Creates and returns code cache for the specified unbound_script. @@ -1784,6 +2013,12 @@ class V8_EXPORT Message { */ int GetEndPosition() const; + /** + * Returns the Wasm function index where the error occurred. Returns -1 if + * message is not from a Wasm script. + */ + int GetWasmFunctionIndex() const; + /** * Returns the error level of the message. */ @@ -1816,6 +2051,7 @@ class V8_EXPORT Message { static const int kNoLineNumberInfo = 0; static const int kNoColumnInfo = 0; static const int kNoScriptIdInfo = 0; + static const int kNoWasmFunctionIndexInfo = -1; }; @@ -1933,6 +2169,11 @@ class V8_EXPORT StackFrame { * Returns whether or not the associated functions is defined in wasm. */ bool IsWasm() const; + + /** + * Returns whether or not the associated function is defined by the user. + */ + bool IsUserJavaScript() const; }; @@ -1951,10 +2192,11 @@ enum StateTag { // A RegisterState represents the current state of registers used // by the sampling profiler API. struct RegisterState { - RegisterState() : pc(nullptr), sp(nullptr), fp(nullptr) {} + RegisterState() : pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {} void* pc; // Instruction pointer. void* sp; // Stack pointer. void* fp; // Frame pointer. + void* lr; // Link register (or nullptr on platforms without a link register). }; // The output structure filled up by GetStackSample API function. @@ -1963,6 +2205,7 @@ struct SampleInfo { StateTag vm_state; // Current VM state. void* external_callback_entry; // External callback address if VM is // executing an external callback. + void* top_context; // Incumbent native context address. }; struct MemoryRange { @@ -1978,6 +2221,8 @@ struct UnwindState { MemoryRange code_range; MemoryRange embedded_code_range; JSEntryStub js_entry_stub; + JSEntryStub js_construct_entry_stub; + JSEntryStub js_run_microtasks_entry_stub; }; /** @@ -2120,10 +2365,10 @@ class V8_EXPORT ValueSerializer { void WriteDouble(double value); void WriteRawBytes(const void* source, size_t length); - private: ValueSerializer(const ValueSerializer&) = delete; void operator=(const ValueSerializer&) = delete; + private: struct PrivateData; PrivateData* private_; }; @@ -2222,10 +2467,10 @@ class V8_EXPORT ValueDeserializer { V8_WARN_UNUSED_RESULT bool ReadDouble(double* value); V8_WARN_UNUSED_RESULT bool ReadRawBytes(size_t length, const void** data); - private: ValueDeserializer(const ValueDeserializer&) = delete; void operator=(const ValueDeserializer&) = delete; + private: struct PrivateData; PrivateData* private_; }; @@ -2520,9 +2765,6 @@ class V8_EXPORT Value : public Data { V8_WARN_UNUSED_RESULT MaybeLocal ToBigInt( Local context) const; - V8_DEPRECATED("ToBoolean can never throw. Use Local version.", - V8_WARN_UNUSED_RESULT MaybeLocal ToBoolean( - Local context) const); V8_WARN_UNUSED_RESULT MaybeLocal ToNumber( Local context) const; V8_WARN_UNUSED_RESULT MaybeLocal ToString( @@ -2538,16 +2780,6 @@ class V8_EXPORT Value : public Data { V8_WARN_UNUSED_RESULT MaybeLocal ToInt32(Local context) const; Local ToBoolean(Isolate* isolate) const; - V8_DEPRECATED("Use maybe version", - Local ToNumber(Isolate* isolate) const); - V8_DEPRECATED("Use maybe version", - Local ToString(Isolate* isolate) const); - V8_DEPRECATED("Use maybe version", - Local ToObject(Isolate* isolate) const); - V8_DEPRECATED("Use maybe version", - Local ToInteger(Isolate* isolate) const); - V8_DEPRECATED("Use maybe version", - Local ToInt32(Isolate* isolate) const); /** * Attempts to convert a string to an array index. @@ -2558,9 +2790,6 @@ class V8_EXPORT Value : public Data { bool BooleanValue(Isolate* isolate) const; - V8_DEPRECATED("BooleanValue can never throw. Use Isolate version.", - V8_WARN_UNUSED_RESULT Maybe BooleanValue( - Local context) const); V8_WARN_UNUSED_RESULT Maybe NumberValue(Local context) const; V8_WARN_UNUSED_RESULT Maybe IntegerValue( Local context) const; @@ -2764,6 +2993,10 @@ class V8_EXPORT String : public Name { */ virtual bool IsCacheable() const { return true; } + // Disallow copying and assigning. + ExternalStringResourceBase(const ExternalStringResourceBase&) = delete; + void operator=(const ExternalStringResourceBase&) = delete; + protected: ExternalStringResourceBase() = default; @@ -2793,10 +3026,6 @@ class V8_EXPORT String : public Name { */ virtual void Unlock() const {} - // Disallow copying and assigning. - ExternalStringResourceBase(const ExternalStringResourceBase&) = delete; - void operator=(const ExternalStringResourceBase&) = delete; - private: friend class internal::ExternalString; friend class v8::String; @@ -2880,43 +3109,23 @@ class V8_EXPORT String : public Name { V8_INLINE static String* Cast(v8::Value* obj); - // TODO(dcarney): remove with deprecation of New functions. - enum NewStringType { - kNormalString = static_cast(v8::NewStringType::kNormal), - kInternalizedString = static_cast(v8::NewStringType::kInternalized) - }; - - /** Allocates a new string from UTF-8 data.*/ - static V8_DEPRECATED( - "Use maybe version", - Local NewFromUtf8(Isolate* isolate, const char* data, - NewStringType type = kNormalString, - int length = -1)); - /** Allocates a new string from UTF-8 data. Only returns an empty value when * length > kMaxLength. **/ static V8_WARN_UNUSED_RESULT MaybeLocal NewFromUtf8( - Isolate* isolate, const char* data, v8::NewStringType type, - int length = -1); + Isolate* isolate, const char* data, + NewStringType type = NewStringType::kNormal, int length = -1); /** Allocates a new string from Latin-1 data. Only returns an empty value * when length > kMaxLength. **/ static V8_WARN_UNUSED_RESULT MaybeLocal NewFromOneByte( - Isolate* isolate, const uint8_t* data, v8::NewStringType type, - int length = -1); - - /** Allocates a new string from UTF-16 data.*/ - static V8_DEPRECATED( - "Use maybe version", - Local NewFromTwoByte(Isolate* isolate, const uint16_t* data, - NewStringType type = kNormalString, - int length = -1)); + Isolate* isolate, const uint8_t* data, + NewStringType type = NewStringType::kNormal, int length = -1); /** Allocates a new string from UTF-16 data. Only returns an empty value when * length > kMaxLength. **/ static V8_WARN_UNUSED_RESULT MaybeLocal NewFromTwoByte( - Isolate* isolate, const uint16_t* data, v8::NewStringType type, - int length = -1); + Isolate* isolate, const uint16_t* data, + NewStringType type = NewStringType::kNormal, int length = -1); /** * Creates a new string by concatenating the left and the right strings @@ -2955,10 +3164,6 @@ class V8_EXPORT String : public Name { * should the underlying buffer be deallocated or modified except through the * destructor of the external string resource. */ - static V8_DEPRECATED( - "Use maybe version", - Local NewExternal(Isolate* isolate, - ExternalOneByteStringResource* resource)); static V8_WARN_UNUSED_RESULT MaybeLocal NewExternalOneByte( Isolate* isolate, ExternalOneByteStringResource* resource); @@ -3048,30 +3253,35 @@ class V8_EXPORT String : public Name { class V8_EXPORT Symbol : public Name { public: /** - * Returns the print name string of the symbol, or undefined if none. + * Returns the description string of the symbol, or undefined if none. */ - Local Name() const; + Local Description() const; + + V8_DEPRECATE_SOON("Use Symbol::Description()") + Local Name() const { return Description(); } /** - * Create a symbol. If name is not empty, it will be used as the description. + * Create a symbol. If description is not empty, it will be used as the + * description. */ static Local New(Isolate* isolate, - Local name = Local()); + Local description = Local()); /** * Access global symbol registry. * Note that symbols created this way are never collected, so * they should only be used for statically fixed properties. - * Also, there is only one global name space for the names used as keys. + * Also, there is only one global name space for the descriptions used as + * keys. * To minimize the potential for clashes, use qualified names as keys. */ - static Local For(Isolate *isolate, Local name); + static Local For(Isolate* isolate, Local description); /** * Retrieve a global symbol. Similar to |For|, but using a separate * registry that is not accessible by (and cannot clash with) JavaScript code. */ - static Local ForApi(Isolate *isolate, Local name); + static Local ForApi(Isolate* isolate, Local description); // Well-known symbols static Local GetAsyncIterator(Isolate* isolate); @@ -3343,7 +3553,7 @@ enum class IndexFilter { kIncludeIndices, kSkipIndices }; * kConvertToString will convert integer indices to strings. * kKeepNumbers will return numbers for integer indices. */ -enum class KeyConversionMode { kConvertToString, kKeepNumbers }; +enum class KeyConversionMode { kConvertToString, kKeepNumbers, kNoNumbers }; /** * Integrity level for objects. @@ -3355,8 +3565,6 @@ enum class IntegrityLevel { kFrozen, kSealed }; */ class V8_EXPORT Object : public Value { public: - V8_DEPRECATE_SOON("Use maybe version", - bool Set(Local key, Local value)); /** * Set only return Just(true) or Empty(), so if it should never fail, use * result.Check(). @@ -3364,8 +3572,6 @@ class V8_EXPORT Object : public Value { V8_WARN_UNUSED_RESULT Maybe Set(Local context, Local key, Local value); - V8_DEPRECATE_SOON("Use maybe version", - bool Set(uint32_t index, Local value)); V8_WARN_UNUSED_RESULT Maybe Set(Local context, uint32_t index, Local value); @@ -3407,13 +3613,12 @@ class V8_EXPORT Object : public Value { // // Returns true on success. V8_WARN_UNUSED_RESULT Maybe DefineProperty( - Local context, Local key, PropertyDescriptor& descriptor); + Local context, Local key, + PropertyDescriptor& descriptor); // NOLINT(runtime/references) - V8_DEPRECATE_SOON("Use maybe version", Local Get(Local key)); V8_WARN_UNUSED_RESULT MaybeLocal Get(Local context, Local key); - V8_DEPRECATE_SOON("Use maybe version", Local Get(uint32_t index)); V8_WARN_UNUSED_RESULT MaybeLocal Get(Local context, uint32_t index); @@ -3592,8 +3797,9 @@ class V8_EXPORT Object : public Value { return object.val_->InternalFieldCount(); } - /** Same as above, but works for TracedGlobal. */ - V8_INLINE static int InternalFieldCount(const TracedGlobal& object) { + /** Same as above, but works for TracedReferenceBase. */ + V8_INLINE static int InternalFieldCount( + const TracedReferenceBase& object) { return object.val_->InternalFieldCount(); } @@ -3618,7 +3824,7 @@ class V8_EXPORT Object : public Value { /** Same as above, but works for TracedGlobal. */ V8_INLINE static void* GetAlignedPointerFromInternalField( - const TracedGlobal& object, int index) { + const TracedReferenceBase& object, int index) { return object.val_->GetAlignedPointerFromInternalField(index); } @@ -3737,6 +3943,15 @@ class V8_EXPORT Object : public Value { */ bool IsConstructor(); + /** + * True if this object can carry information relevant to the embedder in its + * embedder fields, false otherwise. This is generally true for objects + * constructed through function templates but also holds for other types where + * V8 automatically adds internal fields at compile time, such as e.g. + * v8::ArrayBuffer. + */ + bool IsApiWrapper(); + /** * Call an Object as a function if a callback is set by the * ObjectTemplate::SetCallAsFunctionHandler method. @@ -3897,12 +4112,9 @@ class ReturnValue { } // Local setters template - V8_INLINE V8_DEPRECATED("Use Global<> instead", - void Set(const Persistent& handle)); - template V8_INLINE void Set(const Global& handle); template - V8_INLINE void Set(const TracedGlobal& handle); + V8_INLINE void Set(const TracedReferenceBase& handle); template V8_INLINE void Set(const Local handle); // Fast primitive setters @@ -4458,46 +4670,14 @@ class V8_EXPORT CompiledWasmModule { // An instance of WebAssembly.Module. class V8_EXPORT WasmModuleObject : public Object { public: - /** - * An opaque, native heap object for transferring wasm modules. It - * supports move semantics, and does not support copy semantics. - * TODO(wasm): Merge this with CompiledWasmModule once code sharing is always - * enabled. - */ - class TransferrableModule final { - public: - TransferrableModule(TransferrableModule&& src) = default; - TransferrableModule(const TransferrableModule& src) = delete; - - TransferrableModule& operator=(TransferrableModule&& src) = default; - TransferrableModule& operator=(const TransferrableModule& src) = delete; - - private: - typedef std::shared_ptr SharedModule; - friend class WasmModuleObject; - explicit TransferrableModule(SharedModule shared_module) - : shared_module_(std::move(shared_module)) {} - TransferrableModule(OwnedBuffer serialized, OwnedBuffer bytes) - : serialized_(std::move(serialized)), wire_bytes_(std::move(bytes)) {} - - SharedModule shared_module_; - OwnedBuffer serialized_ = {nullptr, 0}; - OwnedBuffer wire_bytes_ = {nullptr, 0}; - }; - - /** - * Get an in-memory, non-persistable, and context-independent (meaning, - * suitable for transfer to another Isolate and Context) representation - * of this wasm compiled module. - */ - TransferrableModule GetTransferrableModule(); + WasmModuleObject() = delete; /** * Efficiently re-create a WasmModuleObject, without recompiling, from - * a TransferrableModule. + * a CompiledWasmModule. */ - static MaybeLocal FromTransferrableModule( - Isolate* isolate, const TransferrableModule&); + static MaybeLocal FromCompiledModule( + Isolate* isolate, const CompiledWasmModule&); /** * Get the compiled module for this module object. The compiled module can be @@ -4521,11 +4701,7 @@ class V8_EXPORT WasmModuleObject : public Object { static MaybeLocal Compile(Isolate* isolate, const uint8_t* start, size_t length); - static MemorySpan AsReference(const OwnedBuffer& buff) { - return {buff.buffer.get(), buff.size}; - } - WasmModuleObject(); static void CheckCast(Value* obj); }; @@ -4657,6 +4833,56 @@ class V8_EXPORT WasmModuleObjectBuilderStreaming final { enum class ArrayBufferCreationMode { kInternalized, kExternalized }; +/** + * A wrapper around the backing store (i.e. the raw memory) of an array buffer. + * See a document linked in http://crbug.com/v8/9908 for more information. + * + * The allocation and destruction of backing stores is generally managed by + * V8. Clients should always use standard C++ memory ownership types (i.e. + * std::unique_ptr and std::shared_ptr) to manage lifetimes of backing stores + * properly, since V8 internal objects may alias backing stores. + * + * This object does not keep the underlying |ArrayBuffer::Allocator| alive by + * default. Use Isolate::CreateParams::array_buffer_allocator_shared when + * creating the Isolate to make it hold a reference to the allocator itself. + */ +class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase { + public: + ~BackingStore(); + + /** + * Return a pointer to the beginning of the memory block for this backing + * store. The pointer is only valid as long as this backing store object + * lives. + */ + void* Data() const; + + /** + * The length (in bytes) of this backing store. + */ + size_t ByteLength() const; + + /** + * Indicates whether the backing store was created for an ArrayBuffer or + * a SharedArrayBuffer. + */ + bool IsShared() const; + + private: + /** + * See [Shared]ArrayBuffer::GetBackingStore and + * [Shared]ArrayBuffer::NewBackingStore. + */ + BackingStore(); +}; + +/** + * This callback is used only if the memory block for this backing store cannot + * be allocated with an ArrayBuffer::Allocator. In such cases the destructor + * of this backing store object invokes the callback to free the memory block. + */ +using BackingStoreDeleterCallback = void (*)(void* data, size_t length, + void* deleter_data); /** * An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5). @@ -4789,14 +5015,58 @@ class V8_EXPORT ArrayBuffer : public Object { * |Allocator::Free| once all ArrayBuffers referencing it are collected by * the garbage collector. */ + V8_DEPRECATE_SOON( + "Use the version that takes a BackingStore. " + "See http://crbug.com/v8/9908.") static Local New( Isolate* isolate, void* data, size_t byte_length, ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized); + /** + * Create a new ArrayBuffer with an existing backing store. + * The created array keeps a reference to the backing store until the array + * is garbage collected. Note that the IsExternal bit does not affect this + * reference from the array to the backing store. + * + * In future IsExternal bit will be removed. Until then the bit is set as + * follows. If the backing store does not own the underlying buffer, then + * the array is created in externalized state. Otherwise, the array is created + * in internalized state. In the latter case the array can be transitioned + * to the externalized state using Externalize(backing_store). + */ + static Local New(Isolate* isolate, + std::shared_ptr backing_store); + + /** + * Returns a new standalone BackingStore that is allocated using the array + * buffer allocator of the isolate. The result can be later passed to + * ArrayBuffer::New. + * + * If the allocator returns nullptr, then the function may cause GCs in the + * given isolate and re-try the allocation. If GCs do not help, then the + * function will crash with an out-of-memory error. + */ + static std::unique_ptr NewBackingStore(Isolate* isolate, + size_t byte_length); + /** + * Returns a new standalone BackingStore that takes over the ownership of + * the given buffer. The destructor of the BackingStore invokes the given + * deleter callback. + * + * The result can be later passed to ArrayBuffer::New. The raw pointer + * to the buffer must not be passed again to any V8 API function. + */ + static std::unique_ptr NewBackingStore( + void* data, size_t byte_length, BackingStoreDeleterCallback deleter, + void* deleter_data); + /** * Returns true if ArrayBuffer is externalized, that is, does not * own its memory block. */ + V8_DEPRECATE_SOON( + "With v8::BackingStore externalized ArrayBuffers are " + "the same as ordinary ArrayBuffers. See http://crbug.com/v8/9908.") bool IsExternal() const; /** @@ -4804,12 +5074,6 @@ class V8_EXPORT ArrayBuffer : public Object { */ bool IsDetachable() const; - // TODO(913887): fix the use of 'neuter' in the API. - V8_DEPRECATE_SOON("Use IsDetachable() instead.", - inline bool IsNeuterable() const) { - return IsDetachable(); - } - /** * Detaches this ArrayBuffer and all its views (typed arrays). * Detaching sets the byte length of the buffer and all typed arrays to zero, @@ -4818,9 +5082,6 @@ class V8_EXPORT ArrayBuffer : public Object { */ void Detach(); - // TODO(913887): fix the use of 'neuter' in the API. - V8_DEPRECATE_SOON("Use Detach() instead.", inline void Neuter()) { Detach(); } - /** * Make this ArrayBuffer external. The pointer to underlying memory block * and byte length are returned as |Contents| structure. After ArrayBuffer @@ -4829,10 +5090,22 @@ class V8_EXPORT ArrayBuffer : public Object { * * The Data pointer of ArrayBuffer::Contents must be freed using the provided * deleter, which will call ArrayBuffer::Allocator::Free if the buffer - * was allocated with ArraryBuffer::Allocator::Allocate. + * was allocated with ArrayBuffer::Allocator::Allocate. */ + V8_DEPRECATE_SOON( + "Use GetBackingStore or Detach. See http://crbug.com/v8/9908.") Contents Externalize(); + /** + * Marks this ArrayBuffer external given a witness that the embedder + * has fetched the backing store using the new GetBackingStore() function. + * + * With the new lifetime management of backing stores there is no need for + * externalizing, so this function exists only to make the transition easier. + */ + V8_DEPRECATE_SOON("This will be removed together with IsExternal.") + void Externalize(const std::shared_ptr& backing_store); + /** * Get a pointer to the ArrayBuffer's underlying memory block without * externalizing it. If the ArrayBuffer is not externalized, this pointer @@ -4841,8 +5114,19 @@ class V8_EXPORT ArrayBuffer : public Object { * The embedder should make sure to hold a strong reference to the * ArrayBuffer while accessing this pointer. */ + V8_DEPRECATE_SOON("Use GetBackingStore. See http://crbug.com/v8/9908.") Contents GetContents(); + /** + * Get a shared pointer to the backing store of this array buffer. This + * pointer coordinates the lifetime management of the internal storage + * with any live ArrayBuffers on the heap, even across isolates. The embedder + * should not attempt to manage lifetime of the storage through other means. + * + * This function replaces both Externalize() and GetContents(). + */ + std::shared_ptr GetBackingStore(); + V8_INLINE static ArrayBuffer* Cast(Value* obj); static const int kInternalFieldCount = V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT; @@ -4851,6 +5135,7 @@ class V8_EXPORT ArrayBuffer : public Object { private: ArrayBuffer(); static void CheckCast(Value* obj); + Contents GetContents(bool externalize); }; @@ -4918,7 +5203,9 @@ class V8_EXPORT TypedArray : public ArrayBufferView { /* * The largest typed array size that can be constructed using New. */ - static constexpr size_t kMaxLength = internal::kSmiMaxValue; + static constexpr size_t kMaxLength = internal::kApiSystemPointerSize == 4 + ? internal::kSmiMaxValue + : 0x7FFFFFFF; // kMaxInt32 /** * Number of elements in this typed array @@ -5213,24 +5500,69 @@ class V8_EXPORT SharedArrayBuffer : public Object { * specified. The memory block will not be reclaimed when a created * SharedArrayBuffer is garbage-collected. */ + V8_DEPRECATE_SOON( + "Use the version that takes a BackingStore. " + "See http://crbug.com/v8/9908.") static Local New( Isolate* isolate, void* data, size_t byte_length, ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized); + /** + * Create a new SharedArrayBuffer with an existing backing store. + * The created array keeps a reference to the backing store until the array + * is garbage collected. Note that the IsExternal bit does not affect this + * reference from the array to the backing store. + * + * In future IsExternal bit will be removed. Until then the bit is set as + * follows. If the backing store does not own the underlying buffer, then + * the array is created in externalized state. Otherwise, the array is created + * in internalized state. In the latter case the array can be transitioned + * to the externalized state using Externalize(backing_store). + */ + static Local New( + Isolate* isolate, std::shared_ptr backing_store); + + /** + * Returns a new standalone BackingStore that is allocated using the array + * buffer allocator of the isolate. The result can be later passed to + * SharedArrayBuffer::New. + * + * If the allocator returns nullptr, then the function may cause GCs in the + * given isolate and re-try the allocation. If GCs do not help, then the + * function will crash with an out-of-memory error. + */ + static std::unique_ptr NewBackingStore(Isolate* isolate, + size_t byte_length); + /** + * Returns a new standalone BackingStore that takes over the ownership of + * the given buffer. The destructor of the BackingStore invokes the given + * deleter callback. + * + * The result can be later passed to SharedArrayBuffer::New. The raw pointer + * to the buffer must not be passed again to any V8 functions. + */ + static std::unique_ptr NewBackingStore( + void* data, size_t byte_length, BackingStoreDeleterCallback deleter, + void* deleter_data); + /** * Create a new SharedArrayBuffer over an existing memory block. Propagate * flags to indicate whether the underlying buffer can be grown. */ - V8_DEPRECATED("Use New method with data, and byte_length instead.", - static Local New( - Isolate* isolate, const SharedArrayBuffer::Contents&, - ArrayBufferCreationMode mode = - ArrayBufferCreationMode::kExternalized)); + V8_DEPRECATED( + "Use the version that takes a BackingStore. " + "See http://crbug.com/v8/9908.") + static Local New( + Isolate* isolate, const SharedArrayBuffer::Contents&, + ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized); /** * Returns true if SharedArrayBuffer is externalized, that is, does not * own its memory block. */ + V8_DEPRECATE_SOON( + "With v8::BackingStore externalized SharedArrayBuffers are the same " + "as ordinary SharedArrayBuffers. See http://crbug.com/v8/9908.") bool IsExternal() const; /** @@ -5245,8 +5577,20 @@ class V8_EXPORT SharedArrayBuffer : public Object { * v8::Isolate::CreateParams::array_buffer_allocator. * */ + V8_DEPRECATE_SOON( + "Use GetBackingStore or Detach. See http://crbug.com/v8/9908.") Contents Externalize(); + /** + * Marks this SharedArrayBuffer external given a witness that the embedder + * has fetched the backing store using the new GetBackingStore() function. + * + * With the new lifetime management of backing stores there is no need for + * externalizing, so this function exists only to make the transition easier. + */ + V8_DEPRECATE_SOON("This will be removed together with IsExternal.") + void Externalize(const std::shared_ptr& backing_store); + /** * Get a pointer to the ArrayBuffer's underlying memory block without * externalizing it. If the ArrayBuffer is not externalized, this pointer @@ -5259,8 +5603,19 @@ class V8_EXPORT SharedArrayBuffer : public Object { * by the allocator specified in * v8::Isolate::CreateParams::array_buffer_allocator. */ + V8_DEPRECATE_SOON("Use GetBackingStore. See http://crbug.com/v8/9908.") Contents GetContents(); + /** + * Get a shared pointer to the backing store of this array buffer. This + * pointer coordinates the lifetime management of the internal storage + * with any live ArrayBuffers on the heap, even across isolates. The embedder + * should not attempt to manage lifetime of the storage through other means. + * + * This function replaces both Externalize() and GetContents(). + */ + std::shared_ptr GetBackingStore(); + V8_INLINE static SharedArrayBuffer* Cast(Value* obj); static const int kInternalFieldCount = V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT; @@ -5268,6 +5623,7 @@ class V8_EXPORT SharedArrayBuffer : public Object { private: SharedArrayBuffer(); static void CheckCast(Value* obj); + Contents GetContents(bool externalize); }; @@ -5287,38 +5643,6 @@ class V8_EXPORT Date : public Object { V8_INLINE static Date* Cast(Value* obj); - /** - * Time zone redetection indicator for - * DateTimeConfigurationChangeNotification. - * - * kSkip indicates V8 that the notification should not trigger redetecting - * host time zone. kRedetect indicates V8 that host time zone should be - * redetected, and used to set the default time zone. - * - * The host time zone detection may require file system access or similar - * operations unlikely to be available inside a sandbox. If v8 is run inside a - * sandbox, the host time zone has to be detected outside the sandbox before - * calling DateTimeConfigurationChangeNotification function. - */ - enum class TimeZoneDetection { kSkip, kRedetect }; - - /** - * Notification that the embedder has changed the time zone, - * daylight savings time, or other date / time configuration - * parameters. V8 keeps a cache of various values used for - * date / time computation. This notification will reset - * those cached values for the current context so that date / - * time configuration changes would be reflected in the Date - * object. - * - * This API should not be called more than needed as it will - * negatively impact the performance of date operations. - */ - V8_DEPRECATED("Use Isolate::DateTimeConfigurationChangeNotification", - static void DateTimeConfigurationChangeNotification( - Isolate* isolate, TimeZoneDetection time_zone_detection = - TimeZoneDetection::kSkip)); - private: static void CheckCast(Value* obj); }; @@ -5421,6 +5745,8 @@ class V8_EXPORT RegExp : public Object { kDotAll = 1 << 5, }; + static constexpr int kFlagCount = 6; + /** * Creates a regular expression from the given pattern string and * the flags bit field. May throw a JavaScript exception as @@ -5435,6 +5761,29 @@ class V8_EXPORT RegExp : public Object { Local pattern, Flags flags); + /** + * Like New, but additionally specifies a backtrack limit. If the number of + * backtracks done in one Exec call hits the limit, a match failure is + * immediately returned. + */ + static V8_WARN_UNUSED_RESULT MaybeLocal NewWithBacktrackLimit( + Local context, Local pattern, Flags flags, + uint32_t backtrack_limit); + + /** + * Executes the current RegExp instance on the given subject string. + * Equivalent to RegExp.prototype.exec as described in + * + * https://tc39.es/ecma262/#sec-regexp.prototype.exec + * + * On success, an Array containing the matched strings is returned. On + * failure, returns Null. + * + * Note: modifies global context state, accessible e.g. through RegExp.input. + */ + V8_WARN_UNUSED_RESULT MaybeLocal Exec(Local context, + Local subject); + /** * Returns the value of the source property: a string representing * the regular expression. @@ -5452,6 +5801,32 @@ class V8_EXPORT RegExp : public Object { static void CheckCast(Value* obj); }; +/** + * An instance of the built-in FinalizationGroup constructor. + * + * This API is experimental and may change significantly. + */ +class V8_EXPORT FinalizationGroup : public Object { + public: + /** + * Runs the cleanup callback of the given FinalizationGroup. + * + * V8 will inform the embedder that there are finalizer callbacks be + * called through HostCleanupFinalizationGroupCallback. + * + * HostCleanupFinalizationGroupCallback should schedule a task to + * call FinalizationGroup::Cleanup() at some point in the + * future. It's the embedders responsiblity to make this call at a + * time which does not interrupt synchronous ECMAScript code + * execution. + * + * If the result is Nothing then an exception has + * occurred. Otherwise the result is |true| if the cleanup callback + * was called successfully. The result is never |false|. + */ + static V8_WARN_UNUSED_RESULT Maybe Cleanup( + Local finalization_group); +}; /** * A JavaScript value that wraps a C++ void*. This type of value is mainly used @@ -5929,6 +6304,7 @@ class V8_EXPORT FunctionTemplate : public Template { SideEffectType side_effect_type = SideEffectType::kHasSideEffect); /** Get a template included in the snapshot by index. */ + V8_DEPRECATED("Use v8::Isolate::GetDataFromSnapshotOnce instead") static MaybeLocal FromSnapshot(Isolate* isolate, size_t index); @@ -6004,21 +6380,6 @@ class V8_EXPORT FunctionTemplate : public Template { */ void SetAcceptAnyReceiver(bool value); - /** - * Determines whether the __proto__ accessor ignores instances of - * the function template. If instances of the function template are - * ignored, __proto__ skips all instances and instead returns the - * next object in the prototype chain. - * - * Call with a value of true to make the __proto__ accessor ignore - * instances of the function template. Call with a value of false - * to make the __proto__ accessor not ignore instances of the - * function template. By default, instances of a function template - * are not ignored. - */ - V8_DEPRECATED("This feature is incompatible with ES6+.", - void SetHiddenPrototype(bool value)); - /** * Sets the ReadOnly flag in the attributes of the 'prototype' property * of functions created from this FunctionTemplate to true. @@ -6235,6 +6596,7 @@ class V8_EXPORT ObjectTemplate : public Template { Local constructor = Local()); /** Get a template included in the snapshot by index. */ + V8_DEPRECATED("Use v8::Isolate::GetDataFromSnapshotOnce instead") static MaybeLocal FromSnapshot(Isolate* isolate, size_t index); @@ -6522,7 +6884,26 @@ V8_INLINE Local False(Isolate* isolate); */ class V8_EXPORT ResourceConstraints { public: - ResourceConstraints(); + /** + * Configures the constraints with reasonable default values based on the + * provided heap size limit. The heap size includes both the young and + * the old generation. + * + * \param initial_heap_size_in_bytes The initial heap size or zero. + * By default V8 starts with a small heap and dynamically grows it to + * match the set of live objects. This may lead to ineffective + * garbage collections at startup if the live set is large. + * Setting the initial heap size avoids such garbage collections. + * Note that this does not affect young generation garbage collections. + * + * \param maximum_heap_size_in_bytes The hard limit for the heap size. + * When the heap size approaches this limit, V8 will perform series of + * garbage collections and invoke the NearHeapLimitCallback. If the garbage + * collections do not help and the callback does not increase the limit, + * then V8 will crash with V8::FatalProcessOutOfMemory. + */ + void ConfigureDefaultsFromHeapSize(size_t initial_heap_size_in_bytes, + size_t maximum_heap_size_in_bytes); /** * Configures the constraints with reasonable default values based on the @@ -6536,45 +6917,92 @@ class V8_EXPORT ResourceConstraints { void ConfigureDefaults(uint64_t physical_memory, uint64_t virtual_memory_limit); - // Returns the max semi-space size in KB. - size_t max_semi_space_size_in_kb() const { - return max_semi_space_size_in_kb_; - } - - // Sets the max semi-space size in KB. - void set_max_semi_space_size_in_kb(size_t limit_in_kb) { - max_semi_space_size_in_kb_ = limit_in_kb; - } - - size_t max_old_space_size() const { return max_old_space_size_; } - void set_max_old_space_size(size_t limit_in_mb) { - max_old_space_size_ = limit_in_mb; - } + /** + * The address beyond which the VM's stack may not grow. + */ uint32_t* stack_limit() const { return stack_limit_; } - // Sets an address beyond which the VM's stack may not grow. void set_stack_limit(uint32_t* value) { stack_limit_ = value; } - size_t code_range_size() const { return code_range_size_; } + + /** + * The amount of virtual memory reserved for generated code. This is relevant + * for 64-bit architectures that rely on code range for calls in code. + */ + size_t code_range_size_in_bytes() const { return code_range_size_; } + void set_code_range_size_in_bytes(size_t limit) { code_range_size_ = limit; } + + /** + * The maximum size of the old generation. + * When the old generation approaches this limit, V8 will perform series of + * garbage collections and invoke the NearHeapLimitCallback. + * If the garbage collections do not help and the callback does not + * increase the limit, then V8 will crash with V8::FatalProcessOutOfMemory. + */ + size_t max_old_generation_size_in_bytes() const { + return max_old_generation_size_; + } + void set_max_old_generation_size_in_bytes(size_t limit) { + max_old_generation_size_ = limit; + } + + /** + * The maximum size of the young generation, which consists of two semi-spaces + * and a large object space. This affects frequency of Scavenge garbage + * collections and should be typically much smaller that the old generation. + */ + size_t max_young_generation_size_in_bytes() const { + return max_young_generation_size_; + } + void set_max_young_generation_size_in_bytes(size_t limit) { + max_young_generation_size_ = limit; + } + + size_t initial_old_generation_size_in_bytes() const { + return initial_old_generation_size_; + } + void set_initial_old_generation_size_in_bytes(size_t initial_size) { + initial_old_generation_size_ = initial_size; + } + + size_t initial_young_generation_size_in_bytes() const { + return initial_young_generation_size_; + } + void set_initial_young_generation_size_in_bytes(size_t initial_size) { + initial_young_generation_size_ = initial_size; + } + + /** + * Deprecated functions. Do not use in new code. + */ + V8_DEPRECATE_SOON("Use code_range_size_in_bytes.") + size_t code_range_size() const { return code_range_size_ / kMB; } + V8_DEPRECATE_SOON("Use set_code_range_size_in_bytes.") void set_code_range_size(size_t limit_in_mb) { - code_range_size_ = limit_in_mb; + code_range_size_ = limit_in_mb * kMB; } - V8_DEPRECATE_SOON("Zone does not pool memory any more.", - size_t max_zone_pool_size() const) { - return max_zone_pool_size_; - } - V8_DEPRECATE_SOON("Zone does not pool memory any more.", - void set_max_zone_pool_size(size_t bytes)) { - max_zone_pool_size_ = bytes; + V8_DEPRECATE_SOON("Use max_young_generation_size_in_bytes.") + size_t max_semi_space_size_in_kb() const; + V8_DEPRECATE_SOON("Use set_max_young_generation_size_in_bytes.") + void set_max_semi_space_size_in_kb(size_t limit_in_kb); + V8_DEPRECATE_SOON("Use max_old_generation_size_in_bytes.") + size_t max_old_space_size() const { return max_old_generation_size_ / kMB; } + V8_DEPRECATE_SOON("Use set_max_old_generation_size_in_bytes.") + void set_max_old_space_size(size_t limit_in_mb) { + max_old_generation_size_ = limit_in_mb * kMB; } + V8_DEPRECATE_SOON("Zone does not pool memory any more.") + size_t max_zone_pool_size() const { return max_zone_pool_size_; } + V8_DEPRECATE_SOON("Zone does not pool memory any more.") + void set_max_zone_pool_size(size_t bytes) { max_zone_pool_size_ = bytes; } private: - // max_semi_space_size_ is in KB - size_t max_semi_space_size_in_kb_; - - // The remaining limits are in MB - size_t max_old_space_size_; - uint32_t* stack_limit_; - size_t code_range_size_; - size_t max_zone_pool_size_; + static constexpr size_t kMB = 1048576u; + size_t code_range_size_ = 0; + size_t max_old_generation_size_ = 0; + size_t max_young_generation_size_ = 0; + size_t max_zone_pool_size_ = 0; + size_t initial_old_generation_size_ = 0; + size_t initial_young_generation_size_ = 0; + uint32_t* stack_limit_ = nullptr; }; @@ -6632,10 +7060,35 @@ typedef void* (*CreateHistogramCallback)(const char* name, typedef void (*AddHistogramSampleCallback)(void* histogram, int sample); +// --- Crashkeys Callback --- +enum class CrashKeyId { + kIsolateAddress, + kReadonlySpaceFirstPageAddress, + kMapSpaceFirstPageAddress, + kCodeSpaceFirstPageAddress, + kDumpType, +}; + +typedef void (*AddCrashKeyCallback)(CrashKeyId id, const std::string& value); + // --- Enter/Leave Script Callback --- typedef void (*BeforeCallEnteredCallback)(Isolate*); typedef void (*CallCompletedCallback)(Isolate*); +/** + * HostCleanupFinalizationGroupCallback is called when we require the + * embedder to enqueue a task that would call + * FinalizationGroup::Cleanup(). + * + * The FinalizationGroup is the one for which the embedder needs to + * call FinalizationGroup::Cleanup() on. + * + * The context provided is the one in which the FinalizationGroup was + * created in. + */ +typedef void (*HostCleanupFinalizationGroupCallback)( + Local context, Local fg); + /** * HostImportModuleDynamicallyCallback is called when we require the * embedder to load a module. This is used as part of the dynamic @@ -6733,8 +7186,8 @@ class PromiseRejectMessage { typedef void (*PromiseRejectCallback)(PromiseRejectMessage message); // --- Microtasks Callbacks --- -V8_DEPRECATE_SOON("Use *WithData version.", - typedef void (*MicrotasksCompletedCallback)(Isolate*)); +V8_DEPRECATE_SOON("Use *WithData version.") +typedef void (*MicrotasksCompletedCallback)(Isolate*); typedef void (*MicrotasksCompletedCallbackWithData)(Isolate*, void*); typedef void (*MicrotaskCallback)(void* data); @@ -6823,11 +7276,12 @@ class V8_EXPORT MicrotaskQueue { */ virtual int GetMicrotasksScopeDepth() const = 0; + MicrotaskQueue(const MicrotaskQueue&) = delete; + MicrotaskQueue& operator=(const MicrotaskQueue&) = delete; + private: friend class internal::MicrotaskQueue; MicrotaskQueue() = default; - MicrotaskQueue(const MicrotaskQueue&) = delete; - MicrotaskQueue& operator=(const MicrotaskQueue&) = delete; }; /** @@ -6887,6 +7341,23 @@ typedef void (*FailedAccessCheckCallback)(Local target, typedef bool (*AllowCodeGenerationFromStringsCallback)(Local context, Local source); +struct ModifyCodeGenerationFromStringsResult { + // If true, proceed with the codegen algorithm. Otherwise, block it. + bool codegen_allowed = false; + // Overwrite the original source with this string, if present. + // Use the original source if empty. + // This field is considered only if codegen_allowed is true. + MaybeLocal modified_source; +}; + +/** + * Callback to check if codegen is allowed from a source object, and convert + * the source to string if necessary.See ModifyCodeGenerationFromStrings. + */ +typedef ModifyCodeGenerationFromStringsResult ( + *ModifyCodeGenerationFromStringsCallback)(Local context, + Local source); + // --- WebAssembly compilation callbacks --- typedef bool (*ExtensionCallback)(const FunctionCallbackInfo&); @@ -6903,6 +7374,10 @@ typedef void (*WasmStreamingCallback)(const FunctionCallbackInfo&); // --- Callback for checking if WebAssembly threads are enabled --- typedef bool (*WasmThreadsEnabledCallback)(Local context); +// --- Callback for loading source map file for WASM profiling support +typedef Local (*WasmLoadSourceMapCallback)(Isolate* isolate, + const char* name); + // --- Garbage Collection Callbacks --- /** @@ -6959,10 +7434,33 @@ typedef void (*InterruptCallback)(Isolate* isolate, void* data); typedef size_t (*NearHeapLimitCallback)(void* data, size_t current_heap_limit, size_t initial_heap_limit); +/** + * Collection of shared per-process V8 memory information. + * + * Instances of this class can be passed to + * v8::V8::GetSharedMemoryStatistics to get shared memory statistics from V8. + */ +class V8_EXPORT SharedMemoryStatistics { + public: + SharedMemoryStatistics(); + size_t read_only_space_size() { return read_only_space_size_; } + size_t read_only_space_used_size() { return read_only_space_used_size_; } + size_t read_only_space_physical_size() { + return read_only_space_physical_size_; + } + + private: + size_t read_only_space_size_; + size_t read_only_space_used_size_; + size_t read_only_space_physical_size_; + + friend class V8; +}; + /** * Collection of V8 heap information. * - * Instances of this class can be passed to v8::V8::HeapStatistics to + * Instances of this class can be passed to v8::Isolate::GetHeapStatistics to * get heap statistics from V8. */ class V8_EXPORT HeapStatistics { @@ -7118,6 +7616,20 @@ struct JitCodeEvent { PositionType position_type; }; + struct wasm_source_info_t { + // Source file name. + const char* filename; + // Length of filename. + size_t filename_size; + // Line number table, which maps offsets of JITted code to line numbers of + // source file. + const line_info_t* line_number_table; + // Number of entries in the line number table. + size_t line_number_table_size; + }; + + wasm_source_info_t* wasm_source_info; + union { // Only valid for CODE_ADDED. struct name_t name; @@ -7218,6 +7730,11 @@ enum class MemoryPressureLevel { kNone, kModerate, kCritical }; */ class V8_EXPORT EmbedderHeapTracer { public: + enum TraceFlags : uint64_t { + kNoFlags = 0, + kReduceMemory = 1 << 0, + }; + // Indicator for the stack state of the embedder. enum EmbedderStackState { kUnknown, @@ -7231,7 +7748,26 @@ class V8_EXPORT EmbedderHeapTracer { class V8_EXPORT TracedGlobalHandleVisitor { public: virtual ~TracedGlobalHandleVisitor() = default; - virtual void VisitTracedGlobalHandle(const TracedGlobal& value) = 0; + virtual void VisitTracedGlobalHandle(const TracedGlobal& handle) {} + virtual void VisitTracedReference(const TracedReference& handle) {} + }; + + /** + * Summary of a garbage collection cycle. See |TraceEpilogue| on how the + * summary is reported. + */ + struct TraceSummary { + /** + * Time spent managing the retained memory in milliseconds. This can e.g. + * include the time tracing through objects in the embedder. + */ + double time = 0.0; + + /** + * Memory retained by the embedder through the |EmbedderHeapTracer| + * mechanism in bytes. + */ + size_t allocated_size = 0; }; virtual ~EmbedderHeapTracer() = default; @@ -7251,12 +7787,14 @@ class V8_EXPORT EmbedderHeapTracer { virtual void RegisterV8References( const std::vector >& embedder_fields) = 0; - void RegisterEmbedderReference(const TracedGlobal& ref); + V8_DEPRECATED("Use version taking TracedReferenceBase argument") + void RegisterEmbedderReference(const TracedReferenceBase& ref); + void RegisterEmbedderReference(const TracedReferenceBase& ref); /** * Called at the beginning of a GC cycle. */ - virtual void TracePrologue() = 0; + virtual void TracePrologue(TraceFlags flags) {} /** * Called to advance tracing in the embedder. @@ -7279,9 +7817,11 @@ class V8_EXPORT EmbedderHeapTracer { /** * Called at the end of a GC cycle. * - * Note that allocation is *not* allowed within |TraceEpilogue|. + * Note that allocation is *not* allowed within |TraceEpilogue|. Can be + * overriden to fill a |TraceSummary| that is used by V8 to schedule future + * garbage collections. */ - virtual void TraceEpilogue() = 0; + virtual void TraceEpilogue(TraceSummary* trace_summary) {} /** * Called upon entering the final marking pause. No more incremental marking @@ -7303,13 +7843,38 @@ class V8_EXPORT EmbedderHeapTracer { /** * Returns true if the TracedGlobal handle should be considered as root for * the currently running non-tracing garbage collection and false otherwise. + * The default implementation will keep all TracedGlobal references as roots. * - * Default implementation will keep all TracedGlobal references as roots. + * If this returns false, then V8 may decide that the object referred to by + * such a handle is reclaimed. In that case: + * - No action is required if handles are used with destructors, i.e., by just + * using |TracedGlobal|. + * - When run without destructors, i.e., by using + * |TracedReference|, V8 calls |ResetHandleInNonTracingGC|. + * + * Note that the |handle| is different from the handle that the embedder holds + * for retaining the object. The embedder may use |WrapperClassId()| to + * distinguish cases where it wants handles to be treated as roots from not + * being treated as roots. */ virtual bool IsRootForNonTracingGC( - const v8::TracedGlobal& handle) { - return true; - } + const v8::TracedReference& handle); + virtual bool IsRootForNonTracingGC(const v8::TracedGlobal& handle); + + /** + * Used in combination with |IsRootForNonTracingGC|. Called by V8 when an + * object that is backed by a handle is reclaimed by a non-tracing garbage + * collection. It is up to the embedder to reset the original handle. + * + * Note that the |handle| is different from the handle that the embedder holds + * for retaining the object. It is up to the embedder to find the original + * handle via the object or class id. + */ + virtual void ResetHandleInNonTracingGC( + const v8::TracedReference& handle); + V8_DEPRECATED("Use TracedReference version when not requiring destructors.") + virtual void ResetHandleInNonTracingGC( + const v8::TracedGlobal& handle); /* * Called by the embedder to immediately perform a full garbage collection. @@ -7318,6 +7883,15 @@ class V8_EXPORT EmbedderHeapTracer { */ void GarbageCollectionForTesting(EmbedderStackState stack_state); + /* + * Called by the embedder to signal newly allocated or freed memory. Not bound + * to tracing phases. Embedders should trade off when increments are reported + * as V8 may consult global heuristics on whether to trigger garbage + * collection on this change. + */ + void IncreaseAllocatedSize(size_t bytes); + void DecreaseAllocatedSize(size_t bytes); + /* * Returns the v8::Isolate this tracer is attached too and |nullptr| if it * is not attached to any v8::Isolate. @@ -7367,6 +7941,8 @@ struct DeserializeInternalFieldsCallback { }; typedef DeserializeInternalFieldsCallback DeserializeEmbedderFieldsCallback; +enum class MeasureMemoryMode { kSummary, kDetailed }; + /** * Isolate represents an isolated instance of the V8 engine. V8 isolates have * completely separate states. Objects from one isolate must not be used in @@ -7388,6 +7964,7 @@ class V8_EXPORT Isolate { create_histogram_callback(nullptr), add_histogram_sample_callback(nullptr), array_buffer_allocator(nullptr), + array_buffer_allocator_shared(), external_references(nullptr), allow_atomics_wait(true), only_terminate_in_safe_scope(false) {} @@ -7427,8 +8004,14 @@ class V8_EXPORT Isolate { /** * The ArrayBuffer::Allocator to use for allocating and freeing the backing * store of ArrayBuffers. + * + * If the shared_ptr version is used, the Isolate instance and every + * |BackingStore| allocated using this allocator hold a std::shared_ptr + * to the allocator, in order to facilitate lifetime + * management for the allocator instance. */ ArrayBuffer::Allocator* array_buffer_allocator; + std::shared_ptr array_buffer_allocator_shared; /** * Specifies an optional nullptr-terminated array of raw addresses in the @@ -7520,8 +8103,8 @@ class V8_EXPORT Isolate { */ class V8_EXPORT SuppressMicrotaskExecutionScope { public: - explicit SuppressMicrotaskExecutionScope(Isolate* isolate); - explicit SuppressMicrotaskExecutionScope(MicrotaskQueue* microtask_queue); + explicit SuppressMicrotaskExecutionScope( + Isolate* isolate, MicrotaskQueue* microtask_queue = nullptr); ~SuppressMicrotaskExecutionScope(); // Prevent copying of Scope objects. @@ -7533,6 +8116,9 @@ class V8_EXPORT Isolate { private: internal::Isolate* const isolate_; internal::MicrotaskQueue* const microtask_queue_; + internal::Address previous_stack_height_; + + friend class internal::ThreadLocalTop; }; /** @@ -7644,9 +8230,28 @@ class V8_EXPORT Isolate { kRegExpMatchIsFalseishOnJSRegExp = 73, kDateGetTimezoneOffset = 74, kStringNormalize = 75, + kCallSiteAPIGetFunctionSloppyCall = 76, + kCallSiteAPIGetThisSloppyCall = 77, + kRegExpMatchAllWithNonGlobalRegExp = 78, + kRegExpExecCalledOnSlowRegExp = 79, + kRegExpReplaceCalledOnSlowRegExp = 80, + kDisplayNames = 81, + kSharedArrayBufferConstructed = 82, + // Temporary kCallInDetachedWindowBy* counters are for reporting function + // calls within contexts marked using |SetDetachedWindowReason|. + // TODO(bartekn,chromium:1018156): Remove once not needed. + kCallInDetachedWindowByNavigation = 83, + kCallInDetachedWindowByNavigationAfter10s = 84, + kCallInDetachedWindowByNavigationAfter1min = 85, + kCallInDetachedWindowByClosing = 86, + kCallInDetachedWindowByClosingAfter10s = 87, + kCallInDetachedWindowByClosingAfter1min = 88, + kCallInDetachedWindowByOtherReason = 89, + kCallInDetachedWindowByOtherReasonAfter10s = 90, + kCallInDetachedWindowByOtherReasonAfter1min = 91, // If you add new values here, you'll also need to update Chromium's: - // web_feature.mojom, UseCounterCallback.cpp, and enums.xml. V8 changes to + // web_feature.mojom, use_counter_callback.cc, and enums.xml. V8 changes to // this list need to be landed first, then changes on the Chromium side. kUseCounterFeatureCount // This enum value must be last. }; @@ -7704,6 +8309,18 @@ class V8_EXPORT Isolate { */ static Isolate* GetCurrent(); + /** + * Clears the set of objects held strongly by the heap. This set of + * objects are originally built when a WeakRef is created or + * successfully dereferenced. + * + * The embedder is expected to call this when a synchronous sequence + * of ECMAScript execution completes. It's the embedders + * responsiblity to make this call at a time which does not + * interrupt synchronous ECMAScript code execution. + */ + void ClearKeptObjects(); + /** * Custom callback used by embedders to help V8 determine if it should abort * when it throws and no internal handler is predicted to catch the @@ -7717,6 +8334,14 @@ class V8_EXPORT Isolate { void SetAbortOnUncaughtExceptionCallback( AbortOnUncaughtExceptionCallback callback); + /** + * This specifies the callback to be called when finalization groups + * are ready to be cleaned up and require FinalizationGroup::Cleanup() + * to be called in a future task. + */ + void SetHostCleanupFinalizationGroupCallback( + HostCleanupFinalizationGroupCallback callback); + /** * This specifies the callback called by the upcoming dynamic * import() language feature to load modules. @@ -7861,6 +8486,17 @@ class V8_EXPORT Isolate { */ bool GetHeapCodeAndMetadataStatistics(HeapCodeStatistics* object_statistics); + /** + * Enqueues a memory measurement request for the given context and mode. + * This API is experimental and may change significantly. + * + * \param mode Indicates whether the result should include per-context + * memory usage or just the total memory usage. + * \returns a promise that will be resolved with memory usage estimate. + */ + v8::MaybeLocal MeasureMemory(v8::Local context, + MeasureMemoryMode mode); + /** * Get a call stack sample from the isolate. * \param state Execution state. @@ -7922,8 +8558,8 @@ class V8_EXPORT Isolate { Local GetCurrentContext(); /** Returns the last context entered through V8's C++ API. */ - V8_DEPRECATED("Use GetEnteredOrMicrotaskContext().", - Local GetEnteredContext()); + V8_DEPRECATED("Use GetEnteredOrMicrotaskContext().") + Local GetEnteredContext(); /** * Returns either the last context entered through V8's C++ API, or the @@ -8235,18 +8871,16 @@ class V8_EXPORT Isolate { * Executing scripts inside the callback will not re-trigger microtasks and * the callback. */ - V8_DEPRECATE_SOON("Use *WithData version.", - void AddMicrotasksCompletedCallback( - MicrotasksCompletedCallback callback)); + V8_DEPRECATE_SOON("Use *WithData version.") + void AddMicrotasksCompletedCallback(MicrotasksCompletedCallback callback); void AddMicrotasksCompletedCallback( MicrotasksCompletedCallbackWithData callback, void* data = nullptr); /** * Removes callback that was installed by AddMicrotasksCompletedCallback. */ - V8_DEPRECATE_SOON("Use *WithData version.", - void RemoveMicrotasksCompletedCallback( - MicrotasksCompletedCallback callback)); + V8_DEPRECATE_SOON("Use *WithData version.") + void RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallback callback); void RemoveMicrotasksCompletedCallback( MicrotasksCompletedCallbackWithData callback, void* data = nullptr); @@ -8270,6 +8904,13 @@ class V8_EXPORT Isolate { void SetCreateHistogramFunction(CreateHistogramCallback); void SetAddHistogramSampleFunction(AddHistogramSampleCallback); + /** + * Enables the host application to provide a mechanism for recording a + * predefined set of data as crash keys to be used in postmortem debugging in + * case of a crash. + */ + void SetAddCrashKeyCallback(AddCrashKeyCallback); + /** * Optional notification that the embedder is idle. * V8 uses the notification to perform garbage collection. @@ -8448,6 +9089,8 @@ class V8_EXPORT Isolate { */ void SetAllowCodeGenerationFromStringsCallback( AllowCodeGenerationFromStringsCallback callback); + void SetModifyCodeGenerationFromStringsCallback( + ModifyCodeGenerationFromStringsCallback callback); /** * Set the callback to invoke to check if wasm code generation should @@ -8467,6 +9110,8 @@ class V8_EXPORT Isolate { void SetWasmThreadsEnabledCallback(WasmThreadsEnabledCallback callback); + void SetWasmLoadSourceMapCallback(WasmLoadSourceMapCallback callback); + /** * Check if V8 is dead and therefore unusable. This is the case after * fatal errors such as out-of-memory situations. @@ -8610,6 +9255,13 @@ class V8_EXPORT Isolate { class V8_EXPORT StartupData { public: + /** + * Whether the data created can be rehashed and and the hash seed can be + * recomputed when deserialized. + * Only valid for StartupData returned by SnapshotCreator::CreateBlob(). + */ + bool CanBeRehashed() const; + const char* data; int raw_size; }; @@ -8658,7 +9310,6 @@ class V8_EXPORT V8 { * handled entirely on the embedders' side. * - The call will abort if the data is invalid. */ - static void SetNativesDataBlob(StartupData* startup_blob); static void SetSnapshotDataBlob(StartupData* startup_blob); /** Set the callback to invoke in case of Dcheck failures. */ @@ -8668,7 +9319,8 @@ class V8_EXPORT V8 { /** * Sets V8 flags from a string. */ - static void SetFlagsFromString(const char* str, int length); + static void SetFlagsFromString(const char* str); + static void SetFlagsFromString(const char* str, size_t length); /** * Sets V8 flags from the command line. @@ -8742,17 +9394,16 @@ class V8_EXPORT V8 { * V8 needs to be given those external files during startup. There are * three ways to do this: * - InitializeExternalStartupData(const char*) - * This will look in the given directory for files "natives_blob.bin" - * and "snapshot_blob.bin" - which is what the default build calls them. - * - InitializeExternalStartupData(const char*, const char*) - * As above, but will directly use the two given file names. - * - Call SetNativesDataBlob, SetNativesDataBlob. - * This will read the blobs from the given data structures and will + * This will look in the given directory for the file "snapshot_blob.bin". + * - InitializeExternalStartupDataFromFile(const char*) + * As above, but will directly use the given file name. + * - Call SetSnapshotDataBlob. + * This will read the blobs from the given data structure and will * not perform any file IO. */ static void InitializeExternalStartupData(const char* directory_path); - static void InitializeExternalStartupData(const char* natives_blob, - const char* snapshot_blob); + static void InitializeExternalStartupDataFromFile(const char* snapshot_blob); + /** * Sets the v8::Platform to use. This should be invoked before V8 is * initialized. @@ -8785,9 +9436,8 @@ class V8_EXPORT V8 { * \param context The third argument passed to the Linux signal handler, which * points to a ucontext_t structure. */ - V8_DEPRECATE_SOON("Use TryHandleWebAssemblyTrapPosix", - static bool TryHandleSignal(int signal_number, void* info, - void* context)); + V8_DEPRECATE_SOON("Use TryHandleWebAssemblyTrapPosix") + static bool TryHandleSignal(int signal_number, void* info, void* context); #endif // V8_OS_POSIX /** @@ -8812,6 +9462,11 @@ class V8_EXPORT V8 { UnhandledExceptionCallback unhandled_exception_callback); #endif + /** + * Get statistics about the shared memory usage. + */ + static void GetSharedMemoryStatistics(SharedMemoryStatistics* statistics); + private: V8(); @@ -8819,11 +9474,14 @@ class V8_EXPORT V8 { internal::Address* handle); static internal::Address* GlobalizeTracedReference(internal::Isolate* isolate, internal::Address* handle, - internal::Address* slot); + internal::Address* slot, + bool has_destructor); static void MoveGlobalReference(internal::Address** from, internal::Address** to); static void MoveTracedGlobalReference(internal::Address** from, internal::Address** to); + static void CopyTracedGlobalReference(const internal::Address* const* from, + internal::Address** to); static internal::Address* CopyGlobalReference(internal::Address* from); static void DisposeGlobal(internal::Address* global_handle); static void DisposeTracedGlobal(internal::Address* global_handle); @@ -8839,9 +9497,6 @@ class V8_EXPORT V8 { const char* label); static Value* Eternalize(Isolate* isolate, Value* handle); - static void RegisterExternallyReferencedObject(internal::Address* location, - internal::Isolate* isolate); - template friend class PersistentValueMapBase; @@ -8856,8 +9511,12 @@ class V8_EXPORT V8 { template friend class Maybe; template + friend class TracedReferenceBase; + template friend class TracedGlobal; template + friend class TracedReference; + template friend class WeakCallbackInfo; template friend class Eternal; template friend class PersistentBase; @@ -8929,6 +9588,7 @@ class V8_EXPORT SnapshotCreator { * Add a template to be included in the snapshot blob. * \returns the index of the template in the snapshot blob. */ + V8_DEPRECATED("use AddData instead") size_t AddTemplate(Local