From 74c5f836582d4cdee925bc7235a8bc5c05c879c1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Apr 2020 19:24:28 +0200 Subject: [PATCH] - moved most of the root marking out of the garbage collector, replacing it with callbacks. Yet another place where low level code was tied too tightly to the game instead of providing a proper interface. --- src/common/objects/dobjgc.cpp | 41 +++++++---------------------- src/common/objects/dobjgc.h | 4 +++ src/common/scripting/core/types.cpp | 2 +- src/d_main.cpp | 22 ++++++++++++++++ src/g_statusbar/shared_sbar.cpp | 1 + src/menu/menu.cpp | 1 + 6 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp index de4614664..40b29a680 100644 --- a/src/common/objects/dobjgc.cpp +++ b/src/common/objects/dobjgc.cpp @@ -58,21 +58,9 @@ #include "dobject.h" #include "templates.h" -#include "b_bot.h" -#include "p_local.h" -#include "g_game.h" -#include "a_sharedglobal.h" -#include "sbar.h" #include "c_dispatch.h" -#include "s_sndseq.h" -#include "r_data/r_interpolate.h" -#include "doomstat.h" -#include "po_man.h" -#include "r_utility.h" #include "menu/menu.h" -#include "intermission/intermission.h" -#include "g_levellocals.h" -#include "events.h" +#include "stats.h" // MACROS ------------------------------------------------------------------ @@ -112,8 +100,6 @@ // EXTERNAL DATA DECLARATIONS ---------------------------------------------- -extern DThinker *NextToThink; - // PUBLIC DATA DEFINITIONS ------------------------------------------------- namespace GC @@ -274,26 +260,19 @@ void MarkArray(DObject **obj, size_t count) // //========================================================================== +TArray markers; +void AddMarkerFunc(GCMarkerFunc func) +{ + if (markers.Find(func) == markers.Size()) + markers.Push(func); +} + static void MarkRoot() { Gray = NULL; - Mark(StatusBar); - M_MarkMenus(); - Mark(DIntermissionController::CurrentIntermission); - Mark(staticEventManager.FirstEventHandler); - Mark(staticEventManager.LastEventHandler); - for (auto Level : AllLevels()) - Level->Mark(); - // Mark players. - for (int i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - players[i].PropagateMark(); - } - - // NextToThink must not be freed while thinkers are ticking. - Mark(NextToThink); + for (auto func : markers) func(); + // Mark soft roots. if (SoftRoots != NULL) { diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index 5a181c736..de187db6c 100644 --- a/src/common/objects/dobjgc.h +++ b/src/common/objects/dobjgc.h @@ -154,6 +154,10 @@ namespace GC { MarkArray(&arr[0], arr.Size()); } + + using GCMarkerFunc = void(*)(); + void AddMarkerFunc(GCMarkerFunc func); + } // A template class to help with handling read barriers. It does not diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index 5211bc956..d06c08250 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -1115,7 +1115,7 @@ void PSpriteID::WriteValue(FSerializer &ar, const char *key, const void *addr) c bool PSpriteID::ReadValue(FSerializer &ar, const char *key, void *addr) const { - int32_t val; + int32_t val = 0; #ifdef GZDOOM ar.Sprite(key, val, nullptr); #endif diff --git a/src/d_main.cpp b/src/d_main.cpp index 69301e295..ee515f689 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2748,6 +2748,27 @@ static void Doom_CastSpriteIDToString(FString* a, unsigned int b) *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; } + +extern DThinker* NextToThink; + +static void GC_MarkGameRoots() +{ + GC::Mark(DIntermissionController::CurrentIntermission); + GC::Mark(staticEventManager.FirstEventHandler); + GC::Mark(staticEventManager.LastEventHandler); + for (auto Level : AllLevels()) + Level->Mark(); + + // Mark players. + for (int i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + players[i].PropagateMark(); + } + + // NextToThink must not be freed while thinkers are ticking. + GC::Mark(NextToThink); +} //========================================================================== // // D_DoomMain @@ -2764,6 +2785,7 @@ static int D_DoomMain_Internal (void) int argcount; FIWadManager *iwad_man; + GC::AddMarkerFunc(GC_MarkGameRoots); VM_CastSpriteIDToString = Doom_CastSpriteIDToString; // Set up the button list. Mlook and Klook need a bit of extra treatment. diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index e294c716a..a8487c349 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -259,6 +259,7 @@ void ST_CreateStatusBar(bool bTitleLevel) StatusBar->Destroy(); StatusBar = NULL; } + GC::AddMarkerFunc([]() { GC::Mark(StatusBar); }); bool shouldWarn = true; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 5f354d934..13cb0d956 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -952,6 +952,7 @@ void M_Init (void) try { M_ParseMenuDefs(); + GC::AddMarkerFunc(M_MarkMenus); } catch (CVMAbortException &err) {