aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/d8
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2019-09-24 11:56:38 -0400
committerMyles Borins <myles.borins@gmail.com>2019-10-07 03:19:23 -0400
commitf7f6c928c1c9c136b7926f892b8a2fda11d8b4b2 (patch)
treef5edbccb3ffda2573d70a6e291e7157f290e0ae0 /deps/v8/src/d8
parentffd22e81983056d09c064c59343a0e488236272d (diff)
downloadandroid-node-v8-f7f6c928c1c9c136b7926f892b8a2fda11d8b4b2.tar.gz
android-node-v8-f7f6c928c1c9c136b7926f892b8a2fda11d8b4b2.tar.bz2
android-node-v8-f7f6c928c1c9c136b7926f892b8a2fda11d8b4b2.zip
deps: update V8 to 7.8.279.9
PR-URL: https://github.com/nodejs/node/pull/29694 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Diffstat (limited to 'deps/v8/src/d8')
-rw-r--r--deps/v8/src/d8/d8.cc203
-rw-r--r--deps/v8/src/d8/d8.h29
2 files changed, 168 insertions, 64 deletions
diff --git a/deps/v8/src/d8/d8.cc b/deps/v8/src/d8/d8.cc
index 6656ab608d..13a35b0cd3 100644
--- a/deps/v8/src/d8/d8.cc
+++ b/deps/v8/src/d8/d8.cc
@@ -36,6 +36,7 @@
#include "src/init/v8.h"
#include "src/interpreter/interpreter.h"
#include "src/logging/counters.h"
+#include "src/objects/managed.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/parsing/parse-info.h"
@@ -76,7 +77,6 @@ namespace {
const int kMB = 1024 * 1024;
-const int kMaxWorkers = 100;
const int kMaxSerializerMemoryUsage =
1 * kMB; // Arbitrary maximum for testing.
@@ -227,14 +227,13 @@ Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) {
return nullptr;
}
- Worker* worker =
- static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0));
- if (worker == nullptr) {
+ i::Handle<i::Object> handle = Utils::OpenHandle(*object->GetInternalField(0));
+ if (handle->IsSmi()) {
Throw(isolate, "Worker is defunct because main thread is terminating");
return nullptr;
}
-
- return worker;
+ auto managed = i::Handle<i::Managed<Worker>>::cast(handle);
+ return managed->raw();
}
base::Thread::Options GetThreadOptions(const char* name) {
@@ -333,7 +332,7 @@ const base::TimeTicks Shell::kInitialTicks =
Global<Function> Shell::stringify_function_;
base::LazyMutex Shell::workers_mutex_;
bool Shell::allow_new_workers_ = true;
-std::vector<Worker*> Shell::workers_;
+std::unordered_set<std::shared_ptr<Worker>> Shell::running_workers_;
std::vector<ExternalizedContents> Shell::externalized_contents_;
std::atomic<bool> Shell::script_executed_{false};
base::LazyMutex Shell::isolate_status_lock_;
@@ -485,7 +484,7 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
} else if (options.stress_background_compile) {
// Start a background thread compiling the script.
BackgroundCompileThread background_compile_thread(isolate, source);
- background_compile_thread.Start();
+ CHECK(background_compile_thread.Start());
// In parallel, compile on the main thread to flush out any data races.
{
@@ -762,6 +761,16 @@ MaybeLocal<Promise> Shell::HostImportModuleDynamically(
return MaybeLocal<Promise>();
}
+void Shell::HostCleanupFinalizationGroup(Local<Context> context,
+ Local<FinalizationGroup> fg) {
+ Isolate* isolate = context->GetIsolate();
+ PerIsolateData::Get(isolate)->HostCleanupFinalizationGroup(fg);
+}
+
+void PerIsolateData::HostCleanupFinalizationGroup(Local<FinalizationGroup> fg) {
+ cleanup_finalization_groups_.emplace(isolate_, fg);
+}
+
void Shell::HostInitializeImportMetaObject(Local<Context> context,
Local<Module> module,
Local<Object> meta) {
@@ -908,6 +917,15 @@ MaybeLocal<Context> PerIsolateData::GetTimeoutContext() {
return result;
}
+MaybeLocal<FinalizationGroup> PerIsolateData::GetCleanupFinalizationGroup() {
+ if (cleanup_finalization_groups_.empty())
+ return MaybeLocal<FinalizationGroup>();
+ Local<FinalizationGroup> result =
+ cleanup_finalization_groups_.front().Get(isolate_);
+ cleanup_finalization_groups_.pop();
+ return result;
+}
+
PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) {
data_->realm_count_ = 1;
data_->realm_current_ = 0;
@@ -1392,30 +1410,36 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
+ // Initialize the embedder field to 0; if we return early without
+ // creating a new Worker (because the main thread is terminating) we can
+ // early-out from the instance calls.
+ args.Holder()->SetInternalField(0, v8::Integer::New(isolate, 0));
+
{
+ // Don't allow workers to create more workers if the main thread
+ // is waiting for existing running workers to terminate.
base::MutexGuard lock_guard(workers_mutex_.Pointer());
- if (workers_.size() >= kMaxWorkers) {
- Throw(args.GetIsolate(), "Too many workers, I won't let you create more");
- return;
- }
-
- // Initialize the embedder field to nullptr; if we return early without
- // creating a new Worker (because the main thread is terminating) we can
- // early-out from the instance calls.
- args.Holder()->SetAlignedPointerInInternalField(0, nullptr);
-
if (!allow_new_workers_) return;
- Worker* worker = new Worker;
- args.Holder()->SetAlignedPointerInInternalField(0, worker);
- workers_.push_back(worker);
-
String::Utf8Value script(args.GetIsolate(), source);
if (!*script) {
Throw(args.GetIsolate(), "Can't get worker script");
return;
}
- worker->StartExecuteInThread(*script);
+
+ // The C++ worker object's lifetime is shared between the Managed<Worker>
+ // object on the heap, which the JavaScript object points to, and an
+ // internal std::shared_ptr in the worker thread itself.
+ auto worker = std::make_shared<Worker>(*script);
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ const size_t kWorkerSizeEstimate = 4 * 1024 * 1024; // stack + heap.
+ i::Handle<i::Object> managed = i::Managed<Worker>::FromSharedPtr(
+ i_isolate, kWorkerSizeEstimate, worker);
+ args.Holder()->SetInternalField(0, Utils::ToLocal(managed));
+ if (!Worker::StartWorkerThread(std::move(worker))) {
+ Throw(args.GetIsolate(), "Can't start thread");
+ return;
+ }
}
}
@@ -1475,7 +1499,7 @@ void Shell::QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args) {
int exit_code = (*args)[0]
->Int32Value(args->GetIsolate()->GetCurrentContext())
.FromMaybe(0);
- CleanupWorkers();
+ WaitForRunningWorkers();
args->GetIsolate()->Exit();
OnExit(args->GetIsolate());
base::OS::ExitProcess(exit_code);
@@ -1920,6 +1944,9 @@ Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
EscapableHandleScope handle_scope(isolate);
Local<Context> context = Context::New(isolate, nullptr, global_template);
DCHECK(!context.IsEmpty());
+ if (i::FLAG_perf_prof_annotate_wasm) {
+ isolate->SetWasmLoadSourceMapCallback(ReadFile);
+ }
InitializeModuleEmbedderData(context);
if (options.include_arguments) {
Context::Scope scope(context);
@@ -2468,6 +2495,8 @@ void SourceGroup::ExecuteInThread() {
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = Shell::array_buffer_allocator;
Isolate* isolate = Isolate::New(create_params);
+ isolate->SetHostCleanupFinalizationGroupCallback(
+ Shell::HostCleanupFinalizationGroup);
isolate->SetHostImportModuleDynamicallyCallback(
Shell::HostImportModuleDynamically);
isolate->SetHostInitializeImportMetaObjectCallback(
@@ -2504,7 +2533,7 @@ void SourceGroup::ExecuteInThread() {
void SourceGroup::StartExecuteInThread() {
if (thread_ == nullptr) {
thread_ = new IsolateThread(this);
- thread_->Start();
+ CHECK(thread_->Start());
}
next_semaphore_.Signal();
}
@@ -2550,11 +2579,11 @@ void SerializationDataQueue::Clear() {
data_.clear();
}
-Worker::Worker()
+Worker::Worker(const char* script)
: in_semaphore_(0),
out_semaphore_(0),
thread_(nullptr),
- script_(nullptr),
+ script_(i::StrDup(script)),
running_(false) {}
Worker::~Worker() {
@@ -2562,15 +2591,29 @@ Worker::~Worker() {
thread_ = nullptr;
delete[] script_;
script_ = nullptr;
- in_queue_.Clear();
- out_queue_.Clear();
}
-void Worker::StartExecuteInThread(const char* script) {
- running_ = true;
- script_ = i::StrDup(script);
- thread_ = new WorkerThread(this);
- thread_->Start();
+bool Worker::StartWorkerThread(std::shared_ptr<Worker> worker) {
+ worker->running_ = true;
+ auto thread = new WorkerThread(worker);
+ worker->thread_ = thread;
+ if (thread->Start()) {
+ Shell::AddRunningWorker(std::move(worker));
+ return true;
+ }
+ return false;
+}
+
+void Worker::WorkerThread::Run() {
+ // Prevent a lifetime cycle from Worker -> WorkerThread -> Worker.
+ // We must clear the worker_ field of the thread, but we keep the
+ // worker alive via a stack root until the thread finishes execution
+ // and removes itself from the running set. Thereafter the only
+ // remaining reference can be from a JavaScript object via a Managed.
+ auto worker = std::move(worker_);
+ worker_ = nullptr;
+ worker->ExecuteInThread();
+ Shell::RemoveRunningWorker(worker);
}
void Worker::PostMessage(std::unique_ptr<SerializationData> data) {
@@ -2605,6 +2648,8 @@ void Worker::ExecuteInThread() {
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = Shell::array_buffer_allocator;
Isolate* isolate = Isolate::New(create_params);
+ isolate->SetHostCleanupFinalizationGroupCallback(
+ Shell::HostCleanupFinalizationGroup);
isolate->SetHostImportModuleDynamicallyCallback(
Shell::HostImportModuleDynamically);
isolate->SetHostInitializeImportMetaObjectCallback(
@@ -2657,6 +2702,7 @@ void Worker::ExecuteInThread() {
.ToLocalChecked();
if (onmessage->IsFunction()) {
Local<Function> onmessage_fun = Local<Function>::Cast(onmessage);
+ SealHandleScope shs(isolate);
// Now wait for messages
while (true) {
in_semaphore_.Wait();
@@ -2666,6 +2712,7 @@ void Worker::ExecuteInThread() {
break;
}
v8::TryCatch try_catch(isolate);
+ HandleScope scope(isolate);
Local<Value> value;
if (Shell::DeserializeValue(isolate, std::move(data))
.ToLocal(&value)) {
@@ -2936,7 +2983,7 @@ int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) {
options.isolate_sources[i].WaitForThread();
}
}
- CleanupWorkers();
+ WaitForRunningWorkers();
// In order to finish successfully, success must be != expected_to_throw.
return success == Shell::options.expected_to_throw ? 1 : 0;
}
@@ -2966,6 +3013,40 @@ void Shell::SetWaitUntilDone(Isolate* isolate, bool value) {
}
namespace {
+bool RunSetTimeoutCallback(Isolate* isolate, bool* did_run) {
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ HandleScope handle_scope(isolate);
+ Local<Function> callback;
+ if (!data->GetTimeoutCallback().ToLocal(&callback)) return true;
+ Local<Context> context;
+ if (!data->GetTimeoutContext().ToLocal(&context)) return true;
+ TryCatch try_catch(isolate);
+ try_catch.SetVerbose(true);
+ Context::Scope context_scope(context);
+ if (callback->Call(context, Undefined(isolate), 0, nullptr).IsEmpty()) {
+ Shell::ReportException(isolate, &try_catch);
+ return false;
+ }
+ *did_run = true;
+ return true;
+}
+
+bool RunCleanupFinalizationGroupCallback(Isolate* isolate, bool* did_run) {
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+ HandleScope handle_scope(isolate);
+ while (true) {
+ Local<FinalizationGroup> fg;
+ if (!data->GetCleanupFinalizationGroup().ToLocal(&fg)) return true;
+ *did_run = true;
+ TryCatch try_catch(isolate);
+ try_catch.SetVerbose(true);
+ if (FinalizationGroup::Cleanup(fg).IsNothing()) {
+ Shell::ReportException(isolate, &try_catch);
+ return false;
+ }
+ }
+}
+
bool ProcessMessages(
Isolate* isolate,
const std::function<platform::MessageLoopBehavior()>& behavior) {
@@ -2976,24 +3057,23 @@ bool ProcessMessages(
while (v8::platform::PumpMessageLoop(g_default_platform, isolate,
behavior())) {
MicrotasksScope::PerformCheckpoint(isolate);
+ isolate->ClearKeptObjects();
}
if (g_default_platform->IdleTasksEnabled(isolate)) {
v8::platform::RunIdleTasks(g_default_platform, isolate,
50.0 / base::Time::kMillisecondsPerSecond);
}
- HandleScope handle_scope(isolate);
- PerIsolateData* data = PerIsolateData::Get(isolate);
- Local<Function> callback;
- if (!data->GetTimeoutCallback().ToLocal(&callback)) break;
- Local<Context> context;
- if (!data->GetTimeoutContext().ToLocal(&context)) break;
- TryCatch try_catch(isolate);
- try_catch.SetVerbose(true);
- Context::Scope context_scope(context);
- if (callback->Call(context, Undefined(isolate), 0, nullptr).IsEmpty()) {
- Shell::ReportException(isolate, &try_catch);
+ bool ran_finalization_callback = false;
+ if (!RunCleanupFinalizationGroupCallback(isolate,
+ &ran_finalization_callback)) {
return false;
}
+ bool ran_set_timeout = false;
+ if (!RunSetTimeoutCallback(isolate, &ran_set_timeout)) {
+ return false;
+ }
+
+ if (!ran_set_timeout && !ran_finalization_callback) return true;
}
return true;
}
@@ -3267,24 +3347,35 @@ MaybeLocal<Value> Shell::DeserializeValue(
return deserializer.ReadValue(context);
}
-void Shell::CleanupWorkers() {
- // Make a copy of workers_, because we don't want to call Worker::Terminate
- // while holding the workers_mutex_ lock. Otherwise, if a worker is about to
- // create a new Worker, it would deadlock.
- std::vector<Worker*> workers_copy;
+void Shell::AddRunningWorker(std::shared_ptr<Worker> worker) {
+ workers_mutex_.Pointer()->AssertHeld(); // caller should hold the mutex.
+ running_workers_.insert(worker);
+}
+
+void Shell::RemoveRunningWorker(const std::shared_ptr<Worker>& worker) {
+ base::MutexGuard lock_guard(workers_mutex_.Pointer());
+ auto it = running_workers_.find(worker);
+ if (it != running_workers_.end()) running_workers_.erase(it);
+}
+
+void Shell::WaitForRunningWorkers() {
+ // Make a copy of running_workers_, because we don't want to call
+ // Worker::Terminate while holding the workers_mutex_ lock. Otherwise, if a
+ // worker is about to create a new Worker, it would deadlock.
+ std::unordered_set<std::shared_ptr<Worker>> workers_copy;
{
base::MutexGuard lock_guard(workers_mutex_.Pointer());
allow_new_workers_ = false;
- workers_copy.swap(workers_);
+ workers_copy.swap(running_workers_);
}
- for (Worker* worker : workers_copy) {
+ for (auto& worker : workers_copy) {
worker->WaitForThread();
- delete worker;
}
// Now that all workers are terminated, we can re-enable Worker creation.
base::MutexGuard lock_guard(workers_mutex_.Pointer());
+ DCHECK(running_workers_.empty());
allow_new_workers_ = true;
externalized_contents_.clear();
}
@@ -3405,6 +3496,8 @@ int Shell::Main(int argc, char* argv[]) {
}
Isolate* isolate = Isolate::New(create_params);
+ isolate->SetHostCleanupFinalizationGroupCallback(
+ Shell::HostCleanupFinalizationGroup);
isolate->SetHostImportModuleDynamicallyCallback(
Shell::HostImportModuleDynamically);
isolate->SetHostInitializeImportMetaObjectCallback(
@@ -3462,6 +3555,8 @@ int Shell::Main(int argc, char* argv[]) {
i::FLAG_hash_seed ^= 1337; // Use a different hash seed.
Isolate* isolate2 = Isolate::New(create_params);
i::FLAG_hash_seed ^= 1337; // Restore old hash seed.
+ isolate2->SetHostCleanupFinalizationGroupCallback(
+ Shell::HostCleanupFinalizationGroup);
isolate2->SetHostImportModuleDynamicallyCallback(
Shell::HostImportModuleDynamically);
isolate2->SetHostInitializeImportMetaObjectCallback(
diff --git a/deps/v8/src/d8/d8.h b/deps/v8/src/d8/d8.h
index 1e0dd43c2d..04fc5f5d34 100644
--- a/deps/v8/src/d8/d8.h
+++ b/deps/v8/src/d8/d8.h
@@ -11,6 +11,7 @@
#include <queue>
#include <string>
#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "src/base/once.h"
@@ -207,12 +208,9 @@ class SerializationDataQueue {
class Worker {
public:
- Worker();
+ explicit Worker(const char* script);
~Worker();
- // Run the given script on this Worker. This function should only be called
- // once, and should only be called by the thread that created the Worker.
- void StartExecuteInThread(const char* script);
// Post a message to the worker's incoming message queue. The worker will
// take ownership of the SerializationData.
// This function should only be called by the thread that created the Worker.
@@ -231,17 +229,20 @@ class Worker {
// This function can be called by any thread.
void WaitForThread();
+ // Start running the given worker in another thread.
+ static bool StartWorkerThread(std::shared_ptr<Worker> worker);
+
private:
class WorkerThread : public base::Thread {
public:
- explicit WorkerThread(Worker* worker)
+ explicit WorkerThread(std::shared_ptr<Worker> worker)
: base::Thread(base::Thread::Options("WorkerThread")),
- worker_(worker) {}
+ worker_(std::move(worker)) {}
- void Run() override { worker_->ExecuteInThread(); }
+ void Run() override;
private:
- Worker* worker_;
+ std::shared_ptr<Worker> worker_;
};
void ExecuteInThread();
@@ -275,6 +276,8 @@ class PerIsolateData {
PerIsolateData* data_;
};
+ inline void HostCleanupFinalizationGroup(Local<FinalizationGroup> fg);
+ inline MaybeLocal<FinalizationGroup> GetCleanupFinalizationGroup();
inline void SetTimeout(Local<Function> callback, Local<Context> context);
inline MaybeLocal<Function> GetTimeoutCallback();
inline MaybeLocal<Context> GetTimeoutContext();
@@ -292,6 +295,7 @@ class PerIsolateData {
Global<Value> realm_shared_;
std::queue<Global<Function>> set_timeout_callbacks_;
std::queue<Global<Context>> set_timeout_contexts_;
+ std::queue<Global<FinalizationGroup>> cleanup_finalization_groups_;
AsyncHooks* async_hooks_wrapper_;
int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
@@ -378,7 +382,6 @@ class Shell : public i::AllStatic {
Isolate* isolate, Local<Value> value, Local<Value> transfer);
static MaybeLocal<Value> DeserializeValue(
Isolate* isolate, std::unique_ptr<SerializationData> data);
- static void CleanupWorkers();
static int* LookupCounter(const char* name);
static void* CreateHistogram(const char* name, int min, int max,
size_t buckets);
@@ -465,6 +468,8 @@ class Shell : public i::AllStatic {
static void SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args);
static void MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void HostCleanupFinalizationGroup(Local<Context> context,
+ Local<FinalizationGroup> fg);
static MaybeLocal<Promise> HostImportModuleDynamically(
Local<Context> context, Local<ScriptOrModule> referrer,
Local<String> specifier);
@@ -493,6 +498,10 @@ class Shell : public i::AllStatic {
!options.test_shell;
}
+ static void WaitForRunningWorkers();
+ static void AddRunningWorker(std::shared_ptr<Worker> worker);
+ static void RemoveRunningWorker(const std::shared_ptr<Worker>& worker);
+
private:
static Global<Context> evaluation_context_;
static base::OnceType quit_once_;
@@ -509,7 +518,7 @@ class Shell : public i::AllStatic {
static base::LazyMutex workers_mutex_; // Guards the following members.
static bool allow_new_workers_;
- static std::vector<Worker*> workers_;
+ static std::unordered_set<std::shared_ptr<Worker>> running_workers_;
static std::vector<ExternalizedContents> externalized_contents_;
// Multiple isolates may update this flag concurrently.