CON: Remix resizearray in the following ways:

Make only one allocation instead of two.
Calculate array byte sizes in a way compatible with GAMEARRAY_BOOLEAN.
Clear the expanded part of grown arrays using correct counts for non-int32 sizes.
Support resizing an array to 0 to free it.

git-svn-id: https://svn.eduke32.com/eduke32@6900 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
hendricks266 2018-05-23 05:58:12 +00:00
parent cb86c86ee1
commit a442c4f7bf
2 changed files with 42 additions and 26 deletions

View file

@ -5004,33 +5004,42 @@ GAMEEXEC_STATIC void VM_Execute(native_t loop)
{ {
tw = *insptr++; tw = *insptr++;
gamearray_t & array = aGameArrays[tw];
int const newSize = Gv_GetVarX(*insptr++); int const newSize = Gv_GetVarX(*insptr++);
int const oldSize = aGameArrays[tw].size; int const oldSize = array.size;
if (newSize >= 0 && newSize != oldSize) if (newSize == oldSize || newSize < 0)
continue;
#if 0
OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n",
array.szLabel, array.size, newSize);
#endif
if (newSize == 0)
{ {
// OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", Baligned_free(array.pValues);
// aGameArrays[j].szLabel, aGameArrays[j].size, newSize); array.pValues = nullptr;
array.size = 0;
continue;
}
int const eltSize = Gv_GetArrayElementSize(tw); size_t const oldBytes = Gv_GetArrayAllocSizeForCount(tw, oldSize);
intptr_t *const pArray = oldSize != 0 ? (intptr_t *)Xmalloc(eltSize * oldSize) : NULL; size_t const newBytes = Gv_GetArrayAllocSizeForCount(tw, newSize);
intptr_t * const oldArray = array.pValues;
intptr_t * const newArray = (intptr_t *)Xaligned_alloc(ARRAY_ALIGNMENT, newBytes);
if (oldSize != 0) if (oldSize != 0)
Bmemcpy(pArray, aGameArrays[tw].pValues, eltSize * oldSize); Bmemcpy(newArray, oldArray, min(oldBytes, newBytes));
Baligned_free(aGameArrays[tw].pValues);
aGameArrays[tw].pValues = newSize != 0 ? (intptr_t *)Xaligned_alloc(ARRAY_ALIGNMENT, eltSize * newSize) : NULL;
aGameArrays[tw].size = newSize;
if (oldSize != 0)
Bmemcpy(aGameArrays[tw].pValues, pArray, eltSize * min(oldSize, newSize));
if (newSize > oldSize) if (newSize > oldSize)
Bmemset(&aGameArrays[tw].pValues[oldSize], 0, eltSize * (newSize - oldSize)); Bmemset((char *)newArray + oldBytes, 0, newBytes - oldBytes);
array.pValues = newArray;
array.size = newSize;
Baligned_free(oldArray);
Bfree(pArray);
}
continue; continue;
} }

View file

@ -376,7 +376,7 @@ unsigned __fastcall Gv_GetArrayElementSize(int const arrayIdx)
void Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32_t dwFlags) void Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32_t dwFlags)
{ {
Bassert(asize); Bassert(asize >= 0);
if (EDUKE32_PREDICT_FALSE(g_gameArrayCount >= MAXGAMEARRAYS)) if (EDUKE32_PREDICT_FALSE(g_gameArrayCount >= MAXGAMEARRAYS))
{ {
@ -434,9 +434,16 @@ void Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32_t
int const allocSize = Gv_GetArrayAllocSize(i); int const allocSize = Gv_GetArrayAllocSize(i);
aGameArrays[i].flags |= GAMEARRAY_ALLOCATED; aGameArrays[i].flags |= GAMEARRAY_ALLOCATED;
if (allocSize > 0)
{
aGameArrays[i].pValues = (intptr_t *) Xaligned_alloc(ARRAY_ALIGNMENT, allocSize); aGameArrays[i].pValues = (intptr_t *) Xaligned_alloc(ARRAY_ALIGNMENT, allocSize);
Bmemset(aGameArrays[i].pValues, 0, allocSize); Bmemset(aGameArrays[i].pValues, 0, allocSize);
} }
else
{
aGameArrays[i].pValues = nullptr;
}
}
g_gameArrayCount++; g_gameArrayCount++;
hash_add(&h_arrays, aGameArrays[i].szLabel, i, 1); hash_add(&h_arrays, aGameArrays[i].szLabel, i, 1);