Friday, March 15, 2013

探索Lua5.2內部實現:虛擬機指令(5)Arithmetic


nameargsdesc
OP_ADDABCR(A) := RK(B) + RK(C)
OP_SUBABCR(A) := RK(B) - RK(C)
OP_MULABCR(A) := RK(B) * RK(C)
OP_DIVABCR(A) := RK(B) / RK(C)
OP_MODABCR(A) := RK(B) % RK(C)
OP_POWABCR(A) := RK(B) ^ RK(C)
上表中的指令都是與lua本身的二元操作符一一對應的標準3地址指令。B和C兩個操作數計算的結果存入A中。
  1. local a = 1;  
  2. a = a + 1;  
  3. a = a - 1;  
  4. a = a * 1;  
  5. a = a / 1;  
  6. a = a % 1;  
  7. a = a ^ 1;  
  1. main <test.lua:0,0> (8 instructions at 0x80048eb0)  
  2. 0+ params, 2 slots, 1 upvalue, 1 local, 1 constant, 0 functions  
  3.     1 [1] LOADK 0 -1 ; 1  
  4.     2 [2] ADD 0 0 -1 ; - 1  
  5.     3 [3] SUB 0 0 -1 ; - 1  
  6.     4 [4] MUL 0 0 -1 ; - 1  
  7.     5 [5] DIV 0 0 -1 ; - 1  
  8.     6 [6] MOD 0 0 -1  
  9.     7 [7] POW 0 0 -1 ; - 1  
  10.     8 [7] RETURN 0 1  
  11. constants (1) for 0x80048eb0:  
  12.     1 1  
  13. locals (1) for 0x80048eb0:  
  14.     0 a 2 9  
  15. upvalues​​ (1) for 0x80048eb0:  
  16.     0 _ENV 1 0    
可以看到,生成的指令沒有多餘的操作,每個指令都對應一個完整的二元計算操作。
nameargsdesc
OP_UNMABR(A) := -R(B)
OP_NOTABAB  R(A) := not R(B)
上表中指令對應'-'和'not'一元操作符,表示將B取反或not後放入A中。
  1. local a = 1;  
  2. local b = not a;  
  3. local c = -a;  
  1. 1 [1] LOADK 0 -1 ; 1  
  2. 2 [2] NOT 1 0  
  3. 3 [3] UNM 2 0  
  4. 4 [3] RETURN 0 1   
在編譯和指令生成階段,lua還支持所有一元和二元操作符表達式的常量表達式折疊”(const expression folding)優化。也就是如果計算操作數如果都是數字常量,可以在編譯期計算出結果,就直接使用這個結果值,而不用生成計算指令。
  1. local a = 1 + 1;  
  2. local b = not 1;  
  1. 1 [1] LOADK 0 -1 ; 2  
  2. 2 [2] LOADBOOL 1 0 0  
  3. 3 [2] RETURN 0 1  
從生成的結果可以看到1+1並沒有生成對應的OP_ADD,而是直接把結果2賦值給了a。並且也沒有為not 1生成OP_NOT指令,而是直接將false賦值給了b。
nameargsdesc
OP_LENABR(A) := length of R(B)
LEN直接對應'#'操作符,返回B對象的長度,並保存到A中。
  1. local a = #"foo";  
  1. 1 [1] LOADK 0 -1 ; "foo"  
  2. 2 [1] LEN 0 0  
  3. 3 [1] RETURN 0 1   
nameargsdesc
OP_CONCATABCR(A) := R(B).. ... ..R(C)
CONCAT將B和C指定範圍內的字符串按順序傳接到一起,將結果存入到A。
  1. local a = "foo1".."foo2".."foo3";  
  1. 1 [1] LOADK 0 -1 ; "foo1"  
  2. 2 [1] LOADK 1 -2 ; "foo2"  
  3. 3 [1] LOADK 2 -3 ; "foo3"  
  4. 4 [1] CONCAT 0 0 2  
  5. 5 [1] RETURN 0 1   

No comments: