lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Josh Haberman wrote:
> Mike Pall <mikelu-1102 <at> mike.de> writes:
> > Rule #437: Never hoist out constants (if possible)!
> 
> This seems like a big limitation to me -- is there any way to
> work around it?

You are overdramatizing. I've given advice on how to speed up your
code. You can happily ignore that, but then please don't complain.

> Ideally there would be a way to make it efficient
> instead of having to tell programmers over and over that the
> efficiency of hoisting is the opposite of what they expect.

All variables in Lua are mutable, whereas literals are not.
The constness of variables can only be inferred, if the initial
assignment of a literal to a variable happens on the same trace.
Anything else is not covered by Lua semantics.

The equivalent in C would be to store all constants in a global,
non-const variable. The compiler can't infer that it's const
anymore.

> Is the debug API the issue here?  Without funny business going
> on it seems that LJ should be able to recognize that a variable
> is only assigned once.

That's one issue. One could just flush all generated code if the
debug API is used to modify any variables. But I have a feeling
that users of debuggers might be unhappy about this.

Recognizing single-assignment requires per-module analysis of the
bytecode. That would cover number or string constants. But the far
more interesting case is to treat something like this as const:
  local sin = math.sin
Except that the piece of Lua code that does this assignment
(usually the outermost chunk) may be executed more than once. And
the next time the value could be different. E.g.:

  function f()
    local sin = math.sin
    return function() local x=0; for i=1,100 do x=x+sin(i) end; return x end
  end

  print(f()())
  math.sin = math.cos
  print(f()())

As you can see, there's only a single assignment to 'sin', but
it's still not a constant.

There are a slew of other problems, e.g. finding the bytecode for
the outer functions. Or the outer function has been collected,
which makes it hard to find the bytecode of the siblings (one of
them may write to the variable). One would have to pre-analyze
everything during initial bytecode generation, even if none of
that overhead would do any good later on.

Don't you think if it was that simple, then I'd have done
something about this already?

--Mike