static void shieldDebugCheck(Arena arena) { Shield shield; Seg seg; Count queued = 0; Count depth = 0; AVERT(Arena, arena); shield = ArenaShield(arena); AVER(shield->inside || shield->limit == 0); if (SegFirst(&seg, arena)) do { depth += SegDepth(seg); if (shield->limit == 0) { AVER(!seg->queued); AVER(SegIsSynced(seg)); /* You can directly set protections here to see if it makes a difference. */ /* ProtSet(SegBase(seg), SegLimit(seg), SegPM(seg)); */ } else { if (seg->queued) ++queued; } } while(SegNext(&seg, arena, seg)); AVER(depth == shield->depth); AVER(queued == shield->limit); }
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)); } }
/* ArenaExposeRemember -- park arena and then lift all protection barriers. Parameter 'remember' specifies whether to remember the protection state or not (for later restoration with ArenaRestoreProtection). */ void ArenaExposeRemember(Globals globals, Bool remember) { Seg seg; Arena arena; AVERT(Globals, globals); AVERT(Bool, remember); ArenaPark(globals); arena = GlobalsArena(globals); if(SegFirst(&seg, arena)) { Addr base; do { base = SegBase(seg); if (IsA(GCSeg, seg)) { if(remember) { RefSet summary; summary = SegSummary(seg); if(summary != RefSetUNIV) { Res res = arenaRememberSummaryOne(globals, base, summary); if(res != ResOK) { /* If we got an error then stop trying to remember any protections. */ remember = 0; } } } SegSetSummary(seg, RefSetUNIV); AVER(SegSM(seg) == AccessSetEMPTY); } } while(SegNext(&seg, arena, seg)); } }
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; }