|
@@ -541,29 +541,28 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** Convert an "abstract size" (number of values in an array) to
|
|
|
-** "concrete size" (number of cell elements in the array). Cells
|
|
|
-** do not need to be full; we only must make sure it has the values
|
|
|
-** needed and its 'tag' element. So, we compute the concrete tag index
|
|
|
-** and the concrete value index of the last element, get their maximum
|
|
|
-** and adds 1.
|
|
|
+** Convert an "abstract size" (number of slots in an array) to
|
|
|
+** "concrete size" (number of bytes in the array).
|
|
|
+** If the abstract size is not a multiple of NM, the last cell is
|
|
|
+** incomplete, so we don't need to allocate memory for the whole cell.
|
|
|
+** 'extra' computes how many values are not needed in that last cell.
|
|
|
+** It will be zero when 'size' is a multiple of NM, and from there it
|
|
|
+** increases as 'size' decreases, up to (NM - 1).
|
|
|
*/
|
|
|
-static unsigned int concretesize (unsigned int size) {
|
|
|
- if (size == 0) return 0;
|
|
|
- else {
|
|
|
- unsigned int ts = TagIndex(size - 1);
|
|
|
- unsigned int vs = ValueIndex(size - 1);
|
|
|
- return ((ts >= vs) ? ts : vs) + 1;
|
|
|
- }
|
|
|
+static size_t concretesize (unsigned int size) {
|
|
|
+ unsigned int numcells = (size + NM - 1) / NM; /* (size / NM) rounded up */
|
|
|
+ unsigned int extra = NM - 1 - ((size + NM - 1) % NM);
|
|
|
+ return numcells * sizeof(ArrayCell) - extra * sizeof(Value);
|
|
|
}
|
|
|
|
|
|
|
|
|
static ArrayCell *resizearray (lua_State *L , Table *t,
|
|
|
unsigned int oldasize,
|
|
|
unsigned int newasize) {
|
|
|
- oldasize = concretesize(oldasize);
|
|
|
- newasize = concretesize(newasize);
|
|
|
- return luaM_reallocvector(L, t->array, oldasize, newasize, ArrayCell);
|
|
|
+ size_t oldasizeb = concretesize(oldasize);
|
|
|
+ size_t newasizeb = concretesize(newasize);
|
|
|
+ void *a = luaM_reallocvector(L, t->array, oldasizeb, newasizeb, lu_byte);
|
|
|
+ return cast(ArrayCell*, a);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -747,10 +746,19 @@ Table *luaH_new (lua_State *L) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+** Frees a table. The assert ensures the correctness of 'concretesize',
|
|
|
+** checking its result against the address of the last element in the
|
|
|
+** array part of the table, computed abstractly.
|
|
|
+*/
|
|
|
void luaH_free (lua_State *L, Table *t) {
|
|
|
- unsigned ps = concretesize(luaH_realasize(t));
|
|
|
+ unsigned int realsize = luaH_realasize(t);
|
|
|
+ size_t sizeb = concretesize(realsize);
|
|
|
+ lua_assert((sizeb == 0 && realsize == 0) ||
|
|
|
+ cast_charp(t->array) + sizeb - sizeof(Value) ==
|
|
|
+ cast_charp(getArrVal(t, realsize - 1)));
|
|
|
freehash(L, t);
|
|
|
- luaM_freearray(L, t->array, ps);
|
|
|
+ luaM_freemem(L, t->array, sizeb);
|
|
|
luaM_free(L, t);
|
|
|
}
|
|
|
|
|
@@ -944,7 +952,7 @@ TString *luaH_getstrkey (Table *t, TString *key) {
|
|
|
** main search function
|
|
|
*/
|
|
|
int luaH_get (Table *t, const TValue *key, TValue *res) {
|
|
|
- const TValue *slot;
|
|
|
+ const TValue *slot;
|
|
|
switch (ttypetag(key)) {
|
|
|
case LUA_VSHRSTR:
|
|
|
slot = luaH_Hgetshortstr(t, tsvalue(key));
|