diff options
Diffstat (limited to 'src/lua51')
| -rw-r--r-- | src/lua51/lapi.c | 3 | ||||
| -rw-r--r-- | src/lua51/lauxlib.c | 3 | ||||
| -rw-r--r-- | src/lua51/lauxlib.h | 2 | ||||
| -rw-r--r-- | src/lua51/lcode.c | 7 | ||||
| -rw-r--r-- | src/lua51/ldo.c | 4 | ||||
| -rw-r--r-- | src/lua51/ldo.h | 2 | ||||
| -rw-r--r-- | src/lua51/lgc.c | 82 | ||||
| -rw-r--r-- | src/lua51/lgc.h | 7 | ||||
| -rw-r--r-- | src/lua51/linit.c | 1 | ||||
| -rw-r--r-- | src/lua51/loadlib.c | 2 | ||||
| -rw-r--r-- | src/lua51/lobject.h | 9 | ||||
| -rw-r--r-- | src/lua51/lstate.h | 10 | ||||
| -rw-r--r-- | src/lua51/lstring.c | 8 | ||||
| -rw-r--r-- | src/lua51/ltable.c | 4 | ||||
| -rw-r--r-- | src/lua51/lua.c | 6 | ||||
| -rw-r--r-- | src/lua51/luac.c | 5 | ||||
| -rw-r--r-- | src/lua51/lundump.c | 3 | ||||
| -rw-r--r-- | src/lua51/lvm.c | 54 | ||||
| -rw-r--r-- | src/lua51/lvm.h | 1 |
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); |
