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

From: Stefan Monnier <[email-masked]>
Date: Sun, 15 Sep 2013 01:04:22 -0400

> Can the fact that `dotimes', `dolist' and `loop' are advised with
> cl--wrap-in-nil-block', which expands into `catch' form, make much
> of a difference?

No, these only expand to `catch' if there's a `return' inside.

> `js2-get-token' has 13 local variables (*).  Which is, while not a little,
> far from 100.  Most of the other functions have fewer than that.

I don't know how many it takes to be significantly slower than `symbol-value'.

> Are you counting the global variables, too?

No.  But arguments, yes, and every (defvar <var>) between point and BOB
as well.

> The dynamic-binding interpreter has to work with them, too.  How is it
> that much faster?

Dynamic binding lookup is done by `symbol-value' which is just a field
access (plus checking that the var is not special (e.g. buffer-local or
a predefined C variable).

>>> But 2.6 vs 2.1, it still a noticeable regression. Do you suppose the usage
>>> of `setq' is the main contributor?
>> The problem goes as follows: ...
> Thank you for the detailed explanation.
> There are a few `catch' forms left there, for tags `continue' and `break',
> used for control flow. So, most of the 0.5s difference left is likely due to
> them, right?

The problem is not just the use of catch, but the combination of "catch"
with all those vars let-bound outside of catch, used inside, and mutated:
- make a variable immutable (i.e. remove the setqs on it) and that
  variable becomes more efficient again.
- move the let binding inside the catch, and the var becomes efficient again.
- don't use the variable inside the catch, and it becomes efficient again.

        Stefan