diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_tab.c | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/src/lj_tab.c b/src/lj_tab.c index a38eabd8..8011212f 100644 --- a/src/lj_tab.c +++ b/src/lj_tab.c | |||
@@ -29,7 +29,12 @@ static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash) | |||
29 | #define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi))) | 29 | #define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi))) |
30 | #define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1)) | 30 | #define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1)) |
31 | #define hashptr(t, p) hashlohi((t), u32ptr(p), u32ptr(p) + HASH_BIAS) | 31 | #define hashptr(t, p) hashlohi((t), u32ptr(p), u32ptr(p) + HASH_BIAS) |
32 | #if LJ_GC64 | ||
33 | #define hashgcref(t, r) \ | ||
34 | hashlohi((t), (uint32_t)gcrefu(r), (uint32_t)(gcrefu(r) >> 32)) | ||
35 | #else | ||
32 | #define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS) | 36 | #define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS) |
37 | #endif | ||
33 | 38 | ||
34 | /* Hash an arbitrary key and return its anchor position in the hash table. */ | 39 | /* Hash an arbitrary key and return its anchor position in the hash table. */ |
35 | static Node *hashkey(const GCtab *t, cTValue *key) | 40 | static Node *hashkey(const GCtab *t, cTValue *key) |
@@ -58,8 +63,8 @@ static LJ_AINLINE void newhpart(lua_State *L, GCtab *t, uint32_t hbits) | |||
58 | lj_err_msg(L, LJ_ERR_TABOV); | 63 | lj_err_msg(L, LJ_ERR_TABOV); |
59 | hsize = 1u << hbits; | 64 | hsize = 1u << hbits; |
60 | node = lj_mem_newvec(L, hsize, Node); | 65 | node = lj_mem_newvec(L, hsize, Node); |
61 | setmref(node->freetop, &node[hsize]); | ||
62 | setmref(t->node, node); | 66 | setmref(t->node, node); |
67 | setfreetop(t, node, &node[hsize]); | ||
63 | t->hmask = hsize-1; | 68 | t->hmask = hsize-1; |
64 | } | 69 | } |
65 | 70 | ||
@@ -98,6 +103,7 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits) | |||
98 | GCtab *t; | 103 | GCtab *t; |
99 | /* First try to colocate the array part. */ | 104 | /* First try to colocate the array part. */ |
100 | if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) { | 105 | if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) { |
106 | Node *nilnode; | ||
101 | lua_assert((sizeof(GCtab) & 7) == 0); | 107 | lua_assert((sizeof(GCtab) & 7) == 0); |
102 | t = (GCtab *)lj_mem_newgco(L, sizetabcolo(asize)); | 108 | t = (GCtab *)lj_mem_newgco(L, sizetabcolo(asize)); |
103 | t->gct = ~LJ_TTAB; | 109 | t->gct = ~LJ_TTAB; |
@@ -107,8 +113,13 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits) | |||
107 | setgcrefnull(t->metatable); | 113 | setgcrefnull(t->metatable); |
108 | t->asize = asize; | 114 | t->asize = asize; |
109 | t->hmask = 0; | 115 | t->hmask = 0; |
110 | setmref(t->node, &G(L)->nilnode); | 116 | nilnode = &G(L)->nilnode; |
117 | setmref(t->node, nilnode); | ||
118 | #if LJ_GC64 | ||
119 | setmref(t->freetop, nilnode); | ||
120 | #endif | ||
111 | } else { /* Otherwise separately allocate the array part. */ | 121 | } else { /* Otherwise separately allocate the array part. */ |
122 | Node *nilnode; | ||
112 | t = lj_mem_newobj(L, GCtab); | 123 | t = lj_mem_newobj(L, GCtab); |
113 | t->gct = ~LJ_TTAB; | 124 | t->gct = ~LJ_TTAB; |
114 | t->nomm = (uint8_t)~0; | 125 | t->nomm = (uint8_t)~0; |
@@ -117,7 +128,11 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits) | |||
117 | setgcrefnull(t->metatable); | 128 | setgcrefnull(t->metatable); |
118 | t->asize = 0; /* In case the array allocation fails. */ | 129 | t->asize = 0; /* In case the array allocation fails. */ |
119 | t->hmask = 0; | 130 | t->hmask = 0; |
120 | setmref(t->node, &G(L)->nilnode); | 131 | nilnode = &G(L)->nilnode; |
132 | setmref(t->node, nilnode); | ||
133 | #if LJ_GC64 | ||
134 | setmref(t->freetop, nilnode); | ||
135 | #endif | ||
121 | if (asize > 0) { | 136 | if (asize > 0) { |
122 | if (asize > LJ_MAX_ASIZE) | 137 | if (asize > LJ_MAX_ASIZE) |
123 | lj_err_msg(L, LJ_ERR_TABOV); | 138 | lj_err_msg(L, LJ_ERR_TABOV); |
@@ -149,6 +164,12 @@ GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits) | |||
149 | return t; | 164 | return t; |
150 | } | 165 | } |
151 | 166 | ||
167 | /* The API of this function conforms to lua_createtable(). */ | ||
168 | GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h) | ||
169 | { | ||
170 | return lj_tab_new(L, (uint32_t)(a > 0 ? a+1 : 0), hsize2hbits(h)); | ||
171 | } | ||
172 | |||
152 | #if LJ_HASJIT | 173 | #if LJ_HASJIT |
153 | GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize) | 174 | GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize) |
154 | { | 175 | { |
@@ -185,7 +206,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt) | |||
185 | Node *node = noderef(t->node); | 206 | Node *node = noderef(t->node); |
186 | Node *knode = noderef(kt->node); | 207 | Node *knode = noderef(kt->node); |
187 | ptrdiff_t d = (char *)node - (char *)knode; | 208 | ptrdiff_t d = (char *)node - (char *)knode; |
188 | setmref(node->freetop, (Node *)((char *)noderef(knode->freetop) + d)); | 209 | setfreetop(t, node, (Node *)((char *)getfreetop(kt, knode) + d)); |
189 | for (i = 0; i <= hmask; i++) { | 210 | for (i = 0; i <= hmask; i++) { |
190 | Node *kn = &knode[i]; | 211 | Node *kn = &knode[i]; |
191 | Node *n = &node[i]; | 212 | Node *n = &node[i]; |
@@ -198,6 +219,17 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt) | |||
198 | return t; | 219 | return t; |
199 | } | 220 | } |
200 | 221 | ||
222 | /* Clear a table. */ | ||
223 | void LJ_FASTCALL lj_tab_clear(GCtab *t) | ||
224 | { | ||
225 | clearapart(t); | ||
226 | if (t->hmask > 0) { | ||
227 | Node *node = noderef(t->node); | ||
228 | setfreetop(t, node, &node[t->hmask+1]); | ||
229 | clearhpart(t); | ||
230 | } | ||
231 | } | ||
232 | |||
201 | /* Free a table. */ | 233 | /* Free a table. */ |
202 | void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t) | 234 | void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t) |
203 | { | 235 | { |
@@ -214,7 +246,7 @@ void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t) | |||
214 | /* -- Table resizing ------------------------------------------------------ */ | 246 | /* -- Table resizing ------------------------------------------------------ */ |
215 | 247 | ||
216 | /* Resize a table to fit the new array/hash part sizes. */ | 248 | /* Resize a table to fit the new array/hash part sizes. */ |
217 | static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits) | 249 | void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits) |
218 | { | 250 | { |
219 | Node *oldnode = noderef(t->node); | 251 | Node *oldnode = noderef(t->node); |
220 | uint32_t oldasize = t->asize; | 252 | uint32_t oldasize = t->asize; |
@@ -247,6 +279,9 @@ static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits) | |||
247 | } else { | 279 | } else { |
248 | global_State *g = G(L); | 280 | global_State *g = G(L); |
249 | setmref(t->node, &g->nilnode); | 281 | setmref(t->node, &g->nilnode); |
282 | #if LJ_GC64 | ||
283 | setmref(t->freetop, &g->nilnode); | ||
284 | #endif | ||
250 | t->hmask = 0; | 285 | t->hmask = 0; |
251 | } | 286 | } |
252 | if (asize < oldasize) { /* Array part shrinks? */ | 287 | if (asize < oldasize) { /* Array part shrinks? */ |
@@ -348,7 +383,7 @@ static void rehashtab(lua_State *L, GCtab *t, cTValue *ek) | |||
348 | asize += countint(ek, bins); | 383 | asize += countint(ek, bins); |
349 | na = bestasize(bins, &asize); | 384 | na = bestasize(bins, &asize); |
350 | total -= na; | 385 | total -= na; |
351 | resizetab(L, t, asize, hsize2hbits(total)); | 386 | lj_tab_resize(L, t, asize, hsize2hbits(total)); |
352 | } | 387 | } |
353 | 388 | ||
354 | #if LJ_HASFFI | 389 | #if LJ_HASFFI |
@@ -360,7 +395,7 @@ void lj_tab_rehash(lua_State *L, GCtab *t) | |||
360 | 395 | ||
361 | void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize) | 396 | void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize) |
362 | { | 397 | { |
363 | resizetab(L, t, nasize+1, t->hmask > 0 ? lj_fls(t->hmask)+1 : 0); | 398 | lj_tab_resize(L, t, nasize+1, t->hmask > 0 ? lj_fls(t->hmask)+1 : 0); |
364 | } | 399 | } |
365 | 400 | ||
366 | /* -- Table getters ------------------------------------------------------- */ | 401 | /* -- Table getters ------------------------------------------------------- */ |
@@ -428,7 +463,7 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key) | |||
428 | Node *n = hashkey(t, key); | 463 | Node *n = hashkey(t, key); |
429 | if (!tvisnil(&n->val) || t->hmask == 0) { | 464 | if (!tvisnil(&n->val) || t->hmask == 0) { |
430 | Node *nodebase = noderef(t->node); | 465 | Node *nodebase = noderef(t->node); |
431 | Node *collide, *freenode = noderef(nodebase->freetop); | 466 | Node *collide, *freenode = getfreetop(t, nodebase); |
432 | lua_assert(freenode >= nodebase && freenode <= nodebase+t->hmask+1); | 467 | lua_assert(freenode >= nodebase && freenode <= nodebase+t->hmask+1); |
433 | do { | 468 | do { |
434 | if (freenode == nodebase) { /* No free node found? */ | 469 | if (freenode == nodebase) { /* No free node found? */ |
@@ -436,7 +471,7 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key) | |||
436 | return lj_tab_set(L, t, key); /* Retry key insertion. */ | 471 | return lj_tab_set(L, t, key); /* Retry key insertion. */ |
437 | } | 472 | } |
438 | } while (!tvisnil(&(--freenode)->key)); | 473 | } while (!tvisnil(&(--freenode)->key)); |
439 | setmref(nodebase->freetop, freenode); | 474 | setfreetop(t, nodebase, freenode); |
440 | lua_assert(freenode != &G(L)->nilnode); | 475 | lua_assert(freenode != &G(L)->nilnode); |
441 | collide = hashkey(t, &n->key); | 476 | collide = hashkey(t, &n->key); |
442 | if (collide != n) { /* Colliding node not the main node? */ | 477 | if (collide != n) { /* Colliding node not the main node? */ |