Browse Source

src: move env init logic into Environment class

PR-URL: https://github.com/nodejs/node/pull/7090
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
v7.x
Ben Noordhuis 9 years ago
parent
commit
58cec4e85b
  1. 17
      src/env-inl.h
  2. 90
      src/env.cc
  3. 14
      src/env.h
  4. 100
      src/node.cc
  5. 6
      src/node_internals.h

17
src/env-inl.h

@ -260,23 +260,6 @@ inline uv_idle_t* Environment::immediate_idle_handle() {
return &immediate_idle_handle_; return &immediate_idle_handle_;
} }
inline Environment* Environment::from_idle_prepare_handle(
uv_prepare_t* handle) {
return ContainerOf(&Environment::idle_prepare_handle_, handle);
}
inline uv_prepare_t* Environment::idle_prepare_handle() {
return &idle_prepare_handle_;
}
inline Environment* Environment::from_idle_check_handle(uv_check_t* handle) {
return ContainerOf(&Environment::idle_check_handle_, handle);
}
inline uv_check_t* Environment::idle_check_handle() {
return &idle_check_handle_;
}
inline void Environment::RegisterHandleCleanup(uv_handle_t* handle, inline void Environment::RegisterHandleCleanup(uv_handle_t* handle,
HandleCleanupCb cb, HandleCleanupCb cb,
void *arg) { void *arg) {

90
src/env.cc

@ -1,6 +1,8 @@
#include "env.h" #include "env.h"
#include "env-inl.h" #include "env-inl.h"
#include "async-wrap.h"
#include "v8.h" #include "v8.h"
#include "v8-profiler.h"
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define getpid GetCurrentProcessId #define getpid GetCurrentProcessId
@ -12,6 +14,8 @@
namespace node { namespace node {
using v8::Context;
using v8::FunctionTemplate;
using v8::HandleScope; using v8::HandleScope;
using v8::Local; using v8::Local;
using v8::Message; using v8::Message;
@ -19,6 +23,92 @@ using v8::StackFrame;
using v8::StackTrace; using v8::StackTrace;
using v8::Value; using v8::Value;
void Environment::Start(int argc,
const char* const* argv,
int exec_argc,
const char* const* exec_argv,
bool start_profiler_idle_notifier) {
HandleScope handle_scope(isolate());
Context::Scope context_scope(context());
isolate()->SetAutorunMicrotasks(false);
uv_check_init(event_loop(), immediate_check_handle());
uv_unref(reinterpret_cast<uv_handle_t*>(immediate_check_handle()));
uv_idle_init(event_loop(), immediate_idle_handle());
// Inform V8's CPU profiler when we're idle. The profiler is sampling-based
// but not all samples are created equal; mark the wall clock time spent in
// epoll_wait() and friends so profiling tools can filter it out. The samples
// still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
// TODO(bnoordhuis) Depends on a libuv implementation detail that we should
// probably fortify in the API contract, namely that the last started prepare
// or check watcher runs first. It's not 100% foolproof; if an add-on starts
// a prepare or check watcher after us, any samples attributed to its callback
// will be recorded with state=IDLE.
uv_prepare_init(event_loop(), &idle_prepare_handle_);
uv_check_init(event_loop(), &idle_check_handle_);
uv_unref(reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_));
uv_unref(reinterpret_cast<uv_handle_t*>(&idle_check_handle_));
auto close_and_finish = [](Environment* env, uv_handle_t* handle, void* arg) {
handle->data = env;
uv_close(handle, [](uv_handle_t* handle) {
static_cast<Environment*>(handle->data)->FinishHandleCleanup(handle);
});
};
RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(immediate_check_handle()),
close_and_finish,
nullptr);
RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(immediate_idle_handle()),
close_and_finish,
nullptr);
RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_),
close_and_finish,
nullptr);
RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(&idle_check_handle_),
close_and_finish,
nullptr);
if (start_profiler_idle_notifier) {
StartProfilerIdleNotifier();
}
auto process_template = FunctionTemplate::New(isolate());
process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate(), "process"));
auto process_object =
process_template->GetFunction()->NewInstance(context()).ToLocalChecked();
set_process_object(process_object);
SetupProcessObject(this, argc, argv, exec_argc, exec_argv);
LoadAsyncWrapperInfo(this);
}
void Environment::StartProfilerIdleNotifier() {
uv_prepare_start(&idle_prepare_handle_, [](uv_prepare_t* handle) {
Environment* env = ContainerOf(&Environment::idle_prepare_handle_, handle);
env->isolate()->GetCpuProfiler()->SetIdle(true);
});
uv_check_start(&idle_check_handle_, [](uv_check_t* handle) {
Environment* env = ContainerOf(&Environment::idle_check_handle_, handle);
env->isolate()->GetCpuProfiler()->SetIdle(false);
});
}
void Environment::StopProfilerIdleNotifier() {
uv_prepare_stop(&idle_prepare_handle_);
uv_check_stop(&idle_check_handle_);
}
void Environment::PrintSyncTrace() const { void Environment::PrintSyncTrace() const {
if (!trace_sync_io_) if (!trace_sync_io_)
return; return;

14
src/env.h

@ -449,11 +449,19 @@ class Environment {
// See CreateEnvironment() in src/node.cc. // See CreateEnvironment() in src/node.cc.
static inline Environment* New(IsolateData* isolate_data, static inline Environment* New(IsolateData* isolate_data,
v8::Local<v8::Context> context); v8::Local<v8::Context> context);
void Start(int argc,
const char* const* argv,
int exec_argc,
const char* const* exec_argv,
bool start_profiler_idle_notifier);
inline void CleanupHandles(); inline void CleanupHandles();
inline void Dispose(); inline void Dispose();
void AssignToContext(v8::Local<v8::Context> context); void AssignToContext(v8::Local<v8::Context> context);
void StartProfilerIdleNotifier();
void StopProfilerIdleNotifier();
inline v8::Isolate* isolate() const; inline v8::Isolate* isolate() const;
inline uv_loop_t* event_loop() const; inline uv_loop_t* event_loop() const;
inline bool async_wrap_callbacks_enabled() const; inline bool async_wrap_callbacks_enabled() const;
@ -464,12 +472,6 @@ 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();
static inline Environment* from_idle_prepare_handle(uv_prepare_t* handle);
inline uv_prepare_t* idle_prepare_handle();
static inline Environment* from_idle_check_handle(uv_check_t* handle);
inline uv_check_t* idle_check_handle();
// Register clean-up cb to be called on env->Dispose() // Register clean-up cb to be called on env->Dispose()
inline void RegisterHandleCleanup(uv_handle_t* handle, inline void RegisterHandleCleanup(uv_handle_t* handle,
HandleCleanupCb cb, HandleCleanupCb cb,

100
src/node.cc

@ -101,7 +101,6 @@ using v8::Exception;
using v8::Float64Array; using v8::Float64Array;
using v8::Function; using v8::Function;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::HandleScope; using v8::HandleScope;
using v8::HeapStatistics; using v8::HeapStatistics;
using v8::Integer; using v8::Integer;
@ -2864,39 +2863,15 @@ static void NeedImmediateCallbackSetter(
} }
void SetIdle(uv_prepare_t* handle) {
Environment* env = Environment::from_idle_prepare_handle(handle);
env->isolate()->GetCpuProfiler()->SetIdle(true);
}
void ClearIdle(uv_check_t* handle) {
Environment* env = Environment::from_idle_check_handle(handle);
env->isolate()->GetCpuProfiler()->SetIdle(false);
}
void StartProfilerIdleNotifier(Environment* env) {
uv_prepare_start(env->idle_prepare_handle(), SetIdle);
uv_check_start(env->idle_check_handle(), ClearIdle);
}
void StopProfilerIdleNotifier(Environment* env) {
uv_prepare_stop(env->idle_prepare_handle());
uv_check_stop(env->idle_check_handle());
}
void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) { void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args); Environment* env = Environment::GetCurrent(args);
StartProfilerIdleNotifier(env); env->StartProfilerIdleNotifier();
} }
void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) { void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args); Environment* env = Environment::GetCurrent(args);
StopProfilerIdleNotifier(env); env->StopProfilerIdleNotifier();
} }
@ -4262,20 +4237,6 @@ int EmitExit(Environment* env) {
} }
static void HandleCloseCb(uv_handle_t* handle) {
Environment* env = reinterpret_cast<Environment*>(handle->data);
env->FinishHandleCleanup(handle);
}
static void HandleCleanup(Environment* env,
uv_handle_t* handle,
void* arg) {
handle->data = env;
uv_close(handle, HandleCloseCb);
}
IsolateData* CreateIsolateData(Isolate* isolate, uv_loop_t* loop) { IsolateData* CreateIsolateData(Isolate* isolate, uv_loop_t* loop) {
return new IsolateData(isolate, loop); return new IsolateData(isolate, loop);
} }
@ -4294,64 +4255,9 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
const char* const* exec_argv) { const char* const* exec_argv) {
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); Environment* env = Environment::New(isolate_data, context);
env->Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
isolate->SetAutorunMicrotasks(false);
uv_check_init(env->event_loop(), env->immediate_check_handle());
uv_unref(
reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
uv_idle_init(env->event_loop(), env->immediate_idle_handle());
// Inform V8's CPU profiler when we're idle. The profiler is sampling-based
// but not all samples are created equal; mark the wall clock time spent in
// epoll_wait() and friends so profiling tools can filter it out. The samples
// still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
// TODO(bnoordhuis) Depends on a libuv implementation detail that we should
// probably fortify in the API contract, namely that the last started prepare
// or check watcher runs first. It's not 100% foolproof; if an add-on starts
// a prepare or check watcher after us, any samples attributed to its callback
// will be recorded with state=IDLE.
uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
uv_check_init(env->event_loop(), env->idle_check_handle());
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
// Register handle cleanups
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()),
HandleCleanup,
nullptr);
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->immediate_idle_handle()),
HandleCleanup,
nullptr);
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()),
HandleCleanup,
nullptr);
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->idle_check_handle()),
HandleCleanup,
nullptr);
if (v8_is_profiling) {
StartProfilerIdleNotifier(env);
}
Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
Local<Object> process_object =
process_template->GetFunction()->NewInstance(context).ToLocalChecked();
env->set_process_object(process_object);
SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
LoadAsyncWrapperInfo(env);
return env; return env;
} }

6
src/node_internals.h

@ -145,6 +145,12 @@ NO_RETURN void FatalError(const char* location, const char* message);
v8::Local<v8::Value> BuildStatsObject(Environment* env, const uv_stat_t* s); v8::Local<v8::Value> BuildStatsObject(Environment* env, const uv_stat_t* s);
void SetupProcessObject(Environment* env,
int argc,
const char* const* argv,
int exec_argc,
const char* const* exec_argv);
enum Endianness { enum Endianness {
kLittleEndian, // _Not_ LITTLE_ENDIAN, clashes with endian.h. kLittleEndian, // _Not_ LITTLE_ENDIAN, clashes with endian.h.
kBigEndian kBigEndian

Loading…
Cancel
Save