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