name | args | desc |
---|---|---|
OP_CALL | ABC | ABC R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) |
CALL執行一個函數調用。寄存器A中存放函數對象,所有參數按順序放置在A後面的寄存器中。B-1表示參數個數。如果參數列表的最後一個表達式是變長的,則B會設置為0,表示使用A+1到當前棧頂作為參數。函數調用的返回值會按順序存放在從寄存器A開始的C-1個寄存器中。如果C為0,表示返回值的個數由函數決定。
- < font > < font > f(); </ font > </ font >
- < font > < font > 1 [1] GETTABUP 0 0 -1 ; _ENV "f" </ font > </ font > < font ></ font > < font > < font >
- 2 [1] CALL 0 1 1 </ font > </ font > < font > </ font > < font > < font >
- 3 [1] RETURN 0 1 </ font > </ font > < font > </ font >
第一行取得全局變量f的值,保存到寄存器0。第二行CALL調用寄存器0中的函數,參數和返回值都是0。
- <font><font>local t = {f(...)};</font></font>
- <font><font> 1 [1] NEWTABLE 0 0 0</font></font><font></font><font><font>
- 2 [1] GETTABUP 1 0 -1 ; _ENV "f"</font></font><font></font><font><font>
- 3 [1] VARARG 2 0</font></font><font></font><font><font>
- 4 [1] CALL 1 0 0</font></font><font></font><font><font>
- 5 [1] SETLIST 0 0 1 ; 1</font></font><font></font><font><font>
- 6 [1] RETURN 0 1</font></font><font></font>
第一行NETTABLE創建一個表放到寄存器0中。第二行獲取全局變量f放到寄存器1中。第三行VARARG表示使用當前函數的變長參數列表。第四行的CALL調用寄存器1中的函數,B為0,代表參數是變長的。前面講過,如果表的構造的最後一項是多返回值的表達式,則這個表會接受所有的返回值。這裡就是這種情況,表的構造會接受函數所有的返回值,所以C也為0。
name | args | desc |
---|---|---|
OP_TAILCALL | ABC | ABC return R(A)(R(A+1), ... ,R(A+B-1)) |
如果一個return statement只有一個函數調用表達式,這個函數調用指令CALL會被改為TAILCALL指令。TAILCALL不會為要調用的函數增加調用堆棧的深度,而是直接使用當前調用信息。ABC操作數與CALL的意思一樣,不過C永遠都是0。TAILCALL在執行過程中,只對lua closure進行tail call處理,對於c closure,其實與CALL沒什麼區別。
- <font><font>return f();</font></font>
- <font><font> 1 [1] GETTABUP 0 0 -1 ; _ENV "f"</font></font><font></font><font><font>
- 2 [1] TAILCALL 0 1 0</font></font><font></font><font><font>
- 3 [1] RETURN 0 0</font></font><font></font><font><font>
- 4 [1] RETURN 0 1</font></font>
上面如果f是一個lua closure,那麼執行到第二行後,此函數就會返回了,不會執行到後面第三行的RETURN。如果f是一個c closure,那就和CALL一樣調用這個函數,然後依賴第三行的RETURN返回。這就是為什麼TAILCALL後面還會己跟著生成一個RETURN的原因。
name | args | desc |
---|---|---|
OP_RETURN | AB | return R(A), ... ,R(A+B-2) |
RETURE將返回結果存放到寄存器A到寄存器A+B-2中。如果返回的為變長表達式,則B會被設置為0,表示將寄存器A到當前棧頂的所有值返回。
- <font><font>return 1;</font></font>
- <font><font> 1 [1] LOADK 0 -1 ; 1</font></font><font></font><font><font>
- 2 [1] RETURN 0 2</font></font><font></font><font><font>
- 3 [1] RETURN 0 1</font></font><font></font>
RETURN只能從寄存器返回數據,所以第一行LOADK先將常量1裝載道寄存器0,然後返回。
- <font><font>return ...;
- </font></font>
- <font><font> 1 [1] VARARG 0 0</font></font><font></font><font><font>
- 2 [1] RETURN 0 0</font></font><font></font><font><font>
- 3 [1] RETURN 0 1</font></font><font></font>
name | args | desc |
---|---|---|
OP_CLOSURE | A Bx | R(A) := closure(KPROTO[Bx]) |
CLOSURE為指定的函數prototype創建一個closure,並將這個closure保存到寄存器A中。Bx用來指定函數prototype的id。
- <font><font>local function f()</font></font><font></font><font><font>
- end</font></font>
- <font><font>main <test.lua:0,0> (2 instructions at 0x102a016f0)</font></font><font></font><font><font>
- 0+ params, 2 slots, 1 upvalue, 1 local, 0 constants, 1 function</font></font><font></font><font><font>
- 1 [2] CLOSURE 0 0 ; 0x102a019b0</font></font><font></font><font><font>
- 2 [2] RETURN 0 1</font></font><font></font><font><font>
- constants (0) for 0x102a016f0:</font></font><font></font><font><font>
- locals (1) for 0x102a016f0:</font></font><font></font><font><font>
- 0 f 2 3</font></font><font></font><font><font>
- upvalues (1) for 0x102a016f0:</font></font><font></font><font><font>
- 0 _ENV 1 0</font></font><font></font>
- <font></font><font><font>
- function <test.lua:1,2> (1 instruction at 0x102a019b0)</font></font><font></font><font><font>
- 0 params, 2 slots, 0 upvalues, 0 locals, 0 constants, 0 functions</font></font><font></font><font><font>
- 1 [2] RETURN 0 1</font></font><font></font><font><font>
- constants (0) for 0x102a019b0:</font></font><font></font><font><font>
- locals (0) for 0x102a019b0:</font></font><font></font><font><font>
- upvalues (0) for 0x102a019b0:</font></font><font></font>
name | args | desc |
---|---|---|
OP_VARARG | AB | R(A), R(A+1), ..., R(A+B-2) = vararg |
VARARG直接對應'...'運算符。VARARG拷貝B-1個參數到從A開始的寄存器中,如果不足,使用nil補充。如果B為0,表示拷貝實際的參數數量。
- <font><font>local a = ...;</font></font>
- <font><font> 1 [1] VARARG 0 2</font></font><font></font><font><font>
- 2 [1] RETURN 0 1</font></font><font></font>
- <font><font>f(...);
- </font></font>
- <font><font> 1 [1] GETTABUP 0 0 -1 ; _ENV "f"</font></font><font></font><font><font>
- 2 [1] VARARG 1 0</font></font><font></font><font><font>
- 3 [1] CALL 0 0 1</font></font><font></font><font><font>
- 4 [1] RETURN 0 1</font></font><font></font>
name | args | desc |
---|---|---|
OP_SELF | ABC |
R(A+1) := R(B); R(A) := R(B)[RK(C)]
|
SELF是專門為“:”運算符準備的指令。從寄存器B表示的table中,獲取出C作為key的closure,存入寄存器A中,然後將table本身存入到寄存器A+1中,為接下來調用這個closure做準備。
- <font><font>a:b();
- </font></font>
- <font><font> 1 [1] GETTABUP 0 0 -1 ; _ENV "a"</font></font><font></font><font><font>
- 2 [1] SELF 0 0 -2 ; "b"</font></font><font></font><font><font>
- 3 [1] CALL 0 2 1</font></font><font></font><font><font>
- 4 [1] RETURN 0 1</font></font><font></font>
- <font><font>ab(a);</font></font>
- <font><font> 1 [1] GETTABUP 0 0 -1 ; _ENV "a"</font></font><font></font><font><font>
- 2 [1] GETTABLE 0 0 -2 ; "b"</font></font><font></font><font><font>
- 3 [1] GETTABUP 1 0 -1 ; _ENV "a"</font></font><font></font><font><font>
- 4 [1] CALL 0 2 1</font></font><font></font><font><font>
- 5 [1] RETURN 0 1</font></font><font></font>
No comments:
Post a Comment