aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code/poolabs.c
diff options
context:
space:
mode:
authorNick Barnes2001-10-31 14:40:56 +0000
committerNick Barnes2001-10-31 14:40:56 +0000
commit7acfca905d76140f4cc0b09c9a12de237de364cd (patch)
tree3ed8babfa3a73d30f29e08ca5d5adcda4ca4e826 /mps/code/poolabs.c
parentb7ce4893f9902d57cd67ac9a92fa6c3d5a8fc833 (diff)
downloademacs-7acfca905d76140f4cc0b09c9a12de237de364cd.tar.gz
emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.zip
Branch imports for masters.
Copied from Perforce Change: 23678 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/poolabs.c')
-rw-r--r--mps/code/poolabs.c627
1 files changed, 627 insertions, 0 deletions
diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c
new file mode 100644
index 00000000000..0f530a1b68c
--- /dev/null
+++ b/mps/code/poolabs.c
@@ -0,0 +1,627 @@
1/* impl.c.poolabs: ABSTRACT POOL CLASSES
2 *
3 * $HopeName: MMsrc!poolabs.c(trunk.8) $
4 * Copyright (C) 1999 Harlequin Limited. All rights reserved.
5 *
6 * PURPOSE
7 *
8 * .purpose: This defines the abstract pool classes, giving
9 * a single-inheritance framework which concrete classes
10 * may utilize. The purpose is to reduce the fragility of class
11 * definitions for pool implementations when small changes are
12 * made to the pool protocol. For now, the class hierarchy for
13 * the abstract classes is intended to be useful, but not to
14 * represent any particular design for pool inheritance.
15 *
16 * HIERARCHY
17 *
18 * .hierarchy: define the following hierarchy of abstract pool classes:
19 * AbstractPoolClass - implements init, finish, describe
20 * AbstractAllocFreePoolClass - implements alloc & free
21 * AbstractBufferPoolClass - implements the buffer protocol
22 * AbstractSegBufPoolClass - uses SegBuf buffer class
23 * AbstractScanPoolClass - implements basic scanning
24 * AbstractCollectPoolClass - implements basic GC
25 */
26
27#include "mpm.h"
28
29SRCID(poolabs, "$HopeName: MMsrc!poolabs.c(trunk.8) $");
30
31
32typedef PoolClassStruct AbstractPoolClassStruct;
33typedef PoolClassStruct AbstractAllocFreePoolClassStruct;
34typedef PoolClassStruct AbstractBufferPoolClassStruct;
35typedef PoolClassStruct AbstractSegBufPoolClassStruct;
36typedef PoolClassStruct AbstractScanPoolClassStruct;
37typedef PoolClassStruct AbstractCollectPoolClassStruct;
38
39
40/* Mixins:
41 *
42 * For now (at least) we're avoiding multiple inheritance.
43 * However, there is a significant use of multiple inheritance
44 * in practice amongst the pool classes, as there are several
45 * orthogonal sub-protocols included in the pool protocol.
46 * The following mixin functions help to provide the inheritance
47 * via a simpler means than real multiple inheritance.
48 */
49
50
51/* PoolClassMixInAllocFree -- mix in the protocol for Alloc / Free */
52
53void PoolClassMixInAllocFree(PoolClass class)
54{
55 /* Can't check class because it's not initialized yet */
56 class->attr |= (AttrALLOC | AttrFREE);
57 class->alloc = PoolTrivAlloc;
58 class->free = PoolTrivFree;
59}
60
61
62/* PoolClassMixInBuffer -- mix in the protocol for buffer reserve / commit */
63
64void PoolClassMixInBuffer(PoolClass class)
65{
66 /* Can't check class because it's not initialized yet */
67 class->attr |= (AttrBUF | AttrBUF_RESERVE);
68 class->bufferFill = PoolTrivBufferFill;
69 class->bufferEmpty = PoolTrivBufferEmpty;
70 /* By default, buffered pools treat frame operations as NOOPs */
71 class->framePush = PoolTrivFramePush;
72 class->framePop = PoolTrivFramePop;
73 class->bufferClass = BufferClassGet;
74}
75
76
77/* PoolClassMixInScan -- mix in the protocol for scanning */
78
79void PoolClassMixInScan(PoolClass class)
80{
81 /* Can't check class because it's not initialized yet */
82 class->attr |= AttrSCAN;
83 class->access = PoolSegAccess;
84 class->blacken = PoolTrivBlacken;
85 class->grey = PoolTrivGrey;
86 /* Scan is part of the scanning protocol - but there is */
87 /* no useful default method */
88}
89
90
91/* PoolClassMixInFormat -- mix in the protocol for formatted pools */
92
93void PoolClassMixInFormat(PoolClass class)
94{
95 /* Can't check class because it's not initialized yet */
96 class->attr |= AttrFMT;
97}
98
99
100/* PoolClassMixInCollect -- mix in the protocol for GC */
101
102void PoolClassMixInCollect(PoolClass class)
103{
104 /* Can't check class because it's not initialized yet */
105 class->attr |= (AttrGC | AttrINCR_RB);
106 class->whiten = PoolTrivWhiten;
107 /* Fix & reclaim are part of the collection protocol - but there */
108 /* are no useful default methods for them. */
109 class->rampBegin = PoolTrivRampBegin;
110 class->rampEnd = PoolTrivRampEnd;
111}
112
113
114/* Classes */
115
116
117DEFINE_CLASS(AbstractPoolClass, class)
118{
119 INHERIT_CLASS(&class->protocol, ProtocolClass);
120 class->name = "ABSTRACT";
121 class->size = 0;
122 class->offset = 0;
123 class->attr = 0;
124 class->init = PoolTrivInit;
125 class->finish = PoolTrivFinish;
126 class->alloc = PoolNoAlloc;
127 class->free = PoolNoFree;
128 class->bufferFill = PoolNoBufferFill;
129 class->bufferEmpty = PoolNoBufferEmpty;
130 class->access = PoolNoAccess;
131 class->whiten = PoolNoWhiten;
132 class->grey = PoolNoGrey;
133 class->blacken = PoolNoBlacken;
134 class->scan = PoolNoScan;
135 class->fix = PoolNoFix;
136 class->fixEmergency = PoolNoFix;
137 class->reclaim = PoolNoReclaim;
138 class->rampBegin = PoolNoRampBegin;
139 class->rampEnd = PoolNoRampEnd;
140 class->framePush = PoolNoFramePush;
141 class->framePop = PoolNoFramePop;
142 class->framePopPending = PoolNoFramePopPending;
143 class->walk = PoolNoWalk;
144 class->bufferClass = PoolNoBufferClass;
145 class->describe = PoolTrivDescribe;
146 class->debugMixin = PoolNoDebugMixin;
147 class->labelled = FALSE;
148 class->sig = PoolClassSig;
149}
150
151DEFINE_CLASS(AbstractAllocFreePoolClass, class)
152{
153 INHERIT_CLASS(class, AbstractPoolClass);
154 PoolClassMixInAllocFree(class);
155}
156
157DEFINE_CLASS(AbstractBufferPoolClass, class)
158{
159 INHERIT_CLASS(class, AbstractPoolClass);
160 PoolClassMixInBuffer(class);
161}
162
163DEFINE_CLASS(AbstractSegBufPoolClass, class)
164{
165 INHERIT_CLASS(class, AbstractBufferPoolClass);
166 class->bufferClass = SegBufClassGet;
167}
168
169DEFINE_CLASS(AbstractScanPoolClass, class)
170{
171 INHERIT_CLASS(class, AbstractSegBufPoolClass);
172 PoolClassMixInScan(class);
173}
174
175DEFINE_CLASS(AbstractCollectPoolClass, class)
176{
177 INHERIT_CLASS(class, AbstractScanPoolClass);
178 PoolClassMixInCollect(class);
179}
180
181
182/* PoolNo*, PoolTriv* -- Trivial and non-methods for Pool Classes
183 *
184 * See design.mps.pool.no and design.mps.pool.triv
185 */
186
187
188void PoolTrivFinish(Pool pool)
189{
190 AVERT(Pool, pool);
191 NOOP;
192}
193
194Res PoolTrivInit(Pool pool, va_list args)
195{
196 AVERT(Pool, pool);
197 UNUSED(args);
198 return ResOK;
199}
200
201Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size,
202 Bool withReservoirPermit)
203{
204 AVER(pReturn != NULL);
205 AVERT(Pool, pool);
206 AVER(size > 0);
207 AVER(BoolCheck(withReservoirPermit));
208 NOTREACHED;
209 return ResUNIMPL;
210}
211
212Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size,
213 Bool withReservoirPermit)
214{
215 AVER(pReturn != NULL);
216 AVERT(Pool, pool);
217 AVER(size > 0);
218 AVER(BoolCheck(withReservoirPermit));
219 return ResLIMIT;
220}
221
222void PoolNoFree(Pool pool, Addr old, Size size)
223{
224 AVERT(Pool, pool);
225 AVER(old != NULL);
226 AVER(size > 0);
227 NOTREACHED;
228}
229
230void PoolTrivFree(Pool pool, Addr old, Size size)
231{
232 AVERT(Pool, pool);
233 AVER(old != NULL);
234 AVER(size > 0);
235 NOOP; /* trivial free has no effect */
236}
237
238
239Res PoolNoBufferFill(Addr *baseReturn, Addr *limitReturn,
240 Pool pool, Buffer buffer, Size size,
241 Bool withReservoirPermit)
242{
243 AVER(baseReturn != NULL);
244 AVER(limitReturn != NULL);
245 AVERT(Pool, pool);
246 AVERT(Buffer, buffer);
247 AVER(size > 0);
248 AVER(BoolCheck(withReservoirPermit));
249 NOTREACHED;
250 return ResUNIMPL;
251}
252
253Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn,
254 Pool pool, Buffer buffer, Size size,
255 Bool withReservoirPermit)
256{
257 Res res;
258 Addr p;
259
260 AVER(baseReturn != NULL);
261 AVER(limitReturn != NULL);
262 AVERT(Pool, pool);
263 AVERT(Buffer, buffer);
264 AVER(size > 0);
265 AVER(BoolCheck(withReservoirPermit));
266
267 res = PoolAlloc(&p, pool, size, withReservoirPermit);
268 if(res != ResOK) return res;
269
270 *baseReturn = p;
271 *limitReturn = AddrAdd(p, size);
272 return ResOK;
273}
274
275
276void PoolNoBufferEmpty(Pool pool, Buffer buffer,
277 Addr init, Addr limit)
278{
279 AVERT(Pool, pool);
280 AVERT(Buffer, buffer);
281 AVER(BufferIsReady(buffer));
282 AVER(init <= limit);
283 NOTREACHED;
284}
285
286void PoolTrivBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
287{
288 AVERT(Pool, pool);
289 AVERT(Buffer, buffer);
290 AVER(BufferIsReady(buffer));
291 AVER(init <= limit);
292 if (limit > init)
293 PoolFree(pool, init, AddrOffset(init, limit));
294}
295
296
297Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream)
298{
299 AVERT(Pool, pool);
300 AVER(stream != NULL);
301 return WriteF(stream, " No class-specific description available.\n", NULL);
302}
303
304
305Res PoolNoTraceBegin(Pool pool, Trace trace)
306{
307 AVERT(Pool, pool);
308 AVERT(Trace, trace);
309 AVER(PoolArena(pool) == trace->arena);
310 NOTREACHED;
311 return ResUNIMPL;
312}
313
314Res PoolTrivTraceBegin(Pool pool, Trace trace)
315{
316 AVERT(Pool, pool);
317 AVERT(Trace, trace);
318 AVER(PoolArena(pool) == trace->arena);
319 return ResOK;
320}
321
322/* NoAccess
323 *
324 * Should be used (for the access method) by Pool Classes which do
325 * not expect to ever have pages which the mutator will fault on.
326 * That is, no protected pages, or only pages which are inaccessible
327 * by the mutator are protected.
328 */
329Res PoolNoAccess(Pool pool, Seg seg, Addr addr,
330 AccessSet mode, MutatorFaultContext context)
331{
332 AVERT(Pool, pool);
333 AVERT(Seg, seg);
334 AVER(SegBase(seg) <= addr);
335 AVER(addr < SegLimit(seg));
336 /* can't check AccessSet as there is no Check method */
337 /* can't check context as there is no Check method */
338 UNUSED(mode);
339 UNUSED(context);
340
341 NOTREACHED;
342 return ResUNIMPL;
343}
344
345
346/* SegAccess
347 *
348 * Should be used (for the access method) by Pool Classes which intend
349 * to handle page faults by scanning the entire segment and lowering
350 * the barrier.
351 */
352Res PoolSegAccess(Pool pool, Seg seg, Addr addr,
353 AccessSet mode, MutatorFaultContext context)
354{
355 AVERT(Pool, pool);
356 AVERT(Seg, seg);
357 AVER(SegBase(seg) <= addr);
358 AVER(addr < SegLimit(seg));
359 AVER(SegPool(seg) == pool);
360 /* can't check AccessSet as there is no Check method */
361 /* can't check context as there is no Check method */
362
363 UNUSED(addr);
364 UNUSED(context);
365 TraceSegAccess(PoolArena(pool), seg, mode);
366 return ResOK;
367}
368
369
370/* SingleAccess
371 *
372 * Handles page faults by attempting emulation. If the faulting
373 * instruction cannot be emulated then this function returns ResFAIL.
374 *
375 * Due to the assumptions made below, pool classes should only use
376 * this function if all words in an object are tagged or traceable.
377 *
378 * .single-access.assume.ref: It currently assumes that the address
379 * being faulted on contains a plain reference or a tagged non-reference.
380 * .single-access.improve.format: * later this will be abstracted
381 * through the cleint object format interface, so that
382 * no such assumption is necessary.
383 */
384Res PoolSingleAccess(Pool pool, Seg seg, Addr addr,
385 AccessSet mode, MutatorFaultContext context)
386{
387 Arena arena;
388
389 AVERT(Pool, pool);
390 AVERT(Seg, seg);
391 AVER(SegBase(seg) <= addr);
392 AVER(addr < SegLimit(seg));
393 AVER(SegPool(seg) == pool);
394 /* can't check AccessSet as there is no Check method */
395 /* can't check context as there is no Check method */
396
397 arena = PoolArena(pool);
398
399 if(ProtCanStepInstruction(context)) {
400 Ref ref;
401 Res res;
402
403 ShieldExpose(arena, seg);
404
405 if(mode & SegSM(seg) & AccessREAD) {
406 /* read access */
407 /* .single-access.assume.ref */
408 /* .single-access.improve.format */
409 ref = *(Ref *)addr;
410 /* Check that the reference is aligned to a word boundary */
411 /* (we assume it is not a reference otherwise) */
412 if(WordIsAligned((Word)ref, sizeof(Word))) {
413 /* See the note in TraceSegAccess about using RankEXACT here */
414 /* (impl.c.trace.scan.conservative) */
415 TraceScanSingleRef(arena->flippedTraces, RankEXACT, arena,
416 seg, (Ref *)addr);
417 }
418 }
419 res = ProtStepInstruction(context);
420 AVER(res == ResOK);
421
422 /* update SegSummary according to the possibly changed reference */
423 ref = *(Ref *)addr;
424 SegSetSummary(seg, RefSetAdd(arena, SegSummary(seg), ref));
425
426 ShieldCover(arena, seg);
427
428 return ResOK;
429 } else {
430 /* couldn't single-step instruction */
431 return ResFAIL;
432 }
433}
434
435
436Res PoolTrivWhiten(Pool pool, Trace trace, Seg seg)
437{
438 AVERT(Pool, pool);
439 AVERT(Trace, trace);
440 AVERT(Seg, seg);
441
442 SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace));
443
444 return ResOK;
445}
446
447Res PoolNoWhiten(Pool pool, Trace trace, Seg seg)
448{
449 AVERT(Pool, pool);
450 AVERT(Trace, trace);
451 AVERT(Seg, seg);
452 NOTREACHED;
453 return ResUNIMPL;
454}
455
456
457void PoolNoGrey(Pool pool, Trace trace, Seg seg)
458{
459 AVERT(Pool, pool);
460 AVERT(Trace, trace);
461 AVERT(Seg, seg);
462 NOTREACHED;
463}
464
465void PoolTrivGrey(Pool pool, Trace trace, Seg seg)
466{
467 AVERT(Pool, pool);
468 AVERT(Trace, trace);
469 AVERT(Seg, seg);
470
471 /* @@@@ The trivial grey method probably shouldn't exclude */
472 /* the white segments, since they might also contain grey objects. */
473 if(!TraceSetIsMember(SegWhite(seg), trace))
474 SegSetGrey(seg, TraceSetSingle(trace));
475}
476
477
478void PoolNoBlacken(Pool pool, TraceSet traceSet, Seg seg)
479{
480 AVERT(Pool, pool);
481 AVERT(TraceSet, traceSet);
482 AVERT(Seg, seg);
483 NOTREACHED;
484}
485
486void PoolTrivBlacken(Pool pool, TraceSet traceSet, Seg seg)
487{
488 AVERT(Pool, pool);
489 AVERT(TraceSet, traceSet);
490 AVERT(Seg, seg);
491
492 /* The trivial blacken method does nothing; for pool classes which do */
493 /* not keep additional colour information. */
494 NOOP;
495}
496
497
498Res PoolNoScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
499{
500 AVER(totalReturn != NULL);
501 AVERT(ScanState, ss);
502 AVERT(Pool, pool);
503 AVERT(Seg, seg);
504 NOTREACHED;
505 return ResUNIMPL;
506}
507
508Res PoolNoFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
509{
510 AVERT(Pool, pool);
511 AVERT(ScanState, ss);
512 AVERT(Seg, seg);
513 AVER(refIO != NULL);
514 NOTREACHED;
515 return ResUNIMPL;
516}
517
518void PoolNoReclaim(Pool pool, Trace trace, Seg seg)
519{
520 AVERT(Pool, pool);
521 AVERT(Trace, trace);
522 AVERT(Seg, seg);
523 NOTREACHED;
524}
525
526
527void PoolNoRampBegin(Pool pool, Buffer buf, Bool collectAll)
528{
529 AVERT(Pool, pool);
530 AVERT(Buffer, buf);
531 AVERT(Bool, collectAll);
532 NOTREACHED;
533}
534
535
536void PoolNoRampEnd(Pool pool, Buffer buf)
537{
538 AVERT(Pool, pool);
539 AVERT(Buffer, buf);
540 NOTREACHED;
541}
542
543
544void PoolTrivRampBegin(Pool pool, Buffer buf, Bool collectAll)
545{
546 AVERT(Pool, pool);
547 AVERT(Buffer, buf);
548 AVERT(Bool, collectAll);
549}
550
551
552void PoolTrivRampEnd(Pool pool, Buffer buf)
553{
554 AVERT(Pool, pool);
555 AVERT(Buffer, buf);
556}
557
558
559Res PoolNoFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf)
560{
561 AVER(frameReturn != NULL);
562 AVERT(Pool, pool);
563 AVERT(Buffer, buf);
564 NOTREACHED;
565 return ResUNIMPL;
566}
567
568
569Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame)
570{
571 AVERT(Pool, pool);
572 AVERT(Buffer, buf);
573 /* frame is of a abstract type & can't be checked */
574 UNUSED(frame);
575 NOTREACHED;
576 return ResUNIMPL;
577}
578
579
580void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame)
581{
582 AVERT(Pool, pool);
583 AVERT(Buffer, buf);
584 /* frame is of a abstract type & can't be checked */
585 UNUSED(frame);
586 NOTREACHED;
587}
588
589
590Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf)
591{
592 AVER(frameReturn != NULL);
593 AVERT(Pool, pool);
594 AVERT(Buffer, buf);
595 return ResOK;
596}
597
598
599Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame)
600{
601 AVERT(Pool, pool);
602 AVERT(Buffer, buf);
603 /* frame is of a abstract type & can't be checked */
604 UNUSED(frame);
605 return ResOK;
606}
607
608
609void PoolNoWalk(Pool pool, Seg seg,
610 FormattedObjectsStepMethod f, void *p, Size s)
611{
612 AVERT(Pool, pool);
613 AVERT(Seg, seg);
614 AVER(FUNCHECK(f));
615 /* p and s are arbitrary, hence can't be checked */
616 UNUSED(p);
617 UNUSED(s);
618
619 NOTREACHED;
620}
621
622
623BufferClass PoolNoBufferClass(void)
624{
625 NOTREACHED;
626 return NULL;
627}