2
0
Эх сурвалжийг харах

string hash uses one single hash table

Roberto Ierusalimschy 25 жил өмнө
parent
commit
330e51bed3
7 өөрчлөгдсөн 90 нэмэгдсэн , 131 устгасан
  1. 30 25
      lgc.c
  2. 2 2
      lobject.h
  3. 3 3
      lparser.c
  4. 4 6
      lstate.h
  5. 35 76
      lstring.c
  6. 5 7
      lstring.h
  7. 11 12
      ltests.c

+ 30 - 25
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.47 2000/04/14 18:12:35 roberto Exp roberto $
+** $Id: lgc.c,v 1.48 2000/05/08 19:32:53 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -166,36 +166,41 @@ static void collecttable (lua_State *L) {
 ** with limit=1, that means all unmarked elements;
 ** with limit=MAX_INT, that means all elements.
 */
-static void collectstring (lua_State *L, int limit) {
-  TObject o;  /* to call userdata `gc' tag method */
+static void collectstringtab (lua_State *L, int limit, stringtable *tb) {
   int i;
+  TObject o;  /* to call userdata `gc' tag method */
   ttype(&o) = TAG_USERDATA;
-  for (i=0; i<NUM_HASHS; i++) {  /* for each hash table */
-    stringtable *tb = &L->string_root[i];
-    int j;
-    for (j=0; j<tb->size; j++) {  /* for each list */
-      TString **p = &tb->hash[j];
-      TString *next;
-      while ((next = *p) != NULL) {
-       if (next->marked >= limit) {
-         if (next->marked < FIXMARK)  /* does not change FIXMARKs */
-           next->marked = 0;
-         p = &next->nexthash;
-       } 
-       else {  /* collect */
-          if (next->constindex == -1) {  /* is userdata? */
-            tsvalue(&o) = next;
-            luaD_gcTM(L, &o);
-          }
-          *p = next->nexthash;
-          luaS_free(L, next);
-          tb->nuse--;
+  for (i=0; i<tb->size; i++) {  /* for each list */
+    TString **p = &tb->hash[i];
+    TString *next;
+    while ((next = *p) != NULL) {
+     if (next->marked >= limit) {
+       if (next->marked < FIXMARK)  /* does not change FIXMARKs */
+         next->marked = 0;
+       p = &next->nexthash;
+     } 
+     else {  /* collect */
+        if (tb == &L->strt)  /* is string? */
+          L->nblocks -= gcsizestring(L, next->u.s.len);
+        else {
+          tsvalue(&o) = next;
+          luaD_gcTM(L, &o);
+          L->nblocks -= gcsizeudata;
         }
+        *p = next->nexthash;
+        tb->nuse--;
+        luaM_free(L, next);
       }
     }
-    if ((tb->nuse+1)*6 < tb->size)
-      luaS_resize(L, tb, tb->size/2);  /* table is too big */
   }
+  if (tb->nuse < (tb->size/4) && tb->size > 10)
+    luaS_resize(L, tb, tb->size/2);  /* table is too big */
+}
+
+
+static void collectstring (lua_State *L, int limit) {
+  collectstringtab(L, limit, &L->strt);
+  collectstringtab(L, limit, &L->udt);
 }
 
 

+ 2 - 2
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.62 2000/05/08 19:32:53 roberto Exp roberto $
+** $Id: lobject.h,v 1.63 2000/05/08 19:37:10 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -93,6 +93,7 @@ typedef struct TString {
     struct {  /* for strings */
       unsigned long hash;
       long len;
+      int constindex;  /* hint to reuse constants */
     } s;
     struct {  /* for userdata */
       int tag;
@@ -100,7 +101,6 @@ typedef struct TString {
     } d;
   } u;
   struct TString *nexthash;  /* chain for hash table */
-  int constindex;  /* hint to reuse constants (= -1 if this is a userdata) */
   unsigned char marked;
   char str[1];   /* variable length string!! must be the last field! */
 } TString;

+ 3 - 3
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.83 2000/04/27 17:39:56 roberto Exp roberto $
+** $Id: lparser.c,v 1.84 2000/05/08 18:46:34 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -139,13 +139,13 @@ static void check_END (LexState *ls, int who, int where) {
 
 static int string_constant (FuncState *fs, TString *s) {
   Proto *f = fs->f;
-  int c = s->constindex;
+  int c = s->u.s.constindex;
   if (c >= f->nkstr || f->kstr[c] != s) {
     luaM_growvector(fs->L, f->kstr, f->nkstr, 1, TString *,
                     constantEM, MAXARG_U);
     c = f->nkstr++;
     f->kstr[c] = s;
-    s->constindex = c;  /* hint for next time */
+    s->u.s.constindex = c;  /* hint for next time */
   }
   return c;
 }

+ 4 - 6
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.31 2000/03/30 17:19:48 roberto Exp roberto $
+** $Id: lstate.h,v 1.32 2000/05/08 19:32:53 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -42,7 +42,7 @@ struct C_Lua_Stack {
 
 typedef struct stringtable {
   int size;
-  int nuse;  /* number of elements */
+  long nuse;  /* number of elements */
   TString **hash;
 } stringtable;
 
@@ -66,7 +66,8 @@ struct lua_State {
   Proto *rootproto;  /* list of all prototypes */
   Closure *rootcl;  /* list of all closures */
   Hash *roottable;  /* list of all tables */
-  stringtable *string_root;  /* array of hash tables for strings and udata */
+  stringtable strt;  /* hash table for strings */
+  stringtable udt;   /* hash table for udata */
   Hash *gt;  /* table for globals */
   struct IM *IMtable;  /* table for tag methods */
   int last_tag;  /* last used tag in IMtable */
@@ -82,8 +83,5 @@ struct lua_State {
 };
 
 
-
-
-
 #endif
 

+ 35 - 76
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.34 2000/03/10 18:37:44 roberto Exp roberto $
+** $Id: lstring.c,v 1.35 2000/05/08 19:32:53 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -17,30 +17,20 @@
 
 
 
-#define gcsizestring(L, l)	numblocks(L, 0, sizeof(TString)+l)
-#define gcsizeudata		gcsizestring(L, 0)
-
-
-
 void luaS_init (lua_State *L) {
-  int i;
-  L->string_root = luaM_newvector(L, NUM_HASHS, stringtable);
-  for (i=0; i<NUM_HASHS; i++) {
-    L->string_root[i].size = 1;
-    L->string_root[i].nuse = 0;
-    L->string_root[i].hash = luaM_newvector(L, 1, TString *);;
-    L->string_root[i].hash[0] = NULL;
-  }
+  L->strt.size = L->udt.size = 1;
+  L->strt.nuse = L->udt.nuse = 0;
+  L->strt.hash = luaM_newvector(L, 1, TString *);
+  L->udt.hash = luaM_newvector(L, 1, TString *);
+  L->strt.hash[0] = L->udt.hash[0] = NULL;
 }
 
 
 void luaS_freeall (lua_State *L) {
-  int i;
-  for (i=0; i<NUM_HASHS; i++) {
-    LUA_ASSERT(L, L->string_root[i].nuse==0, "non-empty string table");
-    luaM_free(L, L->string_root[i].hash);
-  }
-  luaM_free(L, L->string_root);
+  LUA_ASSERT(L, L->strt.nuse==0, "non-empty string table");
+  luaM_free(L, L->strt.hash);
+  LUA_ASSERT(L, L->udt.nuse==0, "non-empty udata table");
+  luaM_free(L, L->udt.hash);
 }
 
 
@@ -62,8 +52,7 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
     TString *p = tb->hash[i];
     while (p) {  /* for each node in the list */
       TString *next = p->nexthash;  /* save next */
-      unsigned long h = (p->constindex == -1) ? IntPoint(p->u.d.value) :
-                                                p->u.s.hash;
+      unsigned long h = (tb == &L->strt) ? p->u.s.hash : IntPoint(p->u.d.value);
       int h1 = h&(newsize-1);  /* new position */
       LUA_ASSERT(L, h%newsize == (h&(newsize-1)),
                     "a&(x-1) == a%x, for x power of 2");
@@ -78,79 +67,55 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
 }
 
 
-static TString *newone (lua_State *L, long l) {
-  TString *ts = (TString *)luaM_malloc(L, sizeof(TString)+l*sizeof(char));
-  ts->marked = 0;
-  ts->nexthash = NULL;
-  return ts;
-}
-
-
-static TString *newone_s (lua_State *L, const char *str,
-                               long l, unsigned long h) {
-  TString *ts = newone(L, l);
-  memcpy(ts->str, str, l);
-  ts->str[l] = 0;  /* ending 0 */
-  ts->u.s.len = l;
-  ts->u.s.hash = h;
-  ts->constindex = 0;
-  L->nblocks += gcsizestring(L, l);
-  return ts;
-}
-
-
-static TString *newone_u (lua_State *L, void *buff, int tag) {
-  TString *ts = newone(L, 0);
-  ts->u.d.value = buff;
-  ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
-  ts->constindex = -1;  /* tag -> this is a userdata */
-  L->nblocks += gcsizeudata;
-  return ts;
-}
-
-
 static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) {
   ts->nexthash = tb->hash[h];  /* chain new entry */
   tb->hash[h] = ts;
   tb->nuse++;
-  if (tb->nuse > tb->size)  /* too crowded? */
+  if (tb->nuse > tb->size && tb->size < MAX_INT/2)  /* too crowded? */
     luaS_resize(L, tb, tb->size*2);
 }
 
 
+
 TString *luaS_newlstr (lua_State *L, const char *str, long l) {
   unsigned long h = hash_s(str, l);
-  stringtable *tb = &L->string_root[(l==0) ? 0 :
-                         ((unsigned int)(str[0]+str[l-1]))&(NUM_HASHSTR-1)];
-  int h1 = h&(tb->size-1);
+  int h1 = h&(L->strt.size-1);
   TString *ts;
-  for (ts = tb->hash[h1]; ts; ts = ts->nexthash) {
+  for (ts = L->strt.hash[h1]; ts; ts = ts->nexthash) {
     if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0))
       return ts;
   }
   /* not found */
-  ts = newone_s(L, str, l, h);  /* create new entry */
-  newentry(L, tb, ts, h1);  /* insert it on table */
+  ts = (TString *)luaM_malloc(L, sizeof(TString)+l*sizeof(char));
+  ts->marked = 0;
+  ts->nexthash = NULL;
+  ts->u.s.len = l;
+  ts->u.s.hash = h;
+  ts->u.s.constindex = 0;
+  memcpy(ts->str, str, l);
+  ts->str[l] = 0;  /* ending 0 */
+  L->nblocks += gcsizestring(L, l);
+  newentry(L, &L->strt, ts, h1);  /* insert it on table */
   return ts;
 }
 
 
-/*
-** uses '%' for one hashing with userdata because addresses are too regular,
-** so two '&' operations would be highly correlated
-*/
 TString *luaS_createudata (lua_State *L, void *udata, int tag) {
   unsigned long h = IntPoint(udata);
-  stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR];
-  int h1 = h&(tb->size-1);
+  int h1 = h&(L->udt.size-1);
   TString *ts;
-  for (ts = tb->hash[h1]; ts; ts = ts->nexthash) {
+  for (ts = L->udt.hash[h1]; ts; ts = ts->nexthash) {
     if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG))
       return ts;
   }
   /* not found */
-  ts = newone_u(L, udata, tag);
-  newentry(L, tb, ts, h1);
+  ts = luaM_new(L, TString);
+  ts->marked = 0;
+  ts->nexthash = NULL;
+  ts->u.d.value = udata;
+  ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
+  L->nblocks += gcsizeudata;
+  newentry(L, &L->udt, ts, h1);  /* insert it on table */
   return ts;
 }
 
@@ -159,16 +124,10 @@ TString *luaS_new (lua_State *L, const char *str) {
   return luaS_newlstr(L, str, strlen(str));
 }
 
+
 TString *luaS_newfixed (lua_State *L, const char *str) {
   TString *ts = luaS_new(L, str);
   if (ts->marked == 0) ts->marked = FIXMARK;  /* avoid GC */
   return ts;
 }
 
-
-void luaS_free (lua_State *L, TString *t) {
-  L->nblocks -= (t->constindex == -1) ? gcsizeudata :
-                                        gcsizestring(L, t->u.s.len);
-  luaM_free(L, t);
-}
-

+ 5 - 7
lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.18 2000/03/10 18:37:44 roberto Exp roberto $
+** $Id: lstring.h,v 1.19 2000/05/08 19:32:53 roberto Exp roberto $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -12,11 +12,6 @@
 #include "lstate.h"
 
 
-#define NUM_HASHSTR     32
-#define NUM_HASHUDATA   31
-#define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA)
-
-
 /*
 ** any TString with mark>=FIXMARK is never collected.
 ** Marks>=RESERVEDMARK are used to identify reserved words.
@@ -25,11 +20,14 @@
 #define RESERVEDMARK	3
 
 
+#define gcsizestring(L, l)      numblocks(L, 0, sizeof(TString)+l)
+#define gcsizeudata             gcsizestring(L, 0)
+
+
 void luaS_init (lua_State *L);
 void luaS_resize (lua_State *L, stringtable *tb, int newsize);
 TString *luaS_createudata (lua_State *L, void *udata, int tag);
 void luaS_freeall (lua_State *L);
-void luaS_free (lua_State *L, TString *ts);
 TString *luaS_newlstr (lua_State *L, const char *str, long l);
 TString *luaS_new (lua_State *L, const char *str);
 TString *luaS_newfixed (lua_State *L, const char *str);

+ 11 - 12
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.16 2000/04/14 17:46:15 roberto Exp roberto $
+** $Id: ltests.c,v 1.17 2000/05/08 19:32:53 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -14,6 +14,7 @@
 
 #include "lapi.h"
 #include "lauxlib.h"
+#include "ldo.h"
 #include "lmem.h"
 #include "lopcodes.h"
 #include "lstate.h"
@@ -193,24 +194,22 @@ static void table_query (lua_State *L) {
 
 
 static void string_query (lua_State *L) {
-  int h = luaL_check_int(L, 1) - 1;
+  stringtable *tb = (*luaL_check_string(L, 1) == 's') ? &L->strt : &L->udt;
   int s = luaL_opt_int(L, 2, 0) - 1;
   if (s==-1) {
-    if (h < NUM_HASHS) {
-      lua_pushnumber(L, L->string_root[h].nuse);
-      lua_pushnumber(L, L->string_root[h].size);
-    }
+    lua_pushnumber(L, tb->nuse);
+    lua_pushnumber(L, tb->size);
   }
-  else {
-    TString *ts = L->string_root[h].hash[s];
-    for (ts = L->string_root[h].hash[s]; ts; ts = ts->nexthash) {
-      if (ts->constindex == -1) lua_pushstring(L, "<USERDATA>");
-      else lua_pushstring(L, ts->str);
+  else if (s < tb->size) {
+    TString *ts;
+    for (ts = tb->hash[s]; ts; ts = ts->nexthash) {
+      ttype(L->top) = TAG_STRING;
+      tsvalue(L->top) = ts;
+      incr_top;
     }
   }
 }
 
-
 /*
 ** {======================================================
 ** function to test the API with C. It interprets a kind of "assembler"