Added code to initialize and destroy string variables in classes

- Will require being able to add strings to non-native classes to actually
  test this.
This commit is contained in:
Randy Heit 2016-04-03 17:45:04 -05:00
parent 15208188de
commit 7c8cff64e6
5 changed files with 212 additions and 31 deletions

View File

@ -257,46 +257,50 @@ DObject::DObject (PClass *inClass)
DObject::~DObject ()
{
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
if (!PClass::bShutdown)
{
DObject **probe;
PClass *type = GetClass();
if (!(ObjectFlags & OF_YesReallyDelete))
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
{
Printf ("Warning: '%s' is freed outside the GC process.\n",
type != NULL ? type->TypeName.GetChars() : "==some object==");
}
DObject **probe;
// Find all pointers that reference this object and NULL them.
StaticPointerSubstitution(this, NULL);
// Now unlink this object from the GC list.
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
{
if (*probe == this)
if (!(ObjectFlags & OF_YesReallyDelete))
{
*probe = ObjNext;
if (&ObjNext == GC::SweepPos)
{
GC::SweepPos = probe;
}
break;
Printf("Warning: '%s' is freed outside the GC process.\n",
type != NULL ? type->TypeName.GetChars() : "==some object==");
}
}
// If it's gray, also unlink it from the gray list.
if (this->IsGray())
{
for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext))
// Find all pointers that reference this object and NULL them.
StaticPointerSubstitution(this, NULL);
// Now unlink this object from the GC list.
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
{
if (*probe == this)
{
*probe = GCNext;
*probe = ObjNext;
if (&ObjNext == GC::SweepPos)
{
GC::SweepPos = probe;
}
break;
}
}
// If it's gray, also unlink it from the gray list.
if (this->IsGray())
{
for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext))
{
if (*probe == this)
{
*probe = GCNext;
break;
}
}
}
}
type->DestroySpecials(this);
}
}

View File

@ -500,6 +500,36 @@ void PType::SkipValue(FArchive &ar, int tag)
}
}
//==========================================================================
//
// PType :: SetDefaultValue
//
//==========================================================================
void PType::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *stroffs) const
{
}
//==========================================================================
//
// PType :: InitializeValue
//
//==========================================================================
void PType::InitializeValue(void *addr, const void *def) const
{
}
//==========================================================================
//
// PType :: DestroyValue
//
//==========================================================================
void PType::DestroyValue(void *addr) const
{
}
//==========================================================================
//
// PType :: SetValue
@ -1497,6 +1527,43 @@ bool PString::ReadValue(FArchive &ar, void *addr) const
return true;
}
//==========================================================================
//
// PString :: SetDefaultValue
//
//==========================================================================
void PString::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
{
new((BYTE *)base + offset) FString;
if (special != NULL)
{
special->Push(std::make_pair(this, offset));
}
}
//==========================================================================
//
// PString :: InitializeValue
//
//==========================================================================
void PString::InitializeValue(void *addr, const void *def) const
{
new(addr) FString(*(FString *)def);
}
//==========================================================================
//
// PString :: DestroyValue
//
//==========================================================================
void PString::DestroyValue(void *addr) const
{
((FString *)addr)->~FString();
}
/* PName ******************************************************************/
IMPLEMENT_CLASS(PName)
@ -2328,6 +2395,20 @@ bool PArray::ReadValue(FArchive &ar, void *addr) const
return false;
}
//==========================================================================
//
// PArray :: SetDefaultValue
//
//==========================================================================
void PArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
{
for (unsigned i = 0; i < ElementCount; ++i)
{
ElementType->SetDefaultValue(base, offset + i*ElementSize, special);
}
}
//==========================================================================
//
// NewArray
@ -2581,6 +2662,23 @@ PStruct::PStruct(FName name, DObject *outer)
{
}
//==========================================================================
//
// PStruct :: SetDefaultValue
//
//==========================================================================
void PStruct::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const
{
for (const PField *field : Fields)
{
if (!(field->Flags & VARF_Native))
{
field->Type->SetDefaultValue(base, offset + field->Offset, special);
}
}
}
//==========================================================================
//
// PStruct :: WriteValue
@ -3287,9 +3385,50 @@ DObject *PClass::CreateNew() const
ConstructNative (mem);
((DObject *)mem)->SetClass (const_cast<PClass *>(this));
if (Defaults != NULL)
{
InitializeSpecials(mem);
}
return (DObject *)mem;
}
//==========================================================================
//
// PClass :: InitializeSpecials
//
// Initialize special fields of a newly-created instance (e.g. strings).
//
//==========================================================================
void PClass::InitializeSpecials(void *addr) const
{
if (ParentClass != NULL)
{
ParentClass->InitializeSpecials(addr);
}
for (auto tao : SpecialInits)
{
tao.first->InitializeValue((BYTE*)addr + tao.second, Defaults + tao.second);
}
}
//==========================================================================
//
// PClass :: DestroySpecials
//
//==========================================================================
void PClass::DestroySpecials(void *addr) const
{
if (ParentClass != NULL)
{
ParentClass->DestroySpecials(addr);
}
for (auto tao : SpecialInits)
{
tao.first->DestroyValue((BYTE *)addr + tao.second);
}
}
//==========================================================================
//
// PClass :: Derive
@ -3388,6 +3527,11 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
{
Defaults = (BYTE *)M_Realloc(Defaults, Size);
memset(Defaults + oldsize, 0, Size - oldsize);
// If this is a native class, then we must not initialize and
// destroy any of its members. We do, however, initialize the
// default instance since it's not a normal instance of the class.
type->SetDefaultValue(Defaults, field->Offset,
bRuntimeClass ? &SpecialInits : NULL);
}
return field;
}

