mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-23 15:22:20 -07:00
Mps: added (untested) internals for messagetypegcstart
Copied from Perforce Change: 39768 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
5e4a1006a6
commit
eb7fb7e384
13 changed files with 273 additions and 34 deletions
|
|
@ -209,6 +209,10 @@
|
|||
#define TraceLIMIT ((size_t)1)
|
||||
/* I count 4 function calls to scan, 10 to copy. */
|
||||
#define TraceCopyScanRATIO (1.5)
|
||||
/* Length (in chars) of a char buffer used to store the reason why a
|
||||
collection started in the TraceStartMessageStruct (used by
|
||||
mps_message_type_gc_start). */
|
||||
#define TRACE_START_MESSAGE_WHY_LEN 64
|
||||
|
||||
|
||||
|
||||
|
|
@ -316,7 +320,7 @@
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2003 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -628,8 +628,9 @@ Bool ArenaStep(Globals globals, double interval, double multiplier)
|
|||
stepped = FALSE;
|
||||
|
||||
if (arenaShouldCollectWorld(arena, interval, multiplier,
|
||||
start, clocks_per_sec)) {
|
||||
ArenaStartCollect(globals);
|
||||
start, clocks_per_sec))
|
||||
{
|
||||
ArenaStartCollect(globals, TraceStartWhyOPPORTUNISM);
|
||||
arena->lastWorldCollect = start;
|
||||
stepped = TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ Bool MessageClassCheck(MessageClass class)
|
|||
CHECKL(class->name != NULL);
|
||||
CHECKL(FUNCHECK(class->delete));
|
||||
CHECKL(FUNCHECK(class->finalizationRef));
|
||||
CHECKL(FUNCHECK(class->gcLiveSize));
|
||||
CHECKL(FUNCHECK(class->gcCondemnedSize));
|
||||
CHECKL(FUNCHECK(class->gcNotCondemnedSize));
|
||||
CHECKL(FUNCHECK(class->gcStartWhy));
|
||||
CHECKL(class->endSig == MessageClassSig);
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -352,6 +356,14 @@ Size MessageGCNotCondemnedSize(Message message)
|
|||
return (*message->class->gcNotCondemnedSize)(message);
|
||||
}
|
||||
|
||||
const char *MessageGCStartWhy(Message message)
|
||||
{
|
||||
AVERT(Message, message);
|
||||
AVER(message->type == MessageTypeGCSTART);
|
||||
|
||||
return (*message->class->gcStartWhy)(message);
|
||||
}
|
||||
|
||||
|
||||
/* type-specific stub methods */
|
||||
|
||||
|
|
@ -396,6 +408,16 @@ Size MessageNoGCNotCondemnedSize(Message message)
|
|||
return (Size)0;
|
||||
}
|
||||
|
||||
const char *MessageNoGCStartWhy(Message message)
|
||||
{
|
||||
AVERT(Message, message);
|
||||
UNUSED(message);
|
||||
|
||||
NOTREACHED;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* messtest.c: MESSAGE TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2003 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
|
@ -34,7 +34,8 @@ static MessageClassStruct DFMessageClassStruct = {
|
|||
MessageNoFinalizationRef, /* FinalizationRef */
|
||||
MessageNoGCLiveSize, /* GCLiveSize */
|
||||
MessageNoGCCondemnedSize, /* GCCondemnedSize */
|
||||
MessageNoGCNotCondemnedSize, /* GCNoteCondemnedSize */
|
||||
MessageNoGCNotCondemnedSize, /* GCNotCondemnedSize */
|
||||
MessageNoGCStartWhy, /* GCStartWhy */
|
||||
MessageClassSig /* <design/message/#class.sig.double> */
|
||||
};
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ static MessageClassStruct DGCMessageClassStruct = {
|
|||
MessageNoGCLiveSize, /* GCLiveSize */
|
||||
MessageNoGCCondemnedSize, /* GCCondemnedSize */
|
||||
MessageNoGCNotCondemnedSize, /* GCNoteCondemnedSize */
|
||||
MessageNoGCStartWhy, /* GCStartWhy */
|
||||
MessageClassSig /* <design/message/#class.sig.double> */
|
||||
};
|
||||
|
||||
|
|
@ -271,7 +273,7 @@ extern int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2003 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -90,6 +90,17 @@ typedef const struct SrcIdStruct {
|
|||
#define STR_(x) #x
|
||||
#define STR(x) STR_(x)
|
||||
|
||||
/* NELEMS -- counts number of elements in an array
|
||||
*
|
||||
* NELEMS(a) expands into an expression that is the number
|
||||
* of elements in the array a.
|
||||
*
|
||||
* WARNING: expands a more than once (you'd have to write obviously
|
||||
* perverse code for this to matter though).
|
||||
*/
|
||||
|
||||
#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
|
||||
|
||||
|
||||
/* DISCARD -- discards an expression, but checks syntax
|
||||
*
|
||||
|
|
|
|||
|
|
@ -309,6 +309,7 @@ extern void MessageFinalizationRef(Ref *refReturn,
|
|||
extern Size MessageGCLiveSize(Message message);
|
||||
extern Size MessageGCCondemnedSize(Message message);
|
||||
extern Size MessageGCNotCondemnedSize(Message message);
|
||||
extern const char *MessageGCStartWhy(Message message);
|
||||
|
||||
/* Convenience methods */
|
||||
extern void MessageNoFinalizationRef(Ref *refReturn,
|
||||
|
|
@ -316,6 +317,7 @@ extern void MessageNoFinalizationRef(Ref *refReturn,
|
|||
extern Size MessageNoGCLiveSize(Message message);
|
||||
extern Size MessageNoGCCondemnedSize(Message message);
|
||||
extern Size MessageNoGCNotCondemnedSize(Message message);
|
||||
extern const char *MessageNoGCStartWhy(Message message);
|
||||
|
||||
|
||||
/* Trace Interface -- see <code/trace.c> */
|
||||
|
|
@ -350,7 +352,7 @@ extern RefSet ScanStateSummary(ScanState ss);
|
|||
extern Bool TraceIdCheck(TraceId id);
|
||||
extern Bool TraceSetCheck(TraceSet ts);
|
||||
extern Bool TraceCheck(Trace trace);
|
||||
extern Res TraceCreate(Trace *traceReturn, Arena arena);
|
||||
extern Res TraceCreate(Trace *traceReturn, Arena arena, int why);
|
||||
extern void TraceDestroy(Trace trace);
|
||||
|
||||
extern Res TraceAddWhite(Trace trace, Seg seg);
|
||||
|
|
@ -475,8 +477,8 @@ extern Bool (ArenaStep)(Globals globals, double interval, double multiplier);
|
|||
extern void ArenaClamp(Globals globals);
|
||||
extern void ArenaRelease(Globals globals);
|
||||
extern void ArenaPark(Globals globals);
|
||||
extern Res ArenaStartCollect(Globals globals);
|
||||
extern Res ArenaCollect(Globals globals);
|
||||
extern Res ArenaStartCollect(Globals globals, int why);
|
||||
extern Res ArenaCollect(Globals globals, int why);
|
||||
extern Bool ArenaHasAddr(Arena arena, Addr addr);
|
||||
|
||||
extern Res ControlInit(Arena arena);
|
||||
|
|
|
|||
|
|
@ -200,9 +200,20 @@ typedef struct MessageClassStruct {
|
|||
|
||||
/* methods specific to MessageTypeGC */
|
||||
MessageGCLiveSizeMethod gcLiveSize;
|
||||
|
||||
/* methods specific to MessageTypeGC and MessageTypeGCGen */
|
||||
MessageGCCondemnedSizeMethod gcCondemnedSize;
|
||||
MessageGCNotCondemnedSizeMethod gcNotCondemnedSize;
|
||||
|
||||
/* methods specific to MessageTypeGCStart */
|
||||
MessageGCStartWhyMethod gcStartWhy;
|
||||
|
||||
/* methods specific to MessageTypeGCGen */
|
||||
#if 0 /* @@@@ */
|
||||
MessageGCGenNameMethod gcGenName;
|
||||
MessageGCGenForwardMethod gcGenForward;
|
||||
#endif
|
||||
|
||||
Sig endSig; /* <design/message/#class.sig.double> */
|
||||
} MessageClassStruct;
|
||||
|
||||
|
|
@ -442,6 +453,20 @@ typedef struct LDStruct {
|
|||
RefSet rs; /* RefSet of Add'ed references */
|
||||
} LDStruct;
|
||||
|
||||
/* TraceStartMessage
|
||||
*
|
||||
* See <design/message-gc/>.
|
||||
*
|
||||
* Embedded in TraceStruct. */
|
||||
|
||||
#define TraceStartMessageSig ((Sig)0x51926535) /* SIG TRaceStartMeSsage */
|
||||
|
||||
typedef struct TraceStartMessageStruct {
|
||||
Sig sig;
|
||||
char why[TRACE_START_MESSAGE_WHY_LEN];
|
||||
MessageStruct messageStruct;
|
||||
} TraceStartMessageStruct;
|
||||
|
||||
|
||||
/* ScanState
|
||||
*
|
||||
|
|
@ -525,6 +550,9 @@ typedef struct TraceStruct {
|
|||
Size preservedInPlaceSize; /* bytes preserved in place */
|
||||
STATISTIC_DECL(Count reclaimCount); /* segments reclaimed */
|
||||
STATISTIC_DECL(Count reclaimSize); /* bytes reclaimed */
|
||||
/* Always allocated message structure. Implements
|
||||
mps_message_type_gc_start(). See <design/message-gc/> */
|
||||
TraceStartMessageStruct startMessage;
|
||||
} TraceStruct;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ typedef PoolClass AbstractBufferPoolClass; /* <code/poolabs.c> */
|
|||
typedef PoolClass AbstractSegBufPoolClass; /* <code/poolabs.c> */
|
||||
typedef PoolClass AbstractScanPoolClass; /* <code/poolabs.c> */
|
||||
typedef PoolClass AbstractCollectPoolClass; /* <code/poolabs.c> */
|
||||
typedef struct TraceStartMessageStruct
|
||||
*TraceStartMessage; /* <design/mesage-gc> */
|
||||
typedef struct TraceStruct *Trace; /* <design/trace/> */
|
||||
typedef struct ScanStateStruct *ScanState; /* <design/trace/> */
|
||||
typedef struct ChainStruct *Chain; /* <design/trace/> */
|
||||
|
|
@ -232,6 +234,7 @@ typedef void (*MessageFinalizationRefMethod)
|
|||
typedef Size (*MessageGCLiveSizeMethod)(Message message);
|
||||
typedef Size (*MessageGCCondemnedSizeMethod)(Message message);
|
||||
typedef Size (*MessageGCNotCondemnedSizeMethod)(Message message);
|
||||
typedef const char * (*MessageGCStartWhyMethod)(Message message);
|
||||
|
||||
|
||||
/* Message Types -- <design/message/> and elsewhere */
|
||||
|
|
@ -401,6 +404,18 @@ enum {
|
|||
TraceFINISHED
|
||||
};
|
||||
|
||||
/* TraceStart reasons. Reasons for why a trace is started. */
|
||||
|
||||
enum {
|
||||
TraceStartWhyBASE = 1, /* not a reason, the base of the enum. */
|
||||
TraceStartWhyNURSERY = TraceStartWhyBASE,
|
||||
TraceStartWhyGLOBAL,
|
||||
TraceStartWhyOPPORTUNISM,
|
||||
TraceStartWhyCLIENT,
|
||||
TraceStartWhyWALK,
|
||||
TraceStartWhyLIMIT /* not a reason, the limit of the enum. */
|
||||
};
|
||||
|
||||
|
||||
/* MessageTypes -- see <design/message/> */
|
||||
/* .message.types: Keep in sync with <code/mps.h#message.types> */
|
||||
|
|
@ -408,6 +423,7 @@ enum {
|
|||
enum {
|
||||
MessageTypeFINALIZATION,
|
||||
MessageTypeGC,
|
||||
MessageTypeGCSTART,
|
||||
MessageTypeLIMIT
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -65,17 +65,20 @@ enum {
|
|||
MPS_RES_PARAM /* illegal user parameter value */
|
||||
};
|
||||
|
||||
/* .message.types: Keep in sync with <code/mpmtypes.h#message.types> */
|
||||
/* <a id="message.types"> Keep in sync with
|
||||
* <code/mpmtypes.h#message.types> */
|
||||
/* Not meant to be used by clients, they should use the macros below. */
|
||||
enum {
|
||||
MPS_MESSAGE_TYPE_FINALIZATION,
|
||||
MPS_MESSAGE_TYPE_GC
|
||||
MPS_MESSAGE_TYPE_GC,
|
||||
MPS_MESSAGE_TYPE_GC_START
|
||||
};
|
||||
|
||||
/* Message Types
|
||||
* This is what clients should use. */
|
||||
#define mps_message_type_finalization() MPS_MESSAGE_TYPE_FINALIZATION
|
||||
#define mps_message_type_gc() MPS_MESSAGE_TYPE_GC
|
||||
#define mps_message_type_gc_start() MPS_MESSAGE_TYPE_GC_START
|
||||
|
||||
|
||||
/* Reference Ranks
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ mps_res_t mps_arena_start_collect(mps_space_t mps_space)
|
|||
Res res;
|
||||
Arena arena = (Arena)mps_space;
|
||||
ArenaEnter(arena);
|
||||
res = ArenaStartCollect(ArenaGlobals(arena));
|
||||
res = ArenaStartCollect(ArenaGlobals(arena), TraceStartWhyCLIENT);
|
||||
ArenaLeave(arena);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -356,7 +356,7 @@ mps_res_t mps_arena_collect(mps_space_t mps_space)
|
|||
Res res;
|
||||
Arena arena = (Arena)mps_space;
|
||||
ArenaEnter(arena);
|
||||
res = ArenaCollect(ArenaGlobals(arena));
|
||||
res = ArenaCollect(ArenaGlobals(arena), TraceStartWhyCLIENT);
|
||||
ArenaLeave(arena);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -463,7 +463,8 @@ static MessageClassStruct MRGMessageClassStruct = {
|
|||
MRGMessageFinalizationRef, /* FinalizationRef */
|
||||
MessageNoGCLiveSize, /* GCLiveSize */
|
||||
MessageNoGCCondemnedSize, /* GCCondemnedSize */
|
||||
MessageNoGCNotCondemnedSize, /* GCNoteCondemnedSize */
|
||||
MessageNoGCNotCondemnedSize, /* GCNotCondemnedSize */
|
||||
MessageNoGCStartWhy, /* GCStartWhy */
|
||||
MessageClassSig /* <design/message/#class.sig.double> */
|
||||
};
|
||||
|
||||
|
|
|
|||
187
mps/code/trace.c
187
mps/code/trace.c
|
|
@ -12,11 +12,16 @@
|
|||
|
||||
SRCID(trace, "$Id$");
|
||||
|
||||
/* Forward declarations */
|
||||
static void TraceStartMessageInit(Arena arena, TraceStartMessage tsMessage);
|
||||
|
||||
/* Types */
|
||||
|
||||
enum {traceAccountingPhaseRootScan = 1, traceAccountingPhaseSegScan,
|
||||
traceAccountingPhaseSingleScan};
|
||||
enum {
|
||||
traceAccountingPhaseRootScan = 1,
|
||||
traceAccountingPhaseSegScan,
|
||||
traceAccountingPhaseSingleScan
|
||||
};
|
||||
typedef int traceAccountingPhase;
|
||||
|
||||
|
||||
|
|
@ -32,7 +37,7 @@ typedef struct TraceMessageStruct {
|
|||
MessageStruct messageStruct;
|
||||
} TraceMessageStruct, *TraceMessage;
|
||||
|
||||
#define TraceMessageMessage(TraceMessage) (&((TraceMessage)->messageStruct))
|
||||
#define TraceMessageMessage(traceMessage) (&((traceMessage)->messageStruct))
|
||||
#define MessageTraceMessage(message) \
|
||||
(PARENT(TraceMessageStruct, messageStruct, message))
|
||||
|
||||
|
|
@ -102,6 +107,7 @@ static MessageClassStruct TraceMessageClassStruct = {
|
|||
TraceMessageLiveSize, /* GCLiveSize */
|
||||
TraceMessageCondemnedSize, /* GCCondemnedSize */
|
||||
TraceMessageNotCondemnedSize, /* GCNotCondemnedSize */
|
||||
MessageNoGCStartWhy, /* GCStartWhy */
|
||||
MessageClassSig /* <design/message/#class.sig.double> */
|
||||
};
|
||||
|
||||
|
|
@ -119,6 +125,135 @@ static void TraceMessageInit(Arena arena, TraceMessage tMessage)
|
|||
AVERT(TraceMessage, tMessage);
|
||||
}
|
||||
|
||||
/* TraceStartMessage - manages info needed by start of trace message
|
||||
(mps_message_type_gc_start).
|
||||
|
||||
(structure declared in <code/mpmst.h> ) */
|
||||
|
||||
#define TraceStartMessageMessage(traceStartMessage) \
|
||||
(&((traceStartMessage)->messageStruct))
|
||||
#define MessageTraceStartMessage(message) \
|
||||
(PARENT(TraceStartMessageStruct, messageStruct, message))
|
||||
|
||||
static Bool TraceStartMessageCheck(TraceStartMessage message)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
CHECKS(TraceStartMessage, message);
|
||||
CHECKD(Message, TraceStartMessageMessage(message));
|
||||
CHECKL(MessageGetType(TraceStartMessageMessage(message)) ==
|
||||
MessageTypeGCSTART);
|
||||
|
||||
/* Check that why is NUL terminated. */
|
||||
for(i=0; i<NELEMS(message->why); ++i) {
|
||||
if(message->why[i] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECKL(i<NELEMS(message->why));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void TraceStartMessageDelete(Message message)
|
||||
{
|
||||
TraceStartMessage tsMessage;
|
||||
|
||||
AVERT(Message, message);
|
||||
tsMessage = MessageTraceStartMessage(message);
|
||||
AVERT(TraceStartMessage, tsMessage);
|
||||
|
||||
TraceStartMessageInit(MessageArena(message), tsMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static const char *TraceStartMessageWhy(Message message)
|
||||
{
|
||||
TraceStartMessage tsMessage;
|
||||
|
||||
AVERT(Message, message);
|
||||
tsMessage = MessageTraceStartMessage(message);
|
||||
AVERT(TraceStartMessage, tsMessage);
|
||||
|
||||
return tsMessage->why;
|
||||
}
|
||||
|
||||
static MessageClassStruct TraceStartMessageClassStruct = {
|
||||
MessageClassSig, /* sig */
|
||||
"TraceGCStart", /* name */
|
||||
TraceStartMessageDelete, /* Delete */
|
||||
MessageNoFinalizationRef, /* FinalizationRef */
|
||||
MessageNoGCLiveSize, /* GCLiveSize */
|
||||
MessageNoGCCondemnedSize, /* GCCondemnedSize */
|
||||
MessageNoGCNotCondemnedSize, /* GCNotCondemnedSize */
|
||||
TraceStartMessageWhy, /* GCStartWhy */
|
||||
MessageClassSig /* <design/message/#class.sig.double> */
|
||||
};
|
||||
|
||||
static void TraceStartMessageInit(Arena arena, TraceStartMessage tsMessage)
|
||||
{
|
||||
AVERT(Arena, arena);
|
||||
|
||||
MessageInit(arena, TraceStartMessageMessage(tsMessage),
|
||||
&TraceStartMessageClassStruct, MessageTypeGCSTART);
|
||||
tsMessage->why[0] = '\0';
|
||||
|
||||
tsMessage->sig = TraceStartMessageSig;
|
||||
AVERT(TraceStartMessage, tsMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* traceStartWhyToString
|
||||
*
|
||||
* Converts a TraceStartWhy* code into a string description.
|
||||
* s specifies the beginning of the buffer to write the string
|
||||
* into, len specifies the length of the buffer.
|
||||
* The string written into will be NUL terminated (truncated if
|
||||
* necessary). */
|
||||
static void traceStartWhyToString(char *s, size_t len, int why)
|
||||
{
|
||||
const char *r;
|
||||
size_t i;
|
||||
|
||||
AVER(s);
|
||||
/* len can be anything, including 0. */
|
||||
AVER(TraceStartWhyBASE <= why);
|
||||
AVER(why < TraceStartWhyLIMIT);
|
||||
|
||||
switch(why) {
|
||||
case TraceStartWhyNURSERY:
|
||||
r = "Nursery generation is full.";
|
||||
break;
|
||||
case TraceStartWhyGLOBAL:
|
||||
r = "Preventing global exhaustion of memory.";
|
||||
break;
|
||||
case TraceStartWhyOPPORTUNISM:
|
||||
r = "Opportunism.";
|
||||
break;
|
||||
case TraceStartWhyCLIENT:
|
||||
r = "Client request.";
|
||||
break;
|
||||
case TraceStartWhyWALK:
|
||||
r = "Walking.";
|
||||
break;
|
||||
default:
|
||||
NOTREACHED;
|
||||
r = "Unknown reason (internal error).";
|
||||
break;
|
||||
}
|
||||
|
||||
for(i=0; i<len; ++i) {
|
||||
s[i] = r[i];
|
||||
if(r[i] == '\0')
|
||||
break;
|
||||
}
|
||||
s[len-1] = '\0';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* ScanStateCheck -- check consistency of a ScanState object */
|
||||
|
||||
|
|
@ -162,8 +297,9 @@ void ScanStateInit(ScanState ss, TraceSet ts, Arena arena,
|
|||
|
||||
ss->fix = TraceFix;
|
||||
TRACE_SET_ITER(ti, trace, ts, arena)
|
||||
if (trace->emergency)
|
||||
if (trace->emergency) {
|
||||
ss->fix = TraceFixEmergency;
|
||||
}
|
||||
TRACE_SET_ITER_END(ti, trace, ts, arena);
|
||||
ss->rank = rank;
|
||||
ss->traces = ts;
|
||||
|
|
@ -580,6 +716,8 @@ static void traceFlip(Trace trace)
|
|||
/* collector), so that we allocate grey or white before the flip */
|
||||
/* and black afterwards. For instance, see */
|
||||
/* <design/poolams/#invariant.alloc>. */
|
||||
/* (surely we mean "write-barrier" not "read-barrier" above? */
|
||||
/* drj 2003-02-19) */
|
||||
|
||||
/* Now that the mutator is black we must prevent it from reading */
|
||||
/* grey objects so that it can't obtain white pointers. This is */
|
||||
|
|
@ -625,7 +763,7 @@ static void traceFlip(Trace trace)
|
|||
* This code is written to be adaptable to allocating Trace objects
|
||||
* dynamically. */
|
||||
|
||||
Res TraceCreate(Trace *traceReturn, Arena arena)
|
||||
Res TraceCreate(Trace *traceReturn, Arena arena, int why)
|
||||
{
|
||||
TraceId ti;
|
||||
Trace trace;
|
||||
|
|
@ -678,6 +816,9 @@ found:
|
|||
trace->preservedInPlaceSize = (Size)0; /* see .message.data */
|
||||
STATISTIC(trace->reclaimCount = (Count)0);
|
||||
STATISTIC(trace->reclaimSize = (Size)0);
|
||||
TraceStartMessageInit(arena, &trace->startMessage);
|
||||
traceStartWhyToString(trace->startMessage.why,
|
||||
sizeof trace->startMessage.why, why);
|
||||
trace->sig = TraceSig;
|
||||
arena->busyTraces = TraceSetAdd(arena->busyTraces, trace);
|
||||
AVERT(Trace, trace);
|
||||
|
|
@ -1373,8 +1514,9 @@ static Res rootGrey(Root root, void *p)
|
|||
AVERT(Root, root);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
if (ZoneSetInter(RootSummary(root), trace->white) != ZoneSetEMPTY)
|
||||
if (ZoneSetInter(RootSummary(root), trace->white) != ZoneSetEMPTY) {
|
||||
RootGrey(root, trace);
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -1389,9 +1531,10 @@ void TraceStart(Trace trace, double mortality, double finishingTime)
|
|||
AVERT(Trace, trace);
|
||||
AVER(trace->state == TraceINIT);
|
||||
AVER(0.0 <= mortality && mortality <= 1.0);
|
||||
arena = trace->arena;
|
||||
AVER(finishingTime >= 0.0);
|
||||
|
||||
arena = trace->arena;
|
||||
|
||||
/* From the already set up white set, derive a grey set. */
|
||||
|
||||
/* @@@@ Instead of iterating over all the segments, we could */
|
||||
|
|
@ -1420,13 +1563,15 @@ void TraceStart(Trace trace, double mortality, double finishingTime)
|
|||
/* approximation to the white set. */
|
||||
if (ZoneSetInter(SegSummary(seg), trace->white) != ZoneSetEMPTY) {
|
||||
PoolGrey(SegPool(seg), trace, seg);
|
||||
if (TraceSetIsMember(SegGrey(seg), trace))
|
||||
if (TraceSetIsMember(SegGrey(seg), trace)) {
|
||||
trace->foundation += size;
|
||||
}
|
||||
}
|
||||
|
||||
if ((SegPool(seg)->class->attr & AttrGC)
|
||||
&& !TraceSetIsMember(SegWhite(seg), trace))
|
||||
&& !TraceSetIsMember(SegWhite(seg), trace)) {
|
||||
trace->notCondemned += size;
|
||||
}
|
||||
}
|
||||
} while (SegNext(&seg, arena, base));
|
||||
}
|
||||
|
|
@ -1508,9 +1653,12 @@ static void traceQuantum(Trace trace)
|
|||
}
|
||||
|
||||
/* traceStartCollectAll: start a trace which condemns everything in
|
||||
* the arena. */
|
||||
* the arena.
|
||||
*
|
||||
* "why" is a TraceStartWhy* enum member that specifies why the
|
||||
* collection is starting. */
|
||||
|
||||
static Res traceStartCollectAll(Trace *traceReturn, Arena arena)
|
||||
static Res traceStartCollectAll(Trace *traceReturn, Arena arena, int why)
|
||||
{
|
||||
Trace trace;
|
||||
Res res;
|
||||
|
|
@ -1519,16 +1667,17 @@ static Res traceStartCollectAll(Trace *traceReturn, Arena arena)
|
|||
AVERT(Arena, arena);
|
||||
AVER(arena->busyTraces == TraceSetEMPTY);
|
||||
|
||||
res = TraceCreate(&trace, arena);
|
||||
res = TraceCreate(&trace, arena, why);
|
||||
AVER(res == ResOK); /* succeeds because no other trace is busy */
|
||||
res = traceCondemnAll(trace);
|
||||
if (res != ResOK) /* should try some other trace, really @@@@ */
|
||||
goto failCondemn;
|
||||
finishingTime = ArenaAvail(arena)
|
||||
- trace->condemned * (1.0 - TraceTopGenMortality);
|
||||
if (finishingTime < 0)
|
||||
if (finishingTime < 0) {
|
||||
/* Run out of time, should really try a smaller collection. @@@@ */
|
||||
finishingTime = 0.0;
|
||||
}
|
||||
TraceStart(trace, TraceTopGenMortality, finishingTime);
|
||||
*traceReturn = trace;
|
||||
return ResOK;
|
||||
|
|
@ -1572,7 +1721,7 @@ Size TracePoll(Globals globals)
|
|||
dynamicDeferral = (double)ArenaAvail(arena) - (double)sConsTrace;
|
||||
|
||||
if (dynamicDeferral < 0.0) { /* start full GC */
|
||||
res = traceStartCollectAll(&trace, arena);
|
||||
res = traceStartCollectAll(&trace, arena, TraceStartWhyGLOBAL);
|
||||
if (res != ResOK)
|
||||
goto failStart;
|
||||
scannedSize = traceWorkClock(trace);
|
||||
|
|
@ -1596,7 +1745,7 @@ Size TracePoll(Globals globals)
|
|||
if (firstTime < 0) {
|
||||
double mortality;
|
||||
|
||||
res = TraceCreate(&trace, arena);
|
||||
res = TraceCreate(&trace, arena, TraceStartWhyNURSERY);
|
||||
AVER(res == ResOK);
|
||||
res = ChainCondemnAuto(&mortality, firstChain, trace);
|
||||
if (res != ResOK) /* should try some other trace, really @@@@ */
|
||||
|
|
@ -1675,7 +1824,7 @@ void ArenaPark(Globals globals)
|
|||
/* ArenaStartCollect -- start a collection of everything in the
|
||||
* arena; leave unclamped. */
|
||||
|
||||
Res ArenaStartCollect(Globals globals)
|
||||
Res ArenaStartCollect(Globals globals, int why)
|
||||
{
|
||||
Arena arena;
|
||||
Res res;
|
||||
|
|
@ -1685,7 +1834,7 @@ Res ArenaStartCollect(Globals globals)
|
|||
arena = GlobalsArena(globals);
|
||||
|
||||
ArenaPark(globals);
|
||||
res = traceStartCollectAll(&trace, arena);
|
||||
res = traceStartCollectAll(&trace, arena, why);
|
||||
if (res != ResOK)
|
||||
goto failStart;
|
||||
ArenaRelease(globals);
|
||||
|
|
@ -1698,12 +1847,12 @@ failStart:
|
|||
|
||||
/* ArenaCollect -- collect everything in arena; leave clamped */
|
||||
|
||||
Res ArenaCollect(Globals globals)
|
||||
Res ArenaCollect(Globals globals, int why)
|
||||
{
|
||||
Res res;
|
||||
|
||||
AVERT(Globals, globals);
|
||||
res = ArenaStartCollect(globals);
|
||||
res = ArenaStartCollect(globals, why);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
|
|||
/* call the client closure. This fix method must perform no tracing */
|
||||
/* operations of its own. */
|
||||
|
||||
res = TraceCreate(&trace, arena);
|
||||
res = TraceCreate(&trace, arena, TraceStartWhyWALK);
|
||||
/* Have to fail if no trace available. Unlikely due to .assume.parked. */
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue