上一文解析了token,本章我们来看执行
1. 一个简单的例子
local a = {1,2,3}
a[6] = 1
a["aaa"]= 1
2.解析出的token是什么
// 我们的例子
local a = {1,2,3}
a[6] = 1
a["aaa"]= 1
268(TK_LOCAL) -> 285(TK_NAME) -> 61('=') -> 123('{') -> 284(TK_NUMBER) -> 44(',') -> 284(TK_NUMBER) -> 44(',') -> 284(TK_NUMBER) -> 125('}')
285(TK_NAME) -> 91('[') -> 284(TK_NUMBER) -> 93(']') -> 61('=') -> 284(TK_NUMBER)
285(TK_NAME) -> 91('[') -> 286(TK_STRING) -> 93(']') -> 61('=') -> 284(TK_NUMBER)
3.执行的开始
static int handle_script(gafq_State *L, char **argv, int n)
{
...
status = docall(L, narg, 0); // 这边执行了文件好像
...
}
4.执行
void gafqD_call(gafq_State *L, StkId func, int nResults)
{
//好像如果是c方法gafqD_precall这里会执行, gafq方法就gafqV_execute执行
if (gafqD_precall(L, func, nResults) == PCRGAFQ)// 判断是gafq的函数还是c的函数
gafqV_execute(L, 1);
}
5.gafqV_execute
gvm.c
void gafqV_execute(gafq_State *L, int nexeccalls)
{
...
for (;;)
{
//取出当前指令 i = 25165834 // 00011000000 00000000000 001010 // 001010是十进制10,这个操作是创建一个新的table
const Instruction i = *pc++;
...
ra = RA(i); // 0x635420
switch (GET_OPCODE(i))
{
case OP_NEWTABLE:
{
int b = GETARG_B(i);
int c = GETARG_C(i);
sethvalue(L, ra, gafqH_new(L, gafqO_fb2int(b), gafqO_fb2int(c)));
Protect(gafqC_checkGC(L));
continue;
}
}
}
}
6.gafqV_execute 我们所有的指令i
gvm.c
const Instruction i = *pc++;
i = 25165834 OP_NEWTABLE
i = 65 OP_LOADK
i = 16513 OP_LOADK
i = 32961 OP_LOADK
i = 25182242 OP_SETLIST
i = 2176843785 OP_SETTABLE
i = 2185232393 OP_SETTABLE
i = 8388638 OP_RETURN
7. 初始化table
gtable.c
// 初始化table
Table *gafqH_new(gafq_State *L, int narray, int nhash)
{
Table *t = gafqM_new(L, Table);
gafqC_link(L, obj2gco(t), GAFQ_TTABLE);
t->metatable = NULL;
t->flags = cast_byte(~0);
/* temporary values (kept only if some malloc fails) */
t->array = NULL;
t->sizearray = 0;
t->lsizenode = 0;
t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray); // 初始化数组部分
setnodevector(L, t, nhash); // 初始化哈希部分
return t;
}
// 初始化数组部分, 我们的例子local a = {1,2,3}这里数组部分size是3
static void setarrayvector(gafq_State *L, Table *t, int size)
{
int i;
gafqM_reallocvector(L, t->array, t->sizearray, size, TValue);
for (i = t->sizearray; i < size; i++)
setnilvalue(&t->array[i]);
t->sizearray = size;
}
//我们的例子local a = {1,2,3}这里的size是0
static void setnodevector(gafq_State *L, Table *t, int size)
{
int lsize;
if (size == 0)
{ /* no elements to hash part? */
t->node = cast(Node *, dummynode); /* use common `dummynode' */
lsize = 0;
}
else
{ // 新建表有hash的时候的数据
...
}
t->lsizenode = cast_byte(lsize);
t->lastfree = gnode(t, size); /* all positions are free */
}
8.看OP_SETLIST操作,对应我们的local a = {1,2,3}
case OP_SETLIST:
{
int n = GETARG_B(i);
int c = GETARG_C(i);
int last;
Table *h;
if (n == 0)
{
n = cast_int(L->top - ra) - 1;
L->top = L->ci->top;
}
if (c == 0)
c = cast_int(*pc++);
runtime_check(L, ttistable(ra));
h = hvalue(ra); // ra放的是我们的table
last = ((c - 1) * LFIELDS_PER_FLUSH) + n;
if (last > h->sizearray) // 判断数组部分的空间够不够
gafqH_resizearray(L, h, last); // 重新弄一下数组部分的空间
for (; n > 0; n--)
{
TValue *val = ra + n;
setobj2t(L, gafqH_setnum(L, h, last--), val);
gafqC_barriert(L, h, val);
}
continue;
}
// 扩大数组部分的空间
void gafqH_resizearray(gafq_State *L, Table *t, int nasize)
{
int nsize = (t->node == dummynode) ? 0 : sizenode(t);
resize(L, t, nasize, nsize);
}
// 重新计算我们的table的大小
static void resize(gafq_State *L, Table *t, int nasize, int nhsize)
{
int i;
int oldasize = t->sizearray;
int oldhsize = t->lsizenode;
Node *nold = t->node; 原本的哈希表部分
if (nasize > oldasize) // 判断数组部分需要增加?
setarrayvector(L, t, nasize);
setnodevector(L, t, nhsize); // 增加哈希部分的空间
if (nasize < oldasize)
{ /* array part must shrink? */
t->sizearray = nasize;
/* re-insert elements from vanishing slice */
for (i = nasize; i < oldasize; i++)
{
if (!ttisnil(&t->array[i]))
setobjt2t(L, gafqH_setnum(L, t, i + 1), &t->array[i]);
}
/* shrink array */
gafqM_reallocvector(L, t->array, oldasize, nasize, TValue);
}
/* re-insert elements from hash part */
for (i = twoto(oldhsize) - 1; i >= 0; i--)
{
Node *old = nold + i;
if (!ttisnil(gval(old)))
setobjt2t(L, gafqH_set(L, t, key2tval(old)), gval(old));
}
if (nold != dummynode)
gafqM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
}
TValue *gafqH_setnum(gafq_State *L, Table *t, int key)
{
const TValue *p = gafqH_getnum(t, key);
if (p != gafqO_nilobject)
return cast(TValue *, p);
else
{
TValue k;
setnvalue(&k, cast_num(key));
return newkey(L, t, &k);
}
}
// 查找的数字
const TValue *gafqH_getnum(Table *t, int key)
{
// 如果查找的索引在array里面,那么是在数组里面,否则是在哈希表里面
if (cast(unsigned int, key - 1) < cast(unsigned int, t->sizearray))
return &t->array[key - 1];
else
{
gafq_Number nk = cast_num(key);
Node *n = hashnum(t, nk);
do
{ /* check whether `key' is somewhere in the chain */
if (ttisnumber(gkey(n)) && gafqi_numeq(nvalue(gkey(n)), nk))
return gval(n); /* that's it */
else
n = gnext(n);
} while (n);
return gafqO_nilobject;
}
}
9.看OP_SETTABLE操作
void gafqV_execute(gafq_State *L, int nexeccalls)
{
for (;;)
{
//取出当前指令
const Instruction i = *pc++;
...
switch (GET_OPCODE(i)){
...
case OP_SETTABLE:
{
//但操作的表不在 upvalue 中,而在寄存器里。它们在实现上的区别仅在于,前者b是对 upvalue 的索引,而后者则表示寄存器号。
Protect(gafqV_settable(L, ra, RKB(i), RKC(i)));
continue;
}
}
}
}
//对表结构写操作的封装,同样会引发元方法
void gafqV_settable(gafq_State *L, const TValue *t, TValue *key, StkId val)
{
int loop;
TValue temp;
for (loop = 0; loop < MAXTAGLOOP; loop++) // 避免元表死循环
{
const TValue *tm;
if (ttistable(t))
{ // 我们这里是个table
Table *h = hvalue(t);
TValue *oldval = gafqH_set(L, h, key);
if (!ttisnil(oldval) || (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL)
{ //没有元方法走这里
setobj2t(L, oldval, val);
h->flags = 0;
gafqC_barriert(L, h, val); // 处理垃圾回收
return;
}
/* else will try the tag method */
}
if (ttisfunction(tm))
{
// 有元方法走这里
callTM(L, tm, t, key, val);
return;
}
...
setobj(L, &temp, tm);
t = &temp;
}
gafqG_runerror(L, "loop in settable");
}