|
@@ -40,24 +40,26 @@
|
|
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
-** Only tables with hash parts larget than LIMFORLAST has a 'lastfree'
|
|
|
|
-** field that optimizes finding a free slot. Smaller tables do a
|
|
|
|
|
|
+** Only tables with hash parts larger than 2^LIMFORLAST has a 'lastfree'
|
|
|
|
+** field that optimizes finding a free slot. That field is stored just
|
|
|
|
+** before the array of nodes, in the same block. Smaller tables do a
|
|
** complete search when looking for a free slot.
|
|
** complete search when looking for a free slot.
|
|
*/
|
|
*/
|
|
-#define LLIMFORLAST 2 /* log2 of LIMTFORLAST */
|
|
|
|
-#define LIMFORLAST twoto(LLIMFORLAST)
|
|
|
|
|
|
+#define LIMFORLAST 2 /* log2 of real limit */
|
|
|
|
|
|
/*
|
|
/*
|
|
-** Union to store an int field ensuring that what follows it in
|
|
|
|
-** memory is properly aligned to store a TValue.
|
|
|
|
|
|
+** The union 'Limbox' stores 'lastfree' and ensures that what follows it
|
|
|
|
+** is properly aligned to store a Node.
|
|
*/
|
|
*/
|
|
|
|
+typedef struct { Node *dummy; Node follows_pNode; } Limbox_aux;
|
|
|
|
+
|
|
typedef union {
|
|
typedef union {
|
|
- int lastfree;
|
|
|
|
- char padding[offsetof(struct { int i; TValue v; }, v)];
|
|
|
|
|
|
+ Node *lastfree;
|
|
|
|
+ char padding[offsetof(Limbox_aux, follows_pNode)];
|
|
} Limbox;
|
|
} Limbox;
|
|
|
|
|
|
-#define haslastfree(t) ((t)->lsizenode > LLIMFORLAST)
|
|
|
|
-#define getlastfree(t) (&((cast(Limbox *, (t)->node) - 1)->lastfree))
|
|
|
|
|
|
+#define haslastfree(t) ((t)->lsizenode > LIMFORLAST)
|
|
|
|
+#define getlastfree(t) ((cast(Limbox *, (t)->node) - 1)->lastfree)
|
|
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -593,13 +595,13 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
|
|
if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE)
|
|
if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE)
|
|
luaG_runerror(L, "table overflow");
|
|
luaG_runerror(L, "table overflow");
|
|
size = twoto(lsize);
|
|
size = twoto(lsize);
|
|
- if (lsize <= LLIMFORLAST) /* no 'lastfree' field? */
|
|
|
|
|
|
+ if (lsize <= LIMFORLAST) /* no 'lastfree' field? */
|
|
t->node = luaM_newvector(L, size, Node);
|
|
t->node = luaM_newvector(L, size, Node);
|
|
else {
|
|
else {
|
|
size_t bsize = size * sizeof(Node) + sizeof(Limbox);
|
|
size_t bsize = size * sizeof(Node) + sizeof(Limbox);
|
|
char *node = luaM_newblock(L, bsize);
|
|
char *node = luaM_newblock(L, bsize);
|
|
t->node = cast(Node *, node + sizeof(Limbox));
|
|
t->node = cast(Node *, node + sizeof(Limbox));
|
|
- *getlastfree(t) = size; /* all positions are free */
|
|
|
|
|
|
+ getlastfree(t) = gnode(t, size); /* all positions are free */
|
|
}
|
|
}
|
|
t->lsizenode = cast_byte(lsize);
|
|
t->lsizenode = cast_byte(lsize);
|
|
setnodummy(t);
|
|
setnodummy(t);
|
|
@@ -776,8 +778,8 @@ void luaH_free (lua_State *L, Table *t) {
|
|
static Node *getfreepos (Table *t) {
|
|
static Node *getfreepos (Table *t) {
|
|
if (haslastfree(t)) { /* does it have 'lastfree' information? */
|
|
if (haslastfree(t)) { /* does it have 'lastfree' information? */
|
|
/* look for a spot before 'lastfree', updating 'lastfree' */
|
|
/* look for a spot before 'lastfree', updating 'lastfree' */
|
|
- while (*getlastfree(t) > 0) {
|
|
|
|
- Node *free = gnode(t, --(*getlastfree(t)));
|
|
|
|
|
|
+ while (getlastfree(t) > t->node) {
|
|
|
|
+ Node *free = --getlastfree(t);
|
|
if (keyisnil(free))
|
|
if (keyisnil(free))
|
|
return free;
|
|
return free;
|
|
}
|
|
}
|