diff options
| author | Mike Pall <mike> | 2010-03-22 15:05:37 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-03-22 15:05:37 +0100 |
| commit | 361266518c1500f25f7d83464ad4b2e2bd81db51 (patch) | |
| tree | ddc694f82caadb2915e9f0d6b7a24c81c162fd03 /src | |
| parent | 51c14bf1c80367ec2645819cbdb93d84524060d2 (diff) | |
| download | luajit-361266518c1500f25f7d83464ad4b2e2bd81db51.tar.gz luajit-361266518c1500f25f7d83464ad4b2e2bd81db51.tar.bz2 luajit-361266518c1500f25f7d83464ad4b2e2bd81db51.zip | |
Move free node pos to t->node[0].freetop. Saves 4 bytes in GCtab.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_obj.h | 3 | ||||
| -rw-r--r-- | src/lj_state.c | 1 | ||||
| -rw-r--r-- | src/lj_tab.c | 89 |
3 files changed, 38 insertions, 55 deletions
diff --git a/src/lj_obj.h b/src/lj_obj.h index a37c0882..048a74f9 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
| @@ -453,7 +453,7 @@ typedef struct Node { | |||
| 453 | TValue val; /* Value object. Must be first field. */ | 453 | TValue val; /* Value object. Must be first field. */ |
| 454 | TValue key; /* Key object. */ | 454 | TValue key; /* Key object. */ |
| 455 | MRef next; /* Hash chain. */ | 455 | MRef next; /* Hash chain. */ |
| 456 | int32_t unused; /* For consistent alignment. */ | 456 | MRef freetop; /* Top of free elements (stored in t->node[0]). */ |
| 457 | } Node; | 457 | } Node; |
| 458 | 458 | ||
| 459 | LJ_STATIC_ASSERT(offsetof(Node, val) == 0); | 459 | LJ_STATIC_ASSERT(offsetof(Node, val) == 0); |
| @@ -468,7 +468,6 @@ typedef struct GCtab { | |||
| 468 | MRef node; /* Hash part. */ | 468 | MRef node; /* Hash part. */ |
| 469 | uint32_t asize; /* Size of array part (keys [0, asize-1]). */ | 469 | uint32_t asize; /* Size of array part (keys [0, asize-1]). */ |
| 470 | uint32_t hmask; /* Hash part mask (size of hash part - 1). */ | 470 | uint32_t hmask; /* Hash part mask (size of hash part - 1). */ |
| 471 | MRef lastfree; /* Any free position is before this position. */ | ||
| 472 | } GCtab; | 471 | } GCtab; |
| 473 | 472 | ||
| 474 | #define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab)) | 473 | #define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab)) |
diff --git a/src/lj_state.c b/src/lj_state.c index 1e490b28..e90359ef 100644 --- a/src/lj_state.c +++ b/src/lj_state.c | |||
| @@ -200,6 +200,7 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) | |||
| 200 | setnilV(registry(L)); | 200 | setnilV(registry(L)); |
| 201 | setnilV(&g->nilnode.val); | 201 | setnilV(&g->nilnode.val); |
| 202 | setnilV(&g->nilnode.key); | 202 | setnilV(&g->nilnode.key); |
| 203 | setmref(g->nilnode.freetop, &g->nilnode); | ||
| 203 | lj_str_initbuf(L, &g->tmpbuf); | 204 | lj_str_initbuf(L, &g->tmpbuf); |
| 204 | g->gc.state = GCSpause; | 205 | g->gc.state = GCSpause; |
| 205 | setgcref(g->gc.root, obj2gco(L)); | 206 | setgcref(g->gc.root, obj2gco(L)); |
diff --git a/src/lj_tab.c b/src/lj_tab.c index fc44fdb4..be26bdda 100644 --- a/src/lj_tab.c +++ b/src/lj_tab.c | |||
| @@ -60,9 +60,9 @@ static LJ_AINLINE void newhpart(lua_State *L, GCtab *t, uint32_t hbits) | |||
| 60 | lj_err_msg(L, LJ_ERR_TABOV); | 60 | lj_err_msg(L, LJ_ERR_TABOV); |
| 61 | hsize = 1u << hbits; | 61 | hsize = 1u << hbits; |
| 62 | node = lj_mem_newvec(L, hsize, Node); | 62 | node = lj_mem_newvec(L, hsize, Node); |
| 63 | setmref(node->freetop, &node[hsize]); | ||
| 63 | setmref(t->node, node); | 64 | setmref(t->node, node); |
| 64 | t->hmask = hsize-1; | 65 | t->hmask = hsize-1; |
| 65 | setmref(t->lastfree, &node[hsize]); | ||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /* | 68 | /* |
| @@ -116,7 +116,6 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits) | |||
| 116 | t->asize = asize; | 116 | t->asize = asize; |
| 117 | t->hmask = 0; | 117 | t->hmask = 0; |
| 118 | setmref(t->node, &g->nilnode); | 118 | setmref(t->node, &g->nilnode); |
| 119 | setmref(t->lastfree, &g->nilnode); | ||
| 120 | } else { /* Otherwise separately allocate the array part. */ | 119 | } else { /* Otherwise separately allocate the array part. */ |
| 121 | t = lj_mem_newobj(L, GCtab); | 120 | t = lj_mem_newobj(L, GCtab); |
| 122 | t->gct = ~LJ_TTAB; | 121 | t->gct = ~LJ_TTAB; |
| @@ -128,7 +127,6 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits) | |||
| 128 | t->hmask = 0; | 127 | t->hmask = 0; |
| 129 | g = G(L); | 128 | g = G(L); |
| 130 | setmref(t->node, &g->nilnode); | 129 | setmref(t->node, &g->nilnode); |
| 131 | setmref(t->lastfree, &g->nilnode); | ||
| 132 | if (asize > 0) { | 130 | if (asize > 0) { |
| 133 | if (asize > LJ_MAX_ASIZE) | 131 | if (asize > LJ_MAX_ASIZE) |
| 134 | lj_err_msg(L, LJ_ERR_TABOV); | 132 | lj_err_msg(L, LJ_ERR_TABOV); |
| @@ -196,7 +194,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt) | |||
| 196 | Node *node = noderef(t->node); | 194 | Node *node = noderef(t->node); |
| 197 | Node *knode = noderef(kt->node); | 195 | Node *knode = noderef(kt->node); |
| 198 | ptrdiff_t d = (char *)node - (char *)knode; | 196 | ptrdiff_t d = (char *)node - (char *)knode; |
| 199 | setmref(t->lastfree, (Node *)((char *)noderef(kt->lastfree) + d)); | 197 | setmref(node->freetop, (Node *)((char *)noderef(knode->freetop) + d)); |
| 200 | for (i = 0; i <= hmask; i++) { | 198 | for (i = 0; i <= hmask; i++) { |
| 201 | Node *kn = &knode[i]; | 199 | Node *kn = &knode[i]; |
| 202 | Node *n = &node[i]; | 200 | Node *n = &node[i]; |
| @@ -263,7 +261,6 @@ static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits) | |||
| 263 | } else { | 261 | } else { |
| 264 | global_State *g = G(L); | 262 | global_State *g = G(L); |
| 265 | setmref(t->node, &g->nilnode); | 263 | setmref(t->node, &g->nilnode); |
| 266 | setmref(t->lastfree, &g->nilnode); | ||
| 267 | t->hmask = 0; | 264 | t->hmask = 0; |
| 268 | } | 265 | } |
| 269 | if (asize < oldasize) { /* Array part shrinks? */ | 266 | if (asize < oldasize) { /* Array part shrinks? */ |
| @@ -427,59 +424,45 @@ cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key) | |||
| 427 | 424 | ||
| 428 | /* -- Table setters ------------------------------------------------------- */ | 425 | /* -- Table setters ------------------------------------------------------- */ |
| 429 | 426 | ||
| 430 | static Node *getfreepos(GCtab *t) | 427 | /* Insert new key. Use Brent's variation to optimize the chain length. */ |
| 431 | { | ||
| 432 | Node *node = noderef(t->node); | ||
| 433 | Node *lastfree = noderef(t->lastfree); | ||
| 434 | while (lastfree > node) { | ||
| 435 | lastfree--; | ||
| 436 | setmref(t->lastfree, lastfree); | ||
| 437 | if (tvisnil(&lastfree->key)) | ||
| 438 | return lastfree; | ||
| 439 | } | ||
| 440 | return NULL; /* could not find a free place */ | ||
| 441 | } | ||
| 442 | |||
| 443 | /* | ||
| 444 | ** inserts a new key into a hash table; first, check whether key's main | ||
| 445 | ** position is free. If not, check whether colliding node is in its main | ||
| 446 | ** position or not: if it is not, move colliding node to an empty place and | ||
| 447 | ** put new key in its main position; otherwise (colliding node is in its main | ||
| 448 | ** position), new key goes to an empty position. | ||
| 449 | */ | ||
| 450 | TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key) | 428 | TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key) |
| 451 | { | 429 | { |
| 452 | Node *mp = hashkey(t, key); | 430 | Node *n = hashkey(t, key); |
| 453 | if (!tvisnil(&mp->val) || t->hmask == 0) { | 431 | if (!tvisnil(&n->val) || t->hmask == 0) { |
| 454 | Node *othern; | 432 | Node *nodebase = noderef(t->node); |
| 455 | Node *n = getfreepos(t); /* get a free place */ | 433 | Node *collide, *freenode = noderef(nodebase->freetop); |
| 456 | if (n == NULL) { /* cannot find a free place? */ | 434 | lua_assert(freenode >= nodebase && freenode <= nodebase+t->hmask+1); |
| 457 | rehashtab(L, t, key); /* grow table */ | 435 | do { |
| 458 | return lj_tab_set(L, t, key); /* re-insert key into grown table */ | 436 | if (freenode == nodebase) { /* No free node found? */ |
| 459 | } | 437 | rehashtab(L, t, key); /* Rehash table. */ |
| 460 | lua_assert(n != &G(L)->nilnode); | 438 | return lj_tab_set(L, t, key); /* Retry key insertion. */ |
| 461 | othern = hashkey(t, &mp->key); | 439 | } |
| 462 | if (othern != mp) { /* is colliding node out of its main position? */ | 440 | } while (!tvisnil(&(--freenode)->key)); |
| 463 | /* yes; move colliding node into free position */ | 441 | setmref(nodebase->freetop, freenode); |
| 464 | while (noderef(othern->next) != mp) | 442 | lua_assert(freenode != &G(L)->nilnode); |
| 465 | othern = nextnode(othern); /* find previous */ | 443 | collide = hashkey(t, &n->key); |
| 466 | setmref(othern->next, n); /* redo the chain with `n' in place of `mp' */ | 444 | if (collide != n) { /* Colliding node not the main node? */ |
| 467 | *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ | 445 | while (noderef(collide->next) != n) /* Find predecessor. */ |
| 468 | setmref(mp->next, NULL); /* now `mp' is free */ | 446 | collide = nextnode(collide); |
| 469 | setnilV(&mp->val); | 447 | setmref(collide->next, freenode); /* Relink chain. */ |
| 470 | } else { /* colliding node is in its own main position */ | 448 | /* Copy colliding node into free node and free main node. */ |
| 471 | /* new node will go into free position */ | 449 | freenode->val = n->val; |
| 472 | setmrefr(n->next, mp->next); /* chain new position */ | 450 | freenode->key = n->key; |
| 473 | setmref(mp->next, n); | 451 | freenode->next = n->next; |
| 474 | mp = n; | 452 | setmref(n->next, NULL); |
| 453 | setnilV(&n->val); | ||
| 454 | } else { /* Otherwise use free node. */ | ||
| 455 | setmrefr(freenode->next, n->next); /* Insert into chain. */ | ||
| 456 | setmref(n->next, freenode); | ||
| 457 | n = freenode; | ||
| 475 | } | 458 | } |
| 476 | } | 459 | } |
| 477 | mp->key.u64 = key->u64; | 460 | n->key.u64 = key->u64; |
| 478 | if (LJ_UNLIKELY(tvismzero(&mp->key))) | 461 | if (LJ_UNLIKELY(tvismzero(&n->key))) |
| 479 | mp->key.u64 = 0; | 462 | n->key.u64 = 0; |
| 480 | lj_gc_barriert(L, t, key); | 463 | lj_gc_barriert(L, t, key); |
| 481 | lua_assert(tvisnil(&mp->val)); | 464 | lua_assert(tvisnil(&n->val)); |
| 482 | return &mp->val; | 465 | return &n->val; |
| 483 | } | 466 | } |
| 484 | 467 | ||
| 485 | TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key) | 468 | TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key) |
