From 33fea6ed5f506e7748cb9132f63dc03215a9eb39 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 20 Mar 2015 17:20:43 +0100 Subject: [PATCH] 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 --- lib/timers.js | 58 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/lib/timers.js b/lib/timers.js index 72f275a6421e62..102a927a19c6a1 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -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 if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { repeat = 1; // schedule on next tick, follows browser behaviour } - var args, i; var timer = new Timeout(repeat); - var len = arguments.length - 2; - timer._onTimeout = wrapper; - timer._repeat = true; - // Initialize args once for repeated invocation of slow case below - if (len > 3) { - args = new Array(len); - for (i = 0; i < len; i++) - args[i] = arguments[i + 2]; + var length = arguments.length; + var ontimeout = callback; + switch (length) { + case 0: + case 1: + case 2: + break; + 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; exports.active(timer); @@ -254,27 +270,9 @@ exports.setInterval = function(callback, repeat, arg1, arg2, arg3) { return timer; function wrapper() { - switch (len) { - // 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; - } + timer._repeat.call(this); // 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 (this._handle) { this._handle.start(repeat, 0);