- reverted most of the last commit after realizing that trying to manage constructing/destructing per variable is not going to work because it'd require some extensive exception management in the compiled VM code.

- instead add a list of SpecialInits to VMScriptFunction so this can be done transparently when setting up and popping the stack frame. The only drawback is that this requires permanent allocation of stack objects for the entire lifetime of a function but this is a relatively small tradeoff for significantly reduced maintenance work throughout.
- removed most #include "vm.h", because nearly all files already pull this in through dobject.h.
This commit is contained in:
Christoph Oelckers 2016-11-17 13:10:19 +01:00
parent 30e6e8e25f
commit d86f03e2e0
30 changed files with 55 additions and 235 deletions

View file

@ -70,7 +70,6 @@
#include "doomerrors.h" #include "doomerrors.h"
#include "p_effect.h" #include "p_effect.h"
#include "serializer.h" #include "serializer.h"
#include "vm.h"
#include "thingdef.h" #include "thingdef.h"
#include "info.h" #include "info.h"
#include "v_text.h" #include "v_text.h"

View file

@ -109,7 +109,6 @@
#include "p_local.h" #include "p_local.h"
#include "autosegs.h" #include "autosegs.h"
#include "fragglescript/t_fs.h" #include "fragglescript/t_fs.h"
#include "vm.h"
EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Bool, hud_althud)
void DrawHUD(); void DrawHUD();

View file

@ -77,7 +77,6 @@
#include "r_utility.h" #include "r_utility.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "intermission/intermission.h" #include "intermission/intermission.h"
#include "vm.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------

View file

@ -1869,39 +1869,6 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset>
} }
} }
//==========================================================================
//
// PArray :: InitializeValue
// This is needed for local array variables
//
//==========================================================================
void PArray::InitializeValue(void *addr, const void *def) const
{
char *caddr = (char*)addr;
char *cdef = (char*)def;
for (unsigned i = 0; i < ElementCount; ++i)
{
ElementType->InitializeValue(caddr + i * ElementSize, cdef + i * ElementSize);
}
}
//==========================================================================
//
// PArray :: DestroyValue
// This is needed for local array variables
//
//==========================================================================
void PArray::DestroyValue(void *addr) const
{
char *caddr = (char*)addr;
for (unsigned i = 0; i < ElementCount; ++i)
{
ElementType->DestroyValue(caddr + i * ElementSize);
}
}
//========================================================================== //==========================================================================
// //
// NewArray // NewArray
@ -1985,28 +1952,6 @@ void PDynArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
id2 = 0; id2 = 0;
} }
//==========================================================================
//
// PDynArray :: InitializeValue
//
//==========================================================================
void PDynArray::InitializeValue(void *addr, const void *def) const
{
// DynArrays are not implemented yet.
}
//==========================================================================
//
// PDynArray :: DestroyValue
//
//==========================================================================
void PDynArray::DestroyValue(void *addr) const
{
// DynArrays are not implemented yet.
}
//========================================================================== //==========================================================================
// //
// NewDynArray // NewDynArray
@ -2091,28 +2036,6 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
id2 = (intptr_t)ValueType; id2 = (intptr_t)ValueType;
} }
//==========================================================================
//
// PMap :: InitializeValue
//
//==========================================================================
void PMap::InitializeValue(void *addr, const void *def) const
{
// Maps are not implemented yet.
}
//==========================================================================
//
// PMap :: DestroyValue
//
//==========================================================================
void PMap::DestroyValue(void *addr) const
{
// Maps are not implemented yet.
}
//========================================================================== //==========================================================================
// //
// NewMap // NewMap
@ -2335,76 +2258,6 @@ size_t PStruct::PropagateMark()
return Fields.Size() * sizeof(void*) + Super::PropagateMark(); return Fields.Size() * sizeof(void*) + Super::PropagateMark();
} }
//==========================================================================
//
// PStruct :: InitializeValue
// This is needed for local array variables
//
//==========================================================================
void PStruct::InitializeValue(void *addr, const void *def) const
{
char *caddr = (char*)addr;
char *cdef = (char*)def;
for (auto tao : SpecialInits)
{
tao.first->InitializeValue(caddr + tao.second, cdef + tao.second);
}
}
//==========================================================================
//
// PStruct :: DestroyValue
// This is needed for local array variables
//
//==========================================================================
void PStruct::DestroyValue(void *addr) const
{
char *caddr = (char*)addr;
for (auto tao : SpecialInits)
{
tao.first->DestroyValue(caddr + tao.second);
}
}
//==========================================================================
//
// PStruct :: InitializeSpecialInits
//
// Initialize special field list.
//
//==========================================================================
void PStruct::InitializeSpecialInits()
{
// and initialize our own special values.
auto it = Symbols.GetIterator();
PSymbolTable::MapType::Pair *pair;
while (it.NextPair(pair))
{
auto field = dyn_cast<PField>(pair->Value);
if (field != nullptr && !(field->Flags & VARF_Native))
{
field->Type->SetDefaultValue(nullptr, unsigned(field->Offset), &SpecialInits);
}
}
}
//==========================================================================
//
// PStruct :: RequireConstruction
//
//==========================================================================
bool PStruct::RequireConstruction() const
{
return SpecialInits.Size() > 0;
}
//========================================================================== //==========================================================================
// //
// NewStruct // NewStruct

View file

@ -5,10 +5,10 @@
#error You must #include "dobject.h" to get dobjtype.h #error You must #include "dobject.h" to get dobjtype.h
#endif #endif
#include "vm.h"
typedef std::pair<const class PType *, unsigned> FTypeAndOffset; typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
#include "vm.h"
// 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
@ -256,9 +256,6 @@ public:
// Initialize the value, if needed (e.g. strings) // Initialize the value, if needed (e.g. strings)
virtual void InitializeValue(void *addr, const void *def) const; virtual void InitializeValue(void *addr, const void *def) const;
// This is for stack variables that may need construction/destruction at runtime
virtual bool RequireConstruction() const { return false; }
// Destroy the value, if needed (e.g. strings) // Destroy the value, if needed (e.g. strings)
virtual void DestroyValue(void *addr) const; virtual void DestroyValue(void *addr) const;
@ -492,7 +489,6 @@ public:
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override; void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
void InitializeValue(void *addr, const void *def) const override; void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override; void DestroyValue(void *addr) const override;
virtual bool RequireConstruction() const override { return true; }
}; };
// Variations of integer types ---------------------------------------------- // Variations of integer types ----------------------------------------------
@ -630,9 +626,6 @@ public:
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override; void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
bool RequireConstruction() const override { return ElementType->RequireConstruction(); }
protected: protected:
PArray(); PArray();
@ -649,9 +642,6 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
bool RequireConstruction() const override { return true; }
protected: protected:
PDynArray(); PDynArray();
}; };
@ -668,9 +658,6 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
bool RequireConstruction() const override { return true; }
protected: protected:
PMap(); PMap();
}; };
@ -678,10 +665,6 @@ protected:
class PStruct : public PNamedType class PStruct : public PNamedType
{ {
DECLARE_CLASS(PStruct, PNamedType); DECLARE_CLASS(PStruct, PNamedType);
protected:
TArray<FTypeAndOffset> SpecialInits;
public: public:
PStruct(FName name, PTypeBase *outer); PStruct(FName name, PTypeBase *outer);
@ -699,12 +682,6 @@ public:
static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields); static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FSerializer &ar, void *addr) const; bool ReadFields(FSerializer &ar, void *addr) const;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
bool RequireConstruction() const override;
void InitializeSpecialInits();
protected: protected:
PStruct(); PStruct();
}; };
@ -771,6 +748,7 @@ 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;
void Derive(PClass *newclass, FName name); void Derive(PClass *newclass, FName name);
void InitializeSpecials(void *addr) const; void InitializeSpecials(void *addr) const;
void SetSuper(); void SetSuper();

View file

@ -7,7 +7,6 @@
#include "gi.h" #include "gi.h"
#include "doomstat.h" #include "doomstat.h"
#include "gstrings.h" #include "gstrings.h"
#include "vm.h"
#include "g_level.h" #include "g_level.h"
#include "p_enemy.h" #include "p_enemy.h"
#include "a_doomglobal.h" #include "a_doomglobal.h"
@ -19,7 +18,6 @@
#include "p_maputl.h" #include "p_maputl.h"
#include "serializer.h" #include "serializer.h"
#include "g_shared/a_pickups.h" #include "g_shared/a_pickups.h"
#include "vm.h"
// Include all the other Doom stuff here to reduce compile time // Include all the other Doom stuff here to reduce compile time
#include "a_bossbrain.cpp" #include "a_bossbrain.cpp"

View file

@ -6,7 +6,6 @@
#include "p_local.h" #include "p_local.h"
#include "s_sound.h" #include "s_sound.h"
#include "gstrings.h" #include "gstrings.h"
#include "vm.h"
#include "p_enemy.h" #include "p_enemy.h"
#include "a_specialspot.h" #include "a_specialspot.h"
#include "g_level.h" #include "g_level.h"
@ -18,7 +17,6 @@
#include "a_morph.h" #include "a_morph.h"
#include "p_spec.h" #include "p_spec.h"
#include "serializer.h" #include "serializer.h"
#include "vm.h"
// Include all the other Heretic stuff here to reduce compile time // Include all the other Heretic stuff here to reduce compile time
#include "a_chicken.cpp" #include "a_chicken.cpp"

View file

@ -7,7 +7,6 @@
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "a_hexenglobal.h" #include "a_hexenglobal.h"
#include "i_system.h" #include "i_system.h"
#include "vm.h"
#include "gi.h" #include "gi.h"
#include "g_level.h" #include "g_level.h"
#include "p_enemy.h" #include "p_enemy.h"
@ -24,7 +23,6 @@
#include "p_maputl.h" #include "p_maputl.h"
#include "p_spec.h" #include "p_spec.h"
#include "serializer.h" #include "serializer.h"
#include "vm.h"
// Include all the Hexen stuff here to reduce compile time // Include all the Hexen stuff here to reduce compile time
#include "a_blastradius.cpp" #include "a_blastradius.cpp"

View file

@ -1,5 +1,4 @@
#include "actor.h" #include "actor.h"
#include "vm.h"
#include "p_conversation.h" #include "p_conversation.h"
#include "p_lnspec.h" #include "p_lnspec.h"
#include "a_action.h" #include "a_action.h"

View file

@ -2,7 +2,6 @@
#include "info.h" #include "info.h"
#include "gi.h" #include "gi.h"
#include "m_random.h" #include "m_random.h"
#include "vm.h"
static FRandom pr_orbit ("Orbit"); static FRandom pr_orbit ("Orbit");

View file

@ -14,7 +14,6 @@
#include "a_strifeglobal.h" #include "a_strifeglobal.h"
#include "a_morph.h" #include "a_morph.h"
#include "a_specialspot.h" #include "a_specialspot.h"
#include "vm.h"
#include "g_level.h" #include "g_level.h"
#include "g_game.h" #include "g_game.h"
#include "doomstat.h" #include "doomstat.h"

View file

@ -14,7 +14,6 @@
#include "statnums.h" #include "statnums.h"
#include "gstrings.h" #include "gstrings.h"
#include "a_action.h" #include "a_action.h"
#include "vm.h"
#include "v_text.h" #include "v_text.h"
#include "doomstat.h" #include "doomstat.h"
#include "doomdata.h" #include "doomdata.h"

View file

@ -37,7 +37,6 @@
#include "p_local.h" #include "p_local.h"
#include "statnums.h" #include "statnums.h"
#include "i_system.h" #include "i_system.h"
#include "vm.h"
#include "doomstat.h" #include "doomstat.h"
#include "serializer.h" #include "serializer.h"
#include "a_pickups.h" #include "a_pickups.h"

View file

@ -13,7 +13,6 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "templates.h" #include "templates.h"
#include "sbar.h" #include "sbar.h"
#include "vm.h"
#include "doomstat.h" #include "doomstat.h"
#include "g_level.h" #include "g_level.h"
#include "d_net.h" #include "d_net.h"

View file

@ -43,7 +43,6 @@
#include "v_text.h" #include "v_text.h"
#include "gi.h" #include "gi.h"
#include "vm.h"
#include "actor.h" #include "actor.h"
#include "r_state.h" #include "r_state.h"
#include "i_system.h" #include "i_system.h"
@ -52,7 +51,6 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "g_level.h" #include "g_level.h"
#include "stats.h" #include "stats.h"
#include "vm.h"
#include "thingdef.h" #include "thingdef.h"
#include "d_player.h" #include "d_player.h"
#include "doomerrors.h" #include "doomerrors.h"

View file

@ -43,7 +43,6 @@
#include "dobject.h" #include "dobject.h"
#include "doomdef.h" #include "doomdef.h"
#include "vm.h"
#include "s_sound.h" #include "s_sound.h"
#include "m_fixed.h" #include "m_fixed.h"

View file

@ -61,7 +61,6 @@
#include "c_console.h" #include "c_console.h"
#include "doomerrors.h" #include "doomerrors.h"
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "vm.h"
#include "v_video.h" #include "v_video.h"
#include "v_font.h" #include "v_font.h"
#include "doomstat.h" #include "doomstat.h"
@ -77,7 +76,6 @@
#include "p_maputl.h" #include "p_maputl.h"
#include "p_spec.h" #include "p_spec.h"
#include "templates.h" #include "templates.h"
#include "vm.h"
#include "v_text.h" #include "v_text.h"
#include "thingdef.h" #include "thingdef.h"
#include "math/cmath.h" #include "math/cmath.h"

View file

@ -43,7 +43,6 @@
#include "p_enemy.h" #include "p_enemy.h"
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "a_action.h" #include "a_action.h"
#include "vm.h"
#include "d_dehacked.h" #include "d_dehacked.h"
#include "g_level.h" #include "g_level.h"
#include "r_utility.h" #include "r_utility.h"
@ -53,7 +52,6 @@
#include "p_spec.h" #include "p_spec.h"
#include "p_checkposition.h" #include "p_checkposition.h"
#include "math/cmath.h" #include "math/cmath.h"
#include "vm.h"
#include "gi.h" #include "gi.h"

View file

@ -1,7 +1,7 @@
#ifndef __P_ENEMY_H__ #ifndef __P_ENEMY_H__
#define __P_ENEMY_H__ #define __P_ENEMY_H__
#include "vm.h" #include "dobject.h"
#include "vectors.h" #include "vectors.h"
struct sector_t; struct sector_t;

View file

@ -53,7 +53,6 @@
#include "a_action.h" #include "a_action.h"
#include "a_keys.h" #include "a_keys.h"
#include "p_conversation.h" #include "p_conversation.h"
#include "vm.h"
#include "g_game.h" #include "g_game.h"
#include "teaminfo.h" #include "teaminfo.h"
#include "r_data/r_translate.h" #include "r_data/r_translate.h"

View file

@ -25,7 +25,6 @@
#include "gi.h" #include "gi.h"
#include "p_pspr.h" #include "p_pspr.h"
#include "templates.h" #include "templates.h"
#include "vm.h"
#include "g_level.h" #include "g_level.h"
#include "d_player.h" #include "d_player.h"
#include "serializer.h" #include "serializer.h"

View file

@ -25,7 +25,6 @@
// Basic data types. // Basic data types.
// Needs fixed point, and BAM angles. // Needs fixed point, and BAM angles.
//#include "vm.h"
#define WEAPONBOTTOM 128. #define WEAPONBOTTOM 128.

View file

@ -39,7 +39,6 @@
#include "i_system.h" #include "i_system.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "v_text.h" #include "v_text.h"
#include "vm.h"
#include "thingdef.h" #include "thingdef.h"
// stores indices for symbolic state labels for some old-style DECORATE functions. // stores indices for symbolic state labels for some old-style DECORATE functions.

View file

@ -48,7 +48,6 @@
#include "doomdef.h" #include "doomdef.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "tarray.h" #include "tarray.h"
#include "vm.h"
#include "g_level.h" #include "g_level.h"
#include "d_net.h" #include "d_net.h"
#include "gstrings.h" #include "gstrings.h"

View file

@ -6,7 +6,6 @@
#include "s_sound.h" #include "s_sound.h"
#include "sc_man.h" #include "sc_man.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "vm.h"
class FScanner; class FScanner;

View file

@ -2,7 +2,6 @@
#define VM_H #define VM_H
#include "zstring.h" #include "zstring.h"
#include "dobject.h"
#include "autosegs.h" #include "autosegs.h"
#include "vectors.h" #include "vectors.h"
@ -815,6 +814,12 @@ public:
VM_UHALF MaxParam; // Maximum number of parameters this function has on the stack at once VM_UHALF MaxParam; // Maximum number of parameters this function has on the stack at once
VM_UBYTE NumArgs; // Number of arguments this function takes VM_UBYTE NumArgs; // Number of arguments this function takes
FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong. FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong.
TArray<FTypeAndOffset> SpecialInits; // list of all contents on the extra stack which require construction and destruction
void InitExtra(void *addr);
void DestroyExtra(void *addr);
void SetExtraSpecial(PType *type, unsigned offset);
int AllocExtraStack(PType *type);
}; };
class VMFrameStack class VMFrameStack
@ -822,7 +827,6 @@ class VMFrameStack
public: public:
VMFrameStack(); VMFrameStack();
~VMFrameStack(); ~VMFrameStack();
VMFrame *AllocFrame(int numregd, int numregf, int numregs, int numrega);
VMFrame *AllocFrame(VMScriptFunction *func); VMFrame *AllocFrame(VMScriptFunction *func);
VMFrame *PopFrame(); VMFrame *PopFrame();
VMFrame *TopFrame() VMFrame *TopFrame()

View file

