diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index a3e7dce3773..a2fe1461590 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -457,11 +457,21 @@ mps_res_t mps_addr_object(mps_addr_t *p_o, mps_arena_t arena, mps_addr_t addr) AVER(p_o != NULL); + /* This function cannot be called while walking the heap, unlike + * mps_arena_has_addr(). This is because it is designed to be called + * with an active mutator, so takes the arena lock. This is in order + * that it sees a consistent view of MPS structures and the heap, + * and can peek behind the barrier. + */ ArenaEnter(arena); AVERT(Arena, arena); res = ArenaAddrObject(&p, arena, (Addr)addr); ArenaLeave(arena); - + /* We require the object to be ambiguously referenced (hence pinned) + * so that p doesn't become invalid before it is written to *p_o. + * (We can't simply put this write before the ArenaLeave(), because + * p_o could point to MPS-managed memory that is behind a barrier.) + */ if (res == ResOK) *p_o = (mps_addr_t)p; diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 4e6267f7737..1db13147fef 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -1956,6 +1956,17 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Addr addr) base = SegBase(seg); if (SegBuffer(&buffer, seg)) + /* We use BufferGetInit here (and not BufferScanLimit) because we + * want to be able to find objects that have been allocated and + * committed since the last flip. These objects lie between the + * addresses returned by BufferScanLimit (which returns the value + * of init at the last flip) and BufferGetInit. + * + * Strictly speaking we only need a limit that is at least the + * maximum of the objects on the segments. This is because addr + * *must* point inside a live object and we stop skipping once we + * have found it. The init pointer serves this purpose. + */ limit = BufferGetInit(buffer); else limit = SegLimit(seg);