diff --git a/src/d_think.h b/src/d_think.h index efc1589bf..589124587 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -51,6 +51,7 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; + boolean cachable; #ifdef PARANOIA INT32 debug_mobjtype; diff --git a/src/p_local.h b/src/p_local.h index c26c09860..70eb3435e 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -71,6 +71,7 @@ typedef enum NUM_THINKERLISTS } thinklistnum_t; /**< Thinker lists. */ extern thinker_t thlist[]; +extern mobj_t *mobjcache; void P_InitThinkers(void); void P_AddThinker(const thinklistnum_t n, thinker_t *thinker); diff --git a/src/p_mobj.c b/src/p_mobj.c index 7a5aaf424..f424fba06 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -45,6 +45,8 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; +mobj_t *mobjcache = NULL; + void P_InitCachedActions(void) { actioncachehead.prev = actioncachehead.next = &actioncachehead; @@ -10659,7 +10661,16 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) type = MT_RAY; } - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + if (mobjcache != NULL) + { + mobj = mobjcache; + mobjcache = mobjcache->hnext; + memset(mobj, 0, sizeof(*mobj)); + } + else + { + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + } // this is officially a mobj, declared as soon as possible. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -11214,7 +11225,9 @@ void P_RemoveMobj(mobj_t *mobj) INT32 prevreferences; if (!mobj->thinker.references) { - Z_Free(mobj); // No refrrences? Can be removed immediately! :D + // no references, dump it directly in the mobj cache + mobj->hnext = mobjcache; + mobjcache = mobj; return; } diff --git a/src/p_setup.c b/src/p_setup.c index 7f6fcd36c..ab6b68bd1 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7806,6 +7806,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) Patch_FreeTag(PU_PATCH_LOWPRIORITY); Patch_FreeTag(PU_PATCH_ROTATED); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + mobjcache = NULL; R_InitializeLevelInterpolators(); diff --git a/src/p_tick.c b/src/p_tick.c index 444b68d2f..c19f901e3 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -217,6 +217,7 @@ void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) thlist[n].prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 + thinker->cachable = n == THINK_MOBJ; #ifdef PARANOIA thinker->debug_mobjtype = MT_NULL; @@ -319,7 +320,16 @@ void P_RemoveThinkerDelayed(thinker_t *thinker) (next->prev = currentthinker = thinker->prev)->next = next; R_DestroyLevelInterpolators(thinker); - Z_Free(thinker); + if (thinker->cachable) + { + // put cachable thinkers in the mobj cache, so we can avoid allocations + ((mobj_t *)thinker)->hnext = mobjcache; + mobjcache = (mobj_t *)thinker; + } + else + { + Z_Free(thinker); + } } //