Lua5.1 源码注释(一) table.c

来源:互联网 发布:虚拟机centos安装教程 编辑:程序博客网 时间:2024/06/05 17:27
从今天起,我要注释完lua 的所有源码,现在发布第一篇,我要坚持,坚持,坚持完成这个注释工作,哈哈。  

本来第一篇打算一周内就可以完成的,妈蛋,注释了一个月才完成。

现在,发布第一个文件,table.c,

/*** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $** Lua tables (hash)** See Copyright Notice in lua.h*//*** Implementation of tables (aka arrays, objects, or hash tables).** Tables keep its elements in two parts: an array part and a hash part.** Non-negative integer keys are all candidates to be kept in the array** part. The actual size of the array is the largest `n' such that at** least half the slots between 0 and n are in use.** Hash uses a mix of chained scatter table with Brent's variation.** A main invariant of these tables is that, if an element is not** in its main position (i.e. the `original' position that its hash gives** to it), then the colliding element is in its own main position.** Hence even when the load factor reaches 100%, performance remains good.*/#include <math.h>#include <string.h>#define ltable_c#define LUA_CORE#include "lua.h"#include "ldebug.h"#include "ldo.h"#include "lgc.h"#include "lmem.h"#include "lobject.h"#include "lstate.h"#include "ltable.h"/*** max size of array part is 2^MAXBITS*/#if LUAI_BITSINT > 26#define MAXBITS26#else#define MAXBITS(LUAI_BITSINT-2)#endif#define MAXASIZE(1 << MAXBITS)#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))  #define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)#define hashboolean(t,p)        hashpow2(t, p)/*** for some types, it is better to avoid modulus by power of 2, as** they tend to have many 2 factors.*/#define hashmod(t,n)(gnode(t, ((n) % ((sizenode(t)-1)|1))))//n对sizenode取模#define hashpointer(t,p)hashmod(t, IntPoint(p))/*** number of ints inside a lua_Number*/#define numintscast_int(sizeof(lua_Number)/sizeof(int))#define dummynode(&dummynode_)static const Node dummynode_ = { //这是一个静态的空node,key是空的,value也是空的,用来表示所有没有被分配空间的table  {{NULL}, LUA_TNIL},  /* value */  {{{NULL}, LUA_TNIL, NULL}}  /* key */};/*** hash for lua_Numbers*/static Node *hashnum (const Table *t, lua_Number n) { //这个函数找出数字n的hash node,lua_Number事实上是double  unsigned int a[numints];//numints  通常是4  int i;  if (luai_numeq(n, 0))  /* avoid problems with -0 */ //这里是和    return gnode(t, 0);//假如是0的话,直接返回hash node的第一个  memcpy(a, &n, sizeof(a));//字节复制n的数据到a上面  for (i = 1; i < numints; i++) a[0] += a[i];//所谓hash,其实就是一字节一字节加起来放到a[0],这种做法的hash分布可能不太理想,不过效率较快  return hashmod(t, a[0]);//a[0]就是hash值,返回这个hash节点的node}/*** returns the `main' position of an element in a table (that is, the index** of its hash value)*/static Node *mainposition (const Table *t, const TValue *key) {  switch (ttype(key)) {//找出key的类型    case LUA_TNUMBER:      return hashnum(t, nvalue(key));//是number hash     case LUA_TSTRING:      return hashstr(t, rawtsvalue(key));//string hash    case LUA_TBOOLEAN:      return hashboolean(t, bvalue(key));//布尔hash    case LUA_TLIGHTUSERDATA:      return hashpointer(t, pvalue(key));//指针hash    default:      return hashpointer(t, gcvalue(key));//默认的也是指针hash  }}/*** returns the index for `key' if `key' is an appropriate key to live in** the array part of the table, -1 otherwise.*/static int arrayindex (const TValue *key) {//候如key值可以放在 table的数值部分的话,就返回key的下标,否则返回-1  if (ttisnumber(key)) {//首先,key必须是number    lua_Number n = nvalue(key);//获得number的实际数值    int k;    lua_number2int(k, n);//将这个number转换成int,并且赋值给k    if (luai_numeq(cast_num(k), n))//假如转换后的k和原值是一样的,说明没有精度损失,n本身就是uint,返回它即可      return k;  }  return -1;  /* `key' did not match some condition */ }/*** returns the index of a `key' for table traversals. First goes all** elements in the array part, then elements in the hash part. The** beginning of a traversal is signalled by -1.*///遍历table,返回key对应的下标,首先遍历数组部分,然后遍历hash部分,-1表示遍历开始static int findindex (lua_State *L, Table *t, StkId key) {   int i;  if (ttisnil(key)) return -1;  /* first iteration */ //key是一个空值的话,返回-1   i = arrayindex(key);//找出key在数组中的index,如果不存在,arrayindex是会返回-1的  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */    return i-1;  /* yes; that's the index (corrected to C) */ //如果key在数组中存在,则返回它在数组中的c数组下标  else {    Node *n = mainposition(t, key); //在数组中不存在,开始在hash中找 key对应的hash node N    do {  /* check whether `key' is somewhere in the chain */      /* key may be dead already, but it is ok to use it in `next' */      if (luaO_rawequalObj(key2tval(n), key) ||            (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&             gcvalue(gkey(n)) == gcvalue(key))) {//检查key值是不是在hash的链表中, key == n则说明它在hash表中,或者key已经被回收了, 那么检查一下xxxxx        i = cast_int(n - gnode(t, 0));  /* key index in hash table */ //        /* hash elements are numbered after array ones */        return i + t->sizearray;//i是hash node的位置,要加上数组的长度      }      else n = gnext(n);//找node指向的下个node    } while (n);    luaG_runerror(L, "invalid key to " LUA_QL("next"));  /* key not found */ //找不到这个key    return 0;  /* to avoid warnings */  }}int luaH_next (lua_State *L, Table *t, StkId key) { //找出key对应的下一个元素,并把它的值放在key里面  int i = findindex(L, t, key);  /* find original element */ //找出key在table中的索引  for (i++; i < t->sizearray; i++) {  /* try first array part */ //假如是在数组中    if (!ttisnil(&t->array[i])) {  /* a non-nil value? */ //遍历数组,一直找到下一个非空值为止      setnvalue(key, cast_num(i+1));//将key的值变成number,并赋i+1      setobj2s(L, key+1, &t->array[i]);//一是将array[i]的值赋给key+1指向的值      return 1;    }  }  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */  //候如前面没有找到,就从hash里面找,i重置    if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */ //找出hash 中的i对应的值,是否为空,如果不是      setobj2s(L, key, key2tval(gnode(t, i)));//将i对应该的hash node的键值放在 key里面      setobj2s(L, key+1, gval(gnode(t, i))); //将i对应该的 hash node的 value值放在key +1      return 1;    }  }  return 0;  /* no more elements */}/*** {=============================================================** Rehash** ==============================================================*/static int computesizes (int nums[], int *narray) { //计算size  //nums所有的值加起来得出的总值,和narray的值是一样大小的  int i;  int twotoi;  /* 2^i */  int a = 0;  /* number of elements smaller than 2^i */  int na = 0;  /* number of elements to go to array part */  int n = 0;  /* optimal size for array part */  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {    if (nums[i] > 0) {      a += nums[i];//a一直累加      if (a > twotoi/2) {  /* more than half elements present? */        n = twotoi;  /* optimal size (till now) */        na = a;  /* all elements smaller than n will go to array part */      }    }    if (a == *narray) break;  /* all elements already counted */ //直到a累加到上限,退出  }  *narray = n;  lua_assert(*narray/2 <= na && na <= *narray);//na的值应该大于narray的一半,小于narray,否则报错  return na;}static int countint (const TValue *key, int *nums) {//找出key在table中的索引,并将 nums下标为索引log2()的值自增1  int k = arrayindex(key);//找出key 在数组部分 的位置  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */    nums[ceillog2(k)]++;  /* count as such */  //取这个位置的log2    return 1;  }  else    return 0;}static int numusearray (const Table *t, int *nums) { //统计数组中的非空元素个数  int lg;  int ttlg;  /* 2^lg */  int ause = 0;  /* summation of `nums' */  int i = 1;  /* count to traverse all array keys */  for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */ //[1]={1-2},[2]={3-4},3={5-8},[4]={9-16},[5]={17-64)}...这样分组,从头到尾遍历非nil的元素,统计每个分组的个数,并返回总个数.    int lc = 0;  /* counter */    int lim = ttlg;    if (lim > t->sizearray) { //最后组不免2的n次幂时,以实现长度为准      lim = t->sizearray;  /* adjust upper limit */      if (i > lim)        break;  /* no more elements to count */ //上一轮已经没有数据了,开始新一轮时i>lim会退出    }    /* count elements in range (2^(lg-1), 2^lg] */    for (; i <= lim; i++) {//执行一轮统计,找出这一轮所有非空的元素      if (!ttisnil(&t->array[i-1]))        lc++;    }    nums[lg] += lc;    ause += lc;  }  return ause; //返回总数}static int numusehash (const Table *t, int *nums, int *pnasize) {  int totaluse = 0;  /* total number of elements */  int ause = 0;  /* summation of `nums' */  int i = sizenode(t);//找出hash的长度  while (i--) {    Node *n = &t->node[i];    if (!ttisnil(gval(n))) {      ause += countint(key2tval(n), nums);//找出key值所在的位置index,并将nums[log(index)]自加1,找到就返回1,找不到返回0      totaluse++;//总数加1    }  }  *pnasize += ause;//对应的数组总长度+1  return totaluse;//返回所有非空数量 }static void setarrayvector (lua_State *L, Table *t, int size) {//重新分配table的数组内存  int i;  luaM_reallocvector(L, t->array, t->sizearray, size, TValue);//释放旧的内存,然后分配新的内存,因为是数组部分,所以不担心内存回收的问题,直接都释放了,话说这个东西真的不进行数据复制的,会不会太狠了?  for (i=t->sizearray; i<size; i++)//为什么后面的数据要设置为nil,前面的就不管了?luaM_reallocvector好像真的没有内存复制啊     setnilvalue(&t->array[i]);//设置nil  t->sizearray = size;//设置size}static void setnodevector (lua_State *L, Table *t, int size) { //设置hash表  int lsize;  if (size == 0) {  /* no elements to hash part? */ //假如新的长度是0    t->node = cast(Node *, dummynode);  /* use common `dummynode' */ //则将node指向空值    lsize = 0;//size设置为0  }  else {    int i;    lsize = ceillog2(size); //否则,lsize=size的log2,并向上取整    if (lsize > MAXBITS) //超出了最大容量      luaG_runerror(L, "table overflow");//报错    size = twoto(lsize);//将size变成lsize的平方    t->node = luaM_newvector(L, size, Node);// 分配一个新的长度的node    for (i=0; i<size; i++) {//初始化node      Node *n = gnode(t, i);      gnext(n) = NULL;//next指针清空      setnilvalue(gkey(n));//key 清空      setnilvalue(gval(n));//value清空    }  }  t->lsizenode = cast_byte(lsize);//新的size  t->lastfree = gnode(t, size);  /* all positions are free */ //所有的node都是可用的}static void resize (lua_State *L, Table *t, int nasize, int nhsize) { //重新分配size,nasize新数组长度,nhsize新hash表长度  int i;  int oldasize = t->sizearray;//旧数组长度  int oldhsize = t->lsizenode;//旧hash长度  Node *nold = t->node;  /* save old hash ... * /   //保存旧的hash表数据  if (nasize > oldasize)  /* array part must grow? */    setarrayvector(L, t, nasize); //假如新的数组长度旧的数级长度长,则配置新的数组  /* create new hash part with appropriate size */  setnodevector(L, t, nhsize);  //分配新的hash表  if (nasize < oldasize) {  /* array part must shrink? */    t->sizearray = nasize;//假如旧的数组长长比新的数组长度短,则收缩    /* re-insert elements from vanishing slice */    for (i=nasize; i<oldasize; i++) {//将收缩后的数据根据下标放入到hash表中      if (!ttisnil(&t->array[i])) //假如数组数据非空        setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);//将数据放入到key=i+1的hash里面,为什么i+1?因为lua的下标比c的下标大1    }    /* shrink array */    luaM_reallocvector(L, t->array, oldasize, nasize, TValue);//收缩数组同存空间  }  /* re-insert elements from hash part */  for (i = twoto(oldhsize) - 1; i >= 0; i--) {//遍历hash数据    Node *old = nold+i;//找出node    if (!ttisnil(gval(old)))//如果node的value非空,则将数据复制到新的hash表中      setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));//复制旧值到新node中  }  if (nold != dummynode)//释放非空的旧hash表数据    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */}void luaH_resizearray (lua_State *L, Table *t, int nasize) {//重新分配数组数据  int nsize = (t->node == dummynode) ? 0 : sizenode(t);//hash表的长度,如果table是空的话,则设置为0,如果是非空的话,则设置为table的hash长度  resize(L, t, nasize, nsize);//重新分配空间}static void rehash (lua_State *L, Table *t, const TValue *ek) {//重新分配hash数据  int nasize, na;   int nums[MAXBITS+1];  /* nums[i] = number of keys between 2^(i-1) and 2^i */ //定义一个nusm数组,用来记录 2^(i-1) and 2^i 之间已经使用了的数据数量   int i;  int totaluse;  for (i=0; i<=MAXBITS; i++) nums[i] = 0;  /* reset counts */ //清空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 */ //计算hash中已经使用了的个数  /* count extra key */  nasize += countint(ek, nums); //计算额外的数据,ek假如可以放到array中的话,nums对应的位置+1,countint返回1,否则返回0  totaluse++;//totaluse无论ek可以放在数组还是hash,它都会加1  /* compute new size for array part */  na = computesizes(nums, &nasize); //计算新的数组的长度  /* resize the table to new computed sizes */  resize(L, t, nasize, totaluse - na); //重新分配空间,//为什么会这样重新分配?totaluse - na即是hash部分的长度是用已经分配了的长度来决定?}/*** }=============================================================*/Table *luaH_new (lua_State *L, int narray, int nhash) {//分配一个新的table  Table *t = luaM_new(L, Table);//首先,分配table的空间  luaC_link(L, obj2gco(t), LUA_TTABLE);//这是什么鬼?将table放入到gc里面吗?应该是的  t->metatable = NULL;//元表是空  t->flags = cast_byte(~0);//flags是1,即是使用中?  /* temporary values (kept only if some malloc fails) */  t->array = NULL;//数组指针是空  t->sizearray = 0;//数组长度是空  t->lsizenode = 0;//hash长度是空  t->node = cast(Node *, dummynode);//node指向空  setarrayvector(L, t, narray);//分配数组空间  setnodevector(L, t, nhash);//分配hash空间  return t;}void luaH_free (lua_State *L, Table *t) {//释放table的内存  if (t->node != dummynode)//假如node 表不是空    luaM_freearray(L, t->node, sizenode(t), Node); //释放node 表  luaM_freearray(L, t->array, t->sizearray, TValue);//释放数组表  luaM_free(L, t);//释放table占的内存}static Node *getfreepos (Table *t) {//找出一个空的node  while (t->lastfree-- > t->node) {//向前找,直到第一个为止    if (ttisnil(gkey(t->lastfree)))//假如当前的lastfree是空的话,      return t->lastfree;//则返回这个lastfree  }  return NULL;  /* could not find a free place */}/*** 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 ** position or not: if it is not, move colliding node to an empty place and ** put new key in its main position; otherwise (colliding node is in its main ** position), new key goes to an empty position. *//*插入一个新key到hash 表中,首先,检查key对应的main position是否是空的,如果不是,则检查冲突的node是不是main position,如果不是,就应该将冲突的node移到一个新的空位置,将新key放到main position。如果冲突的点就已经是main position,则将新key放到一个空白点*/static TValue *newkey (lua_State *L, Table *t, const TValue *key) {  Node *mp = mainposition(t, key);  if (!ttisnil(gval(mp)) || mp == dummynode) { //mp的值不是空或者mp是空    Node *othern;    Node *n = getfreepos(t);  /* get a free place */ //找出一个空点    if (n == NULL) {  /* cannot find a free place? *///假如找不到,即是没有空间了,要重新分配      rehash(L, t, key);  /* grow table */      return luaH_set(L, t, key);  /* re-insert key into grown table */ //然后返回新分配空间后的点    }    lua_assert(n != dummynode);    othern = mainposition(t, key2tval(mp));// 通常key2tval(mp)的值就是ke,这里面不用key,重新取一次    if (othern != mp) {  /* is colliding node out of its main position? */ //假如有mp.key取出来的值不等于mp,这就尴尬了,说明是冲突的点      /* yes; move colliding node into free position */      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */ //other-> ...->pre->mainposition,遍历,找出pre点      gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */ //将pre 点的next指针赋成n点      *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */ //将mp的数据放进n时面      gnext(mp) = NULL;  /* now `mp' is free */ //然后清空mp的next指针      setnilvalue(gval(mp));//再新空mp的值        else {  /* colliding node is in its own main position */  //假如冲突node本来就应该放在mp上面      /* new node will go into free position */      gnext(n) = gnext(mp);  /* chain new position */ // 那么,将n插入到mp->{n}->next 中间      gnext(mp) = n;      mp = n;//将mp赋成n    }  }  gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;//将mp的key值变成key的什,  luaC_barriert(L, t, key);//这是什么鬼,是用来做内存回收的吧  lua_assert(ttisnil(gval(mp)));//断言mp的值必须是空,如果非空,有问题啊  return gval(mp);//返回mp node的value}/*** search function for integers*/const TValue *luaH_getnum (Table *t, int key) {//获取key为数值的node的value  /* (1 <= key && key <= t->sizearray) */  if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) //假如key小于数组的长度,直接返回数组的数据     return &t->array[key-1];  else {    lua_Number nk = cast_num(key);//否则,查找hash里面的数据    Node *n = hashnum(t, nk); //找出hash node    do {  /* check whether `key' is somewhere in the chain */      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) //假如node n的key是数值,并且这个数值和nk相等的话        return gval(n);  /* that's it */ //返回 node的value,      else n = gnext(n);//否则,查找下一个    } while (n);//直到下一个是空为止    return luaO_nilobject;//返回空  }}/*** search function for strings*/const TValue *luaH_getstr (Table *t, TString *key) {//返回key为字付串的node的value  Node *n = hashstr(t, key); //将key转换成hash值,并且访问表中对应的 node  do {  /* check whether `key' is somewhere in the chain */    if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)//假如这个node的key是string,并且和参数key相等,则返回node的值      return gval(n);  /* that's it */ //就是它了    else n = gnext(n); //如果不是,则找node的下一个,继续对比  } while (n);  return luaO_nilobject;//找不到,返回nil}/*** main search function*/const TValue *luaH_get (Table *t, const TValue *key) { //找出key在table中的value  switch (ttype(key)) {    case LUA_TNIL: return luaO_nilobject; //空key,返回空值    case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));//字符串的key,找hash    case LUA_TNUMBER: {//数值key      int k;      lua_Number n = nvalue(key); //找出key的double值      lua_number2int(k, n);//转成int      if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ //假如double和int值是一样的        return luaH_getnum(t, k);  /* use specialized version */ //luaH_getnum先从array里面查找,如果找不到,就从hash里面查找      /* else go through */    }    default: {      Node *n = mainposition(t, key);//其它的默认情况,先从hash中找出main postion      do {  /* check whether `key' is somewhere in the chain */        if (luaO_rawequalObj(key2tval(n), key))// //然后对比main position和key值是否相等          return gval(n);  /* that's it */ //假如相等则返回,        else n = gnext(n);//假如不等,则通过main position 的next指针找下一个      } while (n);//一直找到空的为止      return luaO_nilobject;// 最后找不到的就返回空    }  }}TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { //设置table key,返回一个Tvalue的指针  const TValue *p = luaH_get(t, key);//找出key对应的Tvalue  t->flags = 0; //这是什么鬼?加锁吗?  if (p != luaO_nilobject) //假如p不等于nil,    return cast(TValue *, p);//将p转换成TValue指针,为嘛要转换?前面不用const不就可以了  else {    if (ttisnil(key)) luaG_runerror(L, "table index is nil"); //假如P是nil,则检查key,如果key是nil,则报错    else if (ttisnumber(key) && luai_numisnan(nvalue(key)))//如果key是数值,并且是nan,同样报错.      luaG_runerror(L, "table index is NaN");    return newkey(L, t, key);//否则,插入一个新key  }}TValue *luaH_setnum (lua_State *L, Table *t, int key) { //设置key是数值的value,返回value的指针,这样就可以通过修改指针改值  const TValue *p = luaH_getnum(t, key);//找出key对应的value  if (p != luaO_nilobject)//假如是空,则    return cast(TValue *, p);//则直接返回tvalue指针  else {    TValue k;    setnvalue(&k, cast_num(key));//否则,将k转成Tvalue,    return newkey(L, t, &k);//然后插入新node,返回node的value  }}TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {//设置key是string的value  const TValue *p = luaH_getstr(t, key);//获得value  if (p != luaO_nilobject)//假如非空    return cast(TValue *, p);//则直接返回tvalue指针  else {//假如是空    TValue k;    setsvalue(L, &k, key);//生成一个新key    return newkey(L, t, &k);//插入node中  }}static int unbound_search (Table *t, unsigned int j) {  unsigned int i = j;  /* i is zero or a present index */ //先记录j坐标  j++; //j下一个元素  /* find `i' and `j' such that i is present and j is not */  while (!ttisnil(luaH_getnum(t, j))) {//j对应的元素不是nil的话,要继续找下去    i = j;//记录一下不是nil的j    j *= 2;//j double,晕,又是倍数增长    if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */ //2倍就超长啦,丧尽天良,回复到线性查找 吧      /* table was built with bad purposes: resort to linear search */      i = 1; //从1开始      while (!ttisnil(luaH_getnum(t, i))) i++;//      return i - 1;    }  }  /* now do a binary search between them */  while (j - i > 1) { //j在前面就已经2倍增长了,一直增长到luaH_getnum(t, j)为空时    unsigned int m = (i+j)/2;//折半查找    if (ttisnil(luaH_getnum(t, m))) j = m;//假如中间也是空,则j=m    else i = m;//假如中间不是空,则i=m  }  return i;}/*** 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).*/int luaH_getn (Table *t) { //找出table的边界i,这个i指t[i]是非空的,t[i+1]是空的  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 */    unsigned int i = 0;    while (j - i > 1) {      unsigned int m = (i+j)/2;//居然是用折半查找 的方法,汗      if (ttisnil(&t->array[m - 1])) j = m;//假如中间的是空,则从开始到中间之间找      else i = m;//否则从中间到最后之间找    }    return i;//当中间没有数值时  }  /* else must find a boundary in hash part */ //走到这里,前明前面的数组部分全是满的(其实就是数组最后一个值是非空的而已)  else if (t->node == dummynode)  /* hash part is empty? */ //假如hash部分就是空的话,直接返回数组长度    return j;  /* that is easy... */  else return unbound_search(t, j);//否则,开始调用unbound_search找出,unbound_search也是二分法查找hash 表部份}#if defined(LUA_DEBUG)Node *luaH_mainposition (const Table *t, const TValue *key) {// 返回key值对应的node,只是封装了一下mainposition  return mainposition(t, key);}int luaH_isdummy (Node *n) { return n == dummynode; }//判断这个node是不是假的#endif