Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7277629
  • 博文数量: 512
  • 博客积分: 12019
  • 博客等级: 上将
  • 技术积分: 6857
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-01 16:46
文章分类

全部博文(512)

文章存档

2024年(2)

2022年(2)

2021年(6)

2020年(59)

2019年(4)

2018年(10)

2017年(5)

2016年(2)

2015年(4)

2014年(4)

2013年(16)

2012年(47)

2011年(65)

2010年(46)

2009年(34)

2008年(52)

2007年(52)

2006年(80)

2005年(22)

分类:

2009-02-25 14:15:48

3 lua中函数调用的方法

         前面,以及分析了lua中定义一个函数的方法,现在总结如下:

1、  将函数名作为局部变量存在局部变量表里,并在栈上开辟一个寄存器空间,在运行期,将新建一个closure,并存在已保留的寄存器里;

2、  将在语法解析阶段新建的FuncState结构体保存在其父函数的局部函数定义数组里。

        

         现在,就要分析,当lua进行函数调用的时候,是怎么调用的呢?

        

         当分析到这里,对于lua生成中间码的过程就比较熟悉了。关键是生成的中间码必须要和lua虚拟机的执行联系在一起。所以,对于这里分析的函数调用,要结合lua虚拟机的执行一起来分析。

        

         上篇文章对生成局部函数中间码做了简单的介绍。这里知道,当lua发现一个新定义的函数的时候,会生成OP_CLOSURE指令。那么,lua虚拟机执行到OP_CLOSURE后怎么执行呢?

         在此之前,先说在lua解析代码完了以后,会做那些善后之事呢?

         前面说过,lua会把一个代码文件当作是一个函数解析执行。在解析期间,它会率先生成一个FuncState的结构,作为最外面的函数。但这是解析时做的事情,运行期间,是不会有FuncState这个东西出现的。在运行期间,是由一个个叫CallInfo的数据结果的,它指的是当前运行的函数。

         那么,在解析代码以后,是怎么转入运行的呢?

        

         秘密就在lua做的一些善后工作。在f_parser()函数里,解析完了后,最外层的那个FuncState是有的,其实用的是FuncState里的函数头Proto。然后,lua会新建一个闭包(Closure),通过函数luaF_newLclosure(),并把刚才解析代码生成的Proto保存在这个闭包里,cl->l.p=tf,新建完了这个Closurelua会把它压入栈。然后就转入运行期进行运行。也就是进入lua_pcall()函数执行。而lua_pcall()这个函数就是假设在当前栈顶有一个Closure,然后执行这个Closure。具体说来如下:

         lua_pcall()经过一系列调用,最后通过调用luaD_precall()来执行。

         这个luaD_precall()做什么呢?如果这个函数是C函数,那么就直接执行,如果是lua函数,这个函数便字如其人了,就是做执行前的准备。

         首先,这个函数就会在Lci数组里申请一项空槽。也就是说,L里有一个CallInfo数组,代表每个执行的函数。然后用现在的Closure初始化这个CallInfo。并且将这个函数的栈底标志在栈顶,也就是那个Closure压入栈的地方。

         接着,就是转入lua的虚拟机的运行了。也就是函数luaV_execute()

 

         这时,如果遇到OP_CALL的时候,也就是在lua代码中有函数调用的时候,就会直接用luaD_precall(),将要执行的函数加载到L->ci中去,然后重新开始luaV_execute()虚拟机执行。

        

         与调用函数相对应的,怎么从一个函数里返回呢?

 

         也就是,当lua虚拟机遇到OP_RETUREN的时候,该如何操作呢?

 

         lua会通过一个函数来实现从子函数到调用它的函数里的一个转变:luaD_poscall()。在这个函数里,lua主要做的事情就是,因为L->ci是个链,代表当前运行函数的嵌套调用链,调用过的函数会被直接丢弃。于是,只要L->ci--,也就是让当前ci指针退一格,指向前面调用它的函数,即可返回。另外,要将栈底位置和pc值恢复,这些恢复都很简单。

 

         但是,最主要的一件事,就是如果这个函数里含有upvalue怎么办?这个留在明天再研究一下。

阅读(7105) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~