diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-05-10 13:33:20 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-05-10 13:33:20 -0300 |
| commit | 330e51bed3159aa83dcc9cc559c22e7d84d37604 (patch) | |
| tree | 8d11540f124fe432e12296c85091947161fb3886 /lstring.c | |
| parent | 44b71ca81696dbec561c0172d1b81533f1c2153e (diff) | |
| download | lua-330e51bed3159aa83dcc9cc559c22e7d84d37604.tar.gz lua-330e51bed3159aa83dcc9cc559c22e7d84d37604.tar.bz2 lua-330e51bed3159aa83dcc9cc559c22e7d84d37604.zip | |
string hash uses one single hash table
Diffstat (limited to 'lstring.c')
| -rw-r--r-- | lstring.c | 111 |
1 files changed, 35 insertions, 76 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 1.34 2000/03/10 18:37:44 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.35 2000/05/08 19:32:53 roberto Exp roberto $ |
| 3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -17,30 +17,20 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | #define gcsizestring(L, l) numblocks(L, 0, sizeof(TString)+l) | ||
| 21 | #define gcsizeudata gcsizestring(L, 0) | ||
| 22 | |||
| 23 | |||
| 24 | |||
| 25 | void luaS_init (lua_State *L) { | 20 | void luaS_init (lua_State *L) { |
| 26 | int i; | 21 | L->strt.size = L->udt.size = 1; |
| 27 | L->string_root = luaM_newvector(L, NUM_HASHS, stringtable); | 22 | L->strt.nuse = L->udt.nuse = 0; |
| 28 | for (i=0; i<NUM_HASHS; i++) { | 23 | L->strt.hash = luaM_newvector(L, 1, TString *); |
| 29 | L->string_root[i].size = 1; | 24 | L->udt.hash = luaM_newvector(L, 1, TString *); |
| 30 | L->string_root[i].nuse = 0; | 25 | L->strt.hash[0] = L->udt.hash[0] = NULL; |
| 31 | L->string_root[i].hash = luaM_newvector(L, 1, TString *);; | ||
| 32 | L->string_root[i].hash[0] = NULL; | ||
| 33 | } | ||
| 34 | } | 26 | } |
| 35 | 27 | ||
| 36 | 28 | ||
| 37 | void luaS_freeall (lua_State *L) { | 29 | void luaS_freeall (lua_State *L) { |
| 38 | int i; | 30 | LUA_ASSERT(L, L->strt.nuse==0, "non-empty string table"); |
| 39 | for (i=0; i<NUM_HASHS; i++) { | 31 | luaM_free(L, L->strt.hash); |
| 40 | LUA_ASSERT(L, L->string_root[i].nuse==0, "non-empty string table"); | 32 | LUA_ASSERT(L, L->udt.nuse==0, "non-empty udata table"); |
| 41 | luaM_free(L, L->string_root[i].hash); | 33 | luaM_free(L, L->udt.hash); |
| 42 | } | ||
| 43 | luaM_free(L, L->string_root); | ||
| 44 | } | 34 | } |
| 45 | 35 | ||
| 46 | 36 | ||
| @@ -62,8 +52,7 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) { | |||
| 62 | TString *p = tb->hash[i]; | 52 | TString *p = tb->hash[i]; |
| 63 | while (p) { /* for each node in the list */ | 53 | while (p) { /* for each node in the list */ |
| 64 | TString *next = p->nexthash; /* save next */ | 54 | TString *next = p->nexthash; /* save next */ |
| 65 | unsigned long h = (p->constindex == -1) ? IntPoint(p->u.d.value) : | 55 | unsigned long h = (tb == &L->strt) ? p->u.s.hash : IntPoint(p->u.d.value); |
| 66 | p->u.s.hash; | ||
| 67 | int h1 = h&(newsize-1); /* new position */ | 56 | int h1 = h&(newsize-1); /* new position */ |
| 68 | LUA_ASSERT(L, h%newsize == (h&(newsize-1)), | 57 | LUA_ASSERT(L, h%newsize == (h&(newsize-1)), |
| 69 | "a&(x-1) == a%x, for x power of 2"); | 58 | "a&(x-1) == a%x, for x power of 2"); |
| @@ -78,79 +67,55 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) { | |||
| 78 | } | 67 | } |
| 79 | 68 | ||
| 80 | 69 | ||
| 81 | static TString *newone (lua_State *L, long l) { | ||
| 82 | TString *ts = (TString *)luaM_malloc(L, sizeof(TString)+l*sizeof(char)); | ||
| 83 | ts->marked = 0; | ||
| 84 | ts->nexthash = NULL; | ||
| 85 | return ts; | ||
| 86 | } | ||
| 87 | |||
| 88 | |||
| 89 | static TString *newone_s (lua_State *L, const char *str, | ||
| 90 | long l, unsigned long h) { | ||
| 91 | TString *ts = newone(L, l); | ||
| 92 | memcpy(ts->str, str, l); | ||
| 93 | ts->str[l] = 0; /* ending 0 */ | ||
| 94 | ts->u.s.len = l; | ||
| 95 | ts->u.s.hash = h; | ||
| 96 | ts->constindex = 0; | ||
| 97 | L->nblocks += gcsizestring(L, l); | ||
| 98 | return ts; | ||
| 99 | } | ||
| 100 | |||
| 101 | |||
| 102 | static TString *newone_u (lua_State *L, void *buff, int tag) { | ||
| 103 | TString *ts = newone(L, 0); | ||
| 104 | ts->u.d.value = buff; | ||
| 105 | ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; | ||
| 106 | ts->constindex = -1; /* tag -> this is a userdata */ | ||
| 107 | L->nblocks += gcsizeudata; | ||
| 108 | return ts; | ||
| 109 | } | ||
| 110 | |||
| 111 | |||
| 112 | static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) { | 70 | static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) { |
| 113 | ts->nexthash = tb->hash[h]; /* chain new entry */ | 71 | ts->nexthash = tb->hash[h]; /* chain new entry */ |
| 114 | tb->hash[h] = ts; | 72 | tb->hash[h] = ts; |
| 115 | tb->nuse++; | 73 | tb->nuse++; |
| 116 | if (tb->nuse > tb->size) /* too crowded? */ | 74 | if (tb->nuse > tb->size && tb->size < MAX_INT/2) /* too crowded? */ |
| 117 | luaS_resize(L, tb, tb->size*2); | 75 | luaS_resize(L, tb, tb->size*2); |
| 118 | } | 76 | } |
| 119 | 77 | ||
| 120 | 78 | ||
| 79 | |||
| 121 | TString *luaS_newlstr (lua_State *L, const char *str, long l) { | 80 | TString *luaS_newlstr (lua_State *L, const char *str, long l) { |
| 122 | unsigned long h = hash_s(str, l); | 81 | unsigned long h = hash_s(str, l); |
| 123 | stringtable *tb = &L->string_root[(l==0) ? 0 : | 82 | int h1 = h&(L->strt.size-1); |
| 124 | ((unsigned int)(str[0]+str[l-1]))&(NUM_HASHSTR-1)]; | ||
| 125 | int h1 = h&(tb->size-1); | ||
| 126 | TString *ts; | 83 | TString *ts; |
| 127 | for (ts = tb->hash[h1]; ts; ts = ts->nexthash) { | 84 | for (ts = L->strt.hash[h1]; ts; ts = ts->nexthash) { |
| 128 | if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0)) | 85 | if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0)) |
| 129 | return ts; | 86 | return ts; |
| 130 | } | 87 | } |
| 131 | /* not found */ | 88 | /* not found */ |
| 132 | ts = newone_s(L, str, l, h); /* create new entry */ | 89 | ts = (TString *)luaM_malloc(L, sizeof(TString)+l*sizeof(char)); |
| 133 | newentry(L, tb, ts, h1); /* insert it on table */ | 90 | ts->marked = 0; |
| 91 | ts->nexthash = NULL; | ||
| 92 | ts->u.s.len = l; | ||
| 93 | ts->u.s.hash = h; | ||
| 94 | ts->u.s.constindex = 0; | ||
| 95 | memcpy(ts->str, str, l); | ||
| 96 | ts->str[l] = 0; /* ending 0 */ | ||
| 97 | L->nblocks += gcsizestring(L, l); | ||
| 98 | newentry(L, &L->strt, ts, h1); /* insert it on table */ | ||
| 134 | return ts; | 99 | return ts; |
| 135 | } | 100 | } |
| 136 | 101 | ||
| 137 | 102 | ||
| 138 | /* | ||
| 139 | ** uses '%' for one hashing with userdata because addresses are too regular, | ||
| 140 | ** so two '&' operations would be highly correlated | ||
| 141 | */ | ||
| 142 | TString *luaS_createudata (lua_State *L, void *udata, int tag) { | 103 | TString *luaS_createudata (lua_State *L, void *udata, int tag) { |
| 143 | unsigned long h = IntPoint(udata); | 104 | unsigned long h = IntPoint(udata); |
| 144 | stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR]; | 105 | int h1 = h&(L->udt.size-1); |
| 145 | int h1 = h&(tb->size-1); | ||
| 146 | TString *ts; | 106 | TString *ts; |
| 147 | for (ts = tb->hash[h1]; ts; ts = ts->nexthash) { | 107 | for (ts = L->udt.hash[h1]; ts; ts = ts->nexthash) { |
| 148 | if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG)) | 108 | if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG)) |
| 149 | return ts; | 109 | return ts; |
| 150 | } | 110 | } |
| 151 | /* not found */ | 111 | /* not found */ |
| 152 | ts = newone_u(L, udata, tag); | 112 | ts = luaM_new(L, TString); |
| 153 | newentry(L, tb, ts, h1); | 113 | ts->marked = 0; |
| 114 | ts->nexthash = NULL; | ||
| 115 | ts->u.d.value = udata; | ||
| 116 | ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; | ||
| 117 | L->nblocks += gcsizeudata; | ||
| 118 | newentry(L, &L->udt, ts, h1); /* insert it on table */ | ||
| 154 | return ts; | 119 | return ts; |
| 155 | } | 120 | } |
| 156 | 121 | ||
| @@ -159,16 +124,10 @@ TString *luaS_new (lua_State *L, const char *str) { | |||
| 159 | return luaS_newlstr(L, str, strlen(str)); | 124 | return luaS_newlstr(L, str, strlen(str)); |
| 160 | } | 125 | } |
| 161 | 126 | ||
| 127 | |||
| 162 | TString *luaS_newfixed (lua_State *L, const char *str) { | 128 | TString *luaS_newfixed (lua_State *L, const char *str) { |
| 163 | TString *ts = luaS_new(L, str); | 129 | TString *ts = luaS_new(L, str); |
| 164 | if (ts->marked == 0) ts->marked = FIXMARK; /* avoid GC */ | 130 | if (ts->marked == 0) ts->marked = FIXMARK; /* avoid GC */ |
| 165 | return ts; | 131 | return ts; |
| 166 | } | 132 | } |
| 167 | 133 | ||
| 168 | |||
| 169 | void luaS_free (lua_State *L, TString *t) { | ||
| 170 | L->nblocks -= (t->constindex == -1) ? gcsizeudata : | ||
| 171 | gcsizestring(L, t->u.s.len); | ||
| 172 | luaM_free(L, t); | ||
| 173 | } | ||
| 174 | |||
