diff options
Diffstat (limited to 'ltable.c')
-rw-r--r-- | ltable.c | 30 |
1 files changed, 16 insertions, 14 deletions
@@ -40,24 +40,26 @@ | |||
40 | 40 | ||
41 | 41 | ||
42 | /* | 42 | /* |
43 | ** Only tables with hash parts larget than LIMFORLAST has a 'lastfree' | 43 | ** Only tables with hash parts larger than 2^LIMFORLAST has a 'lastfree' |
44 | ** field that optimizes finding a free slot. Smaller tables do a | 44 | ** field that optimizes finding a free slot. That field is stored just |
45 | ** before the array of nodes, in the same block. Smaller tables do a | ||
45 | ** complete search when looking for a free slot. | 46 | ** complete search when looking for a free slot. |
46 | */ | 47 | */ |
47 | #define LLIMFORLAST 2 /* log2 of LIMTFORLAST */ | 48 | #define LIMFORLAST 2 /* log2 of real limit */ |
48 | #define LIMFORLAST twoto(LLIMFORLAST) | ||
49 | 49 | ||
50 | /* | 50 | /* |
51 | ** Union to store an int field ensuring that what follows it in | 51 | ** The union 'Limbox' stores 'lastfree' and ensures that what follows it |
52 | ** memory is properly aligned to store a TValue. | 52 | ** is properly aligned to store a Node. |
53 | */ | 53 | */ |
54 | typedef struct { Node *dummy; Node follows_pNode; } Limbox_aux; | ||
55 | |||
54 | typedef union { | 56 | typedef union { |
55 | int lastfree; | 57 | Node *lastfree; |
56 | char padding[offsetof(struct { int i; TValue v; }, v)]; | 58 | char padding[offsetof(Limbox_aux, follows_pNode)]; |
57 | } Limbox; | 59 | } Limbox; |
58 | 60 | ||
59 | #define haslastfree(t) ((t)->lsizenode > LLIMFORLAST) | 61 | #define haslastfree(t) ((t)->lsizenode > LIMFORLAST) |
60 | #define getlastfree(t) (&((cast(Limbox *, (t)->node) - 1)->lastfree)) | 62 | #define getlastfree(t) ((cast(Limbox *, (t)->node) - 1)->lastfree) |
61 | 63 | ||
62 | 64 | ||
63 | /* | 65 | /* |
@@ -593,13 +595,13 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { | |||
593 | if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) | 595 | if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) |
594 | luaG_runerror(L, "table overflow"); | 596 | luaG_runerror(L, "table overflow"); |
595 | size = twoto(lsize); | 597 | size = twoto(lsize); |
596 | if (lsize <= LLIMFORLAST) /* no 'lastfree' field? */ | 598 | if (lsize <= LIMFORLAST) /* no 'lastfree' field? */ |
597 | t->node = luaM_newvector(L, size, Node); | 599 | t->node = luaM_newvector(L, size, Node); |
598 | else { | 600 | else { |
599 | size_t bsize = size * sizeof(Node) + sizeof(Limbox); | 601 | size_t bsize = size * sizeof(Node) + sizeof(Limbox); |
600 | char *node = luaM_newblock(L, bsize); | 602 | char *node = luaM_newblock(L, bsize); |
601 | t->node = cast(Node *, node + sizeof(Limbox)); | 603 | t->node = cast(Node *, node + sizeof(Limbox)); |
602 | *getlastfree(t) = size; /* all positions are free */ | 604 | getlastfree(t) = gnode(t, size); /* all positions are free */ |
603 | } | 605 | } |
604 | t->lsizenode = cast_byte(lsize); | 606 | t->lsizenode = cast_byte(lsize); |
605 | setnodummy(t); | 607 | setnodummy(t); |
@@ -776,8 +778,8 @@ void luaH_free (lua_State *L, Table *t) { | |||
776 | static Node *getfreepos (Table *t) { | 778 | static Node *getfreepos (Table *t) { |
777 | if (haslastfree(t)) { /* does it have 'lastfree' information? */ | 779 | if (haslastfree(t)) { /* does it have 'lastfree' information? */ |
778 | /* look for a spot before 'lastfree', updating 'lastfree' */ | 780 | /* look for a spot before 'lastfree', updating 'lastfree' */ |
779 | while (*getlastfree(t) > 0) { | 781 | while (getlastfree(t) > t->node) { |
780 | Node *free = gnode(t, --(*getlastfree(t))); | 782 | Node *free = --getlastfree(t); |
781 | if (keyisnil(free)) | 783 | if (keyisnil(free)) |
782 | return free; | 784 | return free; |
783 | } | 785 | } |