From d86f03e2e00bce5f95b87ce77b393891ef3993fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Nov 2016 13:10:19 +0100 Subject: [PATCH] - 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. --- src/d_dehacked.cpp | 1 - src/d_main.cpp | 1 - src/dobjgc.cpp | 1 - src/dobjtype.cpp | 147 ------------------------------- src/dobjtype.h | 28 +----- src/g_doom/a_doommisc.cpp | 2 - src/g_heretic/a_hereticmisc.cpp | 2 - src/g_hexen/a_hexenmisc.cpp | 2 - src/g_shared/a_action.cpp | 1 - src/g_shared/a_bridge.cpp | 1 - src/g_shared/a_pickups.cpp | 1 - src/g_shared/a_randomspawner.cpp | 1 - src/g_shared/a_specialspot.cpp | 1 - src/g_shared/a_weapons.cpp | 1 - src/info.cpp | 2 - src/info.h | 1 - src/p_actionfunctions.cpp | 2 - src/p_enemy.cpp | 2 - src/p_enemy.h | 2 +- src/p_mobj.cpp | 1 - src/p_pspr.cpp | 1 - src/p_pspr.h | 1 - src/p_states.cpp | 1 - src/p_user.cpp | 1 - src/scripting/thingdef.h | 1 - src/scripting/vm/vm.h | 8 +- src/scripting/vm/vmbuilder.h | 2 +- src/scripting/vm/vmdisasm.cpp | 2 +- src/scripting/vm/vmexec.cpp | 2 +- src/scripting/vm/vmframe.cpp | 71 +++++++++------ 30 files changed, 55 insertions(+), 235 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index d0addb095..8d3a13580 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -70,7 +70,6 @@ #include "doomerrors.h" #include "p_effect.h" #include "serializer.h" -#include "vm.h" #include "thingdef.h" #include "info.h" #include "v_text.h" diff --git a/src/d_main.cpp b/src/d_main.cpp index d7757ddf4..dad2b86d9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -109,7 +109,6 @@ #include "p_local.h" #include "autosegs.h" #include "fragglescript/t_fs.h" -#include "vm.h" EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index fa8723e90..40ef7b784 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -77,7 +77,6 @@ #include "r_utility.h" #include "menu/menu.h" #include "intermission/intermission.h" -#include "vm.h" // MACROS ------------------------------------------------------------------ diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index b9d518abf..1597494d9 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -1869,39 +1869,6 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray } } -//========================================================================== -// -// 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 @@ -1985,28 +1952,6 @@ void PDynArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const 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 @@ -2091,28 +2036,6 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const 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 @@ -2335,76 +2258,6 @@ size_t PStruct::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(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 diff --git a/src/dobjtype.h b/src/dobjtype.h index dcf316fec..0062c56ab 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -5,10 +5,10 @@ #error You must #include "dobject.h" to get dobjtype.h #endif -#include "vm.h" - typedef std::pair FTypeAndOffset; +#include "vm.h" + // Variable/parameter/field flags ------------------------------------------- // 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) 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) virtual void DestroyValue(void *addr) const; @@ -492,7 +489,6 @@ public: void SetDefaultValue(void *base, unsigned offset, TArray *special=NULL) const override; void InitializeValue(void *addr, const void *def) const override; void DestroyValue(void *addr) const override; - virtual bool RequireConstruction() const override { return true; } }; // Variations of integer types ---------------------------------------------- @@ -630,9 +626,6 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *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: PArray(); @@ -649,9 +642,6 @@ public: virtual bool IsMatch(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: PDynArray(); }; @@ -668,9 +658,6 @@ public: virtual bool IsMatch(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: PMap(); }; @@ -678,10 +665,6 @@ protected: class PStruct : public PNamedType { DECLARE_CLASS(PStruct, PNamedType); - -protected: - TArray SpecialInits; - public: PStruct(FName name, PTypeBase *outer); @@ -699,12 +682,6 @@ public: static void WriteFields(FSerializer &ar, const void *addr, const TArray &fields); 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: PStruct(); }; @@ -771,6 +748,7 @@ class PClass : public PStruct protected: // We unravel _WITH_META here just as we did for PType. enum { MetaClassNum = CLASSREG_PClassClass }; + TArray SpecialInits; void Derive(PClass *newclass, FName name); void InitializeSpecials(void *addr) const; void SetSuper(); diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index eabf887f0..30fd6c671 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -7,7 +7,6 @@ #include "gi.h" #include "doomstat.h" #include "gstrings.h" -#include "vm.h" #include "g_level.h" #include "p_enemy.h" #include "a_doomglobal.h" @@ -19,7 +18,6 @@ #include "p_maputl.h" #include "serializer.h" #include "g_shared/a_pickups.h" -#include "vm.h" // Include all the other Doom stuff here to reduce compile time #include "a_bossbrain.cpp" diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 6af969842..17cd4df09 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -6,7 +6,6 @@ #include "p_local.h" #include "s_sound.h" #include "gstrings.h" -#include "vm.h" #include "p_enemy.h" #include "a_specialspot.h" #include "g_level.h" @@ -18,7 +17,6 @@ #include "a_morph.h" #include "p_spec.h" #include "serializer.h" -#include "vm.h" // Include all the other Heretic stuff here to reduce compile time #include "a_chicken.cpp" diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 21227e848..c87c9e46d 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -7,7 +7,6 @@ #include "a_sharedglobal.h" #include "a_hexenglobal.h" #include "i_system.h" -#include "vm.h" #include "gi.h" #include "g_level.h" #include "p_enemy.h" @@ -24,7 +23,6 @@ #include "p_maputl.h" #include "p_spec.h" #include "serializer.h" -#include "vm.h" // Include all the Hexen stuff here to reduce compile time #include "a_blastradius.cpp" diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index edd97a6d4..a371e4ad5 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -1,5 +1,4 @@ #include "actor.h" -#include "vm.h" #include "p_conversation.h" #include "p_lnspec.h" #include "a_action.h" diff --git a/src/g_shared/a_bridge.cpp b/src/g_shared/a_bridge.cpp index 8ce23b68e..c4b452f77 100644 --- a/src/g_shared/a_bridge.cpp +++ b/src/g_shared/a_bridge.cpp @@ -2,7 +2,6 @@ #include "info.h" #include "gi.h" #include "m_random.h" -#include "vm.h" static FRandom pr_orbit ("Orbit"); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 223a2f75f..fbc5ea509 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -14,7 +14,6 @@ #include "a_strifeglobal.h" #include "a_morph.h" #include "a_specialspot.h" -#include "vm.h" #include "g_level.h" #include "g_game.h" #include "doomstat.h" diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index 2b2c82956..40fdd0745 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -14,7 +14,6 @@ #include "statnums.h" #include "gstrings.h" #include "a_action.h" -#include "vm.h" #include "v_text.h" #include "doomstat.h" #include "doomdata.h" diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 92306ce6b..c094ee8ba 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -37,7 +37,6 @@ #include "p_local.h" #include "statnums.h" #include "i_system.h" -#include "vm.h" #include "doomstat.h" #include "serializer.h" #include "a_pickups.h" diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 2d159eb7d..4a947cbee 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -13,7 +13,6 @@ #include "cmdlib.h" #include "templates.h" #include "sbar.h" -#include "vm.h" #include "doomstat.h" #include "g_level.h" #include "d_net.h" diff --git a/src/info.cpp b/src/info.cpp index e771108c3..8ef594d1b 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -43,7 +43,6 @@ #include "v_text.h" #include "gi.h" -#include "vm.h" #include "actor.h" #include "r_state.h" #include "i_system.h" @@ -52,7 +51,6 @@ #include "cmdlib.h" #include "g_level.h" #include "stats.h" -#include "vm.h" #include "thingdef.h" #include "d_player.h" #include "doomerrors.h" diff --git a/src/info.h b/src/info.h index 0b7d4dfc3..5af51f34b 100644 --- a/src/info.h +++ b/src/info.h @@ -43,7 +43,6 @@ #include "dobject.h" #include "doomdef.h" -#include "vm.h" #include "s_sound.h" #include "m_fixed.h" diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 2d219fc38..37a2d533e 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -61,7 +61,6 @@ #include "c_console.h" #include "doomerrors.h" #include "a_sharedglobal.h" -#include "vm.h" #include "v_video.h" #include "v_font.h" #include "doomstat.h" @@ -77,7 +76,6 @@ #include "p_maputl.h" #include "p_spec.h" #include "templates.h" -#include "vm.h" #include "v_text.h" #include "thingdef.h" #include "math/cmath.h" diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 6bb96ef30..db237e8bb 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -43,7 +43,6 @@ #include "p_enemy.h" #include "a_sharedglobal.h" #include "a_action.h" -#include "vm.h" #include "d_dehacked.h" #include "g_level.h" #include "r_utility.h" @@ -53,7 +52,6 @@ #include "p_spec.h" #include "p_checkposition.h" #include "math/cmath.h" -#include "vm.h" #include "gi.h" diff --git a/src/p_enemy.h b/src/p_enemy.h index c4a966344..a9aa40dc2 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -1,7 +1,7 @@ #ifndef __P_ENEMY_H__ #define __P_ENEMY_H__ -#include "vm.h" +#include "dobject.h" #include "vectors.h" struct sector_t; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9c36e861c..02c2a3578 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -53,7 +53,6 @@ #include "a_action.h" #include "a_keys.h" #include "p_conversation.h" -#include "vm.h" #include "g_game.h" #include "teaminfo.h" #include "r_data/r_translate.h" diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 5a76f0b55..1ba452b2b 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -25,7 +25,6 @@ #include "gi.h" #include "p_pspr.h" #include "templates.h" -#include "vm.h" #include "g_level.h" #include "d_player.h" #include "serializer.h" diff --git a/src/p_pspr.h b/src/p_pspr.h index 3f819714c..d75f08b06 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -25,7 +25,6 @@ // Basic data types. // Needs fixed point, and BAM angles. -//#include "vm.h" #define WEAPONBOTTOM 128. diff --git a/src/p_states.cpp b/src/p_states.cpp index ac7121f49..a49d30af2 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -39,7 +39,6 @@ #include "i_system.h" #include "c_dispatch.h" #include "v_text.h" -#include "vm.h" #include "thingdef.h" // stores indices for symbolic state labels for some old-style DECORATE functions. diff --git a/src/p_user.cpp b/src/p_user.cpp index 8c8858b63..11fe487b9 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -48,7 +48,6 @@ #include "doomdef.h" #include "c_dispatch.h" #include "tarray.h" -#include "vm.h" #include "g_level.h" #include "d_net.h" #include "gstrings.h" diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 5992dba04..a2c224558 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -6,7 +6,6 @@ #include "s_sound.h" #include "sc_man.h" #include "cmdlib.h" -#include "vm.h" class FScanner; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index ae867a975..d82411d51 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -2,7 +2,6 @@ #define VM_H #include "zstring.h" -#include "dobject.h" #include "autosegs.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_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. + TArray 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 @@ -822,7 +827,6 @@ class VMFrameStack public: VMFrameStack(); ~VMFrameStack(); - VMFrame *AllocFrame(int numregd, int numregf, int numregs, int numrega); VMFrame *AllocFrame(VMScriptFunction *func); VMFrame *PopFrame(); VMFrame *TopFrame() diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 5394dec32..a5013dc57 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -1,7 +1,7 @@ #ifndef VMUTIL_H #define VMUTIL_H -#include "vm.h" +#include "dobject.h" class VMFunctionBuilder { diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index 49c929f05..48b6d168b 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -31,7 +31,7 @@ ** */ -#include "vm.h" +#include "dobject.h" #include "c_console.h" #include "templates.h" diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 57ce48a95..8f8559d93 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -34,7 +34,7 @@ #include #include #include -#include "vm.h" +#include "dobject.h" #include "xs_Float.h" #include "math/cmath.h" diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 3a593861c..e5a302606 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -32,7 +32,7 @@ */ #include -#include "vm.h" +#include "dobject.h" IMPLEMENT_CLASS(VMException, false, false, false, false) IMPLEMENT_CLASS(VMFunction, true, true, false, false) @@ -162,6 +162,38 @@ size_t VMScriptFunction::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 @@ -223,34 +255,6 @@ VMFrameStack::~VMFrameStack() 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 @@ -273,6 +277,10 @@ VMFrame *VMFrameStack::AllocFrame(VMScriptFunction *func) frame->MaxParam = func->MaxParam; frame->Func = func; frame->InitRegS(); + if (func->SpecialInits.Size()) + { + func->InitExtra(frame->GetExtra()); + } return frame; } @@ -358,6 +366,11 @@ VMFrame *VMFrameStack::PopFrame() { return NULL; } + auto Func = static_cast(frame->Func); + if (Func->SpecialInits.Size()) + { + Func->DestroyExtra(frame->GetExtra()); + } // Free any string registers this frame had. FString *regs = frame->GetRegS(); for (int i = frame->NumRegS; i != 0; --i)