@ -1,7 +1,7 @@
#ifndef VMUTIL_H #ifndef VMUTIL_H
#define VMUTIL_H #define VMUTIL_H
#include "vm.h" #include "dobject.h"
class VMFunctionBuilder class VMFunctionBuilder
{ {

View file

@ -31,7 +31,7 @@
** **
*/ */
#include "vm.h" #include "dobject.h"
#include "c_console.h" #include "c_console.h"
#include "templates.h" #include "templates.h"

View file

@ -34,7 +34,7 @@
#include <math.h> #include <math.h>
#include <v_video.h> #include <v_video.h>
#include <s_sound.h> #include <s_sound.h>
#include "vm.h" #include "dobject.h"
#include "xs_Float.h" #include "xs_Float.h"
#include "math/cmath.h" #include "math/cmath.h"

View file

@ -32,7 +32,7 @@
*/ */
#include <new> #include <new>
#include "vm.h" #include "dobject.h"
IMPLEMENT_CLASS(VMException, false, false, false, false) IMPLEMENT_CLASS(VMException, false, false, false, false)
IMPLEMENT_CLASS(VMFunction, true, true, false, false) IMPLEMENT_CLASS(VMFunction, true, true, false, false)
@ -162,6 +162,38 @@ size_t VMScriptFunction::PropagateMark()
return NumKonstA * sizeof(void *) + Super::PropagateMark(); return NumKonstA * sizeof(void *) + Super::PropagateMark();
} }
void VMScriptFunction::InitExtra(void *addr)
{
char *caddr = (char*)addr;
for (auto tao : SpecialInits)
{
tao.first->InitializeValue(caddr + tao.second, nullptr);
}
}
void VMScriptFunction::DestroyExtra(void *addr)
{
char *caddr = (char*)addr;
for (auto tao : SpecialInits)
{
tao.first->DestroyValue(caddr + tao.second);
}
}
void VMScriptFunction::SetExtraSpecial(PType *type, unsigned offset)
{
type->SetDefaultValue(nullptr, offset, &SpecialInits);
}
int VMScriptFunction::AllocExtraStack(PType *type)
{
int address = ((ExtraSpace + type->Align - 1) / type->Align) * type->Align;
ExtraSpace = address + type->Size;
return address;
}
//=========================================================================== //===========================================================================
// //
// VMFrame :: InitRegS // VMFrame :: InitRegS
@ -223,34 +255,6 @@ VMFrameStack::~VMFrameStack()
UnusedBlocks = NULL; UnusedBlocks = NULL;
} }
//===========================================================================
//
// VMFrameStack :: AllocFrame
//
// Allocates a frame from the stack with the desired number of registers.
//
//===========================================================================
VMFrame *VMFrameStack::AllocFrame(int numregd, int numregf, int numregs, int numrega)
{
assert((unsigned)numregd < 255);
assert((unsigned)numregf < 255);
assert((unsigned)numregs < 255);
assert((unsigned)numrega < 255);
// To keep the arguments to this function simpler, it assumes that every
// register might be used as a parameter for a single call.
int numparam = numregd + numregf + numregs + numrega;
int size = VMFrame::FrameSize(numregd, numregf, numregs, numrega, numparam, 0);
VMFrame *frame = Alloc(size);
frame->NumRegD = numregd;
frame->NumRegF = numregf;
frame->NumRegS = numregs;
frame->NumRegA = numrega;
frame->MaxParam = numparam;
frame->InitRegS();
return frame;
}
//=========================================================================== //===========================================================================
// //
// VMFrameStack :: AllocFrame // VMFrameStack :: AllocFrame
@ -273,6 +277,10 @@ VMFrame *VMFrameStack::AllocFrame(VMScriptFunction *func)
frame->MaxParam = func->MaxParam; frame->MaxParam = func->MaxParam;
frame->Func = func; frame->Func = func;
frame->InitRegS(); frame->InitRegS();
if (func->SpecialInits.Size())
{
func->InitExtra(frame->GetExtra());
}
return frame; return frame;
} }
@ -358,6 +366,11 @@ VMFrame *VMFrameStack::PopFrame()
{ {
return NULL; return NULL;
} }
auto Func = static_cast<VMScriptFunction *>(frame->Func);
if (Func->SpecialInits.Size())
{
Func->DestroyExtra(frame->GetExtra());
}
// Free any string registers this frame had. // Free any string registers this frame had.
FString *regs = frame->GetRegS(); FString *regs = frame->GetRegS();
for (int i = frame->NumRegS; i != 0; --i) for (int i = frame->NumRegS; i != 0; --i)