static void ArenaFormattedObjectsWalk(Arena arena, FormattedObjectsStepMethod f, void *p, size_t s) { Seg seg; FormattedObjectsStepClosure c; AVERT(Arena, arena); AVER(FUNCHECK(f)); AVER(f == ArenaFormattedObjectsStep); /* p and s are arbitrary closures. */ /* Know that p is a FormattedObjectsStepClosure */ /* Know that s is 0 */ AVER(p != NULL); AVER(s == 0); c = p; AVERT(FormattedObjectsStepClosure, c); if (SegFirst(&seg, arena)) { do { Pool pool; pool = SegPool(seg); if (PoolHasAttr(pool, AttrFMT)) { ShieldExpose(arena, seg); PoolWalk(pool, seg, f, p, s); ShieldCover(arena, seg); } } while(SegNext(&seg, arena, seg)); } }
static Res RootsWalkFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) { rootsStepClosure rsc; Ref ref; UNUSED(pool); AVERT(ScanState, ss); AVER(refIO != NULL); rsc = ScanState2rootsStepClosure(ss); AVERT(rootsStepClosure, rsc); ref = *refIO; /* If the segment isn't GCable then the ref is not to the heap and */ /* shouldn't be passed to the client. */ AVER(PoolHasAttr(SegPool(seg), AttrGC)); /* Call the client closure - .assume.rootaddr */ rsc->f((mps_addr_t*)refIO, (mps_root_t)rsc->root, rsc->p, rsc->s); AVER(ref == *refIO); /* can walk object graph - but not modify it */ return ResOK; }
Bool PoolCheck(Pool pool) { PoolClass klass; /* Checks ordered as per struct decl in <code/mpmst.h#pool> */ CHECKS(Pool, pool); CHECKC(AbstractPool, pool); /* Break modularity for checking efficiency */ CHECKL(pool->serial < ArenaGlobals(pool->arena)->poolSerial); klass = ClassOfPoly(Pool, pool); CHECKD(PoolClass, klass); CHECKU(Arena, pool->arena); CHECKD_NOSIG(Ring, &pool->arenaRing); CHECKD_NOSIG(Ring, &pool->bufferRing); /* Cannot check pool->bufferSerial */ CHECKD_NOSIG(Ring, &pool->segRing); CHECKL(AlignCheck(pool->alignment)); /* Normally pool->format iff PoolHasAttr(pool, AttrFMT), but during pool initialization the class may not yet be set. */ CHECKL(!PoolHasAttr(pool, AttrFMT) || pool->format != NULL); return TRUE; }
static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f, void *p, size_t s) { Arena arena; rootsStepClosureStruct rscStruct; rootsStepClosure rsc = &rscStruct; Trace trace; ScanState ss; Rank rank; Res res; Seg seg; AVERT(Globals, arenaGlobals); AVER(FUNCHECK(f)); /* p and s are arbitrary client-provided closure data. */ arena = GlobalsArena(arenaGlobals); /* Scan all the roots with a minimal trace. Invoke the scanner with a */ /* rootsStepClosure, which is a subclass of ScanState and contains the */ /* client-provided closure. Supply a special fix method in order to */ /* call the client closure. This fix method must perform no tracing */ /* operations of its own. */ res = TraceCreate(&trace, arena, TraceStartWhyWALK); /* Have to fail if no trace available. Unlikely due to .assume.parked. */ if (res != ResOK) return res; /* ArenaRootsWalk only passes references to GCable pools to the client. */ /* NOTE: I'm not sure why this is. RB 2012-07-24 */ if (SegFirst(&seg, arena)) { do { if (PoolHasAttr(SegPool(seg), AttrGC)) { res = TraceAddWhite(trace, seg); AVER(res == ResOK); } } while (SegNext(&seg, arena, seg)); } /* Make the roots grey so that they are scanned */ res = RootsIterate(arenaGlobals, rootWalkGrey, trace); /* Make this trace look like any other trace. */ arena->flippedTraces = TraceSetAdd(arena->flippedTraces, trace); rootsStepClosureInit(rsc, arenaGlobals, trace, RootsWalkFix, f, p, s); ss = rootsStepClosure2ScanState(rsc); for(rank = RankAMBIG; rank < RankLIMIT; ++rank) { ss->rank = rank; AVERT(ScanState, ss); res = RootsIterate(arenaGlobals, rootWalk, (void *)ss); if (res != ResOK) break; } /* Turn segments black again. */ if (SegFirst(&seg, arena)) { do { if (PoolHasAttr(SegPool(seg), AttrGC)) { SegSetGrey(seg, TraceSetDel(SegGrey(seg), trace)); SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace)); } } while (SegNext(&seg, arena, seg)); } rootsStepClosureFinish(rsc); /* Make this trace look like any other finished trace. */ trace->state = TraceFINISHED; TraceDestroy(trace); AVER(!ArenaEmergency(arena)); /* There was no allocation. */ return res; }