Skip to content

Commit 6a5a7b0

Browse files
committed
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.
1 parent 2cd7adc commit 6a5a7b0

2 files changed

Lines changed: 32 additions & 23 deletions

File tree

src/node.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ static Cached<String> immediate_callback_sym;
180180
static struct {
181181
uint32_t length;
182182
uint32_t index;
183+
uint32_t in_tick;
184+
uint32_t last_threw;
183185
} tick_infobox;
184186

185187
#ifdef OPENSSL_NPN_NEGOTIATED
@@ -969,6 +971,15 @@ MakeDomainCallback(const Handle<Object> object,
969971
}
970972
}
971973

974+
if (tick_infobox.last_threw == 1) {
975+
tick_infobox.last_threw = 0;
976+
return ret;
977+
}
978+
979+
if (tick_infobox.in_tick == 1) {
980+
return ret;
981+
}
982+
972983
if (tick_infobox.length == 0) {
973984
tick_infobox.index = 0;
974985
return ret;
@@ -1017,6 +1028,10 @@ MakeCallback(const Handle<Object> object,
10171028
return Undefined(node_isolate);
10181029
}
10191030

1031+
if (tick_infobox.in_tick == 1) {
1032+
return ret;
1033+
}
1034+
10201035
if (tick_infobox.length == 0) {
10211036
tick_infobox.index = 0;
10221037
return ret;
@@ -2383,7 +2398,7 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
23832398
Local<Object> info_box = Object::New();
23842399
info_box->SetIndexedPropertiesToExternalArrayData(&tick_infobox,
23852400
kExternalUnsignedIntArray,
2386-
2);
2401+
4);
23872402
process->Set(String::NewSymbol("_tickInfoBox"), info_box);
23882403

23892404
// pre-set _events object for faster emit checks

src/node.js

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -315,31 +315,25 @@
315315
};
316316

317317
startup.processNextTick = function() {
318-
var lastThrew = false;
319318
var nextTickQueue = [];
320-
var needSpinner = true;
321-
var inTick = false;
322319

323-
// this infobox thing is used so that the C++ code in src/node.cc
320+
// this infoBox thing is used so that the C++ code in src/node.cc
324321
// can have easy accesss to our nextTick state, and avoid unnecessary
325322
// calls into process._tickCallback.
326-
// order is [length, index]
323+
// order is [length, index, inTick, lastThrew]
327324
// Never write code like this without very good reason!
328325
var infoBox = process._tickInfoBox;
329326
var length = 0;
330327
var index = 1;
328+
var inTick = 2;
329+
var lastThrew = 3;
331330

332331
process.nextTick = nextTick;
333332
// needs to be accessible from cc land
334333
process._nextDomainTick = _nextDomainTick;
335334
process._tickCallback = _tickCallback;
336335
process._tickDomainCallback = _tickDomainCallback;
337336

338-
function Tock(cb, domain) {
339-
this.callback = cb;
340-
this.domain = domain;
341-
}
342-
343337
function tickDone() {
344338
if (infoBox[length] !== 0) {
345339
if (infoBox[length] <= infoBox[index]) {
@@ -350,7 +344,7 @@
350344
infoBox[length] = nextTickQueue.length;
351345
}
352346
}
353-
inTick = false;
347+
infoBox[inTick] = 0;
354348
infoBox[index] = 0;
355349
}
356350

@@ -359,12 +353,12 @@
359353
function _tickCallback() {
360354
var callback, nextTickLength, threw;
361355

362-
if (inTick) return;
356+
if (infoBox[inTick] === 1) return;
363357
if (infoBox[length] === 0) {
364358
infoBox[index] = 0;
365359
return;
366360
}
367-
inTick = true;
361+
infoBox[inTick] = 1;
368362

369363
while (infoBox[index] < infoBox[length]) {
370364
callback = nextTickQueue[infoBox[index]++].callback;
@@ -383,17 +377,17 @@
383377
function _tickDomainCallback() {
384378
var nextTickLength, tock, callback;
385379

386-
if (lastThrew) {
387-
lastThrew = false;
380+
if (infoBox[lastThrew] === 1) {
381+
infoBox[lastThrew] = 0;
388382
return;
389383
}
390384

391-
if (inTick) return;
385+
if (infoBox[inTick] === 1) return;
392386
if (infoBox[length] === 0) {
393387
infoBox[index] = 0;
394388
return;
395389
}
396-
inTick = true;
390+
infoBox[inTick] = 1;
397391

398392
while (infoBox[index] < infoBox[length]) {
399393
tock = nextTickQueue[infoBox[index]++];
@@ -402,12 +396,12 @@
402396
if (tock.domain._disposed) continue;
403397
tock.domain.enter();
404398
}
405-
lastThrew = true;
399+
infoBox[lastThrew] = 1;
406400
try {
407401
callback();
408-
lastThrew = false;
402+
infoBox[lastThrew] = 0;
409403
} finally {
410-
if (lastThrew) tickDone();
404+
if (infoBox[lastThrew] === 1) tickDone();
411405
}
412406
if (tock.domain)
413407
tock.domain.exit();
@@ -421,7 +415,7 @@
421415
if (process._exiting)
422416
return;
423417

424-
nextTickQueue.push(new Tock(callback, null));
418+
nextTickQueue.push({ callback: callback, domain: null });
425419
infoBox[length]++;
426420
}
427421

@@ -430,7 +424,7 @@
430424
if (process._exiting)
431425
return;
432426

433-
nextTickQueue.push(new Tock(callback, process.domain));
427+
nextTickQueue.push({ callback: callback, domain: process.domain });
434428
infoBox[length]++;
435429
}
436430
};

0 commit comments

Comments
 (0)