Subject: Re: bug#15294: 24.3.50; js2-mode parser is several times slower in lexical-binding mode

From: Stefan Monnier <[email-masked]>
Date: Thu, 12 Sep 2013 23:40:45 -0400

> In the compiled case, loading js2-mode-lexical.elc and then redefining
> `js2-get-token' to the value it has in js2-mode-dynamic.elc brings me
> back the same speed as with js2-mode-dynamic.elc.
> IOW the slowdown is in js2-get-token.

It seems the slowdown is indeed linked to the way `catch' is handled
(indeed, this non-idiomatic ELisp code ends up byte-compiled in a really
poor way).

The trivial patch below brings the time down from 5s to 2.6s (as
compared to 2.1s for the dynamic-binding version).

        Stefan

diff --git a/packages/js2-mode/js2-mode.el b/packages/js2-mode/js2-mode.el
index 3568f18..1d76469 100644
--- a/packages/js2-mode/js2-mode.el
+++ b/packages/js2-mode/js2-mode.el
@@ -5310,10 +5311,10 @@ corresponding number.  Otherwise return -1."
 
 (defun js2-get-token ()
   "Return next JavaScript token, an int such as js2-RETURN."
-  (let (c c1 identifier-start is-unicode-escape-start
-        contains-escape escape-val str result base
-        is-integer quote-char val look-for-slash continue)
-    (catch 'return
+  (catch 'return
+    (let (c c1 identifier-start is-unicode-escape-start
+            contains-escape escape-val str result base
+            is-integer quote-char val look-for-slash continue)
       (while t
         ;; Eat whitespace, possibly sensitive to newlines.
         (setq continue t)