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