Browse Source

node: Do not use fn.apply() in process._makeCallback

v0.9.9-release
isaacs 12 years ago
parent
commit
016810913d
  1. 21
      src/node.cc
  2. 35
      src/node.js

21
src/node.cc

@ -908,6 +908,11 @@ MakeCallback(const Handle<Object> object,
Handle<Value> argv[]) { Handle<Value> argv[]) {
HandleScope scope; HandleScope scope;
if (argc > 6) {
fprintf(stderr, "node::MakeCallback - Too many args (%d)\n", argc);
abort();
}
Local<Value> callback_v = object->Get(symbol); Local<Value> callback_v = object->Get(symbol);
if (!callback_v->IsFunction()) { if (!callback_v->IsFunction()) {
String::Utf8Value method(symbol); String::Utf8Value method(symbol);
@ -918,18 +923,6 @@ MakeCallback(const Handle<Object> object,
abort(); abort();
} }
Local<Function> callback = Local<Function>::Cast(callback_v);
return scope.Close(MakeCallback(object, callback, argc, argv));
}
Handle<Value>
MakeCallback(const Handle<Object> object,
const Handle<Function> callback,
int argc,
Handle<Value> argv[]) {
HandleScope scope;
// TODO Hook for long stack traces to be made here. // TODO Hook for long stack traces to be made here.
TryCatch try_catch; TryCatch try_catch;
@ -950,9 +943,9 @@ MakeCallback(const Handle<Object> object,
} }
Local<Value> object_l = Local<Value>::New(node_isolate, object); Local<Value> object_l = Local<Value>::New(node_isolate, object);
Local<Value> callback_l = Local<Value>::New(node_isolate, callback); Local<Value> symbol_l = Local<Value>::New(node_isolate, symbol);
Local<Value> args[3] = { object_l, callback_l, argArray }; Local<Value> args[3] = { object_l, symbol_l, argArray };
Local<Value> ret = process_makeCallback->Call(process, ARRAY_SIZE(args), args); Local<Value> ret = process_makeCallback->Call(process, ARRAY_SIZE(args), args);

35
src/node.js

@ -296,6 +296,8 @@
}; };
startup.processMakeCallback = function() { 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) { process._makeCallback = function(obj, fn, args) {
var domain = obj.domain; var domain = obj.domain;
if (domain) { if (domain) {
@ -303,7 +305,38 @@
domain.enter(); domain.enter();
} }
var ret = fn.apply(obj, args); // 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(); if (domain) domain.exit();

Loading…
Cancel
Save