|
|
1.1 ! root 1: /* Storage allocation and gc for GNU Emacs Lisp interpreter. ! 2: Copyright (C) 1985 Richard M. Stallman. ! 3: ! 4: This file is part of GNU Emacs. ! 5: ! 6: GNU Emacs is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU Emacs General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU Emacs, but only under the conditions described in the ! 15: GNU Emacs General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU Emacs so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: #include "config.h" ! 23: ! 24: /* Number of bytes of consing done since the last gc */ ! 25: int consing_since_gc; ! 26: ! 27: /* Number of bytes of consing since gc before another gc should be done. */ ! 28: int gc_cons_threshold; ! 29: ! 30: /* Nonzero during gc */ ! 31: int gc_in_progress; ! 32: ! 33: #ifndef VIRT_ADDR_VARIES ! 34: /* Address below which pointers should not be traced */ ! 35: extern char edata[]; ! 36: #endif /* VIRT_ADDR_VARIES */ ! 37: ! 38: #ifndef VIRT_ADDR_VARIES ! 39: extern ! 40: #endif /* VIRT_ADDR_VARIES */ ! 41: int malloc_sbrk_used; ! 42: ! 43: #ifndef VIRT_ADDR_VARIES ! 44: extern ! 45: #endif /* VIRT_ADDR_VARIES */ ! 46: int malloc_sbrk_unused; ! 47: ! 48: /* Non-nil means defun should do purecopy on the function definition */ ! 49: Lisp_Object Vpurify_flag; ! 50: ! 51: int pure[PURESIZE / sizeof (int)] = {0,}; /* Force it into data space! */ ! 52: ! 53: #define PUREBEG (char *) pure ! 54: ! 55: /* Index in pure at which next pure object will be allocated. */ ! 56: int pureptr; ! 57: ! 58: Lisp_Object ! 59: malloc_warning_1 (str) ! 60: Lisp_Object str; ! 61: { ! 62: return Fprinc (str, Vstandard_output); ! 63: } ! 64: ! 65: /* malloc calls this if it finds we are near exhausting storage */ ! 66: malloc_warning (str) ! 67: char *str; ! 68: { ! 69: Lisp_Object val; ! 70: val = build_string (str); ! 71: internal_with_output_to_temp_buffer (" *Danger*", malloc_warning_1, val); ! 72: } ! 73: ! 74: /* Called if malloc returns zero */ ! 75: memory_full () ! 76: { ! 77: error ("Memory exhausted"); ! 78: } ! 79: ! 80: /* like malloc and realloc but check for no memory left */ ! 81: ! 82: long * ! 83: xmalloc (size) ! 84: int size; ! 85: { ! 86: long *val = (long *) malloc (size); ! 87: if (!val) memory_full (); ! 88: return val; ! 89: } ! 90: ! 91: long * ! 92: xrealloc (block, size) ! 93: long *block; ! 94: int size; ! 95: { ! 96: long *val = (long *) realloc (block, size); ! 97: if (!val) memory_full (); ! 98: return val; ! 99: } ! 100: ! 101: /* Allocation of cons cells */ ! 102: /* We store cons cells inside of cons_blocks, allocating a new ! 103: cons_block with malloc whenever necessary. Cons cells reclaimed by ! 104: GC are put on a free list to be reallocated before allocating ! 105: any new cons cells from the latest cons_block. ! 106: ! 107: Each cons_block is just under 1020 bytes long, ! 108: since malloc really allocates in units of powers of two ! 109: and uses 4 bytes for its own overhead. */ ! 110: ! 111: #define CONS_BLOCK_SIZE \ ! 112: ((1020 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons)) ! 113: ! 114: struct cons_block ! 115: { ! 116: struct cons_block *next; ! 117: struct Lisp_Cons conses[CONS_BLOCK_SIZE]; ! 118: }; ! 119: ! 120: struct cons_block *cons_block; ! 121: int cons_block_index; ! 122: ! 123: struct Lisp_Cons *cons_free_list; ! 124: ! 125: void ! 126: init_cons () ! 127: { ! 128: cons_block = (struct cons_block *) malloc (sizeof (struct cons_block)); ! 129: cons_block->next = 0; ! 130: bzero (cons_block->conses, sizeof cons_block->conses); ! 131: cons_block_index = 0; ! 132: cons_free_list = 0; ! 133: } ! 134: ! 135: /* Explicitly free a cons cell. */ ! 136: free_cons (ptr) ! 137: struct Lisp_Cons *ptr; ! 138: { ! 139: XSETCONS (ptr->car, cons_free_list); ! 140: cons_free_list = ptr; ! 141: } ! 142: ! 143: DEFUN ("cons", Fcons, Scons, 2, 2, 0, ! 144: "Create a new cons, give it CAR and CDR as components, and return it.") ! 145: (car, cdr) ! 146: Lisp_Object car, cdr; ! 147: { ! 148: register Lisp_Object val; ! 149: ! 150: if (cons_free_list) ! 151: { ! 152: XSET (val, Lisp_Cons, cons_free_list); ! 153: cons_free_list = XCONS (cons_free_list->car); ! 154: } ! 155: else ! 156: { ! 157: if (cons_block_index == CONS_BLOCK_SIZE) ! 158: { ! 159: register struct cons_block *new = (struct cons_block *) malloc (sizeof (struct cons_block)); ! 160: if (!new) memory_full (); ! 161: new->next = cons_block; ! 162: cons_block = new; ! 163: cons_block_index = 0; ! 164: } ! 165: XSET (val, Lisp_Cons, &cons_block->conses[cons_block_index++]); ! 166: } ! 167: XCONS (val)->car = car; ! 168: XCONS (val)->cdr = cdr; ! 169: consing_since_gc += sizeof (struct Lisp_Cons); ! 170: return val; ! 171: } ! 172: ! 173: DEFUN ("list", Flist, Slist, 0, MANY, 0, ! 174: "Return a newly created list whose elements are the arguments (any number).") ! 175: (nargs, args) ! 176: int nargs; ! 177: Lisp_Object *args; ! 178: { ! 179: Lisp_Object len, val, val_tail; ! 180: ! 181: XFASTINT (len) = nargs; ! 182: val = Fmake_list (len, Qnil); ! 183: val_tail = val; ! 184: while (!NULL (val_tail)) ! 185: { ! 186: XCONS (val_tail)->car = *args++; ! 187: val_tail = XCONS (val_tail)->cdr; ! 188: } ! 189: return val; ! 190: } ! 191: ! 192: DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, ! 193: "Return a newly created list of length LENGTH, with each element being INIT.") ! 194: (length, init) ! 195: Lisp_Object length, init; ! 196: { ! 197: register Lisp_Object val; ! 198: register int size; ! 199: ! 200: if (XTYPE (length) != Lisp_Int || XINT (length) < 0) ! 201: length = wrong_type_argument (Qnatnump, length); ! 202: size = XINT (length); ! 203: ! 204: val = Qnil; ! 205: while (size-- > 0) ! 206: val = Fcons (init, val); ! 207: return val; ! 208: } ! 209: ! 210: /* Allocation of vectors */ ! 211: ! 212: struct Lisp_Vector *all_vectors; ! 213: ! 214: DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, ! 215: "Return a newly created vector of length LENGTH, with each element being INIT.") ! 216: (length, init) ! 217: Lisp_Object length, init; ! 218: { ! 219: register int sizei, index; ! 220: register Lisp_Object vector; ! 221: ! 222: if (XTYPE (length) != Lisp_Int || XINT (length) < 0) ! 223: length = wrong_type_argument (Qnatnump, length); ! 224: sizei = XINT (length); ! 225: ! 226: XSET (vector, Lisp_Vector, ! 227: (struct Lisp_Vector *) malloc (sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object))); ! 228: consing_since_gc += sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object); ! 229: if (!XVECTOR (vector)) ! 230: memory_full (); ! 231: ! 232: XVECTOR (vector)->size = sizei; ! 233: XVECTOR (vector)->next = all_vectors; ! 234: all_vectors = XVECTOR (vector); ! 235: ! 236: for (index = 0; index < sizei; index++) ! 237: XVECTOR (vector)->contents[index] = init; ! 238: ! 239: return vector; ! 240: } ! 241: ! 242: DEFUN ("vector", Fvector, Svector, 0, MANY, 0, ! 243: "Return a newly created vector with our arguments (any number) as its elements.") ! 244: (nargs, args) ! 245: int nargs; ! 246: Lisp_Object *args; ! 247: { ! 248: register Lisp_Object len, val; ! 249: register int index; ! 250: register struct Lisp_Vector *p; ! 251: ! 252: XFASTINT (len) = nargs; ! 253: val = Fmake_vector (len, Qnil); ! 254: p = XVECTOR (val); ! 255: for (index = 0; index < nargs; index++) ! 256: p->contents[index] = args[index]; ! 257: return val; ! 258: } ! 259: ! 260: /* Allocation of symbols. ! 261: Just like allocation of conses! ! 262: ! 263: Each symbol_block is just under 1020 bytes long, ! 264: since malloc really allocates in units of powers of two ! 265: and uses 4 bytes for its own overhead. */ ! 266: ! 267: #define SYMBOL_BLOCK_SIZE \ ! 268: ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol)) ! 269: ! 270: struct symbol_block ! 271: { ! 272: struct symbol_block *next; ! 273: struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; ! 274: }; ! 275: ! 276: struct symbol_block *symbol_block; ! 277: int symbol_block_index; ! 278: ! 279: struct Lisp_Symbol *symbol_free_list; ! 280: ! 281: void ! 282: init_symbol () ! 283: { ! 284: symbol_block = (struct symbol_block *) malloc (sizeof (struct symbol_block)); ! 285: symbol_block->next = 0; ! 286: bzero (symbol_block->symbols, sizeof symbol_block->symbols); ! 287: symbol_block_index = 0; ! 288: symbol_free_list = 0; ! 289: } ! 290: ! 291: DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, ! 292: "Return a newly allocated uninterned symbol whose name is NAME.\n\ ! 293: Its value and function definition are void, and its property list is NIL.") ! 294: (str) ! 295: Lisp_Object str; ! 296: { ! 297: register Lisp_Object val; ! 298: ! 299: CHECK_STRING (str, 0); ! 300: ! 301: if (symbol_free_list) ! 302: { ! 303: XSET (val, Lisp_Symbol, symbol_free_list); ! 304: symbol_free_list = XSYMBOL (symbol_free_list->value); ! 305: } ! 306: else ! 307: { ! 308: if (symbol_block_index == SYMBOL_BLOCK_SIZE) ! 309: { ! 310: struct symbol_block *new = (struct symbol_block *) malloc (sizeof (struct symbol_block)); ! 311: if (!new) memory_full (); ! 312: new->next = symbol_block; ! 313: symbol_block = new; ! 314: symbol_block_index = 0; ! 315: } ! 316: XSET (val, Lisp_Symbol, &symbol_block->symbols[symbol_block_index++]); ! 317: } ! 318: XSYMBOL (val)->name = XSTRING (str); ! 319: XSYMBOL (val)->plist = Qnil; ! 320: XSYMBOL (val)->value = Qunbound; ! 321: XSYMBOL (val)->function = Qunbound; ! 322: XSYMBOL (val)->next = 0; ! 323: consing_since_gc += sizeof (struct Lisp_Symbol); ! 324: return val; ! 325: } ! 326: ! 327: /* Allocation of markers. ! 328: Works like allocation of conses. */ ! 329: ! 330: #define MARKER_BLOCK_SIZE \ ! 331: ((1020 - sizeof (struct marker_block *)) / sizeof (struct Lisp_Marker)) ! 332: ! 333: struct marker_block ! 334: { ! 335: struct marker_block *next; ! 336: struct Lisp_Marker markers[MARKER_BLOCK_SIZE]; ! 337: }; ! 338: ! 339: struct marker_block *marker_block; ! 340: int marker_block_index; ! 341: ! 342: struct Lisp_Marker *marker_free_list; ! 343: ! 344: void ! 345: init_marker () ! 346: { ! 347: marker_block = (struct marker_block *) malloc (sizeof (struct marker_block)); ! 348: marker_block->next = 0; ! 349: bzero (marker_block->markers, sizeof marker_block->markers); ! 350: marker_block_index = 0; ! 351: marker_free_list = 0; ! 352: } ! 353: ! 354: DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, ! 355: "Return a newly allocated marker which does not point at any place.") ! 356: () ! 357: { ! 358: register Lisp_Object val; ! 359: ! 360: if (marker_free_list) ! 361: { ! 362: XSET (val, Lisp_Marker, marker_free_list); ! 363: marker_free_list = XMARKER (marker_free_list->chain); ! 364: } ! 365: else ! 366: { ! 367: if (marker_block_index == MARKER_BLOCK_SIZE) ! 368: { ! 369: struct marker_block *new = (struct marker_block *) malloc (sizeof (struct marker_block)); ! 370: if (!new) memory_full (); ! 371: new->next = marker_block; ! 372: marker_block = new; ! 373: marker_block_index = 0; ! 374: } ! 375: XSET (val, Lisp_Marker, &marker_block->markers[marker_block_index++]); ! 376: } ! 377: XMARKER (val)->buffer = 0; ! 378: XMARKER (val)->bufpos = 0; ! 379: XMARKER (val)->modified = 0; ! 380: XMARKER (val)->chain = Qnil; ! 381: consing_since_gc += sizeof (struct Lisp_Marker); ! 382: return val; ! 383: } ! 384: ! 385: /* Allocation of strings */ ! 386: ! 387: /* Strings reside inside of string_blocks. The entire data of the string, ! 388: both the size and the contents, live in part of the `chars' component of a string_block. ! 389: The `pos' component is the index within `chars' of the first free byte */ ! 390: ! 391: /* String blocks contain this many bytes. ! 392: Power of 2, minus 4 for malloc overhead. */ ! 393: #define STRING_BLOCK_SIZE (8188 - sizeof (struct string_block_head)) ! 394: ! 395: /* A string bigger than this gets its own specially-made string block ! 396: if it doesn't fit in the current one. */ ! 397: #define STRING_BLOCK_OUTSIZE 1024 ! 398: ! 399: struct string_block_head ! 400: { ! 401: struct string_block *next; ! 402: int pos; ! 403: }; ! 404: ! 405: struct string_block ! 406: { ! 407: struct string_block *next; ! 408: int pos; ! 409: char chars[STRING_BLOCK_SIZE]; ! 410: }; ! 411: ! 412: /* This points to the string block we are now allocating strings in ! 413: which is also the beginning of the chain of all string blocks ever made */ ! 414: ! 415: struct string_block *current_string_block; ! 416: ! 417: void ! 418: init_strings () ! 419: { ! 420: current_string_block = (struct string_block *) malloc (sizeof (struct string_block)); ! 421: consing_since_gc += sizeof (struct string_block); ! 422: current_string_block->next = 0; ! 423: current_string_block->pos = 0; ! 424: } ! 425: ! 426: static Lisp_Object make_zero_string (); ! 427: ! 428: DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0, ! 429: "Return a newly created string of length LENGTH, with each element being INIT.\n\ ! 430: Both LENGTH and INIT must be numbers.") ! 431: (length, init) ! 432: Lisp_Object length, init; ! 433: { ! 434: if (XTYPE (length) != Lisp_Int || XINT (length) < 0) ! 435: length = wrong_type_argument (Qnatnump, length); ! 436: CHECK_NUMBER (init, 1); ! 437: return make_zero_string (XINT (length), XINT (init)); ! 438: } ! 439: ! 440: Lisp_Object ! 441: make_string (contents, length) ! 442: char *contents; ! 443: int length; ! 444: { ! 445: Lisp_Object val; ! 446: val = make_zero_string (length, 0); ! 447: bcopy (contents, XSTRING (val)->data, length); ! 448: return val; ! 449: } ! 450: ! 451: Lisp_Object ! 452: build_string (str) ! 453: char *str; ! 454: { ! 455: return make_string (str, strlen (str)); ! 456: } ! 457: ! 458: static Lisp_Object ! 459: make_zero_string (length, init) ! 460: int length; ! 461: register int init; ! 462: { ! 463: register Lisp_Object val; ! 464: register int fullsize = length + sizeof (int); ! 465: register unsigned char *p, *end; ! 466: ! 467: if (length < 0) abort (); ! 468: ! 469: /* Round `fullsize' up to multiple of size of int; also add one for terminating zero */ ! 470: fullsize += sizeof (int); ! 471: fullsize &= ~(sizeof (int) - 1); ! 472: ! 473: if (fullsize <= STRING_BLOCK_SIZE - current_string_block->pos) ! 474: /* This string can fit in the current string block */ ! 475: { ! 476: XSET (val, Lisp_String, ! 477: (struct Lisp_String *) (current_string_block->chars + current_string_block->pos)); ! 478: current_string_block->pos += fullsize; ! 479: } ! 480: else if (fullsize > STRING_BLOCK_OUTSIZE) ! 481: /* This string gets its own string block */ ! 482: { ! 483: struct string_block *new = (struct string_block *) malloc (sizeof (struct string_block_head) + fullsize); ! 484: if (!new) memory_full (); ! 485: consing_since_gc += sizeof (struct string_block_head) + fullsize; ! 486: new->pos = fullsize; ! 487: new->next = current_string_block->next; ! 488: current_string_block->next = new; ! 489: XSET (val, Lisp_String, ! 490: (struct Lisp_String *) ((struct string_block_head *)new + 1)); ! 491: } ! 492: else ! 493: /* Make a new current string block and start it off with this string */ ! 494: { ! 495: struct string_block *new = (struct string_block *) malloc (sizeof (struct string_block)); ! 496: if (!new) memory_full (); ! 497: consing_since_gc += sizeof (struct string_block); ! 498: new->next = current_string_block; ! 499: current_string_block = new; ! 500: new->pos = fullsize; ! 501: XSET (val, Lisp_String, ! 502: (struct Lisp_String *) current_string_block->chars); ! 503: } ! 504: ! 505: XSTRING (val)->size = length; ! 506: p = XSTRING (val)->data; ! 507: end = p + XSTRING (val)->size; ! 508: while (p != end) ! 509: *p++ = init; ! 510: *p = 0; ! 511: ! 512: return val; ! 513: } ! 514: ! 515: /* Must get an error if pure storage is full, ! 516: since if it cannot hold a large string ! 517: it may be able to hold conses that point to that string; ! 518: then the string is not protected from gc. */ ! 519: ! 520: Lisp_Object ! 521: make_pure_string (data, length) ! 522: char *data; ! 523: int length; ! 524: { ! 525: Lisp_Object new; ! 526: int size = sizeof (int) + length + 1; ! 527: ! 528: if (pureptr + size > PURESIZE) ! 529: error ("Pure Lisp storage exhausted"); ! 530: XSET (new, Lisp_String, PUREBEG + pureptr); ! 531: XSTRING (new)->size = length; ! 532: bcopy (data, XSTRING (new)->data, length); ! 533: XSTRING (new)->data[length] = 0; ! 534: pureptr += (size + sizeof (int) - 1) ! 535: / sizeof (int) * sizeof (int); ! 536: return new; ! 537: } ! 538: ! 539: Lisp_Object ! 540: pure_cons (car, cdr) ! 541: Lisp_Object car, cdr; ! 542: { ! 543: Lisp_Object new; ! 544: ! 545: if (pureptr + sizeof (struct Lisp_Cons) > PURESIZE) ! 546: error ("Pure Lisp storage exhausted"); ! 547: XSET (new, Lisp_Cons, PUREBEG + pureptr); ! 548: pureptr += sizeof (struct Lisp_Cons); ! 549: XCONS (new)->car = Fpurecopy (car); ! 550: XCONS (new)->cdr = Fpurecopy (cdr); ! 551: return new; ! 552: } ! 553: ! 554: Lisp_Object ! 555: make_pure_vector (len) ! 556: int len; ! 557: { ! 558: Lisp_Object new; ! 559: int size = sizeof (struct Lisp_Vector) + (len - 1) * sizeof (Lisp_Object); ! 560: ! 561: if (pureptr + size > PURESIZE) ! 562: error ("Pure Lisp storage exhausted"); ! 563: ! 564: XSET (new, Lisp_Vector, PUREBEG + pureptr); ! 565: pureptr += size; ! 566: XVECTOR (new)->size = len; ! 567: return new; ! 568: } ! 569: ! 570: DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, ! 571: "Make a copy of OBJECT in pure storage.\n\ ! 572: Recursively copies contents of vectors and cons cells.\n\ ! 573: Does not copy symbols.") ! 574: (obj) ! 575: Lisp_Object obj; ! 576: { ! 577: Lisp_Object new, tem; ! 578: int i; ! 579: ! 580: #ifndef VIRT_ADDR_VARIES ! 581: /* Need not trace pointers to pure storage */ ! 582: if (XUINT (obj) < (unsigned int) edata && XUINT (obj) >= 0) ! 583: return obj; ! 584: #else /* VIRT_ADDR_VARIES */ ! 585: if (XUINT (obj) < (unsigned int) ((char *) pure + PURESIZE) ! 586: && XUINT (obj) >= (unsigned int) pure) ! 587: return obj; ! 588: #endif /* VIRT_ADDR_VARIES */ ! 589: ! 590: #ifdef SWITCH_ENUM_BUG ! 591: switch ((int) XTYPE (obj)) ! 592: #else ! 593: switch (XTYPE (obj)) ! 594: #endif ! 595: { ! 596: case Lisp_Marker: ! 597: error ("Attempt to copy a marker to pure storage"); ! 598: ! 599: case Lisp_Cons: ! 600: return pure_cons (XCONS (obj)->car, XCONS (obj)->cdr); ! 601: ! 602: case Lisp_String: ! 603: return make_pure_string (XSTRING (obj)->data, XSTRING (obj)->size); ! 604: ! 605: case Lisp_Vector: ! 606: new = make_pure_vector (XVECTOR (obj)->size); ! 607: for (i = 0; i < XVECTOR (obj)->size; i++) ! 608: { ! 609: tem = XVECTOR (obj)->contents[i]; ! 610: XVECTOR (new)->contents[i] = Fpurecopy (tem); ! 611: } ! 612: return new; ! 613: ! 614: default: ! 615: return obj; ! 616: } ! 617: } ! 618: ! 619: /* Recording what needs to be marked for gc. */ ! 620: ! 621: struct gcpro *gcprolist; ! 622: ! 623: #define NSTATICS 100 ! 624: ! 625: char staticvec1[NSTATICS * sizeof (Lisp_Object *)] = {0}; ! 626: ! 627: int staticidx = 0; ! 628: ! 629: #define staticvec ((Lisp_Object **) staticvec1) ! 630: ! 631: /* Put an entry in staticvec, pointing at the variable whose address is given */ ! 632: ! 633: void ! 634: staticpro (varaddress) ! 635: Lisp_Object *varaddress; ! 636: { ! 637: staticvec[staticidx++] = varaddress; ! 638: if (staticidx >= NSTATICS) ! 639: abort (); ! 640: } ! 641: ! 642: struct catchtag ! 643: { ! 644: Lisp_Object tag; ! 645: Lisp_Object val; ! 646: struct catchtag *next; ! 647: /* jmp_buf jmp; /* We don't need this for GC purposes */ ! 648: }; ! 649: ! 650: extern struct catchtag *catchlist; ! 651: ! 652: struct backtrace ! 653: { ! 654: struct backtrace *next; ! 655: Lisp_Object *function; ! 656: Lisp_Object *args; /* Points to vector of args. */ ! 657: int nargs; /* length of vector */ ! 658: /* if nargs is UNEVALLED, args points to slot holding list of unevalled args */ ! 659: char evalargs; ! 660: }; ! 661: ! 662: extern struct backtrace *backtrace_list; ! 663: ! 664: /* On vector, means it has been marked. ! 665: On string, means it has been copied. */ ! 666: static int most_negative_fixnum; ! 667: ! 668: /* On string, means do not copy it. ! 669: This is set in all copies, and perhaps will be used ! 670: to indicate strings that there is no need to copy. */ ! 671: static int dont_copy_flag; ! 672: ! 673: int total_conses, total_markers, total_symbols, total_string_size, total_vector_size; ! 674: int total_free_conses, total_free_markers, total_free_symbols; ! 675: ! 676: /* Garbage collection: mark and sweep, except copy strings. */ ! 677: static Lisp_Object mark_object (); ! 678: static void clear_marks (), gc_sweep (); ! 679: ! 680: DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", ! 681: "Reclaim storage for Lisp objects no longer needed.\n\ ! 682: Returns info on amount of space in use:\n\ ! 683: ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\ ! 684: (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS)\n\ ! 685: Garbage collection happens automatically if you cons more than\n\ ! 686: gc-cons-threshold bytes of Lisp data since previous garbage collection.") ! 687: () ! 688: { ! 689: struct string_block *old_string_block; ! 690: ! 691: register struct gcpro *tail; ! 692: register struct specbinding *bind; ! 693: struct catchtag *catch; ! 694: struct handler *handler; ! 695: register struct backtrace *backlist; ! 696: register Lisp_Object tem; ! 697: char *omessage = minibuf_message; ! 698: ! 699: register int i; ! 700: ! 701: if (!noninteractive) ! 702: message1 ("Garbage collecting..."); ! 703: ! 704: /* Don't keep command history around forever */ ! 705: tem = Fnthcdr (make_number (30), Vcommand_history); ! 706: if (LISTP (tem)) ! 707: XCONS (tem)->cdr = Qnil; ! 708: ! 709: gc_in_progress = 1; ! 710: ! 711: clear_marks (); ! 712: old_string_block = current_string_block; ! 713: current_string_block = 0; ! 714: total_string_size = 0; ! 715: init_strings (); ! 716: ! 717: for (tail = gcprolist; tail; tail = tail->next) ! 718: { ! 719: for (i = 0; i < tail->nvars; i++) ! 720: { ! 721: tem = tail->var[i]; ! 722: tail->var[i] = mark_object (tem); ! 723: } ! 724: } ! 725: for (i = 0; i < staticidx; i++) ! 726: { ! 727: tem = *staticvec[i]; ! 728: *staticvec[i] = mark_object (tem); ! 729: } ! 730: for (bind = specpdl; bind != specpdl_ptr; bind++) ! 731: { ! 732: bind->symbol = mark_object (bind->symbol); ! 733: bind->old_value = mark_object (bind->old_value); ! 734: } ! 735: for (catch = catchlist; catch; catch = catch->next) ! 736: { ! 737: catch->tag = mark_object (catch->tag); ! 738: catch->val = mark_object (catch->val); ! 739: } ! 740: for (handler = handlerlist; handler; handler = handler->next) ! 741: { ! 742: handler->handler = mark_object (handler->handler); ! 743: handler->var = mark_object (handler->var); ! 744: } ! 745: for (backlist = backtrace_list; backlist; backlist = backlist->next) ! 746: { ! 747: tem = *backlist->function; ! 748: *backlist->function = mark_object (tem); ! 749: if (backlist->nargs == UNEVALLED || backlist->nargs == MANY) ! 750: { ! 751: tem = *backlist->args; ! 752: *backlist->args = mark_object (tem); ! 753: } ! 754: else ! 755: for (i = 0; i < backlist->nargs; i++) ! 756: { ! 757: tem = backlist->args[i]; ! 758: backlist->args[i] = mark_object (tem); ! 759: } ! 760: } ! 761: ! 762: gc_sweep (old_string_block); ! 763: ! 764: clear_marks (); ! 765: gc_in_progress = 0; ! 766: ! 767: consing_since_gc = 0; ! 768: if (gc_cons_threshold < 10000) ! 769: gc_cons_threshold = 10000; ! 770: ! 771: if (omessage) ! 772: message1 (omessage); ! 773: else if (!noninteractive) ! 774: message1 ("Garbage collecting...done"); ! 775: ! 776: return Fcons (Fcons (make_number (total_conses), ! 777: make_number (total_free_conses)), ! 778: Fcons (Fcons (make_number (total_symbols), ! 779: make_number (total_free_symbols)), ! 780: Fcons (Fcons (make_number (total_markers), ! 781: make_number (total_free_markers)), ! 782: Fcons (make_number (total_string_size), ! 783: Fcons (make_number (total_vector_size), ! 784: Qnil))))); ! 785: } ! 786: ! 787: static void ! 788: clear_marks () ! 789: { ! 790: /* Clear marks on all strings */ ! 791: { ! 792: register struct string_block *csb; ! 793: register int pos; ! 794: ! 795: for (csb = current_string_block; csb; csb = csb->next) ! 796: { ! 797: pos = 0; ! 798: while (pos < csb->pos) ! 799: { ! 800: register struct Lisp_String *nextstr ! 801: = (struct Lisp_String *) &csb->chars[pos]; ! 802: register int fullsize; ! 803: ! 804: nextstr->size &= ~dont_copy_flag; ! 805: fullsize = nextstr->size + sizeof (int); ! 806: ! 807: fullsize += sizeof (int); ! 808: fullsize &= ~(sizeof (int) - 1); ! 809: pos += fullsize; ! 810: } ! 811: } ! 812: } ! 813: /* Clear marks on all conses */ ! 814: { ! 815: register struct cons_block *cblk; ! 816: register int lim = cons_block_index; ! 817: ! 818: for (cblk = cons_block; cblk; cblk = cblk->next) ! 819: { ! 820: register int i; ! 821: for (i = 0; i < lim; i++) ! 822: XUNMARK (cblk->conses[i].car); ! 823: lim = CONS_BLOCK_SIZE; ! 824: } ! 825: } ! 826: /* Clear marks on all symbols */ ! 827: { ! 828: register struct symbol_block *sblk; ! 829: register int lim = symbol_block_index; ! 830: ! 831: for (sblk = symbol_block; sblk; sblk = sblk->next) ! 832: { ! 833: register int i; ! 834: for (i = 0; i < lim; i++) ! 835: XUNMARK (sblk->symbols[i].plist); ! 836: lim = SYMBOL_BLOCK_SIZE; ! 837: } ! 838: } ! 839: /* Clear marks on all markers */ ! 840: { ! 841: register struct marker_block *sblk; ! 842: register int lim = marker_block_index; ! 843: ! 844: for (sblk = marker_block; sblk; sblk = sblk->next) ! 845: { ! 846: register int i; ! 847: for (i = 0; i < lim; i++) ! 848: XUNMARK (sblk->markers[i].chain); ! 849: lim = MARKER_BLOCK_SIZE; ! 850: } ! 851: } ! 852: /* Clear mark bits on all buffers */ ! 853: { ! 854: register struct buffer *nextb = all_buffers; ! 855: ! 856: while (nextb) ! 857: { ! 858: XUNMARK (nextb->name); ! 859: nextb = nextb->next; ! 860: } ! 861: } ! 862: } ! 863: ! 864: /* Mark one Lisp object, and recursively mark all the objects it points to ! 865: if this is the first time it is being marked. ! 866: If the object is a string, it is copied (once, only) and the copy is returned. ! 867: The original string's `size' is set to a value in which 1<<31 is set ! 868: and the rest of which is the string address shifted right by one. ! 869: If the object is not a string, it is returned unchanged. */ ! 870: ! 871: static Lisp_Object ! 872: mark_object (obj) ! 873: Lisp_Object obj; ! 874: { ! 875: Lisp_Object original; ! 876: ! 877: original = obj; ! 878: ! 879: loop: ! 880: #ifndef VIRT_ADDR_VARIES ! 881: /* Need not trace pointers to pure storage */ ! 882: if (XUINT (obj) < (unsigned int) edata && XUINT (obj) >= 0) ! 883: return original; ! 884: #else /* VIRT_ADDR_VARIES */ ! 885: if (XUINT (obj) < (unsigned int) ((char *) pure + PURESIZE) ! 886: && XUINT (obj) >= (unsigned int) pure) ! 887: return original; ! 888: #endif /* VIRT_ADDR_VARIES */ ! 889: ! 890: #ifdef SWITCH_ENUM_BUG ! 891: switch ((int) XGCTYPE (obj)) ! 892: #else ! 893: switch (XGCTYPE (obj)) ! 894: #endif ! 895: { ! 896: case Lisp_String: ! 897: { ! 898: register struct Lisp_String *ptr = XSTRING (obj); ! 899: Lisp_Object tem; ! 900: ! 901: if (ptr->size & most_negative_fixnum) ! 902: { ! 903: XSETSTRING (obj, (struct Lisp_String *) (ptr->size & ~most_negative_fixnum)); ! 904: return obj; ! 905: } ! 906: if (ptr->size & dont_copy_flag) ! 907: return obj; ! 908: total_string_size += ptr->size; ! 909: tem = make_string (ptr->data, ptr->size); ! 910: ptr->size = most_negative_fixnum | XINT (tem); ! 911: XSTRING (tem)->size |= dont_copy_flag; ! 912: return tem; ! 913: } ! 914: ! 915: case Lisp_Vector: ! 916: case Lisp_Window: ! 917: case Lisp_Process: ! 918: { ! 919: register struct Lisp_Vector *ptr = XVECTOR (obj); ! 920: register int size = ptr->size; ! 921: register int i; ! 922: Lisp_Object tem; ! 923: ! 924: if (size & most_negative_fixnum) break; /* Already marked */ ! 925: ptr->size |= most_negative_fixnum; /* Else mark it */ ! 926: for (i = 0; i < size; i++) /* and then mark its elements */ ! 927: { ! 928: tem = ptr->contents[i]; ! 929: ptr->contents[i] = mark_object (tem); ! 930: } ! 931: } ! 932: break; ! 933: ! 934: case Lisp_Temp_Vector: ! 935: { ! 936: register struct Lisp_Vector *ptr = XVECTOR (obj); ! 937: register int size = ptr->size; ! 938: register int i; ! 939: Lisp_Object tem; ! 940: ! 941: for (i = 0; i < size; i++) /* and then mark its elements */ ! 942: { ! 943: tem = ptr->contents[i]; ! 944: ptr->contents[i] = mark_object (tem); ! 945: } ! 946: } ! 947: break; ! 948: ! 949: case Lisp_Symbol: ! 950: { ! 951: register struct Lisp_Symbol *ptr = XSYMBOL (obj); ! 952: struct Lisp_Symbol *ptrx; ! 953: Lisp_Object tem; ! 954: ! 955: if (XMARKBIT (ptr->plist)) break; ! 956: XMARK (ptr->plist); ! 957: XSET (tem, Lisp_String, ptr->name); ! 958: tem = mark_object (tem); ! 959: ptr->name = XSTRING (tem); ! 960: ptr->value = mark_object (ptr->value); ! 961: ptr->function = mark_object (ptr->function); ! 962: tem = ptr->plist; ! 963: XUNMARK (tem); ! 964: ptr->plist = mark_object (tem); ! 965: XMARK (ptr->plist); ! 966: ptr = ptr->next; ! 967: if (ptr) ! 968: { ! 969: ptrx = ptr; /* Use pf ptrx avoids compiled bug on Sun */ ! 970: XSETSYMBOL (obj, ptrx); ! 971: goto loop; ! 972: } ! 973: } ! 974: break; ! 975: ! 976: case Lisp_Marker: ! 977: XMARK (XMARKER (obj)->chain); ! 978: /* DO NOT mark thru the marker's chain. ! 979: The buffer's markers chain does not preserve markers from gc; ! 980: instead, markers are removed from the chain when they are freed by gc. */ ! 981: break; ! 982: ! 983: case Lisp_Cons: ! 984: case Lisp_Buffer_Local_Value: ! 985: case Lisp_Some_Buffer_Local_Value: ! 986: { ! 987: Lisp_Object tem; ! 988: register struct Lisp_Cons *ptr = XCONS (obj); ! 989: if (XMARKBIT (ptr->car)) break; ! 990: tem = ptr->car; ! 991: XMARK (ptr->car); ! 992: ptr->car = mark_object (tem); ! 993: XMARK (ptr->car); ! 994: if (XGCTYPE (ptr->cdr) != Lisp_String) ! 995: { ! 996: obj = ptr->cdr; ! 997: goto loop; ! 998: } ! 999: ptr->cdr = mark_object (ptr->cdr); ! 1000: } ! 1001: break; ! 1002: ! 1003: case Lisp_Objfwd: ! 1004: *XOBJFWD (obj) = mark_object (*XOBJFWD (obj)); ! 1005: break; ! 1006: ! 1007: case Lisp_Buffer: ! 1008: if (!XMARKBIT (XBUFFER (obj)->name)) ! 1009: mark_buffer (obj); ! 1010: break; ! 1011: ! 1012: /* Don't bother with Lisp_Buffer_Objfwd, ! 1013: since all markable slots in current buffer marked anyway. */ ! 1014: } ! 1015: return original; ! 1016: } ! 1017: ! 1018: /* Mark the pointers in a buffer structure. */ ! 1019: ! 1020: mark_buffer (buf) ! 1021: Lisp_Object buf; ! 1022: { ! 1023: Lisp_Object tem; ! 1024: register struct buffer *buffer = XBUFFER (buf); ! 1025: ! 1026: buffer->number = mark_object (buffer->number); ! 1027: buffer->name = mark_object (buffer->name); ! 1028: XMARK (buffer->name); ! 1029: buffer->filename = mark_object (buffer->filename); ! 1030: buffer->directory = mark_object (buffer->directory); ! 1031: buffer->save_length = mark_object (buffer->save_length); ! 1032: buffer->auto_save_file_name = mark_object (buffer->auto_save_file_name); ! 1033: buffer->read_only = mark_object (buffer->read_only); ! 1034: /* buffer->markers does not preserve from gc: scavenger removes marker from ! 1035: the markers chain if it is freed. See gc_sweep */ ! 1036: buffer->mark = mark_object (buffer->mark); ! 1037: buffer->major_mode = mark_object (buffer->major_mode); ! 1038: buffer->mode_name = mark_object (buffer->mode_name); ! 1039: buffer->mode_line_format = mark_object (buffer->mode_line_format); ! 1040: buffer->keymap = mark_object (buffer->keymap); ! 1041: XSET (tem, Lisp_Vector, buffer->syntax_table_v); ! 1042: if (buffer->syntax_table_v) ! 1043: mark_object (tem); ! 1044: buffer->abbrev_table = mark_object (buffer->abbrev_table); ! 1045: buffer->case_fold_search = mark_object (buffer->case_fold_search); ! 1046: buffer->tab_width = mark_object (buffer->tab_width); ! 1047: buffer->fill_column = mark_object (buffer->fill_column); ! 1048: buffer->left_margin = mark_object (buffer->left_margin); ! 1049: buffer->auto_fill_hook = mark_object (buffer->auto_fill_hook); ! 1050: buffer->local_var_alist = mark_object (buffer->local_var_alist); ! 1051: buffer->truncate_lines = mark_object (buffer->truncate_lines); ! 1052: buffer->ctl_arrow = mark_object (buffer->ctl_arrow); ! 1053: buffer->selective_display = mark_object (buffer->selective_display); ! 1054: buffer->minor_modes = mark_object (buffer->minor_modes); ! 1055: buffer->overwrite_mode = mark_object (buffer->overwrite_mode); ! 1056: buffer->abbrev_mode = mark_object (buffer->abbrev_mode); ! 1057: ! 1058: } ! 1059: ! 1060: /* Find all structures not marked, and free them. */ ! 1061: ! 1062: static void ! 1063: gc_sweep (old_string_block) ! 1064: struct string_block *old_string_block; ! 1065: { ! 1066: /* Put all unmarked conses on free list */ ! 1067: { ! 1068: register struct cons_block *cblk; ! 1069: register int lim = cons_block_index; ! 1070: register int num_free = 0, num_used = 0; ! 1071: ! 1072: cons_free_list = 0; ! 1073: ! 1074: for (cblk = cons_block; cblk; cblk = cblk->next) ! 1075: { ! 1076: register int i; ! 1077: for (i = 0; i < lim; i++) ! 1078: if (!XMARKBIT (cblk->conses[i].car)) ! 1079: { ! 1080: XSETCONS (cblk->conses[i].car, cons_free_list); ! 1081: num_free++; ! 1082: cons_free_list = &cblk->conses[i]; ! 1083: } ! 1084: else num_used++; ! 1085: lim = CONS_BLOCK_SIZE; ! 1086: } ! 1087: total_conses = num_used; ! 1088: total_free_conses = num_free; ! 1089: } ! 1090: ! 1091: /* Put all unmarked symbols on free list */ ! 1092: { ! 1093: register struct symbol_block *sblk; ! 1094: register int lim = symbol_block_index; ! 1095: register int num_free = 0, num_used = 0; ! 1096: ! 1097: symbol_free_list = 0; ! 1098: ! 1099: for (sblk = symbol_block; sblk; sblk = sblk->next) ! 1100: { ! 1101: register int i; ! 1102: for (i = 0; i < lim; i++) ! 1103: if (!XMARKBIT (sblk->symbols[i].plist)) ! 1104: { ! 1105: XSETSYMBOL (sblk->symbols[i].value, symbol_free_list); ! 1106: symbol_free_list = &sblk->symbols[i]; ! 1107: num_free++; ! 1108: } ! 1109: else num_used++; ! 1110: lim = SYMBOL_BLOCK_SIZE; ! 1111: } ! 1112: total_symbols = num_used; ! 1113: total_free_symbols = num_free; ! 1114: } ! 1115: ! 1116: #ifndef standalone ! 1117: /* Put all unmarked markers on free list. ! 1118: Dechain each one first from the buffer it points into. */ ! 1119: { ! 1120: register struct marker_block *mblk; ! 1121: struct Lisp_Marker *tem1; ! 1122: register int lim = marker_block_index; ! 1123: register int num_free = 0, num_used = 0; ! 1124: ! 1125: marker_free_list = 0; ! 1126: ! 1127: for (mblk = marker_block; mblk; mblk = mblk->next) ! 1128: { ! 1129: register int i; ! 1130: for (i = 0; i < lim; i++) ! 1131: if (!XMARKBIT (mblk->markers[i].chain)) ! 1132: { ! 1133: Lisp_Object tem; ! 1134: tem1 = &mblk->markers[i]; /* tem1 avoids Sun compiler bug */ ! 1135: XSET (tem, Lisp_Marker, tem1); ! 1136: unchain_marker (tem); ! 1137: XSETMARKER (mblk->markers[i].chain, marker_free_list); ! 1138: marker_free_list = &mblk->markers[i]; ! 1139: num_free++; ! 1140: } ! 1141: else num_used++; ! 1142: lim = MARKER_BLOCK_SIZE; ! 1143: } ! 1144: ! 1145: total_markers = num_used; ! 1146: total_free_markers = num_free; ! 1147: } ! 1148: ! 1149: /* Free all unmarked buffers */ ! 1150: { ! 1151: register struct buffer *buffer = all_buffers, *prev = 0, *next = 0; ! 1152: ! 1153: while (buffer) ! 1154: if (!XMARKBIT (buffer->name)) ! 1155: { ! 1156: if (prev) ! 1157: prev->next = buffer->next; ! 1158: else ! 1159: all_buffers = buffer->next; ! 1160: next = buffer->next; ! 1161: free (buffer); ! 1162: buffer = next; ! 1163: } ! 1164: else ! 1165: { ! 1166: XUNMARK (buffer->name); ! 1167: prev = buffer, buffer = buffer->next; ! 1168: } ! 1169: } ! 1170: ! 1171: #endif standalone ! 1172: ! 1173: /* Free all unmarked vectors */ ! 1174: { ! 1175: register struct Lisp_Vector *vector = all_vectors, *prev = 0, *next = 0; ! 1176: total_vector_size = 0; ! 1177: ! 1178: while (vector) ! 1179: if (!(vector->size & most_negative_fixnum)) ! 1180: { ! 1181: if (prev) ! 1182: prev->next = vector->next; ! 1183: else ! 1184: all_vectors = vector->next; ! 1185: next = vector->next; ! 1186: free (vector); ! 1187: vector = next; ! 1188: } ! 1189: else ! 1190: { ! 1191: vector->size &= ~most_negative_fixnum; ! 1192: total_vector_size += vector->size; ! 1193: prev = vector, vector = vector->next; ! 1194: } ! 1195: } ! 1196: ! 1197: /* Free all old string blocks, since all strings still used have been copied. */ ! 1198: { ! 1199: register struct string_block *sblk = old_string_block; ! 1200: while (sblk) ! 1201: { ! 1202: struct string_block *next = sblk->next; ! 1203: free (sblk); ! 1204: sblk = next; ! 1205: } ! 1206: } ! 1207: } ! 1208: ! 1209: /* Initialization */ ! 1210: ! 1211: init_alloc_once () ! 1212: { ! 1213: register int i, x; ! 1214: /* Compute an int in which only the sign bit is set. */ ! 1215: for (i = 0, x = 1; (x <<= 1) & ~1; i++) ! 1216: /*empty loop*/; ! 1217: most_negative_fixnum = 1 << i; ! 1218: dont_copy_flag = 1 << (i - 1); ! 1219: ! 1220: Vpurify_flag = Qt; ! 1221: ! 1222: pureptr = 0; ! 1223: all_vectors = 0; ! 1224: init_strings (); ! 1225: init_cons (); ! 1226: init_symbol (); ! 1227: init_marker (); ! 1228: gcprolist = 0; ! 1229: staticidx = 0; ! 1230: consing_since_gc = 0; ! 1231: gc_cons_threshold = 100000; ! 1232: #ifdef VIRT_ADDR_VARIES ! 1233: malloc_sbrk_unused = 1<<22; /* A large number */ ! 1234: malloc_sbrk_used = 100000; /* as reasonable as any number */ ! 1235: #endif /* VIRT_ADDR_VARIES */ ! 1236: } ! 1237: ! 1238: init_alloc () ! 1239: { ! 1240: gcprolist = 0; ! 1241: } ! 1242: ! 1243: void ! 1244: syms_of_alloc () ! 1245: { ! 1246: DefIntVar ("gc-cons-threshold", &gc_cons_threshold, ! 1247: "*Number of bytes of consing between garbage collections."); ! 1248: ! 1249: DefIntVar ("pure-bytes-used", &pureptr, ! 1250: "Number of bytes of sharable Lisp data allocated so far."); ! 1251: ! 1252: DefIntVar ("data-bytes-used", &malloc_sbrk_used, ! 1253: "Number of bytes of unshared memory allocated in this session."); ! 1254: ! 1255: DefIntVar ("data-bytes-free", &malloc_sbrk_unused, ! 1256: "Number of bytes of unshared memory remaining available in this session."); ! 1257: ! 1258: DefLispVar ("purify-flag", &Vpurify_flag, ! 1259: "Non-nil means defun should purecopy the function definition."); ! 1260: ! 1261: defsubr (&Scons); ! 1262: defsubr (&Slist); ! 1263: defsubr (&Svector); ! 1264: defsubr (&Smake_list); ! 1265: defsubr (&Smake_vector); ! 1266: defsubr (&Smake_string); ! 1267: defsubr (&Smake_symbol); ! 1268: defsubr (&Smake_marker); ! 1269: defsubr (&Spurecopy); ! 1270: defsubr (&Sgarbage_collect); ! 1271: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.