Lua源码分析(原创)[持续更新中]

关于Lua源码的基础型别、内存分配、字符串存储、垃圾回收机制、table原理等部分讲解,我发现有位仁兄写得相当之好,强烈推荐大家先认真阅读下面这篇文章,链接如下

http://simohayha.iteye.com/blog/517748

 

本文将只对Lua的字节码和虚拟机的运行相关内容做重点分析

 

LUA OPCODE格式分析

Lopcodes.c

Lua Opcode的格式关键在下面这个宏:

 

#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))

 

t(7)

a(6)

b(4~5)

c(2~3)

m(0~1)

 

如图,第0~1bitm, 2~3bit c,4~5 bitb位,6bita位,7bitt

t,a,b,c,m四部分,一起组成1 byteopcode。下面依次分析下t,a,b,c,m各自扮演什么角色。

 

lua所有指令编码都在下面这个结构中

const lu_byte luaP_opmodes[NUM_OPCODES] = {

/*       T  A    B       C     mode        opcode   */

  opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_MOVE */

 ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_LOADK */

 ......(此处略去78行,有需要请参考附录A LUA OPCODE一览)

 ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_VARARG */

};

enum OpArgMask {

  OpArgN,  /* 参数未被使用 */

  OpArgU,  /* 已使用参数 */

  OpArgR,  /* 该参数是寄存器或跳转偏移 */

  OpArgK   /* 该参数是个常量或寄存器常量, Kconst之意 */

};

结合上面定义以及源码注释,不难分析出如下结论:

 

含义

t

是否是测试操作,测试意味着跳转,跳转和测试指令该位为1

a

是否是寄存器操作

b

B参数OpArgMask类型

c

C参数,OpArgMask类型

m

op mode

 

 

LUA 指令格式分析

任意一条指令由操作码(opcode)和操作数组成。

上一章主要对操作码的格式进行了分析,下面来整体分析下Lua中单条指令的格式。

 

Lua中单条指令为32位,依参数的类型和个数不同,有三种模式:

 

    ------------------------->  

iABC:

B(23~31)

C(14~22)

A(6~13)

opcode(0~5)

 

iABx:

Bx(  14~31 )      

A(6~13)

opcode(0~5)

 

iAsBx:

sBx( 14~31 )      

A(6~13)

opcode(0~5)

 

三种模式中i表示6位的opcode,iABC表示三个参数的指令,iABx将iABC中的B和C合并为18位的无符号数,

iAsBx将iABC中的B和C合并为18位的有符号数。

 

 

相关元素SIZEPOS定义如下:

#define SIZE_C      9

#define SIZE_B      9

#define SIZE_Bx     (SIZE_C + SIZE_B)

#define SIZE_A      8

 

#define SIZE_OP     6

 

#define POS_OP      0

#define POS_A       (POS_OP + SIZE_OP)

#define POS_C       (POS_A + SIZE_A)

#define POS_B       (POS_C + SIZE_C)

#define POS_Bx      POS_C

 

 

 

附录A

LUA OPCODE一览

const lu_byte luaP_opmodes[NUM_OPCODES] = {

/*       T  A    B       C     mode        opcode   */

  opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_MOVE */

 ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_LOADK */

 ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_LOADBOOL */

 ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_LOADNIL */

 ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_GETUPVAL */

 ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_GETGLOBAL */

 ,opmode(0, 1, OpArgR, OpArgK, iABC)        /* OP_GETTABLE */

 ,opmode(0, 0, OpArgK, OpArgN, iABx)        /* OP_SETGLOBAL */

 ,opmode(0, 0, OpArgU, OpArgN, iABC)        /* OP_SETUPVAL */

 ,opmode(0, 0, OpArgK, OpArgK, iABC)        /* OP_SETTABLE */

 ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_NEWTABLE */

 ,opmode(0, 1, OpArgR, OpArgK, iABC)        /* OP_SELF */

 ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_ADD */

 ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_SUB */

 ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_MUL */

 ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_DIV */

 ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_MOD */

 ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_POW */

 ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_UNM */

 ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_NOT */

 ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_LEN */

 ,opmode(0, 1, OpArgR, OpArgR, iABC)        /* OP_CONCAT */

 ,opmode(0, 0, OpArgR, OpArgN, iAsBx)       /* OP_JMP */

 ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_EQ */

 ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_LT */

 ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_LE */

 ,opmode(1, 1, OpArgR, OpArgU, iABC)        /* OP_TEST */

 ,opmode(1, 1, OpArgR, OpArgU, iABC)        /* OP_TESTSET */

 ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_CALL */

 ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_TAILCALL */

 ,opmode(0, 0, OpArgU, OpArgN, iABC)        /* OP_RETURN */

 ,opmode(0, 1, OpArgR, OpArgN, iAsBx)       /* OP_FORLOOP */

 ,opmode(0, 1, OpArgR, OpArgN, iAsBx)       /* OP_FORPREP */

 ,opmode(1, 0, OpArgN, OpArgU, iABC)        /* OP_TFORLOOP */

 ,opmode(0, 0, OpArgU, OpArgU, iABC)        /* OP_SETLIST */

 ,opmode(0, 0, OpArgN, OpArgN, iABC)        /* OP_CLOSE */

 ,opmode(0, 1, OpArgU, OpArgN, iABx)        /* OP_CLOSURE */

 ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_VARARG */

};

 

