summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/00-misc/math_return_table/init.lua0
-rw-r--r--src/00-misc/math_return_table/matrix.lua0
-rw-r--r--src/00-misc/math_return_table/misc/guid.lua0
-rw-r--r--src/00-misc/math_return_table/misc/init.lua0
-rw-r--r--src/00-misc/math_return_table/misc/lerp.lua0
-rw-r--r--src/00-misc/math_return_table/misc/rand.lua0
-rw-r--r--src/00-misc/math_return_table/misc/uuid.lua0
-rw-r--r--src/00-misc/math_return_table/quaternion.lua0
-rw-r--r--src/00-misc/math_return_table/vector.lua0
-rw-r--r--src/00-misc/misc.lua8
-rw-r--r--src/00-misc/vec.lua3
-rw-r--r--src/lua51/lapi.c9
-rw-r--r--src/lua51/lauxlib.c2
-rw-r--r--src/lua51/lauxlib.h2
-rw-r--r--src/lua51/lcode.c1
-rw-r--r--src/lua51/ldo.c39
-rw-r--r--src/lua51/lgc.c68
-rw-r--r--src/lua51/lgc.h28
-rw-r--r--src/lua51/llex.c4
-rw-r--r--src/lua51/llex.h1
-rw-r--r--src/lua51/lobject.h62
-rw-r--r--src/lua51/lopcodes.c7
-rw-r--r--src/lua51/lopcodes.h33
-rw-r--r--src/lua51/lparser.c5
-rw-r--r--src/lua51/lstate.c1
-rw-r--r--src/lua51/lstate.h52
-rw-r--r--src/lua51/lstring.c39
-rw-r--r--src/lua51/ltable.c36
-rw-r--r--src/lua51/lua.h1
-rw-r--r--src/lua51/lvm.c24
-rw-r--r--src/math/math.cpp37
-rw-r--r--src/math/math.h9
32 files changed, 370 insertions, 101 deletions
diff --git a/src/00-misc/math_return_table/init.lua b/src/00-misc/math_return_table/init.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/init.lua
diff --git a/src/00-misc/math_return_table/matrix.lua b/src/00-misc/math_return_table/matrix.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/matrix.lua
diff --git a/src/00-misc/math_return_table/misc/guid.lua b/src/00-misc/math_return_table/misc/guid.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/misc/guid.lua
diff --git a/src/00-misc/math_return_table/misc/init.lua b/src/00-misc/math_return_table/misc/init.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/misc/init.lua
diff --git a/src/00-misc/math_return_table/misc/lerp.lua b/src/00-misc/math_return_table/misc/lerp.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/misc/lerp.lua
diff --git a/src/00-misc/math_return_table/misc/rand.lua b/src/00-misc/math_return_table/misc/rand.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/misc/rand.lua
diff --git a/src/00-misc/math_return_table/misc/uuid.lua b/src/00-misc/math_return_table/misc/uuid.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/misc/uuid.lua
diff --git a/src/00-misc/math_return_table/quaternion.lua b/src/00-misc/math_return_table/quaternion.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/quaternion.lua
diff --git a/src/00-misc/math_return_table/vector.lua b/src/00-misc/math_return_table/vector.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/00-misc/math_return_table/vector.lua
diff --git a/src/00-misc/misc.lua b/src/00-misc/misc.lua
index e73d2e3..8894dbb 100644
--- a/src/00-misc/misc.lua
+++ b/src/00-misc/misc.lua
@@ -1,3 +1,5 @@
-package.preload["00-misc.vec"] = loadfile("00-misc/vec.lua")
-
-require("00-misc.vec")
+a = "a"
+b = "b"
+c = "c"
+c = nil
+collectgarbage()
diff --git a/src/00-misc/vec.lua b/src/00-misc/vec.lua
index 2862a16..9d81f40 100644
--- a/src/00-misc/vec.lua
+++ b/src/00-misc/vec.lua
@@ -1 +1,2 @@
-print("vec.lua") \ No newline at end of file
+print("vec.lua")
+
diff --git a/src/lua51/lapi.c b/src/lua51/lapi.c
index 5d5145d..0678908 100644
--- a/src/lua51/lapi.c
+++ b/src/lua51/lapi.c
@@ -801,7 +801,7 @@ static void f_call (lua_State *L, void *ud) {
}
-
+//c
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
struct CallS c;
int status;
@@ -816,7 +816,7 @@ 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 */
+ c.func = L->top - (nargs+1); /* function to be called */ //调用的函数的指针,是f_parser函数的输出,放在栈顶的那个指针
c.nresults = nresults;
status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
adjustresults(L, nresults);
@@ -859,6 +859,8 @@ LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
}
+//c 加载代码,并编译生成函数原型 调用了f_parser
+//c load完之后会生成一个closure(包含proto)在栈顶
LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
const char *chunkname) {
ZIO z;
@@ -866,7 +868,8 @@ 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);
- status = luaD_protectedparser(L, &z, chunkname);
+ //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 10f14e2..f1bdd39 100644
--- a/src/lua51/lauxlib.c
+++ b/src/lua51/lauxlib.c
@@ -548,7 +548,7 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
return LUA_ERRFILE;
}
-
+//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 3425823..6ac7967 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 679cb9c..e1da87b 100644
--- a/src/lua51/lcode.c
+++ b/src/lua51/lcode.c
@@ -786,6 +786,7 @@ void luaK_fixline (FuncState *fs, int line) {
}
+//c 指令生成
static int luaK_code (FuncState *fs, Instruction i, int line) {
Proto *f = fs->f;
dischargejpc(fs); /* `pc' will change */
diff --git a/src/lua51/ldo.c b/src/lua51/ldo.c
index d1bf786..eac8d03 100644
--- a/src/lua51/ldo.c
+++ b/src/lua51/ldo.c
@@ -149,6 +149,7 @@ void luaD_reallocstack (lua_State *L, int newsize) {
}
+//c
void luaD_reallocCI (lua_State *L, int newsize) {
CallInfo *oldci = L->base_ci;
luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
@@ -165,7 +166,8 @@ void luaD_growstack (lua_State *L, int n) {
luaD_reallocstack(L, L->stacksize + n);
}
-
+//c 当分配的callinfo数组不够大的,以2的指数扩展它
+//c callinfo的大小不会超过LUAI_MAXCALLS
static CallInfo *growCI (lua_State *L) {
if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */
luaD_throw(L, LUA_ERRERR);
@@ -256,12 +258,14 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
}
-
+//c 如果不够大了,扩容;然后返回++L->ci,即下一个ci
#define inc_ci(L) \
((L->ci == L->end_ci) ? growCI(L) : \
(condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
+//c 做函数调用前的准备
+//c 将函数原型的指令code放在savedpc中,准备就绪
int luaD_precall (lua_State *L, StkId func, int nresults) {
LClosure *cl;
ptrdiff_t funcr;
@@ -269,7 +273,7 @@ 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;
+ L->ci->savedpc = L->savedpc;//c 先把当前虚拟机执行的位置保存下来,留给后面调用完函数后luad_poscall恢复到这个位置
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
StkId st, base;
@@ -294,6 +298,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
L->savedpc = p->code; /* starting point */
ci->tailcalls = 0;
ci->nresults = nresults;
+ //c 将多余的参数赋值为nil,比如函数定义需要3个参数,但是只穿了1个,那么另外两个赋值为nil
for (st = L->top; st < ci->top; st++)
setnilvalue(st);
L->top = ci->top;
@@ -305,14 +310,20 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
return PCRLUA;
}
else { /* if is a C function, call it */
+ //c 这里能发现两个限制,一个是函数调用的嵌套限制LUAI_MAXCALL,一个是函数调用需要的数据栈大小不能超过
+ //c lua_State数据栈的大小BASIC_STACK_SIZE + EXTRA_STACK(在stack_init函数中)
+
CallInfo *ci;
int n;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ //c 找一个新的调用CallInfo对象,如果lua_state的callinfo数组不够大了,扩展它,但不能超过LUAI_MAXCALLS
+ //c 拿到下一个callinfo对象
ci = inc_ci(L); /* now `enter' new function */
- ci->func = restorestack(L, funcr);
- L->base = ci->base = ci->func + 1;
- ci->top = L->top + LUA_MINSTACK;
- lua_assert(ci->top <= L->stack_last);
+ ci->func = restorestack(L, funcr);//c callinfo的函数原型
+ //c 从这里能看出,lua_state的数据栈的base是跟着调用变动的
+ L->base = ci->base = ci->func + 1;//c 设置当前调用的数据栈
+ ci->top = L->top + LUA_MINSTACK;//c 设置当前调用的最大数据栈容量
+ lua_assert(ci->top <= L->stack_last); //c 调用的栈顶不能超过lua数据栈的上限
ci->nresults = nresults;
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
@@ -340,6 +351,7 @@ static StkId callrethooks (lua_State *L, StkId firstResult) {
}
+//c 函数执行完毕后,将lua_state恢复到上一次函数调用的状态
int luaD_poscall (lua_State *L, StkId firstResult) {
StkId res;
int wanted, i;
@@ -350,7 +362,7 @@ 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 */
+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ //c 恢复到调用之前的状态,很好理解,在父函数处这个函数执行完了,可以接着走了
/* move results to correct place */
for (i = wanted; i != 0 && firstResult < L->top; i--)
setobjs2s(L, res++, firstResult++);
@@ -361,6 +373,7 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
}
+//c 执行代码的入口,不限于函数(因为lua代码段就是封装为了函数)
/*
** Call a function (C or Lua). The function to be called is at *func.
** The arguments are on the stack, right after the function.
@@ -374,6 +387,8 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
+ //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 */
L->nCcalls--;
@@ -453,6 +468,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
}
+//c 调用函数
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t old_top, ptrdiff_t ef) {
int status;
@@ -488,6 +504,8 @@ struct SParser { /* data to `f_parser' */
const char *name;
};
+//c 词法分析和语法分析,调用luaY_parser
+//c 执行完后将closure留在栈顶
static void f_parser (lua_State *L, void *ud) {
int i;
Proto *tf;
@@ -499,18 +517,21 @@ static void f_parser (lua_State *L, void *ud) {
&p->buff, p->name);
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
cl->l.p = tf;
+ //c 初始化upvalue
for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
cl->l.upvals[i] = luaF_newupval(L);
- setclvalue(L, L->top, cl);
+ setclvalue(L, L->top, cl);//把闭包放在栈顶
incr_top(L);
}
+//c 保护模式下编译代码
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
struct SParser p;
int status;
p.z = z; p.name = name;
luaZ_initbuffer(L, &p.buff);
+ //c在保护模式下执行 f_parser 函数
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
return status;
diff --git a/src/lua51/lgc.c b/src/lua51/lgc.c
index e909c79..f4dbdfb 100644
--- a/src/lua51/lgc.c
+++ b/src/lua51/lgc.c
@@ -48,7 +48,7 @@
#define VALUEWEAK bitmask(VALUEWEAKBIT)
-
+// 标记对象,有点类似一个安全声明,mark了的对象不会被回收,会被标记为灰色(大多数情况下)或黑色
#define markvalue(g,o) { checkconsistency(o); \
if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
@@ -66,16 +66,24 @@ static void removeentry (Node *n) {
}
+//c 标记object(不标记这个object引用的object,udata除外,需要标记udata的mt和env)
+//c 至于标记object引用的object留在扫描阶段
static void reallymarkobject (global_State *g, GCObject *o) {
lua_assert(iswhite(o) && !isdead(g, o));
+ //改为灰色
white2gray(o);
+ //对于大部分类型,都是把gcobject加到gray链表
switch (o->gch.tt) {
case LUA_TSTRING: {
+ // 字符串不会引用其他数据,所以略过,不用加到gray list
return;
}
case LUA_TUSERDATA: {
+ // udata本身也不会引用其他对象,所以不需要扫描,直接标记为黑色
Table *mt = gco2u(o)->metatable;
+ // 直接标记为黑色
gray2black(o); /* udata are never gray */
+ // 标记一下它的mt和env表
if (mt) markobject(g, mt);
markobject(g, gco2u(o)->env);
return;
@@ -83,6 +91,8 @@ static void reallymarkobject (global_State *g, GCObject *o) {
case LUA_TUPVAL: {
UpVal *uv = gco2uv(o);
markvalue(g, uv->v);
+ // 当这个upvalue是closed状态,表示这个uv已经没有与其他数据的引用关系
+ // 直接标记黑色
if (uv->v == &uv->u.value) /* closed? */
gray2black(o); /* open upvalues are never black */
return;
@@ -154,7 +164,8 @@ size_t luaC_separateudata (lua_State *L, int all) {
return deadmem;
}
-
+// 遍历table
+// 如果是弱表,返回1
static int traversetable (global_State *g, Table *h) {
int i;
int weakkey = 0;
@@ -170,16 +181,23 @@ static int traversetable (global_State *g, Table *h) {
h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
(weakvalue << VALUEWEAKBIT));
+ // 加到weak链表
h->gclist = g->weak; /* must be cleared after GC, ... */
g->weak = obj2gco(h); /* ... so put in the appropriate list */
}
}
- if (weakkey && weakvalue) return 1;
+ if (weakkey && weakvalue) return 1; // 如果是弱表,返回1
+
+ // 如果不是弱表,遍历table的散列部分和数组部分所有元素
+
+ //数组
if (!weakvalue) {
i = h->sizearray;
while (i--)
markvalue(g, &h->array[i]);
}
+
+ //散列
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
@@ -277,24 +295,25 @@ static void traversestack (global_State *g, lua_State *l) {
static l_mem propagatemark (global_State *g) {
GCObject *o = g->gray;
lua_assert(isgray(o));
- gray2black(o);
+ gray2black(o);//预先标记为黑色
switch (o->gch.tt) {
- case LUA_TTABLE: {
+ case LUA_TTABLE: { //扫描table,尝试标记数组和哈希部分
Table *h = gco2h(o);
g->gray = h->gclist;
+ // 如果是弱表,回退回灰色状态
if (traversetable(g, h)) /* table is weak? */
black2gray(o); /* keep it gray */
return sizeof(Table) + sizeof(TValue) * h->sizearray +
sizeof(Node) * sizenode(h);
}
- case LUA_TFUNCTION: {
+ case LUA_TFUNCTION: { //扫描函数,尝试标记env、upvalue
Closure *cl = gco2cl(o);
g->gray = cl->c.gclist;
traverseclosure(g, cl);
return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
sizeLclosure(cl->l.nupvalues);
}
- case LUA_TTHREAD: {
+ case LUA_TTHREAD: { //扫描线程对象,
lua_State *th = gco2th(o);
g->gray = th->gclist;
th->gclist = g->grayagain;
@@ -428,11 +447,15 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
}
+//c 检查字符串桶的大小,如果太大了,将空的桶删掉,重新分配桶
+//c
static void checkSizes (lua_State *L) {
global_State *g = G(L);
/* check size of string hash */
+ //c 如果桶的总大小是用到的桶位(即字符串数量)的4倍,且是MINSTRTABSIZE的2倍
+ //c 给桶瘦身
if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
- g->strt.size > MINSTRTABSIZE*2)
+ g->strt.size > MINSTRTABSIZE*2)
luaS_resize(L, g->strt.size/2); /* table is too big */
/* check size of buffer */
if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
@@ -497,15 +520,21 @@ static void markmt (global_State *g) {
}
+//c 初始化root
+//c 将mainthread,
/* mark root set */
static void markroot (lua_State *L) {
global_State *g = G(L);
+ // 清空
g->gray = NULL;
g->grayagain = NULL;
g->weak = NULL;
+ // 标记mainthread
markobject(g, g->mainthread);
/* make global table be traversed before main stack */
+ // 标记 _G 为灰色
markvalue(g, gt(g->mainthread));
+ // 标记注册表为灰色
markvalue(g, registry(L));
markmt(g);
g->gcstate = GCSpropagate;
@@ -553,15 +582,16 @@ static void atomic (lua_State *L) {
}
+//c! 单步GC的入口
static l_mem singlestep (lua_State *L) {
global_State *g = G(L);
/*lua_checkmemory(L);*/
switch (g->gcstate) {
- case GCSpause: {
+ case GCSpause: { // 初始化
markroot(L); /* start a new collection */
return 0;
}
- case GCSpropagate: {
+ case GCSpropagate: { // 扫描并标记
if (g->gray)
return propagatemark(g);
else { /* no more `gray' objects */
@@ -681,27 +711,33 @@ void luaC_barrierback (lua_State *L, Table *t) {
g->grayagain = o;
}
-
+//c! 将一个新建的GCGamobject(udata除外,加载其他地方,具体看luaS_newudata)加入root,并标记为白色
+//c upvalue 不一定会设为white,所以不会调这个函数
+//c 虽然被加入了rootgc,但是不会被轻易回收,lua有双白色缓冲概念
+//c 分为currentwhite和otherwhite。如果某个对象创建在GC的标记阶段以后,它的white和标记时的white不是一个white,
+//c 在回收阶段会判断一下,不会回收这个对象
+//c global_State的currentwhite switch发生在标记阶段后
void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
global_State *g = G(L);
o->gch.next = g->rootgc;
g->rootgc = o;
- o->gch.marked = luaC_white(g);
- o->gch.tt = tt;
+ o->gch.marked = luaC_white(g);//标记为current white
+ o->gch.tt = tt;//设置数据类型
}
-
+//c! 将一个upvalue加入root,由于upvalue是对已经存在的对象的间接引用,所以和普通对象不太一样
void luaC_linkupval (lua_State *L, UpVal *uv) {
global_State *g = G(L);
GCObject *o = obj2gco(uv);
o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
g->rootgc = o;
+ // 这里和普通对象不一样
if (isgray(o)) {
- if (g->gcstate == GCSpropagate) {
+ if (g->gcstate == GCSpropagate) {//如果在扫描阶段,直接将对象置为黑色
gray2black(o); /* closed upvalues need barrier */
luaC_barrier(L, uv, uv->v);
}
- else { /* sweep phase: sweep it (turning it into white) */
+ else { /* 否则的话和普通对象一样置为白色 */ /* sweep phase: sweep it (turning it into white) */
makewhite(g, o);
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
}
diff --git a/src/lua51/lgc.h b/src/lua51/lgc.h
index 5a8dc60..9fa686a 100644
--- a/src/lua51/lgc.h
+++ b/src/lua51/lgc.h
@@ -14,11 +14,11 @@
/*
** Possible states of the Garbage Collector
*/
-#define GCSpause 0
-#define GCSpropagate 1
-#define GCSsweepstring 2
-#define GCSsweep 3
-#define GCSfinalize 4
+#define GCSpause 0 // 暂停
+#define GCSpropagate 1 // 扫描,正在遍历灰色节点,检查引用情况
+#define GCSsweepstring 2 // 字符串回收阶段
+#define GCSsweep 3 // 除了字符串的其他对象的回收阶段
+#define GCSfinalize 4 // 终止阶段
/*
@@ -51,15 +51,15 @@
*/
-#define WHITE0BIT 0
-#define WHITE1BIT 1
+#define WHITE0BIT 0 // 01
+#define WHITE1BIT 1 // 10
#define BLACKBIT 2
-#define FINALIZEDBIT 3
-#define KEYWEAKBIT 3
-#define VALUEWEAKBIT 4
-#define FIXEDBIT 5
-#define SFIXEDBIT 6
-#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
+#define FINALIZEDBIT 3 //标记没有被引用的udata
+#define KEYWEAKBIT 3 //标记弱表的key
+#define VALUEWEAKBIT 4 // 标记弱表的value
+#define FIXEDBIT 5 // 标记lua_state主线程对象不可回收
+#define SFIXEDBIT 6 // 标记lua关键字不要回收
+#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) // 结果是11
#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
@@ -74,6 +74,8 @@
#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
+// g->currentwhite & WHITEBITS是 current white
+// g->currentwhite ^ WHITEBITS是 otherwhite
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
diff --git a/src/lua51/llex.c b/src/lua51/llex.c
index 88c6790..fe4e3ee 100644
--- a/src/lua51/llex.c
+++ b/src/lua51/llex.c
@@ -33,6 +33,7 @@
#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
+//c 对应RESERVED中的枚举, tokens
/* ORDER RESERVED */
const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
@@ -61,12 +62,15 @@ static void save (LexState *ls, int c) {
}
+//c 设置保留字
void luaX_init (lua_State *L) {
int i;
for (i=0; i<NUM_RESERVED; i++) {
TString *ts = luaS_new(L, luaX_tokens[i]);
luaS_fix(ts); /* reserved words are never collected */
lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
+ //c 标记这个字符串为保留字,即不为零
+ //c luaX_tokens中的索引
ts->tsv.reserved = cast_byte(i+1); /* reserved word */
}
}
diff --git a/src/lua51/llex.h b/src/lua51/llex.h
index a9201ce..8a013f9 100644
--- a/src/lua51/llex.h
+++ b/src/lua51/llex.h
@@ -17,6 +17,7 @@
#define TOKEN_LEN (sizeof("function")/sizeof(char))
+//c tokens枚举,用来做终结符
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER RESERVED"
diff --git a/src/lua51/lobject.h b/src/lua51/lobject.h
index f1e447e..af6b63a 100644
--- a/src/lua51/lobject.h
+++ b/src/lua51/lobject.h
@@ -40,6 +40,10 @@ typedef union GCObject GCObject;
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
+// 需要垃圾回收的类型包含这个头
+//c next 指向下一个gc链表的成员
+//c tt 数据类型
+//c GC标记,用来保存颜色,有白色(2种),灰色和黑色
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
@@ -53,6 +57,8 @@ typedef struct GCheader {
+//c lua_TValue下第二高级的数据封装类型,不含数据类型标识
+//c 包含需要GC的类型和不需要GC的类型
/*
** Union of all Lua values
*/
@@ -68,8 +74,10 @@ typedef union {
** Tagged Values
*/
+//c 用在两个地方,lua_TValue和TKey
#define TValuefields Value value; int tt
+//c 最上层的Value类型,包含值和类型
typedef struct lua_TValue {
TValuefields;
} TValue;
@@ -112,7 +120,7 @@ typedef struct lua_TValue {
lua_assert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
-
+//c 将TValue结构具体为对应的类型和值;即修改TValue的tt和value部分
/* Macros to set values */
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
@@ -193,6 +201,9 @@ typedef struct lua_TValue {
typedef TValue *StkId; /* index to stack elements */
+//c 字符串
+//c 每个字符串都需要计算hash,用来比较和查找字符串
+//c 如果这个字符串已经存在,不再生成新的字符串,而是使用旧的
/*
** String headers for string table
*/
@@ -200,8 +211,8 @@ typedef union TString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */
struct {
CommonHeader;
- lu_byte reserved;
- unsigned int hash;
+ lu_byte reserved;//标记字符串是否是lua的关键字,如果是,不会被GC回收
+ unsigned int hash;//字符串的哈希值,比较字符串的依据
size_t len;
} tsv;
} TString;
@@ -210,8 +221,7 @@ typedef union TString {
#define getstr(ts) cast(const char *, (ts) + 1)
#define svalue(o) getstr(rawtsvalue(o))
-
-
+// userdata,和TString比较像
typedef union Udata {
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct {
@@ -223,18 +233,22 @@ typedef union Udata {
} Udata;
-
-
+//c! 函数原型,是沟通前端和后端(分析阶段和执行阶段)的数据
+//c! 主要有 字节码、常量、局部变量、upvalue
/*
** Function Prototypes
*/
typedef struct Proto {
CommonHeader;
+ //c 函数的常量
TValue *k; /* constants used by the function */
+ //c 函数字节码
Instruction *code;
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;
int sizeupvalues;
@@ -259,6 +273,7 @@ typedef struct Proto {
#define VARARG_NEEDSARG 4
+//c 局部变量
typedef struct LocVar {
TString *varname;
int startpc; /* first point where variable is active */
@@ -312,6 +327,7 @@ typedef union Closure {
} Closure;
+//c 判断函数类型,5.2通过高位判断,在基础类型基础上产生变体 variant
#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
@@ -319,36 +335,54 @@ typedef union Closure {
/*
** Tables
*/
-
+//c 表的某个元素的key
typedef union TKey {
+ //nk 用来拿到下一个node的指针
struct {
- TValuefields;
+ TValuefields; // 就是TValue
+ //c 指向下一个node
struct Node *next; /* for chaining */
- } nk;
- TValue tvk;
+ } nk; // next key
+ //tvk 用来拿本node的key值
+ TValue tvk; // key value
} TKey;
-
+//c 表的单个元素
typedef struct Node {
- TValue i_val;
- TKey i_key;
+ TValue i_val;//value
+ TKey i_key; //key
} Node;
+//c 表
typedef struct Table {
CommonHeader;
+ //c 标记这个表有哪些元方法,第一次查找时为0,如果有某个元方法,将对应位置为1
+ //c 下次查找时就不需要查找字符串了
+ //c flag会在luaH_set清空
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
+ //c lsizenode=log2(length of hash table) 由此可知散列表大小一定是2的幂
+ //c 所以如果散列表要扩展,在原大小基础上扩展一倍
+ //c 要得到散列表大小,只需要移位 length of hash table = 1 << lsizenode
lu_byte lsizenode; /* log2 of size of `node' array */
+ //c 该表的元表
struct Table *metatable;
+ //c 数组部分
TValue *array; /* array part */
+ //c 散列桶起始位置
+ //c 多个桶,桶内通过TKey->nk->next连接
Node *node;
+ //c 空位置
Node *lastfree; /* any free position is before this position */
+ //c 在global_State中有关gc的链表的下一个(如果这个对象被加入了的话)
GCObject *gclist;
+ //c 数组部分的大小
int sizearray; /* size of `array' array */
} Table;
+//c 计算哈希值,用在很多地方
/*
** `module' operation for hashing (size is always a power of 2)
*/
diff --git a/src/lua51/lopcodes.c b/src/lua51/lopcodes.c
index 4cc7452..64652bb 100644
--- a/src/lua51/lopcodes.c
+++ b/src/lua51/lopcodes.c
@@ -55,7 +55,12 @@ const char *const luaP_opnames[NUM_OPCODES+1] = {
NULL
};
-
+//c 限制每个指令的具体格式,用来后续判断
+//c t 是不是逻辑判断类指令,如相等,大于,小于
+//c a 此指令会不会赋值给寄存器A
+//c b 参数格式OpArgMask,如是寄存器,指令跳转偏移,常数
+//c c 同上
+//c m 指令格式
#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
const lu_byte luaP_opmodes[NUM_OPCODES] = {
diff --git a/src/lua51/lopcodes.h b/src/lua51/lopcodes.h
index 41224d6..8c0d1a8 100644
--- a/src/lua51/lopcodes.h
+++ b/src/lua51/lopcodes.h
@@ -34,13 +34,24 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
/*
** size and position of opcode arguments.
*/
-#define SIZE_C 9
-#define SIZE_B 9
-#define SIZE_Bx (SIZE_C + SIZE_B)
-#define SIZE_A 8
+/*
+三种指令的格式
+iABC B:9 C:9 A:8 Opcode:6
+iABx Bx:18 A:8 Opcode:6
+iAsBx sBx:18 A:8 Opcode:6
+注:sBx是signed BX
+寄存器就是相对于callinfo和lua_state的当前调用的base的某个偏移(即ABC值)
+*/
+//c 单个指令Instruction的每部分的大小
+// 9 + 9 + 8 + 6 = 32 bits
+#define SIZE_B 9
+#define SIZE_C 9
+#define SIZE_Bx (SIZE_C + SIZE_B)
+#define SIZE_A 8
#define SIZE_OP 6
+//c 每个部分在Instruction中的偏移量,从低位到高位
#define POS_OP 0
#define POS_A (POS_OP + SIZE_OP)
#define POS_C (POS_A + SIZE_A)
@@ -76,7 +87,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
/*
** the following macros help to manipulate instructions
*/
-
+//c 获取和设置Instruction中的某个部分
#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
@@ -115,9 +126,11 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
** Macros to operate RK indices
*/
+//c 高位为1时代表常数
/* this bit 1 means constant (0 means register) */
#define BITRK (1 << (SIZE_B - 1))
+//c 检查x是不是常量,规定高位是1的话就是常量,去常量表里查,而不是寄存器
/* test whether value is a constant */
#define ISK(x) ((x) & BITRK)
@@ -241,12 +254,12 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
** bit 6: instruction set register A
** bit 7: operator is a test
*/
-
+//c 指令的参数格式
enum OpArgMask {
- OpArgN, /* argument is not used */
- OpArgU, /* argument is used */
- OpArgR, /* argument is a register or a jump offset */
- OpArgK /* argument is a constant or register/constant */
+ OpArgN, /* argument is not used */ // 未使用(没有座位R()和RK()的参数使用)
+ OpArgU, /* argument is used */ // 使用的
+ OpArgR, /* argument is a register or a jump offset */ // 寄存器、跳转偏移
+ OpArgK /* argument is a constant or register/constant */ // 寄存器、常量
};
LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
diff --git a/src/lua51/lparser.c b/src/lua51/lparser.c
index dda7488..7da34e7 100644
--- a/src/lua51/lparser.c
+++ b/src/lua51/lparser.c
@@ -380,9 +380,10 @@ static void close_func (LexState *ls) {
}
+//c! 编译生成字节码,分析阶段的唯一入口,返回proto指针
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
struct LexState lexstate;
- struct FuncState funcstate;
+ struct FuncState funcstate; // 分析过程中的临时数据
lexstate.buff = buff;
luaX_setinput(L, &lexstate, z, luaS_new(L, name));
open_func(&lexstate, &funcstate);
@@ -394,7 +395,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
lua_assert(funcstate.prev == NULL);
lua_assert(funcstate.f->nups == 0);
lua_assert(lexstate.fs == NULL);
- return funcstate.f;
+ return funcstate.f; //c 最终生成的字节码
}
diff --git a/src/lua51/lstate.c b/src/lua51/lstate.c
index 4313b83..7e55cd0 100644
--- a/src/lua51/lstate.c
+++ b/src/lua51/lstate.c
@@ -39,6 +39,7 @@ typedef struct LG {
+//c 初始化一个lua_state的栈
static void stack_init (lua_State *L1, lua_State *L) {
/* initialize CallInfo array */
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
diff --git a/src/lua51/lstate.h b/src/lua51/lstate.h
index 3bc575b..1ec30a8 100644
--- a/src/lua51/lstate.h
+++ b/src/lua51/lstate.h
@@ -35,20 +35,31 @@ struct lua_longjmp; /* defined in ldo.c */
+//c 散列桶
+//c 全局存放字符串的地方。如果一个字符串在此存在,不用重新生成。
+//c 如果表扩张的太厉害,每个桶的字符串太多,会进行一次rehash,重新分配每个桶的数据量
+//c rehash在lstring.c -> luaS_resize
typedef struct stringtable {
- GCObject **hash;
- lu_int32 nuse; /* number of elements */
- int size;
+ GCObject **hash; //c 字符串,因为是散列桶,所以是**
+ lu_int32 nuse; //c 桶用到的容量,因为不一定size都用到了 /* number of elements */
+ int size; //c 桶的总容量,是常值
+ // nuse和size是用来动态控制桶容量的关键
} stringtable;
+//c 当前函数的调用信息,和lua_State的调用部分类似
+//c 都有top, base俩个与栈相关的成员
+//c StkId引用的永远是lua_State栈上的内容
/*
** informations about a call
*/
typedef struct CallInfo {
+ //c 当前调用的base值,即在栈上操作的开始位置
StkId base; /* base for this function */
+ //c 函数原型在lua_State数据栈上的位置
StkId func; /* function index in the stack */
StkId top; /* top for this function */
+ //c 当前执行到的指令位置
const Instruction *savedpc;
int nresults; /* expected number of results from this function */
int tailcalls; /* number of tail calls lost under this entry */
@@ -61,31 +72,46 @@ typedef struct CallInfo {
#define f_isLua(ci) (!ci_func(ci)->c.isC)
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
-
+//c 当前虚拟机所有协程共用的内容
/*
** `global state', shared by all threads of this state
*/
typedef struct global_State {
+ //c string table,开散列表,存储所有的字符串
stringtable strt; /* hash table for strings */
lua_Alloc frealloc; /* function to reallocate memory */
void *ud; /* auxiliary data to `frealloc' */
- lu_byte currentwhite;
+ lu_byte currentwhite;//当前白
+ //c 当前的GC状态,有5个,在lgc.h定义
lu_byte gcstate; /* state of garbage collector */
+ //c strt中字符串散列桶索引,字符串回收阶段每次回收一个散列桶的字符串,
int sweepstrgc; /* position of sweep in `strt' */
+ //c 白色链表。可回收的对象,会在回收阶段被回收
+ //c 所有新建的对象都会暂存在这里,但不会被回收,因为lua有双白色机制
GCObject *rootgc; /* list of all collectable objects */
+ //c 保存rootgc中当前回收到的位置,下次从这个位置继续回收
GCObject **sweepgc; /* position of sweep in `rootgc' */
+ //c 灰色链表
GCObject *gray; /* list of gray objects */
+ //c 不可被打断的对象的灰色链表
GCObject *grayagain; /* list of objects to be traversed atomically */
+ //c 弱表
GCObject *weak; /* list of weak tables (to be cleared) */
+ //c 有__gc方法的userdata
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 内存大小的估计值
lu_mem estimate; /* an estimate of number of bytes actually in use */
lu_mem gcdept; /* how much GC is `behind schedule' */
+ //c 控制下一轮GC开始时机
int gcpause; /* size of pause between successive GCs */
+ //c 控制GC回收速度
int gcstepmul; /* GC `granularity' */
lua_CFunction panic; /* to be called in unprotected errors */
+ //c 注册表
TValue l_registry;
struct lua_State *mainthread;
UpVal uvhead; /* head of double-linked list of all open upvalues */
@@ -94,20 +120,29 @@ typedef struct global_State {
} global_State;
+//c 一个lua_state,可以看做是一个
+//c StkId引用的永远是lua_State栈上的内容
/*
** `per thread' state
*/
struct lua_State {
CommonHeader;
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 */
global_State *l_G;
+ //c 当前函数的调用信息,是base_ci数组中的某个
CallInfo *ci; /* call info for current function */
const Instruction *savedpc; /* `savedpc' of current function */
+ //c lua_State数据栈的终点
StkId stack_last; /* last free slot in the stack */
+ //c 数据栈(栈数组的起始地址)(数据栈的起始点)
StkId stack; /* stack base */
+ //c callinfo数组的终点
CallInfo *end_ci; /* points after end of ci array*/
+ //c callinfo 数组, 沿着base_ci遍历可以得到完整的lua调用链
CallInfo *base_ci; /* array of CallInfo's */
int stacksize;
int size_ci; /* size of array `base_ci' */
@@ -118,6 +153,7 @@ struct lua_State {
int basehookcount;
int hookcount;
lua_Hook hook;
+ //c _G global table
TValue l_gt; /* table of globals */
TValue env; /* temporary place for environments */
GCObject *openupval; /* list of open upvalues in this stack */
@@ -130,6 +166,10 @@ struct lua_State {
#define G(L) (L->l_G)
+//c 需要GC的类型基类,通过GCObject能够引用到GCheader中定义的/
+//c #define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
+//c 这种写法是一种实现C继承的方式
+//c 每个
/*
** Union of all collectable objects
*/
@@ -144,7 +184,7 @@ union GCObject {
struct lua_State th; /* thread */
};
-
+//c TValue\GCObject 获取union中的内容
/* macros to convert a GCObject into a specific value */
#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
#define gco2ts(o) (&rawgco2ts(o)->tsv)
diff --git a/src/lua51/lstring.c b/src/lua51/lstring.c
index 4911315..ec1fcdb 100644
--- a/src/lua51/lstring.c
+++ b/src/lua51/lstring.c
@@ -19,25 +19,29 @@
+//c 重新分配global_State->strt每个桶的数据量
+//c 当桶的大小远超字符串容量,重新分配大小,删掉一些空桶(空位)
void luaS_resize (lua_State *L, int newsize) {
GCObject **newhash;
stringtable *tb;
int i;
- if (G(L)->gcstate == GCSsweepstring)
+ if (G(L)->gcstate == GCSsweepstring)//如果GC在回收字符串阶段,不要rehash
return; /* cannot resize during GC traverse */
- newhash = luaM_newvector(L, newsize, GCObject *);
- tb = &G(L)->strt;
+ newhash = luaM_newvector(L, newsize, GCObject *); //建立一个新的散列桶,并清空
+ tb = &G(L)->strt;//旧的散列桶
for (i=0; i<newsize; i++) newhash[i] = NULL;
- /* rehash */
+ //遍历就的散列桶,并填入新的散列桶
+ /* rehash */
for (i=0; i<tb->size; i++) {
GCObject *p = tb->hash[i];
while (p) { /* for each node in the list */
GCObject *next = p->gch.next; /* save next */
unsigned int h = gco2ts(p)->hash;
+ //新的散列值
int h1 = lmod(h, newsize); /* new position */
lua_assert(cast_int(h%newsize) == lmod(h, newsize));
- p->gch.next = newhash[h1]; /* chain it */
- newhash[h1] = p;
+ p->gch.next = newhash[h1];//c 接在同一个hash的最前面 /* chain it */
+ newhash[h1] = p; //c 将p作为桶内第一个存起来
p = next;
}
}
@@ -47,6 +51,7 @@ void luaS_resize (lua_State *L, int newsize) {
}
+//c 新建字符串
static TString *newlstr (lua_State *L, const char *str, size_t l,
unsigned int h) {
TString *ts;
@@ -62,42 +67,53 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */
tb = &G(L)->strt;
+ // 计算hash值
h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */
tb->hash[h] = obj2gco(ts);
tb->nuse++;
+ //c 给字符串通扩容,如果字符串数量大于桶容量
+ //c 给桶扩容为2倍
if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
return ts;
}
+//c 创建字符串
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
GCObject *o;
unsigned int h = cast(unsigned int, l); /* seed */
size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
+ //c 如果字符串非常长,不要逐位计算散列值,每step步取一个字符计算即可
for (l1=l; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
o != NULL;
o = o->gch.next) {
TString *ts = rawgco2ts(o);
- if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {//c 如果散列值相同,用memcmp快速对比
+ //c 如果字符串被标记了回收(gch.marked),重新标记它不要回收
/* string may be dead */
if (isdead(G(L), o)) changewhite(o);
return ts;
}
}
+ //c 如果global->strt里没有这个字符串,新建立一个,并加到哈希桶里
return newlstr(L, str, l, h); /* not found */
}
-
+//c 创建userdata
+//c userdata的gc和普通对象(udata和uv除外的)是分开的
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后面
+ //c udata标记为 white
u->uv.marked = luaC_white(G(L)); /* is not finalized */
u->uv.tt = LUA_TUSERDATA;
u->uv.len = s;
@@ -105,7 +121,10 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
u->uv.env = e;
/* chain it on udata list (after main thread) */
u->uv.next = G(L)->mainthread->next;
- G(L)->mainthread->next = obj2gco(u);
- return u;
+ // 可见所有userdata都跟在mainthread之后第一个
+ // 这样是为了方便,是一个hack
+ // 由于userdata可能会定义了__gc,所以统一处理
+ G(L)->mainthread->next = obj2gco(u);
+ return u;
}
diff --git a/src/lua51/ltable.c b/src/lua51/ltable.c
index ec84f4f..f489a03 100644
--- a/src/lua51/ltable.c
+++ b/src/lua51/ltable.c
@@ -159,6 +159,9 @@ static int findindex (lua_State *L, Table *t, StkId key) {
}
+//c table的遍历操作,返回下一个node
+//c 先计算key的hash,如果在array范围内,在array中找,否则在hash中找
+//c 注意实际上不会两个for循环都走
int luaH_next (lua_State *L, Table *t, StkId key) {
int i = findindex(L, t, key); /* find original element */
for (i++; i < t->sizearray; i++) { /* try first array part */
@@ -208,8 +211,10 @@ static int computesizes (int nums[], int *narray) {
}
+//c 返回1或0,是否将这个key算进要加入表的数组部分
static int countint (const TValue *key, int *nums) {
int k = arrayindex(key);
+ //c 所以数字key的最大范围是0~MAXASIZE
if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
nums[ceillog2(k)]++; /* count as such */
return 1;
@@ -294,6 +299,9 @@ static void setnodevector (lua_State *L, Table *t, int size) {
}
+//c 重新分配table的哈希部分大小为
+//nasize 是 array size
+//nhsize 是 hash table size
static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
int i;
int oldasize = t->sizearray;
@@ -330,18 +338,26 @@ void luaH_resizearray (lua_State *L, Table *t, int nasize) {
}
+//c 给table的散列桶部分重新hash
+//c 用于给table扩容
static void rehash (lua_State *L, Table *t, const TValue *ek) {
+ //c 先计算落在2^(i-1)~2^i范围内的各个区间的元素数量,用于决策新容量
int nasize, na;
+ //c 以2的指数级扩展的数组,记录的是指数。能看出来表的最大大小是2^MAXBITS
int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */
int i;
int totaluse;
for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
+ //c 遍历数组部分和散列桶部分,找出正整数key的值的数量,以此更新nums[]
nasize = numusearray(t, nums); /* count keys in array part */
totaluse = nasize; /* all those keys are integer keys */
totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
/* count extra key */
+ //c 加上这个key(如果在范围内的话)
nasize += countint(ek, nums);
totaluse++;
+ //c 找到一个位置i,这个位置之前的元素个数大于50%,即2^i/2。这个位置之后意味着太空了,效率比较低
+ //c 这个位置
/* compute new size for array part */
na = computesizes(nums, &nasize);
/* resize the table to new computed sizes */
@@ -354,7 +370,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
** }=============================================================
*/
-
+//c 新建table
Table *luaH_new (lua_State *L, int narray, int nhash) {
Table *t = luaM_new(L, Table);
luaC_link(L, obj2gco(t), LUA_TTABLE);
@@ -388,7 +404,7 @@ static Node *getfreepos (Table *t) {
}
-
+//c 表新建key
/*
** inserts a new key into a hash table; first, check whether key's main
** position is free. If not, check whether colliding node is in its main
@@ -398,30 +414,41 @@ static Node *getfreepos (Table *t) {
*/
static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp = mainposition(t, key);
- if (!ttisnil(gval(mp)) || mp == dummynode) {
+ if (!ttisnil(gval(mp)) || mp == dummynode) {//c mainposition上已经有数据
Node *othern;
Node *n = getfreepos(t); /* get a free place */
+ //c 如果没有空位,扩展hash table大小为2倍
if (n == NULL) { /* cannot find a free place? */
rehash(L, t, key); /* grow table */
+ //c 扩展完大小后重试
return luaH_set(L, t, key); /* re-insert key into grown table */
}
lua_assert(n != dummynode);
+ //c 先看一下现在mainposition上的这个node,它的mainposition是不是这个值
+ //c 不是的话给新的key让路
othern = mainposition(t, key2tval(mp));
if (othern != mp) { /* is colliding node out of its main position? */
+ // 把mp空出来,mp里的值移到n(freeposition)
/* yes; move colliding node into free position */
+ //? 这行没看懂
while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
*n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
gnext(mp) = NULL; /* now `mp' is free */
setnilvalue(gval(mp));
+ //mp是要赋值的位置,即新key的元素的位置
}
else { /* colliding node is in its own main position */
/* new node will go into free position */
+ //c 将free position插入到mp后第一个
gnext(n) = gnext(mp); /* chain new position */
gnext(mp) = n;
+ //c 修改一下mp指针,指向freeposition,留个后续使用
mp = n;
}
}
+ //c 如果mainposition位置上是空的,可以直接用mp位置存
+ //c 赋值
gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
luaC_barriert(L, t, key);
lua_assert(ttisnil(gval(mp)));
@@ -553,6 +580,7 @@ static int unbound_search (Table *t, unsigned int j) {
}
+//c 获得table长度
/*
** Try to find a boundary in table `t'. A `boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
@@ -560,7 +588,9 @@ static int unbound_search (Table *t, unsigned int j) {
int luaH_getn (Table *t) {
unsigned int j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {
+ // 二分查找,找到
/* there is a boundary in the array part: (binary) search for it */
+ // i是左界,j是右界
unsigned int i = 0;
while (j - i > 1) {
unsigned int m = (i+j)/2;
diff --git a/src/lua51/lua.h b/src/lua51/lua.h
index a4b73e7..9f45735 100644
--- a/src/lua51/lua.h
+++ b/src/lua51/lua.h
@@ -71,6 +71,7 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
*/
#define LUA_TNONE (-1)
+//c 对外的基础类型,但是内部会区分闭包(C\Lua)、函数(C\Lua)、userdata的类型
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
diff --git a/src/lua51/lvm.c b/src/lua51/lvm.c
index e0a0cd8..85e214a 100644
--- a/src/lua51/lvm.c
+++ b/src/lua51/lvm.c
@@ -343,7 +343,7 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
*/
#define runtime_check(L, c) { if (!(c)) break; }
-
+//c 获得指令中的某个部分的值,并根据opmode进行校验
#define RA(i) (base+GETARG_A(i))
/* to be used after possible stack reallocation */
#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
@@ -374,17 +374,25 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
+//c 执行lua函数(不含C函数,C函数在luaD_precall执行)
+//c 读取字节码并运行,沟通前端和后端的桥梁
+//c 在ldo.c->luaD_call函数中执行,前一步是luaD_precall()
void luaV_execute (lua_State *L, int nexeccalls) {
- LClosure *cl;
- StkId base;
- TValue *k;
- const Instruction *pc;
+ //c 管理指令和数据栈的4个变量,会随着函数调用而改变
+ LClosure *cl;// lua closure,包含函数原型、upvalue、环境env
+ StkId base;// 当前调用的base地址
+ TValue *k;// 当前函数原型里面的常数表
+ const Instruction *pc; //c 执行的指令
+
+ //c 此函数已经返回或调用了其他函数
reentry: /* entry point */
- lua_assert(isLua(L->ci));
- pc = L->savedpc;
+ lua_assert(isLua(L->ci)); // 做一个防护,重入必然是lua代码,OP_CALL和OP_TAILCALL会用luaD_precall处理C函数调用
+
+ pc = L->savedpc;//c 最开始是luaD_precall中赋值的函数原型的指令开头
cl = &clvalue(L->ci->func)->l;
base = L->base;
- k = cl->p->k;
+ k = cl->p->k; //c 当前函数原型的常量,所有函数调用都会用到的
+
/* main loop of interpreter */
for (;;) {
const Instruction i = *pc++;
diff --git a/src/math/math.cpp b/src/math/math.cpp
new file mode 100644
index 0000000..acb215f
--- /dev/null
+++ b/src/math/math.cpp
@@ -0,0 +1,37 @@
+#include "math.h"
+
+#pragma comment(lib, "lua.lib")
+
+#define MATH_API __declspec(dllexport)
+
+MATH_API int /*__cdecl*/ luaopen_math_vector(lua_State* L)
+{
+ lua_pushstring(L, "math.vector module");
+
+ return 1;
+}
+
+
+extern "C" MATH_API int /*__cdecl*/ luaopen_math_matrix(lua_State* L)
+{
+ lua_pushstring(L, "math.matrix module");
+
+ return 1;
+}
+
+extern "C" MATH_API int /*__cdecl*/ luaopen_math_quaternion(lua_State* L)
+{
+ lua_pushstring(L, "math.quaternion module");
+
+ return 1;
+}
+
+MATH_API void foo()
+{
+
+}
+
+class MATH_API Vector
+{
+
+};
diff --git a/src/math/math.h b/src/math/math.h
new file mode 100644
index 0000000..494b725
--- /dev/null
+++ b/src/math/math.h
@@ -0,0 +1,9 @@
+#pragma once
+
+extern "C" {
+#include "../lua51/lua.h"
+#include "../lua51/lualib.h"
+#include "../lua51/lauxlib.h"
+}
+
+//#define MATH_API __declspec(dllexport)