- fixed: the restart CCMD must clear out all statically stored pointers to VM functions because they do not survive the shutdown that is needed before loading new data.

This commit is contained in:
Christoph Oelckers 2017-01-31 13:41:23 +01:00
parent f0a325a904
commit 3131c08640
6 changed files with 25 additions and 6 deletions

View file

@ -69,6 +69,7 @@ FNamespaceManager Namespaces;
FTypeTable TypeTable; FTypeTable TypeTable;
TArray<PClass *> PClass::AllClasses; TArray<PClass *> PClass::AllClasses;
TArray<VMFunction**> PClass::FunctionPtrList;
bool PClass::bShutdown; bool PClass::bShutdown;
bool PClass::bVMOperational; bool PClass::bVMOperational;
@ -2840,6 +2841,12 @@ void PClass::StaticShutdown ()
TArray<size_t *> uniqueFPs(64); TArray<size_t *> uniqueFPs(64);
unsigned int i, j; unsigned int i, j;
// delete all variables containing pointers to script functions.
for (auto p : FunctionPtrList)
{
*p = nullptr;
}
FunctionPtrList.Clear();
// Make a full garbage collection here so that all destroyed but uncollected higher level objects that still exist can be properly taken down. // Make a full garbage collection here so that all destroyed but uncollected higher level objects that still exist can be properly taken down.
GC::FullGC(); GC::FullGC();
@ -3547,6 +3554,16 @@ VMFunction *PClass::FindFunction(FName clsname, FName funcname)
return func->Variants[0].Implementation; return func->Variants[0].Implementation;
} }
void PClass::FindFunction(VMFunction **pptr, FName clsname, FName funcname)
{
auto cls = PClass::FindActor(clsname);
if (!cls) return;
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol(funcname, true));
if (!func) return;
*pptr = func->Variants[0].Implementation;
FunctionPtrList.Push(pptr);
}
/* FTypeTable **************************************************************/ /* FTypeTable **************************************************************/

View file

@ -848,9 +848,11 @@ public:
static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); } static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); }
static PClassActor *FindActor(FName name); static PClassActor *FindActor(FName name);
static VMFunction *FindFunction(FName cls, FName func); static VMFunction *FindFunction(FName cls, FName func);
static void FindFunction(VMFunction **pptr, FName cls, FName func);
PClass *FindClassTentative(FName name); PClass *FindClassTentative(FName name);
static TArray<PClass *> AllClasses; static TArray<PClass *> AllClasses;
static TArray<VMFunction**> FunctionPtrList;
static bool bShutdown; static bool bShutdown;
static bool bVMOperational; static bool bVMOperational;

View file

@ -522,7 +522,7 @@ DEFINE_ACTION_FUNCTION(AInventory, DoRespawn)
bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return) bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return)
{ {
static VMFunction *func = nullptr; static VMFunction *func = nullptr;
if (func == nullptr) func = PClass::FindFunction(NAME_Inventory, NAME_CallTryPickup); if (func == nullptr) PClass::FindFunction(&func, NAME_Inventory, NAME_CallTryPickup);
VMValue params[2] = { (DObject*)this, toucher }; VMValue params[2] = { (DObject*)this, toucher };
VMReturn ret[2]; VMReturn ret[2];
int res; int res;

View file

@ -1437,7 +1437,7 @@ class CommandDrawNumber : public CommandDrawString
{ {
// num = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem) / TICRATE + 1; // num = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem) / TICRATE + 1;
static VMFunction *func = nullptr; static VMFunction *func = nullptr;
if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem"); if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem");
VMValue params[] = { statusBar->CPlayer->mo, inventoryItem }; VMValue params[] = { statusBar->CPlayer->mo, inventoryItem };
int retv; int retv;
VMReturn ret(&retv); VMReturn ret(&retv);
@ -2830,7 +2830,7 @@ class CommandDrawBar : public SBarInfoCommand
// [value, max] = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem); // [value, max] = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem);
// value++; max++; // value++; max++;
static VMFunction *func = nullptr; static VMFunction *func = nullptr;
if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem"); if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem");
VMValue params[] = { statusBar->CPlayer->mo, data.inventoryItem }; VMValue params[] = { statusBar->CPlayer->mo, data.inventoryItem };
VMReturn ret[2]; VMReturn ret[2];
int ival; int ival;

View file

@ -478,7 +478,7 @@ void cht_DoCheat (player_t *player, int cheat)
if (player->mo != NULL && player->health >= 0) if (player->mo != NULL && player->health >= 0)
{ {
static VMFunction *gsp = nullptr; static VMFunction *gsp = nullptr;
if (gsp == nullptr) gsp = PClass::FindFunction(NAME_Sigil, NAME_GiveSigilPiece); if (gsp == nullptr) PClass::FindFunction(&gsp, NAME_Sigil, NAME_GiveSigilPiece);
if (gsp) if (gsp)
{ {
VMValue params[1] = { player->mo }; VMValue params[1] = { player->mo };

View file

@ -6203,7 +6203,7 @@ static bool CharArrayParms(int &capacity, int &offset, int &a, int *Stack, int &
static void SetMarineWeapon(AActor *marine, int weapon) static void SetMarineWeapon(AActor *marine, int weapon)
{ {
static VMFunction *smw = nullptr; static VMFunction *smw = nullptr;
if (smw == nullptr) smw = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetWeapon); if (smw == nullptr) PClass::FindFunction(&smw, NAME_ScriptedMarine, NAME_SetWeapon);
if (smw) if (smw)
{ {
VMValue params[2] = { marine, weapon }; VMValue params[2] = { marine, weapon };
@ -6214,7 +6214,7 @@ static void SetMarineWeapon(AActor *marine, int weapon)
static void SetMarineSprite(AActor *marine, PClassActor *source) static void SetMarineSprite(AActor *marine, PClassActor *source)
{ {
static VMFunction *sms = nullptr; static VMFunction *sms = nullptr;
if (sms == nullptr) sms = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetSprite); if (sms == nullptr) PClass::FindFunction(&sms, NAME_ScriptedMarine, NAME_SetSprite);
if (sms) if (sms)
{ {
VMValue params[2] = { marine, source }; VMValue params[2] = { marine, source };