|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: /na/franz/franz/RCS/alloc.c,v 1.8 83/08/06 08:38:19 jkf Exp $"; ! 4: #endif ! 5: ! 6: /* -[Fri Aug 5 12:44:01 1983 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)bitmap[r=(int)p>>5] & (s=bitmsk[((int)p>>2)&7])) ! 46: # define lookbit(p) (bitmap[(int)p>>5] & bitmsk[((int)p>>2) & 7]) ! 47: /* # define setbit(p) {bitmap[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];} */ ! 48: # define oksetbit {bitmap[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 *bitmap = (char *) bitmapi; /* byte version of bit map array */ ! 75: double *bitmapq = (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 markdpcount; ! 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: pnewdoub() ! 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: char *inewstr(s) char *s; ! 401: { ! 402: strbuf[STRBLEN-1] = '\0'; ! 403: strcpyn(strbuf,s,STRBLEN-1); ! 404: return(newstr(0)); ! 405: } ! 406: ! 407: char *pinewstr(s) char *s; ! 408: { ! 409: strbuf[STRBLEN-1] = '\0'; ! 410: strcpyn(strbuf,s,STRBLEN-1); ! 411: return(newstr(1)); ! 412: } ! 413: ! 414: lispval ! 415: newarray() ! 416: { ! 417: register lispval temp; ! 418: ! 419: temp = next_one(&array_str); ! 420: temp->ar.data = (char *)nil; ! 421: temp->ar.accfun = nil; ! 422: temp->ar.aux = nil; ! 423: temp->ar.length = SMALL(0); ! 424: temp->ar.delta = SMALL(0); ! 425: return(temp); ! 426: } ! 427: ! 428: lispval ! 429: newfunct() ! 430: { ! 431: register lispval temp; ! 432: lispval badcall(); ! 433: temp = next_one(&funct_str); ! 434: temp->bcd.start = badcall; ! 435: temp->bcd.discipline = nil; ! 436: return(temp); ! 437: } ! 438: ! 439: lispval ! 440: newval() ! 441: { ! 442: register lispval temp; ! 443: temp = next_one(&val_str); ! 444: temp->l = nil; ! 445: return(temp); ! 446: } ! 447: ! 448: lispval ! 449: pnewval() ! 450: { ! 451: register lispval temp; ! 452: temp = next_pure_one(&val_str); ! 453: temp->l = nil; ! 454: return(temp); ! 455: } ! 456: ! 457: lispval ! 458: newhunk(hunknum) ! 459: int hunknum; ! 460: { ! 461: register lispval temp; ! 462: ! 463: temp = next_one(&hunk_str[hunknum]); /* Get a hunk */ ! 464: return(temp); ! 465: } ! 466: ! 467: lispval ! 468: pnewhunk(hunknum) ! 469: int hunknum; ! 470: { ! 471: register lispval temp; ! 472: ! 473: temp = next_pure_one(&hunk_str[hunknum]); /* Get a hunk */ ! 474: return(temp); ! 475: } ! 476: ! 477: lispval ! 478: inewval(arg) lispval arg; ! 479: { ! 480: lispval temp; ! 481: temp = next_one(&val_str); ! 482: temp->l = arg; ! 483: return(temp); ! 484: } ! 485: ! 486: /* ! 487: * Vector allocators. ! 488: * a vector looks like: ! 489: * longword: N = size in bytes ! 490: * longword: pointer to lisp object, this is the vector property field ! 491: * N consecutive bytes ! 492: * ! 493: */ ! 494: lispval getvec(); ! 495: ! 496: lispval ! 497: newvec(size) ! 498: { ! 499: return(getvec(size,&vect_str,FALSE)); ! 500: } ! 501: ! 502: lispval ! 503: pnewvec(size) ! 504: { ! 505: return(getvec(size,&vect_str,TRUE)); ! 506: } ! 507: ! 508: lispval ! 509: nveci(size) ! 510: { ! 511: return(getvec(size,&vecti_str,FALSE)); ! 512: } ! 513: ! 514: lispval ! 515: pnveci(size) ! 516: { ! 517: return(getvec(size,&vecti_str,TRUE)); ! 518: } ! 519: ! 520: /* ! 521: * getvec ! 522: * get a vector of size byte, from type structure typestr and ! 523: * get it from pure space if purep is TRUE. ! 524: * vectors are stored linked through their property field. Thus ! 525: * when the code here refers to v.vector[0], it is the prop field ! 526: * and vl.vectorl[-1] is the size field. In other code, ! 527: * v.vector[-1] is the prop field, and vl.vectorl[-2] is the size. ! 528: */ ! 529: lispval ! 530: getvec(size,typestr,purep) ! 531: register struct types *typestr; ! 532: { ! 533: register lispval back, current; ! 534: int sizewant, bytes, thissize, pages, pindex, triedgc = FALSE; ! 535: ! 536: /* we have to round up to a multiple of 4 bytes to determine the ! 537: * size of vector we want. The rounding up assures that the ! 538: * property pointers are longword aligned ! 539: */ ! 540: sizewant = VecTotSize(size); ! 541: if(debugin) fprintf(stderr,"want vect %db\n",size); ! 542: again: ! 543: if(purep) ! 544: back = (lispval) &(typestr->next_pure_free); ! 545: else ! 546: back = (lispval) &(typestr->next_free); ! 547: current = back->v.vector[0]; ! 548: while(current != CNIL) ! 549: { ! 550: if(debugin) ! 551: fprintf(stderr,"next free size %db; ", current->vl.vectorl[-1]); ! 552: if ((thissize = VecTotSize(current->vl.vectorl[-1])) == sizewant) ! 553: { ! 554: if(debugin) fprintf(stderr,"exact match of size %d at 0x%x\n", ! 555: 4*thissize, ¤t->v.vector[1]); ! 556: back->v.vector[0] ! 557: = current->v.vector[0];/* change free pointer*/ ! 558: current->v.vector[0] = nil; /* put nil in property */ ! 559: /* to the user, vector begins one after property*/ ! 560: return((lispval)¤t->v.vector[1]); ! 561: } ! 562: else if (thissize >= sizewant + 3) ! 563: { ! 564: /* the reason that there is a `+ 3' instead of `+ 2' ! 565: * is that we don't want to leave a zero sized vector which ! 566: * isn't guaranteed to be followed by another vector ! 567: */ ! 568: if(debugin) ! 569: fprintf(stderr,"breaking a %d vector into a ", ! 570: current->vl.vectorl[-1]); ! 571: ! 572: current->v.vector[1+sizewant+1] ! 573: = current->v.vector[0]; /* free list pointer */ ! 574: current->vl.vectorl[1+sizewant] ! 575: = VecTotToByte(thissize - sizewant - 2);/*size info */ ! 576: back->v.vector[0] = (lispval) &(current->v.vector[1+sizewant+1]); ! 577: current->vl.vectorl[-1] = size; ! 578: ! 579: if(debugin)fprintf(stderr," %d one and a %d one\n", ! 580: current->vl.vectorl[-1],current->vl.vectorl[1+sizewant]); ! 581: current->v.vector[0] = nil; /* put nil in property */ ! 582: /* vector begins one after the property */ ! 583: if(debugin) fprintf(stderr," and returning vector at 0x%x\n", ! 584: ¤t->v.vector[1]); ! 585: return((lispval)(¤t->v.vector[1])); ! 586: } ! 587: back = current; ! 588: current = current->v.vector[0]; ! 589: } ! 590: if(!triedgc ! 591: && !purep ! 592: && (gcdis->a.clb == nil) ! 593: && (initflag == FALSE)) ! 594: { ! 595: gc(typestr); ! 596: triedgc = TRUE; ! 597: goto again; ! 598: } ! 599: ! 600: /* set bytes to size needed for this vector */ ! 601: bytes = size + 2*sizeof(long); ! 602: ! 603: /* must make sure that if the vector we are allocating doesnt ! 604: completely fill a page, there is room for another vector to record ! 605: the size left over */ ! 606: if((bytes & (LBPG - 1)) > (LBPG - 2*sizeof(long))) bytes += LBPG; ! 607: bytes = roundup(bytes,LBPG); ! 608: ! 609: current = csegment(typestr->type,bytes/sizeof(long),purep); ! 610: current->vl.vectorl[0] = bytes - 2*sizeof(long); ! 611: ! 612: if(purep) { ! 613: current->v.vector[1] = (lispval)(typestr->next_pure_free); ! 614: typestr->next_pure_free = (char *) &(current->v.vector[1]); ! 615: /* make them pure */ ! 616: pages = bytes/LBPG; ! 617: for(pindex = ATOX(current); pages ; pages--) ! 618: { ! 619: purepage[pindex++] = TRUE; ! 620: } ! 621: } else { ! 622: current->v.vector[1] = (lispval)(typestr->next_free); ! 623: typestr->next_free = (char *) &(current->v.vector[1]); ! 624: if(debugin) fprintf(stderr,"grabbed %d vec pages\n",bytes/LBPG); ! 625: } ! 626: if(debugin) ! 627: fprintf(stderr,"creating a new vec, size %d\n",current->v.vector[0]); ! 628: goto again; ! 629: } ! 630: ! 631: /* ! 632: * Ipurep :: routine to check for pureness of a data item ! 633: * ! 634: */ ! 635: lispval ! 636: Ipurep(element) ! 637: lispval element; ! 638: { ! 639: if(purepage[ATOX(element)]) return(tatom) ; else return(nil); ! 640: } ! 641: ! 642: /* routines to return space to the free list. These are used by the ! 643: * arithmetic routines which tend to create large intermediate results ! 644: * which are know to be garbage after the calculation is over. ! 645: * ! 646: * There are jsb callable versions of these routines in qfuncl.s ! 647: */ ! 648: ! 649: /* pruneb - prune bignum. A bignum is an sdot followed by a list of ! 650: * dtprs. The dtpr list is linked by car instead of cdr so when we ! 651: * put it in the free list, we have to change the links. ! 652: */ ! 653: pruneb(bignum) ! 654: lispval bignum; ! 655: { ! 656: register lispval temp = bignum; ! 657: ! 658: if(TYPE(temp) != SDOT) ! 659: errorh(Vermisc,"value to pruneb not a sdot",nil,FALSE,0); ! 660: ! 661: --(sdot_items->i); ! 662: temp->s.I = (int) sdot_str.next_free; ! 663: sdot_str.next_free = (char *) temp; ! 664: ! 665: /* bignums are not terminated by nil on the dual, ! 666: they are terminated by (lispval) 0 */ ! 667: ! 668: while(temp = temp->s.CDR) ! 669: { ! 670: if(TYPE(temp) != DTPR) ! 671: errorh(Vermisc,"value to pruneb not a list", ! 672: nil,FALSE,0); ! 673: --(dtpr_items->i); ! 674: temp->s.I = (int) dtpr_str.next_free; ! 675: dtpr_str.next_free = (char *) temp; ! 676: } ! 677: } ! 678: lispval ! 679: badcall() ! 680: { error("BAD FUNCTION DESCRIPTOR USED IN CALL",FALSE); } ! 681: ! 682: ! 683: ! 684: /* ! 685: * Ngc ! 686: * this is the lisp function gc ! 687: * ! 688: */ ! 689: ! 690: lispval ! 691: Ngc() ! 692: { ! 693: return(gc((struct types *)CNIL)); ! 694: } ! 695: ! 696: /* ! 697: * gc(type_struct) ! 698: * ! 699: * garbage collector: Collects garbage by mark and sweep algorithm. ! 700: * After this is done, calls the Nlambda, gcafter. ! 701: * gc may also be called from LISP, as an nlambda of no arguments. ! 702: * type_struct is the type of lisp data that ran out causing this ! 703: * garbage collection ! 704: */ ! 705: int printall = 0; ! 706: lispval ! 707: gc(type_struct) ! 708: struct types *type_struct; ! 709: { ! 710: lispval save; ! 711: struct tms begin, finish; ! 712: extern int gctime; ! 713: ! 714: /* if this was called automatically when space ran out ! 715: * print out a message ! 716: */ ! 717: if((Vgcprint->a.clb != nil) ! 718: && (type_struct != (struct types *) CNIL )) ! 719: { ! 720: FILE *port = okport(Vpoport->a.clb,poport); ! 721: fprintf(port,"gc:"); ! 722: fflush(port); ! 723: } ! 724: ! 725: if(gctime) times(&begin); ! 726: ! 727: gc1(); /* mark&sweep */ ! 728: ! 729: /* Now we call gcafter--special c ase if gc called from LISP */ ! 730: ! 731: if( type_struct == (struct types *) CNIL ) ! 732: gccall1->d.cdr = nil; /* make the call "(gcafter)" */ ! 733: else ! 734: { ! 735: gccall1->d.cdr = gccall2; ! 736: gccall2->d.car = *(type_struct->type_name); ! 737: } ! 738: PUSHDOWN(gcdis,gcdis); /* flag to indicate in garbage collector */ ! 739: save = eval(gccall1); /* call gcafter */ ! 740: POP; /* turn off flag */ ! 741: ! 742: if(gctime) { ! 743: times(&finish); ! 744: gctime += (finish.tms_utime - begin.tms_utime); ! 745: } ! 746: return(save); /* return result of gcafter */ ! 747: } ! 748: ! 749: ! 750: ! 751: /* gc1() **************************************************************/ ! 752: /* */ ! 753: /* Mark-and-sweep phase */ ! 754: ! 755: gc1() ! 756: { ! 757: int j, k; ! 758: register int *start,bvalue,type_len; ! 759: register struct types *s; ! 760: int *point,i,freecnt,itemstogo,bits,bindex,type,bytestoclear; ! 761: int usedcnt; ! 762: char *pindex; ! 763: struct argent *loop2; ! 764: struct nament *loop3; ! 765: struct atom *symb; ! 766: int markdp(); ! 767: extern int hashtop; ! 768: ! 769: pagerand(); ! 770: /* decide whether to check LISP structure or not */ ! 771: ! 772: ! 773: #ifdef METER ! 774: vtimes(&premark,0); ! 775: markdpcount = 0; ! 776: conssame = consdiff = consnil = 0; ! 777: #endif ! 778: ! 779: /* first set all bit maps to zero */ ! 780: ! 781: ! 782: #ifdef SLOCLEAR ! 783: { ! 784: int enddat; ! 785: enddat = (int)(datalim-OFFSET) >> 8; ! 786: for(bvalue=0; bvalue < (int)enddat ; ++bvalue) ! 787: { ! 788: bitmapq[bvalue] = zeroq; ! 789: } ! 790: } ! 791: #endif ! 792: ! 793: /* try the movc5 to clear the bit maps */ ! 794: /* the maximum number of bytes we can clear in one sweep is ! 795: * 2^16 (or 1<<16 in the C lingo) ! 796: */ ! 797: bytestoclear = ((((int)datalim)-((int)beginsweep)) >> 9) * 16; ! 798: if(bytestoclear > MAXCLEAR) ! 799: { ! 800: blzero(((int) &bitmapi[ATOLX(beginsweep)]) + MAXCLEAR, ! 801: bytestoclear - MAXCLEAR); ! 802: bytestoclear = MAXCLEAR; ! 803: } ! 804: blzero((int)&bitmapi[ATOLX(beginsweep)],bytestoclear); ! 805: ! 806: /* mark all atoms in the oblist */ ! 807: for( bvalue=0 ; bvalue <= hashtop-1 ; bvalue++ ) /* though oblist */ ! 808: { ! 809: for( symb = hasht[bvalue] ; symb != (struct atom *) CNIL ; ! 810: symb = symb-> hshlnk) { ! 811: markdp((lispval)symb); ! 812: } ! 813: } ! 814: ! 815: ! 816: /* Mark all the atoms and ints associated with the hunk ! 817: data types */ ! 818: ! 819: for(i=0; i<7; i++) { ! 820: markdp(hunk_items[i]); ! 821: markdp(hunk_name[i]); ! 822: markdp(hunk_pages[i]); ! 823: } ! 824: /* next run up the name stack */ ! 825: for(loop2 = np - 1; loop2 >= orgnp; --loop2) MARKVAL(loop2->val); ! 826: ! 827: /* now the bindstack (vals only, atoms are marked elsewhere ) */ ! 828: for(loop3 = bnp - 1; loop3 >= orgbnp; --loop3)MARKVAL(loop3->val); ! 829: ! 830: ! 831: /* next mark all compiler linked data */ ! 832: /* if the Vpurcopylits switch is non nil (lisp variable $purcopylits) ! 833: * then when compiled code is read in, it tables will not be linked ! 834: * into this table and thus will not be marked here. That is ok ! 835: * though, since that data is assumed to be pure. ! 836: */ ! 837: point = bind_lists; ! 838: while((start = point) != (int *)CNIL) { ! 839: while( *start != -1 ) ! 840: { ! 841: markdp((lispval)*start); ! 842: start++; ! 843: } ! 844: point = (int *)*(point-1); ! 845: } ! 846: ! 847: /* next mark all system-significant lisp data */ ! 848: ! 849: ! 850: for(i=0; i<SIGNIF; ++i) markdp((lispsys[i])); ! 851: ! 852: #ifdef METER ! 853: vtimes(&presweep,0); ! 854: #endif ! 855: /* all accessible data has now been marked. */ ! 856: /* all collectable spaces must be swept, */ ! 857: /* and freelists constructed. */ ! 858: ! 859: /* first clear the structure elements for types ! 860: * we will sweep ! 861: */ ! 862: ! 863: for(k=0 ; k <= VECTORI ; k++) ! 864: { ! 865: if( s=gcableptr[k]) { ! 866: if(k==STRNG && !gcstrings) { /* don't do anything*/ } ! 867: else ! 868: { ! 869: (*(s->items))->i = 0; ! 870: s->space_left = 0; ! 871: s->next_free = (char *) CNIL; ! 872: } ! 873: } ! 874: } ! 875: #if m_68k ! 876: fixbits(bitmapi+ATOLX(beginsweep),bitmapi+ATOLX(datalim)); ! 877: #endif ! 878: ! 879: ! 880: /* sweep up in memory looking at gcable pages */ ! 881: ! 882: for(start = beginsweep, bindex = ATOLX(start), ! 883: pindex = &purepage[ATOX(start)]; ! 884: start < (int *)datalim; ! 885: start += 128, pindex++) ! 886: { ! 887: if(!(s=gcableptr[type = TYPE(start)]) || *pindex ! 888: #ifdef GCSTRINGS ! 889: || (type==STRNG && !gcstrings) ! 890: #endif ! 891: ) ! 892: { ! 893: /* ignore this page but advance pointer */ ! 894: bindex += 4; /* and 4 words of 32 bit bitmap words */ ! 895: continue; ! 896: } ! 897: ! 898: freecnt = 0; /* number of free items found */ ! 899: usedcnt = 0; /* number of used items found */ ! 900: ! 901: point = start; ! 902: /* sweep dtprs as a special case, since ! 903: * 1) there will (usually) be more dtpr pages than any other type ! 904: * 2) most dtpr pages will be empty so we can really win by special ! 905: * caseing the sweeping of massive numbers of free cells ! 906: */ ! 907: /* since sdot's have the same structure as dtprs, this code will ! 908: work for them too ! 909: */ ! 910: if((type == DTPR) || (type == SDOT)) ! 911: { ! 912: int *head,*lim; ! 913: head = (int *) s->next_free; /* first value on free list*/ ! 914: ! 915: for(i=0; i < 4; i++) /* 4 bit map words per page */ ! 916: { ! 917: bvalue = bitmapi[bindex++]; /* 32 bits = 16 dtprs */ ! 918: if(bvalue == 0) /* if all are free */ ! 919: { ! 920: *point = (int)head; ! 921: lim = point + 32; /* 16 dtprs = 32 ints */ ! 922: for(point += 2; point < lim ; point += 2) ! 923: { ! 924: *point = (int)(point - 2); ! 925: } ! 926: head = point - 2; ! 927: freecnt += 16; ! 928: } ! 929: else for(j = 0; j < 16 ; j++) ! 930: { ! 931: if(!(bvalue & 1)) ! 932: { ! 933: freecnt++; ! 934: *point = (int)head; ! 935: head = point; ! 936: } ! 937: #ifdef METER ! 938: /* check if the page address of this cell is the ! 939: * same as the address of its cdr ! 940: */ ! 941: else if(FALSE && gcstat && (type == DTPR)) ! 942: { ! 943: if(((int)point & ~511) ! 944: == ((int)(*point) & ~511)) conssame++; ! 945: else consdiff++; ! 946: usedcnt++; ! 947: } ! 948: #endif ! 949: else usedcnt++; /* keep track of used */ ! 950: ! 951: point += 2; ! 952: bvalue = bvalue >> 2; ! 953: } ! 954: } ! 955: s->next_free = (char *) head; ! 956: } ! 957: else if((type == VECTOR) || (type == VECTORI)) ! 958: { ! 959: int canjoin = FALSE; ! 960: int *tempp; ! 961: ! 962: /* check if first item on freelist ends exactly at ! 963: this page ! 964: */ ! 965: if(((tempp = (int *)s->next_free) != (int *)CNIL) ! 966: && ((VecTotSize(((lispval)tempp)->vl.vectorl[-1]) ! 967: + 1 + tempp) ! 968: == point)) ! 969: canjoin = TRUE; ! 970: ! 971: /* arbitrary sized vector sweeper */ ! 972: /* ! 973: * jump past first word since that is a size fixnum ! 974: * and second word since that is property word ! 975: */ ! 976: if(debugin) ! 977: fprintf(stderr,"vector sweeping, start at 0x%x\n", ! 978: point); ! 979: bits = 30; ! 980: bvalue = bitmapi[bindex++] >> 2; ! 981: point += 2; ! 982: while (TRUE) { ! 983: type_len = point[VSizeOff]; ! 984: if(debugin) { ! 985: fprintf(stderr,"point: 0x%x, type_len %d\n", ! 986: point, type_len); ! 987: fprintf(stderr,"bvalue: 0x%x, bits: %d, bindex: 0x%x\n", ! 988: bvalue, bits, bindex); ! 989: } ! 990: /* get size of vector */ ! 991: if(!(bvalue & 1)) /* if free */ ! 992: { ! 993: if(debugin) fprintf(stderr,"free\n"); ! 994: freecnt += type_len + 2*sizeof(long); ! 995: if(canjoin) ! 996: { ! 997: /* join by adjusting size of first vector */ ! 998: ((lispval)(s->next_free))->vl.vectorl[-1] ! 999: += type_len + 2*sizeof(long); ! 1000: if(debugin) ! 1001: fprintf(stderr,"joined size: %d\n", ! 1002: ((lispval)(s->next_free))->vl.vectorl[-1]); ! 1003: } ! 1004: else { ! 1005: /* vectors are linked at the property word */ ! 1006: *(point - 1) = (int)(s->next_free); ! 1007: s->next_free = (char *) (point - 1); ! 1008: } ! 1009: canjoin = TRUE; ! 1010: } ! 1011: else { ! 1012: canjoin = FALSE; ! 1013: usedcnt += type_len + 2*sizeof(long); ! 1014: } ! 1015: ! 1016: point += VecTotSize(type_len); ! 1017: /* we stop sweeping only when we reach a page ! 1018: boundary since vectors can span pages ! 1019: */ ! 1020: if(((int)point & 511) == 0) ! 1021: { ! 1022: /* reset the counters, we cannot predict how ! 1023: * many pages we have crossed over ! 1024: */ ! 1025: bindex = ATOLX(point); ! 1026: /* these will be inced, so we must dec */ ! 1027: pindex = &purepage[ATOX(point)] - 1; ! 1028: start = point - 128; ! 1029: if(debugin) ! 1030: fprintf(stderr, ! 1031: "out of vector sweep when point = 0x%x\n", ! 1032: point); ! 1033: break; ! 1034: } ! 1035: /* must advance to next point and next value in bitmap. ! 1036: * we add VecTotSize(type_len) + 2 to get us to the 0th ! 1037: * entry in the next vector (beyond the size fixnum) ! 1038: */ ! 1039: point += 2; /* point to next 0th entry */ ! 1040: if ( (bits -= (VecTotSize(type_len) + 2)) > 0) ! 1041: bvalue = bvalue >> (VecTotSize(type_len) + 2); ! 1042: else { ! 1043: bits = -bits; /* must advance to next word in map */ ! 1044: bindex += bits / 32; /* this is tricky stuff... */ ! 1045: bits = bits % 32; ! 1046: bvalue = bitmapi[bindex++] >> bits; ! 1047: bits = 32 - bits; ! 1048: } ! 1049: } ! 1050: } ! 1051: else { ! 1052: /* general sweeper, will work for all types */ ! 1053: itemstogo = s->space; /* number of items per page */ ! 1054: bits = 32; /* number of bits per word */ ! 1055: type_len = s->type_len; ! 1056: ! 1057: /* printf(" s %d, itemstogo %d, len %d\n",s,itemstogo,type_len);*/ ! 1058: bvalue = bitmapi[bindex++]; ! 1059: ! 1060: while(TRUE) ! 1061: { ! 1062: if(!(bvalue & 1)) /* if data element is not marked */ ! 1063: { ! 1064: freecnt++; ! 1065: *point = (int) (s->next_free) ; ! 1066: s->next_free = (char *) point; ! 1067: } ! 1068: else usedcnt++; ! 1069: ! 1070: if( --itemstogo <= 0 ) ! 1071: { if(type_len >= 64) ! 1072: { ! 1073: bindex++; ! 1074: if(type_len >=128) bindex += 2; ! 1075: } ! 1076: break; ! 1077: } ! 1078: ! 1079: point += type_len; ! 1080: /* shift over mask by number of words in data type */ ! 1081: ! 1082: if( (bits -= type_len) > 0) ! 1083: { bvalue = bvalue >> type_len; ! 1084: } ! 1085: else if( bits == 0 ) ! 1086: { bvalue = bitmapi[bindex++]; ! 1087: bits = 32; ! 1088: } ! 1089: else ! 1090: { bits = -bits; ! 1091: while( bits >= 32) { bindex++; ! 1092: bits -= 32; ! 1093: } ! 1094: bvalue = bitmapi[bindex++]; ! 1095: bvalue = bvalue >> bits; ! 1096: bits = 32 - bits;; ! 1097: } ! 1098: } ! 1099: } ! 1100: ! 1101: s->space_left += freecnt; ! 1102: (*(s->items))->i += usedcnt; ! 1103: } ! 1104: ! 1105: #ifdef METER ! 1106: vtimes(&alldone,0); ! 1107: if(gcstat) gcdump(); ! 1108: #endif ! 1109: pagenorm(); ! 1110: } ! 1111: ! 1112: /* ! 1113: * alloc ! 1114: * ! 1115: * This routine tries to allocate one or more pages of the space named ! 1116: * by the first argument. Returns the number of pages actually allocated. ! 1117: * ! 1118: */ ! 1119: ! 1120: lispval ! 1121: alloc(tname,npages) ! 1122: lispval tname; long npages; ! 1123: { ! 1124: long ii, jj; ! 1125: struct types *typeptr; ! 1126: ! 1127: ii = typenum(tname); ! 1128: typeptr = spaces[ii]; ! 1129: if(npages <= 0) return(inewint(npages)); ! 1130: ! 1131: if((ATOX(datalim)) + npages > TTSIZE) ! 1132: error("Space request would exceed maximum memory allocation",FALSE); ! 1133: if((ii == VECTOR) || (ii == VECTORI)) ! 1134: { ! 1135: /* allocate in one big chunk */ ! 1136: tname = csegment((int) ii,(int) npages*128,0); ! 1137: tname->vl.vectorl[0] = (npages*512 - 2*sizeof(long)); ! 1138: tname->v.vector[1] = (lispval) typeptr->next_free; ! 1139: typeptr->next_free = (char *) &(tname->v.vector[1]); ! 1140: if(debugin) fprintf(stderr,"alloced %d vec pages\n",npages); ! 1141: return(inewint(npages)); ! 1142: } ! 1143: ! 1144: for( jj=0; jj<npages; ++jj) ! 1145: if(get_more_space(spaces[ii],FALSE)) break; ! 1146: return(inewint(jj)); ! 1147: } ! 1148: ! 1149: /* ! 1150: * csegment(typecode,nitems,useholeflag) ! 1151: * allocate nitems of type typecode. If useholeflag is true, then ! 1152: * allocate in the hole if there is room. This routine doesn't look ! 1153: * in the free lists, it always allocates space. ! 1154: */ ! 1155: lispval ! 1156: csegment(typecode,nitems,useholeflag) ! 1157: { ! 1158: register int ii, jj; ! 1159: register char *charadd; ! 1160: ! 1161: ii = typecode; ! 1162: ! 1163: if(ii!=OTHER) nitems *= 4*spaces[ii]->type_len; ! 1164: nitems = roundup(nitems,512); /* round up to right length */ ! 1165: #ifdef HOLE ! 1166: if(useholeflag) ! 1167: charadd = gethspace(nitems,ii); ! 1168: else ! 1169: #endif ! 1170: { ! 1171: charadd = sbrk(nitems); ! 1172: datalim = (lispval)(charadd+nitems); ! 1173: } ! 1174: if( (int) charadd == 0 ) ! 1175: error("NOT ENOUGH SPACE FOR ARRAY",FALSE); ! 1176: /*if(ii!=OTHER)*/ (*spaces[ii]->pages)->i += nitems/512; ! 1177: if(ATOX(datalim) > fakettsize) { ! 1178: datalim = (lispval) (OFFSET + (fakettsize << 9)); ! 1179: if(fakettsize >= TTSIZE) ! 1180: { ! 1181: printf("There isn't room enough to continue, goodbye\n"); ! 1182: franzexit(1); ! 1183: } ! 1184: fakettsize++; ! 1185: badmem(53); ! 1186: } ! 1187: for(jj=0; jj<nitems; jj=jj+512) { ! 1188: SETTYPE(charadd+jj, ii,30); ! 1189: } ! 1190: ii = (int) charadd; ! 1191: while(nitems > MAXCLEAR) ! 1192: { ! 1193: blzero(ii,MAXCLEAR); ! 1194: nitems -= MAXCLEAR; ! 1195: ii += MAXCLEAR; ! 1196: } ! 1197: blzero(ii,nitems); ! 1198: return((lispval)charadd); ! 1199: } ! 1200: ! 1201: int csizeof(tname) lispval tname; ! 1202: { ! 1203: return( spaces[typenum(tname)]->type_len * 4 ); ! 1204: } ! 1205: ! 1206: int typenum(tname) lispval tname; ! 1207: { ! 1208: int ii; ! 1209: ! 1210: chek: for(ii=0; ii<NUMSPACES; ++ii) ! 1211: if(spaces[ii] && tname == *(spaces[ii]->type_name)) break; ! 1212: if(ii == NUMSPACES) ! 1213: { ! 1214: tname = error("BAD TYPE NAME",TRUE); ! 1215: goto chek; ! 1216: } ! 1217: ! 1218: return(ii); ! 1219: ! 1220: } ! 1221: char * ! 1222: gethspace(segsiz,type) ! 1223: { ! 1224: extern usehole; extern char holend[]; extern char *curhbeg; ! 1225: register char *value; ! 1226: ! 1227: if(usehole) { ! 1228: curhbeg = (char *) roundup(((int)curhbeg),LBPG); ! 1229: if((holend - curhbeg) < segsiz) ! 1230: { printf("[fasl hole filled up]\n"); ! 1231: usehole = FALSE; ! 1232: curhbeg = holend; ! 1233: } else { ! 1234: value = curhbeg; ! 1235: curhbeg = curhbeg + segsiz; ! 1236: /*printf("start %d, finish %d, size %d\n",value, curhbeg,segsiz);*/ ! 1237: return(value); ! 1238: } ! 1239: } ! 1240: value = (ysbrk(segsiz/LBPG,type)); ! 1241: datalim = (lispval)(value + segsiz); ! 1242: return(value); ! 1243: } ! 1244: gcrebear() ! 1245: { ! 1246: #ifdef HOLE ! 1247: register int i; register struct types *p; ! 1248: ! 1249: /* this gets done upon rebirth */ ! 1250: str_current[1].space_left = 0; ! 1251: #ifndef GCSTRINGS ! 1252: str_current[0].space_left = 0; /* both kinds of strings go in hole*/ ! 1253: #endif ! 1254: funct_str.space_left = 0; ! 1255: funct_str.next_free = (char *) CNIL; ! 1256: /* clear pure space pointers */ ! 1257: for(i = 0; i < NUMSPACES; i++) ! 1258: { ! 1259: if(p=spaces[i]) ! 1260: p->next_pure_free = (char *) CNIL; ! 1261: } ! 1262: #endif ! 1263: } ! 1264: ! 1265: /** markit(p) ***********************************************************/ ! 1266: /* just calls markdp */ ! 1267: ! 1268: markit(p) lispval *p; { markdp(*p); } ! 1269: ! 1270: /* ! 1271: * markdp(p) ! 1272: * ! 1273: * markdp is the routine which marks each data item. If it is a ! 1274: * dotted pair, the car and cdr are marked also. ! 1275: * An iterative method is used to mark list structure, to avoid ! 1276: * excessive recursion. ! 1277: */ ! 1278: markdp(p) register lispval p; ! 1279: { ! 1280: /* register int r, s; (goes with non-asm readbit, oksetbit) */ ! 1281: /* register hsize, hcntr; */ ! 1282: int hsize, hcntr; ! 1283: ! 1284: #ifdef METER ! 1285: markdpcount++; ! 1286: #endif ! 1287: ptr_loop: ! 1288: if(((int)p) <= ((int)nil)) return; /* do not mark special data types or nil=0 */ ! 1289: ! 1290: ! 1291: switch( TYPE(p) ) ! 1292: { ! 1293: case ATOM: ! 1294: ftstbit; ! 1295: MARKVAL(p->a.clb); ! 1296: MARKVAL(p->a.plist); ! 1297: MARKVAL(p->a.fnbnd); ! 1298: #ifdef GCSTRINGS ! 1299: if(gcstrings) MARKVAL(((lispval)p->a.pname)); ! 1300: return; ! 1301: ! 1302: case STRNG: ! 1303: p = (lispval) (((int) p) & ~ (LBPG-1)); ! 1304: ftstbit; ! 1305: #endif ! 1306: return; ! 1307: ! 1308: case INT: ! 1309: case DOUB: ! 1310: ftstbit; ! 1311: return; ! 1312: case VALUE: ! 1313: ftstbit; ! 1314: p = p->l; ! 1315: goto ptr_loop; ! 1316: case DTPR: ! 1317: ftstbit; ! 1318: MARKVAL(p->d.car); ! 1319: #ifdef METER ! 1320: /* if we are metering , then check if the cdr is ! 1321: * nil, or if the cdr is on the same page, and if ! 1322: * it isn't one of those, then it is on a different ! 1323: * page ! 1324: */ ! 1325: if(gcstat) ! 1326: { ! 1327: if(p->d.cdr == nil) consnil++; ! 1328: else if(((int)p & ~511) ! 1329: == (((int)(p->d.cdr)) & ~511)) ! 1330: conssame++; ! 1331: else consdiff++; ! 1332: } ! 1333: #endif ! 1334: p = p->d.cdr; ! 1335: goto ptr_loop; ! 1336: ! 1337: case ARRAY: ! 1338: ftstbit; /* mark array itself */ ! 1339: ! 1340: MARKVAL(p->ar.accfun); /* mark access function */ ! 1341: MARKVAL(p->ar.aux); /* mark aux data */ ! 1342: MARKVAL(p->ar.length); /* mark length */ ! 1343: MARKVAL(p->ar.delta); /* mark delta */ ! 1344: if(TYPE(p->ar.aux)==DTPR && p->ar.aux->d.car==Vnogbar) ! 1345: { ! 1346: /* a non garbage collected array must have its ! 1347: * array space marked but the value of the array ! 1348: * space is not marked ! 1349: */ ! 1350: int l; ! 1351: int cnt,d; ! 1352: if(debugin && FALSE) { ! 1353: printf("mark array holders len %d, del %d, start 0x%x\n", ! 1354: p->ar.length->i,p->ar.delta->i,p->ar.data); ! 1355: fflush(stdout); ! 1356: } ! 1357: l = p->ar.length->i; /* number of elements */ ! 1358: d = p->ar.delta->i; /* bytes per element */ ! 1359: p = (lispval) p->ar.data;/* address of first one*/ ! 1360: if(purepage[ATOX(p)]) return; ! 1361: ! 1362: for((cnt = 0); cnt<l ; ! 1363: p = (lispval)(((char *) p) + d), cnt++) ! 1364: { ! 1365: setbit; ! 1366: } ! 1367: } else { ! 1368: /* register int i, l; int d; */ ! 1369: /* register char *dataptr = p->ar.data; */ ! 1370: int i,l,d; ! 1371: char *dataptr = p->ar.data; ! 1372: ! 1373: for(i=0, l=p->ar.length->i, d=p->ar.delta->i; i<l; ++i) ! 1374: { ! 1375: markdp((lispval)dataptr); ! 1376: dataptr += d; ! 1377: } ! 1378: } ! 1379: return; ! 1380: case SDOT: ! 1381: do { ! 1382: ftstbit; ! 1383: p = p->s.CDR; ! 1384: } while (p!=0); ! 1385: return; ! 1386: ! 1387: case BCD: ! 1388: ftstbit; ! 1389: markdp(p->bcd.discipline); ! 1390: return; ! 1391: ! 1392: case HUNK2: ! 1393: case HUNK4: ! 1394: case HUNK8: ! 1395: case HUNK16: ! 1396: case HUNK32: ! 1397: case HUNK64: ! 1398: case HUNK128: ! 1399: { ! 1400: hsize = 2 << HUNKSIZE(p); ! 1401: ftstbit; ! 1402: for (hcntr = 0; hcntr < hsize; hcntr++) ! 1403: MARKVAL(p->h.hunk[hcntr]); ! 1404: return; ! 1405: } ! 1406: ! 1407: case VECTORI: ! 1408: ftstbit; ! 1409: MARKVAL(p->v.vector[-1]); /* mark property */ ! 1410: return; ! 1411: ! 1412: case VECTOR: ! 1413: { ! 1414: register int vsize; ! 1415: ftstbit; ! 1416: vsize = VecSize(p->vl.vectorl[VSizeOff]); ! 1417: if(debugin) ! 1418: fprintf(stderr,"mark vect at %x size %d\n", ! 1419: p,vsize); ! 1420: while(--vsize >= -1) ! 1421: { ! 1422: MARKVAL(p->v.vector[vsize]); ! 1423: }; ! 1424: return; ! 1425: } ! 1426: } ! 1427: return; ! 1428: } ! 1429: ! 1430: ! 1431: /* xsbrk allocates space in large chunks (currently 16 pages) ! 1432: * xsbrk(1) returns a pointer to a page ! 1433: * xsbrk(0) returns a pointer to the next page we will allocate (like sbrk(0)) ! 1434: */ ! 1435: ! 1436: char * ! 1437: xsbrk(n) ! 1438: { ! 1439: static char *xx; /* pointer to next available blank page */ ! 1440: extern int xcycle; /* number of blank pages available */ ! 1441: lispval u; /* used to compute limits of bit table */ ! 1442: ! 1443: if( (xcycle--) <= 0 ) ! 1444: { ! 1445: xcycle = 15; ! 1446: xx = sbrk(16*LBPG); /* get pages 16 at a time */ ! 1447: if( (int)xx== -1 ) ! 1448: lispend("For sbrk from lisp: no space... Goodbye!"); ! 1449: } ! 1450: else xx += LBPG; ! 1451: ! 1452: if(n == 0) ! 1453: { ! 1454: xcycle++; /* don't allocate the page */ ! 1455: xx -= LBPG; ! 1456: return(xx); /* just return its address */ ! 1457: } ! 1458: ! 1459: if( (u = (lispval)(xx+LBPG)) > datalim ) datalim = u; ! 1460: return(xx); ! 1461: } ! 1462: ! 1463: char *ysbrk(pages,type) int pages, type; ! 1464: { ! 1465: char *xx; /* will point to block of storage */ ! 1466: int i; ! 1467: ! 1468: xx = sbrk(pages*LBPG); ! 1469: if((int)xx == -1) ! 1470: error("OUT OF SPACE FOR ARRAY REQUEST",FALSE); ! 1471: ! 1472: datalim = (lispval)(xx+pages*LBPG); /* compute bit table limit */ ! 1473: ! 1474: /* set type for pages */ ! 1475: ! 1476: for(i = 0; i < pages; ++i) { ! 1477: SETTYPE((xx + i*LBPG),type,10); ! 1478: } ! 1479: ! 1480: return(xx); /* return pointer to block of storage */ ! 1481: } ! 1482: ! 1483: /* ! 1484: * getatom ! 1485: * returns either an existing atom with the name specified in strbuf, or ! 1486: * if the atom does not already exist, regurgitates a new one and ! 1487: * returns it. ! 1488: */ ! 1489: lispval ! 1490: getatom(purep) ! 1491: { register lispval aptr; ! 1492: register char *name, *endname; ! 1493: register int hash; ! 1494: lispval b; ! 1495: char c; ! 1496: ! 1497: name = strbuf; ! 1498: if (*name == (char)0377) return (eofa); ! 1499: hash = hashfcn(name); ! 1500: atmlen = strlen(name) + 1; ! 1501: aptr = (lispval) hasht[hash]; ! 1502: while (aptr != CNIL) ! 1503: if (strcmp(name,aptr->a.pname)==0) ! 1504: return (aptr); ! 1505: else ! 1506: aptr = (lispval) aptr->a.hshlnk; ! 1507: aptr = (lispval) newatom(purep); /*share pname of atoms on oblist*/ ! 1508: aptr->a.hshlnk = hasht[hash]; ! 1509: hasht[hash] = (struct atom *) aptr; ! 1510: endname = name + atmlen - 2; ! 1511: if ((atmlen != 4) && (*name == 'c') && (*endname == 'r')) ! 1512: { ! 1513: b = newdot(); ! 1514: protect(b); ! 1515: b->d.car = lambda; ! 1516: b->d.cdr = newdot(); ! 1517: b = b->d.cdr; ! 1518: b->d.car = newdot(); ! 1519: (b->d.car)->d.car = xatom; ! 1520: while(TRUE) ! 1521: { ! 1522: b->d.cdr = newdot(); ! 1523: b= b->d.cdr; ! 1524: if(++name == endname) ! 1525: { ! 1526: b->d.car= (lispval) xatom; ! 1527: aptr->a.fnbnd = (--np)->val; ! 1528: break; ! 1529: } ! 1530: b->d.car= newdot(); ! 1531: b= b->d.car; ! 1532: if((c = *name) == 'a') b->d.car = cara; ! 1533: else if (c == 'd') b->d.car = cdra; ! 1534: else{ --np; ! 1535: break; ! 1536: } ! 1537: } ! 1538: } ! 1539: ! 1540: return(aptr); ! 1541: } ! 1542: ! 1543: /* our hash function */ ! 1544: ! 1545: hashfcn(symb) ! 1546: register char *symb; ! 1547: { ! 1548: register int i; ! 1549: for (i=0 ; *symb ; i += i + *symb++); ! 1550: return(i & (HASHTOP-1)); ! 1551: } ! 1552: ! 1553: lispval ! 1554: LImemory() ! 1555: { ! 1556: int nextadr, pagesinuse; ! 1557: ! 1558: printf("Memory report. max pages = %d (0x%x) = %d Bytes\n", ! 1559: TTSIZE,TTSIZE,TTSIZE*LBPG); ! 1560: #ifdef HOLE ! 1561: printf("This lisp has a hole:\n"); ! 1562: printf(" current hole start: %d (0x%x), end %d (0x%x)\n", ! 1563: curhbeg, curhbeg, holend, holend); ! 1564: printf(" hole free: %d bytes = %d pages\n\n", ! 1565: holend-curhbeg, (holend-curhbeg)/LBPG); ! 1566: #endif ! 1567: nextadr = (int) xsbrk(0); /* next space to be allocated */ ! 1568: pagesinuse = nextadr/LBPG; ! 1569: printf("Next allocation at addr %d (0x%x) = page %d\n", ! 1570: nextadr, nextadr, pagesinuse); ! 1571: printf("Free data pages: %d\n", TTSIZE-pagesinuse); ! 1572: return(nil); ! 1573: } ! 1574: ! 1575: extern struct atom *hasht[HASHTOP]; ! 1576: myhook(){}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.