1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-26 08:41:47 -07:00

Make awl (and lo) work with auto-header formats.

New test awluthe, based on awlut, using auto-header format in AWL
and LO.  Seems to work.  Not the greatest test ever.

Copied from Perforce
 Change: 28076
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Nick Barnes 2002-04-11 15:10:37 +01:00
parent a87c3633dc
commit cf42e2e28e
7 changed files with 631 additions and 32 deletions

326
mps/code/awluthe.c Normal file
View file

@ -0,0 +1,326 @@
/* impl.c.awluthe: POOL CLASS AWL UNIT TEST WITH OBJECT HEADERS
*
* $Id$
* Copyright (c) 2001 Ravenbrook Limited.
*
* DESIGN
*
* .design: see design.mps.poolawl.test.*
*/
#include "mpscawl.h"
#include "mpsclo.h"
#include "mpsavm.h"
#include "fmthe.h"
#include "testlib.h"
#include "mps.h"
#include "mpstd.h"
#ifdef MPS_OS_W3
#include "mpsw3.h"
#endif
#include <string.h>
#define testArenaSIZE ((size_t)64<<20)
#define TABLE_SLOTS 49
#define ITERATIONS 5000
#define CHATTER 100
static mps_word_t bogus_class;
#define UNINIT 0x041412ED
#define DYLAN_ALIGN 4 /* depends on value defined in fmtdy.c */
/* size_tAlignUp -- align w up to alignment a */
#define size_tAlignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1))
static mps_word_t wrapper_wrapper[] = {
UNINIT, /* wrapper */
UNINIT, /* class */
0, /* Extra word */
4uL<<2|2, /* F */
2uL<<(MPS_WORD_WIDTH - 8), /* V */
1uL<<2|1, /* VL */
1 /* patterns */
};
static mps_word_t string_wrapper[] = {
UNINIT, /* wrapper */
UNINIT, /* class */
0, /* extra word */
0, /* F */
2uL<<(MPS_WORD_WIDTH - 8)|3uL<<3|4, /* V */
1 /* VL */
};
static mps_word_t table_wrapper[] = {
UNINIT, /* wrapper */
UNINIT, /* class */
0, /* extra word */
1uL<<2|1, /* F */
2uL<<(MPS_WORD_WIDTH - 8)|2, /* V */
1 /* VL */
};
static void initialise_wrapper(mps_word_t *wrapper)
{
wrapper[0] = (mps_word_t)&wrapper_wrapper;
wrapper[1] = (mps_word_t)&bogus_class;
}
/* alloc_string - create a dylan string object
*
* create a dylan string object (byte vector) whose contents
* are the string s (including the terminating NUL)
* .assume.dylan-obj
*/
static mps_word_t *alloc_string(char *s, mps_ap_t ap)
{
size_t l;
size_t objsize;
void *p;
mps_word_t *object;
l = strlen(s)+1;
/* number of words * sizeof word */
objsize = (2 + (l+sizeof(mps_word_t)-1)/sizeof(mps_word_t))
* sizeof(mps_word_t);
objsize = size_tAlignUp(objsize, DYLAN_ALIGN);
do {
size_t i;
char *s2;
die(mps_reserve(&p, ap, objsize + headerSIZE), "Reserve Leaf\n");
object = (mps_word_t *)((char *)p + headerSIZE);
object[0] = (mps_word_t)string_wrapper;
object[1] = l << 2 | 1;
s2 = (char *)&object[2];
for(i = 0; i < l; ++i) {
s2[i] = s[i];
}
((int*)p)[0] = realHeader;
((int*)p)[1] = 0xED0ED;
} while(!mps_commit(ap, p, objsize + headerSIZE));
return object;
}
/* alloc_table -- create a table with n variable slots
*
* .assume.dylan-obj
*/
static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap)
{
size_t objsize;
void *p;
mps_word_t *object;
objsize = (3 + n) * sizeof(mps_word_t);
objsize = size_tAlignUp(objsize, MPS_PF_ALIGN);
do {
unsigned long i;
die(mps_reserve(&p, ap, objsize + headerSIZE), "Reserve Table\n");
object = (mps_word_t *)((char *)p + headerSIZE);
object[0] = (mps_word_t)table_wrapper;
object[1] = 0;
object[2] = n << 2 | 1;
for(i = 0; i < n; ++i) {
object[3+i] = 0;
}
((int*)p)[0] = realHeader;
((int*)p)[1] = 0xED0ED;
} while(!mps_commit(ap, p, objsize + headerSIZE));
return object;
}
/* gets the nth slot from a table
* .assume.dylan-obj
*/
static mps_word_t *table_slot(mps_word_t *table, unsigned long n)
{
return (mps_word_t *)table[3+n];
}
/* sets the nth slot in a table
* .assume.dylan-obj
*/
static void set_table_slot(mps_word_t *table,
unsigned long n, mps_word_t *p)
{
cdie(table[0] == (mps_word_t)table_wrapper, "set_table_slot");
table[3+n] = (mps_word_t)p;
}
/* links two tables together via their link slot
* (1st fixed part slot)
*/
static void table_link(mps_word_t *t1, mps_word_t *t2)
{
cdie(t1[0] == (mps_word_t)table_wrapper, "table_link 1");
cdie(t2[0] == (mps_word_t)table_wrapper, "table_link 2");
t1[1] = (mps_word_t)t2;
t2[1] = (mps_word_t)t1;
}
static void test(mps_ap_t leafap, mps_ap_t exactap, mps_ap_t weakap,
mps_ap_t bogusap)
{
mps_word_t *weaktable;
mps_word_t *exacttable;
mps_word_t *preserve[TABLE_SLOTS]; /* preserves objects in the weak */
/* table by referring to them */
unsigned long i, j;
void *p;
exacttable = alloc_table(TABLE_SLOTS, exactap);
weaktable = alloc_table(TABLE_SLOTS, weakap);
table_link(exacttable, weaktable);
/* Leave bogusap between reserve and commit for the duration */
die(mps_reserve(&p, bogusap, 64), "Reserve bogus");
for(i = 0; i < TABLE_SLOTS; ++i) {
mps_word_t *string;
if (rnd() % 2 == 0) {
string = alloc_string("iamalive", leafap);
preserve[i] = string;
} else {
string = alloc_string("iamdead", leafap);
preserve[i] = 0;
}
set_table_slot(weaktable, i, string);
string = alloc_string("iamexact", leafap);
set_table_slot(exacttable, i, string);
}
for(j = 0; j < ITERATIONS; ++j) {
for(i = 0; i < TABLE_SLOTS; ++i) {
mps_word_t *string;
string = alloc_string("spong", leafap);
}
}
for(i = 0; i < TABLE_SLOTS; ++i) {
if (preserve[i] == 0) {
if (table_slot(weaktable, i)) {
error("Strongly unreachable weak table entry found, slot %lu.\n", i);
} else {
if (table_slot(exacttable, i) != 0) {
error("Weak table entry deleted, but corresponding "
"exact table entry not deleted, slot %lu.\n", i);
}
}
}
}
(void)mps_commit(bogusap, p, 64);
}
/* setup -- set up pools for the test
*
* v serves two purposes:
* - a pseudo stack base for the stack root.
* - pointer to a guff structure, which packages some values needed
* (arena and thr mostly)
*/
struct guff_s {
mps_arena_t arena;
mps_thr_t thr;
};
static void *setup(void *v, size_t s)
{
struct guff_s *guff;
mps_arena_t arena;
mps_pool_t leafpool;
mps_pool_t tablepool;
mps_fmt_t dylanfmt;
mps_fmt_t dylanweakfmt;
mps_ap_t leafap, exactap, weakap, bogusap;
mps_root_t stack;
mps_thr_t thr;
guff = (struct guff_s *)v;
(void)s;
arena = guff->arena;
thr = guff->thr;
die(mps_root_create_reg(&stack, arena, MPS_RANK_AMBIG, 0, thr,
mps_stack_scan_ambig, v, 0),
"Root Create\n");
EnsureHeaderFormat(&dylanfmt, arena);
EnsureHeaderWeakFormat(&dylanweakfmt, arena);
die(mps_pool_create(&leafpool, arena, mps_class_lo(), dylanfmt),
"Leaf Pool Create\n");
die(mps_pool_create(&tablepool, arena, mps_class_awl(), dylanweakfmt,
dylan_weak_dependent),
"Table Pool Create\n");
die(mps_ap_create(&leafap, leafpool, MPS_RANK_EXACT),
"Leaf AP Create\n");
die(mps_ap_create(&exactap, tablepool, MPS_RANK_EXACT),
"Exact AP Create\n");
die(mps_ap_create(&weakap, tablepool, MPS_RANK_WEAK),
"Weak AP Create\n");
die(mps_ap_create(&bogusap, tablepool, MPS_RANK_EXACT),
"Bogus AP Create\n");
test(leafap, exactap, weakap, bogusap);
mps_ap_destroy(bogusap);
mps_ap_destroy(weakap);
mps_ap_destroy(exactap);
mps_ap_destroy(leafap);
mps_pool_destroy(tablepool);
mps_pool_destroy(leafpool);
mps_fmt_destroy(dylanweakfmt);
mps_fmt_destroy(dylanfmt);
mps_root_destroy(stack);
return NULL;
}
int main(int argc, char **argv)
{
struct guff_s guff;
mps_arena_t arena;
mps_thr_t thread;
void *r;
randomize(argc, argv);
initialise_wrapper(wrapper_wrapper);
initialise_wrapper(string_wrapper);
initialise_wrapper(table_wrapper);
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
"arena_create\n");
die(mps_thread_reg(&thread, arena), "thread_reg");
guff.arena = arena;
guff.thr = thread;
mps_tramp(&r, setup, &guff, 0);
mps_thread_dereg(thread);
mps_arena_destroy(arena);
fflush(stdout); /* synchronize */
fprintf(stderr, "\nConclusion: Failed to find any defects.\n");
return 0;
}

View file

@ -277,7 +277,7 @@ endif
# %%TARGET: Add the target to the all dependencies, if it uses the
# CONFIG_PROD_MPS configuration, to swall if CONFIG_PROD_EPCORE
all: mpmss sacss amcss amcsshe amsss segsmss awlut \
all: mpmss sacss amcss amcsshe amsss segsmss awlut awluthe \
mpsicv lockcov poolncv locv qs apss \
finalcv arenacv bttest teletest \
abqtest cbstest btcv mv2test messtest \
@ -289,8 +289,9 @@ swall: mmsw.a epvmss replaysw epdss
# These tests are run overnight (see design.buildsys.overnight).
# bttest & teletest cannot be run unattended
# mv2test cannot be run because MV2 is broken
testrun: mpmss apss sacss amcss amcsshe amsss segsmss awlut mpsicv lockcov \
poolncv locv qs finalcv arenacv abqtest cbstest btcv messtest
testrun: mpmss apss sacss amcss amcsshe amsss segsmss awlut awluthe \
mpsicv lockcov poolncv locv qs finalcv arenacv \
abqtest cbstest btcv messtest
$(^:%=date && $(PFM)/$(VARIETY)/% &&) true
# Runs the automatic tests that are built with CONFIG_PROD_EPCORE
@ -304,7 +305,7 @@ testrunep: epvmss epdss
# %%TARGET: Add a pseudo-target for the new target here.
mpmss sacss amcss amcssth amcsshe amsss segsmss awlut awlutth \
mpsicv lockcov poolncv locv qs apss \
awluthe mpsicv lockcov poolncv locv qs apss \
finalcv arenacv bttest teletest epvmss epdss \
abqtest cbstest btcv mv2test \
messtest \
@ -409,6 +410,9 @@ $(PFM)/$(VARIETY)/epdss: $(PFM)/$(VARIETY)/epdss.o \
$(PFM)/$(VARIETY)/awlut: $(PFM)/$(VARIETY)/awlut.o \
$(FMTDYTSTOBJ) $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ)
$(PFM)/$(VARIETY)/awluthe: $(PFM)/$(VARIETY)/awluthe.o \
$(PFM)/$(VARIETY)/fmthe.o $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ)
$(PFM)/$(VARIETY)/awlutth: $(PFM)/$(VARIETY)/awlutth.o \
$(FMTDYTSTOBJ) $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ)

View file

@ -159,7 +159,7 @@ static int dylan_wrapper_check(mps_word_t *w)
/* size. This assumes that DylanWorks is only going to use byte */
/* vectors in the non-word case. */
/* Variable part format 6 is reserved. */
/* Variable part format 6 is reserved. */
assert(vf != 6);
/* There should be no shift in word vector formats. */
@ -216,6 +216,79 @@ static mps_res_t dylan_scan_contig(mps_ss_t mps_ss,
return MPS_RES_OK;
}
/* dylan_weak_dependent -- returns the linked object, if any.
*/
extern mps_addr_t dylan_weak_dependent(mps_addr_t parent)
{
mps_word_t *object;
mps_word_t *wrapper;
mps_word_t fword;
mps_word_t fl;
mps_word_t ff;
assert(parent != NULL);
object = (mps_word_t *)parent;
wrapper = (mps_word_t *)object[0];
assert(dylan_wrapper_check(wrapper));
fword = wrapper[3];
ff = fword & 3;
/* traceable fixed part */
assert(ff == 1);
fl = fword & ~3uL;
/* at least one fixed field */
assert(fl >= 1);
return (mps_addr_t) object[1];
}
/* Scan weakly a contiguous array of references in [base, limit). */
/* Only required to scan vectors for Dylan Weak Tables. */
/* Depends on the vector length field being scannable (ie a tagged */
/* integer). */
/* When a reference that has been fixed to NULL is detected the */
/* corresponding reference in the associated table (pointed to be the */
/* assoc variable) will be deleted. */
static mps_res_t
dylan_scan_contig_weak(mps_ss_t mps_ss,
mps_addr_t *base, mps_addr_t *limit,
mps_addr_t *objectBase, mps_addr_t *assoc)
{
mps_addr_t *p;
mps_res_t res;
mps_addr_t r;
MPS_SCAN_BEGIN(mps_ss) {
p = base;
goto skip_inc;
loop:
++p;
skip_inc:
if(p >= limit)
goto out;
r = *p;
if(((mps_word_t)r & 3) != 0) /* non-pointer */
goto loop;
if(!MPS_FIX1(mps_ss, r))
goto loop;
res = MPS_FIX2(mps_ss, p);
if(res == MPS_RES_OK) {
if(*p == 0 && r != 0) {
if(assoc != NULL) {
assoc[p-objectBase] = 0; /* delete corresponding entry */
}
}
goto loop;
}
return res;
out:
assert(p == limit);
} MPS_SCAN_END(mps_ss);
return MPS_RES_OK;
}
/* dylan_scan_pat -- scan according to pattern
*
@ -450,6 +523,97 @@ static mps_res_t dylan_scan(mps_ss_t mps_ss,
}
static mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io)
{
mps_addr_t *assoc;
mps_addr_t *base;
mps_addr_t *p, q;
mps_res_t res;
mps_word_t *w;
mps_word_t fword, ff, fl;
mps_word_t h;
mps_word_t vword, vf, vl;
int header;
assert(object_io != NULL);
base = (mps_addr_t *)*object_io;
assert(base != NULL);
p = base;
header = *(int*)((char*)p - headerSIZE);
switch(headerType(header)) {
case realTYPE:
break;
case padTYPE:
*object_io = (mps_addr_t)((char*)p + headerPadSize(header));
return MPS_RES_OK;
default:
notreached();
break;
}
h = (mps_word_t)p[0];
/* object should not be forwarded (as there is no forwarding method) */
assert((h & 3) == 0);
mps_fix(mps_ss, p);
/* w points to wrapper */
w = (mps_word_t *)p[0];
assert(dylan_wrapper_check(w));
++p; /* skip header */
fword = w[WF];
fl = fword >> 2;
/* weak vectors should have at least one fixed field */
/* (for assoc field) */
assert(fl >= 1);
ff = fword & 3;
/* weak vectors should have traceable fixed format */
assert(ff == 1);
assoc = (mps_addr_t *)p[0];
vword = w[WV];
vf = vword & 7;
vl = (mps_word_t)p[fl] >> 2;
/* weak vectors should be non-stretchy traceable */
assert(vf == 2);
/* q is end of the object. There are fl fixed fields, vl variable */
/* fields and another slot that contains the vector length */
q = p + fl + vl + 1;
res = dylan_scan_contig_weak(mps_ss, p, q, base, assoc);
if(res != MPS_RES_OK) {
return res;
}
*object_io = AddHeader(q);
return MPS_RES_OK;
}
static mps_res_t dylan_scan_weak(mps_ss_t mps_ss,
mps_addr_t base, mps_addr_t limit)
{
mps_res_t res;
while(base < limit) {
res = dylan_scan1_weak(mps_ss, &base);
if(res) return res;
}
assert(base <= AddHeader(limit));
return MPS_RES_OK;
}
static mps_addr_t dylan_skip(mps_addr_t object)
{
mps_addr_t *p; /* cursor in object */
@ -563,6 +727,25 @@ static void dylan_pad(mps_addr_t addr, size_t fullSize)
}
static mps_addr_t dylan_no_isfwd(mps_addr_t object)
{
unused(object);
notreached();
return 0;
}
static void dylan_no_fwd(mps_addr_t old, mps_addr_t new)
{
unused(old); unused(new);
notreached();
}
static void dylan_no_pad(mps_addr_t addr, size_t size)
{
unused(addr); unused(size);
notreached();
}
/* HeaderFormat -- format descriptor for this format */
static struct mps_fmt_auto_header_s HeaderFormat =
@ -577,6 +760,20 @@ static struct mps_fmt_auto_header_s HeaderFormat =
};
/* HeaderWeakFormat -- format descriptor for this format */
static struct mps_fmt_auto_header_s HeaderWeakFormat =
{
ALIGN,
dylan_scan_weak,
dylan_skip,
dylan_no_fwd,
dylan_no_isfwd,
dylan_no_pad,
(size_t)headerSIZE
};
/* EnsureHeaderFormat -- create a format object for this format */
mps_res_t EnsureHeaderFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena)
@ -585,6 +782,14 @@ mps_res_t EnsureHeaderFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena)
}
/* EnsureHeaderWeakFormat -- create a format object for the weak format */
mps_res_t EnsureHeaderWeakFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena)
{
return mps_fmt_create_auto_header(mps_fmt_o, arena, &HeaderWeakFormat);
}
/* HeaderFormatCheck -- check an object in this format */
mps_res_t HeaderFormatCheck(mps_addr_t addr)
@ -595,3 +800,14 @@ mps_res_t HeaderFormatCheck(mps_addr_t addr)
else
return MPS_RES_FAIL;
}
/* HeaderWeakFormatCheck -- check an object in this format */
mps_res_t HeaderWeakFormatCheck(mps_addr_t addr)
{
if (addr != 0 && ((mps_word_t)addr & (ALIGN-1)) == 0
&& dylan_wrapper_check((mps_word_t *)((mps_word_t *)addr)[0]))
return MPS_RES_OK;
else
return MPS_RES_FAIL;
}

View file

@ -10,10 +10,14 @@
#include "mps.h"
/* Format */
/* Formats */
extern mps_res_t EnsureHeaderFormat(mps_fmt_t *, mps_arena_t);
extern mps_res_t EnsureHeaderWeakFormat(mps_fmt_t *, mps_arena_t);
extern mps_res_t HeaderFormatCheck(mps_addr_t addr);
extern mps_res_t HeaderWeakFormatCheck(mps_addr_t addr);
/* dependent object function for weak pool */
extern mps_addr_t dylan_weak_dependent(mps_addr_t);
/* Constants describing wrappers. Used only for debugging / testing */
#define WW 0 /* offset of Wrapper-Wrapper */

View file

@ -15,8 +15,8 @@ LIBS = -lm -pthread
include gc.gmk
CFLAGSDEBUG = -g -ggdb
CFLAGSOPT = -O -g -ggdb
CFLAGSDEBUG = -g
CFLAGSOPT = -O -g
CC = cc

View file

@ -792,9 +792,10 @@ static void AWLBlacken(Pool pool, TraceSet traceSet, Seg seg)
/* awlScanObject -- scan a single object */
/* base and limit are both offset by the header size */
static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
FormatScanMethod scan, Addr base, Addr limit)
Format format, Addr base, Addr limit)
{
Res res;
Bool dependent; /* is there a dependent object? */
@ -804,7 +805,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
AVERT(Arena, arena);
AVERT(AWL, awl);
AVERT(ScanState, ss);
AVER(FUNCHECK(scan));
AVERT(Format, format);
AVER(base != 0);
AVER(base < limit);
@ -817,7 +818,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
SegSetSummary(dependentSeg, RefSetUNIV);
}
res = (*scan)(ss, base, limit);
res = (*format->scan)(ss, base, limit);
if (res == ResOK)
ss->scannedSize += AddrOffset(base, limit);
@ -836,10 +837,12 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
{
Addr base, limit, bufferScanLimit;
Addr p;
Addr hp;
Arena arena;
AWL awl;
AWLSeg awlseg;
Buffer buffer;
Format format;
AVERT(ScanState, ss);
AVERT(Pool, pool);
@ -851,6 +854,9 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
arena = PoolArena(pool);
AVERT(Arena, arena);
format = pool->format;
AVERT(Format, format);
awlseg = Seg2AWLSeg(seg);
AVERT(AWLSeg, awlseg);
*anyScannedReturn = FALSE;
@ -878,17 +884,19 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
p = AddrAdd(p, pool->alignment);
continue;
}
objectLimit = (*pool->format->skip)(p);
hp = AddrAdd(p, format->headerSize);
objectLimit = (format->skip)(hp);
/* design.mps.poolawl.fun.scan.pass.object */
if (scanAllObjects
|| (BTGet(awlseg->mark, i) && !BTGet(awlseg->scanned, i))) {
Res res = awlScanObject(arena, awl, ss, pool->format->scan,
p, objectLimit);
Res res = awlScanObject(arena, awl, ss, pool->format,
hp, objectLimit);
if (res != ResOK)
return res;
*anyScannedReturn = TRUE;
BTSet(awlseg->scanned, i);
}
objectLimit = AddrSub(objectLimit, format->headerSize);
AVER(p < objectLimit);
p = AddrAlignUp(objectLimit, pool->alignment);
}
@ -954,7 +962,8 @@ static Res AWLScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
{
Ref ref;
Ref clientRef;
Addr base;
Index i;
AWL awl;
AWLSeg awlseg;
@ -970,15 +979,23 @@ static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
awlseg = Seg2AWLSeg(seg);
AVERT(AWLSeg, awlseg);
ref = *refIO;
i = awlIndexOfAddr(SegBase(seg), awl, ref);
clientRef = *refIO;
ss->wasMarked = TRUE;
base = AddrSub((Addr)clientRef, pool->format->headerSize);
/* can get an ambiguous reference to close to the base of the
* segment, so when we subtract the header we are not in the
* segment any longer. This isn't a real reference,
* so we can just skip it. */
if (base < SegBase(seg)) {
return ResOK;
}
i = awlIndexOfAddr(SegBase(seg), awl, base);
switch(ss->rank) {
case RankAMBIG:
/* not a real pointer if not aligned or not allocated */
if (!AddrIsAligned((Addr)ref, pool->alignment) || !BTGet(awlseg->alloc, i))
if (!AddrIsAligned(base, pool->alignment) || !BTGet(awlseg->alloc, i))
return ResOK;
/* falls through */
case RankEXACT:
@ -1012,6 +1029,7 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
AWLSeg awlseg;
Index i;
Count oldFree;
Format format;
Count preservedInPlaceCount = (Count)0;
Size preservedInPlaceSize = (Size)0;
Size freed; /* amount reclaimed, in bytes */
@ -1025,6 +1043,8 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
awlseg = Seg2AWLSeg(seg);
AVERT(AWLSeg, awlseg);
format = pool->format;
base = SegBase(seg);
i = 0; oldFree = awlseg->free;
@ -1046,7 +1066,9 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
continue;
}
}
q = AddrAlignUp(pool->format->skip(p), pool->alignment);
q = format->skip(AddrAdd(p, format->headerSize));
q = AddrSub(q, format->headerSize);
q = AddrAlignUp(q, pool->alignment);
j = awlIndexOfAddr(base, awl, q);
AVER(j <= awlseg->grains);
if (BTGet(awlseg->mark, i)) {
@ -1123,6 +1145,7 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
AWL awl;
AWLSeg awlseg;
Addr object, base, limit;
Format format;
AVERT(Pool, pool);
AVERT(Seg, seg);
@ -1134,6 +1157,8 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
awlseg = Seg2AWLSeg(seg);
AVERT(AWLSeg, awlseg);
format = pool->format;
base = SegBase(seg);
object = base;
limit = SegLimit(seg);
@ -1162,7 +1187,10 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
object = AddrAdd(object, pool->alignment);
continue;
}
next = AddrAlignUp((*pool->format->skip)(object), pool->alignment);
object = AddrAdd(object, format->headerSize);
next = format->skip(object);
next = AddrSub(next, format->headerSize);
next = AddrAlignUp(next, pool->alignment);
if (BTGet(awlseg->mark, i) && BTGet(awlseg->scanned, i))
(*f)(object, pool->format, pool, p, s);
object = next;

View file

@ -329,6 +329,7 @@ static void loSegReclaim(LOSeg loseg, Trace trace)
Count bytesReclaimed = (Count)0;
Seg seg;
LO lo;
Format format;
Count preservedInPlaceCount = (Count)0;
Size preservedInPlaceSize = (Size)0;
@ -341,6 +342,9 @@ static void loSegReclaim(LOSeg loseg, Trace trace)
limit = SegLimit(seg);
marked = FALSE;
format = LOPool(lo)->format;
AVERT(Format, format);
/* i is the index of the current pointer,
* p is the actual address that is being considered.
* j and q act similarly for a pointer which is used to
@ -370,7 +374,8 @@ static void loSegReclaim(LOSeg loseg, Trace trace)
p = AddrAdd(p, LOPool(lo)->alignment);
continue;
}
q = (*LOPool(lo)->format->skip)(p);
q = (*format->skip)(AddrAdd(p, format->headerSize));
q = AddrSub(q, format->headerSize);
if(BTGet(loseg->mark, i)) {
marked = TRUE;
++preservedInPlaceCount;
@ -409,6 +414,7 @@ static void LOWalk(Pool pool, Seg seg,
LO lo;
LOSeg loseg;
Index i, limit;
Format format;
AVERT(Pool, pool);
AVERT(Seg, seg);
@ -420,6 +426,9 @@ static void LOWalk(Pool pool, Seg seg,
loseg = SegLOSeg(seg);
AVERT(LOSeg, loseg);
format = pool->format;
AVERT(Format, format);
base = SegBase(seg);
limit = SegSize(seg) >> lo->alignShift;
i = 0;
@ -449,7 +458,9 @@ static void LOWalk(Pool pool, Seg seg,
++i;
continue;
}
next = (*pool->format->skip)(object);
object = AddrAdd(object, format->headerSize);
next = (*format->skip)(object);
next = AddrSub(object, format->headerSize);
j = loIndexOfAddr(base, lo, next);
AVER(i < j);
(*f)(object, pool->format, pool, p, s);
@ -474,9 +485,9 @@ static Res LOInit(Pool pool, va_list arg)
format = va_arg(arg, Format);
AVERT(Format, format);
lo = PoolPoolLO(pool);
pool->format = format;
lo->poolStruct.alignment = format->alignment;
lo->alignShift =
@ -508,7 +519,7 @@ static void LOFinish(Pool pool)
{
LO lo;
Ring node, nextNode;
AVERT(Pool, pool);
lo = PoolPoolLO(pool);
AVERT(LO, lo);
@ -618,7 +629,7 @@ static void LOBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
seg = BufferSeg(buffer);
AVERT(Seg, seg);
AVER(init <= limit);
loseg = SegLOSeg(seg);
AVERT(LOSeg, loseg);
AVER(loseg->lo == lo);
@ -657,7 +668,7 @@ static Res LOWhiten(Pool pool, Trace trace, Seg seg)
{
LO lo;
unsigned long bits;
AVERT(Pool, pool);
lo = PoolPoolLO(pool);
AVERT(LO, lo);
@ -689,14 +700,14 @@ static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
{
LO lo;
LOSeg loseg;
Ref ref;
Ref clientRef;
Addr base;
AVERT_CRITICAL(Pool, pool);
AVERT_CRITICAL(ScanState, ss);
AVERT_CRITICAL(Seg, seg);
AVER_CRITICAL(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY);
AVER_CRITICAL(refIO != NULL);
ref = *refIO;
lo = PARENT(LOStruct, poolStruct, pool);
AVERT_CRITICAL(LO, lo);
loseg = SegLOSeg(seg);
@ -704,9 +715,19 @@ static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
ss->wasMarked = TRUE; /* design.mps.fix.protocol.was-marked */
clientRef = *refIO;
base = AddrSub((Addr)clientRef, pool->format->headerSize);
/* can get an ambiguous reference to close to the base of the
* segment, so when we subtract the header we are not in the
* segment any longer. This isn't a real reference,
* so we can just skip it. */
if (base < SegBase(seg)) {
return ResOK;
}
switch(ss->rank) {
case RankAMBIG:
if(!AddrIsAligned(ref, PoolAlignment(pool))) {
if(!AddrIsAligned(base, PoolAlignment(pool))) {
return ResOK;
}
/* fall through */
@ -714,7 +735,7 @@ static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
case RankEXACT:
case RankFINAL:
case RankWEAK: {
Size i = AddrOffset(SegBase(seg), (Addr)ref) >> lo->alignShift;
Size i = AddrOffset(SegBase(seg), base) >> lo->alignShift;
if(!BTGet(loseg->mark, i)) {
ss->wasMarked = FALSE; /* design.mps.fix.protocol.was-marked */