diff options
| author | Richard Kistruck | 2008-12-09 16:55:22 +0000 |
|---|---|---|
| committer | Richard Kistruck | 2008-12-09 16:55:22 +0000 |
| commit | 77ea63625ab4250da91ffde66798bd417893a349 (patch) | |
| tree | 5417bd41168c34afe1af896b3e8a60574cdb2d97 /mps/code/trace.c | |
| parent | 6c5443770f517a519f91901c34d56475dad38e9d (diff) | |
| download | emacs-77ea63625ab4250da91ffde66798bd417893a349.tar.gz emacs-77ea63625ab4250da91ffde66798bd417893a349.zip | |
Mps br/timing: traceanc.c -- all this ancillary stuff was making
trace.c very cluttered. Put it here instead.
Copied from Perforce
Change: 166911
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/trace.c')
| -rw-r--r-- | mps/code/trace.c | 547 |
1 files changed, 2 insertions, 545 deletions
diff --git a/mps/code/trace.c b/mps/code/trace.c index bc867431c5c..e7c0b09b6ed 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | SRCID(trace, "$Id$"); | 14 | SRCID(trace, "$Id$"); |
| 15 | 15 | ||
| 16 | /* Forward declarations */ | 16 | /* Forward declarations */ |
| 17 | static void TraceStartMessageInit(Arena arena, TraceStartMessage tsMessage); | ||
| 18 | Rank traceBand(Trace); | 17 | Rank traceBand(Trace); |
| 19 | Bool traceBandAdvance(Trace); | 18 | Bool traceBandAdvance(Trace); |
| 20 | Bool traceBandFirstStretch(Trace); | 19 | Bool traceBandFirstStretch(Trace); |
| @@ -30,278 +29,6 @@ enum { | |||
| 30 | }; | 29 | }; |
| 31 | typedef int traceAccountingPhase; | 30 | typedef int traceAccountingPhase; |
| 32 | 31 | ||
| 33 | struct RememberedSummaryBlockStruct { | ||
| 34 | RingStruct globalRing; /* link on globals->rememberedSummaryRing */ | ||
| 35 | struct SummaryPair { | ||
| 36 | Addr base; | ||
| 37 | RefSet summary; | ||
| 38 | } the[RememberedSummaryBLOCK]; | ||
| 39 | }; | ||
| 40 | |||
| 41 | /* Forward Declarations -- avoid compiler warning. */ | ||
| 42 | Res arenaRememberSummaryOne(Globals global, Addr base, RefSet summary); | ||
| 43 | void arenaForgetProtection(Globals globals); | ||
| 44 | void rememberedSummaryBlockInit(struct RememberedSummaryBlockStruct *block); | ||
| 45 | |||
| 46 | |||
| 47 | /* TraceMessage -- type of GC end messages */ | ||
| 48 | |||
| 49 | #define TraceMessageSig ((Sig)0x51926359) | ||
| 50 | |||
| 51 | typedef struct TraceMessageStruct { | ||
| 52 | Sig sig; | ||
| 53 | Size liveSize; | ||
| 54 | Size condemnedSize; | ||
| 55 | Size notCondemnedSize; | ||
| 56 | MessageStruct messageStruct; | ||
| 57 | } TraceMessageStruct, *TraceMessage; | ||
| 58 | |||
| 59 | #define TraceMessageMessage(traceMessage) (&((traceMessage)->messageStruct)) | ||
| 60 | #define MessageTraceMessage(message) \ | ||
| 61 | (PARENT(TraceMessageStruct, messageStruct, message)) | ||
| 62 | |||
| 63 | static Bool TraceMessageCheck(TraceMessage message) | ||
| 64 | { | ||
| 65 | CHECKS(TraceMessage, message); | ||
| 66 | CHECKD(Message, TraceMessageMessage(message)); | ||
| 67 | CHECKL(MessageGetType(TraceMessageMessage(message)) == | ||
| 68 | MessageTypeGC); | ||
| 69 | /* We can't check anything about the statistics. In particular, */ | ||
| 70 | /* liveSize may exceed condemnedSize because they are only estimates. */ | ||
| 71 | |||
| 72 | return TRUE; | ||
| 73 | } | ||
| 74 | |||
| 75 | static void TraceMessageDelete(Message message) | ||
| 76 | { | ||
| 77 | TraceMessage tMessage; | ||
| 78 | Arena arena; | ||
| 79 | |||
| 80 | AVERT(Message, message); | ||
| 81 | tMessage = MessageTraceMessage(message); | ||
| 82 | AVERT(TraceMessage, tMessage); | ||
| 83 | |||
| 84 | arena = MessageArena(message); | ||
| 85 | ControlFree(arena, (void *)tMessage, sizeof(TraceMessageStruct)); | ||
| 86 | } | ||
| 87 | |||
| 88 | static Size TraceMessageLiveSize(Message message) | ||
| 89 | { | ||
| 90 | TraceMessage tMessage; | ||
| 91 | |||
| 92 | AVERT(Message, message); | ||
| 93 | tMessage = MessageTraceMessage(message); | ||
| 94 | AVERT(TraceMessage, tMessage); | ||
| 95 | |||
| 96 | return tMessage->liveSize; | ||
| 97 | } | ||
| 98 | |||
| 99 | static Size TraceMessageCondemnedSize(Message message) | ||
| 100 | { | ||
| 101 | TraceMessage tMessage; | ||
| 102 | |||
| 103 | AVERT(Message, message); | ||
| 104 | tMessage = MessageTraceMessage(message); | ||
| 105 | AVERT(TraceMessage, tMessage); | ||
| 106 | |||
| 107 | return tMessage->condemnedSize; | ||
| 108 | } | ||
| 109 | |||
| 110 | static Size TraceMessageNotCondemnedSize(Message message) | ||
| 111 | { | ||
| 112 | TraceMessage tMessage; | ||
| 113 | |||
| 114 | AVERT(Message, message); | ||
| 115 | tMessage = MessageTraceMessage(message); | ||
| 116 | AVERT(TraceMessage, tMessage); | ||
| 117 | |||
| 118 | return tMessage->notCondemnedSize; | ||
| 119 | } | ||
| 120 | |||
| 121 | static MessageClassStruct TraceMessageClassStruct = { | ||
| 122 | MessageClassSig, /* sig */ | ||
| 123 | "TraceGC", /* name */ | ||
| 124 | MessageTypeGC, /* Message Type */ | ||
| 125 | TraceMessageDelete, /* Delete */ | ||
| 126 | MessageNoFinalizationRef, /* FinalizationRef */ | ||
| 127 | TraceMessageLiveSize, /* GCLiveSize */ | ||
| 128 | TraceMessageCondemnedSize, /* GCCondemnedSize */ | ||
| 129 | TraceMessageNotCondemnedSize, /* GCNotCondemnedSize */ | ||
| 130 | MessageNoGCStartWhy, /* GCStartWhy */ | ||
| 131 | MessageClassSig /* <design/message/#class.sig.double> */ | ||
| 132 | }; | ||
| 133 | |||
| 134 | static void TraceMessageInit(Arena arena, TraceMessage tMessage) | ||
| 135 | { | ||
| 136 | AVERT(Arena, arena); | ||
| 137 | |||
| 138 | MessageInit(arena, TraceMessageMessage(tMessage), | ||
| 139 | &TraceMessageClassStruct, MessageTypeGC); | ||
| 140 | tMessage->liveSize = (Size)0; | ||
| 141 | tMessage->condemnedSize = (Size)0; | ||
| 142 | tMessage->notCondemnedSize = (Size)0; | ||
| 143 | |||
| 144 | tMessage->sig = TraceMessageSig; | ||
| 145 | AVERT(TraceMessage, tMessage); | ||
| 146 | } | ||
| 147 | |||
| 148 | /* TraceStartMessage - manages info needed by start of trace message | ||
| 149 | (mps_message_type_gc_start). | ||
| 150 | |||
| 151 | (structure declared in <code/mpmst.h> ) */ | ||
| 152 | |||
| 153 | #define TraceStartMessageMessage(traceStartMessage) \ | ||
| 154 | (&((traceStartMessage)->messageStruct)) | ||
| 155 | #define MessageTraceStartMessage(message) \ | ||
| 156 | (PARENT(TraceStartMessageStruct, messageStruct, message)) | ||
| 157 | |||
| 158 | static Bool TraceStartMessageCheck(TraceStartMessage message) | ||
| 159 | { | ||
| 160 | size_t i; | ||
| 161 | |||
| 162 | CHECKS(TraceStartMessage, message); | ||
| 163 | CHECKD(Message, TraceStartMessageMessage(message)); | ||
| 164 | CHECKL(MessageGetType(TraceStartMessageMessage(message)) == | ||
| 165 | MessageTypeGCSTART); | ||
| 166 | |||
| 167 | /* Check that why is NUL terminated. */ | ||
| 168 | for(i=0; i<NELEMS(message->why); ++i) { | ||
| 169 | if(message->why[i] == 0) { | ||
| 170 | break; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | CHECKL(i<NELEMS(message->why)); | ||
| 174 | |||
| 175 | return TRUE; | ||
| 176 | } | ||
| 177 | |||
| 178 | static void TraceStartMessageDelete(Message message) | ||
| 179 | { | ||
| 180 | TraceStartMessage tsMessage; | ||
| 181 | |||
| 182 | AVERT(Message, message); | ||
| 183 | tsMessage = MessageTraceStartMessage(message); | ||
| 184 | AVERT(TraceStartMessage, tsMessage); | ||
| 185 | |||
| 186 | TraceStartMessageInit(MessageArena(message), tsMessage); | ||
| 187 | |||
| 188 | return; | ||
| 189 | } | ||
| 190 | |||
| 191 | static const char *TraceStartMessageWhy(Message message) | ||
| 192 | { | ||
| 193 | TraceStartMessage tsMessage; | ||
| 194 | |||
| 195 | AVERT(Message, message); | ||
| 196 | tsMessage = MessageTraceStartMessage(message); | ||
| 197 | AVERT(TraceStartMessage, tsMessage); | ||
| 198 | |||
| 199 | return tsMessage->why; | ||
| 200 | } | ||
| 201 | |||
| 202 | static MessageClassStruct TraceStartMessageClassStruct = { | ||
| 203 | MessageClassSig, /* sig */ | ||
| 204 | "TraceGCStart", /* name */ | ||
| 205 | MessageTypeGCSTART, /* Message Type */ | ||
| 206 | TraceStartMessageDelete, /* Delete */ | ||
| 207 | MessageNoFinalizationRef, /* FinalizationRef */ | ||
| 208 | MessageNoGCLiveSize, /* GCLiveSize */ | ||
| 209 | MessageNoGCCondemnedSize, /* GCCondemnedSize */ | ||
| 210 | MessageNoGCNotCondemnedSize, /* GCNotCondemnedSize */ | ||
| 211 | TraceStartMessageWhy, /* GCStartWhy */ | ||
| 212 | MessageClassSig /* <design/message/#class.sig.double> */ | ||
| 213 | }; | ||
| 214 | |||
| 215 | static void TraceStartMessageInit(Arena arena, TraceStartMessage tsMessage) | ||
| 216 | { | ||
| 217 | AVERT(Arena, arena); | ||
| 218 | |||
| 219 | MessageInit(arena, TraceStartMessageMessage(tsMessage), | ||
| 220 | &TraceStartMessageClassStruct, MessageTypeGCSTART); | ||
| 221 | tsMessage->why[0] = '\0'; | ||
| 222 | |||
| 223 | tsMessage->sig = TraceStartMessageSig; | ||
| 224 | AVERT(TraceStartMessage, tsMessage); | ||
| 225 | |||
| 226 | return; | ||
| 227 | } | ||
| 228 | |||
| 229 | |||
| 230 | /* traceStartWhyToString -- why-code to text | ||
| 231 | * | ||
| 232 | * Converts a TraceStartWhy* code into a constant string describing | ||
| 233 | * why a trace started. | ||
| 234 | */ | ||
| 235 | |||
| 236 | static const char *traceStartWhyToString(int why) | ||
| 237 | { | ||
| 238 | const char *r; | ||
| 239 | |||
| 240 | switch(why) { | ||
| 241 | case TraceStartWhyCHAIN_GEN0CAP: | ||
| 242 | r = "Generation 0 of a chain has reached capacity:" | ||
| 243 | " start a minor collection."; | ||
| 244 | break; | ||
| 245 | case TraceStartWhyDYNAMICCRITERION: | ||
| 246 | r = "Need to start full collection now, or there won't be enough" | ||
| 247 | " memory (ArenaAvail) to complete it."; | ||
| 248 | break; | ||
| 249 | case TraceStartWhyOPPORTUNISM: | ||
| 250 | r = "Opportunism: client predicts plenty of idle time," | ||
| 251 | " so start full collection."; | ||
| 252 | break; | ||
| 253 | case TraceStartWhyCLIENTFULL_INCREMENTAL: | ||
| 254 | r = "Client requests: start incremental full collection now."; | ||
| 255 | break; | ||
| 256 | case TraceStartWhyCLIENTFULL_BLOCK: | ||
| 257 | r = "Client requests: immediate full collection."; | ||
| 258 | break; | ||
| 259 | case TraceStartWhyWALK: | ||
| 260 | r = "Walking all live objects."; | ||
| 261 | break; | ||
| 262 | default: | ||
| 263 | NOTREACHED; | ||
| 264 | r = "Unknown reason (internal error)."; | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | |||
| 268 | return r; | ||
| 269 | } | ||
| 270 | |||
| 271 | |||
| 272 | /* traceStartWhyToTextBuffer | ||
| 273 | * | ||
| 274 | * Converts a TraceStartWhy* code into a string describing why a trace | ||
| 275 | * started, and copies that into the text buffer the caller provides. | ||
| 276 | * s specifies the beginning of the buffer to write the string | ||
| 277 | * into, len specifies the length of the buffer. | ||
| 278 | * The string written into will be NUL terminated (truncated if | ||
| 279 | * necessary). | ||
| 280 | */ | ||
| 281 | |||
| 282 | static void traceStartWhyToTextBuffer(char *s, size_t len, int why) | ||
| 283 | { | ||
| 284 | const char *r; | ||
| 285 | size_t i; | ||
| 286 | |||
| 287 | AVER(s); | ||
| 288 | /* len can be anything, including 0. */ | ||
| 289 | AVER(TraceStartWhyBASE <= why); | ||
| 290 | AVER(why < TraceStartWhyLIMIT); | ||
| 291 | |||
| 292 | r = traceStartWhyToString(why); | ||
| 293 | |||
| 294 | for(i=0; i<len; ++i) { | ||
| 295 | s[i] = r[i]; | ||
| 296 | if(r[i] == '\0') | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | s[len-1] = '\0'; | ||
| 300 | |||
| 301 | return; | ||
| 302 | } | ||
| 303 | |||
| 304 | |||
| 305 | /* ScanStateCheck -- check consistency of a ScanState object */ | 32 | /* ScanStateCheck -- check consistency of a ScanState object */ |
| 306 | 33 | ||
| 307 | Bool ScanStateCheck(ScanState ss) | 34 | Bool ScanStateCheck(ScanState ss) |
| @@ -1032,40 +759,6 @@ void TraceDestroy(Trace trace) | |||
| 1032 | } | 759 | } |
| 1033 | 760 | ||
| 1034 | 761 | ||
| 1035 | /* tracePostMessage -- post trace end message | ||
| 1036 | * | ||
| 1037 | * .message.data: The trace end message contains the live size | ||
| 1038 | * (forwardedSize + preservedInPlaceSize), the condemned size | ||
| 1039 | * (condemned), and the not-condemned size (notCondemned). */ | ||
| 1040 | |||
| 1041 | static void tracePostMessage(Trace trace) | ||
| 1042 | { | ||
| 1043 | Arena arena; | ||
| 1044 | void *p; | ||
| 1045 | TraceMessage message; | ||
| 1046 | Res res; | ||
| 1047 | |||
| 1048 | AVERT(Trace, trace); | ||
| 1049 | AVER(trace->state == TraceFINISHED); | ||
| 1050 | |||
| 1051 | arena = trace->arena; | ||
| 1052 | res = ControlAlloc(&p, arena, sizeof(TraceMessageStruct), FALSE); | ||
| 1053 | if(res == ResOK) { | ||
| 1054 | message = (TraceMessage)p; | ||
| 1055 | TraceMessageInit(arena, message); | ||
| 1056 | message->liveSize = trace->forwardedSize + trace->preservedInPlaceSize; | ||
| 1057 | message->condemnedSize = trace->condemned; | ||
| 1058 | message->notCondemnedSize = trace->notCondemned; | ||
| 1059 | MessagePost(arena, TraceMessageMessage(message)); | ||
| 1060 | } | ||
| 1061 | if(arena->alertCollection) { | ||
| 1062 | (*arena->alertCollection)(MPS_ALERT_COLLECTION_STOP, trace->why); | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | return; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | |||
| 1069 | /* traceReclaim -- reclaim the remaining objects white for this trace */ | 762 | /* traceReclaim -- reclaim the remaining objects white for this trace */ |
| 1070 | 763 | ||
| 1071 | static void traceReclaim(Trace trace) | 764 | static void traceReclaim(Trace trace) |
| @@ -1997,7 +1690,7 @@ void TraceStart(Trace trace, double mortality, double finishingTime) | |||
| 1997 | 1690 | ||
| 1998 | /* traceQuantum -- progresses a trace by one quantum */ | 1691 | /* traceQuantum -- progresses a trace by one quantum */ |
| 1999 | 1692 | ||
| 2000 | static void traceQuantum(Trace trace) | 1693 | void traceQuantum(Trace trace) |
| 2001 | { | 1694 | { |
| 2002 | Size pollEnd; | 1695 | Size pollEnd; |
| 2003 | 1696 | ||
| @@ -2038,7 +1731,7 @@ static void traceQuantum(Trace trace) | |||
| 2038 | * "why" is a TraceStartWhy* enum member that specifies why the | 1731 | * "why" is a TraceStartWhy* enum member that specifies why the |
| 2039 | * collection is starting. */ | 1732 | * collection is starting. */ |
| 2040 | 1733 | ||
| 2041 | static Res traceStartCollectAll(Trace *traceReturn, Arena arena, int why) | 1734 | Res traceStartCollectAll(Trace *traceReturn, Arena arena, int why) |
| 2042 | { | 1735 | { |
| 2043 | Trace trace; | 1736 | Trace trace; |
| 2044 | Res res; | 1737 | Res res; |
| @@ -2160,242 +1853,6 @@ failStart: | |||
| 2160 | } | 1853 | } |
| 2161 | 1854 | ||
| 2162 | 1855 | ||
| 2163 | /* ArenaClamp -- clamp the arena (no optional collection increments) */ | ||
| 2164 | |||
| 2165 | void ArenaClamp(Globals globals) | ||
| 2166 | { | ||
| 2167 | AVERT(Globals, globals); | ||
| 2168 | globals->clamped = TRUE; | ||
| 2169 | } | ||
| 2170 | |||
| 2171 | |||
| 2172 | /* ArenaRelease -- release the arena (allow optional collection | ||
| 2173 | * increments) */ | ||
| 2174 | |||
| 2175 | void ArenaRelease(Globals globals) | ||
| 2176 | { | ||
| 2177 | AVERT(Globals, globals); | ||
| 2178 | arenaForgetProtection(globals); | ||
| 2179 | globals->clamped = FALSE; | ||
| 2180 | (void)TracePoll(globals); | ||
| 2181 | } | ||
| 2182 | |||
| 2183 | |||
| 2184 | /* ArenaPark -- finish all current collections and clamp the arena */ | ||
| 2185 | |||
| 2186 | void ArenaPark(Globals globals) | ||
| 2187 | { | ||
| 2188 | TraceId ti; | ||
| 2189 | Trace trace; | ||
| 2190 | Arena arena; | ||
| 2191 | |||
| 2192 | AVERT(Globals, globals); | ||
| 2193 | arena = GlobalsArena(globals); | ||
| 2194 | |||
| 2195 | globals->clamped = TRUE; | ||
| 2196 | |||
| 2197 | while(arena->busyTraces != TraceSetEMPTY) { | ||
| 2198 | /* Poll active traces to make progress. */ | ||
| 2199 | TRACE_SET_ITER(ti, trace, arena->busyTraces, arena) | ||
| 2200 | traceQuantum(trace); | ||
| 2201 | if(trace->state == TraceFINISHED) { | ||
| 2202 | TraceDestroy(trace); | ||
| 2203 | } | ||
| 2204 | TRACE_SET_ITER_END(ti, trace, arena->busyTraces, arena); | ||
| 2205 | } | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | /* Low level stuff for Expose / Remember / Restore */ | ||
| 2209 | |||
| 2210 | typedef struct RememberedSummaryBlockStruct *RememberedSummaryBlock; | ||
| 2211 | |||
| 2212 | void rememberedSummaryBlockInit(struct RememberedSummaryBlockStruct *block) | ||
| 2213 | { | ||
| 2214 | size_t i; | ||
| 2215 | |||
| 2216 | RingInit(&block->globalRing); | ||
| 2217 | for(i = 0; i < RememberedSummaryBLOCK; ++ i) { | ||
| 2218 | block->the[i].base = (Addr)0; | ||
| 2219 | block->the[i].summary = RefSetUNIV; | ||
| 2220 | } | ||
| 2221 | return; | ||
| 2222 | } | ||
| 2223 | |||
| 2224 | Res arenaRememberSummaryOne(Globals global, Addr base, RefSet summary) | ||
| 2225 | { | ||
| 2226 | Arena arena; | ||
| 2227 | RememberedSummaryBlock block; | ||
| 2228 | |||
| 2229 | AVER(summary != RefSetUNIV); | ||
| 2230 | |||
| 2231 | arena = GlobalsArena(global); | ||
| 2232 | |||
| 2233 | if(global->rememberedSummaryIndex == 0) { | ||
| 2234 | void *p; | ||
| 2235 | RememberedSummaryBlock newBlock; | ||
| 2236 | int res; | ||
| 2237 | |||
| 2238 | res = ControlAlloc(&p, arena, sizeof *newBlock, 0); | ||
| 2239 | if(res != ResOK) { | ||
| 2240 | return res; | ||
| 2241 | } | ||
| 2242 | newBlock = p; | ||
| 2243 | rememberedSummaryBlockInit(newBlock); | ||
| 2244 | RingAppend(GlobalsRememberedSummaryRing(global), | ||
| 2245 | &newBlock->globalRing); | ||
| 2246 | } | ||
| 2247 | block = RING_ELT(RememberedSummaryBlock, globalRing, | ||
| 2248 | RingPrev(GlobalsRememberedSummaryRing(global))); | ||
| 2249 | AVER(global->rememberedSummaryIndex < RememberedSummaryBLOCK); | ||
| 2250 | AVER(block->the[global->rememberedSummaryIndex].base == (Addr)0); | ||
| 2251 | AVER(block->the[global->rememberedSummaryIndex].summary == RefSetUNIV); | ||
| 2252 | block->the[global->rememberedSummaryIndex].base = base; | ||
| 2253 | block->the[global->rememberedSummaryIndex].summary = summary; | ||
| 2254 | ++ global->rememberedSummaryIndex; | ||
| 2255 | if(global->rememberedSummaryIndex >= RememberedSummaryBLOCK) { | ||
| 2256 | AVER(global->rememberedSummaryIndex == RememberedSummaryBLOCK); | ||
| 2257 | global->rememberedSummaryIndex = 0; | ||
| 2258 | } | ||
| 2259 | |||
| 2260 | return ResOK; | ||
| 2261 | } | ||
| 2262 | |||
| 2263 | /* ArenaExposeRemember -- park arena and then lift all protection | ||
| 2264 | barriers. Parameter 'rememember' specifies whether to remember the | ||
| 2265 | protection state or not (for later restoration with | ||
| 2266 | ArenaRestoreProtection). | ||
| 2267 | */ | ||
| 2268 | void ArenaExposeRemember(Globals globals, int remember) | ||
| 2269 | { | ||
| 2270 | Seg seg; | ||
| 2271 | Arena arena; | ||
| 2272 | |||
| 2273 | AVERT(Globals, globals); | ||
| 2274 | |||
| 2275 | ArenaPark(globals); | ||
| 2276 | |||
| 2277 | arena = GlobalsArena(globals); | ||
| 2278 | if(SegFirst(&seg, arena)) { | ||
| 2279 | Addr base; | ||
| 2280 | |||
| 2281 | do { | ||
| 2282 | base = SegBase(seg); | ||
| 2283 | if(IsSubclassPoly(ClassOfSeg(seg), GCSegClassGet())) { | ||
| 2284 | if(remember) { | ||
| 2285 | RefSet summary; | ||
| 2286 | |||
| 2287 | summary = SegSummary(seg); | ||
| 2288 | if(summary != RefSetUNIV) { | ||
| 2289 | Res res = arenaRememberSummaryOne(globals, base, summary); | ||
| 2290 | if(res != ResOK) { | ||
| 2291 | /* If we got an error then stop trying to remember any | ||
| 2292 | protections. */ | ||
| 2293 | remember = 0; | ||
| 2294 | } | ||
| 2295 | } | ||
| 2296 | } | ||
| 2297 | SegSetSummary(seg, RefSetUNIV); | ||
| 2298 | AVER(SegSM(seg) == AccessSetEMPTY); | ||
| 2299 | } | ||
| 2300 | } while(SegNext(&seg, arena, base)); | ||
| 2301 | } | ||
| 2302 | return; | ||
| 2303 | } | ||
| 2304 | |||
| 2305 | void ArenaRestoreProtection(Globals globals) | ||
| 2306 | { | ||
| 2307 | Ring node, next; | ||
| 2308 | Arena arena; | ||
| 2309 | |||
| 2310 | arena = GlobalsArena(globals); | ||
| 2311 | |||
| 2312 | RING_FOR(node, GlobalsRememberedSummaryRing(globals), next) { | ||
| 2313 | RememberedSummaryBlock block = | ||
| 2314 | RING_ELT(RememberedSummaryBlock, globalRing, node); | ||
| 2315 | size_t i; | ||
| 2316 | |||
| 2317 | for(i = 0; i < RememberedSummaryBLOCK; ++ i) { | ||
| 2318 | Seg seg; | ||
| 2319 | Bool b; | ||
| 2320 | |||
| 2321 | if(block->the[i].base == (Addr)0) { | ||
| 2322 | AVER(block->the[i].summary == RefSetUNIV); | ||
| 2323 | continue; | ||
| 2324 | } | ||
| 2325 | b = SegOfAddr(&seg, arena, block->the[i].base); | ||
| 2326 | if(b && SegBase(seg) == block->the[i].base) { | ||
| 2327 | AVER(IsSubclassPoly(ClassOfSeg(seg), GCSegClassGet())); | ||
| 2328 | SegSetSummary(seg, block->the[i].summary); | ||
| 2329 | } else { | ||
| 2330 | /* Either seg has gone or moved, both of which are */ | ||
| 2331 | /* client errors. */ | ||
| 2332 | NOTREACHED; | ||
| 2333 | } | ||
| 2334 | } | ||
| 2335 | } | ||
| 2336 | |||
| 2337 | arenaForgetProtection(globals); | ||
| 2338 | return; | ||
| 2339 | } | ||
| 2340 | |||
| 2341 | void arenaForgetProtection(Globals globals) | ||
| 2342 | { | ||
| 2343 | Ring node, next; | ||
| 2344 | Arena arena; | ||
| 2345 | |||
| 2346 | arena = GlobalsArena(globals); | ||
| 2347 | /* Setting this early means that we preserve the invariant | ||
| 2348 | <code/global.c#remembered.summary> */ | ||
| 2349 | globals->rememberedSummaryIndex = 0; | ||
| 2350 | RING_FOR(node, GlobalsRememberedSummaryRing(globals), next) { | ||
| 2351 | RememberedSummaryBlock block = | ||
| 2352 | RING_ELT(RememberedSummaryBlock, globalRing, node); | ||
| 2353 | |||
| 2354 | RingRemove(node); | ||
| 2355 | ControlFree(arena, block, sizeof *block); | ||
| 2356 | } | ||
| 2357 | return; | ||
| 2358 | } | ||
| 2359 | |||
| 2360 | /* ArenaStartCollect -- start a collection of everything in the | ||
| 2361 | * arena; leave unclamped. */ | ||
| 2362 | |||
| 2363 | Res ArenaStartCollect(Globals globals, int why) | ||
| 2364 | { | ||
| 2365 | Arena arena; | ||
| 2366 | Res res; | ||
| 2367 | Trace trace; | ||
| 2368 | |||
| 2369 | AVERT(Globals, globals); | ||
| 2370 | arena = GlobalsArena(globals); | ||
| 2371 | |||
| 2372 | ArenaPark(globals); | ||
| 2373 | res = traceStartCollectAll(&trace, arena, why); | ||
| 2374 | if(res != ResOK) | ||
| 2375 | goto failStart; | ||
| 2376 | ArenaRelease(globals); | ||
| 2377 | return ResOK; | ||
| 2378 | |||
| 2379 | failStart: | ||
| 2380 | ArenaRelease(globals); | ||
| 2381 | return res; | ||
| 2382 | } | ||
| 2383 | |||
| 2384 | /* ArenaCollect -- collect everything in arena; leave clamped */ | ||
| 2385 | |||
| 2386 | Res ArenaCollect(Globals globals, int why) | ||
| 2387 | { | ||
| 2388 | Res res; | ||
| 2389 | |||
| 2390 | AVERT(Globals, globals); | ||
| 2391 | res = ArenaStartCollect(globals, why); | ||
| 2392 | if(res != ResOK) | ||
| 2393 | return res; | ||
| 2394 | |||
| 2395 | ArenaPark(globals); | ||
| 2396 | return ResOK; | ||
| 2397 | } | ||
| 2398 | |||
| 2399 | /* C. COPYRIGHT AND LICENSE | 1856 | /* C. COPYRIGHT AND LICENSE |
| 2400 | * | 1857 | * |
| 2401 | * Copyright (C) 2001-2003, 2006, 2007 Ravenbrook Limited | 1858 | * Copyright (C) 2001-2003, 2006, 2007 Ravenbrook Limited |