|
|
1.1 root 1: # include "global.h"
2:
3: # define NUMWORDS TTSIZE * 128 /* max number of words in P0 space */
4: # define BITQUADS TTSIZE * 2 /* length of bit map in quad words */
5:
6: # define ftstbit asm(" ashl $-2,r11,r3");\
7: asm(" bbcs r3,_bitmapq,$1");\
8: asm(" .byte 4");
9: /* define ftstbit if( readbit(p) ) return; oksetbit; */
10: # define readbit(p) ((int)bitmap[r=(int)p>>5] & (s=bitmsk[((int)p>>2)&7]))
11: # define lookbit(p) (bitmap[(int)p>>5] & bitmsk[((int)p>>2) & 7])
12: # define setbit(p) {bitmap[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
13: # define oksetbit {bitmap[r] |= s;}
14:
15: # define readchk(p) ((int)bitfre[(int)p>>5] & bitmsk[((int)p>>2)&7])
16: # define setchk(p) {bitfre[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
17:
18: struct heads {
19: struct heads *link;
20: char *pntr;
21: } header[TTSIZE];
22:
23: FILE * chkport; /* garbage collection dump file */
24: lispval datalim; /* end of data space */
25: double bitmapq[BITQUADS]; /* the bit map--one bit per long */
26: double zeroq; /* a quad word of zeros */
27: char *bitmap = (char *) bitmapq; /* byte version of bit map array */
28: char bitmsk[8]={1,2,4,8,16,32,64,128}; /* used by bit-marking macros */
29: int *bind_lists = (int *) CNIL; /* lisp data for compiled code */
30:
31: char *xsbrk();
32:
33:
34: int atmlen;
35:
36: struct types {
37: char *next_free;
38: int space_left,
39: space,
40: type,
41: type_len; /* note type_len is in units of int */
42: lispval *items,
43: *pages,
44: *type_name;
45: struct heads
46: *first;
47: } atom_str = {(char *)CNIL,0,ATOMSPP,ATOM,5,&atom_items,&atom_pages,&atom_name,(struct heads *)CNIL},
48: strng_str = {(char *)CNIL,0,STRSPP,STRNG,1,&str_items,&str_pages,&str_name,(struct heads *)CNIL},
49: int_str = {(char *)CNIL,0,INTSPP,INT,1,&int_items,&int_pages,&int_name,(struct heads *)CNIL},
50: dtpr_str = {(char *)CNIL,0,DTPRSPP,DTPR,2,&dtpr_items,&dtpr_pages,&dtpr_name,(struct heads *)CNIL},
51: doub_str = {(char *)CNIL,0,DOUBSPP,DOUB,2,&doub_items,&doub_pages,&doub_name,(struct heads *)CNIL},
52: array_str = {(char *)CNIL,0,ARRAYSPP,ARRAY,5,&array_items,&array_pages,&array_name,(struct heads *)CNIL},
53: sdot_str = {(char *)CNIL,0,SDOTSPP,SDOT,2,&sdot_items,&sdot_pages,&sdot_name,(struct heads *)CNIL},
54: val_str = {(char *)CNIL,0,VALSPP,VALUE,1,&val_items,&val_pages,&val_name,(struct heads *)CNIL},
55: funct_str = {(char *)CNIL,0,BCDSPP,BCD,2,&funct_items,&funct_pages,&funct_name,(struct heads *)CNIL};
56:
57: extern int initflag; /* starts off TRUE: initially gc not allowed */
58:
59: int gcflag = FALSE; /* TRUE during garbage collection */
60:
61: int current = 0; /* number of pages currently allocated */
62:
63: #define NUMSPACES 9
64:
65: static struct types *(spaces[NUMSPACES]) =
66: {&atom_str, &strng_str, &int_str,
67: &dtpr_str, &doub_str, &array_str,
68: &sdot_str, &val_str, &funct_str};
69:
70:
71: /** get_more_space(type_struct) *****************************************/
72: /* */
73: /* Allocates and structures a new page, returning 0. */
74: /* If no space is available, returns 1. */
75:
76: get_more_space(type_struct)
77: struct types *type_struct;
78: {
79: int cntr;
80: char *start;
81: int *loop, *temp;
82: lispval p, plim;
83: struct heads *next;
84:
85: if(initflag == FALSE)
86: /* mustn't look at plist of plima too soon */
87: {
88: while( plim=copval(plima,(lispval)CNIL), TYPE(plim)!=INT )
89: copval(plima,error("BAD PAGE LIMIT",TRUE));
90: if( plim->i <= current ) return(1); /* Can't allocate */
91: }
92:
93: if( current >= TTSIZE ) return(2);
94:
95: start = xsbrk( NBPG );
96:
97: /* bump the page counter for this space */
98:
99: ++((*(type_struct->pages))->i);
100:
101: SETTYPE(start, type_struct->type); /* set type of page */
102:
103: type_struct->space_left = type_struct->space;
104: next = &header[ current++ ];
105: if ((type_struct->type)==STRNG)
106: {
107: type_struct->next_free = start;
108: return(0); /* space was available */
109: }
110: next->pntr = start;
111: next->link = type_struct->first;
112: type_struct->first = next;
113: temp = loop = (int *) start;
114: for(cntr=1; cntr < type_struct->space; cntr++)
115: loop = (int *) (*loop = (int) (loop + type_struct->type_len));
116: *loop = (int) (type_struct->next_free);
117: type_struct->next_free = (char *) temp;
118:
119: /* if type atom, set pnames to CNIL */
120:
121: if( type_struct == &atom_str )
122: for(cntr=0, p=(lispval) temp; cntr<atom_str.space; ++cntr)
123: {
124: p->pname = (char *) CNIL;
125: p = (lispval) ((int *)p + atom_str.type_len);
126: }
127: return(0); /* space was available */
128: }
129:
130:
131: /** next_one(type_struct) ************************************************/
132: /* */
133: /* Allocates one new item of each kind of space, except STRNG. */
134: /* If there is no space, calls gc, the garbage collector. */
135: /* If there is still no space, allocates a new page using */
136: /* get_more_space(type_struct) */
137:
138: lispval
139: next_one(type_struct)
140: struct types *type_struct;
141: {
142:
143: register char *temp;
144: snpand(1);
145:
146: while(type_struct->next_free == (char *) CNIL)
147: {
148: int g;
149:
150: if((type_struct->type != ATOM) && /* can't collect atoms */
151: (type_struct->type != STRNG) && /* can't collect strings */
152: (gcthresh->i <= current) && /* threshhold for gc */
153: ISNIL(copval(gcdis,CNIL)) && /* gc not disabled */
154: (NOTNIL(copval(gcload,CNIL)) || (loading->clb != tatom)) &&
155: /* not to collect during load */
156: (initflag == FALSE) && /* dont gc during init */
157: (gcflag == FALSE)) /* don't recurse gc */
158:
159: {
160: /* fputs("Collecting",poport);
161: dmpport(poport);*/
162: gc(type_struct); /* collect */
163: }
164:
165: if( type_struct->next_free != (char *) CNIL ) break;
166:
167: if(! (g=get_more_space(type_struct))) break;
168:
169: if( g==1 )
170: {
171: plimit->i = current+NUMSPACES;
172: /* allow a few more pages */
173: copval(plima,plimit); /* restore to reserved reg */
174:
175: error("PAGE LIMIT EXCEEDED--EMERGENCY PAGES ALLOCATED",
176: TRUE);
177: }
178: else error("SORRY, ABSOLUTE PAGE LIMIT HAS BEEN REACHED",
179: TRUE);
180: }
181:
182: temp = type_struct->next_free;
183: type_struct->next_free = * (char **)(type_struct->next_free);
184: return((lispval) temp);
185: }
186:
187: lispval
188: newint()
189: {
190: ++(int_items->i);
191: return(next_one(&int_str));
192: }
193:
194: lispval
195: newdot()
196: {
197: lispval temp;
198:
199: ++(dtpr_items->i);
200: temp = next_one(&dtpr_str);
201: temp->car = temp->cdr = nil;
202: return(temp);
203: }
204:
205: lispval
206: newdoub()
207: {
208: ++(doub_items->i);
209: return(next_one(&doub_str));
210: }
211:
212: lispval
213: newsdot()
214: {
215: register lispval temp;
216: ++(dtpr_items->i);
217: temp = next_one(&sdot_str);
218: temp->car = temp->cdr = 0;
219: return(temp);
220: }
221:
222: struct atom *newatom() {
223: struct atom *save;
224:
225: ++(atom_items->i);
226: save = (struct atom *) next_one(&atom_str) ;
227: save->plist = save->fnbnd = nil;
228: save->hshlnk = (struct atom *)CNIL;
229: save->clb = CNIL;
230: save->pname = newstr();
231: return (save);
232: }
233:
234: char *newstr() {
235: char *save;
236: int atmlen2;
237:
238: ++(str_items->i);
239: atmlen = strlen(strbuf)+1;
240: if(atmlen > strng_str.space_left)
241: while(get_more_space(&strng_str))
242: error("YOU HAVE RUN OUT OF SPACE",TRUE);
243: strcpy((save = strng_str.next_free), strbuf);
244: atmlen2 = atmlen;
245: while(atmlen2 % 4) ++atmlen2; /* even up length of string */
246: strng_str.next_free += atmlen2;
247: strng_str.space_left -= atmlen2;
248: return(save);
249: }
250:
251: char *inewstr(s) char *s;
252: {
253: strbuf[STRBLEN-1] = '\0';
254: strcpyn(strbuf,s,STRBLEN-1);
255: return(newstr());
256: }
257:
258: lispval
259: newarray()
260: {
261: register lispval temp;
262: ++(array_items->i);
263: temp = next_one(&array_str);
264: temp->data = (char *)nil;
265: temp->accfun = nil;
266: temp->aux = nil;
267: temp->length = SMALL(0);
268: temp->delta = SMALL(0);
269: return(temp);
270: }
271:
272: lispval
273: badcall()
274: { error("BAD FUNCTION DESCRIPTOR USED IN CALL",FALSE); }
275:
276: lispval
277: newfunct()
278: {
279: register lispval temp;
280: ++(funct_items->i);
281: temp = next_one(&funct_str);
282: temp->entry = badcall;
283: temp->discipline = nil;
284: return(temp);
285: }
286:
287: lispval
288: newval()
289: {
290: register lispval temp;
291: ++(val_items->i);
292: temp = next_one(&val_str);
293: temp->l = nil;
294: return(temp);
295: }
296:
297: lispval
298: inewval(arg) lispval arg;
299: {
300: lispval temp;
301: ++(val_items->i);
302: temp = next_one(&val_str);
303: temp->l = arg;
304: return(temp);
305: }
306:
307: /** Ngc *****************************************************************/
308: /* */
309: /* LISP interface to gc. */
310:
311: lispval Ngc()
312: {
313: lispval temp;
314:
315: if( ISNIL(lbot->val) ) return(gc(CNIL));
316:
317: if( TYPE(lbot->val) != DTPR ) error("BAD CALL TO GC",FALSE);
318:
319: chkport = poport;
320:
321: if( NOTNIL(lbot->val->car) )
322: {
323: temp = eval(lbot->val->car);
324: if( TYPE(temp) == PORT ) chkport = (FILE *)*temp;
325: }
326:
327: gc1(TRUE);
328:
329: return(nil);
330: }
331:
332: /** gc(type_struct) *****************************************************/
333: /* */
334: /* garbage collector: Collects garbage by mark and sweep algorithm. */
335: /* After this is done, calls the Nlambda, gcafter. */
336: /* gc may also be called from LISP, as a lambda of no arguments. */
337:
338: lispval
339: gc(type_struct)
340: struct types *type_struct;
341: {
342: lispval save;
343: struct {
344: long mytime;
345: long allelse[3];
346: } begin, finish;
347: extern int GCtime;
348:
349: save = copval(gcport,CNIL);
350: if(GCtime)
351: times(&begin);
352:
353: while( (TYPE(save) != PORT) && NOTNIL(save))
354: save = error("NEED PORT FOR GC",TRUE);
355:
356: chkport = ISNIL(save) ? poport : (FILE *)*save;
357:
358: gc1(NOTNIL(copval(gccheck,CNIL)) || (chkport!=poport)); /* mark&sweep */
359:
360: /* Now we call gcafter--special case if gc called from LISP */
361:
362: if( type_struct == (struct types *) CNIL )
363: gccall1->cdr = nil; /* make the call "(gcafter)" */
364: else
365: {
366: gccall1->cdr = gccall2;
367: gccall2->car = *(type_struct->type_name);
368: }
369: gcflag = TRUE; /* flag to indicate in garbage collector */
370: save = eval(gccall1); /* call gcafter */
371: gcflag = FALSE; /* turn off flag */
372:
373: if(GCtime) {
374: times(&finish);
375: GCtime += (finish.mytime - begin.mytime);
376: }
377: return(save); /* return result of gcafter */
378: }
379:
380:
381:
382: /* gc1() **************************************************************/
383: /* */
384: /* Mark-and-sweep phase */
385:
386: gc1(chkflag) int chkflag;
387: {
388: int i, j, typep;
389: register int *start, *point;
390: struct types *s;
391: struct heads *loop;
392: struct argent *loop2;
393: int markdp();
394:
395:
396: /* decide whether to check LISP structure or not */
397:
398:
399:
400:
401: /* first set all bit maps to zero */
402:
403: for(i=0; i<((int)datalim >> 8); ++i) bitmapq[i] = zeroq;
404:
405:
406: /* then mark all atoms' plists, clbs, and function bindings */
407:
408: for(loop=atom_str.first; loop!=(struct heads *)CNIL; loop=loop->link)
409: for(start=(int *)(loop->pntr), i=1;
410: i <= atom_str.space;
411: start = start + atom_str.type_len, ++i)
412: {
413:
414: /* unused atoms are marked with pname == CNIL */
415: /* this is done by get_more_space, as well as */
416: /* by gc (in the future) */
417:
418: if(((lispval)start)->pname == (char *)CNIL) continue;
419: #define MARKSUB(p) if(nil!=((lispval)start)->p)markdp(((lispval)start)->p);
420: MARKSUB(clb);
421: MARKSUB(fnbnd);
422: MARKSUB(plist);
423: }
424:
425: /* next run up the name stack */
426:
427: for(loop2 = np - 1; loop2 >= orgnp; --loop2) markdp((loop2->val));
428: /* from TBL 29july79 */
429: /* next mark all compiler linked data */
430: point = bind_lists;
431: while((start = point) != (int *)CNIL) {
432: while( *start != -1 )
433: markdp(*start++);
434: point = (int *)*(point-1);
435: }
436: /* end from TBL */
437:
438: /* next mark all system-significant lisp data */
439:
440: for(i=0; i<SIGNIF; ++i) markdp((lispsys[i]));
441:
442: /* all accessible data has now been marked. */
443: /* all collectable spaces must be swept, */
444: /* and freelists constructed. */
445:
446: for(i=0; i<NUMSPACES; ++i)
447: {
448: /* STRINGS do not participate. */
449: /* ATOMS dont either (currently) */
450:
451: s = spaces[i];
452: typep = s->type;
453: if((typep==STRNG) || (typep==ATOM)) continue;
454:
455: s->space_left = 0; /* we will count free cells */
456: (*(s->items))->i = 0; /* and compute cells used */
457:
458: /* for each space, traverse list of pages. */
459:
460: s->next_free = (char *) CNIL; /* reinitialize free list */
461:
462: for(loop = s->first; loop != (struct heads *) CNIL; loop=loop->link)
463: {
464: /* add another page's worth to use count */
465:
466: (*(s->items))->i += s->space;
467:
468: /* for each page, make a list of unmarked data */
469:
470: for(j=0, point=(int *)(loop->pntr);
471: j<s->space; ++j, point += s->type_len)
472: if( ! lookbit(point) )
473: {
474: /* add to free list */
475: /* update pointer to free list*/
476: /* update count of free list */
477:
478: *point = (int)(s->next_free);
479: s->next_free = (char *) point;
480: ++(s->space_left);
481: }
482: }
483: (*(s->items))->i -= s->space_left; /* compute cells used */
484: }
485: }
486:
487: /** alloc() *************************************************************/
488: /* */
489: /* This routine tries to allocate one more page of the space named */
490: /* by the argument. If no more space is available returns 1, else 0. */
491:
492: lispval
493: alloc(tname,npages)
494: lispval tname; int npages;
495: {
496: int ii, jj;
497:
498: ii = typenum(tname);
499:
500: for( jj=0; jj<npages; ++jj)
501: if(get_more_space(spaces[ii])) break;
502: return(inewint(jj));
503: }
504:
505: lispval
506: csegment(tname,nitems)
507: lispval tname; int nitems;
508: {
509: int ii, jj;
510: char *charadd;
511:
512: ii = typenum(tname);
513:
514: nitems = nitems*4*spaces[ii]->type_len; /* find c-length of space */
515: while( nitems%512 ) ++nitems; /* round up to right length */
516: current += nitems/512;
517: charadd = sbrk(nitems);
518: if( (int) charadd == 0 )
519: error("NOT ENOUGH SPACE FOR ARRAY",FALSE);
520: (datalim = (lispval)(charadd+nitems));
521: if((((int)datalim) >> 9) > TTSIZE) {
522: datalim = (lispval) (TTSIZE << 9);
523: badmem(53);
524: }
525: for(jj=0; jj<nitems; jj=jj+512) {
526: SETTYPE(charadd+jj, spaces[ii]->type);
527: }
528: return((lispval)charadd);
529: }
530:
531: int csizeof(tname) lispval tname;
532: {
533: return( spaces[typenum(tname)]->type_len * 4 );
534: }
535:
536: int typenum(tname) lispval tname;
537: {
538: int ii;
539:
540: chek: for(ii=0; ii<NUMSPACES; ++ii)
541: if(tname == *(spaces[ii]->type_name)) break;
542: if(ii == NUMSPACES)
543: {
544: tname = error("BAD TYPE NAME",TRUE);
545: goto chek;
546: }
547:
548: return(ii);
549: }
550:
551: /** markit(p) ***********************************************************/
552: /* just calls markdp */
553:
554: markit(p) lispval *p; { markdp(*p); }
555:
556: /** markdp(p) ***********************************************************/
557: /* */
558: /* markdp is the routine which marks each data item. If it is a */
559: /* dotted pair, the car and cdr are marked also. */
560: /* An iterative method is used to mark list structure, to avoid */
561: /* excessive recursion. */
562:
563:
564: markdp(p) register lispval p;
565: {
566: /* register int r, s; (goes with non-asm readbit, oksetbit) */
567:
568: ptr_loop:
569: if((int)p <= 0) return; /* do not mark special data types or nil=0 */
570:
571: switch( TYPE(p) )
572: {
573: case INT:
574: case DOUB:
575: /* setbit(p);*/
576: ftstbit;
577: return;
578: case VALUE:
579: ftstbit;
580: p = p->l;
581: goto ptr_loop;
582: case DTPR:
583: ftstbit;
584: markdp(p->car);
585: p = p->cdr;
586: goto ptr_loop;
587:
588: case ARRAY:
589: ftstbit; /* mark array itself */
590:
591: markdp(p->accfun); /* mark access function */
592: markdp(p->aux); /* mark aux data */
593: markdp(p->length); /* mark length */
594: markdp(p->delta); /* mark delta */
595:
596: {
597: register int i, l; int d;
598: register char *dataptr = p->data;
599:
600: for(i=0, l=p->length->i, d=p->delta->i; i<l; ++i)
601: {
602: markdp(dataptr);
603: dataptr += d;
604: }
605: return;
606: }
607: case SDOT:
608: do {
609: ftstbit;
610: p = p->CDR;
611: } while (p!=0);
612: return;
613:
614: case BCD:
615: ftstbit;
616: markdp(p->discipline);
617: return;
618: }
619: return;
620: }
621:
622:
623:
624: char *
625: xsbrk()
626: {
627: static char *xx; /* pointer to next available blank page */
628: static int cycle = 0; /* number of blank pages available */
629: lispval u; /* used to compute limits of bit table */
630:
631: if( (cycle--) <= 0 )
632: {
633: cycle = 15;
634: xx = sbrk(16*NBPG); /* get pages 16 at a time */
635: if( (int)xx== -1 )
636: lispend("For sbrk from lisp: no space... Goodbye!");
637: goto done;
638: }
639: xx += NBPG;
640: done: if( (u = (lispval)(xx+NBPG)) > datalim ) datalim = u;
641: return(xx);
642: }
643:
644: char *ysbrk(pages,type) int pages, type;
645: {
646: char *xx; /* will point to block of storage */
647: int i;
648:
649: xx = sbrk(pages*NBPG);
650: if((int)xx == -1)
651: error("OUT OF SPACE FOR ARRAY REQUEST",FALSE);
652:
653: datalim = (lispval)(xx+pages*NBPG); /* compute bit table limit */
654:
655: /* set type for pages */
656:
657: for(i = 0; i < pages; ++i) {
658: SETTYPE((xx + i*NBPG),type);
659: }
660:
661: return(xx); /* return pointer to block of storage */
662: }
663:
664: /* getatom **************************************************************/
665: /* returns either an existing atom with the name specified in strbuf, or*/
666: /* if the atom does not already exist, regurgitates a new one and */
667: /* returns it. */
668: lispval
669: getatom()
670: { register lispval aptr;
671: register char *name, *endname;
672: lispval b;
673: char c;
674: register int hash;
675: snpand(4);
676:
677: name = strbuf;
678: if (*name == (char)0377) return (eofa);
679: hash = 0;
680: for(name=strbuf; *name;) {
681: hash ^= *name++;
682: }
683: hash &= 0177; /* make sure no high-order bits have crept in */
684: atmlen = name - strbuf + 1;
685: aptr = (lispval) hasht[hash];
686: while (aptr != CNIL)
687: if (strcmp(strbuf,aptr->pname)==0)
688: return (aptr);
689: else
690: aptr = (lispval) aptr->hshlnk;
691: aptr = (lispval) newatom();
692: aptr->hshlnk = hasht[hash];
693: hasht[hash] = (struct atom *) aptr;
694: endname = name - 1;
695: name = strbuf;
696: if ((atmlen != 4) && (*name == 'c') && (*endname == 'r'))
697: {
698: b = newdot();
699: protect(b);
700: b->car = lambda;
701: b->cdr = newdot();
702: b = b->cdr;
703: b->car = newdot();
704: (b->car)->car = xatom;
705: while(TRUE)
706: {
707: b->cdr = newdot();
708: b= b->cdr;
709: if(++name == endname)
710: {
711: b->car= (lispval) xatom;
712: aptr->fnbnd = unprot();
713: break;
714: }
715: b->car= newdot();
716: b= b->car;
717: if((c = *name) == 'a') b->car = cara;
718: else if (c == 'd') b->car = cdra;
719: else{ unprot();
720: break;
721: }
722: }
723: }
724:
725: return(aptr);
726: }
727:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.