aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code/trace.c
diff options
context:
space:
mode:
authorRichard Kistruck2008-12-09 16:55:22 +0000
committerRichard Kistruck2008-12-09 16:55:22 +0000
commit77ea63625ab4250da91ffde66798bd417893a349 (patch)
tree5417bd41168c34afe1af896b3e8a60574cdb2d97 /mps/code/trace.c
parent6c5443770f517a519f91901c34d56475dad38e9d (diff)
downloademacs-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.c547
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 @@
14SRCID(trace, "$Id$"); 14SRCID(trace, "$Id$");
15 15
16/* Forward declarations */ 16/* Forward declarations */
17static void TraceStartMessageInit(Arena arena, TraceStartMessage tsMessage);
18Rank traceBand(Trace); 17Rank traceBand(Trace);
19Bool traceBandAdvance(Trace); 18Bool traceBandAdvance(Trace);
20Bool traceBandFirstStretch(Trace); 19Bool traceBandFirstStretch(Trace);
@@ -30,278 +29,6 @@ enum {
30}; 29};
31typedef int traceAccountingPhase; 30typedef int traceAccountingPhase;
32 31
33struct 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. */
42Res arenaRememberSummaryOne(Globals global, Addr base, RefSet summary);
43void arenaForgetProtection(Globals globals);
44void rememberedSummaryBlockInit(struct RememberedSummaryBlockStruct *block);
45
46
47/* TraceMessage -- type of GC end messages */
48
49#define TraceMessageSig ((Sig)0x51926359)
50
51typedef 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
63static 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
75static 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
88static 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
99static 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
110static 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
121static 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
134static 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
158static 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
178static 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
191static 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
202static 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
215static 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
236static 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
282static 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
307Bool ScanStateCheck(ScanState ss) 34Bool 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
1041static 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
1071static void traceReclaim(Trace trace) 764static 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
2000static void traceQuantum(Trace trace) 1693void 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
2041static Res traceStartCollectAll(Trace *traceReturn, Arena arena, int why) 1734Res 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
2165void 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
2175void 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
2186void 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
2210typedef struct RememberedSummaryBlockStruct *RememberedSummaryBlock;
2211
2212void 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
2224Res 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 */
2268void 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
2305void 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
2341void 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
2363Res 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
2379failStart:
2380 ArenaRelease(globals);
2381 return res;
2382}
2383
2384/* ArenaCollect -- collect everything in arena; leave clamped */
2385
2386Res 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