summaryrefslogtreecommitdiff
path: root/src/node_main_instance.cc
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2019-04-14 14:41:04 +0800
committerJoyee Cheung <joyeec9h3@gmail.com>2019-04-17 02:44:24 +0800
commitcab1dc5bb346b6c4d0e02e6785715af6ff6fb090 (patch)
tree9978077693ef273f3d19bf2b4f1a9e1cc9df1582 /src/node_main_instance.cc
parentc6c37e9e850fa2a30b12a0d0fd0dfe144eda0959 (diff)
downloadandroid-node-v8-cab1dc5bb346b6c4d0e02e6785715af6ff6fb090.tar.gz
android-node-v8-cab1dc5bb346b6c4d0e02e6785715af6ff6fb090.tar.bz2
android-node-v8-cab1dc5bb346b6c4d0e02e6785715af6ff6fb090.zip
src: use RAII to manage the main isolate data
This patch encapsulates the main isolate management into a NodeMainInstance class that manages the resources with RAII and controls the Isolate::CreateParams (which is necessary for deserializing snapshots with external references) PR-URL: https://github.com/nodejs/node/pull/27220 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'src/node_main_instance.cc')
-rw-r--r--src/node_main_instance.cc162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc
new file mode 100644
index 0000000000..6ef992d006
--- /dev/null
+++ b/src/node_main_instance.cc
@@ -0,0 +1,162 @@
+#include "node_main_instance.h"
+#include "node_internals.h"
+#include "node_options-inl.h"
+#include "node_v8_platform-inl.h"
+
+namespace node {
+
+using v8::Context;
+using v8::HandleScope;
+using v8::Isolate;
+using v8::Local;
+using v8::Locker;
+using v8::SealHandleScope;
+
+NodeMainInstance::NodeMainInstance(uv_loop_t* event_loop,
+ const std::vector<std::string>& args,
+ const std::vector<std::string>& exec_args)
+ : args_(args),
+ exec_args_(exec_args),
+ array_buffer_allocator_(ArrayBufferAllocator::Create()),
+ isolate_(nullptr),
+ isolate_data_(nullptr) {
+ // TODO(joyeecheung): when we implement snapshot integration this needs to
+ // set params.external_references.
+ Isolate::CreateParams params;
+ params.array_buffer_allocator = array_buffer_allocator_.get();
+ isolate_ =
+ NewIsolate(&params, event_loop, per_process::v8_platform.Platform());
+ CHECK_NOT_NULL(isolate_);
+ isolate_data_.reset(CreateIsolateData(isolate_,
+ event_loop,
+ per_process::v8_platform.Platform(),
+ array_buffer_allocator_.get()));
+}
+
+NodeMainInstance::~NodeMainInstance() {
+ isolate_->Dispose();
+ per_process::v8_platform.Platform()->UnregisterIsolate(isolate_);
+}
+
+int NodeMainInstance::Run() {
+ Locker locker(isolate_);
+ Isolate::Scope isolate_scope(isolate_);
+ HandleScope handle_scope(isolate_);
+
+ int exit_code = 0;
+ std::unique_ptr<Environment> env = CreateMainEnvironment(&exit_code);
+
+ CHECK_NOT_NULL(env);
+ Context::Scope context_scope(env->context());
+
+ if (exit_code == 0) {
+ {
+ AsyncCallbackScope callback_scope(env.get());
+ env->async_hooks()->push_async_ids(1, 0);
+ LoadEnvironment(env.get());
+ env->async_hooks()->pop_async_id(1);
+ }
+
+ {
+ SealHandleScope seal(isolate_);
+ bool more;
+ env->performance_state()->Mark(
+ node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
+ do {
+ uv_run(env->event_loop(), UV_RUN_DEFAULT);
+
+ per_process::v8_platform.DrainVMTasks(isolate_);
+
+ more = uv_loop_alive(env->event_loop());
+ if (more && !env->is_stopping()) continue;
+
+ env->RunBeforeExitCallbacks();
+
+ if (!uv_loop_alive(env->event_loop())) {
+ EmitBeforeExit(env.get());
+ }
+
+ // Emit `beforeExit` if the loop became alive either after emitting
+ // event, or after running some callbacks.
+ more = uv_loop_alive(env->event_loop());
+ } while (more == true && !env->is_stopping());
+ env->performance_state()->Mark(
+ node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
+ }
+
+ env->set_trace_sync_io(false);
+ exit_code = EmitExit(env.get());
+ WaitForInspectorDisconnect(env.get());
+ }
+
+ env->set_can_call_into_js(false);
+ env->stop_sub_worker_contexts();
+ uv_tty_reset_mode();
+ env->RunCleanup();
+ RunAtExit(env.get());
+
+ per_process::v8_platform.DrainVMTasks(isolate_);
+ per_process::v8_platform.CancelVMTasks(isolate_);
+
+#if defined(LEAK_SANITIZER)
+ __lsan_do_leak_check();
+#endif
+
+ return exit_code;
+}
+
+// TODO(joyeecheung): align this with the CreateEnvironment exposed in node.h
+// and the environment creation routine in workers somehow.
+std::unique_ptr<Environment> NodeMainInstance::CreateMainEnvironment(
+ int* exit_code) {
+ *exit_code = 0; // Reset the exit code to 0
+
+ HandleScope handle_scope(isolate_);
+
+ // TODO(addaleax): This should load a real per-Isolate option, currently
+ // this is still effectively per-process.
+ if (isolate_data_->options()->track_heap_objects) {
+ isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
+ }
+
+ Local<Context> context = NewContext(isolate_);
+ Context::Scope context_scope(context);
+
+ std::unique_ptr<Environment> env = std::make_unique<Environment>(
+ isolate_data_.get(),
+ context,
+ static_cast<Environment::Flags>(Environment::kIsMainThread |
+ Environment::kOwnsProcessState |
+ Environment::kOwnsInspector));
+ env->InitializeLibuv(per_process::v8_is_profiling);
+ env->ProcessCliArgs(args_, exec_args_);
+
+#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
+ CHECK(!env->inspector_agent()->IsListening());
+ // Inspector agent can't fail to start, but if it was configured to listen
+ // right away on the websocket port and fails to bind/etc, this will return
+ // false.
+ env->inspector_agent()->Start(args_.size() > 1 ? args_[1].c_str() : "",
+ env->options()->debug_options(),
+ env->inspector_host_port(),
+ true);
+ if (env->options()->debug_options().inspector_enabled &&
+ !env->inspector_agent()->IsListening()) {
+ *exit_code = 12; // Signal internal error.
+ return env;
+ }
+#else
+ // inspector_enabled can't be true if !HAVE_INSPECTOR or
+ // !NODE_USE_V8_PLATFORM
+ // - the option parser should not allow that.
+ CHECK(!env->options()->debug_options().inspector_enabled);
+#endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
+
+ if (RunBootstrapping(env.get()).IsEmpty()) {
+ *exit_code = 1;
+ }
+
+ return env;
+}
+
+} // namespace node