mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-05 03:20:39 -08:00
Merging recent changes from masters, including awl fix to unstick open dylan bootstrap.
Copied from Perforce Change: 179440 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
ce7ddee9f7
4 changed files with 82 additions and 35 deletions
|
|
@ -117,7 +117,7 @@ CFLAGSEXTERNAL =
|
|||
# %%VARIETY: When adding a new variety, define a macro containing the set
|
||||
# of flags for the new variety.
|
||||
CFRASH = /DCONFIG_VAR_RASH $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSEXTERNAL)
|
||||
CFHOT = /DCONFIG_VAR_HOT $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSEXTERNAL)
|
||||
CFHOT = /DCONFIG_VAR_HOT $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL)
|
||||
CFDIAG = /DCONFIG_VAR_DIAG $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL)
|
||||
CFCOOL = /DCONFIG_VAR_COOL $(CRTFLAGSCOOL) $(CFLAGSCOOL) $(CFLAGSINTERNAL)
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ LINKFLAGSINTERNAL = /DEBUG
|
|||
LINKFLAGSEXTERNAL = /RELEASE
|
||||
|
||||
LFRASH = $(LINKFLAGSHOT) $(LINKFLAGSEXTERNAL)
|
||||
LFHOT = $(LINKFLAGSHOT) $(LINKFLAGSEXTERNAL)
|
||||
LFHOT = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL)
|
||||
LFDIAG = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL)
|
||||
LFCOOL = $(LINKFLAGSCOOL) $(LINKFLAGSINTERNAL)
|
||||
|
||||
|
|
|
|||
|
|
@ -393,6 +393,14 @@
|
|||
#define AMCLargeSegPAGES ((Count)8)
|
||||
|
||||
|
||||
/* Pool Class AWL configuration -- see poolawl.c for usage */
|
||||
|
||||
#define AWL_HAVE_SEG_SA_LIMIT TRUE
|
||||
#define AWL_SEG_SA_LIMIT 200 /* TODO: Improve guesswork with measurements */
|
||||
#define AWL_HAVE_TOTAL_SA_LIMIT FALSE
|
||||
#define AWL_TOTAL_SA_LIMIT 0
|
||||
|
||||
|
||||
#endif /* config_h */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
*/
|
||||
|
||||
#define EventNameMAX ((size_t)19)
|
||||
#define EventCodeMAX ((EventCode)0x0071)
|
||||
#define EventCodeMAX ((EventCode)0x0073)
|
||||
|
||||
#define EVENT_LIST(EVENT, X) \
|
||||
/* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \
|
||||
|
|
@ -177,7 +177,9 @@
|
|||
EVENT(X, MessagesExist , 0x006E, TRUE, Arena) \
|
||||
EVENT(X, ChainCondemnAuto , 0x006F, TRUE, Trace) \
|
||||
EVENT(X, TraceFindGrey , 0x0070, TRUE, Trace) \
|
||||
EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace)
|
||||
EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace) \
|
||||
EVENT(X, AWLDeclineTotal , 0x0072, TRUE, Trace) \
|
||||
EVENT(X, AWLDeclineSeg , 0x0073, TRUE, Trace)
|
||||
|
||||
|
||||
/* Remember to update EventNameMAX and EventCodeMAX in eventcom.h!
|
||||
|
|
@ -610,6 +612,14 @@
|
|||
PARAM(X, 1, W, ti) \
|
||||
PARAM(X, 2, W, rank)
|
||||
|
||||
#define EVENT_AWLDeclineTotal_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, seg) /* segment declined single access */ \
|
||||
PARAM(X, 1, U, succAccesses) /* total successive accesses */
|
||||
|
||||
#define EVENT_AWLDeclineSeg_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, seg) /* segment declined single access */ \
|
||||
PARAM(X, 1, U, singleAccesses) /* single accesses this cycle */
|
||||
|
||||
|
||||
#endif /* eventdef_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -289,50 +289,79 @@ DEFINE_SEG_CLASS(AWLSegClass, class)
|
|||
}
|
||||
|
||||
|
||||
/* Single access permission control parameters */
|
||||
/* Single access pattern control parameters
|
||||
*
|
||||
* These control the number of expensive emulated single-accesses we allow
|
||||
* before we give up and scan a segment at whatever rank, possibly causing
|
||||
* retention of weak objects.
|
||||
*
|
||||
* AWLSegSALimit is the number of accesses for a single segment in a GC cycle.
|
||||
* AWLTotalSALimit is the total number of accesses during a GC cycle.
|
||||
*
|
||||
* These should be set in config.h, but are here in static variables so that
|
||||
* it's possible to tweak them in a debugger.
|
||||
*/
|
||||
|
||||
Count AWLSegSALimit = 0; /* Number of single accesses permitted per segment */
|
||||
Bool AWLHaveSegSALimit = FALSE; /* When TRUE, AWLSegSALimit applies */
|
||||
Count AWLSegSALimit = AWL_SEG_SA_LIMIT;
|
||||
Bool AWLHaveSegSALimit = AWL_HAVE_SEG_SA_LIMIT;
|
||||
|
||||
Count AWLTotalSALimit = 0; /* Number of single accesses permitted in a row */
|
||||
Bool AWLHaveTotalSALimit = FALSE; /* When TRUE, AWLTotalSALimit applies */
|
||||
Count AWLTotalSALimit = AWL_TOTAL_SA_LIMIT;
|
||||
Bool AWLHaveTotalSALimit = AWL_HAVE_TOTAL_SA_LIMIT;
|
||||
|
||||
|
||||
/* Determine whether to permit scanning a single ref. */
|
||||
|
||||
static Bool AWLCanTrySingleAccess(AWL awl, Seg seg, Addr addr)
|
||||
static Bool AWLCanTrySingleAccess(Arena arena, AWL awl, Seg seg, Addr addr)
|
||||
{
|
||||
AWLSeg awlseg;
|
||||
|
||||
AVERT(AWL, awl);
|
||||
AVERT(Seg, seg);
|
||||
AVER(addr != NULL);
|
||||
|
||||
/* .assume.noweak */
|
||||
/* .assume.alltraceable */
|
||||
if(RankSetIsMember(SegRankSet(seg), RankWEAK)) {
|
||||
AWLSeg awlseg;
|
||||
if (!RankSetIsMember(SegRankSet(seg), RankWEAK))
|
||||
return FALSE;
|
||||
|
||||
awlseg = Seg2AWLSeg(seg);
|
||||
AVERT(AWLSeg, awlseg);
|
||||
|
||||
if(AWLHaveTotalSALimit) {
|
||||
if(AWLTotalSALimit < awl->succAccesses) {
|
||||
STATISTIC(awl->stats.declined++);
|
||||
return FALSE; /* decline single access because of total limit */
|
||||
}
|
||||
}
|
||||
|
||||
if(AWLHaveSegSALimit) {
|
||||
if(AWLSegSALimit < awlseg->singleAccesses) {
|
||||
STATISTIC(awl->stats.declined++);
|
||||
return FALSE; /* decline single access because of segment limit */
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
} else {
|
||||
return FALSE; /* Single access only for weak segs (.assume.noweak) */
|
||||
/* If there are no traces in progress then the segment isn't read
|
||||
protected and this is just an ordinary write barrier hit. No need to
|
||||
scan at all. */
|
||||
if (arena->flippedTraces == TraceSetEMPTY) {
|
||||
AVER(!(SegSM(seg) & AccessREAD));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The trace is already in the weak band, so we can scan the whole
|
||||
segment without retention anyway. Go for it. */
|
||||
if (TraceRankForAccess(arena, seg) == RankWEAK)
|
||||
return FALSE;
|
||||
|
||||
awlseg = Seg2AWLSeg(seg);
|
||||
AVERT(AWLSeg, awlseg);
|
||||
|
||||
/* If there have been too many single accesses in a row then don't
|
||||
keep trying them, even if it means retaining objects. */
|
||||
if(AWLHaveTotalSALimit) {
|
||||
if(awl->succAccesses >= AWLTotalSALimit) {
|
||||
STATISTIC(awl->stats.declined++);
|
||||
EVENT2(AWLDeclineTotal, seg, awl->succAccesses);
|
||||
return FALSE; /* decline single access because of total limit */
|
||||
}
|
||||
}
|
||||
|
||||
/* If there have been too many single accesses to this segment
|
||||
then don't keep trying them, even if it means retaining objects.
|
||||
(Observed behaviour in Open Dylan 2012-09-10 by RB.) */
|
||||
if(AWLHaveSegSALimit) {
|
||||
if(awlseg->singleAccesses >= AWLSegSALimit) {
|
||||
STATISTIC(awl->stats.declined++);
|
||||
EVENT2(AWLDeclineSeg, seg, awlseg->singleAccesses);
|
||||
return FALSE; /* decline single access because of segment limit */
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1116,9 +1145,9 @@ static Res AWLAccess(Pool pool, Seg seg, Addr addr,
|
|||
AVER(SegBase(seg) <= addr);
|
||||
AVER(addr < SegLimit(seg));
|
||||
AVER(SegPool(seg) == pool);
|
||||
|
||||
|
||||
/* Attempt scanning a single reference if permitted */
|
||||
if(AWLCanTrySingleAccess(awl, seg, addr)) {
|
||||
if(AWLCanTrySingleAccess(PoolArena(pool), awl, seg, addr)) {
|
||||
res = PoolSingleAccess(pool, seg, addr, mode, context);
|
||||
switch(res) {
|
||||
case ResOK:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue