mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-12 09:24:07 +00:00
Move free node pos to t->node[0].freetop. Saves 4 bytes in GCtab.
This commit is contained in:
parent
51c14bf1c8
commit
361266518c
@ -453,7 +453,7 @@ typedef struct Node {
|
|||||||
TValue val; /* Value object. Must be first field. */
|
TValue val; /* Value object. Must be first field. */
|
||||||
TValue key; /* Key object. */
|
TValue key; /* Key object. */
|
||||||
MRef next; /* Hash chain. */
|
MRef next; /* Hash chain. */
|
||||||
int32_t unused; /* For consistent alignment. */
|
MRef freetop; /* Top of free elements (stored in t->node[0]). */
|
||||||
} Node;
|
} Node;
|
||||||
|
|
||||||
LJ_STATIC_ASSERT(offsetof(Node, val) == 0);
|
LJ_STATIC_ASSERT(offsetof(Node, val) == 0);
|
||||||
@ -468,7 +468,6 @@ typedef struct GCtab {
|
|||||||
MRef node; /* Hash part. */
|
MRef node; /* Hash part. */
|
||||||
uint32_t asize; /* Size of array part (keys [0, asize-1]). */
|
uint32_t asize; /* Size of array part (keys [0, asize-1]). */
|
||||||
uint32_t hmask; /* Hash part mask (size of hash part - 1). */
|
uint32_t hmask; /* Hash part mask (size of hash part - 1). */
|
||||||
MRef lastfree; /* Any free position is before this position. */
|
|
||||||
} GCtab;
|
} GCtab;
|
||||||
|
|
||||||
#define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab))
|
#define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab))
|
||||||
|
@ -200,6 +200,7 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
|
|||||||
setnilV(registry(L));
|
setnilV(registry(L));
|
||||||
setnilV(&g->nilnode.val);
|
setnilV(&g->nilnode.val);
|
||||||
setnilV(&g->nilnode.key);
|
setnilV(&g->nilnode.key);
|
||||||
|
setmref(g->nilnode.freetop, &g->nilnode);
|
||||||
lj_str_initbuf(L, &g->tmpbuf);
|
lj_str_initbuf(L, &g->tmpbuf);
|
||||||
g->gc.state = GCSpause;
|
g->gc.state = GCSpause;
|
||||||
setgcref(g->gc.root, obj2gco(L));
|
setgcref(g->gc.root, obj2gco(L));
|
||||||
|
89
src/lj_tab.c
89
src/lj_tab.c
@ -60,9 +60,9 @@ static LJ_AINLINE void newhpart(lua_State *L, GCtab *t, uint32_t hbits)
|
|||||||
lj_err_msg(L, LJ_ERR_TABOV);
|
lj_err_msg(L, LJ_ERR_TABOV);
|
||||||
hsize = 1u << hbits;
|
hsize = 1u << hbits;
|
||||||
node = lj_mem_newvec(L, hsize, Node);
|
node = lj_mem_newvec(L, hsize, Node);
|
||||||
|
setmref(node->freetop, &node[hsize]);
|
||||||
setmref(t->node, node);
|
setmref(t->node, node);
|
||||||
t->hmask = hsize-1;
|
t->hmask = hsize-1;
|
||||||
setmref(t->lastfree, &node[hsize]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -116,7 +116,6 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
|
|||||||
t->asize = asize;
|
t->asize = asize;
|
||||||
t->hmask = 0;
|
t->hmask = 0;
|
||||||
setmref(t->node, &g->nilnode);
|
setmref(t->node, &g->nilnode);
|
||||||
setmref(t->lastfree, &g->nilnode);
|
|
||||||
} else { /* Otherwise separately allocate the array part. */
|
} else { /* Otherwise separately allocate the array part. */
|
||||||
t = lj_mem_newobj(L, GCtab);
|
t = lj_mem_newobj(L, GCtab);
|
||||||
t->gct = ~LJ_TTAB;
|
t->gct = ~LJ_TTAB;
|
||||||
@ -128,7 +127,6 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
|
|||||||
t->hmask = 0;
|
t->hmask = 0;
|
||||||
g = G(L);
|
g = G(L);
|
||||||
setmref(t->node, &g->nilnode);
|
setmref(t->node, &g->nilnode);
|
||||||
setmref(t->lastfree, &g->nilnode);
|
|
||||||
if (asize > 0) {
|
if (asize > 0) {
|
||||||
if (asize > LJ_MAX_ASIZE)
|
if (asize > LJ_MAX_ASIZE)
|
||||||
lj_err_msg(L, LJ_ERR_TABOV);
|
lj_err_msg(L, LJ_ERR_TABOV);
|
||||||
@ -196,7 +194,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
|
|||||||
Node *node = noderef(t->node);
|
Node *node = noderef(t->node);
|
||||||
Node *knode = noderef(kt->node);
|
Node *knode = noderef(kt->node);
|
||||||
ptrdiff_t d = (char *)node - (char *)knode;
|
ptrdiff_t d = (char *)node - (char *)knode;
|
||||||
setmref(t->lastfree, (Node *)((char *)noderef(kt->lastfree) + d));
|
setmref(node->freetop, (Node *)((char *)noderef(knode->freetop) + d));
|
||||||
for (i = 0; i <= hmask; i++) {
|
for (i = 0; i <= hmask; i++) {
|
||||||
Node *kn = &knode[i];
|
Node *kn = &knode[i];
|
||||||
Node *n = &node[i];
|
Node *n = &node[i];
|
||||||
@ -263,7 +261,6 @@ static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
|
|||||||
} else {
|
} else {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
setmref(t->node, &g->nilnode);
|
setmref(t->node, &g->nilnode);
|
||||||
setmref(t->lastfree, &g->nilnode);
|
|
||||||
t->hmask = 0;
|
t->hmask = 0;
|
||||||
}
|
}
|
||||||
if (asize < oldasize) { /* Array part shrinks? */
|
if (asize < oldasize) { /* Array part shrinks? */
|
||||||
@ -427,59 +424,45 @@ cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key)
|
|||||||
|
|
||||||
/* -- Table setters ------------------------------------------------------- */
|
/* -- Table setters ------------------------------------------------------- */
|
||||||
|
|
||||||
static Node *getfreepos(GCtab *t)
|
/* Insert new key. Use Brent's variation to optimize the chain length. */
|
||||||
{
|
|
||||||
Node *node = noderef(t->node);
|
|
||||||
Node *lastfree = noderef(t->lastfree);
|
|
||||||
while (lastfree > node) {
|
|
||||||
lastfree--;
|
|
||||||
setmref(t->lastfree, lastfree);
|
|
||||||
if (tvisnil(&lastfree->key))
|
|
||||||
return lastfree;
|
|
||||||
}
|
|
||||||
return NULL; /* could not find a free place */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** inserts a new key into a hash table; first, check whether key's main
|
|
||||||
** position is free. If not, check whether colliding node is in its main
|
|
||||||
** position or not: if it is not, move colliding node to an empty place and
|
|
||||||
** put new key in its main position; otherwise (colliding node is in its main
|
|
||||||
** position), new key goes to an empty position.
|
|
||||||
*/
|
|
||||||
TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
|
TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
|
||||||
{
|
{
|
||||||
Node *mp = hashkey(t, key);
|
Node *n = hashkey(t, key);
|
||||||
if (!tvisnil(&mp->val) || t->hmask == 0) {
|
if (!tvisnil(&n->val) || t->hmask == 0) {
|
||||||
Node *othern;
|
Node *nodebase = noderef(t->node);
|
||||||
Node *n = getfreepos(t); /* get a free place */
|
Node *collide, *freenode = noderef(nodebase->freetop);
|
||||||
if (n == NULL) { /* cannot find a free place? */
|
lua_assert(freenode >= nodebase && freenode <= nodebase+t->hmask+1);
|
||||||
rehashtab(L, t, key); /* grow table */
|
do {
|
||||||
return lj_tab_set(L, t, key); /* re-insert key into grown table */
|
if (freenode == nodebase) { /* No free node found? */
|
||||||
}
|
rehashtab(L, t, key); /* Rehash table. */
|
||||||
lua_assert(n != &G(L)->nilnode);
|
return lj_tab_set(L, t, key); /* Retry key insertion. */
|
||||||
othern = hashkey(t, &mp->key);
|
}
|
||||||
if (othern != mp) { /* is colliding node out of its main position? */
|
} while (!tvisnil(&(--freenode)->key));
|
||||||
/* yes; move colliding node into free position */
|
setmref(nodebase->freetop, freenode);
|
||||||
while (noderef(othern->next) != mp)
|
lua_assert(freenode != &G(L)->nilnode);
|
||||||
othern = nextnode(othern); /* find previous */
|
collide = hashkey(t, &n->key);
|
||||||
setmref(othern->next, n); /* redo the chain with `n' in place of `mp' */
|
if (collide != n) { /* Colliding node not the main node? */
|
||||||
*n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
|
while (noderef(collide->next) != n) /* Find predecessor. */
|
||||||
setmref(mp->next, NULL); /* now `mp' is free */
|
collide = nextnode(collide);
|
||||||
setnilV(&mp->val);
|
setmref(collide->next, freenode); /* Relink chain. */
|
||||||
} else { /* colliding node is in its own main position */
|
/* Copy colliding node into free node and free main node. */
|
||||||
/* new node will go into free position */
|
freenode->val = n->val;
|
||||||
setmrefr(n->next, mp->next); /* chain new position */
|
freenode->key = n->key;
|
||||||
setmref(mp->next, n);
|
freenode->next = n->next;
|
||||||
mp = n;
|
setmref(n->next, NULL);
|
||||||
|
setnilV(&n->val);
|
||||||
|
} else { /* Otherwise use free node. */
|
||||||
|
setmrefr(freenode->next, n->next); /* Insert into chain. */
|
||||||
|
setmref(n->next, freenode);
|
||||||
|
n = freenode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mp->key.u64 = key->u64;
|
n->key.u64 = key->u64;
|
||||||
if (LJ_UNLIKELY(tvismzero(&mp->key)))
|
if (LJ_UNLIKELY(tvismzero(&n->key)))
|
||||||
mp->key.u64 = 0;
|
n->key.u64 = 0;
|
||||||
lj_gc_barriert(L, t, key);
|
lj_gc_barriert(L, t, key);
|
||||||
lua_assert(tvisnil(&mp->val));
|
lua_assert(tvisnil(&n->val));
|
||||||
return &mp->val;
|
return &n->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key)
|
TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key)
|
||||||
|
Loading…
Reference in New Issue
Block a user