typedef enum {

/*----------------------------------------------------------------------

name        args    description

------------------------------------------------------------------------*/

OP_MOVE,/*  A B R(A) := R(B)                    */

OP_LOADK,/* A Bx    R(A) := Kst(Bx)                 */

OP_LOADBOOL,/*  A B C   R(A) := (Bool)B; if (C) pc++            */

OP_LOADNIL,/*   A B R(A) := ... := R(B) := nil          */

OP_GETUPVAL,/*  A B R(A) := UpValue[B]              */

 

OP_GETGLOBAL,/* A Bx    R(A) := Gbl[Kst(Bx)]                */

OP_GETTABLE,/*  A B C   R(A) := R(B)[RK(C)]             */

 

OP_SETGLOBAL,/* A Bx    Gbl[Kst(Bx)] := R(A)                */

OP_SETUPVAL,/*  A B UpValue[B] := R(A)              */

OP_SETTABLE,/*  A B C   R(A)[RK(B)] := RK(C)                */

 

OP_NEWTABLE,/*  A B C   R(A) := {} (size = B,C)             */

 

OP_SELF,/*  A B C   R(A+1) := R(B); R(A) := R(B)[RK(C)]     */

 

OP_ADD,/*   A B C   R(A) := RK(B) + RK(C)               */

OP_SUB,/*   A B C   R(A) := RK(B) - RK(C)               */

OP_MUL,/*   A B C   R(A) := RK(B) * RK(C)               */

OP_DIV,/*   A B C   R(A) := RK(B) / RK(C)               */

OP_MOD,/*   A B C   R(A) := RK(B) % RK(C)               */

OP_POW,/*   A B C   R(A) := RK(B) ^ RK(C)               */

OP_UNM,/*   A B R(A) := -R(B)                   */

OP_NOT,/*   A B R(A) := not R(B)                */

OP_LEN,/*   A B R(A) := length of R(B)              */

 

OP_CONCAT,/*    A B C   R(A) := R(B).. ... ..R(C)           */

 

OP_JMP,/*   sBx pc+=sBx                 */

 

OP_EQ,/*    A B C   if ((RK(B) == RK(C)) ~= A) then pc++        */

OP_LT,/*    A B C   if ((RK(B) <  RK(C)) ~= A) then pc++        */

OP_LE,/*    A B C   if ((RK(B) <= RK(C)) ~= A) then pc++        */

 

OP_TEST,/*  A C if not (R(A) <=> C) then pc++           */

OP_TESTSET,/*   A B C   if (R(B) <=> C) then R(A) := R(B) else pc++ */

 

OP_CALL,/*  A B C   R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */

OP_TAILCALL,/*  A B C   return R(A)(R(A+1), ... ,R(A+B-1))      */

OP_RETURN,/*    A B return R(A), ... ,R(A+B-2)  (see note)  */

 

OP_FORLOOP,/*   A sBx   R(A)+=R(A+2);

            if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/

OP_FORPREP,/*   A sBx   R(A)-=R(A+2); pc+=sBx               */

 

OP_TFORLOOP,/*  A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));

                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++   */

OP_SETLIST,/*   A B C   R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B    */

 

OP_CLOSE,/* A   close all variables in the stack up to (>=) R(A)*/

OP_CLOSURE,/*   A Bx    R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))  */

 

OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg        */

} OpCode;

posted @ 2011-03-09 16:07  billin  阅读(18698)  评论(2编辑  收藏  举报