summaryrefslogtreecommitdiff
path: root/src/lua51
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2020-09-13 20:56:14 +0800
committerchai <chaifix@163.com>2020-09-13 20:56:14 +0800
commit2dfa15a926f06137f2ba6afcce2e3c1d23300100 (patch)
treef86596654a2ec812a39b2c214420ba35db45595b /src/lua51
parentd9c2d065698641837bc75ded236b23d5aaa36fd4 (diff)
*misc
Diffstat (limited to 'src/lua51')
-rw-r--r--src/lua51/lapi.c9
-rw-r--r--src/lua51/lauxlib.c1
-rw-r--r--src/lua51/lauxlib.h1
-rw-r--r--src/lua51/ldo.c47
-rw-r--r--src/lua51/lfunc.c13
-rw-r--r--src/lua51/lobject.h39
-rw-r--r--src/lua51/lstate.h11
-rw-r--r--src/lua51/lvm.c9
8 files changed, 94 insertions, 36 deletions
diff --git a/src/lua51/lapi.c b/src/lua51/lapi.c
index eeaa5ad..a476634 100644
--- a/src/lua51/lapi.c
+++ b/src/lua51/lapi.c
@@ -795,13 +795,14 @@ struct CallS { /* data to `f_call' */
};
+//c 执行字节码,调用luaD_call进入虚拟机主循环
static void f_call (lua_State *L, void *ud) {
struct CallS *c = cast(struct CallS *, ud);
luaD_call(L, c->func, c->nresults);
}
-//c
+//c 执行字节码
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
struct CallS c;
int status;
@@ -816,8 +817,10 @@ LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
api_checkvalidindex(L, o);
func = savestack(L, o);
}
- c.func = L->top - (nargs+1); /* function to be called */ //调用的函数的指针,是f_parser函数的输出,放在栈顶的那个指针
+ //c 调用的函数的指针,是f_parser函数的输出,放在栈顶的那个指针
+ c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults;
+ //c 进入虚拟机主循环 f_call
status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
adjustresults(L, nresults);
lua_unlock(L);
@@ -868,7 +871,7 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
lua_lock(L);
if (!chunkname) chunkname = "?";
luaZ_init(L, &z, reader, data);
- //c 保护模式下编译源代码
+ //c 保护模式下编译源代码,生成一个闭包留在栈顶
status = luaD_protectedparser(L, &z, chunkname); // 编译
lua_unlock(L);
return status;
diff --git a/src/lua51/lauxlib.c b/src/lua51/lauxlib.c
index 343ec0d..c6ec9b0 100644
--- a/src/lua51/lauxlib.c
+++ b/src/lua51/lauxlib.c
@@ -579,6 +579,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
lf.extraline = 0;
}
ungetc(c, lf.f);
+ //c 在这里编译源代码,生成一个闭包留在栈顶
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
readstatus = ferror(lf.f);
if (filename) fclose(lf.f); /* close file (even in case of errors) */
diff --git a/src/lua51/lauxlib.h b/src/lua51/lauxlib.h
index 3425823..51c9528 100644
--- a/src/lua51/lauxlib.h
+++ b/src/lua51/lauxlib.h
@@ -108,6 +108,7 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
+//c luaL_loadfile() 进行词法\语法分析,lua_pcall在虚拟机执行字节码
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
diff --git a/src/lua51/ldo.c b/src/lua51/ldo.c
index d9b1ea8..2311d41 100644
--- a/src/lua51/ldo.c
+++ b/src/lua51/ldo.c
@@ -1,3 +1,6 @@
+//c 函数调用及栈管理
+
+
/*
** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $
** Stack and Call structure of Lua
@@ -266,6 +269,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
//c 做函数调用前的准备
//c 将函数原型的指令code放在savedpc中,准备就绪
+//c 在 luaD_call 调用
int luaD_precall (lua_State *L, StkId func, int nresults) {
LClosure *cl;
ptrdiff_t funcr;
@@ -273,11 +277,12 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
func = tryfuncTM(L, func); /* check the `function' tag method */
funcr = savestack(L, func);
cl = &clvalue(func)->l;
- L->ci->savedpc = L->savedpc;//c 先把当前虚拟机执行的位置保存下来,留给后面调用完函数后luad_poscall恢复到这个位置
+ //c 先把当前虚拟机执行的位置保存下来,留给后面调用完函数后luaD_poscall恢复到这个位置
+ L->ci->savedpc = L->savedpc;
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
StkId st, base;
- Proto *p = cl->p;
+ Proto *p = cl->p; //c 拿到Proto
luaD_checkstack(L, p->maxstacksize);
func = restorestack(L, funcr);
if (!p->is_vararg) { /* no varargs? */
@@ -290,23 +295,27 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
base = adjust_varargs(L, p, nargs);
func = restorestack(L, funcr); /* previous call may change the stack */
}
- ci = inc_ci(L); /* now `enter' new function */
+
+ //c 设置这次调用的CallInfo并将 L 的相关指针设到这个调用上。L和ci的top及base一致
+ ci = inc_ci(L); /* now `enter' new function */ //c 申请一个新的CallInfo结构
ci->func = func;
- L->base = ci->base = base;
+ L->base = ci->base = base; //c base 一致
ci->top = L->base + p->maxstacksize;
lua_assert(ci->top <= L->stack_last);
- L->savedpc = p->code; /* starting point */
+ L->savedpc = p->code; /* starting point */ //c 设置savedpc为字节码的首地址
ci->tailcalls = 0;
ci->nresults = nresults;
- //c 将多余的参数赋值为nil,比如函数定义需要3个参数,但是只穿了1个,那么另外两个赋值为nil
+ //c 将多余的参数赋值为nil,比如函数定义需要3个参数,但是只传了1个,那么另外两个赋值为nil
for (st = L->top; st < ci->top; st++)
setnilvalue(st);
- L->top = ci->top;
+ L->top = ci->top; //c top一致
+
if (L->hookmask & LUA_MASKCALL) {
L->savedpc++; /* hooks assume 'pc' is already incremented */
luaD_callhook(L, LUA_HOOKCALL, -1);
L->savedpc--; /* correct 'pc' */
}
+
return PCRLUA;
}
else { /* if is a C function, call it */
@@ -352,9 +361,11 @@ static StkId callrethooks (lua_State *L, StkId firstResult) {
//c 函数执行完毕后,将lua_state恢复到上一次函数调用的状态
+//c 在lvm.c > luaV_execute() 中当执行到OP_RETURN时调用
int luaD_poscall (lua_State *L, StkId firstResult) {
StkId res;
int wanted, i;
+ //c 本次调用的ci
CallInfo *ci;
if (L->hookmask & LUA_MASKRET)
firstResult = callrethooks(L, firstResult);
@@ -362,7 +373,8 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
res = ci->func; /* res == final position of 1st result */
wanted = ci->nresults;
L->base = (ci - 1)->base; /* restore base */
- L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ //c 恢复到调用之前的状态,很好理解,在父函数处这个函数执行完了,可以接着走了
+ //c 恢复到调用之前的状态,很好理解,在父函数处这个函数执行完了,可以接着走了
+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
/* move results to correct place */
for (i = wanted; i != 0 && firstResult < L->top; i--)
setobjs2s(L, res++, firstResult++);
@@ -390,7 +402,8 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
//c luad_precall将函数指令放在lua_state的savedpc字段,准备就绪
//c luaV_execute执行函数原型的指令,是执行指令的入口
if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
- luaV_execute(L, 1); /* call it */
+ luaV_execute(L, 1); /* call it */ //c 虚拟机主函数
+ //c 结束之后还会在luaV_execute里调luaD_poscall
L->nCcalls--;
luaC_checkGC(L);
}
@@ -504,11 +517,11 @@ struct SParser { /* data to `f_parser' */
const char *name;
};
-//c 词法分析和语法分析,调用luaY_parser
+//c 对读入的源代码,执行词法分析和语法分析,调用luaY_parser
//c 执行完后将closure留在栈顶
static void f_parser (lua_State *L, void *ud) {
int i;
- Proto *tf;
+ Proto *tf; //c 闭包对应的函数原型
Closure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = luaZ_lookahead(p->z);
@@ -517,12 +530,18 @@ static void f_parser (lua_State *L, void *ud) {
//c 如果是source,走编译流程
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
&p->buff, p->name);
+
+ //c 编译之后会得到Proto* tf, 所有的信息,包括常量表、upvalue、字节码、local变量数量等等都在里面
+
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
- cl->l.p = tf;
- //c 初始化upvalue
+ cl->l.p = tf; //c 设置proto = tf
+ //c 新建nups个closed upvalue
for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
cl->l.upvals[i] = luaF_newupval(L);
- setclvalue(L, L->top, cl);//把闭包放在栈顶
+
+ //c 把闭包放在栈顶
+ //c lua_pcall会执行这个闭包
+ setclvalue(L, L->top, cl);
incr_top(L);
}
diff --git a/src/lua51/lfunc.c b/src/lua51/lfunc.c
index 813e88f..df2c8e3 100644
--- a/src/lua51/lfunc.c
+++ b/src/lua51/lfunc.c
@@ -30,21 +30,24 @@ Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
}
+//c 新建lua closure
+//c nelems upvalue的个数
Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
- luaC_link(L, obj2gco(c), LUA_TFUNCTION);
- c->l.isC = 0;
- c->l.env = e;
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION); //c 加入GC链表
+ c->l.isC = 0; //c not c closure
+ c->l.env = e; //c 设置这个闭包的环境
c->l.nupvalues = cast_byte(nelems);
while (nelems--) c->l.upvals[nelems] = NULL;
return c;
}
+//c 新建一个closed upvalue
UpVal *luaF_newupval (lua_State *L) {
UpVal *uv = luaM_new(L, UpVal);
- luaC_link(L, obj2gco(uv), LUA_TUPVAL);
- uv->v = &uv->u.value;
+ luaC_link(L, obj2gco(uv), LUA_TUPVAL); //c 加入GC链表
+ uv->v = &uv->u.value; //c closed
setnilvalue(uv->v);
return uv;
}
diff --git a/src/lua51/lobject.h b/src/lua51/lobject.h
index 4e9daee..ead9391 100644
--- a/src/lua51/lobject.h
+++ b/src/lua51/lobject.h
@@ -242,14 +242,14 @@ typedef struct Proto {
CommonHeader;
//c 常量表,能看出来lua保存常量的单元是函数原型,所有代码片段都会被编译为proto
TValue *k; /* constants used by the function */
- //c 函数字节码
+ //c 函数字节码起始点
Instruction *code;
//c 内部函数
struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines */
//c 局部变量
struct LocVar *locvars; /* information about local variables */
- //c upvalue
+ //c upvalues
TString **upvalues; /* upvalue names */
TString *source; //文件名
int sizeupvalues;
@@ -262,9 +262,9 @@ typedef struct Proto {
int lastlinedefined;
GCObject *gclist;
lu_byte nups; /* number of upvalues */
- lu_byte numparams;
- lu_byte is_vararg;
- lu_byte maxstacksize;
+ lu_byte numparams; //c 参数个数
+ lu_byte is_vararg; //c 是否是可变参数...
+ lu_byte maxstacksize; //c 最大栈大小, 通常200
} Proto;
@@ -286,10 +286,35 @@ typedef struct LocVar {
/*
** Upvalues
*/
-// 判断upvalue是关闭的方式是 uv->v == &uv->u.value
+//c 判断upvalue是关闭的方式是 uv->v == &uv->u.value
+//c upvalue有开闭的概念
+//c 开是指upvalue完全由此方法所有,之前的调用已经结束
+//c 关闭是指upvalue还在之前的栈上
+/*
+* function func()
+* local a = 10;
+* local b = function()
+* a = a + 1
+* print(a)
+* end
+* b() -- 这个是开
+* end
+*
+* function func()
+* local a = 10;
+* local b = function()
+* a = a + 1
+* print(a)
+* end
+* return b
+* end
+*
+* fn = func()
+* fn() -- 这个是关
+*/
typedef struct UpVal {
CommonHeader;
- TValue *v; /* points to stack or to its own value */
+ TValue *v; /* points to stack or to its own value */ //c upvalue的栈地址
union {
TValue value; /* the value (when closed) */
struct { /* double linked list (when open) */
diff --git a/src/lua51/lstate.h b/src/lua51/lstate.h
index 1c049e1..8da0640 100644
--- a/src/lua51/lstate.h
+++ b/src/lua51/lstate.h
@@ -58,10 +58,13 @@ typedef struct CallInfo {
StkId base; /* base for this function */
//c 函数原型在lua_State数据栈上的位置
StkId func; /* function index in the stack */
+ //c 此函数调用过程中的top指针
StkId top; /* top for this function */
//c 当前执行到的指令位置
const Instruction *savedpc;
+ //c 期待的返回值个数
int nresults; /* expected number of results from this function */
+ //c 尾调用个数
int tailcalls; /* number of tail calls lost under this entry */
} CallInfo;
@@ -129,11 +132,13 @@ struct lua_State {
lu_byte status;
//c 当前栈的下一个可用位置
StkId top; /* first free slot in the stack */
- //c 当前*函数栈*的基地址,给某个函数用,在luad_precall函数中设置L->base = ci->base = ci->func + 1;
- StkId base; /* base of current function */ //c 每个方法被调用时都会得到自己的一组虚拟寄存器
+ //c 当前函数栈的基地址,给某个函数用,在luad_precall函数中设置L->base = ci->base = ci->func + 1;
+ //c 每个方法被调用时都会得到自己的一组虚拟“寄存器”,也就是栈上面的数据
+ StkId base; /* base of current function */
global_State *l_G;
- //c 当前函数的调用信息,是base_ci数组中的某个
+ //c 当前执行中函数的调用信息,是base_ci数组中的某个
CallInfo *ci; /* call info for current function */
+ //c 当前执行到的指令位置。为了处理函数的调用和恢复,会在luaD_precall和luaD_poscall设置和恢复
const Instruction *savedpc; /* `savedpc' of current function */
//c lua_State数据栈的终点
StkId stack_last; /* last free slot in the stack */
diff --git a/src/lua51/lvm.c b/src/lua51/lvm.c
index b353500..ea1d019 100644
--- a/src/lua51/lvm.c
+++ b/src/lua51/lvm.c
@@ -378,17 +378,18 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
//c 读取字节码并运行,沟通前端和后端的桥梁
//c 在ldo.c->luaD_call函数中执行,前一步是luaD_precall()
void luaV_execute (lua_State *L, int nexeccalls) {
+
//c 管理指令和数据栈的4个变量,会随着函数调用而改变
LClosure *cl;// lua closure,包含函数原型、upvalue、环境env
StkId base;// 当前调用的base地址
TValue *k;// 当前函数原型里面的常数表
- const Instruction *pc; //c 执行的指令
+ const Instruction *pc; //c 指令指针
//c 此函数已经返回或调用了其他函数
- reentry: /* entry point */
+reentry: /* entry point */
lua_assert(isLua(L->ci)); // 做一个防护,重入必然是lua代码,OP_CALL和OP_TAILCALL会用luaD_precall处理C函数调用
- pc = L->savedpc;//c 最开始是luaD_precall中赋值的函数原型的指令开头
+ pc = L->savedpc;//c 最开始是luaD_precall中赋值的函数原型的指令开头,L->savedpc在luaD_precall中设置
cl = &clvalue(L->ci->func)->l;
base = L->base; //c base是寄存器开始地址,每个方法被调用时都会得到自己的一组虚拟寄存器
k = cl->p->k; //c 当前函数原型的常量,所有函数调用都会用到的
@@ -650,7 +651,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
if (b != 0) L->top = ra+b-1;
if (L->openupval) luaF_close(L, base);
L->savedpc = pc;
- b = luaD_poscall(L, ra);
+ b = luaD_poscall(L, ra); //c! 执行结束后,将L恢复到调用前的状态
if (--nexeccalls == 0) /* was previous function running `here'? */
return; /* no: return */
else { /* yes: continue its execution */