mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-27 14:12:28 +00:00
- took VMFunction out of the DObject hierarchy.
As it stood, just compiling the internal ZScript code created more than 9000 DObjects, none of which really need to be subjected to garbage collection, aside from allowing lazy deallocation. This puts an incredible drag on the garbage collector which often needs several minutes to finish processing before actual deletion can start. The VM functions with roughly 1800 of these objects were by far the easiest to refactor so they are now. They also use a memory arena now which significantly reduces their memory footprint.
This commit is contained in:
parent
3cddcc8524
commit
3cbd62479b
8 changed files with 59 additions and 73 deletions
|
@ -361,17 +361,6 @@ static void MarkRoot()
|
|||
}
|
||||
Mark(SectorMarker);
|
||||
Mark(interpolator.Head);
|
||||
// Mark action functions
|
||||
if (!FinalGC)
|
||||
{
|
||||
FAutoSegIterator probe(ARegHead, ARegTail);
|
||||
|
||||
while (*++probe != NULL)
|
||||
{
|
||||
AFuncDesc *afunc = (AFuncDesc *)*probe;
|
||||
Mark(*(afunc->VMPointer));
|
||||
}
|
||||
}
|
||||
// Mark types
|
||||
TypeTable.Mark();
|
||||
for (unsigned int i = 0; i < PClass::AllClasses.Size(); ++i)
|
||||
|
@ -776,7 +765,7 @@ CCMD(gc)
|
|||
{
|
||||
if (argv.argc() == 1)
|
||||
{
|
||||
Printf ("Usage: gc stop|now|full|pause [size]|stepmul [size]\n");
|
||||
Printf ("Usage: gc stop|now|full|count|pause [size]|stepmul [size]\n");
|
||||
return;
|
||||
}
|
||||
if (stricmp(argv[1], "stop") == 0)
|
||||
|
@ -791,6 +780,12 @@ CCMD(gc)
|
|||
{
|
||||
GC::FullGC();
|
||||
}
|
||||
else if (stricmp(argv[1], "count") == 0)
|
||||
{
|
||||
int cnt = 0;
|
||||
for (DObject *obj = GC::Root; obj; obj = obj->ObjNext, cnt++)
|
||||
Printf("%d active objects counted\n", cnt);
|
||||
}
|
||||
else if (stricmp(argv[1], "pause") == 0)
|
||||
{
|
||||
if (argv.argc() == 2)
|
||||
|
@ -814,3 +809,4 @@ CCMD(gc)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2698,7 +2698,6 @@ size_t PFunction::PropagateMark()
|
|||
for (unsigned i = 0; i < Variants.Size(); ++i)
|
||||
{
|
||||
GC::Mark(Variants[i].Proto);
|
||||
GC::Mark(Variants[i].Implementation);
|
||||
}
|
||||
return Variants.Size() * sizeof(Variants[0]) + Super::PropagateMark();
|
||||
}
|
||||
|
@ -2947,6 +2946,7 @@ void PClass::StaticShutdown ()
|
|||
*p = nullptr;
|
||||
}
|
||||
FunctionPtrList.Clear();
|
||||
VMFunction::DeleteAll();
|
||||
|
||||
// Make a full garbage collection here so that all destroyed but uncollected higher level objects
|
||||
// that still exist are properly taken down before the low level data is deleted.
|
||||
|
|
26
src/info.cpp
26
src/info.cpp
|
@ -351,32 +351,6 @@ void PClassActor::DeriveData(PClass *newclass)
|
|||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClassActor :: PropagateMark
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t PClassActor::PropagateMark()
|
||||
{
|
||||
// Mark state functions
|
||||
for (int i = 0; i < NumOwnedStates; ++i)
|
||||
{
|
||||
if (OwnedStates[i].ActionFunc != NULL)
|
||||
{
|
||||
GC::Mark(OwnedStates[i].ActionFunc);
|
||||
}
|
||||
}
|
||||
// Mark damage function
|
||||
if (Defaults != NULL)
|
||||
{
|
||||
GC::Mark(((AActor *)Defaults)->DamageFunc);
|
||||
}
|
||||
|
||||
// marked += ActorInfo->NumOwnedStates * sizeof(FState);
|
||||
return Super::PropagateMark();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClassActor :: SetReplacement
|
||||
|
|
|
@ -256,7 +256,6 @@ public:
|
|||
void RegisterIDs();
|
||||
void SetDamageFactor(FName type, double factor);
|
||||
void SetPainChance(FName type, int chance);
|
||||
size_t PropagateMark();
|
||||
bool SetReplacement(FName replaceName);
|
||||
void SetDropItems(DDropItem *drops);
|
||||
|
||||
|
|
|
@ -146,6 +146,26 @@ void FMemArena::FreeAllBlocks()
|
|||
FreeBlockChain(FreeBlocks);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: DumpInfo
|
||||
//
|
||||
// Prints some info about this arena
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMemArena::DumpInfo()
|
||||
{
|
||||
size_t allocated = 0;
|
||||
size_t used = 0;
|
||||
for (auto block = TopBlock; block != NULL; block = block->NextBlock)
|
||||
{
|
||||
allocated += BlockSize;
|
||||
used += BlockSize - ((char*)block->Limit - (char*)block->Avail);
|
||||
}
|
||||
Printf("%zu bytes allocated, %zu bytes in use\n", allocated, used);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: FreeBlockChain
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
void *Alloc(size_t size);
|
||||
void FreeAll();
|
||||
void FreeAllBlocks();
|
||||
void DumpInfo();
|
||||
|
||||
protected:
|
||||
struct Block;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "vectors.h"
|
||||
#include "cmdlib.h"
|
||||
#include "doomerrors.h"
|
||||
#include "memarena.h"
|
||||
|
||||
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return
|
||||
#define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function
|
||||
|
@ -693,10 +694,8 @@ do_double: if (inexact)
|
|||
}
|
||||
};
|
||||
|
||||
class VMFunction : public DObject
|
||||
class VMFunction
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(VMFunction, DObject);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
bool Native;
|
||||
bool Final = false; // cannot be overridden
|
||||
|
@ -709,7 +708,30 @@ public:
|
|||
|
||||
class PPrototype *Proto;
|
||||
|
||||
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {}
|
||||
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL)
|
||||
{
|
||||
AllFunctions.Push(this);
|
||||
}
|
||||
virtual ~VMFunction() {}
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
return Allocator.Alloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *block) {}
|
||||
void operator delete[](void *block) {}
|
||||
static void DeleteAll()
|
||||
{
|
||||
for (auto f : AllFunctions)
|
||||
{
|
||||
f->~VMFunction();
|
||||
}
|
||||
AllFunctions.Clear();
|
||||
}
|
||||
static FMemArena Allocator;
|
||||
static TArray<VMFunction *> AllFunctions;
|
||||
protected:
|
||||
};
|
||||
|
||||
// VM frame layout:
|
||||
|
@ -838,11 +860,9 @@ struct FStatementInfo
|
|||
|
||||
class VMScriptFunction : public VMFunction
|
||||
{
|
||||
DECLARE_CLASS(VMScriptFunction, VMFunction);
|
||||
public:
|
||||
VMScriptFunction(FName name=NAME_None);
|
||||
~VMScriptFunction();
|
||||
size_t PropagateMark();
|
||||
void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers);
|
||||
|
||||
VM_ATAG *KonstATags() { return (VM_UBYTE *)(KonstA + NumKonstA); }
|
||||
|
@ -910,7 +930,6 @@ private:
|
|||
|
||||
class VMNativeFunction : public VMFunction
|
||||
{
|
||||
DECLARE_CLASS(VMNativeFunction, VMFunction);
|
||||
public:
|
||||
typedef int (*NativeCallType)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
||||
|
||||
|
|
|
@ -42,14 +42,10 @@ cycle_t VMCycles[10];
|
|||
int VMCalls[10];
|
||||
|
||||
IMPLEMENT_CLASS(VMException, false, false)
|
||||
IMPLEMENT_CLASS(VMFunction, true, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(VMFunction)
|
||||
IMPLEMENT_POINTER(Proto)
|
||||
IMPLEMENT_POINTERS_END
|
||||
FMemArena VMFunction::Allocator(32768);
|
||||
TArray<VMFunction *> VMFunction::AllFunctions;
|
||||
|
||||
IMPLEMENT_CLASS(VMScriptFunction, false, false)
|
||||
IMPLEMENT_CLASS(VMNativeFunction, false, false)
|
||||
|
||||
VMScriptFunction::VMScriptFunction(FName name)
|
||||
{
|
||||
|
@ -87,7 +83,6 @@ VMScriptFunction::~VMScriptFunction()
|
|||
KonstS[i].~FString();
|
||||
}
|
||||
}
|
||||
M_Free(Code);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +95,7 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko
|
|||
assert(numkonsts >= 0 && numkonsts <= 65535);
|
||||
assert(numkonsta >= 0 && numkonsta <= 65535);
|
||||
assert(numlinenumbers >= 0 && numlinenumbers <= 65535);
|
||||
void *mem = M_Malloc(numops * sizeof(VMOP) +
|
||||
void *mem = Allocator.Alloc(numops * sizeof(VMOP) +
|
||||
numkonstd * sizeof(int) +
|
||||
numkonstf * sizeof(double) +
|
||||
numkonsts * sizeof(FString) +
|
||||
|
@ -166,24 +161,6 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko
|
|||
NumKonstA = numkonsta;
|
||||
}
|
||||
|
||||
size_t VMScriptFunction::PropagateMark()
|
||||
{
|
||||
if (KonstA != NULL)
|
||||
{
|
||||
FVoidObj *konsta = KonstA;
|
||||
VM_UBYTE *atag = KonstATags();
|
||||
for (int count = NumKonstA; count > 0; --count)
|
||||
{
|
||||
if (*atag++ == ATAG_OBJECT)
|
||||
{
|
||||
GC::Mark(konsta->o);
|
||||
}
|
||||
konsta++;
|
||||
}
|
||||
}
|
||||
return NumKonstA * sizeof(void *) + Super::PropagateMark();
|
||||
}
|
||||
|
||||
void VMScriptFunction::InitExtra(void *addr)
|
||||
{
|
||||
char *caddr = (char*)addr;
|
||||
|
|
Loading…
Reference in a new issue