name | args | desc |
---|---|---|
OP_NEWTABLE | ABC | R(A) := {} (size = B,C) |
NEWTABLE在寄存器A處創建一個table對象。B和C分別用來存儲這個table數組部分和hash部分的初始大小。初始大小是在編譯期計算出來並生成到這個指令中的,目的是使接下來對table的初始化填充不會造成rehash而影響效率。B和C使用“floating point byte”的方法來表示成(eeeeexxx)的二進制形式,其實際值為(1xxx) * 2^(eeeee-1)。
- local a = {};
- 1 [1] NEWTABLE 0 0 0
- 2 [1] RETURN 0 1
上面代碼生成一個空的table,放入local變量a,B和C參數都為0。
name | args | desc |
---|---|---|
OP_SETLIST | ABC | R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B |
SETLIST用來配合NEWTABLE,初始化表的數組部分使用的。A為保存待設置表的寄存器,SETLIST要將A下面緊接著的寄存器列表(1--B)中的值逐個設置給表的數組部分。
當表需要初始化數組元素數量比較小的情況下,例如:
- local a = {1,1,1};
- 1 [1] NEWTABLE 0 3 0
- 2 [1] LOADK 1 -1 ; 1
- 3 [1] LOADK 2 -1 ; 1
- 4 [1] LOADK 3 -1 ; 1
- 5 [1] SETLIST 0 3 1 ; 1
- 6 [1] RETURN 0 1
- constants (1) for 0x80048eb0:
- 1 1
如果需要創建一個很大的表,其中包含很多的數組元素,使用如上方法就會遇到一個問題。將這些指按順序放到寄存器時,會超出寄存器的範圍。解決的辦法就是按照一個固定大小,將這些數組元素分批進行設置。在Lua中,每批的數量由lopcodes.h中的LFIELDS_PER_FLUSH定義,數量為50。所以,大數量的設置會按照50個一批,先將值設置到表下面的寄存器,然後設置給對應的表項。C代表的就是這一次調用SETLIST設置的是第幾批。回到上面的例子,因為只有3個表項,所以1批就搞定了,C的值為1。
下面是一個大表的設置:
- local a =
- {
- 1,2,3,4,5,6,7,8,9,0,
- 1,2,3,4,5,6,7,8,9,0,
- 1,2,3,4,5,6,7,8,9,0,
- 1,2,3,4,5,6,7,8,9,0,
- 1,2,3,4,5,6,7,8,9,0,
- 1,2,3
- };
- 1 [1] NEWTABLE 0 30 0
- 2 [3] LOADK 1 -1 ; 1
- 3 [3] LOADK 2 -2 ; 2
- ...
- 50 [7] LOADK 49 -9 ; 9
- 51 [7] LOADK 50 -10 ; 0
- 52 [7] SETLIST 0 50 1 ; 1
- 53 [8] LOADK 1 -1 ; 1
- 54 [8] LOADK 2 -2 ; 2
- 55 [9] LOADK 3 -3 ; 3
- 56 [9] SETLIST 0 3 2 ; 2
- 57 [9] RETURN 0 1
- constants (10) for 0x80048eb0:
- 1 1
- 2 2
- 3 3
- 4 4
- 5 5
- 6 6
- 7 7
- 8 8
- 9 9
- 10 0
如果數據非常大,導致需要的批次超出了C的表示範圍,那麼C會被設置成0,然後在SETLIST指令後面生成一個EXTRAARG指令,並用其Ax來存儲批次。這與前面說到的LOADKX的處理方法一樣,都是為處理超大數據服務的。
如果使用核能產生多個返回值的表達式(... 和函數調用)初始化數組項,如果這個初始化不是表構造的最後一項,那麼只有第一個返回值會被設置到數組項;如果是最後一項,那麼SETLIST中的B會被設置為0,表示從A+1到當前棧頂都用來設置。
SETLIST只負責初始化表的數組部分,對於hash部分,還是通過SETTABLE來初始化。
name | args | desc |
---|---|---|
OP_GETTABLE | ABC | R(A) := R(B)[RK(C)] |
OP_SETTABLE | ABC | R(A)[RK(B)] := RK(C) |
GETTABLE使用C表示的key,將寄存器B中的表項值獲取到寄存器A中。SETTABLE設置寄存器A的表的B項為C代表的值。
- local a = {};
- ax = 1;
- local b = ax;
- 1 [1] NEWTABLE 0 0 0
- 2 [2] SETTABLE 0 -1 -2 ; "x" 1
- 3 [3] GETTABLE 1 0 -1 ; "x"
- 4 [3] RETURN 0 1
No comments:
Post a Comment