Created
December 7, 2011 00:54
-
-
Save ry/1440865 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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