From 6a5a7b089ea77c0001bee3b38e657901364a0b5f Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Tue, 30 Jul 2013 15:06:45 -0700 Subject: [PATCH] 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. --- src/node.cc | 17 ++++++++++++++++- src/node.js | 38 ++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/node.cc b/src/node.cc index 73cd19aca2..c54489d89e 100644 --- a/src/node.cc +++ b/src/node.cc @@ -180,6 +180,8 @@ static Cached immediate_callback_sym; static struct { uint32_t length; uint32_t index; + uint32_t in_tick; + uint32_t last_threw; } tick_infobox; #ifdef OPENSSL_NPN_NEGOTIATED @@ -969,6 +971,15 @@ MakeDomainCallback(const Handle 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) { tick_infobox.index = 0; return ret; @@ -1017,6 +1028,10 @@ MakeCallback(const Handle object, return Undefined(node_isolate); } + if (tick_infobox.in_tick == 1) { + return ret; + } + if (tick_infobox.length == 0) { tick_infobox.index = 0; return ret; @@ -2383,7 +2398,7 @@ Handle SetupProcessObject(int argc, char *argv[]) { Local info_box = Object::New(); info_box->SetIndexedPropertiesToExternalArrayData(&tick_infobox, kExternalUnsignedIntArray, - 2); + 4); process->Set(String::NewSymbol("_tickInfoBox"), info_box); // pre-set _events object for faster emit checks diff --git a/src/node.js b/src/node.js index e9bcd0bcd8..f5411cffdd 100644 --- a/src/node.js +++ b/src/node.js @@ -315,19 +315,18 @@ }; startup.processNextTick = function() { - var lastThrew = false; 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 // calls into process._tickCallback. - // order is [length, index] + // order is [length, index, inTick, lastThrew] // Never write code like this without very good reason! var infoBox = process._tickInfoBox; var length = 0; var index = 1; + var inTick = 2; + var lastThrew = 3; process.nextTick = nextTick; // needs to be accessible from cc land @@ -335,11 +334,6 @@ process._tickCallback = _tickCallback; process._tickDomainCallback = _tickDomainCallback; - function Tock(cb, domain) { - this.callback = cb; - this.domain = domain; - } - function tickDone() { if (infoBox[length] !== 0) { if (infoBox[length] <= infoBox[index]) { @@ -350,7 +344,7 @@ infoBox[length] = nextTickQueue.length; } } - inTick = false; + infoBox[inTick] = 0; infoBox[index] = 0; } @@ -359,12 +353,12 @@ function _tickCallback() { var callback, nextTickLength, threw; - if (inTick) return; + if (infoBox[inTick] === 1) return; if (infoBox[length] === 0) { infoBox[index] = 0; return; } - inTick = true; + infoBox[inTick] = 1; while (infoBox[index] < infoBox[length]) { callback = nextTickQueue[infoBox[index]++].callback; @@ -383,17 +377,17 @@ function _tickDomainCallback() { var nextTickLength, tock, callback; - if (lastThrew) { - lastThrew = false; + if (infoBox[lastThrew] === 1) { + infoBox[lastThrew] = 0; return; } - if (inTick) return; + if (infoBox[inTick] === 1) return; if (infoBox[length] === 0) { infoBox[index] = 0; return; } - inTick = true; + infoBox[inTick] = 1; while (infoBox[index] < infoBox[length]) { tock = nextTickQueue[infoBox[index]++]; @@ -402,12 +396,12 @@ if (tock.domain._disposed) continue; tock.domain.enter(); } - lastThrew = true; + infoBox[lastThrew] = 1; try { callback(); - lastThrew = false; + infoBox[lastThrew] = 0; } finally { - if (lastThrew) tickDone(); + if (infoBox[lastThrew] === 1) tickDone(); } if (tock.domain) tock.domain.exit(); @@ -421,7 +415,7 @@ if (process._exiting) return; - nextTickQueue.push(new Tock(callback, null)); + nextTickQueue.push({ callback: callback, domain: null }); infoBox[length]++; } @@ -430,7 +424,7 @@ if (process._exiting) return; - nextTickQueue.push(new Tock(callback, process.domain)); + nextTickQueue.push({ callback: callback, domain: process.domain }); infoBox[length]++; } };