Lua 闭包 和upvalue

一、基本概念
线程的所有打开upvalue(在堆栈上的upvalue) 都存放在L->openupvalue
当前函数的upvalue 的位置有两种情况:
是父函数的local变量
是父函数的upvalue变量

二、闭包创建:
是父函数的upvalue时,那么只需要引用父函数upvalue。
是父函数的local变量 那么现在L->openupvalue 找,找到就引用。找不到创建一个连接到L->openupvalue 和g->uvhead。注意这里创建的upvalue不会链接到allgc 上。
创建闭包的虚拟指令:
OP_CLOSURE 创建闭包
for(upvalue 数量) 初始化upvalue
{
if (父函数的local变量)
OP_MOVE
else
OP_GETUPVAL
}

三、闭包关闭
OP_CLOSE:
函数关闭时,会清除自己的局部变量。如果这个局部变量是在L->openupvalue 中,那么要将他的值拷贝过去。并从L->openupvalue和g->uvhead移除加入到allgc 
例:
function fatherFun()
local a = 1
function childFun()
local x = a
end
a = 3
end
childFun创建:这时fatherFun还未关闭。

fatherFun关闭:
(1)如果fatherFun的局部变量是其他闭包的upvalue,那么拷贝栈中的值到upvalue中。

(2)从L->openupvalue和g->uvhead移除加入到allgc




C closure 跟 Lua closure 的 upvalue 有什么不同
typedef struct CClosure {
ClosureHeader;
lua_CFunction f;
TValue upvalue[1];
} CClosure;


typedef struct LClosure {
ClosureHeader;
struct Proto *p;
UpVal *upvals[1];
} LClosure;
因为LClosure 有两种状态open 和 close。当open状态是需要链接到openupvalue和uvhead 上,所有需要额外的链接指针信息。


PS:openupvalue 是与线程(L)关联的,uvhead 是全局的。

参考文章 点击打开链接





















猜你喜欢

转载自blog.csdn.net/dingqinghui/article/details/79423006