mirror of
https://github.com/nodejs/node.git
synced 2025-05-03 18:37:06 +00:00
src: use stack-allocated Environment instances
Makes it easier to reason about the lifetime of the Environment object. PR-URL: https://github.com/nodejs/node/pull/7090 Refs: https://github.com/nodejs/node/pull/7082 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
This commit is contained in:
parent
58cec4e85b
commit
aac79dfd78
@ -174,31 +174,24 @@ void Agent::WorkerRun() {
|
|||||||
Local<Context> context = Context::New(isolate);
|
Local<Context> context = Context::New(isolate);
|
||||||
|
|
||||||
Context::Scope context_scope(context);
|
Context::Scope context_scope(context);
|
||||||
Environment* env = CreateEnvironment(
|
Environment env(&isolate_data, context);
|
||||||
&isolate_data,
|
|
||||||
context,
|
|
||||||
arraysize(argv),
|
|
||||||
argv,
|
|
||||||
arraysize(argv),
|
|
||||||
argv);
|
|
||||||
|
|
||||||
child_env_ = env;
|
const bool start_profiler_idle_notifier = false;
|
||||||
|
env.Start(arraysize(argv), argv,
|
||||||
|
arraysize(argv), argv,
|
||||||
|
start_profiler_idle_notifier);
|
||||||
|
|
||||||
|
child_env_ = &env;
|
||||||
|
|
||||||
// Expose API
|
// Expose API
|
||||||
InitAdaptor(env);
|
InitAdaptor(&env);
|
||||||
LoadEnvironment(env);
|
LoadEnvironment(&env);
|
||||||
|
|
||||||
CHECK_EQ(&child_loop_, env->event_loop());
|
CHECK_EQ(&child_loop_, env.event_loop());
|
||||||
uv_run(&child_loop_, UV_RUN_DEFAULT);
|
uv_run(&child_loop_, UV_RUN_DEFAULT);
|
||||||
|
|
||||||
// Clean-up peristent
|
// Clean-up peristent
|
||||||
api_.Reset();
|
api_.Reset();
|
||||||
|
|
||||||
// Clean-up all running handles
|
|
||||||
env->CleanupHandles();
|
|
||||||
|
|
||||||
env->Dispose();
|
|
||||||
env = nullptr;
|
|
||||||
}
|
}
|
||||||
isolate->Dispose();
|
isolate->Dispose();
|
||||||
}
|
}
|
||||||
|
@ -134,13 +134,6 @@ inline void Environment::TickInfo::set_index(uint32_t value) {
|
|||||||
fields_[kIndex] = value;
|
fields_[kIndex] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Environment* Environment::New(IsolateData* isolate_data,
|
|
||||||
v8::Local<v8::Context> context) {
|
|
||||||
Environment* env = new Environment(isolate_data, context);
|
|
||||||
env->AssignToContext(context);
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Environment::AssignToContext(v8::Local<v8::Context> context) {
|
inline void Environment::AssignToContext(v8::Local<v8::Context> context) {
|
||||||
context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, this);
|
context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, this);
|
||||||
}
|
}
|
||||||
@ -184,6 +177,7 @@ inline Environment::Environment(IsolateData* isolate_data,
|
|||||||
#if HAVE_INSPECTOR
|
#if HAVE_INSPECTOR
|
||||||
inspector_agent_(this),
|
inspector_agent_(this),
|
||||||
#endif
|
#endif
|
||||||
|
handle_cleanup_waiting_(0),
|
||||||
http_parser_buffer_(nullptr),
|
http_parser_buffer_(nullptr),
|
||||||
context_(context->GetIsolate(), context) {
|
context_(context->GetIsolate(), context) {
|
||||||
// We'll be creating new objects so make sure we've entered the context.
|
// We'll be creating new objects so make sure we've entered the context.
|
||||||
@ -200,12 +194,21 @@ inline Environment::Environment(IsolateData* isolate_data,
|
|||||||
set_generic_internal_field_template(obj);
|
set_generic_internal_field_template(obj);
|
||||||
|
|
||||||
RB_INIT(&cares_task_list_);
|
RB_INIT(&cares_task_list_);
|
||||||
handle_cleanup_waiting_ = 0;
|
AssignToContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Environment::~Environment() {
|
inline Environment::~Environment() {
|
||||||
v8::HandleScope handle_scope(isolate());
|
v8::HandleScope handle_scope(isolate());
|
||||||
|
|
||||||
|
while (HandleCleanup* hc = handle_cleanup_queue_.PopFront()) {
|
||||||
|
handle_cleanup_waiting_++;
|
||||||
|
hc->cb_(this, hc->handle_, hc->arg_);
|
||||||
|
delete hc;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (handle_cleanup_waiting_ != 0)
|
||||||
|
uv_run(event_loop(), UV_RUN_ONCE);
|
||||||
|
|
||||||
context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex,
|
context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex,
|
||||||
nullptr);
|
nullptr);
|
||||||
#define V(PropertyName, TypeName) PropertyName ## _.Reset();
|
#define V(PropertyName, TypeName) PropertyName ## _.Reset();
|
||||||
@ -217,21 +220,6 @@ inline Environment::~Environment() {
|
|||||||
delete[] http_parser_buffer_;
|
delete[] http_parser_buffer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Environment::CleanupHandles() {
|
|
||||||
while (HandleCleanup* hc = handle_cleanup_queue_.PopFront()) {
|
|
||||||
handle_cleanup_waiting_++;
|
|
||||||
hc->cb_(this, hc->handle_, hc->arg_);
|
|
||||||
delete hc;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (handle_cleanup_waiting_ != 0)
|
|
||||||
uv_run(event_loop(), UV_RUN_ONCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Environment::Dispose() {
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline v8::Isolate* Environment::isolate() const {
|
inline v8::Isolate* Environment::isolate() const {
|
||||||
return isolate_;
|
return isolate_;
|
||||||
}
|
}
|
||||||
|
14
src/env.h
14
src/env.h
@ -446,17 +446,14 @@ class Environment {
|
|||||||
static inline Environment* GetCurrent(
|
static inline Environment* GetCurrent(
|
||||||
const v8::PropertyCallbackInfo<T>& info);
|
const v8::PropertyCallbackInfo<T>& info);
|
||||||
|
|
||||||
// See CreateEnvironment() in src/node.cc.
|
inline Environment(IsolateData* isolate_data, v8::Local<v8::Context> context);
|
||||||
static inline Environment* New(IsolateData* isolate_data,
|
inline ~Environment();
|
||||||
v8::Local<v8::Context> context);
|
|
||||||
void Start(int argc,
|
void Start(int argc,
|
||||||
const char* const* argv,
|
const char* const* argv,
|
||||||
int exec_argc,
|
int exec_argc,
|
||||||
const char* const* exec_argv,
|
const char* const* exec_argv,
|
||||||
bool start_profiler_idle_notifier);
|
bool start_profiler_idle_notifier);
|
||||||
inline void CleanupHandles();
|
|
||||||
inline void Dispose();
|
|
||||||
|
|
||||||
void AssignToContext(v8::Local<v8::Context> context);
|
void AssignToContext(v8::Local<v8::Context> context);
|
||||||
|
|
||||||
void StartProfilerIdleNotifier();
|
void StartProfilerIdleNotifier();
|
||||||
@ -472,7 +469,7 @@ class Environment {
|
|||||||
inline uv_check_t* immediate_check_handle();
|
inline uv_check_t* immediate_check_handle();
|
||||||
inline uv_idle_t* immediate_idle_handle();
|
inline uv_idle_t* immediate_idle_handle();
|
||||||
|
|
||||||
// Register clean-up cb to be called on env->Dispose()
|
// Register clean-up cb to be called on environment destruction.
|
||||||
inline void RegisterHandleCleanup(uv_handle_t* handle,
|
inline void RegisterHandleCleanup(uv_handle_t* handle,
|
||||||
HandleCleanupCb cb,
|
HandleCleanupCb cb,
|
||||||
void *arg);
|
void *arg);
|
||||||
@ -584,9 +581,6 @@ class Environment {
|
|||||||
static const int kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX;
|
static const int kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline Environment(IsolateData* isolate_data, v8::Local<v8::Context> context);
|
|
||||||
inline ~Environment();
|
|
||||||
|
|
||||||
v8::Isolate* const isolate_;
|
v8::Isolate* const isolate_;
|
||||||
IsolateData* const isolate_data_;
|
IsolateData* const isolate_data_;
|
||||||
uv_check_t immediate_check_handle_;
|
uv_check_t immediate_check_handle_;
|
||||||
|
56
src/node.cc
56
src/node.cc
@ -3363,12 +3363,6 @@ void LoadEnvironment(Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FreeEnvironment(Environment* env) {
|
|
||||||
CHECK_NE(env, nullptr);
|
|
||||||
env->Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void PrintHelp();
|
static void PrintHelp();
|
||||||
|
|
||||||
static bool ParseDebugOpt(const char* arg) {
|
static bool ParseDebugOpt(const char* arg) {
|
||||||
@ -4256,12 +4250,17 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
|
|||||||
Isolate* isolate = context->GetIsolate();
|
Isolate* isolate = context->GetIsolate();
|
||||||
HandleScope handle_scope(isolate);
|
HandleScope handle_scope(isolate);
|
||||||
Context::Scope context_scope(context);
|
Context::Scope context_scope(context);
|
||||||
Environment* env = Environment::New(isolate_data, context);
|
auto env = new Environment(isolate_data, context);
|
||||||
env->Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
|
env->Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FreeEnvironment(Environment* env) {
|
||||||
|
delete env;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Entry point for new node instances, also called directly for the main
|
// Entry point for new node instances, also called directly for the main
|
||||||
// node instance.
|
// node instance.
|
||||||
static void StartNodeInstance(void* arg) {
|
static void StartNodeInstance(void* arg) {
|
||||||
@ -4293,60 +4292,60 @@ static void StartNodeInstance(void* arg) {
|
|||||||
array_buffer_allocator.zero_fill_field());
|
array_buffer_allocator.zero_fill_field());
|
||||||
Local<Context> context = Context::New(isolate);
|
Local<Context> context = Context::New(isolate);
|
||||||
Context::Scope context_scope(context);
|
Context::Scope context_scope(context);
|
||||||
Environment* env = CreateEnvironment(&isolate_data,
|
Environment env(&isolate_data, context);
|
||||||
context,
|
env.Start(instance_data->argc(),
|
||||||
instance_data->argc(),
|
instance_data->argv(),
|
||||||
instance_data->argv(),
|
instance_data->exec_argc(),
|
||||||
instance_data->exec_argc(),
|
instance_data->exec_argv(),
|
||||||
instance_data->exec_argv());
|
v8_is_profiling);
|
||||||
|
|
||||||
isolate->SetAbortOnUncaughtExceptionCallback(
|
isolate->SetAbortOnUncaughtExceptionCallback(
|
||||||
ShouldAbortOnUncaughtException);
|
ShouldAbortOnUncaughtException);
|
||||||
|
|
||||||
// Start debug agent when argv has --debug
|
// Start debug agent when argv has --debug
|
||||||
if (instance_data->use_debug_agent())
|
if (instance_data->use_debug_agent())
|
||||||
StartDebug(env, debug_wait_connect);
|
StartDebug(&env, debug_wait_connect);
|
||||||
|
|
||||||
{
|
{
|
||||||
Environment::AsyncCallbackScope callback_scope(env);
|
Environment::AsyncCallbackScope callback_scope(&env);
|
||||||
LoadEnvironment(env);
|
LoadEnvironment(&env);
|
||||||
}
|
}
|
||||||
|
|
||||||
env->set_trace_sync_io(trace_sync_io);
|
env.set_trace_sync_io(trace_sync_io);
|
||||||
|
|
||||||
// Enable debugger
|
// Enable debugger
|
||||||
if (instance_data->use_debug_agent())
|
if (instance_data->use_debug_agent())
|
||||||
EnableDebug(env);
|
EnableDebug(&env);
|
||||||
|
|
||||||
{
|
{
|
||||||
SealHandleScope seal(isolate);
|
SealHandleScope seal(isolate);
|
||||||
bool more;
|
bool more;
|
||||||
do {
|
do {
|
||||||
v8::platform::PumpMessageLoop(default_platform, isolate);
|
v8::platform::PumpMessageLoop(default_platform, isolate);
|
||||||
more = uv_run(env->event_loop(), UV_RUN_ONCE);
|
more = uv_run(env.event_loop(), UV_RUN_ONCE);
|
||||||
|
|
||||||
if (more == false) {
|
if (more == false) {
|
||||||
v8::platform::PumpMessageLoop(default_platform, isolate);
|
v8::platform::PumpMessageLoop(default_platform, isolate);
|
||||||
EmitBeforeExit(env);
|
EmitBeforeExit(&env);
|
||||||
|
|
||||||
// Emit `beforeExit` if the loop became alive either after emitting
|
// Emit `beforeExit` if the loop became alive either after emitting
|
||||||
// event, or after running some callbacks.
|
// event, or after running some callbacks.
|
||||||
more = uv_loop_alive(env->event_loop());
|
more = uv_loop_alive(env.event_loop());
|
||||||
if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
|
if (uv_run(env.event_loop(), UV_RUN_NOWAIT) != 0)
|
||||||
more = true;
|
more = true;
|
||||||
}
|
}
|
||||||
} while (more == true);
|
} while (more == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
env->set_trace_sync_io(false);
|
env.set_trace_sync_io(false);
|
||||||
|
|
||||||
int exit_code = EmitExit(env);
|
int exit_code = EmitExit(&env);
|
||||||
if (instance_data->is_main())
|
if (instance_data->is_main())
|
||||||
instance_data->set_exit_code(exit_code);
|
instance_data->set_exit_code(exit_code);
|
||||||
RunAtExit(env);
|
RunAtExit(&env);
|
||||||
|
|
||||||
#if HAVE_INSPECTOR
|
#if HAVE_INSPECTOR
|
||||||
if (env->inspector_agent()->connected()) {
|
if (env.inspector_agent()->connected()) {
|
||||||
// Restore signal dispositions, the app is done and is no longer
|
// Restore signal dispositions, the app is done and is no longer
|
||||||
// capable of handling signals.
|
// capable of handling signals.
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
@ -4359,16 +4358,13 @@ static void StartNodeInstance(void* arg) {
|
|||||||
CHECK_EQ(0, sigaction(nr, &act, nullptr));
|
CHECK_EQ(0, sigaction(nr, &act, nullptr));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
env->inspector_agent()->WaitForDisconnect();
|
env.inspector_agent()->WaitForDisconnect();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LEAK_SANITIZER)
|
#if defined(LEAK_SANITIZER)
|
||||||
__lsan_do_leak_check();
|
__lsan_do_leak_check();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
env->Dispose();
|
|
||||||
env = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_mutex_lock(&node_isolate_mutex);
|
uv_mutex_lock(&node_isolate_mutex);
|
||||||
|
Loading…
Reference in New Issue
Block a user