ltable.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $
00003 ** Lua tables (hash)
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 
00008 /*
00009 ** Implementation of tables (aka arrays, objects, or hash tables).
00010 ** Tables keep its elements in two parts: an array part and a hash part.
00011 ** Non-negative integer keys are all candidates to be kept in the array
00012 ** part. The actual size of the array is the largest `n' such that at
00013 ** least half the slots between 0 and n are in use.
00014 ** Hash uses a mix of chained scatter table with Brent's variation.
00015 ** A main invariant of these tables is that, if an element is not
00016 ** in its main position (i.e. the `original' position that its hash gives
00017 ** to it), then the colliding element is in its own main position.
00018 ** Hence even when the load factor reaches 100%, performance remains good.
00019 */
00020 
00021 #include <math.h>
00022 #include <string.h>
00023 
00024 #define ltable_c
00025 #define LUA_CORE
00026 
00027 #include "lua.h"
00028 
00029 #include "ldebug.h"
00030 #include "ldo.h"
00031 #include "lgc.h"
00032 #include "lmem.h"
00033 #include "lobject.h"
00034 #include "lstate.h"
00035 #include "ltable.h"
00036 
00037 
00038 /*
00039 ** max size of array part is 2^MAXBITS
00040 */
00041 #if LUAI_BITSINT > 26
00042 #define MAXBITS   26
00043 #else
00044 #define MAXBITS   (LUAI_BITSINT-2)
00045 #endif
00046 
00047 #define MAXASIZE  (1 << MAXBITS)
00048 
00049 
00050 #define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))
00051   
00052 #define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
00053 #define hashboolean(t,p)        hashpow2(t, p)
00054 
00055 
00056 /*
00057 ** for some types, it is better to avoid modulus by power of 2, as
00058 ** they tend to have many 2 factors.
00059 */
00060 #define hashmod(t,n)  (gnode(t, ((n) % ((sizenode(t)-1)|1))))
00061 
00062 
00063 #define hashpointer(t,p)  hashmod(t, IntPoint(p))
00064 
00065 
00066 /*
00067 ** number of ints inside a lua_Number
00068 */
00069 #define numints   cast_int(sizeof(lua_Number)/sizeof(int))
00070 
00071 
00072 
00073 #define dummynode   (&dummynode_)
00074 
00075 static const Node dummynode_ = {
00076   {{NULL}, LUA_TNIL},  /* value */
00077   {{{NULL}, LUA_TNIL, NULL}}  /* key */
00078 };
00079 
00080 
00081 /*
00082 ** hash for lua_Numbers
00083 */
00084 static Node *hashnum (const Table *t, lua_Number n) {
00085   unsigned int a[numints];
00086   int i;
00087   if (luai_numeq(n, 0))  /* avoid problems with -0 */
00088     return gnode(t, 0);
00089   memcpy(a, &n, sizeof(a));
00090   for (i = 1; i < numints; i++) a[0] += a[i];
00091   return hashmod(t, a[0]);
00092 }
00093 
00094 
00095 
00096 /*
00097 ** returns the `main' position of an element in a table (that is, the index
00098 ** of its hash value)
00099 */
00100 static Node *mainposition (const Table *t, const TValue *key) {
00101   switch (ttype(key)) {
00102     case LUA_TNUMBER:
00103       return hashnum(t, nvalue(key));
00104     case LUA_TSTRING:
00105       return hashstr(t, rawtsvalue(key));
00106     case LUA_TBOOLEAN:
00107       return hashboolean(t, bvalue(key));
00108     case LUA_TLIGHTUSERDATA:
00109       return hashpointer(t, pvalue(key));
00110     default:
00111       return hashpointer(t, gcvalue(key));
00112   }
00113 }
00114 
00115 
00116 /*
00117 ** returns the index for `key' if `key' is an appropriate key to live in
00118 ** the array part of the table, -1 otherwise.
00119 */
00120 static int arrayindex (const TValue *key) {
00121   if (ttisnumber(key)) {
00122     lua_Number n = nvalue(key);
00123     int k;
00124     lua_number2int(k, n);
00125     if (luai_numeq(cast_num(k), n))
00126       return k;
00127   }
00128   return -1;  /* `key' did not match some condition */
00129 }
00130 
00131 
00132 /*
00133 ** returns the index of a `key' for table traversals. First goes all
00134 ** elements in the array part, then elements in the hash part. The
00135 ** beginning of a traversal is signalled by -1.
00136 */
00137 static int findindex (lua_State *L, Table *t, StkId key) {
00138   int i;
00139   if (ttisnil(key)) return -1;  /* first iteration */
00140   i = arrayindex(key);
00141   if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */
00142     return i-1;  /* yes; that's the index (corrected to C) */
00143   else {
00144     Node *n = mainposition(t, key);
00145     do {  /* check whether `key' is somewhere in the chain */
00146       /* key may be dead already, but it is ok to use it in `next' */
00147       if (luaO_rawequalObj(key2tval(n), key) ||
00148             (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
00149              gcvalue(gkey(n)) == gcvalue(key))) {
00150         i = cast_int(n - gnode(t, 0));  /* key index in hash table */
00151         /* hash elements are numbered after array ones */
00152         return i + t->sizearray;
00153       }
00154       else n = gnext(n);
00155     } while (n);
00156     luaG_runerror_1(L, "invalid key to " LUA_QL("next"));  /* key not found */
00157     return 0;  /* to avoid warnings */
00158   }
00159 }
00160 
00161 
00162 int luaH_next (lua_State *L, Table *t, StkId key) {
00163   int i = findindex(L, t, key);  /* find original element */
00164   for (i++; i < t->sizearray; i++) {  /* try first array part */
00165     if (!ttisnil(&t->array[i])) {  /* a non-nil value? */
00166       setnvalue(key, cast_num(i+1));
00167       setobj2s(L, key+1, &t->array[i]);
00168       return 1;
00169     }
00170   }
00171   for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */
00172     if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */
00173       setobj2s(L, key, key2tval(gnode(t, i)));
00174       setobj2s(L, key+1, gval(gnode(t, i)));
00175       return 1;
00176     }
00177   }
00178   return 0;  /* no more elements */
00179 }
00180 
00181 
00182 /*
00183 ** {=============================================================
00184 ** Rehash
00185 ** ==============================================================
00186 */
00187 
00188 
00189 static int computesizes (int nums[], int *narray) {
00190   int i;
00191   int twotoi;  /* 2^i */
00192   int a = 0;  /* number of elements smaller than 2^i */
00193   int na = 0;  /* number of elements to go to array part */
00194   int n = 0;  /* optimal size for array part */
00195   for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
00196     if (nums[i] > 0) {
00197       a += nums[i];
00198       if (a > twotoi/2) {  /* more than half elements present? */
00199         n = twotoi;  /* optimal size (till now) */
00200         na = a;  /* all elements smaller than n will go to array part */
00201       }
00202     }
00203     if (a == *narray) break;  /* all elements already counted */
00204   }
00205   *narray = n;
00206   lua_assert(*narray/2 <= na && na <= *narray);
00207   return na;
00208 }
00209 
00210 
00211 static int countint (const TValue *key, int *nums) {
00212   int k = arrayindex(key);
00213   if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */
00214     nums[ceillog2(k)]++;  /* count as such */
00215     return 1;
00216   }
00217   else
00218     return 0;
00219 }
00220 
00221 
00222 static int numusearray (const Table *t, int *nums) {
00223   int lg;
00224   int ttlg;  /* 2^lg */
00225   int ause = 0;  /* summation of `nums' */
00226   int i = 1;  /* count to traverse all array keys */
00227   for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */
00228     int lc = 0;  /* counter */
00229     int lim = ttlg;
00230     if (lim > t->sizearray) {
00231       lim = t->sizearray;  /* adjust upper limit */
00232       if (i > lim)
00233         break;  /* no more elements to count */
00234     }
00235     /* count elements in range (2^(lg-1), 2^lg] */
00236     for (; i <= lim; i++) {
00237       if (!ttisnil(&t->array[i-1]))
00238         lc++;
00239     }
00240     nums[lg] += lc;
00241     ause += lc;
00242   }
00243   return ause;
00244 }
00245 
00246 
00247 static int numusehash (const Table *t, int *nums, int *pnasize) {
00248   int totaluse = 0;  /* total number of elements */
00249   int ause = 0;  /* summation of `nums' */
00250   int i = sizenode(t);
00251   while (i--) {
00252     Node *n = &t->node[i];
00253     if (!ttisnil(gval(n))) {
00254       ause += countint(key2tval(n), nums);
00255       totaluse++;
00256     }
00257   }
00258   *pnasize += ause;
00259   return totaluse;
00260 }
00261 
00262 
00263 static void setarrayvector (lua_State *L, Table *t, int size) {
00264   int i;
00265   luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
00266   for (i=t->sizearray; i<size; i++)
00267      setnilvalue(&t->array[i]);
00268   t->sizearray = size;
00269 }
00270 
00271 
00272 static void setnodevector (lua_State *L, Table *t, int size) {
00273   int lsize;
00274   if (size == 0) {  /* no elements to hash part? */
00275     t->node = cast(Node *, dummynode);  /* use common `dummynode' */
00276     lsize = 0;
00277   }
00278   else {
00279     int i;
00280     lsize = ceillog2(size);
00281     if (lsize > MAXBITS)
00282       luaG_runerror_1(L, "table overflow");
00283     size = twoto(lsize);
00284     t->node = luaM_newvector(L, size, Node);
00285     for (i=0; i<size; i++) {
00286       Node *n = gnode(t, i);
00287       gnext(n) = NULL;
00288       setnilvalue(gkey(n));
00289       setnilvalue(gval(n));
00290     }
00291   }
00292   t->lsizenode = cast_byte(lsize);
00293   t->lastfree = gnode(t, size);  /* all positions are free */
00294 }
00295 
00296 
00297 static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
00298   int i;
00299   int oldasize = t->sizearray;
00300   int oldhsize = t->lsizenode;
00301   Node *nold = t->node;  /* save old hash ... */
00302   if (nasize > oldasize)  /* array part must grow? */
00303     setarrayvector(L, t, nasize);
00304   /* create new hash part with appropriate size */
00305   setnodevector(L, t, nhsize);  
00306   if (nasize < oldasize) {  /* array part must shrink? */
00307     t->sizearray = nasize;
00308     /* re-insert elements from vanishing slice */
00309     for (i=nasize; i<oldasize; i++) {
00310       if (!ttisnil(&t->array[i]))
00311         setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
00312     }
00313     /* shrink array */
00314     luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
00315   }
00316   /* re-insert elements from hash part */
00317   for (i = twoto(oldhsize) - 1; i >= 0; i--) {
00318     Node *old = nold+i;
00319     if (!ttisnil(gval(old)))
00320       setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
00321   }
00322   if (nold != dummynode)
00323     luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
00324 }
00325 
00326 
00327 void luaH_resizearray (lua_State *L, Table *t, int nasize) {
00328   int nsize = (t->node == dummynode) ? 0 : sizenode(t);
00329   resize(L, t, nasize, nsize);
00330 }
00331 
00332 
00333 static void rehash (lua_State *L, Table *t, const TValue *ek) {
00334   int nasize, na;
00335   int nums[MAXBITS+1];  /* nums[i] = number of keys between 2^(i-1) and 2^i */
00336   int i;
00337   int totaluse;
00338   for (i=0; i<=MAXBITS; i++) nums[i] = 0;  /* reset counts */
00339   nasize = numusearray(t, nums);  /* count keys in array part */
00340   totaluse = nasize;  /* all those keys are integer keys */
00341   totaluse += numusehash(t, nums, &nasize);  /* count keys in hash part */
00342   /* count extra key */
00343   nasize += countint(ek, nums);
00344   totaluse++;
00345   /* compute new size for array part */
00346   na = computesizes(nums, &nasize);
00347   /* resize the table to new computed sizes */
00348   resize(L, t, nasize, totaluse - na);
00349 }
00350 
00351 
00352 
00353 /*
00354 ** }=============================================================
00355 */
00356 
00357 
00358 Table *luaH_new (lua_State *L, int narray, int nhash) {
00359   Table *t = luaM_new(L, Table);
00360   luaC_link(L, obj2gco(t), LUA_TTABLE);
00361   t->metatable = NULL;
00362   t->flags = cast_byte(~0);
00363   /* temporary values (kept only if some malloc fails) */
00364   t->array = NULL;
00365   t->sizearray = 0;
00366   t->lsizenode = 0;
00367   t->node = cast(Node *, dummynode);
00368   setarrayvector(L, t, narray);
00369   setnodevector(L, t, nhash);
00370   return t;
00371 }
00372 
00373 
00374 void luaH_free (lua_State *L, Table *t) {
00375   if (t->node != dummynode)
00376     luaM_freearray(L, t->node, sizenode(t), Node);
00377   luaM_freearray(L, t->array, t->sizearray, TValue);
00378   luaM_free(L, t);
00379 }
00380 
00381 
00382 static Node *getfreepos (Table *t) {
00383   while (t->lastfree-- > t->node) {
00384     if (ttisnil(gkey(t->lastfree)))
00385       return t->lastfree;
00386   }
00387   return NULL;  /* could not find a free place */
00388 }
00389 
00390 
00391 
00392 /*
00393 ** inserts a new key into a hash table; first, check whether key's main 
00394 ** position is free. If not, check whether colliding node is in its main 
00395 ** position or not: if it is not, move colliding node to an empty place and 
00396 ** put new key in its main position; otherwise (colliding node is in its main 
00397 ** position), new key goes to an empty position. 
00398 */
00399 static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
00400   Node *mp = mainposition(t, key);
00401   if (!ttisnil(gval(mp)) || mp == dummynode) {
00402     Node *othern;
00403     Node *n = getfreepos(t);  /* get a free place */
00404     if (n == NULL) {  /* cannot find a free place? */
00405       rehash(L, t, key);  /* grow table */
00406       return luaH_set(L, t, key);  /* re-insert key into grown table */
00407     }
00408     lua_assert(n != dummynode);
00409     othern = mainposition(t, key2tval(mp));
00410     if (othern != mp) {  /* is colliding node out of its main position? */
00411       /* yes; move colliding node into free position */
00412       while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */
00413       gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */
00414       *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */
00415       gnext(mp) = NULL;  /* now `mp' is free */
00416       setnilvalue(gval(mp));
00417     }
00418     else {  /* colliding node is in its own main position */
00419       /* new node will go into free position */
00420       gnext(n) = gnext(mp);  /* chain new position */
00421       gnext(mp) = n;
00422       mp = n;
00423     }
00424   }
00425   gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
00426   luaC_barriert(L, t, key);
00427   lua_assert(ttisnil(gval(mp)));
00428   return gval(mp);
00429 }
00430 
00431 
00432 /*
00433 ** search function for integers
00434 */
00435 const TValue *luaH_getnum (Table *t, int key) {
00436   /* (1 <= key && key <= t->sizearray) */
00437   if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
00438     return &t->array[key-1];
00439   else {
00440     lua_Number nk = cast_num(key);
00441     Node *n = hashnum(t, nk);
00442     do {  /* check whether `key' is somewhere in the chain */
00443       if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
00444         return gval(n);  /* that's it */
00445       else n = gnext(n);
00446     } while (n);
00447     return luaO_nilobject;
00448   }
00449 }
00450 
00451 
00452 /*
00453 ** search function for strings
00454 */
00455 const TValue *luaH_getstr (Table *t, TString *key) {
00456   Node *n = hashstr(t, key);
00457   do {  /* check whether `key' is somewhere in the chain */
00458     if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
00459       return gval(n);  /* that's it */
00460     else n = gnext(n);
00461   } while (n);
00462   return luaO_nilobject;
00463 }
00464 
00465 
00466 /*
00467 ** main search function
00468 */
00469 const TValue *luaH_get (Table *t, const TValue *key) {
00470   switch (ttype(key)) {
00471     case LUA_TNIL: return luaO_nilobject;
00472     case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
00473     case LUA_TNUMBER: {
00474       int k;
00475       lua_Number n = nvalue(key);
00476       lua_number2int(k, n);
00477       if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
00478         return luaH_getnum(t, k);  /* use specialized version */
00479       /* else go through */
00480     }
00481     default: {
00482       Node *n = mainposition(t, key);
00483       do {  /* check whether `key' is somewhere in the chain */
00484         if (luaO_rawequalObj(key2tval(n), key))
00485           return gval(n);  /* that's it */
00486         else n = gnext(n);
00487       } while (n);
00488       return luaO_nilobject;
00489     }
00490   }
00491 }
00492 
00493 
00494 TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
00495   const TValue *p = luaH_get(t, key);
00496   t->flags = 0;
00497   if (p != luaO_nilobject)
00498     return cast(TValue *, p);
00499   else {
00500     if (ttisnil(key)) luaG_runerror_1(L, "table index is nil");
00501     else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
00502       luaG_runerror_1(L, "table index is NaN");
00503     return newkey(L, t, key);
00504   }
00505 }
00506 
00507 
00508 TValue *luaH_setnum (lua_State *L, Table *t, int key) {
00509   const TValue *p = luaH_getnum(t, key);
00510   if (p != luaO_nilobject)
00511     return cast(TValue *, p);
00512   else {
00513     TValue k;
00514     setnvalue(&k, cast_num(key));
00515     return newkey(L, t, &k);
00516   }
00517 }
00518 
00519 
00520 TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
00521   const TValue *p = luaH_getstr(t, key);
00522   if (p != luaO_nilobject)
00523     return cast(TValue *, p);
00524   else {
00525     TValue k;
00526     setsvalue(L, &k, key);
00527     return newkey(L, t, &k);
00528   }
00529 }
00530 
00531 
00532 static int unbound_search (Table *t, unsigned int j) {
00533   unsigned int i = j;  /* i is zero or a present index */
00534   j++;
00535   /* find `i' and `j' such that i is present and j is not */
00536   while (!ttisnil(luaH_getnum(t, j))) {
00537     i = j;
00538     j *= 2;
00539     if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */
00540       /* table was built with bad purposes: resort to linear search */
00541       i = 1;
00542       while (!ttisnil(luaH_getnum(t, i))) i++;
00543       return i - 1;
00544     }
00545   }
00546   /* now do a binary search between them */
00547   while (j - i > 1) {
00548     unsigned int m = (i+j)/2;
00549     if (ttisnil(luaH_getnum(t, m))) j = m;
00550     else i = m;
00551   }
00552   return i;
00553 }
00554 
00555 
00556 /*
00557 ** Try to find a boundary in table `t'. A `boundary' is an integer index
00558 ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
00559 */
00560 int luaH_getn (Table *t) {
00561   unsigned int j = t->sizearray;
00562   if (j > 0 && ttisnil(&t->array[j - 1])) {
00563     /* there is a boundary in the array part: (binary) search for it */
00564     unsigned int i = 0;
00565     while (j - i > 1) {
00566       unsigned int m = (i+j)/2;
00567       if (ttisnil(&t->array[m - 1])) j = m;
00568       else i = m;
00569     }
00570     return i;
00571   }
00572   /* else must find a boundary in hash part */
00573   else if (t->node == dummynode)  /* hash part is empty? */
00574     return j;  /* that is easy... */
00575   else return unbound_search(t, j);
00576 }
00577 
00578 
00579 
00580 #if defined(LUA_DEBUG)
00581 
00582 Node *luaH_mainposition (const Table *t, const TValue *key) {
00583   return mainposition(t, key);
00584 }
00585 
00586 int luaH_isdummy (Node *n) { return n == dummynode; }
00587 
00588 #endif

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1