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) |