1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-01 01:41:01 -08:00

Merging branch/2016-04-21/ld-history into master sources.

Copied from Perforce
 Change: 191447
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Brooksby 2016-04-21 13:07:10 +01:00
commit 4db81ddfa0
6 changed files with 139 additions and 56 deletions

View file

@ -107,8 +107,6 @@ Bool GlobalsCheck(Globals arenaGlobals)
Arena arena;
TraceId ti;
Trace trace;
Index i;
RefSet rs;
Rank rank;
CHECKS(Globals, arenaGlobals);
@ -181,18 +179,7 @@ Bool GlobalsCheck(Globals arenaGlobals)
/* no check for arena->lastWorldCollect (Clock) */
/* can't write a check for arena->epoch */
/* check that each history entry is a subset of the next oldest */
rs = RefSetEMPTY;
/* note this loop starts from 1; there is no history age 0 */
for (i=1; i <= LDHistoryLENGTH; ++ i) {
/* check history age 'i'; 'j' is the history index. */
Index j = (arena->epoch + LDHistoryLENGTH - i) % LDHistoryLENGTH;
CHECKL(RefSetSub(rs, arena->history[j]));
rs = arena->history[j];
}
/* the oldest history entry must be a subset of the prehistory */
CHECKL(RefSetSub(rs, arena->prehistory));
CHECKD(History, ArenaHistory(arena));
/* we also check the statics now. <design/arena/#static.check> */
CHECKL(BoolCheck(arenaRingInit));
@ -218,7 +205,6 @@ Bool GlobalsCheck(Globals arenaGlobals)
Res GlobalsInit(Globals arenaGlobals)
{
Arena arena;
Index i;
Rank rank;
TraceId ti;
@ -297,11 +283,8 @@ Res GlobalsInit(Globals arenaGlobals)
STATISTIC(arena->writeBarrierHitCount = 0);
RingInit(&arena->chainRing);
arena->epoch = (Epoch)0; /* <code/ld.c> */
arena->prehistory = RefSetEMPTY;
for(i = 0; i < LDHistoryLENGTH; ++i)
arena->history[i] = RefSetEMPTY;
HistoryInit(ArenaHistory(arena));
arena->emergency = FALSE;
arena->stackAtArenaEnter = NULL;
@ -385,6 +368,7 @@ void GlobalsFinish(Globals arenaGlobals)
arenaGlobals->sig = SigInvalid;
ShieldFinish(ArenaShield(arena));
HistoryFinish(ArenaHistory(arena));
RingFinish(&arena->formatRing);
RingFinish(&arena->chainRing);
RingFinish(&arena->messageRing);
@ -955,7 +939,6 @@ Res GlobalsDescribe(Globals arenaGlobals, mps_lib_FILE *stream, Count depth)
Res res;
Arena arena;
Ring node, nextNode;
Index i;
TraceId ti;
Trace trace;
@ -988,21 +971,13 @@ Res GlobalsDescribe(Globals arenaGlobals, mps_lib_FILE *stream, Count depth)
"threadSerial $U\n", (WriteFU)arena->threadSerial,
"busyTraces $B\n", (WriteFB)arena->busyTraces,
"flippedTraces $B\n", (WriteFB)arena->flippedTraces,
"epoch $U\n", (WriteFU)arena->epoch,
"prehistory = $B\n", (WriteFB)arena->prehistory,
"history {\n",
" [note: indices are raw, not rotated]\n",
NULL);
if (res != ResOK)
return res;
for(i=0; i < LDHistoryLENGTH; ++ i) {
res = WriteF(stream, depth + 2,
"[$U] = $B\n", (WriteFU)i, (WriteFB)arena->history[i],
NULL);
if (res != ResOK)
return res;
}
res = HistoryDescribe(ArenaHistory(arena), stream, depth);
if (res != ResOK)
return res;
res = ShieldDescribe(ArenaShield(arena), stream, depth);
if (res != ResOK)

View file

@ -51,6 +51,88 @@
SRCID(ld, "$Id$");
void HistoryInit(History history)
{
Index i;
AVER(history != NULL);
history->epoch = 0;
history->prehistory = RefSetEMPTY;
for (i = 0; i < LDHistoryLENGTH; ++i)
history->history[i] = RefSetEMPTY;
history->sig = HistorySig;
AVERT(History, history);
}
Bool HistoryCheck(History history)
{
Index i;
RefSet rs;
CHECKS(History, history);
/* check that each history entry is a subset of the next oldest */
rs = RefSetEMPTY;
/* note this loop starts from 1; there is no history age 0 */
for (i = 1; i <= LDHistoryLENGTH; ++i) {
/* check history age 'i'; 'j' is the history index. */
Index j = (history->epoch + LDHistoryLENGTH - i) % LDHistoryLENGTH;
CHECKL(RefSetSub(rs, history->history[j]));
rs = history->history[j];
}
/* the oldest history entry must be a subset of the prehistory */
CHECKL(RefSetSub(rs, history->prehistory));
return TRUE;
}
void HistoryFinish(History history)
{
AVERT(History, history);
history->sig = SigInvalid;
}
Res HistoryDescribe(History history, mps_lib_FILE *stream, Count depth)
{
Res res;
Index i;
if (!TESTT(History, history))
return ResPARAM;
if (stream == NULL)
return ResPARAM;
res = WriteF(stream, depth,
"History $P {\n", (WriteFP)history,
" epoch = $U\n", (WriteFU)history->epoch,
" prehistory = $B\n", (WriteFB)history->prehistory,
" history {\n",
" [note: indices are raw, not rotated]\n",
NULL);
if (res != ResOK)
return res;
for (i = 0; i < LDHistoryLENGTH; ++i) {
res = WriteF(stream, depth + 4,
"[$U] = $B\n", (WriteFU)i, (WriteFB)history->history[i],
NULL);
if (res != ResOK)
return res;
}
res = WriteF(stream, depth,
" }\n",
"} History $P\n", (WriteFP)history,
NULL);
if (res != ResOK)
return res;
return ResOK;
}
/* LDReset -- reset a dependency to empty
*
* .reset.sync: This does not need to be synchronized with LDAge
@ -68,7 +150,7 @@ void LDReset(mps_ld_t ld, Arena arena)
b = SegOfAddr(&seg, arena, (Addr)ld);
if (b)
ShieldExpose(arena, seg); /* .ld.access */
ld->_epoch = arena->epoch;
ld->_epoch = ArenaHistory(arena)->epoch;
ld->_rs = RefSetEMPTY;
if (b)
ShieldCover(arena, seg);
@ -106,7 +188,7 @@ void LDAdd(mps_ld_t ld, Arena arena, Addr addr)
{
AVER(ld != NULL);
AVER(TESTT(Arena, arena)); /* see .add.lock-free */
AVER(ld->_epoch <= arena->epoch);
AVER(ld->_epoch <= ArenaHistory(arena)->epoch);
ld->_rs = RefSetAdd(arena, ld->_rs, addr);
}
@ -134,23 +216,25 @@ void LDAdd(mps_ld_t ld, Arena arena, Addr addr)
*/
Bool LDIsStaleAny(mps_ld_t ld, Arena arena)
{
History history;
RefSet rs;
AVER(ld != NULL);
AVER(TESTT(Arena, arena)); /* .stale.thread-safe */
AVER(ld->_epoch <= arena->epoch);
history = ArenaHistory(arena);
AVER(ld->_epoch <= history->epoch);
if (arena->epoch == ld->_epoch) /* .stale.current */
if (history->epoch == ld->_epoch) /* .stale.current */
return FALSE;
/* Load the history refset, _then_ check to see if it's recent.
* This may in fact load an okay refset, which we decide to throw
* away and use the pre-history instead. */
rs = arena->history[ld->_epoch % LDHistoryLENGTH];
rs = history->history[ld->_epoch % LDHistoryLENGTH];
/* .stale.recent */
/* .stale.recent.conservative */
if (arena->epoch - ld->_epoch > LDHistoryLENGTH) {
rs = arena->prehistory; /* .stale.old */
if (history->epoch - ld->_epoch > LDHistoryLENGTH) {
rs = history->prehistory; /* .stale.old */
}
return RefSetInter(ld->_rs, rs) != RefSetEMPTY;
@ -186,28 +270,30 @@ Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr)
*/
void LDAge(Arena arena, RefSet rs)
{
History history;
Size i;
AVERT(Arena, arena);
history = ArenaHistory(arena);
AVER(rs != RefSetEMPTY);
/* Replace the entry for epoch - LDHistoryLENGTH by an empty */
/* set which will become the set which has moved since the */
/* current epoch. */
arena->history[arena->epoch % LDHistoryLENGTH] = RefSetEMPTY;
history->history[history->epoch % LDHistoryLENGTH] = RefSetEMPTY;
/* Record the fact that the moved set has moved, by adding it */
/* to all the sets in the history, including the set for the */
/* current epoch. */
for(i = 0; i < LDHistoryLENGTH; ++i)
arena->history[i] = RefSetUnion(arena->history[i], rs);
history->history[i] = RefSetUnion(history->history[i], rs);
/* This is the union of all movement since time zero. */
arena->prehistory = RefSetUnion(arena->prehistory, rs);
history->prehistory = RefSetUnion(history->prehistory, rs);
/* Advance the epoch by one. */
++arena->epoch;
AVER(arena->epoch != 0); /* .epoch-size */
++history->epoch;
AVER(history->epoch != 0); /* .epoch-size */
}
@ -221,9 +307,9 @@ void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from)
{
AVER(ld != NULL);
AVER(TESTT(Arena, arena)); /* .merge.lock-free */
AVER(ld->_epoch <= arena->epoch);
AVER(ld->_epoch <= ArenaHistory(arena)->epoch);
AVER(from != NULL);
AVER(from->_epoch <= arena->epoch);
AVER(from->_epoch <= ArenaHistory(arena)->epoch);
/* If a reference has been added since epoch e1 then I've */
/* certainly added since epoch e0 where e0 < e1. Therefore */

View file

@ -524,7 +524,7 @@ extern Ring GlobalsRememberedSummaryRing(Globals);
#define ArenaThreadRing(arena) (&(arena)->threadRing)
#define ArenaDeadRing(arena) (&(arena)->deadRing)
#define ArenaEpoch(arena) ((arena)->epoch) /* .epoch.ts */
#define ArenaEpoch(arena) (ArenaHistory(arena)->epoch) /* .epoch.ts */
#define ArenaTrace(arena, ti) (&(arena)->trace[ti])
#define ArenaZoneShift(arena) ((arena)->zoneShift)
#define ArenaStripeSize(arena) ((Size)1 << ArenaZoneShift(arena))
@ -534,6 +534,7 @@ extern Ring GlobalsRememberedSummaryRing(Globals);
#define ArenaChunkTree(arena) RVALUE((arena)->chunkTree)
#define ArenaChunkRing(arena) RVALUE(&(arena)->chunkRing)
#define ArenaShield(arena) (&(arena)->shieldStruct)
#define ArenaHistory(arena) (&(arena)->historyStruct)
extern Bool ArenaGrainSizeCheck(Size size);
#define AddrArenaGrainUp(addr, arena) AddrAlignUp(addr, ArenaGrainSize(arena))
@ -944,6 +945,10 @@ extern void (ShieldFlush)(Arena arena);
/* Location Dependency -- see <code/ld.c> */
extern void HistoryInit(History history);
extern void HistoryFinish(History);
extern Res HistoryDescribe(History history, mps_lib_FILE *stream, Count depth);
extern Bool HistoryCheck(History history);
extern void LDReset(mps_ld_t ld, Arena arena);
extern void LDAdd(mps_ld_t ld, Arena arena, Addr addr);
extern Bool LDIsStaleAny(mps_ld_t ld, Arena arena);

View file

@ -713,6 +713,21 @@ typedef struct ShieldStruct {
} ShieldStruct;
/* History -- location dependency history
*
* See design.mps.arena.ld.
*/
#define HistorySig ((Sig)0x51981520) /* SIGnature HISTOry */
typedef struct HistoryStruct {
Sig sig; /* design.mps.sig */
Epoch epoch; /* <design/arena/#ld.epoch> */
RefSet prehistory; /* <design/arena/#ld.prehistory> */
RefSet history[LDHistoryLENGTH]; /* <design/arena/#ld.history> */
} HistoryStruct;
/* ArenaStruct -- generic arena
*
* See <code/arena.c>.
@ -796,11 +811,8 @@ typedef struct mps_arena_s {
STATISTIC_DECL(Count writeBarrierHitCount) /* write barrier hits */
RingStruct chainRing; /* ring of chains */
/* location dependency fields (<code/ld.c>) */
Epoch epoch; /* <design/arena/#ld.epoch> */
RefSet prehistory; /* <design/arena/#ld.prehistory> */
RefSet history[LDHistoryLENGTH]; /* <design/arena/#ld.history> */
struct HistoryStruct historyStruct;
Bool emergency; /* garbage collect in emergency mode? */
Word *stackAtArenaEnter; /* NULL or hot end of client stack, in the thread */

View file

@ -112,6 +112,7 @@ typedef struct LandStruct *Land; /* <design/land/> */
typedef struct LandClassStruct *LandClass; /* <design/land/> */
typedef unsigned FindDelete; /* <design/land/> */
typedef struct ShieldStruct *Shield; /* design.mps.shield */
typedef struct HistoryStruct *History; /* design.mps.arena.ld */
/* Arena*Method -- see <code/mpmst.h#ArenaClassStruct> */

View file

@ -567,21 +567,25 @@ end of ``ArenaPoll()`` to the current polling time plus
Location dependencies
.....................
_`.ld.epoch`: ``arena->epoch`` is the "current epoch". This is the
_`.ld`: The ``historyStruct`` contains fields used to maintain a
history of garbage collection and in particular object motion in order
to implement location dependency.
_`.ld.epoch`: The ``epoch`` is the "current epoch". This is the
number of 'flips' of traces in the arena since the arena was created.
From the mutator's point of view locations change atomically at flip.
_`.ld.history`: ``arena->history`` is a circular buffer of
_`.ld.history`: The ``history`` is a circular buffer of
``LDHistoryLENGTH`` elements of type ``RefSet``. These are the
summaries of moved objects since the last ``LDHistoryLENGTH`` epochs.
If ``e`` is one of these recent epochs, then ::
arena->history[e % LDHistoryLENGTH]
history->history[e % LDHistoryLENGTH]
is a summary of (the original locations of) objects moved since epoch
``e``.
_`.ld.prehistory`: ``arena->prehistory`` is a ``RefSet`` summarizing
_`.ld.prehistory`: The ``prehistory`` is a ``RefSet`` summarizing
the original locations of all objects ever moved. When considering
whether a really old location dependency is stale, it is compared with
this summary.