lua-users home
lua-l archive

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


>       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