|
> I'm reading the source code of lua515, there is some code then I
> don't understand yet
>
> int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
> luaK_dischargevars(fs, e);
> if (e->k == VNONRELOC) {
> if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register
> */
> if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
> exp2reg(fs, e, e->u.s.info); /* put value on it */
> return e->u.s.info;
> }
> }
> luaK_exp2nextreg(fs, e); /* default */
> return e->u.s.info;
> }
>
> Here is a branch "e->u.s.info >= fs->nactvar", I don't quite understand,
> can anyone explain the relevant context or example? thank you all.
As the comment explains, the test checks whether the register holds
a local variable. If it does, we cannot change its value, so we put
the value in the next available register (luaK_exp2nextreg). Otherwise,
the final value can live where it is.
As an example, consider the code below:
local a1,a2
do
return (a1 or a2) + 1
end
do
return a1 or (a2 + 1)
end
It generates the follwoing opcodes. (This is 5.3, but the general idea
is the same.)
1 [1] LOADNIL 0 1
2 [3] TESTSET 2 0 1
3 [3] JMP 0 1 ; to 5
4 [3] MOVE 2 1
5 [3] ADD 2 2 -1 ; - 1
6 [3] RETURN 2 2
7 [6] TESTSET 2 0 1
8 [6] JMP 0 1 ; to 10
9 [6] ADD 2 1 -1 ; - 1
10 [6] RETURN 2 2
In the first case (lines 2-6), it cannot put the final result in
register 1, because it cannot change a2. So, it has to put the
result in register 2, and therefore needs a move (line 4). In
the second case, the results are already in register 2, which is
not a variable, so they stay there and there is no need for a move.
-- Roberto