From 1b0e5b3ed11af961ce323ddb2df26b20c955b078 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Wed, 24 Jun 2015 22:42:13 -0500 Subject: [PATCH 1/2] Avoid deopt in iterable destructure template The try/catch was forcing deoptimization under most engines. This roughly doubles throughput under V8 and 7x increases were seen under Firefox. Performance numbers based on https://github.com/kpdecker/six-speed/tree/master/tests/destructuring --- .../templates/helper-sliced-to-array.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/babel/transformation/templates/helper-sliced-to-array.js b/src/babel/transformation/templates/helper-sliced-to-array.js index 1285e55662..9659ca4cef 100644 --- a/src/babel/transformation/templates/helper-sliced-to-array.js +++ b/src/babel/transformation/templates/helper-sliced-to-array.js @@ -1,7 +1,7 @@ (function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { + // Broken out into a separate function to avoid deoptimizations due to the try/catch for the + // array iterator case. + function sliceIterator() { // this is an expanded form of `for...of` that properly supports abrupt completions of // iterators etc. variable names have been minimised to reduce the size of this massive // helper. sometimes spec compliancy is annoying :( @@ -32,6 +32,12 @@ } } return _arr; + } + + if (Array.isArray(arr)) { + return arr; + } else if (Symbol.iterator in Object(arr)) { + return sliceIterator(); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } From 5353ccd773500f7de95c89f27628314356bd67a6 Mon Sep 17 00:00:00 2001 From: kpdecker Date: Thu, 25 Jun 2015 09:18:12 -0500 Subject: [PATCH 2/2] Move slice iterator helper out of primary call Avoids overhead of instantiating the helper on each call to the slice to array helper. --- .../templates/helper-sliced-to-array.js | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/babel/transformation/templates/helper-sliced-to-array.js b/src/babel/transformation/templates/helper-sliced-to-array.js index 9659ca4cef..4e59a8ed57 100644 --- a/src/babel/transformation/templates/helper-sliced-to-array.js +++ b/src/babel/transformation/templates/helper-sliced-to-array.js @@ -1,7 +1,7 @@ -(function (arr, i) { +(function () { // Broken out into a separate function to avoid deoptimizations due to the try/catch for the // array iterator case. - function sliceIterator() { + function sliceIterator(arr, i) { // this is an expanded form of `for...of` that properly supports abrupt completions of // iterators etc. variable names have been minimised to reduce the size of this massive // helper. sometimes spec compliancy is annoying :( @@ -34,11 +34,13 @@ return _arr; } - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(); - } else { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } -}); + return function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else if (Symbol.iterator in Object(arr)) { + return sliceIterator(arr, i); + } else { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + }; +})();