- When purging ACS strings, free the strings themselves as well as marking them as free.

- Fixed: ACSStringPool::InsertString()'s overflow check was far too low.
- Fixed: When ACSStringPool::InsertString() triggered a garbage collection, it ignored the
  newly freed space and expanded the array anyway.

SVN r4328 (trunk)
This commit is contained in:
Randy Heit 2013-06-04 02:49:07 +00:00
parent 5e7ee8f33e
commit e2be8b9e7e
1 changed files with 12 additions and 5 deletions

View File

@ -481,21 +481,27 @@ void ACSStringPool::PurgeStrings()
// Clear the hash buckets. We'll rebuild them as we decide what strings // Clear the hash buckets. We'll rebuild them as we decide what strings
// to keep and which to toss. // to keep and which to toss.
memset(PoolBuckets, 0xFF, sizeof(PoolBuckets)); memset(PoolBuckets, 0xFF, sizeof(PoolBuckets));
size_t usedcount = 0, freedcount = 0;
for (unsigned int i = 0; i < Pool.Size(); ++i) for (unsigned int i = 0; i < Pool.Size(); ++i)
{ {
PoolEntry *entry = &Pool[i]; PoolEntry *entry = &Pool[i];
if (entry->Next != FREE_ENTRY) if (entry->Next != FREE_ENTRY)
{ {
if (entry->LockCount == 0) if (entry->LockCount == 0)
{ // Mark this entry as free. {
freedcount++;
// Mark this entry as free.
entry->Next = FREE_ENTRY; entry->Next = FREE_ENTRY;
if (i < FirstFreeEntry) if (i < FirstFreeEntry)
{ {
FirstFreeEntry = i; FirstFreeEntry = i;
} }
// And free the string.
entry->Str = "";
} }
else else
{ {
usedcount++;
// Rehash this entry. // Rehash this entry.
unsigned int h = entry->Hash % NUM_BUCKETS; unsigned int h = entry->Hash % NUM_BUCKETS;
entry->Next = PoolBuckets[h]; entry->Next = PoolBuckets[h];
@ -543,14 +549,15 @@ int ACSStringPool::FindString(const char *str, size_t len, unsigned int h, unsig
int ACSStringPool::InsertString(FString &str, unsigned int h, unsigned int bucketnum, const SDWORD *stack, int stackdepth) int ACSStringPool::InsertString(FString &str, unsigned int h, unsigned int bucketnum, const SDWORD *stack, int stackdepth)
{ {
if (Pool.Size() >= STRPOOL_LIBRARYID)
{
return -1;
}
unsigned int index = FirstFreeEntry; unsigned int index = FirstFreeEntry;
if (index >= MIN_GC_SIZE && index == Pool.Max()) if (index >= MIN_GC_SIZE && index == Pool.Max())
{ // We will need to grow the array. Try a garbage collection first. { // We will need to grow the array. Try a garbage collection first.
P_CollectACSGlobalStrings(stack, stackdepth); P_CollectACSGlobalStrings(stack, stackdepth);
index = FirstFreeEntry;
}
if (FirstFreeEntry >= STRPOOL_LIBRARYID_OR)
{ // If we go any higher, we'll collide with the library ID marker.
return -1;
} }
if (index == Pool.Size()) if (index == Pool.Size())
{ // There were no free entries; make a new one. { // There were no free entries; make a new one.