先看table.insert调用的C函数:
static int tinsert (lua_State *L) { int e = aux_getn(L, 1) + 1; /* first empty element */ int pos; /* where to insert new element */ switch (lua_gettop(L)) { case 2: { /* called with only 2 arguments */ pos = e; /* insert new element at the end */ break; } case 3: { int i; pos = luaL_checkint(L, 2); /* 2nd argument is the position */ luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); for (i = e; i > pos; i--) { /* move up elements */ lua_rawgeti(L, 1, i-1); lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ } break; } default: { return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); } } lua_rawseti(L, 1, pos); /* t[pos] = v */ return 0; }
LUA_API void lua_rawseti (lua_State *L, int idx, int n) { StkId t; lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); api_check(L, ttistable(t), "table expected"); luaH_setint(L, hvalue(t), n, L->top - 1); luaC_barrierback(L, gcvalue(t), L->top-1); L->top--; lua_unlock(L); }最终调用luaH_setint函数:
void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { const TValue *p = luaH_getint(t, key); TValue *cell; if (p != luaO_nilobject) cell = cast(TValue *, p); else { TValue k; setnvalue(&k, cast_num(key)); cell = luaH_newkey(L, t, &k); } setobj2t(L, cell, value); }此孙数key为table.insert要插入的pos,就是int e = aux_getn(L, 1) + 1的e,value就是要插入的值,看luaH_getint:
/* ** search function for integers */ const TValue *luaH_getint (Table *t, int key) { /* (1 <= key && key <= t->sizearray) */ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) return &t->array[key-1]; else { lua_Number nk = cast_num(key); Node *n = hashnum(t, nk); do { /* check whether `key' is somewhere in the chain */ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) return gval(n); /* that's it */ else n = gnext(n); } while (n); return luaO_nilobject; } }从此函数的注释可以知道,就是查找一个整形key是否存在(包括数组和hash).假如此key存在,刚赋值,不存在,刚新newkey,看luaH_newkey函数:
TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { Node *mp; if (ttisnil(key)) luaG_runerror(L, "table index is nil"); else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) luaG_runerror(L, "table index is NaN"); mp = mainposition(t, key); if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; Node *n = getfreepos(t); /* get a free place */ if (n == NULL) { /* cannot find a free place? */ rehash(L, t, key); /* grow table */ /* whatever called 'newkey' take care of TM cache and GC barrier */ return luaH_set(L, t, key); /* insert key into grown table */ } lua_assert(!isdummy(n)); othern = mainposition(t, gkey(mp)); if (othern != mp) { /* is colliding node out of its main position? */ /* 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)); } else { /* colliding node is in its own main position */ /* new node will go into free position */ gnext(n) = gnext(mp); /* chain new position */ gnext(mp) = n; mp = n; } } setobj2t(L, gkey(mp), key); luaC_barrierback(L, obj2gco(t), key); lua_assert(ttisnil(gval(mp))); return gval(mp); }此函数就是把刚才要插入的key放到hash部分,如果hash已满刚rehash(rehash函数有点复杂,有空再写),到这里,就知道table.insert的值有可能进入到hash,这就是为什么
再讲一点,table的构告是由指令OP_NEWTABLE执行,初始化数组操作是由OP_SETLIST执行(赋值时元素个数是由语法解析生成的),key value赋值是由OP_SETTABLE执行再加上table.insert和table.remove这两 个函数就组成了table所有的外部操作了。
原文:http://blog.csdn.net/ball32109/article/details/44906001