lib: don't penalize setInterval() common case

The common case is where setInterval() is called with two arguments,
the callback and the timeout.  Specifying optional arguments in
the parameter list forces common case calls to go through an arguments
adaptor stack frame.

PR-URL: https://github.com/iojs/io.js/pull/1221
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
This commit is contained in:
Ben Noordhuis 2015-03-20 17:20:43 +01:00
parent 31da9758a0
commit 33fea6ed5f

View File

@ -229,24 +229,40 @@ exports.clearTimeout = function(timer) {
}; };
exports.setInterval = function(callback, repeat, arg1, arg2, arg3) { exports.setInterval = function(callback, repeat) {
repeat *= 1; // coalesce to number or NaN repeat *= 1; // coalesce to number or NaN
if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) {
repeat = 1; // schedule on next tick, follows browser behaviour repeat = 1; // schedule on next tick, follows browser behaviour
} }
var args, i;
var timer = new Timeout(repeat); var timer = new Timeout(repeat);
var len = arguments.length - 2; var length = arguments.length;
timer._onTimeout = wrapper; var ontimeout = callback;
timer._repeat = true; switch (length) {
// Initialize args once for repeated invocation of slow case below case 0:
if (len > 3) { case 1:
args = new Array(len); case 2:
for (i = 0; i < len; i++) break;
args[i] = arguments[i + 2]; case 3:
ontimeout = callback.bind(timer, arguments[2]);
break;
case 4:
ontimeout = callback.bind(timer, arguments[2], arguments[3]);
break;
case 5:
ontimeout =
callback.bind(timer, arguments[2], arguments[3], arguments[4]);
break;
default:
var args = new Array(length - 2);
for (var i = 2; i < length; i += 1)
args[i - 2] = arguments[i];
ontimeout = callback.apply.bind(callback, timer, args);
break;
} }
timer._onTimeout = wrapper;
timer._repeat = ontimeout;
if (process.domain) timer.domain = process.domain; if (process.domain) timer.domain = process.domain;
exports.active(timer); exports.active(timer);
@ -254,27 +270,9 @@ exports.setInterval = function(callback, repeat, arg1, arg2, arg3) {
return timer; return timer;
function wrapper() { function wrapper() {
switch (len) { timer._repeat.call(this);
// fast cases
case 0:
callback.call(this);
break;
case 1:
callback.call(this, arg1);
break;
case 2:
callback.call(this, arg1, arg2);
break;
case 3:
callback.call(this, arg1, arg2, arg3);
break;
// slow case
default:
callback.apply(this, args);
break;
}
// If callback called clearInterval(). // If callback called clearInterval().
if (timer._repeat === false) return; if (timer._repeat === null) return;
// If timer is unref'd (or was - it's permanently removed from the list.) // If timer is unref'd (or was - it's permanently removed from the list.)
if (this._handle) { if (this._handle) {
this._handle.start(repeat, 0); this._handle.start(repeat, 0);