Skip to content

Commit

Permalink
Collect unused GOBs
Browse files Browse the repository at this point in the history
Resolving bug#1989.
Define new GOB_MARK and GOB_USED GC flags.
Use the resv field to store GC flags.
  • Loading branch information
ladislav committed Mar 28, 2013
1 parent f5097f1 commit 42653da
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 1 deletion.
49 changes: 48 additions & 1 deletion src/core/m-gc.c
Expand Up @@ -115,7 +115,11 @@ static void Mark_Series(REBSER *series, REBCNT depth);
REBGOB **pane;
REBCNT i;

if (GOB_PANE(gob) && !IS_MARK_SERIES(GOB_PANE(gob))) {
if (IS_GOB_MARK(gob)) return;

MARK_GOB(gob);

if (GOB_PANE(gob)) {
MARK_SERIES(GOB_PANE(gob));
pane = GOB_HEAD(gob);
for (i = 0; i < GOB_TAIL(gob); i++, pane++) {
Expand Down Expand Up @@ -407,6 +411,48 @@ static void Mark_Series(REBSER *series, REBCNT depth);
}


/***********************************************************************
**
*/ static REBCNT Sweep_Gobs(void)
/*
** Free all unmarked gobs.
**
** Scans all gobs in all segments that are part of the
** GOB_POOL. Free gobs that have not been marked.
**
***********************************************************************/
{
REBSEG *seg;
REBGOB *gob;
REBCNT n;
REBCNT count = 0;

for (seg = Mem_Pools[GOB_POOL].segs; seg; seg = seg->next) {
gob = (REBGOB *) (seg + 1);
for (n = Mem_Pools[GOB_POOL].units; n > 0; n--) {
#ifdef MUNGWALL
gob = (gob *) (((REBYTE *)s)+MUNG_SIZE);
MUNG_CHECK(GOB_POOL, gob, sizeof(*gob));
#endif
if (IS_GOB_USED(gob)) {
if (IS_GOB_MARK(gob))
UNMARK_GOB(gob);
else {
Free_Gob(gob);
count++;
}
}
gob++;
#ifdef MUNGWALL
gob = (gob *) (((REBYTE *)s)+MUNG_SIZE);
#endif
}
}

return count;
}


/***********************************************************************
**
*/ REBCNT Recycle(void)
Expand Down Expand Up @@ -475,6 +521,7 @@ static void Mark_Series(REBSER *series, REBCNT depth);
Mark_Series(Task_Series, 0);

count = Sweep_Series();
count += Sweep_Gobs();

CHECK_MEMORY(4);

Expand Down
14 changes: 14 additions & 0 deletions src/core/m-pools.c
Expand Up @@ -536,6 +536,20 @@ const REBPOOLSPEC Mem_Pool_Spec[MAX_POOLS] =
}


/***********************************************************************
**
*/ void Free_Gob(REBGOB *gob)
/*
** Free a gob, returning its memory for reuse.
**
***********************************************************************/
{
FREE_GOB(gob);

Free_Node(GOB_POOL, (REBNOD *)gob);
}


/***********************************************************************
**
*/ void Prop_Series(REBSER *newser, REBSER *oldser)
Expand Down
2 changes: 2 additions & 0 deletions src/core/t-gob.c
Expand Up @@ -68,6 +68,8 @@ const REBCNT Gob_Flag_Words[] = {
CLEAR(gob, sizeof(REBGOB));
GOB_W(gob) = 100;
GOB_H(gob) = 100;
USE_GOB(gob);
if ((GC_Ballast -= Mem_Pools[GOB_POOL].wide) <= 0) SET_SIGNAL(SIG_RECYCLE);
return gob;
}

Expand Down
13 changes: 13 additions & 0 deletions src/include/reb-gob.h
Expand Up @@ -174,4 +174,17 @@ struct rebol_gob { // size: 64 bytes!
#define IS_GOB_STRING(g) (GOB_CONTENT(g) && GOB_TYPE(g) == GOBT_STRING)
#define IS_GOB_TEXT(g) (GOB_CONTENT(g) && GOB_TYPE(g) == GOBT_TEXT)

// GC Flags:
enum {
GOB_MARK = 1, // Gob was found during GC mark scan.
GOB_USED = 1<<1 // Gob is used (not free).
};

#define IS_GOB_MARK(g) ((g)->resv & GOB_MARK)
#define MARK_GOB(g) ((g)->resv |= GOB_MARK)
#define UNMARK_GOB(g) ((g)->resv &= ~GOB_MARK)
#define IS_GOB_USED(g) ((g)->resv & GOB_USED)
#define USE_GOB(g) ((g)->resv |= GOB_USED)
#define FREE_GOB(g) ((g)->resv &= ~GOB_USED)

extern REBGOB *Gob_Root; // Top level GOB (the screen)

0 comments on commit 42653da

Please sign in to comment.