diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-05-20 09:47:09 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-06-07 11:15:42 +0000 |
commit | 189d4fd8fad9e3c776873be51938cd31a42b6177 (patch) | |
tree | 6497caeff5e383937996768766ab3bb2081a40b2 /chromium/gin | |
parent | 8bc75099d364490b22f43a7ce366b366c08f4164 (diff) | |
download | qtwebengine-chromium-189d4fd8fad9e3c776873be51938cd31a42b6177.tar.gz |
BASELINE: Update Chromium to 90.0.4430.221
Change-Id: Iff4d9d18d2fcf1a576f3b1f453010f744a232920
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/gin')
-rw-r--r-- | chromium/gin/OWNERS | 1 | ||||
-rw-r--r-- | chromium/gin/array_buffer.cc | 114 | ||||
-rw-r--r-- | chromium/gin/array_buffer.h | 15 | ||||
-rw-r--r-- | chromium/gin/function_template.h | 5 | ||||
-rw-r--r-- | chromium/gin/gin_features.cc | 16 | ||||
-rw-r--r-- | chromium/gin/gin_features.h | 4 | ||||
-rw-r--r-- | chromium/gin/modules/console.cc | 6 | ||||
-rw-r--r-- | chromium/gin/public/gin_embedders.h | 8 | ||||
-rw-r--r-- | chromium/gin/v8_foreground_task_runner.cc | 12 | ||||
-rw-r--r-- | chromium/gin/v8_foreground_task_runner.h | 4 | ||||
-rw-r--r-- | chromium/gin/v8_initializer.cc | 26 | ||||
-rw-r--r-- | chromium/gin/v8_isolate_memory_dump_provider.cc | 8 | ||||
-rw-r--r-- | chromium/gin/v8_platform.cc | 34 | ||||
-rw-r--r-- | chromium/gin/v8_platform_unittest.cc | 61 | ||||
-rw-r--r-- | chromium/gin/wrappable.h | 2 |
15 files changed, 175 insertions, 141 deletions
diff --git a/chromium/gin/OWNERS b/chromium/gin/OWNERS index 3ac44eb8e9f..79b041ed379 100644 --- a/chromium/gin/OWNERS +++ b/chromium/gin/OWNERS @@ -1,3 +1,4 @@ +set noparent jochen@chromium.org jbroman@chromium.org rmcilroy@chromium.org diff --git a/chromium/gin/array_buffer.cc b/chromium/gin/array_buffer.cc index 124c2f72a5c..210760801f1 100644 --- a/chromium/gin/array_buffer.cc +++ b/chromium/gin/array_buffer.cc @@ -23,12 +23,6 @@ namespace gin { -namespace { - -gin::WrapperInfo g_array_buffer_wrapper_info = {gin::kEmbedderNativeGin}; - -} // namespace - static_assert(V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT == 2, "array buffers must have two internal fields"); @@ -52,113 +46,11 @@ ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() { return instance; } -// ArrayBuffer::Private ------------------------------------------------------- - -// This class exists to solve a tricky lifetime problem. The V8 API doesn't -// want to expose a direct view into the memory behind an array buffer because -// V8 might deallocate that memory during garbage collection. Instead, the V8 -// API forces us to externalize the buffer and take ownership of the memory. -// In order to know when to free the memory, we need to figure out both when -// we're done with it and when V8 is done with it. -// -// To determine whether we're done with the memory, every view we have into -// the array buffer takes a reference to the ArrayBuffer::Private object that -// actually owns the memory. To determine when V8 is done with the memory, we -// open a weak handle to the ArrayBuffer object. When we receive the weak -// callback, we know the object is about to be garbage collected and we can -// drop V8's implied reference to the memory. -// -// The final subtlety is that we need every ArrayBuffer into the same array -// buffer to AddRef the same ArrayBuffer::Private. To make that work, we store -// a pointer to the ArrayBuffer::Private object in an internal field of the -// ArrayBuffer object. -// -class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> { - public: - static scoped_refptr<Private> From(v8::Isolate* isolate, - v8::Local<v8::ArrayBuffer> array); - - void* buffer() const { return buffer_; } - size_t length() const { return length_; } - - private: - friend class base::RefCounted<Private>; - using DataDeleter = void (*)(void* data, size_t length, void* info); - - Private(v8::Isolate* isolate, v8::Local<v8::ArrayBuffer> array); - ~Private(); - - static void FirstWeakCallback(const v8::WeakCallbackInfo<Private>& data); - static void SecondWeakCallback(const v8::WeakCallbackInfo<Private>& data); - - v8::Global<v8::ArrayBuffer> array_buffer_; - scoped_refptr<Private> self_reference_; - v8::Isolate* isolate_; - void* buffer_; - size_t length_; - DataDeleter deleter_; - void* deleter_data_; -}; - -scoped_refptr<ArrayBuffer::Private> ArrayBuffer::Private::From( - v8::Isolate* isolate, v8::Local<v8::ArrayBuffer> array) { - if (array->IsExternal()) { - CHECK_EQ(WrapperInfo::From(v8::Local<v8::Object>::Cast(array)), - &g_array_buffer_wrapper_info) - << "Cannot mix blink and gin ArrayBuffers"; - return base::WrapRefCounted(static_cast<Private*>( - array->GetAlignedPointerFromInternalField(kEncodedValueIndex))); - } - return base::WrapRefCounted(new Private(isolate, array)); -} - -ArrayBuffer::Private::Private(v8::Isolate* isolate, - v8::Local<v8::ArrayBuffer> array) - : array_buffer_(isolate, array), isolate_(isolate) { - // Take ownership of the array buffer. - CHECK(!array->IsExternal()); - v8::ArrayBuffer::Contents contents = array->Externalize(); - buffer_ = contents.Data(); - length_ = contents.ByteLength(); - deleter_ = contents.Deleter(); - deleter_data_ = contents.DeleterData(); - - array->SetAlignedPointerInInternalField(kWrapperInfoIndex, - &g_array_buffer_wrapper_info); - array->SetAlignedPointerInInternalField(kEncodedValueIndex, this); - - self_reference_ = this; // Cleared in SecondWeakCallback. - array_buffer_.SetWeak(this, FirstWeakCallback, - v8::WeakCallbackType::kParameter); -} - -ArrayBuffer::Private::~Private() { - deleter_(buffer_, length_, deleter_data_); -} - -void ArrayBuffer::Private::FirstWeakCallback( - const v8::WeakCallbackInfo<Private>& data) { - Private* parameter = data.GetParameter(); - parameter->array_buffer_.Reset(); - data.SetSecondPassCallback(SecondWeakCallback); -} - -void ArrayBuffer::Private::SecondWeakCallback( - const v8::WeakCallbackInfo<Private>& data) { - Private* parameter = data.GetParameter(); - parameter->self_reference_.reset(); -} - // ArrayBuffer ---------------------------------------------------------------- +ArrayBuffer::ArrayBuffer() = default; -ArrayBuffer::ArrayBuffer() : bytes_(nullptr), num_bytes_(0) {} - -ArrayBuffer::ArrayBuffer(v8::Isolate* isolate, - v8::Local<v8::ArrayBuffer> array) { - private_ = ArrayBuffer::Private::From(isolate, array); - bytes_ = private_->buffer(); - num_bytes_ = private_->length(); -} +ArrayBuffer::ArrayBuffer(v8::Isolate* isolate, v8::Local<v8::ArrayBuffer> array) + : backing_store_(array->GetBackingStore()) {} ArrayBuffer::~ArrayBuffer() = default; diff --git a/chromium/gin/array_buffer.h b/chromium/gin/array_buffer.h index 2aef366ac81..086371af29b 100644 --- a/chromium/gin/array_buffer.h +++ b/chromium/gin/array_buffer.h @@ -33,16 +33,15 @@ class GIN_EXPORT ArrayBuffer { ~ArrayBuffer(); ArrayBuffer& operator=(const ArrayBuffer& other); - void* bytes() const { return bytes_; } - size_t num_bytes() const { return num_bytes_; } + void* bytes() const { + return backing_store_ ? backing_store_->Data() : nullptr; + } + size_t num_bytes() const { + return backing_store_ ? backing_store_->ByteLength() : 0; + } private: - class Private; - - scoped_refptr<Private> private_; - void* bytes_; - size_t num_bytes_; - + std::shared_ptr<v8::BackingStore> backing_store_; DISALLOW_COPY(ArrayBuffer); }; diff --git a/chromium/gin/function_template.h b/chromium/gin/function_template.h index 3f6a1ddfead..2c13d418a09 100644 --- a/chromium/gin/function_template.h +++ b/chromium/gin/function_template.h @@ -248,9 +248,8 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New( isolate, &internal::Dispatcher<Sig>::DispatchToCallback, - ConvertToV8<v8::Local<v8::External>>(isolate, - holder->GetHandle(isolate))); - tmpl->RemovePrototype(); + ConvertToV8<v8::Local<v8::External>>(isolate, holder->GetHandle(isolate)), + v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kThrow); return tmpl; } diff --git a/chromium/gin/gin_features.cc b/chromium/gin/gin_features.cc index b200a04e342..a2137abed41 100644 --- a/chromium/gin/gin_features.cc +++ b/chromium/gin/gin_features.cc @@ -50,4 +50,20 @@ const base::Feature kV8LocalHeaps{"V8LocalHeaps", const base::Feature kV8TurboDirectHeapAccess{"V8TurboDirectHeapAccess", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables fallback to a breadth-first regexp engine on excessive backtracking. +const base::Feature kV8ExperimentalRegexpEngine{ + "V8ExperimentalRegexpEngine", base::FEATURE_ENABLED_BY_DEFAULT}; + +// Enables experimental Turboprop compiler. +const base::Feature kV8Turboprop{"V8Turboprop", + base::FEATURE_DISABLED_BY_DEFAULT}; + +// Enables experimental Sparkplug compiler. +const base::Feature kV8Sparkplug{"V8Sparkplug", + base::FEATURE_DISABLED_BY_DEFAULT}; + +// Enables fast API calls in TurboFan. +const base::Feature kV8TurboFastApiCalls{"V8TurboFastApiCalls", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features diff --git a/chromium/gin/gin_features.h b/chromium/gin/gin_features.h index 0e2b51c83f3..f1158d05dbb 100644 --- a/chromium/gin/gin_features.h +++ b/chromium/gin/gin_features.h @@ -21,6 +21,10 @@ GIN_EXPORT extern const base::Feature kV8ReduceConcurrentMarkingTasks; GIN_EXPORT extern const base::Feature kV8NoReclaimUnmodifiedWrappers; GIN_EXPORT extern const base::Feature kV8LocalHeaps; GIN_EXPORT extern const base::Feature kV8TurboDirectHeapAccess; +GIN_EXPORT extern const base::Feature kV8ExperimentalRegexpEngine; +GIN_EXPORT extern const base::Feature kV8TurboFastApiCalls; +GIN_EXPORT extern const base::Feature kV8Turboprop; +GIN_EXPORT extern const base::Feature kV8Sparkplug; } // namespace features diff --git a/chromium/gin/modules/console.cc b/chromium/gin/modules/console.cc index 8786392b9e6..7e3087fb982 100644 --- a/chromium/gin/modules/console.cc +++ b/chromium/gin/modules/console.cc @@ -29,9 +29,9 @@ void Log(const v8::FunctionCallbackInfo<v8::Value>& info) { // static void Console::Register(v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> templ) { - v8::Local<v8::FunctionTemplate> log_templ = - v8::FunctionTemplate::New(isolate, Log); - log_templ->RemovePrototype(); + v8::Local<v8::FunctionTemplate> log_templ = v8::FunctionTemplate::New( + isolate, Log, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, + v8::ConstructorBehavior::kThrow); templ->Set(StringToSymbol(isolate, "log"), log_templ); } diff --git a/chromium/gin/public/gin_embedders.h b/chromium/gin/public/gin_embedders.h index 30f48a6c859..e88cc0a555b 100644 --- a/chromium/gin/public/gin_embedders.h +++ b/chromium/gin/public/gin_embedders.h @@ -5,13 +5,17 @@ #ifndef GIN_PUBLIC_GIN_EMBEDDERS_H_ #define GIN_PUBLIC_GIN_EMBEDDERS_H_ +#include <cstdint> + namespace gin { // The GinEmbedder is used to identify the owner of embedder data stored on // v8 objects, and is used as in index into the embedder data slots of a // v8::Isolate. - -enum GinEmbedder { +// +// GinEmbedder is using uint16_t as underlying storage as V8 requires that +// external pointers in embedder fields are at least 2-byte-aligned. +enum GinEmbedder : uint16_t { kEmbedderNativeGin, kEmbedderBlink, kEmbedderPDFium, diff --git a/chromium/gin/v8_foreground_task_runner.cc b/chromium/gin/v8_foreground_task_runner.cc index f0b1209babe..4d93e27b64b 100644 --- a/chromium/gin/v8_foreground_task_runner.cc +++ b/chromium/gin/v8_foreground_task_runner.cc @@ -37,6 +37,14 @@ void V8ForegroundTaskRunner::PostDelayedTask(std::unique_ptr<v8::Task> task, base::TimeDelta::FromSecondsD(delay_in_seconds)); } +void V8ForegroundTaskRunner::PostNonNestableDelayedTask( + std::unique_ptr<v8::Task> task, + double delay_in_seconds) { + task_runner_->PostNonNestableDelayedTask( + FROM_HERE, base::BindOnce(&v8::Task::Run, std::move(task)), + base::TimeDelta::FromSecondsD(delay_in_seconds)); +} + void V8ForegroundTaskRunner::PostIdleTask(std::unique_ptr<v8::IdleTask> task) { DCHECK(IdleTasksEnabled()); idle_task_runner()->PostIdleTask(std::move(task)); @@ -46,4 +54,8 @@ bool V8ForegroundTaskRunner::NonNestableTasksEnabled() const { return true; } +bool V8ForegroundTaskRunner::NonNestableDelayedTasksEnabled() const { + return true; +} + } // namespace gin diff --git a/chromium/gin/v8_foreground_task_runner.h b/chromium/gin/v8_foreground_task_runner.h index 62e4f3ad450..2f8a6ffebf3 100644 --- a/chromium/gin/v8_foreground_task_runner.h +++ b/chromium/gin/v8_foreground_task_runner.h @@ -29,9 +29,13 @@ class V8ForegroundTaskRunner : public V8ForegroundTaskRunnerBase { void PostDelayedTask(std::unique_ptr<v8::Task> task, double delay_in_seconds) override; + void PostNonNestableDelayedTask(std::unique_ptr<v8::Task> task, + double delay_in_seconds) override; + void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override; bool NonNestableTasksEnabled() const override; + bool NonNestableDelayedTasksEnabled() const override; private: scoped_refptr<base::SingleThreadTaskRunner> task_runner_; diff --git a/chromium/gin/v8_initializer.cc b/chromium/gin/v8_initializer.cc index 4174fd98f3a..e9cc71b9684 100644 --- a/chromium/gin/v8_initializer.cc +++ b/chromium/gin/v8_initializer.cc @@ -288,6 +288,32 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode) { v8::V8::SetFlagsFromString(no_direct_access, sizeof(no_direct_access) - 1); } + if (!base::FeatureList::IsEnabled(features::kV8ExperimentalRegexpEngine)) { + // The --enable-experimental-regexp-engine-on-excessive-backtracks flag is + // enabled by default, so we need to explicitly disable it if + // kV8ExperimentalRegexpEngine is disabled. + static constexpr char no_experimental_regexp_engine[] = + "--no-enable-experimental-regexp-engine-on-excessive-backtracks"; + v8::V8::SetFlagsFromString(no_experimental_regexp_engine, + sizeof(no_experimental_regexp_engine) - 1); + } + + if (base::FeatureList::IsEnabled(features::kV8TurboFastApiCalls)) { + static const char turbo_fast_api_calls[] = "--turbo-fast-api-calls"; + v8::V8::SetFlagsFromString(turbo_fast_api_calls, + sizeof(turbo_fast_api_calls) - 1); + } + + if (base::FeatureList::IsEnabled(features::kV8Turboprop)) { + static const char turboprop[] = "--turboprop"; + v8::V8::SetFlagsFromString(turboprop, sizeof(turboprop) - 1); + } + + if (base::FeatureList::IsEnabled(features::kV8Sparkplug)) { + static const char sparkplug[] = "--sparkplug"; + v8::V8::SetFlagsFromString(sparkplug, sizeof(sparkplug) - 1); + } + if (IsolateHolder::kStrictMode == mode) { static const char use_strict[] = "--use_strict"; v8::V8::SetFlagsFromString(use_strict, sizeof(use_strict) - 1); diff --git a/chromium/gin/v8_isolate_memory_dump_provider.cc b/chromium/gin/v8_isolate_memory_dump_provider.cc index 8df3b0f5e86..3f1f9954af8 100644 --- a/chromium/gin/v8_isolate_memory_dump_provider.cc +++ b/chromium/gin/v8_isolate_memory_dump_provider.cc @@ -264,6 +264,14 @@ void V8IsolateMemoryDumpProvider::DumpHeapStatistics( base::trace_event::MemoryAllocatorDump::kNameSize, base::trace_event::MemoryAllocatorDump::kUnitsBytes, heap_statistics.total_global_handles_size()); + global_handles_dump->AddScalar( + "allocated_objects_size", + base::trace_event::MemoryAllocatorDump::kUnitsBytes, + heap_statistics.used_global_handles_size()); + if (system_allocator_name) { + process_memory_dump->AddSuballocation(global_handles_dump->guid(), + system_allocator_name); + } // Dump object statistics only for detailed dumps. if (args.level_of_detail != diff --git a/chromium/gin/v8_platform.cc b/chromium/gin/v8_platform.cc index 68415704fd7..71b0ec4a05d 100644 --- a/chromium/gin/v8_platform.cc +++ b/chromium/gin/v8_platform.cc @@ -22,6 +22,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/trace_event/trace_event.h" +#include "base/tracing_buildflags.h" #include "build/build_config.h" #include "gin/per_isolate_data.h" @@ -245,7 +246,8 @@ class PageAllocator : public v8::PageAllocator { // On Windows, we can only de-commit the trailing pages. FreePages() will // still free all pages in the region including the released tail, so it's // safe to just decommit the tail. - base::DecommitSystemPages(release_base, release_size); + base::DecommitSystemPages(release_base, release_size, + base::PageUpdatePermissions); #else #error Unsupported platform #endif @@ -257,7 +259,12 @@ class PageAllocator : public v8::PageAllocator { Permission permissions) override { // If V8 sets permissions to none, we can discard the memory. if (permissions == v8::PageAllocator::Permission::kNoAccess) { - base::DecommitSystemPages(address, length); + // Use PageKeepPermissionsIfPossible as an optimization, to avoid perf + // regression (see crrev.com/c/2563038 for details). This may cause the + // memory region to still be accessible on certain platforms, but at least + // the physical pages will be discarded. + base::DecommitSystemPages(address, length, + base::PageKeepPermissionsIfPossible); return true; } else { return base::TrySetSystemPagesAccess(address, length, @@ -298,8 +305,7 @@ class JobDelegateImpl : public v8::JobDelegate { class JobHandleImpl : public v8::JobHandle { public: - JobHandleImpl(base::JobHandle handle, std::unique_ptr<v8::JobTask> job_task) - : handle_(std::move(handle)), job_task_(std::move(job_task)) {} + explicit JobHandleImpl(base::JobHandle handle) : handle_(std::move(handle)) {} ~JobHandleImpl() override = default; JobHandleImpl(const JobHandleImpl&) = delete; @@ -316,8 +322,8 @@ class JobHandleImpl : public v8::JobHandle { void Join() override { handle_.Join(); } void Cancel() override { handle_.Cancel(); } void CancelAndDetach() override { handle_.CancelAndDetach(); } - bool IsCompleted() override { return handle_.IsCompleted(); } - bool IsRunning() override { return !!handle_; } + bool IsActive() override { return handle_.IsActive(); } + bool IsValid() override { return !!handle_; } private: static base::TaskPriority ToBaseTaskPriority(v8::TaskPriority priority) { @@ -332,7 +338,6 @@ class JobHandleImpl : public v8::JobHandle { } base::JobHandle handle_; - std::unique_ptr<v8::JobTask> job_task_; }; } // namespace @@ -363,6 +368,7 @@ class V8Platform::TracingControllerImpl : public v8::TracingController { ~TracingControllerImpl() override = default; // TracingController implementation. +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) const uint8_t* GetCategoryGroupEnabled(const char* name) override { return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name); } @@ -430,6 +436,7 @@ class V8Platform::TracingControllerImpl : public v8::TracingController { TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name, traceEventHandle); } +#endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) void AddTraceStateObserver(TraceStateObserver* observer) override { g_trace_state_dispatcher.Get().AddObserver(observer); } @@ -522,22 +529,25 @@ std::unique_ptr<v8::JobHandle> V8Platform::PostJob( task_traits = kBlockingTaskTraits; break; } + // Ownership of |job_task| is assumed by |worker_task|, while + // |max_concurrency_callback| uses an unretained pointer. + auto* job_task_ptr = job_task.get(); auto handle = base::PostJob(FROM_HERE, task_traits, base::BindRepeating( - [](v8::JobTask* job_task, base::JobDelegate* delegate) { + [](const std::unique_ptr<v8::JobTask>& job_task, + base::JobDelegate* delegate) { JobDelegateImpl delegate_impl(delegate); job_task->Run(&delegate_impl); }, - base::Unretained(job_task.get())), + std::move(job_task)), base::BindRepeating( [](v8::JobTask* job_task, size_t worker_count) { return job_task->GetMaxConcurrency(worker_count); }, - base::Unretained(job_task.get()))); + base::Unretained(job_task_ptr))); - return std::make_unique<JobHandleImpl>(std::move(handle), - std::move(job_task)); + return std::make_unique<JobHandleImpl>(std::move(handle)); } bool V8Platform::IdleTasksEnabled(v8::Isolate* isolate) { diff --git a/chromium/gin/v8_platform_unittest.cc b/chromium/gin/v8_platform_unittest.cc index 8dbfbd4342e..332e0f7995c 100644 --- a/chromium/gin/v8_platform_unittest.cc +++ b/chromium/gin/v8_platform_unittest.cc @@ -6,7 +6,9 @@ #include <atomic> +#include "base/barrier_closure.h" #include "base/test/task_environment.h" +#include "base/test/test_waitable_event.h" #include "base/trace_event/trace_event.h" #include "testing/gtest/include/gtest/gtest.h" @@ -84,10 +86,65 @@ TEST(V8PlatformTest, PostJobSimple) { auto handle = V8Platform::Get()->PostJob(v8::TaskPriority::kUserVisible, std::make_unique<Task>(&num_tasks_to_run)); - EXPECT_TRUE(handle->IsRunning()); + EXPECT_TRUE(handle->IsValid()); handle->Join(); - EXPECT_FALSE(handle->IsRunning()); + EXPECT_FALSE(handle->IsValid()); DCHECK_EQ(num_tasks_to_run, 0U); } +// Tests that JobTask's lifetime is extended beyond job handle, until no +// references are left; and is gracefully destroyed. +TEST(V8PlatformTest, PostJobLifetime) { + std::atomic_size_t num_tasks_to_run(4); + + base::TestWaitableEvent threads_running; + base::TestWaitableEvent threads_continue; + base::RepeatingClosure threads_running_barrier = base::BarrierClosure( + num_tasks_to_run, + BindOnce(&base::TestWaitableEvent::Signal, Unretained(&threads_running))); + + class Task : public v8::JobTask { + public: + explicit Task(std::atomic_size_t* num_tasks_to_run, + base::RepeatingClosure threads_running_barrier, + base::TestWaitableEvent* threads_continue) + : num_tasks_to_run_(num_tasks_to_run), + threads_running_barrier_(std::move(threads_running_barrier)), + threads_continue_(threads_continue) {} + ~Task() override { + // This should only be destroyed once all workers returned. + EXPECT_EQ(*num_tasks_to_run_, 0U); + } + + void Run(v8::JobDelegate* delegate) override { + threads_running_barrier_.Run(); + threads_continue_->Wait(); + --(*num_tasks_to_run_); + } + + size_t GetMaxConcurrency(size_t /* worker_count*/) const override { + return *num_tasks_to_run_; + } + + std::atomic_size_t* num_tasks_to_run_; + base::RepeatingClosure threads_running_barrier_; + base::TestWaitableEvent* threads_continue_; + }; + + base::test::TaskEnvironment task_environment; + + auto handle = V8Platform::Get()->PostJob( + v8::TaskPriority::kUserVisible, + std::make_unique<Task>(&num_tasks_to_run, + std::move(threads_running_barrier), + &threads_continue)); + EXPECT_TRUE(handle->IsValid()); + threads_running.Wait(); + handle->CancelAndDetach(); + handle.reset(); + + // Release workers and let the job get destroyed. + threads_continue.Signal(); +} + } // namespace gin diff --git a/chromium/gin/wrappable.h b/chromium/gin/wrappable.h index d558ffb6d68..f9b7b938cb7 100644 --- a/chromium/gin/wrappable.h +++ b/chromium/gin/wrappable.h @@ -120,6 +120,8 @@ struct Converter<T*, typename std::enable_if< std::is_convertible<T*, WrappableBase*>::value>::type> { static v8::MaybeLocal<v8::Value> ToV8(v8::Isolate* isolate, T* val) { + if (val == nullptr) + return v8::Null(isolate); v8::Local<v8::Object> wrapper; if (!val->GetWrapper(isolate).ToLocal(&wrapper)) return v8::MaybeLocal<v8::Value>(); |