设为首页 加入收藏

TOP

Lua执行字节码的过程介绍
2015-07-16 12:56:52 来源: 作者: 【 】 浏览:4
Tags:Lua 执行 字节 过程 介绍

前面一篇文章中介绍了lua给下面代码生成最终的字节码的整个过程,这次我们来看看lua vm执行这些字节码的过程。


生成的字节码如下所示:



接下来第5行,函数luaF_newLclosure生成了一个Closure结构体来表示lua的closure,然后下一行将Proto结构体地址传给cl保存,接下来的循环里cl的upvalue数组记录下main func中的upvalue,然后setclvalue函数将cl放入到lua stack的栈顶上,incr_top将栈顶L->top加一。此时lua stack的顶部存放了包裹了main func的closure结构体,下面lua将会调用lua_pcall函数来执行这个closure了,也即vm加载整个生成的字节码并加以解释。



首先第4行根据要执行的函数参数数量和L->top的值来算出function在lua stack中的位置并将其保存到CallS结构体中,其中CallS结构体中的StkId类型为stack下标类型。接着第6行将c和f_call函数一起传入luaD_pcall函数中,luaD_pcall函数执行一些标志的设置后调用函数luaD_rawrunprotected,函数luaD_rawrunprotected内部调用f_call并将c作为其参数传入。如下所示:


在luaD_call中首先判断lua此时是否到达了函数调用层次的最大值,超过这报错否则判断要执行的函数是不是lua function,是的话就调用luaV_execute函数来运行vm执行字节码。


luaV_execute函数是vm执行字节码的核心过程,整个函数约有400行代码,由于整个过程分支太多,我们只讲解示例中的字节码解析过程。


L->savedpc为字节码数组的指针,因此pc保存了当前要执行字节码的下标,clvalue萃取出当前要执行的lua function对应的closure,k指向了当前function的常量数组。


下面先来看看vm解释loadk01字节码的过程。


第3行i保存了当前要执行的字节码,同时pc指向下一条字节码,第6行ra保存了通过宏RA萃取出的字节码中的a部分并与function stack的base相加得出的stack中的值;第8行Get_OPCODE宏萃取出字节码i的类型,结果是OP_LOADK,因此调用了setobj2s函数,其中KBx宏萃取出字节码i的bx部分并与function的常量数组地址相加得出的常量值,这里ra指向了function stack中相应的位置,KBx(i)部分指向了当前function中常量数组中存放的常量“bar”。


obj1为ra,obj2为KBx结果。可以看到第7行将这两个值转换为了TValue,并将o2的value设为o1的value,o2的值的类型设为o1的类型,效果上完成了将“bar”的值存放在了function stack上。接着又返回到上面的主循环处读取下一个字节码并执行,下一个要执行的字节码为setglobal00.


首先第5行中,cl->env为当前function的环境,函数sethvalue将其传给了g,KBx(i)指向了function常量数组中的值,ra为stack中的值,这里为前一条字节码loadk保存在stack中的“bar”。


这里首先判断g是不是table,然后第7行取得g的hash部分,通过第8行luaH_set里的luaH_get得到table中key对应的old value。最后第11行,函数setobj2t将val("bar")存放在了全局变量foo的位置处,即foo = “bar”。


好了到了这里语句foo = “bar”对应的两条字节码的解释过程已经全部介绍完了,下面的三条字节码就不再详细解释了,大家可以按照上面的路线自己过一遍~


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Lua解析赋值类型代码的过程 下一篇Go 语言的分布式读写互斥

评论

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