View File

@ -7,6 +7,8 @@
#include "vm.h"
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
// Variable/parameter/field flags -------------------------------------------
// Making all these different storage types use a common set of flags seems
@ -200,6 +202,22 @@ public:
static void SkipValue(FArchive &ar);
static void SkipValue(FArchive &ar, int tag);
// Sets the default value for this type at (base + offset)
// If the default value is binary 0, then this function doesn't need
// to do anything, because PClass::Extend() takes care of that.
//
// The stroffs array is so that types that need special initialization
// and destruction (e.g. strings) can add their offsets to it for special
// initialization when the object is created and destruction when the
// object is destroyed.
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const;
// Initialize the value, if needed (e.g. strings)
virtual void InitializeValue(void *addr, const void *def) const;
// Destroy the value, if needed (e.g. strings)
virtual void DestroyValue(void *addr) const;
// Sets the value of a variable of this type at (addr)
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
@ -404,6 +422,9 @@ public:
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
};
// Variations of integer types ----------------------------------------------
@ -577,6 +598,8 @@ public:
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
protected:
PArray();
};
@ -637,6 +660,7 @@ public:
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
static void WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FArchive &ar, void *addr) const;
@ -697,7 +721,9 @@ class PClass : public PStruct
protected:
// We unravel _WITH_META here just as we did for PType.
enum { MetaClassNum = CLASSREG_PClassClass };
TArray<FTypeAndOffset> SpecialInits;
virtual void Derive(PClass *newclass);
void InitializeSpecials(void *addr) const;
public:
typedef PClassClass MetaClass;
MetaClass *GetClass() const;
@ -728,6 +754,7 @@ public:
PField *AddField(FName name, PType *type, DWORD flags=0) override;
void InitializeActorInfo();
void BuildFlatPointers();
void DestroySpecials(void *addr) const;
const PClass *NativeClass() const;
// Returns true if this type is an ancestor of (or same as) the passed type.

View File

@ -94,17 +94,23 @@ public:
{
return &Array[0];
}
const_iterator begin() const
{
return &Array[0];
}
const_iterator cbegin() const
{
return &Array[0];
}
iterator end()
{
return &Array[Count];
}
const_iterator cbegin() const
const_iterator end() const
{
return &Array[0];
return &Array[Count];
}
const_iterator cend() const
{
return &Array[Count];

View File

@ -3039,7 +3039,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
{
ExpEmit indexv(index->Emit(build));
int shiftbits = 0;
while (1 << shiftbits < arraytype->ElementSize)
while (1u << shiftbits < arraytype->ElementSize)
{
shiftbits++;
}