diff options
author | isaacs <i@izs.me> | 2013-02-01 14:23:28 -0800 |
---|---|---|
committer | isaacs <i@izs.me> | 2013-02-15 18:13:01 -0800 |
commit | 95ac576bf956055d3d5758cacbd336b53570f89f (patch) | |
tree | ca47ef3477b8639f7c67c96a80f014a5f3188e73 /src | |
parent | 401cef797df39ca0e5d7a71b2202d6fc750ca912 (diff) | |
download | node-new-95ac576bf956055d3d5758cacbd336b53570f89f.tar.gz |
Revert "Move MakeCallback to JS"
This reverts commit 0109a9f90acdfdb287436676f2384f7b072fbb6a.
Also included: Port all the changes to process._makeCallback into the
C++ version. Immediate nextTick, etc.
This yields a slight boost in several benchmarks. V8 is optimizing and
deoptimizing process._makeCallback repeatedly.
Diffstat (limited to 'src')
-rw-r--r-- | src/node.cc | 71 | ||||
-rw-r--r-- | src/node.js | 52 |
2 files changed, 51 insertions, 72 deletions
diff --git a/src/node.cc b/src/node.cc index 84af978f22..890ea6355d 100644 --- a/src/node.cc +++ b/src/node.cc @@ -100,6 +100,7 @@ Persistent<String> process_symbol; Persistent<String> domain_symbol; static Persistent<Object> process; +static Persistent<Function> process_tickCallback; static Persistent<String> exports_symbol; @@ -114,7 +115,9 @@ static Persistent<String> heap_used_symbol; static Persistent<String> fatal_exception_symbol; -static Persistent<Function> process_makeCallback; +static Persistent<String> enter_symbol; +static Persistent<String> exit_symbol; +static Persistent<String> disposed_symbol; static bool print_eval = false; @@ -926,11 +929,6 @@ MakeCallback(const Handle<Object> object, Handle<Value> argv[]) { HandleScope scope; - if (argc > 6) { - fprintf(stderr, "node::MakeCallback - Too many args (%d)\n", argc); - abort(); - } - Local<Value> callback_v = object->Get(symbol); if (!callback_v->IsFunction()) { String::Utf8Value method(symbol); @@ -945,27 +943,60 @@ MakeCallback(const Handle<Object> object, TryCatch try_catch; - if (process_makeCallback.IsEmpty()) { - Local<Value> cb_v = process->Get(String::New("_makeCallback")); - if (!cb_v->IsFunction()) { - fprintf(stderr, "process._makeCallback assigned to non-function\n"); - abort(); + if (enter_symbol.IsEmpty()) { + enter_symbol = NODE_PSYMBOL("enter"); + exit_symbol = NODE_PSYMBOL("exit"); + disposed_symbol = NODE_PSYMBOL("_disposed"); + } + + Local<Value> domain_v = object->Get(domain_symbol); + Local<Object> domain; + Local<Function> enter; + Local<Function> exit; + if (!domain_v->IsUndefined()) { + domain = domain_v->ToObject(); + if (domain->Get(disposed_symbol)->BooleanValue()) { + // domain has been disposed of. + return Undefined(node_isolate); } - Local<Function> cb = cb_v.As<Function>(); - process_makeCallback = Persistent<Function>::New(cb); + enter = Local<Function>::Cast(domain->Get(enter_symbol)); + enter->Call(domain, 0, NULL); } - Local<Array> argArray = Array::New(argc); - for (int i = 0; i < argc; i++) { - argArray->Set(Integer::New(i, node_isolate), argv[i]); + if (try_catch.HasCaught()) { + FatalException(try_catch); + return Undefined(node_isolate); } - Local<Value> object_l = Local<Value>::New(node_isolate, object); - Local<Value> symbol_l = Local<Value>::New(node_isolate, symbol); + Local<Function> callback = Local<Function>::Cast(callback_v); + Local<Value> ret = callback->Call(object, argc, argv); - Local<Value> args[3] = { object_l, symbol_l, argArray }; + if (try_catch.HasCaught()) { + FatalException(try_catch); + return Undefined(node_isolate); + } - Local<Value> ret = process_makeCallback->Call(process, ARRAY_SIZE(args), args); + if (!domain_v->IsUndefined()) { + exit = Local<Function>::Cast(domain->Get(exit_symbol)); + exit->Call(domain, 0, NULL); + } + + if (try_catch.HasCaught()) { + FatalException(try_catch); + return Undefined(node_isolate); + } + + // process nextTicks after every time we get called. + if (process_tickCallback.IsEmpty()) { + Local<Value> cb_v = process->Get(String::New("_tickCallback")); + if (!cb_v->IsFunction()) { + fprintf(stderr, "process._tickCallback assigned to non-function\n"); + abort(); + } + Local<Function> cb = cb_v.As<Function>(); + process_tickCallback = Persistent<Function>::New(cb); + } + process_tickCallback->Call(process, NULL, 0); if (try_catch.HasCaught()) { FatalException(try_catch); diff --git a/src/node.js b/src/node.js index 62f5fa8ea6..a9e795acdd 100644 --- a/src/node.js +++ b/src/node.js @@ -48,7 +48,6 @@ startup.processAssert(); startup.processConfig(); startup.processNextTick(); - startup.processMakeCallback(); startup.processStdio(); startup.processKillAndExit(); startup.processSignalHandlers(); @@ -297,57 +296,6 @@ }); }; - startup.processMakeCallback = function() { - // Along with EventEmitter.emit, this is the hottest code in node. - // Everything that comes from C++ into JS passes through here. - process._makeCallback = function(obj, fn, args) { - var domain = obj.domain; - if (domain) { - if (domain._disposed) return; - domain.enter(); - } - - // I know what you're thinking, why not just use fn.apply - // Because we hit this function a lot, and really want to make sure - // that V8 can optimize it as well as possible. - var ret; - switch (args.length) { - case 0: - ret = obj[fn](); - break; - case 1: - ret = obj[fn](args[0]); - break; - case 2: - ret = obj[fn](args[0], args[1]); - break; - case 3: - ret = obj[fn](args[0], args[1], args[2]); - break; - case 4: - ret = obj[fn](args[0], args[1], args[2], args[3]); - break; - case 5: - ret = obj[fn](args[0], args[1], args[2], args[3], args[4]); - break; - case 6: - ret = obj[fn](args[0], args[1], args[2], args[3], args[4], args[5]); - break; - - default: - // How did we even get here? This should abort() in C++ land! - throw new Error('too many args to makeCallback'); - break; - } - - if (domain) domain.exit(); - - // process the nextTicks after each time we get called. - process._tickCallback(); - return ret; - }; - }; - startup.processNextTick = function() { var nextTickQueue = []; var nextTickIndex = 0; |