mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
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:
parent
15208188de
commit
7c8cff64e6
5 changed files with 212 additions and 31 deletions
|
@ -257,46 +257,50 @@ DObject::DObject (PClass *inClass)
|
||||||
|
|
||||||
DObject::~DObject ()
|
DObject::~DObject ()
|
||||||
{
|
{
|
||||||
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
|
if (!PClass::bShutdown)
|
||||||
{
|
{
|
||||||
DObject **probe;
|
|
||||||
PClass *type = GetClass();
|
PClass *type = GetClass();
|
||||||
|
if (!(ObjectFlags & OF_Cleanup) && !PClass::bShutdown)
|
||||||
if (!(ObjectFlags & OF_YesReallyDelete))
|
|
||||||
{
|
{
|
||||||
Printf ("Warning: '%s' is freed outside the GC process.\n",
|
DObject **probe;
|
||||||
type != NULL ? type->TypeName.GetChars() : "==some object==");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all pointers that reference this object and NULL them.
|
if (!(ObjectFlags & OF_YesReallyDelete))
|
||||||
StaticPointerSubstitution(this, NULL);
|
|
||||||
|
|
||||||
// Now unlink this object from the GC list.
|
|
||||||
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
|
|
||||||
{
|
|
||||||
if (*probe == this)
|
|
||||||
{
|
{
|
||||||
*probe = ObjNext;
|
Printf("Warning: '%s' is freed outside the GC process.\n",
|
||||||
if (&ObjNext == GC::SweepPos)
|
type != NULL ? type->TypeName.GetChars() : "==some object==");
|
||||||
{
|
|
||||||
GC::SweepPos = probe;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If it's gray, also unlink it from the gray list.
|
// Find all pointers that reference this object and NULL them.
|
||||||
if (this->IsGray())
|
StaticPointerSubstitution(this, NULL);
|
||||||
{
|
|
||||||
for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext))
|
// Now unlink this object from the GC list.
|
||||||
|
for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext))
|
||||||
{
|
{
|
||||||
if (*probe == this)
|
if (*probe == this)
|
||||||
{
|
{
|
||||||
*probe = GCNext;
|
*probe = ObjNext;
|
||||||
|
if (&ObjNext == GC::SweepPos)
|
||||||
|
{
|
||||||
|
GC::SweepPos = probe;
|
||||||
|
}
|
||||||
break;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
144
src/dobjtype.cpp
144
src/dobjtype.cpp
|
@ -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
|
// PType :: SetValue
|
||||||
|
@ -1497,6 +1527,43 @@ bool PString::ReadValue(FArchive &ar, void *addr) const
|
||||||
return true;
|
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 ******************************************************************/
|
/* PName ******************************************************************/
|
||||||
|
|
||||||
IMPLEMENT_CLASS(PName)
|
IMPLEMENT_CLASS(PName)
|
||||||
|
@ -2328,6 +2395,20 @@ bool PArray::ReadValue(FArchive &ar, void *addr) const
|
||||||
return false;
|
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
|
// 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
|
// PStruct :: WriteValue
|
||||||
|
@ -3287,9 +3385,50 @@ DObject *PClass::CreateNew() const
|
||||||
|
|
||||||
ConstructNative (mem);
|
ConstructNative (mem);
|
||||||
((DObject *)mem)->SetClass (const_cast<PClass *>(this));
|
((DObject *)mem)->SetClass (const_cast<PClass *>(this));
|
||||||
|
if (Defaults != NULL)
|
||||||
|
{
|
||||||
|
InitializeSpecials(mem);
|
||||||
|
}
|
||||||
return (DObject *)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
|
// PClass :: Derive
|
||||||
|
@ -3388,6 +3527,11 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
|
||||||
{
|
{
|
||||||
Defaults = (BYTE *)M_Realloc(Defaults, Size);
|
Defaults = (BYTE *)M_Realloc(Defaults, Size);
|
||||||
memset(Defaults + oldsize, 0, Size - oldsize);
|
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;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
|
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
|
||||||
|
|
||||||
// Variable/parameter/field flags -------------------------------------------
|
// Variable/parameter/field flags -------------------------------------------
|
||||||
|
|
||||||
// Making all these different storage types use a common set of flags seems
|
// 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);
|
||||||
static void SkipValue(FArchive &ar, int tag);
|
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)
|
// Sets the value of a variable of this type at (addr)
|
||||||
virtual void SetValue(void *addr, int val);
|
virtual void SetValue(void *addr, int val);
|
||||||
virtual void SetValue(void *addr, double val);
|
virtual void SetValue(void *addr, double val);
|
||||||
|
@ -404,6 +422,9 @@ public:
|
||||||
|
|
||||||
void WriteValue(FArchive &ar, const void *addr) const override;
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
bool ReadValue(FArchive &ar, 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 ----------------------------------------------
|
// Variations of integer types ----------------------------------------------
|
||||||
|
@ -577,6 +598,8 @@ public:
|
||||||
void WriteValue(FArchive &ar, const void *addr) const override;
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
bool ReadValue(FArchive &ar, void *addr) const override;
|
bool ReadValue(FArchive &ar, void *addr) const override;
|
||||||
|
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PArray();
|
PArray();
|
||||||
};
|
};
|
||||||
|
@ -637,6 +660,7 @@ public:
|
||||||
|
|
||||||
void WriteValue(FArchive &ar, const void *addr) const override;
|
void WriteValue(FArchive &ar, const void *addr) const override;
|
||||||
bool ReadValue(FArchive &ar, 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);
|
static void WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields);
|
||||||
bool ReadFields(FArchive &ar, void *addr) const;
|
bool ReadFields(FArchive &ar, void *addr) const;
|
||||||
|
@ -697,7 +721,9 @@ class PClass : public PStruct
|
||||||
protected:
|
protected:
|
||||||
// We unravel _WITH_META here just as we did for PType.
|
// We unravel _WITH_META here just as we did for PType.
|
||||||
enum { MetaClassNum = CLASSREG_PClassClass };
|
enum { MetaClassNum = CLASSREG_PClassClass };
|
||||||
|
TArray<FTypeAndOffset> SpecialInits;
|
||||||
virtual void Derive(PClass *newclass);
|
virtual void Derive(PClass *newclass);
|
||||||
|
void InitializeSpecials(void *addr) const;
|
||||||
public:
|
public:
|
||||||
typedef PClassClass MetaClass;
|
typedef PClassClass MetaClass;
|
||||||
MetaClass *GetClass() const;
|
MetaClass *GetClass() const;
|
||||||
|
@ -728,6 +754,7 @@ public:
|
||||||
PField *AddField(FName name, PType *type, DWORD flags=0) override;
|
PField *AddField(FName name, PType *type, DWORD flags=0) override;
|
||||||
void InitializeActorInfo();
|
void InitializeActorInfo();
|
||||||
void BuildFlatPointers();
|
void BuildFlatPointers();
|
||||||
|
void DestroySpecials(void *addr) const;
|
||||||
const PClass *NativeClass() const;
|
const PClass *NativeClass() const;
|
||||||
|
|
||||||
// Returns true if this type is an ancestor of (or same as) the passed type.
|
// Returns true if this type is an ancestor of (or same as) the passed type.
|
||||||
|
|
14
src/tarray.h
14
src/tarray.h
|
@ -94,17 +94,23 @@ public:
|
||||||
{
|
{
|
||||||
return &Array[0];
|
return &Array[0];
|
||||||
}
|
}
|
||||||
|
const_iterator begin() const
|
||||||
iterator end()
|
|
||||||
{
|
{
|
||||||
return &Array[Count];
|
return &Array[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cbegin() const
|
const_iterator cbegin() const
|
||||||
{
|
{
|
||||||
return &Array[0];
|
return &Array[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterator end()
|
||||||
|
{
|
||||||
|
return &Array[Count];
|
||||||
|
}
|
||||||
|
const_iterator end() const
|
||||||
|
{
|
||||||
|
return &Array[Count];
|
||||||
|
}
|
||||||
const_iterator cend() const
|
const_iterator cend() const
|
||||||
{
|
{
|
||||||
return &Array[Count];
|
return &Array[Count];
|
||||||
|
|
|
@ -3039,7 +3039,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit indexv(index->Emit(build));
|
ExpEmit indexv(index->Emit(build));
|
||||||
int shiftbits = 0;
|
int shiftbits = 0;
|
||||||
while (1 << shiftbits < arraytype->ElementSize)
|
while (1u << shiftbits < arraytype->ElementSize)
|
||||||
{
|
{
|
||||||
shiftbits++;
|
shiftbits++;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue