소스 검색

use of a common `dummynode' for all empty tables

Roberto Ierusalimschy 23 년 전
부모
커밋
383e8b9e77
4개의 변경된 파일46개의 추가작업 그리고 35개의 파일을 삭제
  1. 7 8
      lgc.c
  2. 4 1
      lstate.c
  3. 2 1
      lstate.h
  4. 33 25
      ltable.c

+ 7 - 8
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.133 2002/03/26 18:55:50 roberto Exp roberto $
+** $Id: lgc.c,v 1.134 2002/04/05 18:54:31 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -211,14 +211,13 @@ static void traversetable (GCState *st, Table *h) {
   int weakkey = 0;
   int weakvalue = 0;
   marktable(st, h->metatable);
+  lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
   mode = fasttm(st->L, h->metatable, TM_WEAKMODE);
-  if (mode) {  /* weak table? must be cleared after GC... */
-    h->mark = st->toclear;  /* put in the appropriate list */
-    st->toclear = h;
-    if (ttype(mode) == LUA_TSTRING) {
-      weakkey = (strchr(svalue(mode), 'k') != NULL);
-      weakvalue = (strchr(svalue(mode), 'v') != NULL);
-    }
+  if (mode && ttype(mode) == LUA_TSTRING) {  /* weak table? */
+    h->mark = st->toclear;  /* must be cleared after GC, ... */
+    st->toclear = h;  /* ...put in the appropriate list */
+    weakkey = (strchr(svalue(mode), 'k') != NULL);
+    weakvalue = (strchr(svalue(mode), 'v') != NULL);
   }
   if (!weakvalue) {
     i = sizearray(h);

+ 4 - 1
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.89 2002/04/16 17:08:28 roberto Exp roberto $
+** $Id: lstate.c,v 1.90 2002/04/22 14:40:23 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -69,6 +69,9 @@ static void f_luaopen (lua_State *L, void *ud) {
   G(L)->rootupval = NULL;
   G(L)->rootudata = NULL;
   G(L)->tmudata = NULL;
+  setnilvalue(key(G(L)->dummynode));
+  setnilvalue(val(G(L)->dummynode));
+  G(L)->dummynode->next = NULL;
   G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
   stack_init(L, L);  /* init stack */
   /* create default meta table with a dummy table, and then close the loop */

+ 2 - 1
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.82 2002/04/10 12:11:07 roberto Exp roberto $
+** $Id: lstate.h,v 1.83 2002/04/16 17:08:28 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -113,6 +113,7 @@ typedef struct global_State {
   lu_mem GCthreshold;
   lu_mem nblocks;  /* number of `bytes' currently allocated */
   lua_CFunction panic;  /* to be called in unprotected errors */
+  Node dummynode[1];  /* common node array for all empty tables */
   TString *tmname[TM_N];  /* array with tag-method names */
 } global_State;
 

+ 33 - 25
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.103 2002/04/05 18:54:31 roberto Exp roberto $
+** $Id: ltable.c,v 1.104 2002/04/22 14:40:23 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -52,13 +52,13 @@
 #define hashnum(t,n)	\
            (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t))))
 #define hashstr(t,str)	 (node(t, lmod((str)->tsv.hash, sizenode(t))))
-#define hashboolean(t,p) (node(t, p))  /* `p' in [0,1] < minimum table size */
+#define hashboolean(t,p) (node(t, lmod(p, sizenode(t))))
 
 /*
 ** for pointers, avoid modulus by power of 2, as they tend to have many
 ** 2 factors.
 */
-#define hashpointer(t,p) (node(t, (IntPoint(p) % (sizenode(t)-1))))
+#define hashpointer(t,p) (node(t, (IntPoint(p) % ((sizenode(t)-1)|1))))
 
 
 /*
@@ -200,12 +200,6 @@ static void numuse (const Table *t, int *narray, int *nhash) {
 }
 
 
-/*
-** (log2 of) minimum size for hash part of a table
-*/
-#define MINHASHSIZE	1
-
-
 static void setarrayvector (lua_State *L, Table *t, int size) {
   int i;
   luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
@@ -217,16 +211,22 @@ static void setarrayvector (lua_State *L, Table *t, int size) {
 
 static void setnodevector (lua_State *L, Table *t, int lsize) {
   int i;
-  int size;
-  if (lsize < MINHASHSIZE) lsize = MINHASHSIZE;
-  else if (lsize > MAXBITS)
+  int size = twoto(lsize);
+  if (lsize > MAXBITS)
     luaD_runerror(L, "table overflow");
-  size = twoto(lsize);
-  t->node = luaM_newvector(L, size, Node);
-  for (i=0; i<size; i++) {
-    t->node[i].next = NULL;
-    setnilvalue(key(node(t, i)));
-    setnilvalue(val(node(t, i)));
+  if (lsize == 0) {  /* no elements to hash part? */
+    t->node = G(L)->dummynode;  /* use common `dummynode' */
+    lua_assert(ttype(key(t->node)) == LUA_TNIL);  /* assert invariants: */
+    lua_assert(ttype(val(t->node)) == LUA_TNIL);
+    lua_assert(t->node->next == NULL);  /* (`dummynode' must be empty) */
+  }
+  else {
+    t->node = luaM_newvector(L, size, Node);
+    for (i=0; i<size; i++) {
+      t->node[i].next = NULL;
+      setnilvalue(key(node(t, i)));
+      setnilvalue(val(node(t, i)));
+    }
   }
   t->lsizenode = cast(lu_byte, lsize);
   t->firstfree = node(t, size-1);  /* first free position to be used */
@@ -235,14 +235,22 @@ static void setnodevector (lua_State *L, Table *t, int lsize) {
 
 static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
   int i;
-  int oldasize, oldhsize;
+  int oldasize = t->sizearray;
+  int oldhsize = t->lsizenode;
   Node *nold;
-  oldasize = t->sizearray;
+  Node temp[1];
+  if (oldhsize)
+    nold = t->node;  /* save old hash ... */
+  else {  /* old hash is `dummynode' */
+    lua_assert(t->node == G(L)->dummynode);
+    temp[0] = t->node[0];  /* copy it to `temp' (in case of errors) */
+    nold = temp;
+    setnilvalue(key(G(L)->dummynode));  /* restate invariant */
+    setnilvalue(val(G(L)->dummynode));
+  }
   if (nasize > oldasize)  /* should grow array part? */
     setarrayvector(L, t, nasize);
   /* create new hash part with appropriate size */
-  nold = t->node;  /* save old hash ... */
-  oldhsize = t->lsizenode;  /* ... and (log of) old size */
   setnodevector(L, t, nhsize);  
   /* re-insert elements */
   if (nasize < oldasize) {  /* array part must shrink? */
@@ -262,7 +270,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
     if (ttype(val(old)) != LUA_TNIL)
       luaH_set(L, t, key(old), val(old));
   }
-  luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
+  if (oldhsize)
+    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
 }
 
 
@@ -299,8 +308,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
 
 
 void luaH_free (lua_State *L, Table *t) {
-  lua_assert(t->lsizenode > 0 || t->node == NULL);
-  if (t->lsizenode > 0)
+  if (t->lsizenode)
     luaM_freearray(L, t->node, sizenode(t), Node);
   luaM_freearray(L, t->array, t->sizearray, TObject);
   luaM_freelem(L, t);