设为首页 加入收藏

TOP

Lua解析脚本过程中的关键数据结构介绍(二)
2015-07-16 12:57:01 来源: 作者: 【 】 浏览:33
Tags:Lua 解析 脚本 过程 关键 数据结构 介绍
le structure */
?8? lu_byte upval;? /* true if some variable in the block is an upvalue */
?9? lu_byte isbreakable;? /* true if `block' is a loop */
10 } BlockCnt;


?


Lua使用BlockCnt来保存一个block的数据。与FuncState的分析方法类似,BlockCnt使用一个previous变量保存外围block的引用,形成一个栈结构。


?


下面介绍一些在lobject.h文件里面的数据结构


?


?1 /*
?2 ** Function Prototypes
?3 */
?4 typedef struct Proto {
?5? CommonHeader;
?6? TValue *k;? /* constants used by the function */
?7? Instruction *code;
?8? struct Proto **p;? /* functions defined inside the function */
?9? int *lineinfo;? /* map from opcodes to source lines */
10? struct LocVar *locvars;? /* information about local variables */
11? TString **upvalues;? /* upvalue names */
12? TString? *source;
13? int sizeupvalues;
14? int sizek;? /* size of `k' */
15? int sizecode;
16? int sizelineinfo;
17? int sizep;? /* size of `p' */
18? int sizelocvars;
19? int linedefined;
20? int lastlinedefined;
21? GCObject *gclist;
22? lu_byte nups;? /* number of upvalues */
23? lu_byte numparams;
24? lu_byte is_vararg;
25? lu_byte maxstacksize;
26 } Proto;


?


结构体Proto是lua函数协议的描述,在lua解析脚本时首先会将main chunk代码包裹为一个函数,用main proto描述,接着将里面定义的内部函数一一用Proto结构体描述,将这些Proto的关系用树来组合起来,例如有lua源码文件如下


?


1 a = 1
2 function f1()
3 -- ...
4 end
5 function f2()
6? ? function f3()
7? ? -- ...
8? ? end
9 end


?


则parse完成后会有如图如下关系


?


在Proto结构体中,k指向一个const变量数组,存放则函数要用到的常量;code指向lua parse过程中生成的本函数的instruction集合;p就是指向本函数内部定义的函数的那些proto;locvars指向本函数局部变量数组;upvalues指向本函数upvalue变量数组;nups为upvalue的数量;numparams为函数参数的数量;is_vararg表示函数是否接收可变参数;maxstacksize为函数stack的max大小。


在编译期间lua使用Proto描述函数的,当lua vm开始运行vm时需要根据Proto生成相应的Closure来执行vm instructions。


1 typedef union Closure {
2? CClosure c;
3? LClosure l;
4 } Closure;


Closure要么代表了c函数,要么为lua函数,在这里我们只看lua函数的LClosure


?


1 #define ClosureHeader \
2? ? CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
3? ? struct Table *env
4 //... ...
5 typedef struct LClosure {
6? ClosureHeader;
7? struct Proto *p;
8? UpVal *upvals[1];
9 } LClosure;


?


在LClousre中,p就是指向对应函数的Proto结构体啦,upvals顾名思义就是此closure的upvalue数组罗。在ClosureHeader宏中isC表示此closure是否是c函数,nupvalues为upvalue数目,env指向了此closue运行时的函数环境,在lua中可以用stefenv来改变当前函数的环境,就是改变env变量的指向啦。


最后,在文件lopcode.h中定义了lua vm的指令结构


?


下面是vm指令的一些定义与描述,我在相应vm指令的上方添加了一些注释


?


?1 typedef enum {
?2 /*----------------------------------------------------------------------
?3 name? ? ? ? args? ? description
?4 ------------------------------------------------------------------------*/
?5 OP_MOVE,/*? ? A B? ? R(A) := R(B)? ? ? ? ? ? ? ? ? ? */
?6 //Constants are usually numbers or strings. Each function has its own constant list, or pool.
?7 OP_LOADK,/*? ? A Bx? ? R(A) := Kst(Bx)? ? ? ? ? ? ? ? ? ? */
?8 OP_LOADBOOL,/*? ? A B C? ? R(A) := (Bool)B; if (C) pc++? ? ? ? ? ? */
?9 //The optimization rule is? a simple one: If no other instructions have been generated,
10 //then a LOADNIL as the first instruction can be optimized away.
11 OP_LOADNIL,/*? ? A B? ? R(A) := ... := R(B) := nil? ? ? ? ? ? */
12
13 OP_GETUPVAL,/*? ? A B? ? R(A) := UpValue[B]? ? ? ? ? ? ? ? */
14 OP_GETGLOBAL,/*? ? A Bx? ? R(A) := Gbl[Kst(Bx)]? ? ? ? ? ? ? ? */
15 OP_GETTABLE,/*? ? A B C? ? R(A) := R(B)[RK(C)]? ? ? ? ? ? ? ? */
16
17 OP_SETGLOBAL,/*? ? A Bx? ? Gbl[Kst(Bx)] := R(A)? ? ? ? ? ? ? ? */
18 OP_SETUPVAL,/*? ? A B? ? UpValue[B] := R(A)? ? ? ? ? ? ? ? */
19 OP_SETTABLE,/*? ? A B C? ? R(A)[RK(B)] := RK(C)? ? ? ? ? ? ? ? */
20
21 OP_NEWTABLE,/*? ? A B C? ? R(A) := {} (size = B,C)? ? ? ? ? ? ? ? */
22
23 //This instruction is used for object-oriented programming. It is only generated for method calls that use the colon

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++string中有关大小和容量的函数.. 下一篇Lua中的string类型

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: