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:
commit
4db81ddfa0
6 changed files with 139 additions and 56 deletions
|
|
@ -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)
|
||||
|
|
|
|||
114
mps/code/ld.c
114
mps/code/ld.c
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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> */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue