1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-23 06:00:41 -08:00

New function mps_root_create_reg_masked applies a mask and pattern test to all words in registers and on the stack when scanning them. this supports tagged references in these locations.

Consistently use the type "Word *" for pointers into the stack or into saved registers.
Remove TraceScanAreaTagged.

Copied from Perforce
 Change: 188231
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2015-09-04 12:22:03 +01:00
parent 3e9433f28f
commit edf30c06b4
31 changed files with 335 additions and 174 deletions

View file

@ -472,10 +472,9 @@ extern double TraceWorkFactor;
} \ } \
END END
extern Res TraceScanArea(ScanState ss, Addr *base, Addr *limit); extern Res TraceScanArea(ScanState ss, Word *base, Word *limit);
extern Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit); extern Res TraceScanAreaMasked(ScanState ss, Word *base, Word *limit,
extern Res TraceScanAreaMasked(ScanState ss, Word mask, Word value);
Addr *base, Addr *limit, Word mask);
extern void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena, extern void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
Seg seg, Ref *refIO); Seg seg, Ref *refIO);
@ -948,15 +947,19 @@ extern void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from);
extern Res RootCreateTable(Root *rootReturn, Arena arena, extern Res RootCreateTable(Root *rootReturn, Arena arena,
Rank rank, RootMode mode, Rank rank, RootMode mode,
Addr *base, Addr *limit); Word *base, Word *limit);
extern Res RootCreateTableMasked(Root *rootReturn, Arena arena, extern Res RootCreateTableMasked(Root *rootReturn, Arena arena,
Rank rank, RootMode mode, Rank rank, RootMode mode,
Addr *base, Addr *limit, Word *base, Word *limit,
Word mask); Word mask);
extern Res RootCreateReg(Root *rootReturn, Arena arena, extern Res RootCreateReg(Root *rootReturn, Arena arena,
Rank rank, Thread thread, Rank rank, Thread thread,
mps_reg_scan_t scan, mps_reg_scan_t scan,
void *p, size_t s); void *p, size_t s);
extern Res RootCreateRegMasked(Root *rootReturn, Arena arena,
Rank rank, Thread thread,
Word mask, Word pattern,
Addr stackBot);
extern Res RootCreateFmt(Root *rootReturn, Arena arena, extern Res RootCreateFmt(Root *rootReturn, Arena arena,
Rank rank, RootMode mode, Rank rank, RootMode mode,
mps_fmt_scan_t scan, mps_fmt_scan_t scan,

View file

@ -791,7 +791,7 @@ typedef struct mps_arena_s {
Bool emergency; /* garbage collect in emergency mode? */ Bool emergency; /* garbage collect in emergency mode? */
Addr *stackAtArenaEnter; /* NULL or top of client stack, in the thread */ Word *stackAtArenaEnter; /* NULL or top of client stack, in the thread */
/* that then entered the MPS. */ /* that then entered the MPS. */
Sig sig; Sig sig;

View file

@ -362,6 +362,7 @@ enum {
RootTABLE, RootTABLE,
RootTABLE_MASKED, RootTABLE_MASKED,
RootREG, RootREG,
RootREG_MASKED,
RootFMT, RootFMT,
RootLIMIT RootLIMIT
}; };

View file

@ -672,6 +672,10 @@ extern mps_res_t mps_root_create_fmt(mps_root_t *, mps_arena_t,
extern mps_res_t mps_root_create_reg(mps_root_t *, mps_arena_t, extern mps_res_t mps_root_create_reg(mps_root_t *, mps_arena_t,
mps_rank_t, mps_rm_t, mps_thr_t, mps_rank_t, mps_rm_t, mps_thr_t,
mps_reg_scan_t, void *, size_t); mps_reg_scan_t, void *, size_t);
extern mps_res_t mps_root_create_reg_masked(mps_root_t *, mps_arena_t,
mps_rank_t, mps_rm_t, mps_thr_t,
mps_word_t, mps_word_t,
void *);
extern void mps_root_destroy(mps_root_t); extern void mps_root_destroy(mps_root_t);
extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t, extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t,

View file

@ -1304,7 +1304,7 @@ mps_res_t mps_root_create_table(mps_root_t *mps_root_o, mps_arena_t arena,
/* limit pointers. Be careful. */ /* limit pointers. Be careful. */
res = RootCreateTable(&root, arena, rank, mode, res = RootCreateTable(&root, arena, rank, mode,
(Addr *)base, (Addr *)base + size); (Word *)base, (Word *)base + size);
ArenaLeave(arena); ArenaLeave(arena);
@ -1335,7 +1335,7 @@ mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
/* See .root.table-size. */ /* See .root.table-size. */
res = RootCreateTableMasked(&root, arena, rank, mode, res = RootCreateTableMasked(&root, arena, rank, mode,
(Addr *)base, (Addr *)base + size, (Word *)base, (Word *)base + size,
mask); mask);
ArenaLeave(arena); ArenaLeave(arena);
@ -1401,6 +1401,37 @@ mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
} }
mps_res_t mps_root_create_reg_masked(mps_root_t *mps_root_o, mps_arena_t arena,
mps_rank_t mps_rank, mps_rm_t mps_rm,
mps_thr_t thread, mps_word_t mask,
mps_word_t pattern, void *reg_scan_p)
{
Rank rank = (Rank)mps_rank;
Root root;
Res res;
ArenaEnter(arena);
AVER(mps_root_o != NULL);
AVER(reg_scan_p != NULL); /* stackBot */
AVER(AddrIsAligned(reg_scan_p, sizeof(Word)));
AVER(rank == mps_rank_ambig());
AVER(mps_rm == (mps_rm_t)0);
AVER((~mask & pattern) == 0);
/* See .root-mode. */
res = RootCreateRegMasked(&root, arena, rank, thread,
mask, pattern, (Addr)reg_scan_p);
ArenaLeave(arena);
if (res != ResOK)
return (mps_res_t)res;
*mps_root_o = (mps_root_t)root;
return MPS_RES_OK;
}
/* mps_stack_scan_ambig -- scan the thread state ambiguously /* mps_stack_scan_ambig -- scan the thread state ambiguously
* *
* See .reg-scan. */ * See .reg-scan. */
@ -1410,7 +1441,7 @@ mps_res_t mps_stack_scan_ambig(mps_ss_t mps_ss,
{ {
ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss); ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss);
UNUSED(s); UNUSED(s);
return ThreadScan(ss, thread, p); return ThreadScan(ss, thread, (Word *)p, sizeof(mps_word_t) - 1, 0);
} }

View file

@ -38,17 +38,19 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
} }
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
Word mask, Word pattern)
{ {
Res res; Res res;
/* This scans the root registers (.context.regroots). It also unnecessarily /* This scans the root registers (.context.regroots). It also unnecessarily
scans the rest of the context. The optimisation to scan only relevant scans the rest of the context. The optimisation to scan only relevant
parts would be machine dependent. */ parts would be machine dependent. */
res = TraceScanAreaTagged( res = TraceScanAreaMasked(
ss, ss,
(Addr *)mfc->ucontext, (Word *)mfc->ucontext,
(Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))) (Word *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))),
mask, pattern
); );
return res; return res;

View file

@ -101,7 +101,8 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
} }
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
Word mask, Word pattern)
{ {
mcontext_t *mc; mcontext_t *mc;
Res res; Res res;
@ -110,9 +111,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
unnecessarily scans the rest of the context. The optimisation unnecessarily scans the rest of the context. The optimisation
to scan only relevant parts would be machine dependent. */ to scan only relevant parts would be machine dependent. */
mc = &mfc->ucontext->uc_mcontext; mc = &mfc->ucontext->uc_mcontext;
res = TraceScanAreaTagged(ss, res = TraceScanAreaMasked(ss,
(Addr *)mc, (Word *)mc,
(Addr *)((char *)mc + sizeof(*mc))); (Word *)((char *)mc + sizeof(*mc)),
mask, pattern);
return res; return res;
} }

View file

@ -96,7 +96,8 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
} }
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
Word mask, Word pattern)
{ {
x86_thread_state32_t *mc; x86_thread_state32_t *mc;
Res res; Res res;
@ -105,9 +106,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
unnecessarily scans the rest of the context. The optimisation unnecessarily scans the rest of the context. The optimisation
to scan only relevant parts would be machine dependent. */ to scan only relevant parts would be machine dependent. */
mc = mfc->threadState; mc = mfc->threadState;
res = TraceScanAreaTagged(ss, res = TraceScanAreaMasked(ss,
(Addr *)mc, (Word *)mc,
(Addr *)((char *)mc + sizeof(*mc))); (Word *)((char *)mc + sizeof(*mc)),
mask, pattern);
return res; return res;
} }

View file

@ -32,17 +32,19 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
} }
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
Word mask, Word pattern)
{ {
Res res; Res res;
/* This scans the root registers (.context.regroots). It also unnecessarily /* This scans the root registers (.context.regroots). It also unnecessarily
scans the rest of the context. The optimisation to scan only relevant scans the rest of the context. The optimisation to scan only relevant
parts would be machine dependent. */ parts would be machine dependent. */
res = TraceScanAreaTagged( res = TraceScanAreaMasked(
ss, ss,
(Addr *)mfc->ucontext, (Word *)mfc->ucontext,
(Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))) (Word *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))),
mask, pattern
); );
return res; return res;

View file

@ -105,7 +105,8 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
} }
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
Word mask, Word pattern)
{ {
mcontext_t *mc; mcontext_t *mc;
Res res; Res res;
@ -115,8 +116,9 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
to scan only relevant parts would be machine dependent. */ to scan only relevant parts would be machine dependent. */
mc = &mfc->ucontext->uc_mcontext; mc = &mfc->ucontext->uc_mcontext;
res = TraceScanAreaTagged(ss, res = TraceScanAreaTagged(ss,
(Addr *)mc, (Word *)mc,
(Addr *)((char *)mc + sizeof(*mc))); (Word *)((char *)mc + sizeof(*mc)),
mask, pattern);
return res; return res;
} }

View file

@ -99,7 +99,8 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
} }
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
Word mask, Word pattern)
{ {
x86_thread_state64_t *mc; x86_thread_state64_t *mc;
Res res; Res res;
@ -108,9 +109,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
unnecessarily scans the rest of the context. The optimisation unnecessarily scans the rest of the context. The optimisation
to scan only relevant parts would be machine dependent. */ to scan only relevant parts would be machine dependent. */
mc = mfc->threadState; mc = mfc->threadState;
res = TraceScanAreaTagged(ss, res = TraceScanAreaMasked(ss,
(Addr *)mc, (Word *)mc,
(Addr *)((char *)mc + sizeof(*mc))); (Word *)((char *)mc + sizeof(*mc)),
mask, pattern);
return res; return res;
} }

View file

@ -30,7 +30,8 @@ extern void ProtSync(Arena arena);
extern Bool ProtCanStepInstruction(MutatorFaultContext context); extern Bool ProtCanStepInstruction(MutatorFaultContext context);
extern Res ProtStepInstruction(MutatorFaultContext context); extern Res ProtStepInstruction(MutatorFaultContext context);
extern Addr MutatorFaultContextSP(MutatorFaultContext mfc); extern Addr MutatorFaultContextSP(MutatorFaultContext mfc);
extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc); extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
Word mask, Word pattern);
#endif /* prot_h */ #endif /* prot_h */

View file

@ -38,13 +38,14 @@ typedef struct RootStruct {
size_t s; /* environment for scan */ size_t s; /* environment for scan */
} fun; } fun;
struct { struct {
Addr *base; /* beginning of table */ Word *base; /* beginning of table */
Addr *limit; /* one off end of table */ Word *limit; /* one off end of table */
} table; } table;
struct { struct {
Addr *base; /* beginning of table */ Word *base; /* beginning of table */
Addr *limit; /* one off end of table */ Word *limit; /* one off end of table */
Word mask; /* tag mask for scanning */ Word mask; /* tag mask for scanning */
Word pattern; /* tag pattern for scanning */
} tableMasked; } tableMasked;
struct { struct {
mps_reg_scan_t scan; /* function for scanning registers */ mps_reg_scan_t scan; /* function for scanning registers */
@ -52,6 +53,12 @@ typedef struct RootStruct {
void *p; /* passed to scan */ void *p; /* passed to scan */
size_t s; /* passed to scan */ size_t s; /* passed to scan */
} reg; } reg;
struct {
Thread thread; /* passed to scan */
Word mask; /* tag mask for scanning */
Word pattern; /* tag pattern for scanning */
Word *stackBot; /* bottom of stack */
} regMasked;
struct { struct {
mps_fmt_scan_t scan; /* format-like scanner */ mps_fmt_scan_t scan; /* format-like scanner */
Addr base, limit; /* passed to scan */ Addr base, limit; /* passed to scan */
@ -67,7 +74,8 @@ typedef struct RootStruct {
Bool RootVarCheck(RootVar rootVar) Bool RootVarCheck(RootVar rootVar)
{ {
CHECKL(rootVar == RootTABLE || rootVar == RootTABLE_MASKED CHECKL(rootVar == RootTABLE || rootVar == RootTABLE_MASKED
|| rootVar == RootFUN || rootVar == RootFMT || rootVar == RootREG); || rootVar == RootFUN || rootVar == RootFMT || rootVar == RootREG
|| rootVar == RootREG_MASKED);
UNUSED(rootVar); UNUSED(rootVar);
return TRUE; return TRUE;
} }
@ -112,7 +120,7 @@ Bool RootCheck(Root root)
case RootTABLE_MASKED: case RootTABLE_MASKED:
CHECKL(root->the.tableMasked.base != 0); CHECKL(root->the.tableMasked.base != 0);
CHECKL(root->the.tableMasked.base < root->the.tableMasked.limit); CHECKL(root->the.tableMasked.base < root->the.tableMasked.limit);
/* Can't check anything about the mask. */ CHECKL((~root->the.tableMasked.mask & root->the.tableMasked.pattern) == 0);
break; break;
case RootFUN: case RootFUN:
@ -122,6 +130,13 @@ Bool RootCheck(Root root)
case RootREG: case RootREG:
CHECKL(root->the.reg.scan != NULL); CHECKL(root->the.reg.scan != NULL);
CHECKD_NOSIG(Thread, root->the.reg.thread); /* <design/check/#hidden-type> */ CHECKD_NOSIG(Thread, root->the.reg.thread); /* <design/check/#hidden-type> */
/* Can't check anything about p or s. */
break;
case RootREG_MASKED:
CHECKD_NOSIG(Thread, root->the.regMasked.thread); /* <design/check/#hidden-type> */
CHECKL((~root->the.regMasked.mask & root->the.regMasked.pattern) == 0);
/* Can't check anything about stackBot. */
break; break;
case RootFMT: case RootFMT:
@ -254,7 +269,7 @@ static Res rootCreateProtectable(Root *rootReturn, Arena arena,
} }
Res RootCreateTable(Root *rootReturn, Arena arena, Res RootCreateTable(Root *rootReturn, Arena arena,
Rank rank, RootMode mode, Addr *base, Addr *limit) Rank rank, RootMode mode, Word *base, Word *limit)
{ {
Res res; Res res;
union RootUnion theUnion; union RootUnion theUnion;
@ -276,7 +291,7 @@ Res RootCreateTable(Root *rootReturn, Arena arena,
} }
Res RootCreateTableMasked(Root *rootReturn, Arena arena, Res RootCreateTableMasked(Root *rootReturn, Arena arena,
Rank rank, RootMode mode, Addr *base, Addr *limit, Rank rank, RootMode mode, Word *base, Word *limit,
Word mask) Word mask)
{ {
union RootUnion theUnion; union RootUnion theUnion;
@ -291,6 +306,7 @@ Res RootCreateTableMasked(Root *rootReturn, Arena arena,
theUnion.tableMasked.base = base; theUnion.tableMasked.base = base;
theUnion.tableMasked.limit = limit; theUnion.tableMasked.limit = limit;
theUnion.tableMasked.mask = mask; theUnion.tableMasked.mask = mask;
theUnion.tableMasked.pattern = 0;
return rootCreateProtectable(rootReturn, arena, rank, mode, RootTABLE_MASKED, return rootCreateProtectable(rootReturn, arena, rank, mode, RootTABLE_MASKED,
(Addr)base, (Addr)limit, &theUnion); (Addr)base, (Addr)limit, &theUnion);
@ -317,6 +333,28 @@ Res RootCreateReg(Root *rootReturn, Arena arena,
return rootCreate(rootReturn, arena, rank, (RootMode)0, RootREG, &theUnion); return rootCreate(rootReturn, arena, rank, (RootMode)0, RootREG, &theUnion);
} }
Res RootCreateRegMasked(Root *rootReturn, Arena arena,
Rank rank, Thread thread,
Word mask, Word pattern, Addr stackBot)
{
union RootUnion theUnion;
AVER(rootReturn != NULL);
AVERT(Arena, arena);
AVERT(Rank, rank);
AVERT(Thread, thread);
AVER(ThreadArena(thread) == arena);
AVER((~mask & pattern) == 0);
theUnion.regMasked.thread = thread;
theUnion.regMasked.mask = mask;
theUnion.regMasked.pattern = pattern;
theUnion.regMasked.stackBot = stackBot;
return rootCreate(rootReturn, arena, rank, (RootMode)0, RootREG_MASKED,
&theUnion);
}
/* RootCreateFmt -- create root from block of formatted objects /* RootCreateFmt -- create root from block of formatted objects
* *
* .fmt.no-align-check: Note that we don't check the alignment of base * .fmt.no-align-check: Note that we don't check the alignment of base
@ -481,7 +519,8 @@ Res RootScan(ScanState ss, Root root)
res = TraceScanAreaMasked(ss, res = TraceScanAreaMasked(ss,
root->the.tableMasked.base, root->the.tableMasked.base,
root->the.tableMasked.limit, root->the.tableMasked.limit,
root->the.tableMasked.mask); root->the.tableMasked.mask,
root->the.tableMasked.pattern);
ss->scannedSize += AddrOffset(root->the.table.base, root->the.table.limit); ss->scannedSize += AddrOffset(root->the.table.base, root->the.table.limit);
if (res != ResOK) if (res != ResOK)
goto failScan; goto failScan;
@ -500,6 +539,15 @@ Res RootScan(ScanState ss, Root root)
goto failScan; goto failScan;
break; break;
case RootREG_MASKED:
res = ThreadScan(ss, root->the.regMasked.thread,
root->the.regMasked.stackBot,
root->the.regMasked.mask,
root->the.regMasked.pattern);
if (res != ResOK)
goto failScan;
break;
case RootFMT: case RootFMT:
res = (*root->the.fmt.scan)(&ss->ss_s, root->the.fmt.base, root->the.fmt.limit); res = (*root->the.fmt.scan)(&ss->ss_s, root->the.fmt.base, root->the.fmt.limit);
ss->scannedSize += AddrOffset(root->the.fmt.base, root->the.fmt.limit); ss->scannedSize += AddrOffset(root->the.fmt.base, root->the.fmt.limit);

View file

@ -24,10 +24,8 @@ SRCID(ss, "$Id$");
* scanning. * scanning.
*/ */
Res StackScanInner(ScanState ss, Res StackScanInner(ScanState ss, Word *stackBot, Word *stackTop,
Addr *stackBot, Count nSavedRegs, Word mask, Word pattern)
Addr *stackTop,
Count nSavedRegs)
{ {
Arena arena; Arena arena;
Res res; Res res;
@ -49,14 +47,16 @@ Res StackScanInner(ScanState ss,
if (arena->stackAtArenaEnter != NULL) { if (arena->stackAtArenaEnter != NULL) {
AVER(stackTop < arena->stackAtArenaEnter); AVER(stackTop < arena->stackAtArenaEnter);
AVER(arena->stackAtArenaEnter < stackBot); AVER(arena->stackAtArenaEnter < stackBot);
res = TraceScanAreaTagged(ss, stackTop, stackTop + nSavedRegs); res = TraceScanAreaMasked(ss, stackTop, stackTop + nSavedRegs,
mask, pattern);
if (res != ResOK) if (res != ResOK)
return res; return res;
res = TraceScanAreaTagged(ss, arena->stackAtArenaEnter, stackBot); res = TraceScanAreaMasked(ss, arena->stackAtArenaEnter, stackBot,
mask, pattern);
if (res != ResOK) if (res != ResOK)
return res; return res;
} else { } else {
res = TraceScanAreaTagged(ss, stackTop, stackBot); res = TraceScanAreaMasked(ss, stackTop, stackBot, mask, pattern);
if (res != ResOK) if (res != ResOK)
return res; return res;
} }

View file

@ -32,13 +32,9 @@
* stack itself. * stack itself.
*/ */
extern Res StackScan(ScanState ss, Addr *stackBot); extern Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern);
extern Res StackScanInner(ScanState ss, Word *stackBot, Word *stackTop,
Count nSavedRegs, Word mask, Word pattern);
extern Res StackScanInner(ScanState ss,
Addr *stackBot,
Addr *stackTop,
Count nSavedRegs);
#endif /* ss_h */ #endif /* ss_h */

View file

@ -21,21 +21,22 @@
SRCID(ssan, "$Id$"); SRCID(ssan, "$Id$");
Res StackScan(ScanState ss, Addr *stackBot) Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern)
{ {
jmp_buf jb; jmp_buf jb;
void *stackTop = &jb; Word *stackTop = (Word *)&jb;
/* .assume.stack: This implementation assumes that the stack grows /* .assume.stack: This implementation assumes that the stack grows
* downwards, so that the address of the jmp_buf is the limit of the * downwards, so that the address of the jmp_buf is the limit of the
* part of the stack that needs to be scanned. (StackScanInner makes * part of the stack that needs to be scanned. (StackScanInner makes
* the same assumption.) * the same assumption.)
*/ */
AVER(stackTop < (void *)stackBot); AVER(stackTop < stackBot);
(void)setjmp(jb); (void)setjmp(jb);
return StackScanInner(ss, stackBot, stackTop, sizeof jb / sizeof(Addr*)); return StackScanInner(ss, stackBot, stackTop, sizeof jb / sizeof(Word*),
mask, pattern);
} }

View file

@ -49,9 +49,9 @@ SRCID(ssixi3, "$Id$");
#define ASMV(x) __asm__ volatile (x) #define ASMV(x) __asm__ volatile (x)
Res StackScan(ScanState ss, Addr *stackBot) Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern)
{ {
Addr calleeSaveRegs[4]; Word calleeSaveRegs[4];
/* .assume.asm.stack */ /* .assume.asm.stack */
/* Store the callee save registers on the stack so they get scanned /* Store the callee save registers on the stack so they get scanned
@ -62,7 +62,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
ASMV("mov %%edi, %0" : "=m" (calleeSaveRegs[2])); ASMV("mov %%edi, %0" : "=m" (calleeSaveRegs[2]));
ASMV("mov %%ebp, %0" : "=m" (calleeSaveRegs[3])); ASMV("mov %%ebp, %0" : "=m" (calleeSaveRegs[3]));
return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs)); return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs),
mask, pattern);
} }

View file

@ -47,9 +47,9 @@ SRCID(ssixi6, "$Id$");
#define ASMV(x) __asm__ volatile (x) #define ASMV(x) __asm__ volatile (x)
Res StackScan(ScanState ss, Addr *stackBot) Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern)
{ {
Addr calleeSaveRegs[6]; Word calleeSaveRegs[6];
/* .assume.asm.stack */ /* .assume.asm.stack */
/* Store the callee save registers on the stack so they get scanned /* Store the callee save registers on the stack so they get scanned
@ -62,7 +62,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
ASMV("mov %%r14, %0" : "=m" (calleeSaveRegs[4])); ASMV("mov %%r14, %0" : "=m" (calleeSaveRegs[4]));
ASMV("mov %%r15, %0" : "=m" (calleeSaveRegs[5])); ASMV("mov %%r15, %0" : "=m" (calleeSaveRegs[5]));
return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs)); return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs),
mask, pattern);
} }

View file

@ -22,7 +22,7 @@
SRCID(ssw3i3mv, "$Id$"); SRCID(ssw3i3mv, "$Id$");
Res StackScan(ScanState ss, Addr *stackBot) Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern)
{ {
jmp_buf jb; jmp_buf jb;
@ -33,16 +33,17 @@ Res StackScan(ScanState ss, Addr *stackBot)
/* These checks will just serve to warn us at compile-time if the /* These checks will just serve to warn us at compile-time if the
setjmp.h header changes to indicate that the registers we want aren't setjmp.h header changes to indicate that the registers we want aren't
saved any more. */ saved any more. */
AVER(sizeof(((_JUMP_BUFFER *)jb)->Edi) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Edi) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->Esi) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Esi) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->Ebx) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Ebx) == sizeof(Word));
/* Ensure that the callee-save registers will be found by /* Ensure that the callee-save registers will be found by
StackScanInner when it's passed the address of the Ebx field. */ StackScanInner when it's passed the address of the Ebx field. */
AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4); AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4);
AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8); AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8);
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Ebx, 3); return StackScanInner(ss, stackBot, (Word *)&((_JUMP_BUFFER *)jb)->Ebx, 3,
mask, pattern);
} }
/* C. COPYRIGHT AND LICENSE /* C. COPYRIGHT AND LICENSE

View file

@ -46,7 +46,7 @@ typedef struct __JUMP_BUFFER {
} _JUMP_BUFFER; } _JUMP_BUFFER;
Res StackScan(ScanState ss, Addr *stackBot) Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern)
{ {
jmp_buf jb; jmp_buf jb;
@ -58,7 +58,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4); AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4);
AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8); AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8);
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Ebx, 3); return StackScanInner(ss, stackBot, (Word *)&((_JUMP_BUFFER *)jb)->Ebx, 3,
mask, pattern);
} }

View file

@ -30,7 +30,7 @@
SRCID(ssw3i6mv, "$Id$"); SRCID(ssw3i6mv, "$Id$");
Res StackScan(ScanState ss, Addr *stackBot) Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern)
{ {
jmp_buf jb; jmp_buf jb;
@ -41,13 +41,13 @@ Res StackScan(ScanState ss, Addr *stackBot)
/* These checks will just serve to warn us at compile-time if the /* These checks will just serve to warn us at compile-time if the
setjmp.h header changes to indicate that the registers we want aren't setjmp.h header changes to indicate that the registers we want aren't
saved any more. */ saved any more. */
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Word));
/* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */ /* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */
AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8); AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8);
@ -59,7 +59,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56); AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56);
AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64); AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64);
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Rbx, 9); return StackScanInner(ss, stackBot, (Word *)&((_JUMP_BUFFER *)jb)->Rbx, 9,
mask, pattern);
} }
/* C. COPYRIGHT AND LICENSE /* C. COPYRIGHT AND LICENSE

View file

@ -68,7 +68,7 @@ typedef struct _JUMP_BUFFER {
} _JUMP_BUFFER; } _JUMP_BUFFER;
Res StackScan(ScanState ss, Addr *stackBot) Res StackScan(ScanState ss, Word *stackBot, Word mask, Word pattern)
{ {
jmp_buf jb; jmp_buf jb;
@ -79,13 +79,13 @@ Res StackScan(ScanState ss, Addr *stackBot)
/* These checks will just serve to warn us at compile-time if the /* These checks will just serve to warn us at compile-time if the
setjmp.h header changes to indicate that the registers we want aren't setjmp.h header changes to indicate that the registers we want aren't
saved any more. */ saved any more. */
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Word));
AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Word));
/* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */ /* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */
AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8); AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8);
@ -97,7 +97,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56); AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56);
AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64); AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64);
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Rbx, 9); return StackScanInner(ss, stackBot, (Word *)&((_JUMP_BUFFER *)jb)->Rbx, 9,
mask, pattern);
} }

View file

@ -67,7 +67,8 @@ extern Thread ThreadRingThread(Ring threadRing);
extern Arena ThreadArena(Thread thread); extern Arena ThreadArena(Thread thread);
extern Res ThreadScan(ScanState ss, Thread thread, void *stackBot); extern Res ThreadScan(ScanState ss, Thread thread, Word *stackBot,
Word mask, Word pattern);
#endif /* th_h */ #endif /* th_h */

View file

@ -115,10 +115,11 @@ Arena ThreadArena(Thread thread)
} }
Res ThreadScan(ScanState ss, Thread thread, void *stackBot) Res ThreadScan(ScanState ss, Thread thread, Word *stackBot,
Word mask, Word pattern)
{ {
UNUSED(thread); UNUSED(thread);
return StackScan(ss, stackBot); return StackScan(ss, stackBot, mask, pattern);
} }

View file

@ -222,7 +222,8 @@ Arena ThreadArena(Thread thread)
/* ThreadScan -- scan the state of a thread (stack and regs) */ /* ThreadScan -- scan the state of a thread (stack and regs) */
Res ThreadScan(ScanState ss, Thread thread, void *stackBot) Res ThreadScan(ScanState ss, Thread thread, Word *stackBot,
Word mask, Word pattern)
{ {
pthread_t self; pthread_t self;
Res res; Res res;
@ -231,12 +232,13 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
self = pthread_self(); self = pthread_self();
if(pthread_equal(self, thread->id)) { if(pthread_equal(self, thread->id)) {
/* scan this thread's stack */ /* scan this thread's stack */
res = StackScan(ss, stackBot); res = StackScan(ss, stackBot, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} else { } else {
MutatorFaultContext mfc; MutatorFaultContext mfc;
Addr *stackBase, *stackLimit, stackPtr; Word *stackBase, *stackLimit;
Addr stackPtr;
mfc = thread->mfc; mfc = thread->mfc;
if(mfc == NULL) { if(mfc == NULL) {
@ -248,20 +250,20 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
stackPtr = MutatorFaultContextSP(mfc); stackPtr = MutatorFaultContextSP(mfc);
/* .stack.align */ /* .stack.align */
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Addr));
stackLimit = (Addr *)stackBot; stackLimit = stackBot;
if (stackBase >= stackLimit) if (stackBase >= stackLimit)
return ResOK; /* .stack.below-bottom */ return ResOK; /* .stack.below-bottom */
/* scan stack inclusive of current sp and exclusive of /* scan stack inclusive of current sp and exclusive of
* stackBot (.stack.full-descend) * stackBot (.stack.full-descend)
*/ */
res = TraceScanAreaTagged(ss, stackBase, stackLimit); res = TraceScanAreaMasked(ss, stackBase, stackLimit, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
/* scan the registers in the mutator fault context */ /* scan the registers in the mutator fault context */
res = MutatorFaultContextScan(ss, mfc); res = MutatorFaultContextScan(ss, mfc, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} }

View file

@ -67,7 +67,8 @@
SRCID(thw3i3, "$Id$"); SRCID(thw3i3, "$Id$");
Res ThreadScan(ScanState ss, Thread thread, void *stackBot) Res ThreadScan(ScanState ss, Thread thread, Word *stackBot,
Word mask, Word pattern)
{ {
DWORD id; DWORD id;
Res res; Res res;
@ -77,7 +78,8 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
if(id != thread->id) { /* .thread.id */ if(id != thread->id) { /* .thread.id */
CONTEXT context; CONTEXT context;
BOOL success; BOOL success;
Addr *stackBase, *stackLimit, stackPtr; Word *stackBase, *stackLimit;
Addr stackPtr;
/* scan stack and register roots in other threads */ /* scan stack and register roots in other threads */
@ -95,15 +97,15 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
stackPtr = (Addr)context.Esp; /* .i3.sp */ stackPtr = (Addr)context.Esp; /* .i3.sp */
/* .stack.align */ /* .stack.align */
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Addr));
stackLimit = (Addr *)stackBot; stackLimit = stackBot;
if (stackBase >= stackLimit) if (stackBase >= stackLimit)
return ResOK; /* .stack.below-bottom */ return ResOK; /* .stack.below-bottom */
/* scan stack inclusive of current sp and exclusive of /* scan stack inclusive of current sp and exclusive of
* stackBot (.stack.full-descend) * stackBot (.stack.full-descend)
*/ */
res = TraceScanAreaTagged(ss, stackBase, stackLimit); res = TraceScanAreaMasked(ss, stackBase, stackLimit, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
@ -112,13 +114,14 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
* unnecessarily scans the rest of the context. The optimisation * unnecessarily scans the rest of the context. The optimisation
* to scan only relevant parts would be machine dependent. * to scan only relevant parts would be machine dependent.
*/ */
res = TraceScanAreaTagged(ss, (Addr *)&context, res = TraceScanAreaMasked(ss, (Word *)&context,
(Addr *)((char *)&context + sizeof(CONTEXT))); (Word *)((char *)&context + sizeof(CONTEXT)),
mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} else { /* scan this thread's stack */ } else { /* scan this thread's stack */
res = StackScan(ss, stackBot); res = StackScan(ss, stackBot, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} }

View file

@ -67,7 +67,8 @@
SRCID(thw3i6, "$Id$"); SRCID(thw3i6, "$Id$");
Res ThreadScan(ScanState ss, Thread thread, void *stackBot) Res ThreadScan(ScanState ss, Thread thread, Word *stackBot,
Word mask, Word pattern)
{ {
DWORD id; DWORD id;
Res res; Res res;
@ -77,7 +78,8 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
if(id != thread->id) { /* .thread.id */ if(id != thread->id) { /* .thread.id */
CONTEXT context; CONTEXT context;
BOOL success; BOOL success;
Addr *stackBase, *stackLimit, stackPtr; Word *stackBase, *stackLimit;
Addr stackPtr;
/* scan stack and register roots in other threads */ /* scan stack and register roots in other threads */
@ -95,15 +97,15 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
stackPtr = (Addr)context.Rsp; /* .i6.sp */ stackPtr = (Addr)context.Rsp; /* .i6.sp */
/* .stack.align */ /* .stack.align */
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Addr));
stackLimit = (Addr *)stackBot; stackLimit = stackBot;
if (stackBase >= stackLimit) if (stackBase >= stackLimit)
return ResOK; /* .stack.below-bottom */ return ResOK; /* .stack.below-bottom */
/* scan stack inclusive of current sp and exclusive of /* scan stack inclusive of current sp and exclusive of
* stackBot (.stack.full-descend) * stackBot (.stack.full-descend)
*/ */
res = TraceScanAreaTagged(ss, stackBase, stackLimit); res = TraceScanAreaMasked(ss, stackBase, stackLimit, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
@ -112,13 +114,14 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
* unnecessarily scans the rest of the context. The optimisation * unnecessarily scans the rest of the context. The optimisation
* to scan only relevant parts would be machine dependent. * to scan only relevant parts would be machine dependent.
*/ */
res = TraceScanAreaTagged(ss, (Addr *)&context, res = TraceScanAreaMasked(ss, (Word *)&context,
(Addr *)((char *)&context + sizeof(CONTEXT))); (Word *)((char *)&context + sizeof(CONTEXT)),
mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} else { /* scan this thread's stack */ } else { /* scan this thread's stack */
res = StackScan(ss, stackBot); res = StackScan(ss, stackBot, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} }

View file

@ -189,7 +189,8 @@ Arena ThreadArena(Thread thread)
#include "prmcxc.h" #include "prmcxc.h"
Res ThreadScan(ScanState ss, Thread thread, void *stackBot) Res ThreadScan(ScanState ss, Thread thread, Word *stackBot,
Word mask, Word pattern)
{ {
mach_port_t self; mach_port_t self;
Res res; Res res;
@ -199,13 +200,14 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
AVER(MACH_PORT_VALID(self)); AVER(MACH_PORT_VALID(self));
if (thread->port == self) { if (thread->port == self) {
/* scan this thread's stack */ /* scan this thread's stack */
res = StackScan(ss, stackBot); res = StackScan(ss, stackBot, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} else { } else {
MutatorFaultContextStruct mfcStruct; MutatorFaultContextStruct mfcStruct;
THREAD_STATE_S threadState; THREAD_STATE_S threadState;
Addr *stackBase, *stackLimit, stackPtr; Word *stackBase, *stackLimit;
Addr stackPtr;
mach_msg_type_number_t count; mach_msg_type_number_t count;
kern_return_t kern_return; kern_return_t kern_return;
@ -227,20 +229,20 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
stackPtr = MutatorFaultContextSP(&mfcStruct); stackPtr = MutatorFaultContextSP(&mfcStruct);
/* .stack.align */ /* .stack.align */
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Addr));
stackLimit = (Addr *)stackBot; stackLimit = stackBot;
if (stackBase >= stackLimit) if (stackBase >= stackLimit)
return ResOK; /* .stack.below-bottom */ return ResOK; /* .stack.below-bottom */
/* scan stack inclusive of current sp and exclusive of /* scan stack inclusive of current sp and exclusive of
* stackBot (.stack.full-descend) * stackBot (.stack.full-descend)
*/ */
res = TraceScanAreaTagged(ss, stackBase, stackLimit); res = TraceScanAreaMasked(ss, stackBase, stackLimit, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
/* scan the registers in the mutator fault context */ /* scan the registers in the mutator fault context */
res = MutatorFaultContextScan(ss, &mfcStruct); res = MutatorFaultContextScan(ss, &mfcStruct, mask, pattern);
if(res != ResOK) if(res != ResOK)
return res; return res;
} }

View file

@ -1425,11 +1425,10 @@ void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
* [base, limit). I.e., it calls Fix on all words from base up to * [base, limit). I.e., it calls Fix on all words from base up to
* limit, inclusive of base and exclusive of limit. */ * limit, inclusive of base and exclusive of limit. */
Res TraceScanArea(ScanState ss, Addr *base, Addr *limit) Res TraceScanArea(ScanState ss, Word *base, Word *limit)
{ {
Res res; Res res;
Addr *p; Word word, *p;
Ref ref;
AVER(base != NULL); AVER(base != NULL);
AVER(limit != NULL); AVER(limit != NULL);
@ -1442,10 +1441,10 @@ Res TraceScanArea(ScanState ss, Addr *base, Addr *limit)
loop: loop:
if (p >= limit) if (p >= limit)
goto out; goto out;
ref = *p++; word = *p++;
if(!TRACE_FIX1(ss, ref)) if(!TRACE_FIX1(ss, (Ref)word))
goto loop; goto loop;
res = TRACE_FIX2(ss, p-1); res = TRACE_FIX2(ss, (Ref *)(p-1));
if(res == ResOK) if(res == ResOK)
goto loop; goto loop;
return res; return res;
@ -1457,43 +1456,21 @@ Res TraceScanArea(ScanState ss, Addr *base, Addr *limit)
} }
/* TraceScanAreaTagged -- scan contiguous area of tagged references
*
* .tagging: This is as TraceScanArea except words are only fixed they are
* tagged as zero according to the alignment of a Word.
*
* See also PoolSingleAccess <code/poolabs.c#.tagging>.
*
* TODO: Generalise the handling of tags so that pools can decide how
* their objects are tagged. This may use the user defined format
* to describe how tags are done */
Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit)
{
Word mask;
/* 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 = sizeof(Word) - 1;
AVER(WordIsP2(mask + 1));
return TraceScanAreaMasked(ss, base, limit, mask);
}
/* TraceScanAreaMasked -- scan contiguous area of filtered references /* TraceScanAreaMasked -- scan contiguous area of filtered references
* *
* This is as TraceScanArea except words are only fixed if they are zero * This is as TraceScanArea except words are only fixed if they have
* when masked with a mask. */ * the given value when masked with a mask.
*
* This has ATTRIBUTE_NO_SANITIZE_ADDRESS otherwise Clang's address
* sanitizer will think we have run off the end of an array.
*/
ATTRIBUTE_NO_SANITIZE_ADDRESS ATTRIBUTE_NO_SANITIZE_ADDRESS
Res TraceScanAreaMasked(ScanState ss, Addr *base, Addr *limit, Word mask) Res TraceScanAreaMasked(ScanState ss, Word *base, Word *limit, Word mask,
Word pattern)
{ {
Res res; Res res;
Addr *p; Word word, *p;
Ref ref;
AVERT(ScanState, ss); AVERT(ScanState, ss);
AVER(base != NULL); AVER(base != NULL);
@ -1507,12 +1484,12 @@ Res TraceScanAreaMasked(ScanState ss, Addr *base, Addr *limit, Word mask)
loop: loop:
if (p >= limit) if (p >= limit)
goto out; goto out;
ref = *p++; word = *p++;
if (((Word)ref & mask) if ((word & mask) != pattern)
!= 0) goto loop;
if (!TRACE_FIX1(ss, ref))
goto loop; goto loop;
res = TRACE_FIX2(ss, p-1); if (!TRACE_FIX1(ss, (Ref)word))
goto loop;
res = TRACE_FIX2(ss, (Ref *)(p-1));
if(res == ResOK) if(res == ResOK)
goto loop; goto loop;
return res; return res;

View file

@ -17,6 +17,10 @@ New features
specifying the minimum size of the memory segments that the pool specifying the minimum size of the memory segments that the pool
requests from the :term:`arena`. requests from the :term:`arena`.
#. New function :c:func:`mps_root_create_reg_masked` applies a mask
and pattern test to all words in registers and on the stack when
scanning them. This supports tagged references in these locations.
Interface changes Interface changes
................. .................

View file

@ -393,10 +393,12 @@ Root interface
The registered root description persists until it is destroyed by The registered root description persists until it is destroyed by
calling :c:func:`mps_root_destroy`. calling :c:func:`mps_root_destroy`.
.. c:function:: mps_res_t mps_root_create_reg(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_thr_t thr, mps_reg_scan_t reg_scan, void *p, size_t s) .. c:function:: mps_res_t mps_root_create_reg(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_thr_t thr, mps_reg_scan_t reg_scan, void *p, size_t s)
Register a :term:`root` that consists of the :term:`references` Register a :term:`root` that consists of the :term:`references`
fixed in a :term:`thread's <thread>` stack by a scanning function. fixed in a :term:`thread's <thread>` registers and stack by a
scanning function.
``root_o`` points to a location that will hold the address of the ``root_o`` points to a location that will hold the address of the
new root description. new root description.
@ -427,7 +429,10 @@ Root interface
It is not supported for :term:`client programs` to pass their It is not supported for :term:`client programs` to pass their
own scanning functions to this function. The built-in MPS own scanning functions to this function. The built-in MPS
function :c:func:`mps_stack_scan_ambig` must be used. function :c:func:`mps_stack_scan_ambig` must be used. In this
case the ``p`` argument must be a pointer into the thread's
stack, as described for :c:func:`mps_root_create_reg_masked`
below, and the ``s`` argument is ignored.
This function is intended as a hook should we ever need to This function is intended as a hook should we ever need to
allow client-specific extension or customization of stack and allow client-specific extension or customization of stack and
@ -483,11 +488,14 @@ Root interface
It scans all integer registers and everything on the stack of the It scans all integer registers and everything on the stack of the
thread given, and can therefore only be used with :term:`ambiguous thread given, and can therefore only be used with :term:`ambiguous
roots`. It only scans locations that are at, or higher on the roots`. It scans locations that are more recently added than the
stack (that is, more recently added), the stack bottom that was stack bottom that was passed in the ``p`` argument to
passed to :c:func:`mps_thread_reg`. References are assumed to be :c:func:`mps_root_create_reg`.
represented as machine words, and are required to be
4-byte-aligned; unaligned values are ignored. References are assumed to be represented as machine words, and are
required to be word-aligned; unaligned values are ignored. If
references are tagged, use :c:func:`mps_root_create_reg_masked`
instead.
.. note:: .. note::
@ -496,6 +504,63 @@ Root interface
and in some cases on the compiler. and in some cases on the compiler.
.. c:function:: mps_res_t mps_root_create_reg_masked(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_thr_t thr, mps_word_t mask, mps_word_t pattern, void *stack)
Register a :term:`root` that consists of the :term:`references` in
a :term:`thread's <thread>` registers and stack that match a
binary pattern.
``root_o`` points to a location that will hold the address of the
new root description.
``arena`` is the arena.
``rank`` is the :term:`rank` of references in the root.
``rm`` is the :term:`root mode`.
``thr`` is the thread.
``mask`` is an arbitrary mask that is applied to each word in the
thread's registers and stack.
``pattern`` is an arbitrary pattern; any word that is unequal to
this (after masking with ``mask``) is not considered to be a
reference.
``stack`` is a pointer into the thread's stack. On platforms where
the stack grows downwards (currently, all supported platforms),
locations below this address will be scanned.
Returns :c:macro:`MPS_RES_OK` if the root was registered
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
description could not be allocated, or another :term:`result code`
if there was another error.
The registered root description persists until it is destroyed by
calling :c:func:`mps_root_destroy`.
.. warning::
A risk of using tagged pointers in registers and on the stack
is that in some circumstances, an optimizing compiler might
optimize away the tagged pointer, keeping only the untagged
version of the pointer. In this situation the pointer would be
ignored and if it was the last reference to the object the MPS
might incorrectly determine that it was dead.
You can avoid this risk by setting ``mask`` and ``pattern`` to
zero: in this case all words in registers and on the stack are
scanned, leading to possible additional scanning and retention.
.. note::
An optimization that may be worth considering is setting some
of the top bits in ``mask`` so that addresses that cannot be
allocated by the MPS are rejected quickly. This requires
expertise with the platform's virtual memory interface.
.. c:function:: mps_res_t mps_root_create_table(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count) .. c:function:: mps_res_t mps_root_create_table(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count)
Register a :term:`root` that consists of a vector of Register a :term:`root` that consists of a vector of