windows-nt/Source/XPSP1/NT/sdktools/m4/gc.c
2020-09-26 16:20:57 +08:00

180 lines
3.8 KiB
C

/*****************************************************************************
*
* gc.c
*
* The garbage-collector.
*
*****************************************************************************/
#include "m4.h"
#ifndef Gc
/*****************************************************************************
*
* WalkPv
*
* Mark an arbitrary object.
*
*****************************************************************************/
void STDCALL
WalkPv(PVOID pv)
{
if (pv) {
PAR par = parPv(pv);
Assert(par->tm == g_tmNow - 1);
par->tm = g_tmNow;
AssertPar(par); /* This catches double-references */
}
}
/*****************************************************************************
*
* WalkPtok
*
* Walk a token. The token itself is not walked, but its contents are.
* (Because tokens are typically embedded inside other objects.)
*
*****************************************************************************/
void STDCALL
WalkPtok(PTOK ptok)
{
if (ptok) {
if (!fStaticPtok(ptok)) {
Assert(fHeapPtok(ptok));
WalkPv(ptchPtok(ptok));
}
}
}
/*****************************************************************************
*
* WalkPval
*
* Walk a value.
*
*****************************************************************************/
void STDCALL
WalkPval(PVAL pval)
{
if (pval) {
WalkPv(pval);
WalkPtok(&pval->tok);
}
}
/*****************************************************************************
*
* WalkPmac
*
* Walk a macro.
*
*****************************************************************************/
void STDCALL
WalkPmac(PMAC pmac)
{
if (pmac) {
PVAL pval;
WalkPv(pmac);
WalkPtok(&pmac->tokName);
for (pval = pmac->pval; pval; pval = pval->pvalPrev) {
WalkPval(pval);
}
}
}
/*****************************************************************************
*
* WalkPstm
*
* Walk a stream.
*
* The compiler knows how to optimize tail recursion.
*
*****************************************************************************/
void STDCALL
WalkPstm(PSTM pstm)
{
if (pstm) {
WalkPv(pstm);
WalkPv(pstm->ptchMin);
WalkPv(pstm->ptchName);
WalkPstm(pstm->pstmNext);
}
}
/*****************************************************************************
*
* WalkPdiv
*
* Walk a diversion.
*
*****************************************************************************/
void STDCALL
WalkPdiv(PDIV pdiv)
{
if (pdiv) {
WalkPv(pdiv);
WalkPv(pdiv->ptchMin);
WalkPv(pdiv->ptchName);
}
}
/*****************************************************************************
*
* Sweep
*
* Sweep through memory, looking for garbage.
*
*****************************************************************************/
void STDCALL
Sweep(void)
{
PAR par;
for (par = parHead->parNext; par != parHead; par = par->parNext) {
Assert(par->tm == g_tmNow); /* Memory should have been walked! */
}
}
/*****************************************************************************
*
* Gc
*
* The garbage collector is mark-and-sweep.
*
* Walk all the root objects, recursing into sub-objects, until everything
* is marked with the current (fake) timestamp. Then walk through the
* memory arenas. Anything not marked with the current timestamp is garbage.
*
*****************************************************************************/
TM g_tmNow;
void STDCALL
Gc(void)
{
g_tmNow++;
if (mphashpmac) {
WalkPv(mphashpmac);
EachMacroOp(WalkPmac);
}
WalkPv(rgtokArgv);
WalkPv(rgcellEstack);
WalkPstm(g_pstmCur);
WalkPdiv(g_pdivArg);
WalkPdiv(g_pdivExp);
WalkPdiv(g_pdivOut);
WalkPdiv(g_pdivErr);
WalkPdiv(g_pdivNul);
Sweep();
}
#endif