|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: alloc.c,v 1.12 85/03/24 10:59:57 sklower Exp $";
4: #endif
5:
6: /* -[Thu Feb 2 16:15:30 1984 by jkf]-
7: * alloc.c $Locker: $
8: * storage allocator and garbage collector
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13: # include "global.h"
14: # include "structs.h"
15:
16: #include <sys/types.h>
17: #include <sys/times.h>
18: #ifdef METER
19: #include <sys/vtimes.h>
20: #endif
21:
22: # define NUMWORDS TTSIZE * 128 /* max number of words in P0 space */
23: # define BITQUADS TTSIZE * 2 /* length of bit map in quad words */
24: # define BITLONGS TTSIZE * 4 /* length of bit map in long words */
25:
26: # ifdef vax
27: # define ftstbit asm(" ashl $-2,r11,r3");\
28: asm(" bbcs r3,_bitmapi,1f");\
29: asm(" ret"); \
30: asm("1:");
31:
32: /* setbit is a fast way of setting a bit, it is like ftstbit except it
33: * always continues on to the next instruction
34: */
35: # define setbit asm(" ashl $-2,r11,r0"); \
36: asm(" bbcs r0,_bitmapi,$0");
37: # endif
38:
39: # if m_68k
40: # define ftstbit {if(Itstbt()) return;}
41: # define setbit Itstbt()
42: # endif
43:
44: /* define ftstbit if( readbit(p) ) return; oksetbit; */
45: # define readbit(p) ((int)bbitmap[r=(int)p>>5] & (s=bitmsk[((int)p>>2)&7]))
46: # define lookbit(p) (bbitmap[(int)p>>5] & bitmsk[((int)p>>2) & 7])
47: /* # define setbit(p) {bbitmap[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];} */
48: # define oksetbit {bbitmap[r] |= s;}
49:
50: # define readchk(p) ((int)bitfre[(int)p>>5] & bitmsk[((int)p>>2)&7])
51: # define setchk(p) {bitfre[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
52: # define roundup(x,l) (((x - 1) | (l - 1)) + 1)
53:
54: # define MARKVAL(v) if(((int)v) >= (int)beginsweep) markdp(v);
55: # define ATOLX(p) ((((int)p)-OFFSET)>>7)
56:
57: /* the Vax hardware only allows 2^16-1 bytes to be accessed with one
58: * movc5 instruction. We use the movc5 instruction to clear the
59: * bitmaps.
60: */
61: # define MAXCLEAR ((1<<16)-1)
62:
63: /* METER denotes something added to help meter storage allocation. */
64:
65: extern int *beginsweep; /* first sweepable data */
66: extern char purepage[];
67: extern int fakettsize;
68: extern int gcstrings;
69: int debugin = FALSE; /* temp debug flag */
70:
71: extern lispval datalim; /* end of data space */
72: int bitmapi[BITLONGS]; /* the bit map--one bit per long */
73: double zeroq; /* a quad word of zeros */
74: char *bbitmap = (char *) bitmapi; /* byte version of bit map array */
75: double *qbitmap = (double *) bitmapi; /* integer version of bit map array */
76: #ifdef METER
77: extern int gcstat;
78: extern struct vtimes
79: premark,presweep,alldone; /* actually struct tbuffer's */
80:
81: extern int mrkdpcnt;
82: extern int conssame, consdiff,consnil; /* count of cells whose cdr point
83: * to the same page and different
84: * pages respectively
85: */
86: #endif
87: char bitmsk[8]={1,2,4,8,16,32,64,128}; /* used by bit-marking macros */
88: extern int *bind_lists ; /* lisp data for compiled code */
89:
90: char *xsbrk();
91: char *gethspace();
92:
93:
94: extern struct types atom_str, strng_str, int_str, dtpr_str, doub_str,
95: array_str, sdot_str, val_str, funct_str, hunk_str[], vect_str,
96: vecti_str, other_str;
97:
98: extern struct str_x str_current[];
99:
100: lispval hunk_items[7], hunk_pages[7], hunk_name[7];
101:
102: extern int initflag; /* starts off TRUE: initially gc not allowed */
103:
104:
105: /* this is a table of pointers to all struct types objects
106: * the index is the type number.
107: */
108: static struct types *spaces[NUMSPACES] =
109: {&strng_str, &atom_str, &int_str,
110: &dtpr_str, &doub_str, &funct_str,
111: (struct types *) 0, /* port objects not allocated in this way */
112: &array_str,
113: &other_str, /* other objects not allocated in this way */
114: &sdot_str,&val_str,
115: &hunk_str[0], &hunk_str[1], &hunk_str[2],
116: &hunk_str[3], &hunk_str[4], &hunk_str[5],
117: &hunk_str[6],
118: &vect_str, &vecti_str};
119:
120:
121: /* this is a table of pointers to collectable struct types objects
122: * the index is the type number.
123: */
124: struct types *gcableptr[] = {
125: #ifndef GCSTRINGS
126: (struct types *) 0, /* strings not collectable */
127: #else
128: &strng_str,
129: #endif
130: &atom_str,
131: &int_str, &dtpr_str, &doub_str,
132: (struct types *) 0, /* binary objects not collectable */
133: (struct types *) 0, /* port objects not collectable */
134: &array_str,
135: (struct types *) 0, /* gap in the type number sequence */
136: &sdot_str,&val_str,
137: &hunk_str[0], &hunk_str[1], &hunk_str[2],
138: &hunk_str[3], &hunk_str[4], &hunk_str[5],
139: &hunk_str[6],
140: &vect_str, &vecti_str};
141:
142:
143: /*
144: * get_more_space(type_struct,purep)
145: *
146: * Allocates and structures a new page, returning 0.
147: * If no space is available, returns positive number.
148: * If purep is TRUE, then pure space is allocated.
149: */
150: get_more_space(type_struct,purep)
151: struct types *type_struct;
152: {
153: int cntr;
154: char *start;
155: int *loop, *temp;
156: lispval p;
157: extern char holend[];
158:
159: if( (int) datalim >= TTSIZE*LBPG+OFFSET ) return(2);
160:
161: /*
162: * If the hole is defined, then we allocate binary objects
163: * and strings in the hole. However we don't put strings in
164: * the hole if strings are gc'ed.
165: */
166: #ifdef HOLE
167: if( purep
168: #ifndef GCSTRINGS
169: || type_struct==&strng_str
170: #endif
171: || type_struct==&funct_str)
172: start = gethspace(LBPG,type_struct->type);
173: else
174: #endif
175: start = xsbrk(1); /* get new page */
176:
177:
178: SETTYPE(start, type_struct->type,20); /* set type of page */
179:
180: purepage[ATOX(start)] = (char)purep; /* remember if page was pure*/
181:
182: /* bump the page counter for this space if not pure */
183:
184: if(!purep) ++((*(type_struct->pages))->i);
185:
186: type_struct->space_left = type_struct->space;
187: temp = loop = (int *) start;
188: for(cntr=1; cntr < type_struct->space; cntr++)
189: loop = (int *) (*loop = (int) (loop + type_struct->type_len));
190:
191: /* attach new cells to either the pure space free list or the
192: * standard free list
193: */
194: if(purep) {
195: *loop = (int) (type_struct->next_pure_free);
196: type_struct->next_pure_free = (char *) temp;
197: }
198: else {
199: *loop = (int) (type_struct->next_free);
200: type_struct->next_free = (char *) temp;
201: }
202:
203: /* if type atom, set pnames to CNIL */
204:
205: if( type_struct == &atom_str )
206: for(cntr=0, p=(lispval) temp; cntr<atom_str.space; ++cntr)
207: {
208: p->a.pname = (char *) CNIL;
209: p = (lispval) ((int *)p + atom_str.type_len);
210: }
211: return(0); /* space was available */
212: }
213:
214:
215: /*
216: * next_one(type_struct)
217: *
218: * Allocates one new item of each kind of space, except STRNG.
219: * If there is no space, calls gc, the garbage collector.
220: * If there is still no space, allocates a new page using
221: * get_more_space
222: */
223:
224: lispval
225: next_one(type_struct)
226: struct types *type_struct;
227: {
228:
229: register char *temp;
230:
231: while(type_struct->next_free == (char *) CNIL)
232: {
233: int g;
234:
235: if(
236: (initflag == FALSE) && /* dont gc during init */
237: #ifndef GCSTRINGS
238: (type_struct->type != STRNG) && /* can't collect strings */
239: #else
240: gcstrings && /* user (sstatus gcstrings) */
241: #endif
242: (type_struct->type != BCD) && /* nor function headers */
243: gcdis->a.clb == nil ) /* gc not disabled */
244: /* not to collect during load */
245:
246: {
247: gc(type_struct); /* collect */
248: }
249:
250: if( type_struct->next_free != (char *) CNIL ) break;
251:
252: if(! (g=get_more_space(type_struct,FALSE))) break;
253:
254: space_warn(g);
255: }
256: temp = type_struct->next_free;
257: type_struct->next_free = * (char **)(type_struct->next_free);
258: (*(type_struct->items))->i ++;
259: return((lispval) temp);
260: }
261: /*
262: * Warn about exhaustion of space,
263: * shared with next_pure_free().
264: */
265: space_warn(g)
266: {
267: if( g==1 ) {
268: plimit->i += NUMSPACES; /* allow a few more pages */
269: copval(plima,plimit); /* restore to reserved reg */
270:
271: error("PAGE LIMIT EXCEEDED--EMERGENCY PAGES ALLOCATED", TRUE);
272: } else error("SORRY, ABSOLUTE PAGE LIMIT HAS BEEN REACHED", TRUE);
273: }
274:
275:
276: /* allocate an element of a pure structure. Pure structures will
277: * be ignored by the garbage collector.
278: */
279: lispval
280: next_pure_one(type_struct)
281: struct types *type_struct;
282: {
283:
284: register char *temp;
285:
286: while(type_struct->next_pure_free == (char *) CNIL)
287: {
288: int g;
289: if(! (g=get_more_space(type_struct,TRUE))) break;
290: space_warn(g);
291: }
292:
293: temp = type_struct->next_pure_free;
294: type_struct->next_pure_free = * (char **)(type_struct->next_pure_free);
295: return((lispval) temp);
296: }
297:
298: lispval
299: newint()
300: {
301: return(next_one(&int_str));
302: }
303:
304: lispval
305: pnewint()
306: {
307: return(next_pure_one(&int_str));
308: }
309:
310: lispval
311: newdot()
312: {
313: lispval temp;
314:
315: temp = next_one(&dtpr_str);
316: temp->d.car = temp->d.cdr = nil;
317: return(temp);
318: }
319:
320: lispval
321: pnewdot()
322: {
323: lispval temp;
324:
325: temp = next_pure_one(&dtpr_str);
326: temp->d.car = temp->d.cdr = nil;
327: return(temp);
328: }
329:
330: lispval
331: newdoub()
332: {
333: return(next_one(&doub_str));
334: }
335:
336: lispval
337: pnewdb()
338: {
339: return(next_pure_one(&doub_str));
340: }
341:
342: lispval
343: newsdot()
344: {
345: register lispval temp;
346: temp = next_one(&sdot_str);
347: temp->d.car = temp->d.cdr = 0;
348: return(temp);
349: }
350:
351: lispval
352: pnewsdot()
353: {
354: register lispval temp;
355: temp = next_pure_one(&sdot_str);
356: temp->d.car = temp->d.cdr = 0;
357: return(temp);
358: }
359:
360: struct atom *
361: newatom(pure) {
362: struct atom *save; char *mypname;
363:
364: mypname = newstr(pure);
365: pnameprot = ((lispval) mypname);
366: save = (struct atom *) next_one(&atom_str) ;
367: save->plist = save->fnbnd = nil;
368: save->hshlnk = (struct atom *)CNIL;
369: save->clb = CNIL;
370: save->pname = mypname;
371: return (save);
372: }
373:
374: char *
375: newstr(purep) {
376: char *save, *strcpy();
377: int atmlen;
378: register struct str_x *p = str_current + purep;
379:
380: atmlen = strlen(strbuf)+1;
381: if(atmlen > p->space_left) {
382: if(atmlen >= STRBLEN) {
383: save = (char *)csegment(OTHER, atmlen, purep);
384: SETTYPE(save,STRNG,40);
385: purepage[ATOX(save)] = (char)purep;
386: strcpy(save,strbuf);
387: return(save);
388: }
389: p->next_free = (char *) (purep ?
390: next_pure_one(&strng_str) : next_one(&strng_str)) ;
391: p->space_left = LBPG;
392: }
393: strcpy((save = p->next_free), strbuf);
394: /*while(atmlen & 3) ++atmlen; /* even up length of string */
395: p->next_free += atmlen;
396: p->space_left -= atmlen;
397: return(save);
398: }
399:
400: static char * Iinewstr(s,purep) char *s;
401: {
402: int len = strlen(s);
403: while(len > (endstrb - strbuf - 1)) atomtoolong(strbuf);
404: strcpy(strbuf,s);
405: return(newstr(purep));
406: }
407:
408:
409: char *inewstr(s) char *s;
410: {
411: Iinewstr(s,0);
412: }
413:
414: char *pinewstr(s) char *s;
415: {
416: Iinewstr(s,1);
417: }
418:
419: lispval
420: newarray()
421: {
422: register lispval temp;
423:
424: temp = next_one(&array_str);
425: temp->ar.data = (char *)nil;
426: temp->ar.accfun = nil;
427: temp->ar.aux = nil;
428: temp->ar.length = SMALL(0);
429: temp->ar.delta = SMALL(0);
430: return(temp);
431: }
432:
433: lispval
434: newfunct()
435: {
436: register lispval temp;
437: lispval Badcall();
438: temp = next_one(&funct_str);
439: temp->bcd.start = Badcall;
440: temp->bcd.discipline = nil;
441: return(temp);
442: }
443:
444: lispval
445: newval()
446: {
447: register lispval temp;
448: temp = next_one(&val_str);
449: temp->l = nil;
450: return(temp);
451: }
452:
453: lispval
454: pnewval()
455: {
456: register lispval temp;
457: temp = next_pure_one(&val_str);
458: temp->l = nil;
459: return(temp);
460: }
461:
462: lispval
463: newhunk(hunknum)
464: int hunknum;
465: {
466: register lispval temp;
467:
468: temp = next_one(&hunk_str[hunknum]); /* Get a hunk */
469: return(temp);
470: }
471:
472: lispval
473: pnewhunk(hunknum)
474: int hunknum;
475: {
476: register lispval temp;
477:
478: temp = next_pure_one(&hunk_str[hunknum]); /* Get a hunk */
479: return(temp);
480: }
481:
482: lispval
483: inewval(arg) lispval arg;
484: {
485: lispval temp;
486: temp = next_one(&val_str);
487: temp->l = arg;
488: return(temp);
489: }
490:
491: /*
492: * Vector allocators.
493: * a vector looks like:
494: * longword: N = size in bytes
495: * longword: pointer to lisp object, this is the vector property field
496: * N consecutive bytes
497: *
498: */
499: lispval getvec();
500:
501: lispval
502: newvec(size)
503: {
504: return(getvec(size,&vect_str,FALSE));
505: }
506:
507: lispval
508: pnewvec(size)
509: {
510: return(getvec(size,&vect_str,TRUE));
511: }
512:
513: lispval
514: nveci(size)
515: {
516: return(getvec(size,&vecti_str,FALSE));
517: }
518:
519: lispval
520: pnveci(size)
521: {
522: return(getvec(size,&vecti_str,TRUE));
523: }
524:
525: /*
526: * getvec
527: * get a vector of size byte, from type structure typestr and
528: * get it from pure space if purep is TRUE.
529: * vectors are stored linked through their property field. Thus
530: * when the code here refers to v.vector[0], it is the prop field
531: * and vl.vectorl[-1] is the size field. In other code,
532: * v.vector[-1] is the prop field, and vl.vectorl[-2] is the size.
533: */
534: lispval
535: getvec(size,typestr,purep)
536: register struct types *typestr;
537: {
538: register lispval back, current;
539: int sizewant, bytes, thissize, pages, pindex, triedgc = FALSE;
540:
541: /* we have to round up to a multiple of 4 bytes to determine the
542: * size of vector we want. The rounding up assures that the
543: * property pointers are longword aligned
544: */
545: sizewant = VecTotSize(size);
546: if(debugin) fprintf(stderr,"want vect %db\n",size);
547: again:
548: if(purep)
549: back = (lispval) &(typestr->next_pure_free);
550: else
551: back = (lispval) &(typestr->next_free);
552: current = back->v.vector[0];
553: while(current != CNIL)
554: {
555: if(debugin)
556: fprintf(stderr,"next free size %db; ", current->vl.vectorl[-1]);
557: if ((thissize = VecTotSize(current->vl.vectorl[-1])) == sizewant)
558: {
559: if(debugin) fprintf(stderr,"exact match of size %d at 0x%x\n",
560: 4*thissize, ¤t->v.vector[1]);
561: back->v.vector[0]
562: = current->v.vector[0];/* change free pointer*/
563: current->v.vector[0] = nil; /* put nil in property */
564: /* to the user, vector begins one after property*/
565: return((lispval)¤t->v.vector[1]);
566: }
567: else if (thissize >= sizewant + 3)
568: {
569: /* the reason that there is a `+ 3' instead of `+ 2'
570: * is that we don't want to leave a zero sized vector which
571: * isn't guaranteed to be followed by another vector
572: */
573: if(debugin)
574: fprintf(stderr,"breaking a %d vector into a ",
575: current->vl.vectorl[-1]);
576:
577: current->v.vector[1+sizewant+1]
578: = current->v.vector[0]; /* free list pointer */
579: current->vl.vectorl[1+sizewant]
580: = VecTotToByte(thissize - sizewant - 2);/*size info */
581: back->v.vector[0] = (lispval) &(current->v.vector[1+sizewant+1]);
582: current->vl.vectorl[-1] = size;
583:
584: if(debugin)fprintf(stderr," %d one and a %d one\n",
585: current->vl.vectorl[-1],current->vl.vectorl[1+sizewant]);
586: current->v.vector[0] = nil; /* put nil in property */
587: /* vector begins one after the property */
588: if(debugin) fprintf(stderr," and returning vector at 0x%x\n",
589: ¤t->v.vector[1]);
590: return((lispval)(¤t->v.vector[1]));
591: }
592: back = current;
593: current = current->v.vector[0];
594: }
595: if(!triedgc
596: && !purep
597: && (gcdis->a.clb == nil)
598: && (initflag == FALSE))
599: {
600: gc(typestr);
601: triedgc = TRUE;
602: goto again;
603: }
604:
605: /* set bytes to size needed for this vector */
606: bytes = size + 2*sizeof(long);
607:
608: /* must make sure that if the vector we are allocating doesnt
609: completely fill a page, there is room for another vector to record
610: the size left over */
611: if((bytes & (LBPG - 1)) > (LBPG - 2*sizeof(long))) bytes += LBPG;
612: bytes = roundup(bytes,LBPG);
613:
614: current = csegment(typestr->type,bytes/sizeof(long),purep);
615: current->vl.vectorl[0] = bytes - 2*sizeof(long);
616:
617: if(purep) {
618: current->v.vector[1] = (lispval)(typestr->next_pure_free);
619: typestr->next_pure_free = (char *) &(current->v.vector[1]);
620: /* make them pure */
621: pages = bytes/LBPG;
622: for(pindex = ATOX(current); pages ; pages--)
623: {
624: purepage[pindex++] = TRUE;
625: }
626: } else {
627: current->v.vector[1] = (lispval)(typestr->next_free);
628: typestr->next_free = (char *) &(current->v.vector[1]);
629: if(debugin) fprintf(stderr,"grabbed %d vec pages\n",bytes/LBPG);
630: }
631: if(debugin)
632: fprintf(stderr,"creating a new vec, size %d\n",current->v.vector[0]);
633: goto again;
634: }
635:
636: /*
637: * Ipurep :: routine to check for pureness of a data item
638: *
639: */
640: lispval
641: Ipurep(element)
642: lispval element;
643: {
644: if(purepage[ATOX(element)]) return(tatom) ; else return(nil);
645: }
646:
647: /* routines to return space to the free list. These are used by the
648: * arithmetic routines which tend to create large intermediate results
649: * which are know to be garbage after the calculation is over.
650: *
651: * There are jsb callable versions of these routines in qfuncl.s
652: */
653:
654: /* pruneb - prune bignum. A bignum is an sdot followed by a list of
655: * dtprs. The dtpr list is linked by car instead of cdr so when we
656: * put it in the free list, we have to change the links.
657: */
658: pruneb(bignum)
659: lispval bignum;
660: {
661: register lispval temp = bignum;
662:
663: if(TYPE(temp) != SDOT)
664: errorh(Vermisc,"value to pruneb not a sdot",nil,FALSE,0);
665:
666: --(sdot_items->i);
667: temp->s.I = (int) sdot_str.next_free;
668: sdot_str.next_free = (char *) temp;
669:
670: /* bignums are not terminated by nil on the dual,
671: they are terminated by (lispval) 0 */
672:
673: while(temp = temp->s.CDR)
674: {
675: if(TYPE(temp) != DTPR)
676: errorh(Vermisc,"value to pruneb not a list",
677: nil,FALSE,0);
678: --(dtpr_items->i);
679: temp->s.I = (int) dtpr_str.next_free;
680: dtpr_str.next_free = (char *) temp;
681: }
682: }
683: lispval
684: Badcall()
685: { error("BAD FUNCTION DESCRIPTOR USED IN CALL",FALSE); }
686:
687:
688:
689: /*
690: * Ngc
691: * this is the lisp function gc
692: *
693: */
694:
695: lispval
696: Ngc()
697: {
698: return(gc((struct types *)CNIL));
699: }
700:
701: /*
702: * gc(type_struct)
703: *
704: * garbage collector: Collects garbage by mark and sweep algorithm.
705: * After this is done, calls the Nlambda, gcafter.
706: * gc may also be called from LISP, as an nlambda of no arguments.
707: * type_struct is the type of lisp data that ran out causing this
708: * garbage collection
709: */
710: int printall = 0;
711: lispval
712: gc(type_struct)
713: struct types *type_struct;
714: {
715: lispval save;
716: struct tms begin, finish;
717: extern int gctime;
718:
719: /* if this was called automatically when space ran out
720: * print out a message
721: */
722: if((Vgcprint->a.clb != nil)
723: && (type_struct != (struct types *) CNIL ))
724: {
725: FILE *port = okport(Vpoport->a.clb,poport);
726: fprintf(port,"gc:");
727: fflush(port);
728: }
729:
730: if(gctime) times(&begin);
731:
732: gc1(); /* mark&sweep */
733:
734: /* Now we call gcafter--special c ase if gc called from LISP */
735:
736: if( type_struct == (struct types *) CNIL )
737: gccall1->d.cdr = nil; /* make the call "(gcafter)" */
738: else
739: {
740: gccall1->d.cdr = gccall2;
741: gccall2->d.car = *(type_struct->type_name);
742: }
743: PUSHDOWN(gcdis,gcdis); /* flag to indicate in garbage collector */
744: save = eval(gccall1); /* call gcafter */
745: POP; /* turn off flag */
746:
747: if(gctime) {
748: times(&finish);
749: gctime += (finish.tms_utime - begin.tms_utime);
750: }
751: return(save); /* return result of gcafter */
752: }
753:
754:
755:
756: /* gc1() **************************************************************/
757: /* */
758: /* Mark-and-sweep phase */
759:
760: gc1()
761: {
762: int j, k;
763: register int *start,bvalue,type_len;
764: register struct types *s;
765: int *point,i,freecnt,itemstogo,bits,bindex,type,bytestoclear;
766: int usedcnt;
767: char *pindex;
768: struct argent *loop2;
769: struct nament *loop3;
770: struct atom *symb;
771: int markdp();
772: extern int hashtop;
773:
774: pagerand();
775: /* decide whether to check LISP structure or not */
776:
777:
778: #ifdef METER
779: vtimes(&premark,0);
780: mrkdpcnt = 0;
781: conssame = consdiff = consnil = 0;
782: #endif
783:
784: /* first set all bit maps to zero */
785:
786:
787: #ifdef SLOCLEAR
788: {
789: int enddat;
790: enddat = (int)(datalim-OFFSET) >> 8;
791: for(bvalue=0; bvalue < (int)enddat ; ++bvalue)
792: {
793: qbitmap[bvalue] = zeroq;
794: }
795: }
796: #endif
797:
798: /* try the movc5 to clear the bit maps */
799: /* the maximum number of bytes we can clear in one sweep is
800: * 2^16 (or 1<<16 in the C lingo)
801: */
802: bytestoclear = ((((int)datalim)-((int)beginsweep)) >> 9) * 16;
803: for(start = bitmapi + ATOLX(beginsweep);
804: bytestoclear > 0;)
805: {
806: if(bytestoclear > MAXCLEAR)
807: blzero((int)start,MAXCLEAR);
808: else
809: blzero((int)start,bytestoclear);
810: start = (int *) (MAXCLEAR + (int) start);
811: bytestoclear -= MAXCLEAR;
812: }
813:
814: /* mark all atoms in the oblist */
815: for( bvalue=0 ; bvalue <= hashtop-1 ; bvalue++ ) /* though oblist */
816: {
817: for( symb = hasht[bvalue] ; symb != (struct atom *) CNIL ;
818: symb = symb-> hshlnk) {
819: markdp((lispval)symb);
820: }
821: }
822:
823:
824: /* Mark all the atoms and ints associated with the hunk
825: data types */
826:
827: for(i=0; i<7; i++) {
828: markdp(hunk_items[i]);
829: markdp(hunk_name[i]);
830: markdp(hunk_pages[i]);
831: }
832: /* next run up the name stack */
833: for(loop2 = np - 1; loop2 >= orgnp; --loop2) MARKVAL(loop2->val);
834:
835: /* now the bindstack (vals only, atoms are marked elsewhere ) */
836: for(loop3 = bnp - 1; loop3 >= orgbnp; --loop3)MARKVAL(loop3->val);
837:
838:
839: /* next mark all compiler linked data */
840: /* if the Vpurcopylits switch is non nil (lisp variable $purcopylits)
841: * then when compiled code is read in, it tables will not be linked
842: * into this table and thus will not be marked here. That is ok
843: * though, since that data is assumed to be pure.
844: */
845: point = bind_lists;
846: while((start = point) != (int *)CNIL) {
847: while( *start != -1 )
848: {
849: markdp((lispval)*start);
850: start++;
851: }
852: point = (int *)*(point-1);
853: }
854:
855: /* next mark all system-significant lisp data */
856:
857:
858: for(i=0; i<SIGNIF; ++i) markdp((lispsys[i]));
859:
860: #ifdef METER
861: vtimes(&presweep,0);
862: #endif
863: /* all accessible data has now been marked. */
864: /* all collectable spaces must be swept, */
865: /* and freelists constructed. */
866:
867: /* first clear the structure elements for types
868: * we will sweep
869: */
870:
871: for(k=0 ; k <= VECTORI ; k++)
872: {
873: if( s=gcableptr[k]) {
874: if(k==STRNG && !gcstrings) { /* don't do anything*/ }
875: else
876: {
877: (*(s->items))->i = 0;
878: s->space_left = 0;
879: s->next_free = (char *) CNIL;
880: }
881: }
882: }
883: #if m_68k
884: fixbits(bitmapi+ATOLX(beginsweep),bitmapi+ATOLX(datalim));
885: #endif
886:
887:
888: /* sweep up in memory looking at gcable pages */
889:
890: for(start = beginsweep, bindex = ATOLX(start),
891: pindex = &purepage[ATOX(start)];
892: start < (int *)datalim;
893: start += 128, pindex++)
894: {
895: if(!(s=gcableptr[type = TYPE(start)]) || *pindex
896: #ifdef GCSTRINGS
897: || (type==STRNG && !gcstrings)
898: #endif
899: )
900: {
901: /* ignore this page but advance pointer */
902: bindex += 4; /* and 4 words of 32 bit bitmap words */
903: continue;
904: }
905:
906: freecnt = 0; /* number of free items found */
907: usedcnt = 0; /* number of used items found */
908:
909: point = start;
910: /* sweep dtprs as a special case, since
911: * 1) there will (usually) be more dtpr pages than any other type
912: * 2) most dtpr pages will be empty so we can really win by special
913: * caseing the sweeping of massive numbers of free cells
914: */
915: /* since sdot's have the same structure as dtprs, this code will
916: work for them too
917: */
918: if((type == DTPR) || (type == SDOT))
919: {
920: int *head,*lim;
921: head = (int *) s->next_free; /* first value on free list*/
922:
923: for(i=0; i < 4; i++) /* 4 bit map words per page */
924: {
925: bvalue = bitmapi[bindex++]; /* 32 bits = 16 dtprs */
926: if(bvalue == 0) /* if all are free */
927: {
928: *point = (int)head;
929: lim = point + 32; /* 16 dtprs = 32 ints */
930: for(point += 2; point < lim ; point += 2)
931: {
932: *point = (int)(point - 2);
933: }
934: head = point - 2;
935: freecnt += 16;
936: }
937: else for(j = 0; j < 16 ; j++)
938: {
939: if(!(bvalue & 1))
940: {
941: freecnt++;
942: *point = (int)head;
943: head = point;
944: }
945: #ifdef METER
946: /* check if the page address of this cell is the
947: * same as the address of its cdr
948: */
949: else if(FALSE && gcstat && (type == DTPR))
950: {
951: if(((int)point & ~511)
952: == ((int)(*point) & ~511)) conssame++;
953: else consdiff++;
954: usedcnt++;
955: }
956: #endif
957: else usedcnt++; /* keep track of used */
958:
959: point += 2;
960: bvalue = bvalue >> 2;
961: }
962: }
963: s->next_free = (char *) head;
964: }
965: else if((type == VECTOR) || (type == VECTORI))
966: {
967: int canjoin = FALSE;
968: int *tempp;
969:
970: /* check if first item on freelist ends exactly at
971: this page
972: */
973: if(((tempp = (int *)s->next_free) != (int *)CNIL)
974: && ((VecTotSize(((lispval)tempp)->vl.vectorl[-1])
975: + 1 + tempp)
976: == point))
977: canjoin = TRUE;
978:
979: /* arbitrary sized vector sweeper */
980: /*
981: * jump past first word since that is a size fixnum
982: * and second word since that is property word
983: */
984: if(debugin)
985: fprintf(stderr,"vector sweeping, start at 0x%x\n",
986: point);
987: bits = 30;
988: bvalue = bitmapi[bindex++] >> 2;
989: point += 2;
990: while (TRUE) {
991: type_len = point[VSizeOff];
992: if(debugin) {
993: fprintf(stderr,"point: 0x%x, type_len %d\n",
994: point, type_len);
995: fprintf(stderr,"bvalue: 0x%x, bits: %d, bindex: 0x%x\n",
996: bvalue, bits, bindex);
997: }
998: /* get size of vector */
999: if(!(bvalue & 1)) /* if free */
1000: {
1001: if(debugin) fprintf(stderr,"free\n");
1002: freecnt += type_len + 2*sizeof(long);
1003: if(canjoin)
1004: {
1005: /* join by adjusting size of first vector */
1006: ((lispval)(s->next_free))->vl.vectorl[-1]
1007: += type_len + 2*sizeof(long);
1008: if(debugin)
1009: fprintf(stderr,"joined size: %d\n",
1010: ((lispval)(s->next_free))->vl.vectorl[-1]);
1011: }
1012: else {
1013: /* vectors are linked at the property word */
1014: *(point - 1) = (int)(s->next_free);
1015: s->next_free = (char *) (point - 1);
1016: }
1017: canjoin = TRUE;
1018: }
1019: else {
1020: canjoin = FALSE;
1021: usedcnt += type_len + 2*sizeof(long);
1022: }
1023:
1024: point += VecTotSize(type_len);
1025: /* we stop sweeping only when we reach a page
1026: boundary since vectors can span pages
1027: */
1028: if(((int)point & 511) == 0)
1029: {
1030: /* reset the counters, we cannot predict how
1031: * many pages we have crossed over
1032: */
1033: bindex = ATOLX(point);
1034: /* these will be inced, so we must dec */
1035: pindex = &purepage[ATOX(point)] - 1;
1036: start = point - 128;
1037: if(debugin)
1038: fprintf(stderr,
1039: "out of vector sweep when point = 0x%x\n",
1040: point);
1041: break;
1042: }
1043: /* must advance to next point and next value in bitmap.
1044: * we add VecTotSize(type_len) + 2 to get us to the 0th
1045: * entry in the next vector (beyond the size fixnum)
1046: */
1047: point += 2; /* point to next 0th entry */
1048: if ( (bits -= (VecTotSize(type_len) + 2)) > 0)
1049: bvalue = bvalue >> (VecTotSize(type_len) + 2);
1050: else {
1051: bits = -bits; /* must advance to next word in map */
1052: bindex += bits / 32; /* this is tricky stuff... */
1053: bits = bits % 32;
1054: bvalue = bitmapi[bindex++] >> bits;
1055: bits = 32 - bits;
1056: }
1057: }
1058: }
1059: else {
1060: /* general sweeper, will work for all types */
1061: itemstogo = s->space; /* number of items per page */
1062: bits = 32; /* number of bits per word */
1063: type_len = s->type_len;
1064:
1065: /* printf(" s %d, itemstogo %d, len %d\n",s,itemstogo,type_len);*/
1066: bvalue = bitmapi[bindex++];
1067:
1068: while(TRUE)
1069: {
1070: if(!(bvalue & 1)) /* if data element is not marked */
1071: {
1072: freecnt++;
1073: *point = (int) (s->next_free) ;
1074: s->next_free = (char *) point;
1075: }
1076: else usedcnt++;
1077:
1078: if( --itemstogo <= 0 )
1079: { if(type_len >= 64)
1080: {
1081: bindex++;
1082: if(type_len >=128) bindex += 2;
1083: }
1084: break;
1085: }
1086:
1087: point += type_len;
1088: /* shift over mask by number of words in data type */
1089:
1090: if( (bits -= type_len) > 0)
1091: { bvalue = bvalue >> type_len;
1092: }
1093: else if( bits == 0 )
1094: { bvalue = bitmapi[bindex++];
1095: bits = 32;
1096: }
1097: else
1098: { bits = -bits;
1099: while( bits >= 32) { bindex++;
1100: bits -= 32;
1101: }
1102: bvalue = bitmapi[bindex++];
1103: bvalue = bvalue >> bits;
1104: bits = 32 - bits;;
1105: }
1106: }
1107: }
1108:
1109: s->space_left += freecnt;
1110: (*(s->items))->i += usedcnt;
1111: }
1112:
1113: #ifdef METER
1114: vtimes(&alldone,0);
1115: if(gcstat) gcdump();
1116: #endif
1117: pagenorm();
1118: }
1119:
1120: /*
1121: * alloc
1122: *
1123: * This routine tries to allocate one or more pages of the space named
1124: * by the first argument. Returns the number of pages actually allocated.
1125: *
1126: */
1127:
1128: lispval
1129: alloc(tname,npages)
1130: lispval tname; long npages;
1131: {
1132: long ii, jj;
1133: struct types *typeptr;
1134:
1135: ii = typenum(tname);
1136: typeptr = spaces[ii];
1137: if(npages <= 0) return(inewint(npages));
1138:
1139: if((ATOX(datalim)) + npages > TTSIZE)
1140: error("Space request would exceed maximum memory allocation",FALSE);
1141: if((ii == VECTOR) || (ii == VECTORI))
1142: {
1143: /* allocate in one big chunk */
1144: tname = csegment((int) ii,(int) npages*128,0);
1145: tname->vl.vectorl[0] = (npages*512 - 2*sizeof(long));
1146: tname->v.vector[1] = (lispval) typeptr->next_free;
1147: typeptr->next_free = (char *) &(tname->v.vector[1]);
1148: if(debugin) fprintf(stderr,"alloced %d vec pages\n",npages);
1149: return(inewint(npages));
1150: }
1151:
1152: for( jj=0; jj<npages; ++jj)
1153: if(get_more_space(spaces[ii],FALSE)) break;
1154: return(inewint(jj));
1155: }
1156:
1157: /*
1158: * csegment(typecode,nitems,useholeflag)
1159: * allocate nitems of type typecode. If useholeflag is true, then
1160: * allocate in the hole if there is room. This routine doesn't look
1161: * in the free lists, it always allocates space.
1162: */
1163: lispval
1164: csegment(typecode,nitems,useholeflag)
1165: {
1166: register int ii, jj;
1167: register char *charadd;
1168:
1169: ii = typecode;
1170:
1171: if(ii!=OTHER) nitems *= 4*spaces[ii]->type_len;
1172: nitems = roundup(nitems,512); /* round up to right length */
1173: #ifdef HOLE
1174: if(useholeflag)
1175: charadd = gethspace(nitems,ii);
1176: else
1177: #endif
1178: {
1179: charadd = sbrk(nitems);
1180: datalim = (lispval)(charadd+nitems);
1181: }
1182: if( (int) charadd <= 0 )
1183: error("NOT ENOUGH SPACE FOR ARRAY",FALSE);
1184: /*if(ii!=OTHER)*/ (*spaces[ii]->pages)->i += nitems/512;
1185: if(ATOX(datalim) > fakettsize) {
1186: datalim = (lispval) (OFFSET + (fakettsize << 9));
1187: if(fakettsize >= TTSIZE)
1188: {
1189: printf("There isn't room enough to continue, goodbye\n");
1190: franzexit(1);
1191: }
1192: fakettsize++;
1193: badmem(53);
1194: }
1195: for(jj=0; jj<nitems; jj=jj+512) {
1196: SETTYPE(charadd+jj, ii,30);
1197: }
1198: ii = (int) charadd;
1199: while(nitems > MAXCLEAR)
1200: {
1201: blzero(ii,MAXCLEAR);
1202: nitems -= MAXCLEAR;
1203: ii += MAXCLEAR;
1204: }
1205: blzero(ii,nitems);
1206: return((lispval)charadd);
1207: }
1208:
1209: int csizeof(tname) lispval tname;
1210: {
1211: return( spaces[typenum(tname)]->type_len * 4 );
1212: }
1213:
1214: int typenum(tname) lispval tname;
1215: {
1216: int ii;
1217:
1218: chek: for(ii=0; ii<NUMSPACES; ++ii)
1219: if(spaces[ii] && tname == *(spaces[ii]->type_name)) break;
1220: if(ii == NUMSPACES)
1221: {
1222: tname = error("BAD TYPE NAME",TRUE);
1223: goto chek;
1224: }
1225:
1226: return(ii);
1227:
1228: }
1229: char *
1230: gethspace(segsiz,type)
1231: {
1232: extern usehole; extern char holend[]; extern char *curhbeg;
1233: register char *value;
1234:
1235: if(usehole) {
1236: curhbeg = (char *) roundup(((int)curhbeg),LBPG);
1237: if((holend - curhbeg) < segsiz)
1238: {
1239: usehole = FALSE;
1240: curhbeg = holend;
1241: } else {
1242: value = curhbeg;
1243: curhbeg = curhbeg + segsiz;
1244: /*printf("start %d, finish %d, size %d\n",value, curhbeg,segsiz);*/
1245: return(value);
1246: }
1247: }
1248: value = (ysbrk(segsiz/LBPG,type));
1249: datalim = (lispval)(value + segsiz);
1250: return(value);
1251: }
1252: gcrebear()
1253: {
1254: #ifdef HOLE
1255: register int i; register struct types *p;
1256:
1257: /* this gets done upon rebirth */
1258: str_current[1].space_left = 0;
1259: #ifndef GCSTRINGS
1260: str_current[0].space_left = 0; /* both kinds of strings go in hole*/
1261: #endif
1262: funct_str.space_left = 0;
1263: funct_str.next_free = (char *) CNIL;
1264: /* clear pure space pointers */
1265: for(i = 0; i < NUMSPACES; i++)
1266: {
1267: if(p=spaces[i])
1268: p->next_pure_free = (char *) CNIL;
1269: }
1270: #endif
1271: }
1272:
1273: /** markit(p) ***********************************************************/
1274: /* just calls markdp */
1275:
1276: markit(p) lispval *p; { markdp(*p); }
1277:
1278: /*
1279: * markdp(p)
1280: *
1281: * markdp is the routine which marks each data item. If it is a
1282: * dotted pair, the car and cdr are marked also.
1283: * An iterative method is used to mark list structure, to avoid
1284: * excessive recursion.
1285: */
1286: markdp(p) register lispval p;
1287: {
1288: /* register int r, s; (goes with non-asm readbit, oksetbit) */
1289: /* register hsize, hcntr; */
1290: int hsize, hcntr;
1291:
1292: #ifdef METER
1293: mrkdpcnt++;
1294: #endif
1295: ptr_loop:
1296: if(((int)p) <= ((int)nil)) return; /* do not mark special data types or nil=0 */
1297:
1298:
1299: switch( TYPE(p) )
1300: {
1301: case ATOM:
1302: ftstbit;
1303: MARKVAL(p->a.clb);
1304: MARKVAL(p->a.plist);
1305: MARKVAL(p->a.fnbnd);
1306: #ifdef GCSTRINGS
1307: if(gcstrings) MARKVAL(((lispval)p->a.pname));
1308: return;
1309:
1310: case STRNG:
1311: p = (lispval) (((int) p) & ~ (LBPG-1));
1312: ftstbit;
1313: #endif
1314: return;
1315:
1316: case INT:
1317: case DOUB:
1318: ftstbit;
1319: return;
1320: case VALUE:
1321: ftstbit;
1322: p = p->l;
1323: goto ptr_loop;
1324: case DTPR:
1325: ftstbit;
1326: MARKVAL(p->d.car);
1327: #ifdef METER
1328: /* if we are metering , then check if the cdr is
1329: * nil, or if the cdr is on the same page, and if
1330: * it isn't one of those, then it is on a different
1331: * page
1332: */
1333: if(gcstat)
1334: {
1335: if(p->d.cdr == nil) consnil++;
1336: else if(((int)p & ~511)
1337: == (((int)(p->d.cdr)) & ~511))
1338: conssame++;
1339: else consdiff++;
1340: }
1341: #endif
1342: p = p->d.cdr;
1343: goto ptr_loop;
1344:
1345: case ARRAY:
1346: ftstbit; /* mark array itself */
1347:
1348: MARKVAL(p->ar.accfun); /* mark access function */
1349: MARKVAL(p->ar.aux); /* mark aux data */
1350: MARKVAL(p->ar.length); /* mark length */
1351: MARKVAL(p->ar.delta); /* mark delta */
1352: if(TYPE(p->ar.aux)==DTPR && p->ar.aux->d.car==Vnogbar)
1353: {
1354: /* a non garbage collected array must have its
1355: * array space marked but the value of the array
1356: * space is not marked
1357: */
1358: int l;
1359: int cnt,d;
1360: if(debugin && FALSE) {
1361: printf("mark array holders len %d, del %d, start 0x%x\n",
1362: p->ar.length->i,p->ar.delta->i,p->ar.data);
1363: fflush(stdout);
1364: }
1365: l = p->ar.length->i; /* number of elements */
1366: d = p->ar.delta->i; /* bytes per element */
1367: p = (lispval) p->ar.data;/* address of first one*/
1368: if(purepage[ATOX(p)]) return;
1369:
1370: for((cnt = 0); cnt<l ;
1371: p = (lispval)(((char *) p) + d), cnt++)
1372: {
1373: setbit;
1374: }
1375: } else {
1376: /* register int i, l; int d; */
1377: /* register char *dataptr = p->ar.data; */
1378: int i,l,d;
1379: char *dataptr = p->ar.data;
1380:
1381: for(i=0, l=p->ar.length->i, d=p->ar.delta->i; i<l; ++i)
1382: {
1383: markdp((lispval)dataptr);
1384: dataptr += d;
1385: }
1386: }
1387: return;
1388: case SDOT:
1389: do {
1390: ftstbit;
1391: p = p->s.CDR;
1392: } while (p!=0);
1393: return;
1394:
1395: case BCD:
1396: ftstbit;
1397: markdp(p->bcd.discipline);
1398: return;
1399:
1400: case HUNK2:
1401: case HUNK4:
1402: case HUNK8:
1403: case HUNK16:
1404: case HUNK32:
1405: case HUNK64:
1406: case HUNK128:
1407: {
1408: hsize = 2 << HUNKSIZE(p);
1409: ftstbit;
1410: for (hcntr = 0; hcntr < hsize; hcntr++)
1411: MARKVAL(p->h.hunk[hcntr]);
1412: return;
1413: }
1414:
1415: case VECTORI:
1416: ftstbit;
1417: MARKVAL(p->v.vector[-1]); /* mark property */
1418: return;
1419:
1420: case VECTOR:
1421: {
1422: register int vsize;
1423: ftstbit;
1424: vsize = VecSize(p->vl.vectorl[VSizeOff]);
1425: if(debugin)
1426: fprintf(stderr,"mark vect at %x size %d\n",
1427: p,vsize);
1428: while(--vsize >= -1)
1429: {
1430: MARKVAL(p->v.vector[vsize]);
1431: };
1432: return;
1433: }
1434: }
1435: return;
1436: }
1437:
1438:
1439: /* xsbrk allocates space in large chunks (currently 16 pages)
1440: * xsbrk(1) returns a pointer to a page
1441: * xsbrk(0) returns a pointer to the next page we will allocate (like sbrk(0))
1442: */
1443:
1444: char *
1445: xsbrk(n)
1446: {
1447: static char *xx; /* pointer to next available blank page */
1448: extern int xcycle; /* number of blank pages available */
1449: lispval u; /* used to compute limits of bit table */
1450:
1451: if( (xcycle--) <= 0 )
1452: {
1453: xcycle = 15;
1454: xx = sbrk(16*LBPG); /* get pages 16 at a time */
1455: if( (int)xx== -1 )
1456: lispend("For sbrk from lisp: no space... Goodbye!");
1457: }
1458: else xx += LBPG;
1459:
1460: if(n == 0)
1461: {
1462: xcycle++; /* don't allocate the page */
1463: xx -= LBPG;
1464: return(xx); /* just return its address */
1465: }
1466:
1467: if( (u = (lispval)(xx+LBPG)) > datalim ) datalim = u;
1468: return(xx);
1469: }
1470:
1471: char *ysbrk(pages,type) int pages, type;
1472: {
1473: char *xx; /* will point to block of storage */
1474: int i;
1475:
1476: xx = sbrk(pages*LBPG);
1477: if((int)xx == -1)
1478: error("OUT OF SPACE FOR ARRAY REQUEST",FALSE);
1479:
1480: datalim = (lispval)(xx+pages*LBPG); /* compute bit table limit */
1481:
1482: /* set type for pages */
1483:
1484: for(i = 0; i < pages; ++i) {
1485: SETTYPE((xx + i*LBPG),type,10);
1486: }
1487:
1488: return(xx); /* return pointer to block of storage */
1489: }
1490:
1491: /*
1492: * getatom
1493: * returns either an existing atom with the name specified in strbuf, or
1494: * if the atom does not already exist, regurgitates a new one and
1495: * returns it.
1496: */
1497: lispval
1498: getatom(purep)
1499: { register lispval aptr;
1500: register char *name, *endname;
1501: register int hash;
1502: lispval b;
1503: char c;
1504:
1505: name = strbuf;
1506: if (*name == (char)0377) return (eofa);
1507: hash = hashfcn(name);
1508: atmlen = strlen(name) + 1;
1509: aptr = (lispval) hasht[hash];
1510: while (aptr != CNIL)
1511: /* if (strcmp(name,aptr->a.pname)==0) */
1512: if (*name==*aptr->a.pname && strcmp(name,aptr->a.pname)==0)
1513: return (aptr);
1514: else
1515: aptr = (lispval) aptr->a.hshlnk;
1516: aptr = (lispval) newatom(purep); /*share pname of atoms on oblist*/
1517: aptr->a.hshlnk = hasht[hash];
1518: hasht[hash] = (struct atom *) aptr;
1519: endname = name + atmlen - 2;
1520: if ((atmlen != 4) && (*name == 'c') && (*endname == 'r'))
1521: {
1522: b = newdot();
1523: protect(b);
1524: b->d.car = lambda;
1525: b->d.cdr = newdot();
1526: b = b->d.cdr;
1527: b->d.car = newdot();
1528: (b->d.car)->d.car = xatom;
1529: while(TRUE)
1530: {
1531: b->d.cdr = newdot();
1532: b= b->d.cdr;
1533: if(++name == endname)
1534: {
1535: b->d.car= (lispval) xatom;
1536: aptr->a.fnbnd = (--np)->val;
1537: break;
1538: }
1539: b->d.car= newdot();
1540: b= b->d.car;
1541: if((c = *name) == 'a') b->d.car = cara;
1542: else if (c == 'd') b->d.car = cdra;
1543: else{ --np;
1544: break;
1545: }
1546: }
1547: }
1548:
1549: return(aptr);
1550: }
1551:
1552: /*
1553: * inewatom is like getatom, except that you provide it a string
1554: * to be used as the print name. It doesn't do the automagic
1555: * creation of things of the form c[ad]*r.
1556: */
1557: lispval
1558: inewatom(name)
1559: register char *name;
1560: { register struct atom *aptr;
1561: register int hash;
1562: extern struct types atom_str;
1563: char c;
1564:
1565: if (*name == (char)0377) return (eofa);
1566: hash = hashfcn(name);
1567: aptr = hasht[hash];
1568: while (aptr != (struct atom *)CNIL)
1569: if (strcmp(name,aptr->pname)==0)
1570: return ((lispval) aptr);
1571: else
1572: aptr = aptr->hshlnk;
1573: aptr = (struct atom *) next_one(&atom_str) ;
1574: aptr->plist = aptr->fnbnd = nil;
1575: aptr->clb = CNIL;
1576: aptr->pname = name;
1577: aptr->hshlnk = hasht[hash];
1578: hasht[hash] = aptr;
1579: return((lispval)aptr);
1580: }
1581:
1582:
1583: /* our hash function */
1584:
1585: hashfcn(symb)
1586: register char *symb;
1587: {
1588: register int i;
1589: /* for (i=0 ; *symb ; i += i + *symb++); return(i & (HASHTOP-1)); */
1590: for (i=0 ; *symb ; i += i*2 + *symb++);
1591: return(i&077777 % HASHTOP);
1592: }
1593:
1594: lispval
1595: LImemory()
1596: {
1597: int nextadr, pagesinuse;
1598:
1599: printf("Memory report. max pages = %d (0x%x) = %d Bytes\n",
1600: TTSIZE,TTSIZE,TTSIZE*LBPG);
1601: #ifdef HOLE
1602: printf("This lisp has a hole:\n");
1603: printf(" current hole start: %d (0x%x), end %d (0x%x)\n",
1604: curhbeg, curhbeg, holend, holend);
1605: printf(" hole free: %d bytes = %d pages\n\n",
1606: holend-curhbeg, (holend-curhbeg)/LBPG);
1607: #endif
1608: nextadr = (int) xsbrk(0); /* next space to be allocated */
1609: pagesinuse = nextadr/LBPG;
1610: printf("Next allocation at addr %d (0x%x) = page %d\n",
1611: nextadr, nextadr, pagesinuse);
1612: printf("Free data pages: %d\n", TTSIZE-pagesinuse);
1613: return(nil);
1614: }
1615:
1616: extern struct atom *hasht[HASHTOP];
1617: myhook(){}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.