Skip to content

Commit cab1dc5

Browse files
committed
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: #27220 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent c6c37e9 commit cab1dc5

7 files changed

+236
-184
lines changed

node.gyp

+2
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@
460460
'src/node_http_parser_traditional.cc',
461461
'src/node_http2.cc',
462462
'src/node_i18n.cc',
463+
'src/node_main_instance.cc',
463464
'src/node_messaging.cc',
464465
'src/node_metadata.cc',
465466
'src/node_native_module.cc',
@@ -540,6 +541,7 @@
540541
'src/node_http2_state.h',
541542
'src/node_i18n.h',
542543
'src/node_internals.h',
544+
'src/node_main_instance.h',
543545
'src/node_messaging.h',
544546
'src/node_metadata.h',
545547
'src/node_mutex.h',

src/api/environment.cc

+14-10
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,7 @@ void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) {
169169
delete allocator;
170170
}
171171

172-
void SetIsolateCreateParams(Isolate::CreateParams* params,
173-
ArrayBufferAllocator* allocator) {
174-
if (allocator != nullptr)
175-
params->array_buffer_allocator = allocator;
176-
172+
void SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
177173
const uint64_t total_memory = uv_get_total_memory();
178174
if (total_memory > 0) {
179175
// V8 defaults to 700MB or 1.4GB on 32 and 64 bit platforms respectively.
@@ -204,25 +200,33 @@ Isolate* NewIsolate(ArrayBufferAllocator* allocator, uv_loop_t* event_loop) {
204200
return NewIsolate(allocator, event_loop, GetMainThreadMultiIsolatePlatform());
205201
}
206202

207-
Isolate* NewIsolate(ArrayBufferAllocator* allocator,
203+
// TODO(joyeecheung): we may want to expose this, but then we need to be
204+
// careful about what we override in the params.
205+
Isolate* NewIsolate(Isolate::CreateParams* params,
208206
uv_loop_t* event_loop,
209207
MultiIsolatePlatform* platform) {
210-
Isolate::CreateParams params;
211-
SetIsolateCreateParams(&params, allocator);
212-
213208
Isolate* isolate = Isolate::Allocate();
214209
if (isolate == nullptr) return nullptr;
215210

216211
// Register the isolate on the platform before the isolate gets initialized,
217212
// so that the isolate can access the platform during initialization.
218213
platform->RegisterIsolate(isolate, event_loop);
219-
Isolate::Initialize(isolate, params);
220214

215+
SetIsolateCreateParamsForNode(params);
216+
Isolate::Initialize(isolate, *params);
221217
SetIsolateUpForNode(isolate);
222218

223219
return isolate;
224220
}
225221

222+
Isolate* NewIsolate(ArrayBufferAllocator* allocator,
223+
uv_loop_t* event_loop,
224+
MultiIsolatePlatform* platform) {
225+
Isolate::CreateParams params;
226+
if (allocator != nullptr) params.array_buffer_allocator = allocator;
227+
return NewIsolate(&params, event_loop, platform);
228+
}
229+
226230
IsolateData* CreateIsolateData(Isolate* isolate,
227231
uv_loop_t* loop,
228232
MultiIsolatePlatform* platform,

src/env.cc

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ IsolateData::IsolateData(Isolate* isolate,
7676
// One byte because our strings are ASCII and we can safely skip V8's UTF-8
7777
// decoding step.
7878

79+
HandleScope handle_scope(isolate);
80+
7981
#define V(PropertyName, StringValue) \
8082
PropertyName ## _.Set( \
8183
isolate, \

src/node.cc

+8-173
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,12 @@
2525

2626
#include "debug_utils.h"
2727
#include "node_binding.h"
28-
#include "node_buffer.h"
29-
#include "node_constants.h"
30-
#include "node_context_data.h"
31-
#include "node_errors.h"
3228
#include "node_internals.h"
29+
#include "node_main_instance.h"
3330
#include "node_metadata.h"
3431
#include "node_native_module_env.h"
3532
#include "node_options-inl.h"
3633
#include "node_perf.h"
37-
#include "node_platform.h"
3834
#include "node_process.h"
3935
#include "node_revert.h"
4036
#include "node_v8_platform-inl.h"
@@ -56,13 +52,6 @@
5652
#include "node_dtrace.h"
5753
#endif
5854

59-
#include "async_wrap-inl.h"
60-
#include "env-inl.h"
61-
#include "handle_wrap.h"
62-
#include "req_wrap-inl.h"
63-
#include "string_bytes.h"
64-
#include "util.h"
65-
#include "uv.h"
6655
#if NODE_USE_V8_PLATFORM
6756
#include "libplatform/libplatform.h"
6857
#endif // NODE_USE_V8_PLATFORM
@@ -122,23 +111,19 @@ using native_module::NativeModuleEnv;
122111
using options_parser::kAllowedInEnvironment;
123112
using options_parser::kDisallowedInEnvironment;
124113

125-
using v8::Array;
126114
using v8::Boolean;
127115
using v8::Context;
128-
using v8::DEFAULT;
129116
using v8::EscapableHandleScope;
130117
using v8::Exception;
131118
using v8::Function;
132119
using v8::FunctionCallbackInfo;
133120
using v8::HandleScope;
134121
using v8::Isolate;
135122
using v8::Local;
136-
using v8::Locker;
137123
using v8::Maybe;
138124
using v8::MaybeLocal;
139125
using v8::Object;
140126
using v8::Script;
141-
using v8::SealHandleScope;
142127
using v8::String;
143128
using v8::Undefined;
144129
using v8::V8;
@@ -767,161 +752,6 @@ void Init(int* argc,
767752
argv[i] = strdup(argv_[i].c_str());
768753
}
769754

770-
void RunBeforeExit(Environment* env) {
771-
env->RunBeforeExitCallbacks();
772-
773-
if (!uv_loop_alive(env->event_loop()))
774-
EmitBeforeExit(env);
775-
}
776-
777-
// TODO(joyeecheung): align this with the CreateEnvironment exposed in node.h
778-
// and the environment creation routine in workers somehow.
779-
inline std::unique_ptr<Environment> CreateMainEnvironment(
780-
IsolateData* isolate_data,
781-
const std::vector<std::string>& args,
782-
const std::vector<std::string>& exec_args,
783-
int* exit_code) {
784-
Isolate* isolate = isolate_data->isolate();
785-
HandleScope handle_scope(isolate);
786-
787-
// TODO(addaleax): This should load a real per-Isolate option, currently
788-
// this is still effectively per-process.
789-
if (isolate_data->options()->track_heap_objects) {
790-
isolate->GetHeapProfiler()->StartTrackingHeapObjects(true);
791-
}
792-
793-
Local<Context> context = NewContext(isolate);
794-
Context::Scope context_scope(context);
795-
796-
std::unique_ptr<Environment> env = std::make_unique<Environment>(
797-
isolate_data,
798-
context,
799-
static_cast<Environment::Flags>(Environment::kIsMainThread |
800-
Environment::kOwnsProcessState |
801-
Environment::kOwnsInspector));
802-
env->InitializeLibuv(per_process::v8_is_profiling);
803-
env->ProcessCliArgs(args, exec_args);
804-
805-
#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
806-
CHECK(!env->inspector_agent()->IsListening());
807-
// Inspector agent can't fail to start, but if it was configured to listen
808-
// right away on the websocket port and fails to bind/etc, this will return
809-
// false.
810-
env->inspector_agent()->Start(args.size() > 1 ? args[1].c_str() : "",
811-
env->options()->debug_options(),
812-
env->inspector_host_port(),
813-
true);
814-
if (env->options()->debug_options().inspector_enabled &&
815-
!env->inspector_agent()->IsListening()) {
816-
*exit_code = 12; // Signal internal error.
817-
return env;
818-
}
819-
#else
820-
// inspector_enabled can't be true if !HAVE_INSPECTOR or !NODE_USE_V8_PLATFORM
821-
// - the option parser should not allow that.
822-
CHECK(!env->options()->debug_options().inspector_enabled);
823-
#endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
824-
825-
if (RunBootstrapping(env.get()).IsEmpty()) {
826-
*exit_code = 1;
827-
}
828-
829-
return env;
830-
}
831-
832-
inline int StartNodeWithIsolate(Isolate* isolate,
833-
IsolateData* isolate_data,
834-
const std::vector<std::string>& args,
835-
const std::vector<std::string>& exec_args) {
836-
int exit_code = 0;
837-
std::unique_ptr<Environment> env =
838-
CreateMainEnvironment(isolate_data, args, exec_args, &exit_code);
839-
CHECK_NOT_NULL(env);
840-
HandleScope handle_scope(env->isolate());
841-
Context::Scope context_scope(env->context());
842-
843-
if (exit_code == 0) {
844-
{
845-
AsyncCallbackScope callback_scope(env.get());
846-
env->async_hooks()->push_async_ids(1, 0);
847-
LoadEnvironment(env.get());
848-
env->async_hooks()->pop_async_id(1);
849-
}
850-
851-
{
852-
SealHandleScope seal(isolate);
853-
bool more;
854-
env->performance_state()->Mark(
855-
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
856-
do {
857-
uv_run(env->event_loop(), UV_RUN_DEFAULT);
858-
859-
per_process::v8_platform.DrainVMTasks(isolate);
860-
861-
more = uv_loop_alive(env->event_loop());
862-
if (more && !env->is_stopping()) continue;
863-
864-
RunBeforeExit(env.get());
865-
866-
// Emit `beforeExit` if the loop became alive either after emitting
867-
// event, or after running some callbacks.
868-
more = uv_loop_alive(env->event_loop());
869-
} while (more == true && !env->is_stopping());
870-
env->performance_state()->Mark(
871-
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
872-
}
873-
874-
env->set_trace_sync_io(false);
875-
exit_code = EmitExit(env.get());
876-
WaitForInspectorDisconnect(env.get());
877-
}
878-
879-
env->set_can_call_into_js(false);
880-
env->stop_sub_worker_contexts();
881-
uv_tty_reset_mode();
882-
env->RunCleanup();
883-
RunAtExit(env.get());
884-
885-
per_process::v8_platform.DrainVMTasks(isolate);
886-
per_process::v8_platform.CancelVMTasks(isolate);
887-
888-
#if defined(LEAK_SANITIZER)
889-
__lsan_do_leak_check();
890-
#endif
891-
892-
return exit_code;
893-
}
894-
895-
inline int StartNodeWithLoopAndArgs(uv_loop_t* event_loop,
896-
const std::vector<std::string>& args,
897-
const std::vector<std::string>& exec_args) {
898-
std::unique_ptr<ArrayBufferAllocator, decltype(&FreeArrayBufferAllocator)>
899-
allocator(CreateArrayBufferAllocator(), &FreeArrayBufferAllocator);
900-
Isolate* const isolate = NewIsolate(allocator.get(), event_loop);
901-
if (isolate == nullptr)
902-
return 12; // Signal internal error.
903-
904-
int exit_code;
905-
{
906-
Locker locker(isolate);
907-
Isolate::Scope isolate_scope(isolate);
908-
HandleScope handle_scope(isolate);
909-
std::unique_ptr<IsolateData, decltype(&FreeIsolateData)> isolate_data(
910-
CreateIsolateData(isolate,
911-
event_loop,
912-
per_process::v8_platform.Platform(),
913-
allocator.get()),
914-
&FreeIsolateData);
915-
exit_code =
916-
StartNodeWithIsolate(isolate, isolate_data.get(), args, exec_args);
917-
}
918-
919-
isolate->Dispose();
920-
per_process::v8_platform.Platform()->UnregisterIsolate(isolate);
921-
922-
return exit_code;
923-
}
924-
925755
int Start(int argc, char** argv) {
926756
atexit([] () { uv_tty_reset_mode(); });
927757
PlatformInit();
@@ -981,8 +811,13 @@ int Start(int argc, char** argv) {
981811
V8::Initialize();
982812
performance::performance_v8_start = PERFORMANCE_NOW();
983813
per_process::v8_initialized = true;
984-
const int exit_code =
985-
StartNodeWithLoopAndArgs(uv_default_loop(), args, exec_args);
814+
815+
int exit_code = 0;
816+
{
817+
NodeMainInstance main_instance(uv_default_loop(), args, exec_args);
818+
exit_code = main_instance.Run();
819+
}
820+
986821
per_process::v8_initialized = false;
987822
V8::Dispose();
988823

src/node_internals.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,9 @@ bool SafeGetenv(const char* key, std::string* text, Environment* env = nullptr);
297297
} // namespace credentials
298298

299299
void DefineZlibConstants(v8::Local<v8::Object> target);
300-
300+
v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params,
301+
uv_loop_t* event_loop,
302+
MultiIsolatePlatform* platform);
301303
v8::MaybeLocal<v8::Value> RunBootstrapping(Environment* env);
302304
v8::MaybeLocal<v8::Value> StartExecution(Environment* env,
303305
const char* main_script_id);

0 commit comments

Comments
 (0)