|
|
1.1 root 1: #include "../h/rt.h"
2: #include "../h/gc.h"
3: #ifdef VAX
4: #define MAIN
5: #endif VAX
6: #ifdef PORT
7: #define MAIN
8: #endif PORT
9: #ifdef MAIN
10: /*
11: * hneed - insure that at least bytes of space are left in the heap.
12: * The amount of space needed is transmitted to the collector via
13: * the global variable heapneed.
14: */
15:
16: hneed(bytes)
17: unsigned bytes;
18: {
19: heapneed = bytes;
20: if (bytes > maxheap - hpfree)
21: gcollect(0);
22: }
23:
24: /*
25: * sneed - insure that at least chars of space are left in the string
26: * space. The amount of space needed is transmitted to the collector
27: * via the global variable strneed.
28: */
29:
30: sneed(chars)
31: unsigned chars;
32: {
33: strneed = chars;
34: if (chars > estrings - sfree)
35: gcollect(0);
36: }
37:
38: /*
39: * esneed - insure that there is a free co-expression stack. esfree
40: * points to the linked list of free stacks.
41: */
42:
43: esneed()
44: {
45: if (esfree == NULL)
46: gcollect(1);
47: }
48:
49: /*
50: * escollect - collect the expression stack space. This is done after
51: * the marking phase of garbage collection and the stacks that are
52: * reachable have pointers to data blocks, rather than T_ESTACK,
53: * in their type field.
54: */
55:
56: escollect()
57: {
58: register int *ep;
59: register struct b_estack *sp;
60:
61: /*
62: * Reset the type for &main.
63: */
64: BLKLOC(k_main)->estack.type = T_ESTACK;
65:
66: /*
67: * Reset the free list pointer.
68: */
69: esfree = NULL;
70:
71: /*
72: * The co-expression stacks start at stacks and lie contiguously.
73: * ep is pointed at the low word of each stack and sp is pointed
74: * at the b_estack block contained in the space for the stack.
75: * (Note that the last word of the b_estack block is the last word
76: * of the space for the co-expression stack.
77: */
78: for (ep = stacks; ep < estacks; ep += stksize) {
79: sp = (struct b_estack *) (ep + (stksize - sizeof(struct b_estack)/WORDSIZE));
80: if (blktype(sp) == T_ESTACK) {
81: /*
82: * This co-expression was not marked, so it can be collected.
83: * The stacks are linked through the first word of the stack
84: * space with esfree pointing to the last-collected stack.
85: */
86: *ep = (int) esfree;
87: esfree = ep;
88: }
89: else
90: /*
91: * The co-expression was marked, so just reset the type field.
92: */
93: blktype(sp) = T_ESTACK;
94: }
95: }
96:
97: /*
98: * collect - do a garbage collection. esneed indicates if a co-expression
99: * stack is needed.
100: */
101:
102: collect(esneed)
103: int esneed;
104: {
105: register int extra;
106: register char *newend;
107: register struct descrip *dp;
108: char *sptr;
109: extern char *brk();
110:
111: /*
112: * Reset the string qualifier free list pointer.
113: */
114: sqfree = sqlist;
115:
116: /*
117: * Mark the stacks for &main and the current co-expression.
118: */
119: mark(&k_main);
120: mark(¤t);
121: /*
122: * Mark &subject and the cached s2 and s3 strings for map().
123: */
124: mark(&k_subject);
125: mark(&maps2);
126: mark(&maps3);
127: /*
128: * Mark the tended descriptors and the global and static variables.
129: */
130: for (dp = tended; dp < etended; dp++)
131: mark(dp);
132: for (dp = globals; dp < eglobals; dp++)
133: mark(dp);
134: for (dp = statics; dp < estatics; dp++)
135: mark(dp);
136:
137: /*
138: * Collect available co-expression stacks.
139: */
140: escollect();
141: if (esneed && esfree == NULL) {
142: /*
143: * A co-expression stack is needed, but none are available. The
144: * new stack at the end of the stack space and is made available
145: * by pointing esfree at it. *estacks is zeroed to terminate the
146: * (now one element) co-expression free list.
147: */
148: esfree = estacks;
149: *estacks = 0;
150: /*
151: * Move back the end of the expression space by the size of a
152: * stack and indicate stksize words of memory are needed.
153: */
154: estacks += stksize;
155: extra = stksize*WORDSIZE;
156: newend = (char *) sqlist + extra;
157: /*
158: * This next calculation determines if there is space for the new
159: * stack, but it's not clear what all's going on here.
160: */
161: if (newend < (char *)sqlist || newend > (char *)0x7fffffff ||
162: (newend > (char *)esqlist && ((int) brk(newend) == -1)))
163: runerr(305, NULL);
164: }
165: else
166: /*
167: * Another co-expression stack is not needed.
168: */
169: extra = 0;
170:
171: /*
172: * Collect the string space, indicating that it must be moved back
173: * extra bytes.
174: */
175: scollect(extra);
176: /*
177: * sptr is post-gc value for strings. Move back pointers for estrings
178: * and sqlist according to value of extra.
179: */
180: sptr = strings + extra;
181: estrings += extra;
182: sqlist = sqlist + extra;
183: if (sqlist > esqlist)
184: esqlist = sqlist;
185:
186: /*
187: * Calculate a value for extra space. The value is (the larger of
188: * (twice the string space needed) or (the number of words currently
189: * in the string space)) plus the unallocated string space.
190: */
191: extra = (MAX(2*strneed, (estrings-(char *)estacks)/4) -
192: (estrings - extra - sfree) + (GRANSIZE-1)) & ~(GRANSIZE-1);
193:
194: while (extra > 0) {
195: /*
196: * Try to get extra more bytes of storage. If it can't be gotten,
197: * decrease the value by GRANSIZE and try again. If it's gotten,
198: * move back estrings and sqlist.
199: */
200: newend = (char *)sqlist + extra;
201: if (newend >= (char *)sqlist &&
202: (newend <= (char *)esqlist || ((int) brk(newend) != -1))) {
203: estrings += extra;
204: sqlist = (struct descrip **) newend;
205: break;
206: }
207: extra -= GRANSIZE;
208: }
209:
210: /*
211: * Adjust the pointers in the heap. Note that hpbase is the old base
212: * of the heap and estrings will be the post-gc base of the heap.
213: */
214: adjust(hpbase,estrings);
215: /*
216: * Compact the heap.
217: */
218: compact(hpbase);
219: /*
220: * Calculate a value for extra space. The value is (the larger of
221: * (twice the heap space needed) or (the number of words currently
222: * in the heap space)) plus the unallocated heap space.
223: */
224: extra = (MAX(2*heapneed, (maxheap-hpbase)/4) +
225: hpfree - maxheap + (GRANSIZE-1)) & ~(GRANSIZE-1);
226: while (extra > 0) {
227: /*
228: * Try to get extra more bytes of storage. If it can't be gotten,
229: * decrease the value by GRANSIZE and try again. If it's gotten,
230: * move back sqlist.
231: */
232: newend = (char *)sqlist + extra;
233: if (newend >= (char *)sqlist &&
234: (newend <= (char *)esqlist || ((int) brk(newend) != -1))) {
235: sqlist = (struct descrip **) newend;
236: break;
237: }
238: extra -= GRANSIZE;
239: }
240: if (sqlist > esqlist)
241: esqlist = sqlist;
242:
243: if (estrings != hpbase) {
244: /*
245: * estrings is not equal to hpbase and this indicates that the
246: * co-expression and/or string space was expanded and thus
247: * the heap must be moved. There is an assumption here that the
248: * heap always moves up in memory, i.e., the co-expression and
249: * string spaces never shrink. With this assumption in hand,
250: * the heap must be moved before the string space lest the string
251: * space overwrite heap data. The assumption is valid, but beware
252: * if shrinking regions are ever implemented.
253: */
254: mvc((unsigned)(hpfree - hpbase), hpbase, estrings);
255: hpfree += estrings - hpbase;
256: hpbase = estrings;
257: }
258: if (sptr != strings) {
259: /*
260: * sptr is not equal to strings and this indicates that the
261: * co-expression space was expanded and thus the string space
262: * must be moved up in memory.
263: */
264: mvc((unsigned)(sfree - strings), strings, sptr);
265: sfree += sptr - strings;
266: strings = sptr;
267: }
268:
269: /*
270: * Expand the heap.
271: */
272: maxheap = (char *)sqlist;
273: return;
274: }
275: /*
276: * mark - mark each accessible block in the heap and build back-list of
277: * descriptors pointing to that block. (Phase I of garbage collection.)
278: */
279:
280: mark(cdesc)
281: struct descrip *cdesc;
282: {
283: register struct descrip *ndesc;
284: register char *endblock, *block;
285: static int type;
286: static int fdesc;
287:
288: if (QUAL(*cdesc))
289: /*
290: * The descriptor is for a string, so pass the buck to marksq.
291: */
292: marksq(cdesc);
293: else if (isptr(cdesc)) {
294: /*
295: * The descriptor is a pointer to a block or a variable. Point
296: * block at the block referenced by the descriptor.
297: */
298: block = (char *) BLKLOC(*cdesc);
299: if (VAR(*cdesc) && !TVAR(*cdesc))
300: /*
301: * The descriptor is a variable; point block at the start of the
302: * block containing the descriptor that cdesc points to. For
303: * example, descriptors of this sort are created by subscripting
304: * lists.
305: */
306: block = (char *) ((int *) block - OFFSET(*cdesc));
307:
308: if (block >= hpbase && block < hpfree) {
309: /*
310: * The block is the heap (blocks outside the heap are ignored);
311: * get the type of the block.
312: */
313: type = blktype(block);
314: if (type <= MAXTYPE)
315: /*
316: * type is a valid type, indicating that this block hasn't
317: * been marked. Point endblock at the byte past the end
318: * of the block.
319: */
320: endblock = block + getsize(block);
321: /*
322: * Add cdesc to the back-chain for the block and point the
323: * block (via the type field) at cdesc.
324: */
325: BLKLOC(*cdesc) = (union block *) type;
326: blktype(block) = (int) cdesc;
327: if ((type <= MAXTYPE) && ((fdesc = firstd[(int)type]) > 0))
328: /*
329: * The block has not been marked, and it does contain descriptors.
330: * Mark each descriptor.
331: */
332: for (ndesc = (struct descrip *) (block + fdesc);
333: (char *) ndesc < endblock; ndesc++)
334: mark(ndesc);
335: }
336: if (!VAR(*cdesc) && TYPE(*cdesc) == T_ESTACK &&
337: blktype(block) <= MAXTYPE) {
338: /*
339: * cdesc points to a co-expression block that hasn't been marked.
340: * Point the block at cdesc. Sweep the co-expression's stack
341: * and mark the blocks for the activating co-expression and
342: * the co-expression's refresh block.
343: */
344: blktype(block) = (int) cdesc;
345: sweep(((struct b_estack *)block)->boundary);
346: mark(&((struct b_estack *)block)->activator);
347: mark(&((struct b_estack *)block)->freshblk);
348: }
349: }
350: }
351:
352: /*
353: * adjust - adjust pointers into heap, beginning with block oblk and
354: * basing the "new" heap at nblk. (Phase II of garbage collection.)
355: */
356:
357: adjust(oblk,nblk)
358: char *oblk, *nblk;
359: {
360: register struct descrip *nxtptr, *tptr;
361:
362: /*
363: * Loop through to end of allocated heap space moving oblk to each
364: * block in turn, using the size of a block to find the next block.
365: */
366: while (oblk < hpfree) {
367: if ((int) (nxtptr = (struct descrip *) blktype(oblk)) > MAXTYPE) {
368: /*
369: * The type field of oblk is a back-pointer. Work along the chain
370: * of back pointers, changing each block location from oblk
371: * to nblk.
372: */
373: while ((unsigned)nxtptr > MAXTYPE) {
374: tptr = nxtptr;
375: nxtptr = (struct descrip *) BLKLOC(*nxtptr);
376: if (VAR(*tptr) && !TVAR(*tptr))
377: BLKLOC(*tptr) = (union block *) ((int *) nblk + OFFSET(*tptr));
378: else
379: BLKLOC(*tptr) = (union block *) nblk;
380: }
381: blktype(oblk) = (unsigned)nxtptr | MARK;
382: nblk += getsize(oblk);
383: }
384: oblk += getsize(oblk);
385: }
386: }
387:
388: /*
389: * compact - compact good blocks in heap. (Phase III of garbage collection.)
390: */
391:
392: compact(oblk)
393: char *oblk;
394: {
395: register char *nblk;
396: register int size;
397:
398: /*
399: * Start at oblk, which happens to be hpbase.
400: */
401: nblk = oblk;
402: /*
403: * Loop through to end of allocated heap space moving oblk to each
404: * block in turn, using the size of a block to find the next block.
405: * If a block has been marked, it is copied to the location pointed
406: * at by nblk and nblk is pointed past the end of the block, which
407: * is the location to place the next good block at. Good blocks
408: * are un-marked.
409: */
410: while (oblk < hpfree) {
411: size = getsize(oblk);
412: if (blktype(oblk) & MARK) {
413: blktype(oblk) &= ~MARK;
414: if (oblk != nblk)
415: mvc((unsigned)size,oblk,nblk);
416: nblk += size;
417: }
418: oblk += size;
419: }
420: /*
421: * nblk is the location of the next free block, so now that compaction
422: * is complete, point hpfree at that location.
423: */
424: hpfree = nblk;
425: }
426:
427: /*
428: * marksq - mark a string qualifier. Strings outside the string space
429: * are ignored.
430: */
431:
432: marksq(d)
433: struct descrip *d;
434: {
435: extern char *brk();
436:
437: if (STRLOC(*d) >= strings && STRLOC(*d) < estrings) {
438: /*
439: * The string is in the string space, add it to the string qualifier
440: * list. But before adding it, expand the string qualifier list
441: * if necessary.
442: */
443: if (sqfree >= esqlist) {
444: esqlist += SQLINC;
445: if ((int) brk(esqlist) == -1)
446: runerr(303, NULL);
447: }
448: *sqfree++ = d;
449: }
450: }
451:
452: /*
453: * scollect - collect the string space. sqlist is a list of pointers to
454: * descriptors for all the reachable strings in the string space. For
455: * ease of description, it is referred to as if it were composed of
456: * descriptors rather than pointers to them.
457: */
458:
459: scollect(extra)
460: int extra;
461: {
462: register char *s, *d;
463: register struct descrip **p;
464: char *e;
465: extern int sqcmp();
466:
467: if (sqfree <= sqlist) {
468: /*
469: * There are no accessible strings, thus there are none to collect
470: * and the whole string space is free.
471: */
472: sfree = strings;
473: return;
474: }
475: /*
476: * Sort the sqlist in ascending order of string locations.
477: */
478: qsort(sqlist, sqfree-sqlist, sizeof(struct descrip *), sqcmp);
479: /*
480: * The string qualifiers are now ordered by starting location.
481: * The algorithm used is described in detail in one of the references
482: * cited in the "tour", but briefly...
483: *
484: * The string region can be thought of as being made up of clumps,
485: * where a clump is a contiguous area of strings that are referenced.
486: * For example, imagine sqlist looks like:
487: *
488: * [2,400]
489: * [3,400]
490: * [10,400]
491: * [12,415]
492: * [4,420]
493: * [3,430]
494: * [1,430]
495: *
496: * There are three clumps: The first starts at location 400 and extends
497: * to 409. The second starts at 415 and extends to 426. The third
498: * starts at 430 and extends to 432. Note that there are gaps, i.e.
499: * garbage, at 410-414 and 427-429.
500: *
501: * After collection, sqlist will look like:
502: *
503: * [2,400]
504: * [3,400]
505: * [10,400]
506: * [12,410]
507: * [4,415]
508: * [3,422]
509: * [1,422]
510: *
511: * Note how the gaps have been closed by moving the strings downward
512: * in memory.
513: *
514: * The method used is to look at each qualifier in sqlist in turn
515: * and determine which ones lie in clumps and the extent of each
516: * clump. The qualifiers referencing strings in each clump are
517: * relocated and then the clump is moved down (compacted).
518: *
519: * d points to the next free location to compact into. s is the
520: * start of the current clump and e is the end.
521: */
522: d = strings;
523: s = e = STRLOC(**sqlist);
524: /*
525: * Loop through qualifiers for accessible strings.
526: */
527: for (p = sqlist; p < sqfree; p++) {
528: if (STRLOC(**p) > e) {
529: /*
530: * p is a qualifier for a string in the next clump; the last
531: * clump is moved and s and e are set for the next clump.
532: */
533: while (s < e)
534: *d++ = *s++;
535: s = e = STRLOC(**p);
536: }
537: if (STRLOC(**p)+STRLEN(**p) > e)
538: /*
539: * p is a qualifier for a string in this clump, extend the clump.
540: */
541: e = STRLOC(**p) + STRLEN(**p);
542: /*
543: * Relocate the string qualifier.
544: */
545: STRLOC(**p) += d - s + extra;
546: }
547: /*
548: * Move the last clump.
549: */
550: while (s < e)
551: *d++ = *s++;
552: sfree = d;
553: }
554:
555: /*
556: * sqcmp - compare the location fields of two string qualifiers for qsort.
557: */
558:
559: sqcmp(q1,q2)
560: struct descrip **q1, **q2;
561: {
562: return (STRLOC(**q1) - STRLOC(**q2));
563: }
564:
565: /*
566: * mvc - move n bytes from src to dst.
567: */
568:
569: mvc(n, s, d)
570: unsigned n;
571: register char *s, *d;
572: {
573: register int words;
574: register int *srcw, *dstw;
575: int bytes;
576:
577: words = n / sizeof(int);
578: bytes = n % sizeof(int);
579:
580: srcw = (int *)s;
581: dstw = (int *)d;
582:
583: if (d < s) {
584: /*
585: * The move is from higher memory to lower memory. (It so happens
586: * that leftover bytes are not moved.)
587: */
588: while (--words >= 0)
589: *(dstw)++ = *(srcw)++;
590: while (--bytes >= 0)
591: *d++ = *s++;
592: }
593: else if (d > s) {
594: /*
595: * The move is from lower memory to higher memory.
596: */
597: s += n;
598: d += n;
599: while (--bytes >= 0)
600: *--d = *--s;
601: srcw = (int *)s;
602: dstw = (int *)d;
603: while (--words >= 0)
604: *--dstw = *--srcw;
605: }
606: }
607:
608: #endif MAIN
609: #ifdef PDP11
610: /*
611: * hneed(bytes) - insure at least 'bytes' space left in heap.
612: */
613:
614: hneed(bytes)
615: unsigned bytes;
616: {
617: heapneed = bytes;
618: if (bytes > maxheap - hpfree)
619: gcollect(0);
620: }
621:
622: /*
623: * sneed(chars) - insure at least 'chars' bytes left in string space.
624: */
625:
626: sneed(chars)
627: unsigned chars;
628: {
629: strneed = chars;
630: if (chars > estrings - sfree)
631: gcollect(0);
632: }
633:
634: /*
635: * esneed() - insure stack space free list is not empty.
636: */
637:
638: esneed()
639: {
640: if (esfree == NULL)
641: gcollect(1);
642: }
643:
644: /*
645: * escollect() - collect the expression stack space after marking.
646: */
647:
648: escollect()
649: {
650: register int *ep;
651: register struct b_estack *sp;
652: register struct descrip *nxtptr, *tptr;
653:
654: BLKLOC(k_main)->estack.type = T_ESTACK; /* must reset */
655:
656: esfree = NULL;
657: for (ep = stacks; ep < estacks; ep += stksize) {
658: sp = ep + (stksize - sizeof(struct b_estack)/2);
659: if (blktype(sp) == T_ESTACK) { /* add to free list */
660: *ep = esfree;
661: esfree = ep;
662: }
663: else /* adjust type field */
664: blktype(sp) = T_ESTACK;
665: }
666: }
667:
668: /*
669: * collect - call the heap garbage collector.
670: */
671:
672: collect(esneed)
673: int esneed;
674: {
675: register int extra;
676: register char *newend;
677: register struct descrip *dp;
678: char *sptr;
679: extern char *brk();
680:
681: sqfree = sqlist; /* initialize string qualifier list */
682:
683: mark(&k_main); /* mark main stack */
684: mark(¤t); /* mark current stack */
685: mark(&k_subject); /* mark tended descriptors */
686: mark(&maps2);
687: mark(&maps3);
688: for (dp = tended; dp < etended; dp++)
689: mark(dp);
690: for (dp = globals; dp < eglobals; dp++)
691: mark(dp);
692: for (dp = statics; dp < estatics; dp++)
693: mark(dp);
694:
695: escollect(); /* collect available expression stacks */
696: if (esneed && esfree == NULL) {
697: esfree = estacks; /* need to make room for another stack */
698: *estacks = 0;
699: estacks += stksize;
700: extra = stksize*sizeof(int); /* string and heap ptrs are chars */
701: newend = sqlist + extra;
702: if (newend < (char *)sqlist || newend > (char *)0177700 ||
703: (newend > (char *)esqlist && brk(newend) == -1))
704: runerr(305, NULL);
705: }
706: else
707: extra = 0;
708:
709: scollect(extra); /* collect string space */
710: sptr = strings + extra; /* remember new location of string space */
711: estrings += extra;
712: (char *)sqlist += extra;
713: if (sqlist > esqlist)
714: esqlist = sqlist;
715:
716: extra = (MAX(2*strneed, (estrings-estacks)/4) -
717: (estrings - extra - sfree) + 63) & ~077;
718: while (extra > 0) { /* need breathing room? */
719: newend = (char *)sqlist + extra;
720: if (newend >= (char *)sqlist && newend <= (char *)0177700 &&
721: (newend <= (char *)esqlist || brk(newend) != -1)) {
722: estrings += extra;
723: sqlist = newend;
724: break;
725: }
726: extra -= 64;
727: }
728: adjust(hpbase,estrings); /* adjust pointers into heap */
729: compact(hpbase); /* compact heap */
730: extra = (MAX(2*heapneed, (maxheap-hpbase)/4) +
731: hpfree - maxheap + 63) & ~077;
732: while (extra > 0) { /* need breathing room? */
733: newend = (char *)sqlist + extra;
734: if (newend >= (char *)sqlist && newend <= (char *)0177700 &&
735: (newend <= (char *)esqlist || brk(newend) != -1)) {
736: sqlist = newend;
737: break;
738: }
739: extra -= 64;
740: }
741: if (sqlist > esqlist)
742: esqlist = sqlist;
743: if (estrings != hpbase) { /* move heap */
744: mvc((unsigned)(hpfree - hpbase), hpbase, estrings);
745: hpfree += estrings - hpbase;
746: hpbase = estrings;
747: }
748: if (sptr != strings) { /* move string space */
749: mvc((unsigned)(sfree - strings), strings, sptr);
750: sfree += sptr - strings;
751: strings = sptr;
752: }
753: maxheap = (char *)sqlist; /* expand heap */
754:
755: return;
756: }
757:
758: /*
759: * mark - mark each accessible block in the heap and build back-list of
760: * descriptors pointing to that block. (Phase I of garbage collection)
761: */
762:
763: mark(cdesc)
764: struct descrip *cdesc; /* current descriptor */
765: {
766: register struct descrip *ndesc;
767: register char *endblock, *block;
768: static char *type;
769: static int fdesc;
770:
771: if (QUAL(*cdesc)) /* if descriptor is a string qualifier, */
772: marksq(cdesc); /* mark it for scollect */
773: else if (isptr(cdesc)) { /* ok, descriptor is a pointer */
774: block = BLKLOC(*cdesc); /* get pointer to top of block */
775: if (VAR(*cdesc) && !TVAR(*cdesc)) /* if variable, need offset */
776: block = (int *)block - OFFSET(*cdesc);
777:
778: if (block >= hpbase && block < hpfree) { /* insure it points to heap */
779: type = blktype(block); /* save type and end of block */
780: if (type <= MAXTYPE)
781: endblock = block + getsize(block);
782: BLKLOC(*cdesc) = type; /* add descriptor to back chain */
783: blktype(block) = cdesc;
784: /* sweep descriptors in block */
785: if ((type <= MAXTYPE) && ((fdesc = firstd[(int)type]) > 0))
786: for (ndesc = block + fdesc; ndesc < endblock; ndesc++)
787: mark(ndesc);
788: }
789: if (!VAR(*cdesc) && TYPE(*cdesc) == T_ESTACK &&
790: (char *)blktype(block) <= MAXTYPE) {
791: blktype(block) = cdesc; /* note block as visited */
792: sweep(((struct b_estack *)block)->boundary);
793: mark(&((struct b_estack *)block)->activator);
794: mark(&((struct b_estack *)block)->freshblk);
795: }
796: }
797: }
798:
799: /*
800: * adjust - adjust pointers into heap, beginning with heapblock 'oblk'.
801: * (Phase II of garbage collection)
802: */
803:
804: adjust(oblk,nblk)
805: char *oblk, *nblk;
806: {
807: register struct descrip *nxtptr, *tptr;
808:
809: while (oblk < hpfree) { /* linear sweep through heap */
810: if ((nxtptr = blktype(oblk)) > MAXTYPE) {
811: while ((unsigned)nxtptr > MAXTYPE) {
812: tptr = nxtptr;
813: nxtptr = BLKLOC(*nxtptr);
814: if (VAR(*tptr) && !TVAR(*tptr))
815: BLKLOC(*tptr) = (int *)nblk + OFFSET(*tptr);
816: else
817: BLKLOC(*tptr) = nblk;
818: }
819: blktype(oblk) = (unsigned)nxtptr | MARK;
820: nblk += getsize(oblk);
821: }
822: oblk += getsize(oblk);
823: }
824: }
825:
826: /*
827: * compact - compact good blocks in heap, beginning with block 'oblk'.
828: * (Phase III of garbage collection)
829: */
830:
831: compact(oblk)
832: char *oblk;
833: {
834: register char *nblk;
835: register int size;
836:
837: nblk = oblk; /* linear sweep through heap */
838: while (oblk < hpfree) {
839: size = getsize(oblk);
840: if (blktype(oblk) & MARK) { /* move good block */
841: blktype(oblk) &= ~MARK; /* turn off mark */
842: if (oblk != nblk)
843: mvc((unsigned)size,oblk,nblk);
844: nblk += size;
845: }
846: oblk += size;
847: }
848: hpfree = nblk; /* reset free space pointer */
849: }
850:
851: /*
852: * marksq - mark a string qualifier. If it points into the
853: * string space, put a pointer to it in the string qualifier
854: * list.
855: */
856:
857: marksq(d)
858: struct descrip *d;
859: {
860: extern char *brk();
861:
862: if (STRLOC(*d) >= strings && STRLOC(*d) < estrings) {
863: if (sqfree >= esqlist) {
864: esqlist += SQLINC;
865: if ((int)brk(esqlist) == -1)
866: runerr(303, NULL);
867: }
868: *sqfree++ = d;
869: }
870: }
871:
872: /*
873: * scollect - collect the string space.
874: * A list of string qualifiers points to all valid strings.
875: */
876:
877: scollect(extra)
878: int extra;
879: {
880: register char *s, *d;
881: register struct descrip **p;
882: char *e;
883: extern int sqcmp();
884:
885: if (sqfree <= sqlist) {
886: sfree = strings;
887: return;
888: }
889: qsort(sqlist, sqfree-sqlist, sizeof(struct descrip *), sqcmp);
890: d = strings;
891: s = e = STRLOC(**sqlist);
892: for (p = sqlist; p < sqfree; p++) {
893: if (STRLOC(**p) > e) { /* outside last clump */
894: while (s < e) /* move the clump */
895: *d++ = *s++;
896: s = e = STRLOC(**p); /* start a new clump */
897: }
898: if (STRLOC(**p)+STRLEN(**p) > e) /* extend the clump */
899: e = STRLOC(**p) + STRLEN(**p);
900: STRLOC(**p) += d - s + extra; /* relocate the string qualifier */
901: }
902: while (s < e) /* move the last clump */
903: *d++ = *s++;
904: sfree = d;
905: }
906:
907: /*
908: * sqcmp - compare the location fields of two string qualifiers for qsort.
909: */
910:
911: sqcmp(q1,q2)
912: struct descrip **q1, **q2;
913: {
914: return (STRLOC(**q1) - STRLOC(**q2));
915: }
916:
917: /*
918: * mvc - move n bytes from src to dst.
919: * src and dst must be at word boundaries.
920: */
921:
922: mvc(n, s, d)
923: unsigned n;
924: register char *s, *d;
925: {
926: register int words;
927: int bytes;
928:
929: words = n / sizeof(int);
930: bytes = n % sizeof(int);
931:
932: if (d < s) { /* move back */
933: while (--words >= 0)
934: *((int *)d)++ = *((int *)s)++;
935: while (--bytes >= 0)
936: *d++ = *s++;
937: }
938: else if (d > s) { /* move forward */
939: s += n;
940: d += n;
941: while (--bytes >= 0)
942: *--d = *--s;
943: while (--words >= 0)
944: *--(int *)d = *--(int *)s;
945: }
946: }
947: #endif PDP11
948:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.