上一文解析了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");
}

发表评论