From ed8cd9432d6200bbd8e4f833fcd7b18e9f2af18c Mon Sep 17 00:00:00 2001
From: David Lovemore
Date: Thu, 30 Aug 2012 13:48:41 +0100
Subject: In tracescanareatagged use the alignments of pools in the condemned
set to determine mask.
Copied from Perforce
Change: 179117
ServerID: perforce.ravenbrook.com
---
mps/code/mpm.c | 9 ++++++++-
mps/code/mpm.h | 1 +
mps/code/mpmst.h | 1 +
mps/code/pool.c | 2 ++
mps/code/ssixi3.c | 2 +-
mps/code/ssixi6.c | 2 +-
mps/code/ssw3i3.c | 2 +-
mps/code/ssw3i6.asm | 4 ++--
mps/code/trace.c | 41 ++++++++++++++++++++++++++++++++++++-----
9 files changed, 53 insertions(+), 11 deletions(-)
(limited to 'mps/code')
diff --git a/mps/code/mpm.c b/mps/code/mpm.c
index 4f9af3f888c..71b93d8a41d 100644
--- a/mps/code/mpm.c
+++ b/mps/code/mpm.c
@@ -174,7 +174,14 @@ Word (WordAlignDown)(Word word, Align alignment)
Bool SizeIsP2(Size size)
{
- return size > 0 && (size & (size - 1)) == 0;
+ return WordIsP2((Word)size);
+}
+
+/* WordIsP2 -- tests whether a word is a power of two */
+
+Bool WordIsP2(Word word)
+{
+ return word > 0 && (word & (word - 1)) == 0;
}
diff --git a/mps/code/mpm.h b/mps/code/mpm.h
index b5a58eeef59..263cb795e5d 100644
--- a/mps/code/mpm.h
+++ b/mps/code/mpm.h
@@ -145,6 +145,7 @@ extern Bool SizeIsP2(Size size);
extern Shift SizeLog2(Size size);
extern Shift SizeFloorLog2(Size size);
+extern Bool WordIsP2(Word word);
/* Formatted Output -- see , */
diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h
index 488a6d1b54b..0903e783ba0 100644
--- a/mps/code/mpmst.h
+++ b/mps/code/mpmst.h
@@ -499,6 +499,7 @@ typedef struct TraceStruct {
TraceId ti; /* index into TraceSets */
Arena arena; /* owning arena */
int why; /* why the trace began */
+ Align whiteMinAlign; /* minimum alignment of references in white set */
ZoneSet white; /* zones in the white set */
ZoneSet mayMove; /* zones containing possibly moving objs */
TraceState state; /* current state of trace */
diff --git a/mps/code/pool.c b/mps/code/pool.c
index e2578cf3497..55e70ff1462 100644
--- a/mps/code/pool.c
+++ b/mps/code/pool.c
@@ -305,6 +305,8 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size,
/* .hasaddr.critical: The PoolHasAddr check is expensive, and in */
/* allocation-bound programs this is on the critical path. */
AVER_CRITICAL(PoolHasAddr(pool, *pReturn));
+ /* All allocations should be aligned to the pool's alignment */
+ AVER_CRITICAL(AddrIsAligned(*pReturn, pool->alignment));
/* All PoolAllocs should advance the allocation clock, so we count */
/* it all in the fillMutatorSize field. */
diff --git a/mps/code/ssixi3.c b/mps/code/ssixi3.c
index 0d1c31c7501..04601803438 100644
--- a/mps/code/ssixi3.c
+++ b/mps/code/ssixi3.c
@@ -66,7 +66,7 @@ Res StackScan(ScanState ss, Addr *stackBot)
ASMV("mov %%esp, %0" : "=r" (stackTop) :); /* stackTop = esp */
AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .assume.align */
- res = TraceScanArea(ss, stackTop, stackBot);
+ res = TraceScanAreaTagged(ss, stackTop, stackBot);
return res;
}
diff --git a/mps/code/ssixi6.c b/mps/code/ssixi6.c
index 6b425bed804..6eeac9ae45b 100644
--- a/mps/code/ssixi6.c
+++ b/mps/code/ssixi6.c
@@ -62,7 +62,7 @@ Res StackScan(ScanState ss, Addr *stackBot)
ASMV("mov %%rsp, %0" : "=r" (stackTop) :); /* stackTop = rsp */
AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .assume.align */
- res = TraceScanArea(ss, stackTop, stackBot);
+ res = TraceScanAreaTagged(ss, stackTop, stackBot);
return res;
}
diff --git a/mps/code/ssw3i3.c b/mps/code/ssw3i3.c
index f9b2646b3b6..40f412b12ae 100644
--- a/mps/code/ssw3i3.c
+++ b/mps/code/ssw3i3.c
@@ -35,7 +35,7 @@ Res StackScan(ScanState ss, Addr *stackBot)
}
AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .align */
- res = TraceScanArea(ss, stackTop, stackBot);
+ res = TraceScanAreaTagged(ss, stackTop, stackBot);
__asm {
add esp, 0xc /* pop 3 registers to restore the stack pointer */
diff --git a/mps/code/ssw3i6.asm b/mps/code/ssw3i6.asm
index 4589147758f..c856ef47c33 100644
--- a/mps/code/ssw3i6.asm
+++ b/mps/code/ssw3i6.asm
@@ -9,7 +9,7 @@
;
.CODE
-EXTERN TraceScanArea : PROC
+EXTERN TraceScanAreaTagged : PROC
StackScan PROC FRAME
; Prolog follows. See
@@ -56,7 +56,7 @@ StackScan PROC FRAME
mov rdx, rsp ; top of stack
add rdx, 40 ; where last callee-save register stored
; mov rcx, rcx ; ss already in the right register.
- call TraceScanArea
+ call TraceScanAreaTagged
add rsp, 40
pop r15 ; pop the callee-save registers
pop r14
diff --git a/mps/code/trace.c b/mps/code/trace.c
index a12800d4dd9..0f8d84ba3ac 100644
--- a/mps/code/trace.c
+++ b/mps/code/trace.c
@@ -138,6 +138,7 @@ Bool TraceCheck(Trace trace)
CHECKL(TraceIdCheck(trace->ti));
CHECKL(trace == &trace->arena->trace[trace->ti]);
CHECKL(TraceSetIsMember(trace->arena->busyTraces, trace));
+ CHECKL(AlignCheck(trace->whiteMinAlign));
CHECKL(ZoneSetSub(trace->mayMove, trace->white));
/* Use trace->state to check more invariants. */
switch(trace->state) {
@@ -367,6 +368,10 @@ Res TraceAddWhite(Trace trace, Seg seg)
trace->mayMove = ZoneSetUnion(trace->mayMove,
ZoneSetOfSeg(trace->arena, seg));
}
+ /* This is used to eliminate unaligned references in TraceScanAreaTagged */
+ if(pool->alignment < trace->whiteMinAlign) {
+ trace->whiteMinAlign = pool->alignment;
+ }
}
return ResOK;
@@ -656,6 +661,7 @@ found:
trace->arena = arena;
trace->why = why;
+ trace->whiteMinAlign = (Align)1 << (MPS_WORD_WIDTH - 1);
trace->white = ZoneSetEMPTY;
trace->mayMove = ZoneSetEMPTY;
trace->ti = ti;
@@ -1402,13 +1408,37 @@ Res TraceScanArea(ScanState ss, Addr *base, Addr *limit)
/* TraceScanAreaTagged -- scan contiguous area of tagged references
*
- * This is as TraceScanArea except words are only fixed if they are
- * tagged as Dylan references (i.e., bottom two bits are zero). @@@@
- * This Dylan-specificness should be generalized in some way. */
-
+ * This is as TraceScanArea except words are only fixed they are tagged
+ * as zero according to the minimum alignment of the condemned set.
+ */
Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit)
{
- return TraceScanAreaMasked(ss, base, limit, (Word)3);
+ TraceSet ts;
+ TraceId ti;
+ Trace trace;
+ Arena arena;
+ Word mask;
+
+ AVERT(ScanState, ss);
+
+ /* This calculation of the mask could be moved to ScanStateInit
+ * but there is little point as we probably only do a couple of ambiguous
+ * scan per thread per flip. */
+ /* NOTE: An optimisation that maybe worth considering is setting some of the
+ * top bits in the mask as an early catch of addresses outside the arena.
+ * This might help slightly on 64-bit windows. However these are picked up
+ * soon afterwards by later checks. The bottom bits are more important
+ * to check as we ignore them in AMCFix, so the non-reference could
+ * otherwise end up pinning an object. */
+ mask = (Word)-1;
+ ts = ss->traces;
+ arena = ss->arena;
+ TRACE_SET_ITER(ti, trace, ts, arena)
+ AVER(WordIsP2(trace->whiteMinAlign));
+ mask = mask & (trace->whiteMinAlign - 1);
+ TRACE_SET_ITER_END(ti, trace, ts, arena);
+
+ return TraceScanAreaMasked(ss, base, limit, mask);
}
@@ -1423,6 +1453,7 @@ Res TraceScanAreaMasked(ScanState ss, Addr *base, Addr *limit, Word mask)
Addr *p;
Ref ref;
+ AVERT(ScanState, ss);
AVER(base != NULL);
AVER(limit != NULL);
AVER(base < limit);
--
cgit v1.2.1