Skip to content

Instantly share code, notes, and snippets.

@ry
Created December 7, 2011 00:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ry/1440865 to your computer and use it in GitHub Desktop.
Save ry/1440865 to your computer and use it in GitHub Desktop.
diff --git a/node.gyp b/node.gyp
index 89f5ea7..60f3617 100644
--- a/node.gyp
+++ b/node.gyp
@@ -72,6 +72,7 @@
'src/cares_wrap.cc',
'src/handle_wrap.cc',
'src/node.cc',
+ 'src/node_vars.cc',
'src/node_buffer.cc',
'src/node_constants.cc',
'src/node_extensions.cc',
@@ -94,6 +95,7 @@
# headers to make for a more pleasant IDE experience
'src/handle_wrap.h',
'src/node.h',
+ 'src/node_vars.h',
'src/node_buffer.h',
'src/node_constants.h',
'src/node_crypto.h',
diff --git a/src/node.cc b/src/node.cc
index d0c540f..59d9e24 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -95,82 +95,54 @@ using namespace v8;
extern char **environ;
# endif
-namespace node {
-
-static Persistent<Object> process;
-
-static Persistent<String> errno_symbol;
-static Persistent<String> syscall_symbol;
-static Persistent<String> errpath_symbol;
-static Persistent<String> code_symbol;
-
-static Persistent<String> rss_symbol;
-static Persistent<String> heap_total_symbol;
-static Persistent<String> heap_used_symbol;
-
-static Persistent<String> listeners_symbol;
-static Persistent<String> uncaught_exception_symbol;
-static Persistent<String> emit_symbol;
+#include <node_vars.h>
+#define use_sni NODE_VAR(use_sni)
+#define use_npn NODE_VAR(use_npn)
+#define need_tick_cb NODE_VAR(need_tick_cb)
+#define tick_time_head NODE_VAR(tick_time_head)
+#define gc_timer NODE_VAR(gc_timer)
+#define gc_idle NODE_VAR(gc_idle)
+#define gc_check NODE_VAR(gc_check)
+#define tick_times NODE_VAR(tick_times)
+#define debug_wait_connect NODE_VAR(debug_wait_connect)
+#define use_debug_agent NODE_VAR(use_debug_agent)
+#define tick_spinner NODE_VAR(tick_spinner)
+#define check_tick_watcher NODE_VAR(check_tick_watcher)
+#define prepare_tick_watcher NODE_VAR(prepare_tick_watcher)
+#define max_stack_size NODE_VAR(max_stack_size)
+#define option_end_index NODE_VAR(option_end_index)
+#define debug_port NODE_VAR(debug_port)
+#define print_eval NODE_VAR(print_eval)
+#define eval_string NODE_VAR(eval_string)
+#define process NODE_VAR(process)
+#define errno_symbol NODE_VAR(errno_symbol)
+#define syscall_symbol NODE_VAR(syscall_symbol)
+#define errpath_symbol NODE_VAR(errpath_symbol)
+#define code_symbol NODE_VAR(code_symbol)
+#define rss_symbol NODE_VAR(rss_symbol)
+#define heap_total_symbol NODE_VAR(heap_total_symbol)
+#define heap_used_symbol NODE_VAR(heap_used_symbol)
+#define listeners_symbol NODE_VAR(listeners_symbol)
+#define uncaught_exception_symbol NODE_VAR(uncaught_exception_symbol)
+#define emit_symbol NODE_VAR(emit_symbol)
+#define tick_callback_sym NODE_VAR(tick_callback_sym)
+#define getbuf NODE_VAR(getbuf)
-static bool print_eval = false;
-static char *eval_string = NULL;
-static int option_end_index = 0;
-static bool use_debug_agent = false;
-static bool debug_wait_connect = false;
-static int debug_port=5858;
-static int max_stack_size = 0;
-static uv_check_t check_tick_watcher;
-static uv_prepare_t prepare_tick_watcher;
-static uv_idle_t tick_spinner;
-static bool need_tick_cb;
-static Persistent<String> tick_callback_sym;
-
-
-#ifdef OPENSSL_NPN_NEGOTIATED
-static bool use_npn = true;
-#else
-static bool use_npn = false;
-#endif
+namespace node {
-#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
-static bool use_sni = true;
-#else
-static bool use_sni = false;
-#endif
-#ifdef __POSIX__
-// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
-// scoped at file-level rather than method-level to avoid excess stack usage.
-static char getbuf[PATH_MAX + 1];
-#endif
-// We need to notify V8 when we're idle so that it can run the garbage
-// collector. The interface to this is V8::IdleNotification(). It returns
-// true if the heap hasn't be fully compacted, and needs to be run again.
-// Returning false means that it doesn't have anymore work to do.
-//
-// A rather convoluted algorithm has been devised to determine when Node is
-// idle. You'll have to figure it out for yourself.
-static uv_check_t gc_check;
-static uv_idle_t gc_idle;
-static uv_timer_t gc_timer;
-bool need_gc;
+#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
-#define FAST_TICK 700.
-#define GC_WAIT_TIME 5000.
-#define RPM_SAMPLES 100
-#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
-static int64_t tick_times[RPM_SAMPLES];
-static int tick_time_head;
static void CheckStatus(uv_timer_t* watcher, int status);
static void StartGCTimer () {
if (!uv_is_active((uv_handle_t*) &gc_timer)) {
- uv_timer_start(&node::gc_timer, node::CheckStatus, 5000, 5000);
+ uv_timer_start(&gc_timer, node::CheckStatus, 5000, 5000);
}
}
@@ -213,7 +185,7 @@ static void Check(uv_check_t* watcher, int status) {
// Otherwise start the gc!
//fprintf(stderr, "start idle 2\n");
- uv_idle_start(&node::gc_idle, node::Idle);
+ uv_idle_start(&gc_idle, node::Idle);
}
@@ -821,10 +793,6 @@ Local<Value> UVException(int errorno,
const char *syscall,
const char *msg,
const char *path) {
- static Persistent<String> syscall_symbol;
- static Persistent<String> errpath_symbol;
- static Persistent<String> code_symbol;
-
if (syscall_symbol.IsEmpty()) {
syscall_symbol = NODE_PSYMBOL("syscall");
errno_symbol = NODE_PSYMBOL("errno");
@@ -1487,7 +1455,7 @@ static void CheckStatus(uv_timer_t* watcher, int status) {
V8::GetHeapStatistics(&stats);
if (stats.total_heap_size() > 1024 * 1024 * 128) {
// larger than 128 megs, just start the idle watcher
- uv_idle_start(&node::gc_idle, node::Idle);
+ uv_idle_start(&gc_idle, node::Idle);
return;
}
}
@@ -1498,7 +1466,7 @@ static void CheckStatus(uv_timer_t* watcher, int status) {
if (d >= GC_WAIT_TIME - 1.) {
//fprintf(stderr, "start idle\n");
- uv_idle_start(&node::gc_idle, node::Idle);
+ uv_idle_start(&gc_idle, node::Idle);
}
}
@@ -2132,7 +2100,7 @@ static void SignalExit(int signal) {
}
-void Load(Handle<Object> process) {
+void Load(Handle<Object> process_l) {
// Compile, execute the src/node.js file. (Which was included as static C
// string in node_natives.h. 'natve_node' is the string containing that
// source code.)
@@ -2162,7 +2130,7 @@ void Load(Handle<Object> process) {
// Add a reference to the global object
Local<Object> global = v8::Context::GetCurrent()->Global();
- Local<Value> args[1] = { Local<Value>::New(process) };
+ Local<Value> args[1] = { Local<Value>::New(process_l) };
#ifdef HAVE_DTRACE
InitDTrace(global);
@@ -2429,7 +2397,7 @@ static Handle<Value> DebugProcess(const Arguments& args) {
HandleScope scope;
Handle<Value> rv = Undefined();
DWORD pid;
- HANDLE process = NULL;
+ HANDLE process_l = NULL;
HANDLE thread = NULL;
HANDLE mapping = NULL;
char mapping_name[32];
@@ -2442,12 +2410,12 @@ static Handle<Value> DebugProcess(const Arguments& args) {
pid = (DWORD) args[0]->IntegerValue();
- process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
+ process_l = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
PROCESS_VM_READ,
FALSE,
pid);
- if (process == NULL) {
+ if (process_l == NULL) {
rv = ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
goto out;
}
@@ -2475,7 +2443,7 @@ static Handle<Value> DebugProcess(const Arguments& args) {
goto out;
}
- thread = CreateRemoteThread(process,
+ thread = CreateRemoteThread(process_l,
NULL,
0,
*handler,
@@ -2496,8 +2464,8 @@ static Handle<Value> DebugProcess(const Arguments& args) {
}
out:
- if (process != NULL) {
- CloseHandle(process);
+ if (process_l != NULL) {
+ CloseHandle(process_l);
}
if (thread != NULL) {
CloseHandle(thread);
@@ -2522,18 +2490,18 @@ char** Init(int argc, char *argv[]) {
node::ParseArgs(argc, argv);
// Parse the rest of the args (up to the 'option_end_index' (where '--' was
// in the command line))
- int v8argc = node::option_end_index;
+ int v8argc = option_end_index;
char **v8argv = argv;
- if (node::debug_wait_connect) {
+ if (debug_wait_connect) {
// v8argv is a copy of argv up to the script file argument +2 if --debug-brk
// to expose the v8 debugger js object so that node.js can set
// a breakpoint on the first line of the startup script
v8argc += 2;
v8argv = new char*[v8argc];
- memcpy(v8argv, argv, sizeof(argv) * node::option_end_index);
- v8argv[node::option_end_index] = const_cast<char*>("--expose_debug_as");
- v8argv[node::option_end_index + 1] = const_cast<char*>("v8debug");
+ memcpy(v8argv, argv, sizeof(argv) * option_end_index);
+ v8argv[option_end_index] = const_cast<char*>("--expose_debug_as");
+ v8argv[option_end_index + 1] = const_cast<char*>("v8debug");
}
// For the normal stack which moves from high to low addresses when frames
@@ -2541,11 +2509,11 @@ char** Init(int argc, char *argv[]) {
// the address of a stack variable (e.g. &stack_var) as an approximation
// of the start of the stack (we're assuming that we haven't pushed a lot
// of frames yet).
- if (node::max_stack_size != 0) {
+ if (max_stack_size != 0) {
uint32_t stack_var;
ResourceConstraints constraints;
- uint32_t *stack_limit = &stack_var - (node::max_stack_size / sizeof(uint32_t));
+ uint32_t *stack_limit = &stack_var - (max_stack_size / sizeof(uint32_t));
constraints.set_stack_limit(stack_limit);
SetResourceConstraints(&constraints); // Must be done before V8::Initialize
}
@@ -2558,25 +2526,25 @@ char** Init(int argc, char *argv[]) {
RegisterSignalHandler(SIGTERM, SignalExit);
#endif // __POSIX__
- uv_prepare_init(uv_default_loop(), &node::prepare_tick_watcher);
- uv_prepare_start(&node::prepare_tick_watcher, PrepareTick);
+ uv_prepare_init(uv_default_loop(), &prepare_tick_watcher);
+ uv_prepare_start(&prepare_tick_watcher, PrepareTick);
uv_unref(uv_default_loop());
- uv_check_init(uv_default_loop(), &node::check_tick_watcher);
- uv_check_start(&node::check_tick_watcher, node::CheckTick);
+ uv_check_init(uv_default_loop(), &check_tick_watcher);
+ uv_check_start(&check_tick_watcher, node::CheckTick);
uv_unref(uv_default_loop());
- uv_idle_init(uv_default_loop(), &node::tick_spinner);
+ uv_idle_init(uv_default_loop(), &tick_spinner);
uv_unref(uv_default_loop());
- uv_check_init(uv_default_loop(), &node::gc_check);
- uv_check_start(&node::gc_check, node::Check);
+ uv_check_init(uv_default_loop(), &gc_check);
+ uv_check_start(&gc_check, node::Check);
uv_unref(uv_default_loop());
- uv_idle_init(uv_default_loop(), &node::gc_idle);
+ uv_idle_init(uv_default_loop(), &gc_idle);
uv_unref(uv_default_loop());
- uv_timer_init(uv_default_loop(), &node::gc_timer);
+ uv_timer_init(uv_default_loop(), &gc_timer);
uv_unref(uv_default_loop());
V8::SetFatalErrorHandler(node::OnFatalError);
@@ -2600,7 +2568,7 @@ char** Init(int argc, char *argv[]) {
node_isolate = Isolate::GetCurrent();
// If the --debug flag was specified then initialize the debug thread.
- if (node::use_debug_agent) {
+ if (use_debug_agent) {
EnableDebug(debug_wait_connect);
} else {
#ifdef _WIN32
@@ -2614,14 +2582,14 @@ char** Init(int argc, char *argv[]) {
}
-void EmitExit(v8::Handle<v8::Object> process) {
+void EmitExit(v8::Handle<v8::Object> process_l) {
// process.emit('exit')
- Local<Value> emit_v = process->Get(String::New("emit"));
+ Local<Value> emit_v = process_l->Get(String::New("emit"));
assert(emit_v->IsFunction());
Local<Function> emit = Local<Function>::Cast(emit_v);
Local<Value> args[] = { String::New("exit") };
TryCatch try_catch;
- emit->Call(process, 1, args);
+ emit->Call(process_l, 1, args);
if (try_catch.HasCaught()) {
FatalException(try_catch);
}
@@ -2639,12 +2607,12 @@ int Start(int argc, char *argv[]) {
Persistent<v8::Context> context = v8::Context::New();
v8::Context::Scope context_scope(context);
- Handle<Object> process = SetupProcessObject(argc, argv);
+ Handle<Object> process_l = SetupProcessObject(argc, argv);
v8_typed_array::AttachBindings(context->Global());
// Create all the objects, load modules, do everything.
// so your next reading stop should be node::Load()!
- Load(process);
+ Load(process_l);
// All our arguments are loaded. We've evaluated all of the scripts. We
// might even have created TCP servers. Now we enter the main eventloop. If
@@ -2653,7 +2621,7 @@ int Start(int argc, char *argv[]) {
// watchers, it blocks.
uv_run(uv_default_loop());
- EmitExit(process);
+ EmitExit(process_l);
#ifndef NDEBUG
// Clean up.
diff --git a/src/node_vars.cc b/src/node_vars.cc
new file mode 100644
index 0000000..dbf5364
--- /dev/null
+++ b/src/node_vars.cc
@@ -0,0 +1,42 @@
+#include <node_vars.h>
+#if HAVE_OPENSSL
+# include <node_crypto.h>
+#endif
+#include <string.h>
+
+namespace node {
+
+// For now we just statically initialize the globals structure. Later there
+// will be one struct globals for each isolate.
+
+static struct globals g_struct;
+static struct globals* g_ptr;
+
+
+static void globals_init(struct globals* g) {
+ memset(g, 0, sizeof(struct globals));
+ g->debug_port = 5858;
+
+#ifdef OPENSSL_NPN_NEGOTIATED
+ g->use_npn = true;
+#else
+ g->use_npn = false;
+#endif
+
+#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
+ g->use_sni = true;
+#else
+ g->use_sni = false;
+#endif
+}
+
+
+struct globals* globals_get() {
+ if (!g_ptr) {
+ g_ptr = &g_struct;
+ globals_init(g_ptr);
+ }
+ return g_ptr;
+}
+
+} // namespace node
diff --git a/src/node_vars.h b/src/node_vars.h
new file mode 100644
index 0000000..2713fe9
--- /dev/null
+++ b/src/node_vars.h
@@ -0,0 +1,77 @@
+#ifndef NODE_VARS_H
+#define NODE_VARS_H
+
+// This file contains all Isolate-local variables. We allow people to
+// compile Node either with Isolates or without. In the case that they
+// compile without isolates, these will be static variables.
+
+#include <v8.h>
+#include <uv.h>
+
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
+namespace node {
+
+
+#define NODE_VAR(x) (globals_get()->x)
+
+struct globals {
+ v8::Persistent<v8::Object> process;
+ v8::Persistent<v8::String> errno_symbol;
+ v8::Persistent<v8::String> syscall_symbol;
+ v8::Persistent<v8::String> errpath_symbol;
+ v8::Persistent<v8::String> code_symbol;
+ v8::Persistent<v8::String> rss_symbol;
+ v8::Persistent<v8::String> heap_total_symbol;
+ v8::Persistent<v8::String> heap_used_symbol;
+ v8::Persistent<v8::String> listeners_symbol;
+ v8::Persistent<v8::String> uncaught_exception_symbol;
+ v8::Persistent<v8::String> emit_symbol;
+
+ bool print_eval;
+ char *eval_string;
+ int option_end_index;
+ bool use_debug_agent;
+ bool debug_wait_connect;
+ int debug_port;
+ int max_stack_size;
+
+ uv_check_t check_tick_watcher;
+ uv_prepare_t prepare_tick_watcher;
+ uv_idle_t tick_spinner;
+ bool need_tick_cb;
+ v8::Persistent<v8::String> tick_callback_sym;
+
+ bool use_npn;
+ bool use_sni;
+
+ // Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
+ // scoped at file-level rather than method-level to avoid excess stack usage.
+ char getbuf[PATH_MAX + 1];
+
+ // We need to notify V8 when we're idle so that it can run the garbage
+ // collector. The interface to this is V8::IdleNotification(). It returns
+ // true if the heap hasn't be fully compacted, and needs to be run again.
+ // Returning false means that it doesn't have anymore work to do.
+ //
+ // A rather convoluted algorithm has been devised to determine when Node is
+ // idle. You'll have to figure it out for yourself.
+ uv_check_t gc_check;
+ uv_idle_t gc_idle;
+ uv_timer_t gc_timer;
+ bool need_gc;
+
+# define FAST_TICK 700.
+# define GC_WAIT_TIME 5000.
+# define RPM_SAMPLES 100
+
+ int64_t tick_times[RPM_SAMPLES];
+ int tick_time_head;
+};
+
+struct globals* globals_get();
+
+} // namespace node
+#endif // NODE_VARS_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment