Browse Source

node: add inTick and lastThrew to infoBox

To prevent all unnecessary calls to JS from MakeCallback, the remaining
two immediate return variables inTick and lastThrew have been added to
infoBox. Now MakeCallback should never need to call into JS unless it
absolutely has to.

Also removed Tock. Performance tests showed it was at least as fast or
faster than using a normal object, and this is more readable.
v0.11.5-release
Trevor Norris 12 years ago
parent
commit
6a5a7b089e
  1. 17
      src/node.cc
  2. 38
      src/node.js

17
src/node.cc

@ -180,6 +180,8 @@ static Cached<String> immediate_callback_sym;
static struct { static struct {
uint32_t length; uint32_t length;
uint32_t index; uint32_t index;
uint32_t in_tick;
uint32_t last_threw;
} tick_infobox; } tick_infobox;
#ifdef OPENSSL_NPN_NEGOTIATED #ifdef OPENSSL_NPN_NEGOTIATED
@ -969,6 +971,15 @@ MakeDomainCallback(const Handle<Object> object,
} }
} }
if (tick_infobox.last_threw == 1) {
tick_infobox.last_threw = 0;
return ret;
}
if (tick_infobox.in_tick == 1) {
return ret;
}
if (tick_infobox.length == 0) { if (tick_infobox.length == 0) {
tick_infobox.index = 0; tick_infobox.index = 0;
return ret; return ret;
@ -1017,6 +1028,10 @@ MakeCallback(const Handle<Object> object,
return Undefined(node_isolate); return Undefined(node_isolate);
} }
if (tick_infobox.in_tick == 1) {
return ret;
}
if (tick_infobox.length == 0) { if (tick_infobox.length == 0) {
tick_infobox.index = 0; tick_infobox.index = 0;
return ret; return ret;
@ -2383,7 +2398,7 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
Local<Object> info_box = Object::New(); Local<Object> info_box = Object::New();
info_box->SetIndexedPropertiesToExternalArrayData(&tick_infobox, info_box->SetIndexedPropertiesToExternalArrayData(&tick_infobox,
kExternalUnsignedIntArray, kExternalUnsignedIntArray,
2); 4);
process->Set(String::NewSymbol("_tickInfoBox"), info_box); process->Set(String::NewSymbol("_tickInfoBox"), info_box);
// pre-set _events object for faster emit checks // pre-set _events object for faster emit checks

38
src/node.js

@ -315,19 +315,18 @@
}; };
startup.processNextTick = function() { startup.processNextTick = function() {
var lastThrew = false;
var nextTickQueue = []; var nextTickQueue = [];
var needSpinner = true;
var inTick = false;
// this infobox thing is used so that the C++ code in src/node.cc // this infoBox thing is used so that the C++ code in src/node.cc
// can have easy accesss to our nextTick state, and avoid unnecessary // can have easy accesss to our nextTick state, and avoid unnecessary
// calls into process._tickCallback. // calls into process._tickCallback.
// order is [length, index] // order is [length, index, inTick, lastThrew]
// Never write code like this without very good reason! // Never write code like this without very good reason!
var infoBox = process._tickInfoBox; var infoBox = process._tickInfoBox;
var length = 0; var length = 0;
var index = 1; var index = 1;
var inTick = 2;
var lastThrew = 3;
process.nextTick = nextTick; process.nextTick = nextTick;
// needs to be accessible from cc land // needs to be accessible from cc land
@ -335,11 +334,6 @@
process._tickCallback = _tickCallback; process._tickCallback = _tickCallback;
process._tickDomainCallback = _tickDomainCallback; process._tickDomainCallback = _tickDomainCallback;
function Tock(cb, domain) {
this.callback = cb;
this.domain = domain;
}
function tickDone() { function tickDone() {
if (infoBox[length] !== 0) { if (infoBox[length] !== 0) {
if (infoBox[length] <= infoBox[index]) { if (infoBox[length] <= infoBox[index]) {
@ -350,7 +344,7 @@
infoBox[length] = nextTickQueue.length; infoBox[length] = nextTickQueue.length;
} }
} }
inTick = false; infoBox[inTick] = 0;
infoBox[index] = 0; infoBox[index] = 0;
} }
@ -359,12 +353,12 @@
function _tickCallback() { function _tickCallback() {
var callback, nextTickLength, threw; var callback, nextTickLength, threw;
if (inTick) return; if (infoBox[inTick] === 1) return;
if (infoBox[length] === 0) { if (infoBox[length] === 0) {
infoBox[index] = 0; infoBox[index] = 0;
return; return;
} }
inTick = true; infoBox[inTick] = 1;
while (infoBox[index] < infoBox[length]) { while (infoBox[index] < infoBox[length]) {
callback = nextTickQueue[infoBox[index]++].callback; callback = nextTickQueue[infoBox[index]++].callback;
@ -383,17 +377,17 @@
function _tickDomainCallback() { function _tickDomainCallback() {
var nextTickLength, tock, callback; var nextTickLength, tock, callback;
if (lastThrew) { if (infoBox[lastThrew] === 1) {
lastThrew = false; infoBox[lastThrew] = 0;
return; return;
} }
if (inTick) return; if (infoBox[inTick] === 1) return;
if (infoBox[length] === 0) { if (infoBox[length] === 0) {
infoBox[index] = 0; infoBox[index] = 0;
return; return;
} }
inTick = true; infoBox[inTick] = 1;
while (infoBox[index] < infoBox[length]) { while (infoBox[index] < infoBox[length]) {
tock = nextTickQueue[infoBox[index]++]; tock = nextTickQueue[infoBox[index]++];
@ -402,12 +396,12 @@
if (tock.domain._disposed) continue; if (tock.domain._disposed) continue;
tock.domain.enter(); tock.domain.enter();
} }
lastThrew = true; infoBox[lastThrew] = 1;
try { try {
callback(); callback();
lastThrew = false; infoBox[lastThrew] = 0;
} finally { } finally {
if (lastThrew) tickDone(); if (infoBox[lastThrew] === 1) tickDone();
} }
if (tock.domain) if (tock.domain)
tock.domain.exit(); tock.domain.exit();
@ -421,7 +415,7 @@
if (process._exiting) if (process._exiting)
return; return;
nextTickQueue.push(new Tock(callback, null)); nextTickQueue.push({ callback: callback, domain: null });
infoBox[length]++; infoBox[length]++;
} }
@ -430,7 +424,7 @@
if (process._exiting) if (process._exiting)
return; return;
nextTickQueue.push(new Tock(callback, process.domain)); nextTickQueue.push({ callback: callback, domain: process.domain });
infoBox[length]++; infoBox[length]++;
} }
}; };

Loading…
Cancel
Save