summaryrefslogtreecommitdiff
path: root/src/lua51
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua51')
-rw-r--r--src/lua51/lapi.c3
-rw-r--r--src/lua51/lauxlib.c3
-rw-r--r--src/lua51/lauxlib.h2
-rw-r--r--src/lua51/lcode.c7
-rw-r--r--src/lua51/ldo.c4
-rw-r--r--src/lua51/ldo.h2
-rw-r--r--src/lua51/lgc.c82
-rw-r--r--src/lua51/lgc.h7
-rw-r--r--src/lua51/linit.c1
-rw-r--r--src/lua51/loadlib.c2
-rw-r--r--src/lua51/lobject.h9
-rw-r--r--src/lua51/lstate.h10
-rw-r--r--src/lua51/lstring.c8
-rw-r--r--src/lua51/ltable.c4
-rw-r--r--src/lua51/lua.c6
-rw-r--r--src/lua51/luac.c5
-rw-r--r--src/lua51/lundump.c3
-rw-r--r--src/lua51/lvm.c54
-rw-r--r--src/lua51/lvm.h1
19 files changed, 166 insertions, 47 deletions
diff --git a/src/lua51/lapi.c b/src/lua51/lapi.c
index 0678908..eeaa5ad 100644
--- a/src/lua51/lapi.c
+++ b/src/lua51/lapi.c
@@ -895,10 +895,11 @@ LUA_API int lua_status (lua_State *L) {
}
+//c GC的操作,也可以在脚本内通过collectgarbage函数调用。
+//c 手动触发GC、设置GC相关参数
/*
** Garbage-collection function
*/
-
LUA_API int lua_gc (lua_State *L, int what, int data) {
int res = 0;
global_State *g;
diff --git a/src/lua51/lauxlib.c b/src/lua51/lauxlib.c
index f1bdd39..343ec0d 100644
--- a/src/lua51/lauxlib.c
+++ b/src/lua51/lauxlib.c
@@ -548,7 +548,8 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
return LUA_ERRFILE;
}
-//c 进行词法分析和语法分析
+//c! 执行源代码的入口
+//c 读取源代码\字节码,进行词法分析和语法分析并完成代码生成
LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
LoadF lf;
int status, readstatus;
diff --git a/src/lua51/lauxlib.h b/src/lua51/lauxlib.h
index 6ac7967..3425823 100644
--- a/src/lua51/lauxlib.h
+++ b/src/lua51/lauxlib.h
@@ -119,7 +119,7 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
/*
-** ======================================================
+** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
diff --git a/src/lua51/lcode.c b/src/lua51/lcode.c
index e1da87b..8f25b06 100644
--- a/src/lua51/lcode.c
+++ b/src/lua51/lcode.c
@@ -226,6 +226,7 @@ static void freeexp (FuncState *fs, expdesc *e) {
}
+//c 设置常量表
static int addk (FuncState *fs, TValue *k, TValue *v) {
lua_State *L = fs->L;
TValue *idx = luaH_set(L, fs->h, k);
@@ -247,13 +248,15 @@ static int addk (FuncState *fs, TValue *k, TValue *v) {
}
+//c 设置常量字符串
int luaK_stringK (FuncState *fs, TString *s) {
TValue o;
- setsvalue(fs->L, &o, s);
+ setsvalue(fs->L, &o, s); //c o.value.gc = s; o.tt=LUA_TSTRING
return addk(fs, &o, &o);
}
+//c 设置常量数字
int luaK_numberK (FuncState *fs, lua_Number r) {
TValue o;
setnvalue(&o, r);
@@ -261,6 +264,7 @@ int luaK_numberK (FuncState *fs, lua_Number r) {
}
+//c 设置常量bool值
static int boolK (FuncState *fs, int b) {
TValue o;
setbvalue(&o, b);
@@ -268,6 +272,7 @@ static int boolK (FuncState *fs, int b) {
}
+//c 设置常量nil
static int nilK (FuncState *fs) {
TValue k, v;
setnilvalue(&v);
diff --git a/src/lua51/ldo.c b/src/lua51/ldo.c
index eac8d03..d9b1ea8 100644
--- a/src/lua51/ldo.c
+++ b/src/lua51/ldo.c
@@ -468,7 +468,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
}
-//c 调用函数
+//c 调用C函数
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t old_top, ptrdiff_t ef) {
int status;
@@ -513,6 +513,8 @@ static void f_parser (lua_State *L, void *ud) {
struct SParser *p = cast(struct SParser *, ud);
int c = luaZ_lookahead(p->z);
luaC_checkGC(L);
+ //c 如果是字节码,走直接加载字节码的流程
+ //c 如果是source,走编译流程
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
&p->buff, p->name);
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
diff --git a/src/lua51/ldo.h b/src/lua51/ldo.h
index 98fddac..b310f90 100644
--- a/src/lua51/ldo.h
+++ b/src/lua51/ldo.h
@@ -4,6 +4,8 @@
** See Copyright Notice in lua.h
*/
+//c 函数调用和返回处理。函数(代码块)执行前后的准备和还原工作
+
#ifndef ldo_h
#define ldo_h
diff --git a/src/lua51/lgc.c b/src/lua51/lgc.c
index f4dbdfb..ae845e9 100644
--- a/src/lua51/lgc.c
+++ b/src/lua51/lgc.c
@@ -56,6 +56,9 @@
reallymarkobject(g, obj2gco(t)); }
+// 手动GC
+// estimate 使用中的内存大小估值
+// gcpause 控制两次GC间隔的百分数
#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
@@ -133,28 +136,35 @@ static void marktmu (global_State *g) {
}
}
-
+//c 处理 userdata,userdata都在atomic里面处理,而不是propagatemark
+//c userdata都跟在mainthread之后(这是一个hack的做法,统一放在一个地方,方便处理)
/* move `dead' udata that need finalization to list `tmudata' */
size_t luaC_separateudata (lua_State *L, int all) {
global_State *g = G(L);
size_t deadmem = 0;
+ // udata的链表
GCObject **p = &g->mainthread->next;
GCObject *curr;
- while ((curr = *p) != NULL) {
- if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
+ while ((curr = *p) != NULL) /*遍历*/{
+ //udata创建的时候是白色,加载mainthread后面
+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) // 如果该udata不需要回收,跳过
p = &curr->gch.next; /* don't bother with them */
- else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { // 如果没注册__gc
+ // 标记这个udata为finalized,不需要走finalization流程去调用__gc释放那些native引用
markfinalized(gco2u(curr)); /* don't need finalization */
p = &curr->gch.next;
}
else { /* must call its gc method */
deadmem += sizeudata(gco2u(curr));
+ // 标记为finalized后,还需要加入G(L)->tmudata链表
markfinalized(gco2u(curr));
*p = curr->gch.next;
+ // 把这个udata加到 tmudata 链表最后
/* link `curr' at the end of `tmudata' list */
if (g->tmudata == NULL) /* list is empty? */
g->tmudata = curr->gch.next = curr; /* creates a circular list */
else {
+ //? 这里没看懂
curr->gch.next = g->tmudata->gch.next;
g->tmudata->gch.next = curr;
g->tmudata = curr;
@@ -214,23 +224,29 @@ static int traversetable (global_State *g, Table *h) {
}
+// 扫描函数原型
/*
** All marks are conditional because a GC may happen while the
** prototype is still being created
*/
static void traverseproto (global_State *g, Proto *f) {
int i;
- if (f->source) stringmark(f->source);
+ // 标记文件名
+ if (f->source) stringmark(f->source);
+ // 标记常量
for (i=0; i<f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
+ // 标记upvalue
for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
if (f->upvalues[i])
stringmark(f->upvalues[i]);
}
+ // 标记内部定义的函数
for (i=0; i<f->sizep; i++) { /* mark nested protos */
if (f->p[i])
markobject(g, f->p[i]);
}
+ // 标记局部变量
for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
if (f->locvars[i].varname)
stringmark(f->locvars[i].varname);
@@ -288,6 +304,7 @@ static void traversestack (global_State *g, lua_State *l) {
}
+//c 扫描和标记操作入口
/*
** traverse one gray object, turning it to black.
** Returns `quantity' traversed.
@@ -296,6 +313,7 @@ static l_mem propagatemark (global_State *g) {
GCObject *o = g->gray;
lua_assert(isgray(o));
gray2black(o);//预先标记为黑色
+ //只有table、function、thread、proto会引用其他对象
switch (o->gch.tt) {
case LUA_TTABLE: { //扫描table,尝试标记数组和哈希部分
Table *h = gco2h(o);
@@ -313,20 +331,22 @@ static l_mem propagatemark (global_State *g) {
return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
sizeLclosure(cl->l.nupvalues);
}
- case LUA_TTHREAD: { //扫描线程对象,
+ case LUA_TTHREAD: { //扫描线程对象, 因为lua_State关联的数据变化频繁,所以从graylist中拿出来放到grayaginlist中
lua_State *th = gco2th(o);
+ // 将lua_state从gray中删除,加到grayagain里
g->gray = th->gclist;
th->gclist = g->grayagain;
g->grayagain = o;
+ // 颜色退回为灰色
black2gray(o);
traversestack(g, th);
return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
sizeof(CallInfo) * th->size_ci;
}
- case LUA_TPROTO: {
+ case LUA_TPROTO: { //扫描函数原型,尝试标记文件名、字符串、upvalue、局部变量
Proto *p = gco2p(o);
g->gray = p->gclist;
- traverseproto(g, p);
+ traverseproto(g, p);//标记函数原型的文件名、字符串、upvalue、局部变量
return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
sizeof(Proto *) * p->sizep +
sizeof(TValue) * p->sizek +
@@ -334,7 +354,9 @@ static l_mem propagatemark (global_State *g) {
sizeof(LocVar) * p->sizelocvars +
sizeof(TString *) * p->sizeupvalues;
}
- default: lua_assert(0); return 0;
+ default:
+ lua_assert(0);
+ return 0;
}
}
@@ -419,14 +441,16 @@ static void freeobj (lua_State *L, GCObject *o) {
}
-
+//c 回收阶段回收字符串,每次回收g->strt中的一个桶
+//c p刚进来是这个散列桶的第一个字符串
#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
GCObject *curr;
global_State *g = G(L);
- int deadmask = otherwhite(g);
+ int deadmask = otherwhite(g); // 不可回收的白色,要回收的是currentwhite
+ // 遍历链表
while ((curr = *p) != NULL && count-- > 0) {
if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
sweepwholelist(L, &gco2th(curr)->openupval);
@@ -440,6 +464,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
*p = curr->gch.next;
if (curr == g->rootgc) /* is the first element of the list? */
g->rootgc = curr->gch.next; /* adjust first */
+ //c! 回收对象,根据类型调用不同的内存释放方法
freeobj(L, curr);
}
}
@@ -465,6 +490,7 @@ static void checkSizes (lua_State *L) {
}
+//c 调用 __gc 方法,执行finalization,每次释放一个udata的native引用
static void GCTM (lua_State *L) {
global_State *g = G(L);
GCObject *o = g->tmudata->gch.next; /* get first element */
@@ -477,16 +503,20 @@ static void GCTM (lua_State *L) {
g->tmudata->gch.next = udata->uv.next;
udata->uv.next = g->mainthread->next; /* return it to `root' list */
g->mainthread->next = o;
+ //标记为白色,进入下一次GC的时候回收自身的内存
makewhite(g, o);
+ //调用 __gc
tm = fasttm(L, udata->uv.metatable, TM_GC);
if (tm != NULL) {
lu_byte oldah = L->allowhook;
lu_mem oldt = g->GCthreshold;
L->allowhook = 0; /* stop debug hooks during GC tag method */
g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */
+ // 压入__gc和udata
setobj2s(L, L->top, tm);
setuvalue(L, L->top+1, udata);
L->top += 2;
+ // 调用__gc
luaD_call(L, L->top - 2, 0);
L->allowhook = oldah; /* restore hooks */
g->GCthreshold = oldt; /* restore threshold */
@@ -537,6 +567,7 @@ static void markroot (lua_State *L) {
// 标记注册表为灰色
markvalue(g, registry(L));
markmt(g);
+ //GC 切换到扫描阶段
g->gcstate = GCSpropagate;
}
@@ -551,6 +582,7 @@ static void remarkupvals (global_State *g) {
}
+//c 原子化处理grayagain
static void atomic (lua_State *L) {
global_State *g = G(L);
size_t udsize; /* total size of userdata to be finalized */
@@ -569,6 +601,7 @@ static void atomic (lua_State *L) {
g->gray = g->grayagain;
g->grayagain = NULL;
propagateall(g);
+ // 处理udata
udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
marktmu(g); /* mark `preserved' userdata */
udsize += propagateall(g); /* remark, to propagate `preserveness' */
@@ -576,7 +609,9 @@ static void atomic (lua_State *L) {
/* flip current white */
g->currentwhite = cast_byte(otherwhite(g));
g->sweepstrgc = 0;
+ // 设置当前清理的位置
g->sweepgc = &g->rootgc;
+ // 切换到回收字符串阶段
g->gcstate = GCSsweepstring;
g->estimate = g->totalbytes - udsize; /* first estimate */
}
@@ -592,23 +627,24 @@ static l_mem singlestep (lua_State *L) {
return 0;
}
case GCSpropagate: { // 扫描并标记
- if (g->gray)
+ if (g->gray) // gray list不为空
return propagatemark(g);
else { /* no more `gray' objects */
atomic(L); /* finish mark phase */
return 0;
}
}
- case GCSsweepstring: {
+ case GCSsweepstring: { // 回收字符串
lu_mem old = g->totalbytes;
+ // 回收g->sweepstrgc位置的散列桶
sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
- if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
- g->gcstate = GCSsweep; /* end sweep-string phase */
+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */// 当所有散列桶都回收完毕,切换到sweep
+ g->gcstate = GCSsweep; /* end sweep-string phase */
lua_assert(old >= g->totalbytes);
g->estimate -= old - g->totalbytes;
return GCSWEEPCOST;
}
- case GCSsweep: {
+ case GCSsweep: { // 回收字符串以外的其他类型
lu_mem old = g->totalbytes;
g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
if (*g->sweepgc == NULL) { /* nothing more to sweep? */
@@ -619,7 +655,7 @@ static l_mem singlestep (lua_State *L) {
g->estimate -= old - g->totalbytes;
return GCSWEEPMAX*GCSWEEPCOST;
}
- case GCSfinalize: {
+ case GCSfinalize: { // 结束阶段,专门处理 tmudata ,调用userdata的__gc方法,释放native引用
if (g->tmudata) {
GCTM(L);
if (g->estimate > GCFINALIZECOST)
@@ -627,6 +663,7 @@ static l_mem singlestep (lua_State *L) {
return GCFINALIZECOST;
}
else {
+ // 切到pause,进入下一次GC
g->gcstate = GCSpause; /* end collection */
g->gcdept = 0;
return 0;
@@ -637,6 +674,7 @@ static l_mem singlestep (lua_State *L) {
}
+//c! GC 入口
void luaC_step (lua_State *L) {
global_State *g = G(L);
l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
@@ -688,29 +726,33 @@ void luaC_fullgc (lua_State *L) {
}
+//c 向前避障
void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
lua_assert(ttype(&o->gch) != LUA_TTABLE);
/* must keep invariant? */
- if (g->gcstate == GCSpropagate)
- reallymarkobject(g, v); /* restore invariant */
- else /* don't mind */
+ if (g->gcstate == GCSpropagate)// 如果在扫描阶段,把新建的v加入gray链
+ reallymarkobject(g, v); /* restore invariant */
+ else /* don't mind */ // 否则标记为白色,等待下一次GC
makewhite(g, o); /* mark as white just to avoid other barriers */
}
+//c 向后避障只作用于 table,将table加入 grayagain 链表
void luaC_barrierback (lua_State *L, Table *t) {
global_State *g = G(L);
GCObject *o = obj2gco(t);
lua_assert(isblack(o) && !isdead(g, o));
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
black2gray(o); /* make table gray (again) */
+ // 加到grayagin list里
t->gclist = g->grayagain;
g->grayagain = o;
}
+
//c! 将一个新建的GCGamobject(udata除外,加载其他地方,具体看luaS_newudata)加入root,并标记为白色
//c upvalue 不一定会设为white,所以不会调这个函数
//c 虽然被加入了rootgc,但是不会被轻易回收,lua有双白色缓冲概念
diff --git a/src/lua51/lgc.h b/src/lua51/lgc.h
index 9fa686a..83007ac 100644
--- a/src/lua51/lgc.h
+++ b/src/lua51/lgc.h
@@ -4,6 +4,8 @@
** See Copyright Notice in lua.h
*/
+//c 垃圾回收
+
#ifndef lgc_h
#define lgc_h
@@ -78,12 +80,15 @@
// g->currentwhite ^ WHITEBITS是 otherwhite
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
-
+// 自动触发回收内存,在每次调用内存分配相关API时进行
+// 触发条件是当前分配的内存大于阈值GCthreshold
+// 自动触发不可控,很多人选择关闭它,方法是通过设置一个很大的GCthreshold比如(~0)
#define luaC_checkGC(L) { \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
if (G(L)->totalbytes >= G(L)->GCthreshold) \
luaC_step(L); }
+//c 避障相关操作,分为向前避障 luaC_barrier luaC_objbarrier 和向后避障 luaC_barriert luaC_objbarriert
#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
diff --git a/src/lua51/linit.c b/src/lua51/linit.c
index c1f90df..98b6c3c 100644
--- a/src/lua51/linit.c
+++ b/src/lua51/linit.c
@@ -27,6 +27,7 @@ static const luaL_Reg lualibs[] = {
};
+// 打开内部库
LUALIB_API void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib = lualibs;
for (; lib->func; lib++) {
diff --git a/src/lua51/loadlib.c b/src/lua51/loadlib.c
index 6158c53..a7c68c6 100644
--- a/src/lua51/loadlib.c
+++ b/src/lua51/loadlib.c
@@ -382,7 +382,7 @@ static int loader_Lua (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "path");
if (filename == NULL) return 1; /* library not found in this path */
- if (luaL_loadfile(L, filename) != 0)
+ if (luaL_loadfile(L, filename) != 0) //c 编译生成字节码
loaderror(L, filename);
return 1; /* library loaded successfully */
}
diff --git a/src/lua51/lobject.h b/src/lua51/lobject.h
index af6b63a..25dc341 100644
--- a/src/lua51/lobject.h
+++ b/src/lua51/lobject.h
@@ -244,13 +244,14 @@ typedef struct Proto {
TValue *k; /* constants used by the function */
//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
TString **upvalues; /* upvalue names */
- TString *source;
+ TString *source; //文件名
int sizeupvalues;
int sizek; /* size of `k' */
int sizecode;
@@ -285,7 +286,7 @@ typedef struct LocVar {
/*
** Upvalues
*/
-
+// 判断upvalue是关闭的方式是 uv->v == &uv->u.value
typedef struct UpVal {
CommonHeader;
TValue *v; /* points to stack or to its own value */
@@ -316,8 +317,8 @@ typedef struct CClosure {
typedef struct LClosure {
ClosureHeader;
- struct Proto *p;
- UpVal *upvals[1];
+ struct Proto *p; // lua闭包的函数原型
+ UpVal *upvals[1]; // lua闭包的upvalue
} LClosure;
diff --git a/src/lua51/lstate.h b/src/lua51/lstate.h
index 1ec30a8..2f71e57 100644
--- a/src/lua51/lstate.h
+++ b/src/lua51/lstate.h
@@ -93,20 +93,20 @@ typedef struct global_State {
GCObject **sweepgc; /* position of sweep in `rootgc' */
//c 灰色链表
GCObject *gray; /* list of gray objects */
- //c 不可被打断的对象的灰色链表
+ //c 不可被打断的对象的灰色链表,比如LUA_THREAD
GCObject *grayagain; /* list of objects to be traversed atomically */
//c 弱表
GCObject *weak; /* list of weak tables (to be cleared) */
- //c 有__gc方法的userdata
+ //c 有__gc方法的userdata,会在GC阶段调用__gc释放native侧的引用
GCObject *tmudata; /* last element of list of userdata to be GC */
Mbuffer buff; /* temporary buffer for string concatentation */
lu_mem GCthreshold;
//c 开始进行GC的阈值,当超过这个值时开始GC
lu_mem totalbytes; /* number of bytes currently allocated */
- //c 内存大小的估计值
+ //c 当前使用的内存大小的估计值
lu_mem estimate; /* an estimate of number of bytes actually in use */
lu_mem gcdept; /* how much GC is `behind schedule' */
- //c 控制下一轮GC开始时机
+ //c 一个百分数,控制下一轮GC开始时机,越大,下次gc开始的时间越长
int gcpause; /* size of pause between successive GCs */
//c 控制GC回收速度
int gcstepmul; /* GC `granularity' */
@@ -131,7 +131,7 @@ struct lua_State {
//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 */
+ StkId base; /* base of current function */ //c 每个方法被调用时都会得到自己的一组虚拟寄存器
global_State *l_G;
//c 当前函数的调用信息,是base_ci数组中的某个
CallInfo *ci; /* call info for current function */
diff --git a/src/lua51/lstring.c b/src/lua51/lstring.c
index ec1fcdb..73d34c4 100644
--- a/src/lua51/lstring.c
+++ b/src/lua51/lstring.c
@@ -110,6 +110,8 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
Udata *u;
if (s > MAX_SIZET - sizeof(Udata))
luaM_toobig(L);
+
+ // 创建并赋值
u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
//c udata和普通对象在GC上的区别在于不调用luaC_link,因为不会加在
//c G(L)->rootgc链上,而是加在G(L)->mainthread后面
@@ -119,12 +121,14 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
u->uv.len = s;
u->uv.metatable = NULL;
u->uv.env = e;
- /* chain it on udata list (after main thread) */
- u->uv.next = G(L)->mainthread->next;
+
// 可见所有userdata都跟在mainthread之后第一个
// 这样是为了方便,是一个hack
// 由于userdata可能会定义了__gc,所以统一处理
+ /* chain it on udata list (after main thread) */
+ u->uv.next = G(L)->mainthread->next;
G(L)->mainthread->next = obj2gco(u);
+
return u;
}
diff --git a/src/lua51/ltable.c b/src/lua51/ltable.c
index f489a03..73464a0 100644
--- a/src/lua51/ltable.c
+++ b/src/lua51/ltable.c
@@ -450,7 +450,9 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
//c 如果mainposition位置上是空的,可以直接用mp位置存
//c 赋值
gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
- luaC_barriert(L, t, key);
+ // #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
+ // 如果当前table是黑色,新建key时需要进行向后避障,将table记为灰色,加入grayagin链表
+ luaC_barriert(L, t, key);
lua_assert(ttisnil(gval(mp)));
return gval(mp);
}
diff --git a/src/lua51/lua.c b/src/lua51/lua.c
index 3a46609..eaa70a6 100644
--- a/src/lua51/lua.c
+++ b/src/lua51/lua.c
@@ -1,3 +1,7 @@
+#define COMPILE_LUA_C
+
+#ifdef COMPILE_LUA_C
+
/*
** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
** Lua stand-alone interpreter
@@ -390,3 +394,5 @@ int main (int argc, char **argv) {
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
}
+
+#endif \ No newline at end of file
diff --git a/src/lua51/luac.c b/src/lua51/luac.c
index d070173..08bb8de 100644
--- a/src/lua51/luac.c
+++ b/src/lua51/luac.c
@@ -1,3 +1,5 @@
+#ifdef COMPILE_LUAC
+
/*
** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $
** Lua compiler (saves bytecodes to files; also list bytecodes)
@@ -198,3 +200,6 @@ int main(int argc, char* argv[])
lua_close(L);
return EXIT_SUCCESS;
}
+
+
+#endif \ No newline at end of file
diff --git a/src/lua51/lundump.c b/src/lua51/lundump.c
index 8010a45..564f218 100644
--- a/src/lua51/lundump.c
+++ b/src/lua51/lundump.c
@@ -97,6 +97,7 @@ static void LoadCode(LoadState* S, Proto* f)
static Proto* LoadFunction(LoadState* S, TString* p);
+//c 加载常量
static void LoadConstants(LoadState* S, Proto* f)
{
int i,n;
@@ -158,6 +159,7 @@ static void LoadDebug(LoadState* S, Proto* f)
for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
}
+//c! 加载二进制代码,包含函数原型,常量
static Proto* LoadFunction(LoadState* S, TString* p)
{
Proto* f;
@@ -189,6 +191,7 @@ static void LoadHeader(LoadState* S)
IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
}
+//c 加载编译好的字节码
/*
** load precompiled chunk
*/
diff --git a/src/lua51/lvm.c b/src/lua51/lvm.c
index 85e214a..21de678 100644
--- a/src/lua51/lvm.c
+++ b/src/lua51/lvm.c
@@ -373,7 +373,7 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
}
-
+//c 虚拟机主入口
//c 执行lua函数(不含C函数,C函数在luaD_precall执行)
//c 读取字节码并运行,沟通前端和后端的桥梁
//c 在ldo.c->luaD_call函数中执行,前一步是luaD_precall()
@@ -390,7 +390,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
pc = L->savedpc;//c 最开始是luaD_precall中赋值的函数原型的指令开头
cl = &clvalue(L->ci->func)->l;
- base = L->base;
+ base = L->base; //c base是寄存器开始地址,每个方法被调用时都会得到自己的一组虚拟寄存器
k = cl->p->k; //c 当前函数原型的常量,所有函数调用都会用到的
/* main loop of interpreter */
@@ -407,7 +407,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
base = L->base;
}
/* warning!! several calls may realloc the stack and invalidate `ra' */
- ra = RA(i);
+ ra = RA(i); //c 从指令中拿到ra
lua_assert(base == L->base && L->base == L->ci->base);
lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
@@ -729,18 +729,56 @@ void luaV_execute (lua_State *L, int nexeccalls) {
continue;
}
case OP_CLOSURE: {
- Proto *p;
+ Proto *p; //c 函数原型首地址
Closure *ncl;
int nup, j;
- p = cl->p->p[GETARG_Bx(i)];
- nup = p->nups;
+ p = cl->p->p[GETARG_Bx(i)]; //c 根据索引得到函数原型地址
+ //c lua的每个函数会记录这个函数的信息:参数个数、使用到的stack slot数目、upvalue数目、局部变量数目、常数表、局部函数
+ nup = p->nups; //c number of upvalues,
+ //c 创建闭包new closure
ncl = luaF_newLclosure(L, nup, cl->env);
- ncl->l.p = p;
+ ncl->l.p = p; // 设置函数原型
+ /* //c 一个闭包的创建如下
+-----------------------------------
+1 local a = 10
+2 local b = 20
+3
+4 function foo ()
+5 return a + b
+6 end
+7
+8 local c = 30
+9 foo()
+-----------------------------------
+main <main.lua:0,0> (10 instructions, 40 bytes at 009512A8)
+0+ params, 4 slots, 0 upvalues, 3 locals, 4 constants, 1 function
+ 1 [1] LOADK 0 -1 ; 10
+ 2 [2] LOADK 1 -2 ; 20
+ 3 [6] CLOSURE 2 0 ; 00951CC0
+ 4 [6] MOVE 0 0
+ 5 [6] MOVE 0 1
+ 6 [4] SETGLOBAL 2 -3 ; foo
+ 7 [8] LOADK 2 -4 ; 30
+ 8 [9] GETGLOBAL 3 -3 ; foo
+ 9 [9] CALL 3 1 1
+ 10 [9] RETURN 0 1
+
+function <main.lua:4,6> (5 instructions, 20 bytes at 00951CC0)
+0 params, 2 slots, 2 upvalues, 0 locals, 0 constants, 0 functions
+ 1 [5] GETUPVAL 0 0 ; a
+ 2 [5] GETUPVAL 1 1 ; b
+ 3 [5] ADD 0 0 1
+ 4 [5] RETURN 0 2
+ 5 [6] RETURN 0 1
+-----------------------------------
+012712A8的[6]是闭包的创建过程,两个MOVE指令用来设置闭包的upvalue,两个MOVE的第一个操作数无用
+ */
+ //c 设置闭包的upvalue值
for (j=0; j<nup; j++, pc++) {
if (GET_OPCODE(*pc) == OP_GETUPVAL)
ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
else {
- lua_assert(GET_OPCODE(*pc) == OP_MOVE);
+ lua_assert(GET_OPCODE(*pc) == OP_MOVE);
ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
}
}
diff --git a/src/lua51/lvm.h b/src/lua51/lvm.h
index bfe4f56..19fec22 100644
--- a/src/lua51/lvm.h
+++ b/src/lua51/lvm.h
@@ -30,6 +30,7 @@ LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
StkId val);
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
StkId val);
+//c 虚拟机主入口
LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);
LUAI_FUNC void luaV_concat (lua_State *L, int total, int last);