1. 怎么回收的lua 中所有已经分配的数据都会用一些指令的数据结构来记录,当需要回收时,先遍历当前栈内所有 object,把 ref 标志位打上 1,遍历符号表(这部分不能回收),反符号表中的所有对象的 ref 标志位也打上 1, 如果有其它不用回收的也同样操作。回收也比较简单,这里遍历所有内部数据结构,如果是 0 就直接释放, 如果是 1 就置 0(可能下次就回收了), 这样就结束了
2. 何时回收
这个 1.1 有个内部阀值,当新加 object 的数量到达阀值时,就会触发回收机制。
typedef struct Hash
{
char mark;
unsigned int nhash;
Node **list;
} Hash;
typedef struct node
{
Object ref;
Object val;
struct node *next;
} Node;
typedef union
{
Cfunction f;
real n;
char *s;
Byte *b;
struct Hash *a;
void *u;
} Value;
typedef struct Object
{
Type tag;
Value value;
} Object;
typedef struct
{
char *name;
Object object;
} Symbol;
extern Symbol *lua_table; /* key - value 表*/
extern Word lua_ntable;
static Symbol tablebuffer[MAXSYMBOL] = {
{"type",{T_CFUNCTION,{lua_type}}},
...
};
/* list 和数组的结合使用,目地是用 list 和 array 的特性, 参考 lua_findsymbol
在 list 中查找,找到放到头(这样效率高点,下次再被用的概率大点), 没找到,就在头
节点上加一个
*/
Symbol *lua_table=tablebuffer;
Word lua_ntable=7;
static struct List o6={ tablebuffer+6, 0};
static struct List o5={ tablebuffer+5, &o6 };
static struct List o4={ tablebuffer+4, &o5 };
static struct List o3={ tablebuffer+3, &o4 };
static struct List o2={ tablebuffer+2, &o3 };
static struct List o1={ tablebuffer+1, &o2 };
static struct List o0={ tablebuffer+0, &o1 };
static struct List *searchlist=&o0;
extern char **lua_constant; /* 常量表 */
extern Word lua_nconstant;
static char tm[] = " mark";
static char *constantbuffer[MAXCONSTANT] = {tm+1, ti+1,
...
};
extern char **lua_string; /* 就是普通的字符指针数组 *、
extern Word lua_nstring;
static char *stringbuffer[MAXSTRING];
char **lua_string = stringbuffer;
Word lua_nstring=0;
extern Hash **lua_array;
extern Word lua_narray;
extern char *lua_file[]; /* 记录指针的数组 */
extern int lua_nfile;
ps: lua_next 和 lua_nextval 可以看下,这个有点像迭代器的实现
这个还是建议读下,主要就是对 stack 和 pc 的操作。
/*
** Execute the given opcode. Return 0 in success or 1 on error.
*/
int lua_execute (Byte *pc)
{
Object *oldbase = base;
base = top;
while (1)
{
OpCode opcode;
switch (opcode = (OpCode)*pc++)
{
case PUSHNIL: tag(top++) = T_NIL; break;
case PUSH0: tag(top) = T_NUMBER; nvalue(top++) = 0; break;
case PUSH1: tag(top) = T_NUMBER; nvalue(top++) = 1; break;
case PUSH2: tag(top) = T_NUMBER; nvalue(top++) = 2; break;
case PUSHBYTE: tag(top) = T_NUMBER; nvalue(top++) = *pc++; break;
case PUSHWORD:
{
CodeWord code;
get_word(code,pc);
tag(top) = T_NUMBER; nvalue(top++) = code.w;
}
break;
case PUSHFLOAT:
{
CodeFloat code;
get_float(code,pc);
tag(top) = T_NUMBER; nvalue(top++) = code.f;
}
break;
case PUSHSTRING:
{
CodeWord code;
get_word(code,pc);
tag(top) = T_STRING; svalue(top++) = lua_constant[code.w];
}
break;
case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2:
case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5:
case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8:
case PUSHLOCAL9: *top++ = *(base + (int)(opcode-PUSHLOCAL0)); break;
case PUSHLOCAL: *top++ = *(base + (*pc++)); break;
case PUSHGLOBAL:
{
CodeWord code;
get_word(code,pc);
*top++ = s_object(code.w);
}
break;
case PUSHINDEXED:
--top;
if (tag(top-1) != T_ARRAY)
{
lua_reportbug ("indexed expression not a table");
return 1;
}
{
Object *h = lua_hashdefine (avalue(top-1), top);
if (h == NULL) return 1;
*(top-1) = *h;
}
break;
case PUSHMARK: tag(top++) = T_MARK; break;
case PUSHOBJECT: *top = *(top-3); top++; break;
case STORELOCAL0: case STORELOCAL1: case STORELOCAL2:
case STORELOCAL3: case STORELOCAL4: case STORELOCAL5:
case STORELOCAL6: case STORELOCAL7: case STORELOCAL8:
case STORELOCAL9: *(base + (int)(opcode-STORELOCAL0)) = *(--top); break;
case STORELOCAL: *(base + (*pc++)) = *(--top); break;
case STOREGLOBAL:
{
CodeWord code;
get_word(code,pc);
s_object(code.w) = *(--top);
}
break;
case STOREINDEXED0:
if (tag(top-3) != T_ARRAY)
{
lua_reportbug ("indexed expression not a table");
return 1;
}
{
Object *h = lua_hashdefine (avalue(top-3), top-2);
if (h == NULL) return 1;
*h = *(top-1);
}
top -= 3;
break;
case STOREINDEXED:
{
int n = *pc++;
if (tag(top-3-n) != T_ARRAY)
{
lua_reportbug ("indexed expression not a table");
return 1;
}
{
Object *h = lua_hashdefine (avalue(top-3-n), top-2-n);
if (h == NULL) return 1;
*h = *(top-1);
}
top--;
}
break;
case STORELIST0:
case STORELIST:
{
int m, n;
Object *arr;
if (opcode == STORELIST0) m = 0;
else m = *(pc++) * FIELDS_PER_FLUSH;
n = *(pc++);
arr = top-n-1;
if (tag(arr) != T_ARRAY)
{
lua_reportbug ("internal error - table expected");
return 1;
}
while (n)
{
tag(top) = T_NUMBER; nvalue(top) = n+m;
*(lua_hashdefine (avalue(arr), top)) = *(top-1);
top--;
n--;
}
}
break;
case STORERECORD:
{
int n = *(pc++);
Object *arr = top-n-1;
if (tag(arr) != T_ARRAY)
{
lua_reportbug ("internal error - table expected");
return 1;
}
while (n)
{
CodeWord code;
get_word(code,pc);
tag(top) = T_STRING; svalue(top) = lua_constant[code.w];
*(lua_hashdefine (avalue(arr), top)) = *(top-1);
top--;
n--;
}
}
break;
case ADJUST:
{
Object *newtop = base + *(pc++);
while (top
}
break;
case CREATEARRAY:
if (tag(top-1) == T_NIL)
nvalue(top-1) = 101;
else
{
if (tonumber(top-1)) return 1;
if (nvalue(top-1) <= 0) nvalue(top-1) = 101;
}
avalue(top-1) = lua_createarray(nvalue(top-1));
if (avalue(top-1) == NULL)
return 1;
tag(top-1) = T_ARRAY;
break;
case EQOP:
{
Object *l = top-2;
Object *r = top-1;
--top;
if (tag(l) != tag(r))
tag(top-1) = T_NIL;
else
{
switch (tag(l))
{
case T_NIL: tag(top-1) = T_NUMBER; break;
case T_NUMBER: tag(top-1) = (nvalue(l) == nvalue(r)) ? T_NUMBER : T_NIL; break;
case T_ARRAY: tag(top-1) = (avalue(l) == avalue(r)) ? T_NUMBER : T_NIL; break;
case T_FUNCTION: tag(top-1) = (bvalue(l) == bvalue(r)) ? T_NUMBER : T_NIL; break;
case T_CFUNCTION: tag(top-1) = (fvalue(l) == fvalue(r)) ? T_NUMBER : T_NIL; break;
case T_USERDATA: tag(top-1) = (uvalue(l) == uvalue(r)) ? T_NUMBER : T_NIL; break;
case T_STRING: tag(top-1) = (strcmp (svalue(l), svalue(r)) == 0) ? T_NUMBER : T_NIL; break;
case T_MARK: return 1;
}
}
nvalue(top-1) = 1;
}
break;
case LTOP:
{
Object *l = top-2;
Object *r = top-1;
--top;
if (tag(l) == T_NUMBER && tag(r) == T_NUMBER)
tag(top-1) = (nvalue(l)
{
if (tostring(l) || tostring(r))
return 1;
tag(top-1) = (strcmp (svalue(l), svalue(r)) <0) ? T_NUMBER : T_NIL;
}
nvalue(top-1) = 1;
}
break;
case LEOP:
{
Object *l = top-2;
Object *r = top-1;
--top;
if (tag(l) == T_NUMBER && tag(r) == T_NUMBER)
tag(top-1) = (nvalue(l) <= nvalue(r)) ? T_NUMBER : T_NIL;
else
{
if (tostring(l) || tostring(r))
return 1;
tag(top-1) = (strcmp (svalue(l), svalue(r)) <= 0) ? T_NUMBER : T_NIL;
}
nvalue(top-1) = 1;
}
break;
case ADDOP:
{
Object *l = top-2;
Object *r = top-1;
if (tonumber(r) || tonumber(l))
return 1;
nvalue(l) += nvalue(r);
--top;
}
break;
case SUBOP:
{
Object *l = top-2;
Object *r = top-1;
if (tonumber(r) || tonumber(l))
return 1;
nvalue(l) -= nvalue(r);
--top;
}
break;
case MULTOP:
{
Object *l = top-2;
Object *r = top-1;
if (tonumber(r) || tonumber(l))
return 1;
nvalue(l) *= nvalue(r);
--top;
}
break;
case DIVOP:
{
Object *l = top-2;
Object *r = top-1;
if (tonumber(r) || tonumber(l))
return 1;
nvalue(l) /= nvalue(r);
--top;
}
break;
case CONCOP:
{
Object *l = top-2;
Object *r = top-1;
if (tostring(r) || tostring(l))
return 1;
svalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r)));
if (svalue(l) == NULL)
return 1;
--top;
}
break;
case MINUSOP:
if (tonumber(top-1))
return 1;
nvalue(top-1) = - nvalue(top-1);
break;
case NOTOP:
tag(top-1) = tag(top-1) == T_NIL ? T_NUMBER : T_NIL;
break;
case ONTJMP:
{
CodeWord code;
get_word(code,pc);
if (tag(top-1) != T_NIL) pc += code.w;
}
break;
case ONFJMP:
{
CodeWord code;
get_word(code,pc);
if (tag(top-1) == T_NIL) pc += code.w;
}
break;
case JMP:
{
CodeWord code;
get_word(code,pc);
pc += code.w;
}
break;
case UPJMP:
{
CodeWord code;
get_word(code,pc);
pc -= code.w;
}
break;
case IFFJMP:
{
CodeWord code;
get_word(code,pc);
top--;
if (tag(top) == T_NIL) pc += code.w;
}
break;
case IFFUPJMP:
{
CodeWord code;
get_word(code,pc);
top--;
if (tag(top) == T_NIL) pc -= code.w;
}
break;
case POP: --top; break;
case CALLFUNC:
{
Byte *newpc;
Object *b = top-1;
while (tag(b) != T_MARK) b--;
if (tag(b-1) == T_FUNCTION)
{
lua_debugline = 0; /* always reset debug flag */
newpc = bvalue(b-1);
bvalue(b-1) = pc; /* store return code */
nvalue(b) = (base-stack); /* store base value */
base = b+1;
pc = newpc;
if (MAXSTACK-(base-stack)
lua_error ("stack overflow");
return 1;
}
}
else if (tag(b-1) == T_CFUNCTION)
{
int nparam;
lua_debugline = 0; /* always reset debug flag */
nvalue(b) = (base-stack); /* store base value */
base = b+1;
nparam = top-base; /* number of parameters */
(fvalue(b-1))(); /* call C function */
/* shift returned values */
{
int i;
int nretval = top - base - nparam;
top = base - 2;
base = stack + (int) nvalue(base-1);
for (i=0; i
*top = *(top+nparam+2);
++top;
}
}
}
else
{
lua_reportbug ("call expression not a function");
return 1;
}
}
break;
case RETCODE:
{
int i;
int shift = *pc++;
int nretval = top - base - shift;
top = base - 2;
pc = bvalue(base-2);
base = stack + (int) nvalue(base-1);
for (i=0; i
*top = *(top+shift+2);
++top;
}
}
break;
case HALT:
base = oldbase;
return 0; /* success */
case SETFUNCTION:
{
CodeWord file, func;
get_word(file,pc);
get_word(func,pc);
if (lua_pushfunction (file.w, func.w))
return 1;
}
break;
case SETLINE:
{
CodeWord code;
get_word(code,pc);
lua_debugline = code.w;
}
break;
case RESET:
lua_popfunction ();
break;
default:
lua_error ("internal error - opcode didn't match");
return 1;
}
}
}