|
|
1.1 ! root 1: /* Storage allocation and gc for GNU Emacs Lisp interpreter. ! 2: Copyright (C) 1985, 1986 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU Emacs. ! 5: ! 6: GNU Emacs is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GNU Emacs is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU Emacs; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include "config.h" ! 22: #include "lisp.h" ! 23: #ifndef standalone ! 24: #include "buffer.h" ! 25: #include "window.h" ! 26: #endif ! 27: ! 28: #define max(A,B) ((A) > (B) ? (A) : (B)) ! 29: ! 30: /* Macro to verify that storage intended for Lisp objects is not ! 31: out of range to fit in the space for a pointer. ! 32: ADDRESS is the start of the block, and SIZE ! 33: is the amount of space within which objects can start. */ ! 34: #define VALIDATE_LISP_STORAGE(address, size) \ ! 35: do \ ! 36: { \ ! 37: Lisp_Object val; \ ! 38: XSET (val, Lisp_Cons, (char *) address + size); \ ! 39: if ((char *) XCONS (val) != (char *) address + size) \ ! 40: { \ ! 41: free (address); \ ! 42: memory_full (); \ ! 43: } \ ! 44: } while (0) ! 45: ! 46: /* Number of bytes of consing done since the last gc */ ! 47: int consing_since_gc; ! 48: ! 49: /* Number of bytes of consing since gc before another gc should be done. */ ! 50: int gc_cons_threshold; ! 51: ! 52: /* value of consing_since_gc when undos were last truncated. */ ! 53: int consing_at_last_truncate; ! 54: ! 55: /* Nonzero during gc */ ! 56: int gc_in_progress; ! 57: ! 58: #ifndef VIRT_ADDR_VARIES ! 59: extern ! 60: #endif /* VIRT_ADDR_VARIES */ ! 61: int malloc_sbrk_used; ! 62: ! 63: #ifndef VIRT_ADDR_VARIES ! 64: extern ! 65: #endif /* VIRT_ADDR_VARIES */ ! 66: int malloc_sbrk_unused; ! 67: ! 68: /* Two thresholds controlling how much undo information to keep. */ ! 69: int undo_threshold; ! 70: int undo_high_threshold; ! 71: ! 72: /* Non-nil means defun should do purecopy on the function definition */ ! 73: Lisp_Object Vpurify_flag; ! 74: ! 75: /* Argument we give to Fsignal when memory is full. ! 76: Preallocated since perhaps we can't allocate it when memory is full. */ ! 77: Lisp_Object memory_exhausted_message; ! 78: ! 79: #ifndef HAVE_SHM ! 80: #ifdef VMS ! 81: int pure[PURESIZE / sizeof (int)]; /*no need to initialize - wasted space*/ ! 82: #else ! 83: int pure[PURESIZE / sizeof (int)] = {0,}; /* Force it into data space! */ ! 84: #endif /* NOT VMS */ ! 85: #define PUREBEG (char *) pure ! 86: #else ! 87: #define pure PURE_SEG_BITS /* Use shared memory segment */ ! 88: #define PUREBEG (char *)PURE_SEG_BITS ! 89: #endif /* not HAVE_SHM */ ! 90: ! 91: /* Index in pure at which next pure object will be allocated. */ ! 92: int pureptr; ! 93: ! 94: /* If nonzero, this is a warning delivered by malloc and not yet displayed. */ ! 95: char *pending_malloc_warning; ! 96: ! 97: Lisp_Object ! 98: malloc_warning_1 (str) ! 99: Lisp_Object str; ! 100: { ! 101: Fprinc (str, Vstandard_output); ! 102: write_string ("\nKilling some buffers may delay running out of memory.\n", -1); ! 103: write_string ("However, certainly by the time you receive the 95% warning,\n", -1); ! 104: write_string ("you should clean up, kill this Emacs, and start a new one.", -1); ! 105: return Qnil; ! 106: } ! 107: ! 108: /* malloc calls this if it finds we are near exhausting storage */ ! 109: malloc_warning (str) ! 110: char *str; ! 111: { ! 112: pending_malloc_warning = str; ! 113: } ! 114: ! 115: display_malloc_warning () ! 116: { ! 117: register Lisp_Object val; ! 118: ! 119: val = build_string (pending_malloc_warning); ! 120: pending_malloc_warning = 0; ! 121: internal_with_output_to_temp_buffer (" *Danger*", malloc_warning_1, val); ! 122: } ! 123: ! 124: /* Called if malloc returns zero */ ! 125: memory_full () ! 126: { ! 127: while (1) ! 128: Fsignal (Qerror, memory_exhausted_message); ! 129: } ! 130: ! 131: /* like malloc and realloc but check for no memory left */ ! 132: ! 133: long * ! 134: xmalloc (size) ! 135: int size; ! 136: { ! 137: register long *val; ! 138: /* Avoid failure if malloc (0) returns 0. */ ! 139: if (size == 0) ! 140: size = 1; ! 141: val = (long *) malloc (size); ! 142: if (!val) memory_full (); ! 143: return val; ! 144: } ! 145: ! 146: long * ! 147: xrealloc (block, size) ! 148: long *block; ! 149: int size; ! 150: { ! 151: register long *val; ! 152: /* Avoid failure if malloc (0) returns 0. */ ! 153: if (size == 0) ! 154: size = 1; ! 155: val = (long *) realloc (block, size); ! 156: if (!val) memory_full (); ! 157: return val; ! 158: } ! 159: ! 160: /* Allocation of cons cells */ ! 161: /* We store cons cells inside of cons_blocks, allocating a new ! 162: cons_block with malloc whenever necessary. Cons cells reclaimed by ! 163: GC are put on a free list to be reallocated before allocating ! 164: any new cons cells from the latest cons_block. ! 165: ! 166: Each cons_block is just under 1016 bytes long, ! 167: since malloc really allocates in units of powers of two ! 168: and uses 8 bytes for its own overhead. */ ! 169: ! 170: #define CONS_BLOCK_SIZE \ ! 171: ((1016 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons)) ! 172: ! 173: struct cons_block ! 174: { ! 175: struct cons_block *next; ! 176: struct Lisp_Cons conses[CONS_BLOCK_SIZE]; ! 177: }; ! 178: ! 179: struct cons_block *cons_block; ! 180: int cons_block_index; ! 181: ! 182: struct Lisp_Cons *cons_free_list; ! 183: ! 184: void ! 185: init_cons () ! 186: { ! 187: cons_block = (struct cons_block *) malloc (sizeof (struct cons_block)); ! 188: cons_block->next = 0; ! 189: bzero (cons_block->conses, sizeof cons_block->conses); ! 190: cons_block_index = 0; ! 191: cons_free_list = 0; ! 192: } ! 193: ! 194: /* Explicitly free a cons cell. */ ! 195: free_cons (ptr) ! 196: struct Lisp_Cons *ptr; ! 197: { ! 198: XFASTINT (ptr->car) = (int) cons_free_list; ! 199: cons_free_list = ptr; ! 200: } ! 201: ! 202: DEFUN ("cons", Fcons, Scons, 2, 2, 0, ! 203: "Create a new cons, give it CAR and CDR as components, and return it.") ! 204: (car, cdr) ! 205: Lisp_Object car, cdr; ! 206: { ! 207: register Lisp_Object val; ! 208: ! 209: if (cons_free_list) ! 210: { ! 211: XSET (val, Lisp_Cons, cons_free_list); ! 212: cons_free_list = (struct Lisp_Cons *) XFASTINT (cons_free_list->car); ! 213: } ! 214: else ! 215: { ! 216: if (cons_block_index == CONS_BLOCK_SIZE) ! 217: { ! 218: register struct cons_block *new = (struct cons_block *) malloc (sizeof (struct cons_block)); ! 219: if (!new) memory_full (); ! 220: VALIDATE_LISP_STORAGE (new, sizeof *new); ! 221: new->next = cons_block; ! 222: cons_block = new; ! 223: cons_block_index = 0; ! 224: XSET (val, Lisp_Cons, &cons_block->conses[CONS_BLOCK_SIZE - 1]); ! 225: } ! 226: XSET (val, Lisp_Cons, &cons_block->conses[cons_block_index++]); ! 227: } ! 228: XCONS (val)->car = car; ! 229: XCONS (val)->cdr = cdr; ! 230: consing_since_gc += sizeof (struct Lisp_Cons); ! 231: return val; ! 232: } ! 233: ! 234: DEFUN ("list", Flist, Slist, 0, MANY, 0, ! 235: "Return a newly created list whose elements are the arguments (any number).") ! 236: (nargs, args) ! 237: int nargs; ! 238: register Lisp_Object *args; ! 239: { ! 240: register Lisp_Object len, val, val_tail; ! 241: ! 242: XFASTINT (len) = nargs; ! 243: val = Fmake_list (len, Qnil); ! 244: val_tail = val; ! 245: while (!NULL (val_tail)) ! 246: { ! 247: XCONS (val_tail)->car = *args++; ! 248: val_tail = XCONS (val_tail)->cdr; ! 249: } ! 250: return val; ! 251: } ! 252: ! 253: DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, ! 254: "Return a newly created list of length LENGTH, with each element being INIT.") ! 255: (length, init) ! 256: register Lisp_Object length, init; ! 257: { ! 258: register Lisp_Object val; ! 259: register int size; ! 260: ! 261: if (XTYPE (length) != Lisp_Int || XINT (length) < 0) ! 262: length = wrong_type_argument (Qnatnump, length); ! 263: size = XINT (length); ! 264: ! 265: val = Qnil; ! 266: while (size-- > 0) ! 267: val = Fcons (init, val); ! 268: return val; ! 269: } ! 270: ! 271: /* Allocation of vectors */ ! 272: ! 273: struct Lisp_Vector *all_vectors; ! 274: ! 275: DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, ! 276: "Return a newly created vector of length LENGTH, with each element being INIT.") ! 277: (length, init) ! 278: register Lisp_Object length, init; ! 279: { ! 280: register int sizei, index; ! 281: register Lisp_Object vector; ! 282: register struct Lisp_Vector *p; ! 283: ! 284: if (XTYPE (length) != Lisp_Int || XINT (length) < 0) ! 285: length = wrong_type_argument (Qnatnump, length); ! 286: sizei = XINT (length); ! 287: ! 288: p = (struct Lisp_Vector *) malloc (sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object)); ! 289: if (p == 0) ! 290: memory_full (); ! 291: VALIDATE_LISP_STORAGE (p, 0); ! 292: ! 293: XSET (vector, Lisp_Vector, p); ! 294: consing_since_gc += sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object); ! 295: ! 296: p->size = sizei; ! 297: p->next = all_vectors; ! 298: all_vectors = p; ! 299: ! 300: for (index = 0; index < sizei; index++) ! 301: p->contents[index] = init; ! 302: ! 303: return vector; ! 304: } ! 305: ! 306: DEFUN ("vector", Fvector, Svector, 0, MANY, 0, ! 307: "Return a newly created vector with our arguments (any number) as its elements.") ! 308: (nargs, args) ! 309: register int nargs; ! 310: Lisp_Object *args; ! 311: { ! 312: register Lisp_Object len, val; ! 313: register int index; ! 314: register struct Lisp_Vector *p; ! 315: ! 316: XFASTINT (len) = nargs; ! 317: val = Fmake_vector (len, Qnil); ! 318: p = XVECTOR (val); ! 319: for (index = 0; index < nargs; index++) ! 320: p->contents[index] = args[index]; ! 321: return val; ! 322: } ! 323: ! 324: /* Allocation of symbols. ! 325: Just like allocation of conses! ! 326: ! 327: Each symbol_block is just under 1016 bytes long, ! 328: since malloc really allocates in units of powers of two ! 329: and uses 8 bytes for its own overhead. */ ! 330: ! 331: #define SYMBOL_BLOCK_SIZE \ ! 332: ((1016 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol)) ! 333: ! 334: struct symbol_block ! 335: { ! 336: struct symbol_block *next; ! 337: struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; ! 338: }; ! 339: ! 340: struct symbol_block *symbol_block; ! 341: int symbol_block_index; ! 342: ! 343: struct Lisp_Symbol *symbol_free_list; ! 344: ! 345: void ! 346: init_symbol () ! 347: { ! 348: symbol_block = (struct symbol_block *) malloc (sizeof (struct symbol_block)); ! 349: symbol_block->next = 0; ! 350: bzero (symbol_block->symbols, sizeof symbol_block->symbols); ! 351: symbol_block_index = 0; ! 352: symbol_free_list = 0; ! 353: } ! 354: ! 355: DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, ! 356: "Return a newly allocated uninterned symbol whose name is NAME.\n\ ! 357: Its value and function definition are void, and its property list is NIL.") ! 358: (str) ! 359: Lisp_Object str; ! 360: { ! 361: register Lisp_Object val; ! 362: register struct Lisp_Symbol *p; ! 363: ! 364: CHECK_STRING (str, 0); ! 365: ! 366: if (symbol_free_list) ! 367: { ! 368: XSET (val, Lisp_Symbol, symbol_free_list); ! 369: symbol_free_list ! 370: = (struct Lisp_Symbol *) XFASTINT (symbol_free_list->value); ! 371: } ! 372: else ! 373: { ! 374: if (symbol_block_index == SYMBOL_BLOCK_SIZE) ! 375: { ! 376: struct symbol_block *new = (struct symbol_block *) malloc (sizeof (struct symbol_block)); ! 377: if (!new) memory_full (); ! 378: VALIDATE_LISP_STORAGE (new, sizeof *new); ! 379: new->next = symbol_block; ! 380: symbol_block = new; ! 381: symbol_block_index = 0; ! 382: } ! 383: XSET (val, Lisp_Symbol, &symbol_block->symbols[symbol_block_index++]); ! 384: } ! 385: p = XSYMBOL (val); ! 386: p->name = XSTRING (str); ! 387: p->plist = Qnil; ! 388: p->value = Qunbound; ! 389: p->function = Qunbound; ! 390: p->next = 0; ! 391: consing_since_gc += sizeof (struct Lisp_Symbol); ! 392: return val; ! 393: } ! 394: ! 395: /* Allocation of markers. ! 396: Works like allocation of conses. */ ! 397: ! 398: #define MARKER_BLOCK_SIZE \ ! 399: ((1016 - sizeof (struct marker_block *)) / sizeof (struct Lisp_Marker)) ! 400: ! 401: struct marker_block ! 402: { ! 403: struct marker_block *next; ! 404: struct Lisp_Marker markers[MARKER_BLOCK_SIZE]; ! 405: }; ! 406: ! 407: struct marker_block *marker_block; ! 408: int marker_block_index; ! 409: ! 410: struct Lisp_Marker *marker_free_list; ! 411: ! 412: void ! 413: init_marker () ! 414: { ! 415: marker_block = (struct marker_block *) malloc (sizeof (struct marker_block)); ! 416: marker_block->next = 0; ! 417: bzero (marker_block->markers, sizeof marker_block->markers); ! 418: marker_block_index = 0; ! 419: marker_free_list = 0; ! 420: } ! 421: ! 422: DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, ! 423: "Return a newly allocated marker which does not point at any place.") ! 424: () ! 425: { ! 426: register Lisp_Object val; ! 427: register struct Lisp_Marker *p; ! 428: ! 429: if (marker_free_list) ! 430: { ! 431: XSET (val, Lisp_Marker, marker_free_list); ! 432: marker_free_list ! 433: = (struct Lisp_Marker *) XFASTINT (marker_free_list->chain); ! 434: } ! 435: else ! 436: { ! 437: if (marker_block_index == MARKER_BLOCK_SIZE) ! 438: { ! 439: struct marker_block *new = (struct marker_block *) malloc (sizeof (struct marker_block)); ! 440: if (!new) memory_full (); ! 441: VALIDATE_LISP_STORAGE (new, sizeof *new); ! 442: new->next = marker_block; ! 443: marker_block = new; ! 444: marker_block_index = 0; ! 445: } ! 446: XSET (val, Lisp_Marker, &marker_block->markers[marker_block_index++]); ! 447: } ! 448: p = XMARKER (val); ! 449: p->buffer = 0; ! 450: p->bufpos = 0; ! 451: p->chain = Qnil; ! 452: consing_since_gc += sizeof (struct Lisp_Marker); ! 453: return val; ! 454: } ! 455: ! 456: /* Allocation of strings */ ! 457: ! 458: /* Strings reside inside of string_blocks. The entire data of the string, ! 459: both the size and the contents, live in part of the `chars' component of a string_block. ! 460: The `pos' component is the index within `chars' of the first free byte. ! 461: ! 462: first_string_block points to the first string_block ever allocated. ! 463: Each block points to the next one with its `next' field. ! 464: The `prev' fields chain in reverse order. ! 465: The last one allocated is the one currently being filled. ! 466: current_string_block points to it. ! 467: ! 468: The string_blocks that hold individual large strings ! 469: go in a separate chain, started by large_string_blocks. */ ! 470: ! 471: ! 472: /* String blocks contain this many useful bytes. ! 473: 8184 is power of 2, minus 8 for malloc overhead. */ ! 474: #define STRING_BLOCK_SIZE (8184 - sizeof (struct string_block_head)) ! 475: ! 476: /* A string bigger than this gets its own specially-made string block ! 477: if it doesn't fit in the current one. */ ! 478: #define STRING_BLOCK_OUTSIZE 1024 ! 479: ! 480: struct string_block_head ! 481: { ! 482: struct string_block *next, *prev; ! 483: int pos; ! 484: }; ! 485: ! 486: struct string_block ! 487: { ! 488: struct string_block *next, *prev; ! 489: int pos; ! 490: char chars[STRING_BLOCK_SIZE]; ! 491: }; ! 492: ! 493: /* This points to the string block we are now allocating strings. */ ! 494: ! 495: struct string_block *current_string_block; ! 496: ! 497: /* This points to the oldest string block, the one that starts the chain. */ ! 498: ! 499: struct string_block *first_string_block; ! 500: ! 501: /* Last string block in chain of those made for individual large strings. */ ! 502: ! 503: struct string_block *large_string_blocks; ! 504: ! 505: /* If SIZE is the length of a string, this returns how many bytes ! 506: the string occupies in a string_block (including padding). */ ! 507: ! 508: #define STRING_FULLSIZE(SIZE) \ ! 509: (((SIZE) + 2 * sizeof (int)) & ~(sizeof (int) - 1)) ! 510: ! 511: void ! 512: init_strings () ! 513: { ! 514: current_string_block = (struct string_block *) malloc (sizeof (struct string_block)); ! 515: first_string_block = current_string_block; ! 516: consing_since_gc += sizeof (struct string_block); ! 517: current_string_block->next = 0; ! 518: current_string_block->prev = 0; ! 519: current_string_block->pos = 0; ! 520: large_string_blocks = 0; ! 521: } ! 522: ! 523: static Lisp_Object make_uninit_string (); ! 524: ! 525: DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0, ! 526: "Return a newly created string of length LENGTH, with each element being INIT.\n\ ! 527: Both LENGTH and INIT must be numbers.") ! 528: (length, init) ! 529: Lisp_Object length, init; ! 530: { ! 531: register Lisp_Object val; ! 532: register unsigned char *p, *end, c; ! 533: ! 534: if (XTYPE (length) != Lisp_Int || XINT (length) < 0) ! 535: length = wrong_type_argument (Qnatnump, length); ! 536: CHECK_NUMBER (init, 1); ! 537: val = make_uninit_string (XINT (length)); ! 538: c = XINT (init); ! 539: p = XSTRING (val)->data; ! 540: end = p + XSTRING (val)->size; ! 541: while (p != end) ! 542: *p++ = c; ! 543: *p = 0; ! 544: return val; ! 545: } ! 546: ! 547: Lisp_Object ! 548: make_string (contents, length) ! 549: char *contents; ! 550: int length; ! 551: { ! 552: register Lisp_Object val; ! 553: val = make_uninit_string (length, 0); ! 554: bcopy (contents, XSTRING (val)->data, length); ! 555: return val; ! 556: } ! 557: ! 558: Lisp_Object ! 559: build_string (str) ! 560: char *str; ! 561: { ! 562: return make_string (str, strlen (str)); ! 563: } ! 564: ! 565: static Lisp_Object ! 566: make_uninit_string (length) ! 567: int length; ! 568: { ! 569: register Lisp_Object val; ! 570: register int fullsize = STRING_FULLSIZE (length); ! 571: ! 572: if (length < 0) abort (); ! 573: ! 574: if (fullsize <= STRING_BLOCK_SIZE - current_string_block->pos) ! 575: /* This string can fit in the current string block */ ! 576: { ! 577: XSET (val, Lisp_String, ! 578: (struct Lisp_String *) (current_string_block->chars + current_string_block->pos)); ! 579: current_string_block->pos += fullsize; ! 580: } ! 581: else if (fullsize > STRING_BLOCK_OUTSIZE) ! 582: /* This string gets its own string block */ ! 583: { ! 584: register struct string_block *new ! 585: = (struct string_block *) malloc (sizeof (struct string_block_head) + fullsize); ! 586: if (!new) memory_full (); ! 587: VALIDATE_LISP_STORAGE (new, 0); ! 588: consing_since_gc += sizeof (struct string_block_head) + fullsize; ! 589: new->pos = fullsize; ! 590: new->next = large_string_blocks; ! 591: large_string_blocks = new; ! 592: XSET (val, Lisp_String, ! 593: (struct Lisp_String *) ((struct string_block_head *)new + 1)); ! 594: } ! 595: else ! 596: /* Make a new current string block and start it off with this string */ ! 597: { ! 598: register struct string_block *new ! 599: = (struct string_block *) malloc (sizeof (struct string_block)); ! 600: if (!new) memory_full (); ! 601: VALIDATE_LISP_STORAGE (new, sizeof *new); ! 602: consing_since_gc += sizeof (struct string_block); ! 603: current_string_block->next = new; ! 604: new->prev = current_string_block; ! 605: new->next = 0; ! 606: current_string_block = new; ! 607: new->pos = fullsize; ! 608: XSET (val, Lisp_String, ! 609: (struct Lisp_String *) current_string_block->chars); ! 610: } ! 611: ! 612: XSTRING (val)->size = length; ! 613: XSTRING (val)->data[length] = 0; ! 614: ! 615: return val; ! 616: } ! 617: ! 618: /* Must get an error if pure storage is full, ! 619: since if it cannot hold a large string ! 620: it may be able to hold conses that point to that string; ! 621: then the string is not protected from gc. */ ! 622: ! 623: Lisp_Object ! 624: make_pure_string (data, length) ! 625: char *data; ! 626: int length; ! 627: { ! 628: register Lisp_Object new; ! 629: register int size = sizeof (int) + length + 1; ! 630: ! 631: if (pureptr + size > PURESIZE) ! 632: error ("Pure Lisp storage exhausted"); ! 633: XSET (new, Lisp_String, PUREBEG + pureptr); ! 634: XSTRING (new)->size = length; ! 635: bcopy (data, XSTRING (new)->data, length); ! 636: XSTRING (new)->data[length] = 0; ! 637: pureptr += (size + sizeof (int) - 1) ! 638: / sizeof (int) * sizeof (int); ! 639: return new; ! 640: } ! 641: ! 642: Lisp_Object ! 643: pure_cons (car, cdr) ! 644: Lisp_Object car, cdr; ! 645: { ! 646: register Lisp_Object new; ! 647: ! 648: if (pureptr + sizeof (struct Lisp_Cons) > PURESIZE) ! 649: error ("Pure Lisp storage exhausted"); ! 650: XSET (new, Lisp_Cons, PUREBEG + pureptr); ! 651: pureptr += sizeof (struct Lisp_Cons); ! 652: XCONS (new)->car = Fpurecopy (car); ! 653: XCONS (new)->cdr = Fpurecopy (cdr); ! 654: return new; ! 655: } ! 656: ! 657: Lisp_Object ! 658: make_pure_vector (len) ! 659: int len; ! 660: { ! 661: register Lisp_Object new; ! 662: register int size = sizeof (struct Lisp_Vector) + (len - 1) * sizeof (Lisp_Object); ! 663: ! 664: if (pureptr + size > PURESIZE) ! 665: error ("Pure Lisp storage exhausted"); ! 666: ! 667: XSET (new, Lisp_Vector, PUREBEG + pureptr); ! 668: pureptr += size; ! 669: XVECTOR (new)->size = len; ! 670: return new; ! 671: } ! 672: ! 673: DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, ! 674: "Make a copy of OBJECT in pure storage.\n\ ! 675: Recursively copies contents of vectors and cons cells.\n\ ! 676: Does not copy symbols.") ! 677: (obj) ! 678: register Lisp_Object obj; ! 679: { ! 680: register Lisp_Object new, tem; ! 681: register int i; ! 682: ! 683: if (NULL (Vpurify_flag)) ! 684: return obj; ! 685: ! 686: if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE) ! 687: && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure) ! 688: return obj; ! 689: ! 690: #ifdef SWITCH_ENUM_BUG ! 691: switch ((int) XTYPE (obj)) ! 692: #else ! 693: switch (XTYPE (obj)) ! 694: #endif ! 695: { ! 696: case Lisp_Marker: ! 697: error ("Attempt to copy a marker to pure storage"); ! 698: ! 699: case Lisp_Cons: ! 700: return pure_cons (XCONS (obj)->car, XCONS (obj)->cdr); ! 701: ! 702: case Lisp_String: ! 703: return make_pure_string (XSTRING (obj)->data, XSTRING (obj)->size); ! 704: ! 705: case Lisp_Vector: ! 706: new = make_pure_vector (XVECTOR (obj)->size); ! 707: for (i = 0; i < XVECTOR (obj)->size; i++) ! 708: { ! 709: tem = XVECTOR (obj)->contents[i]; ! 710: XVECTOR (new)->contents[i] = Fpurecopy (tem); ! 711: } ! 712: return new; ! 713: ! 714: default: ! 715: return obj; ! 716: } ! 717: } ! 718: ! 719: /* Recording what needs to be marked for gc. */ ! 720: ! 721: struct gcpro *gcprolist; ! 722: ! 723: #define NSTATICS 200 ! 724: ! 725: int staticidx = 0; ! 726: ! 727: #ifdef __GNUC__ ! 728: Lisp_Object *staticvec[NSTATICS] = {0}; ! 729: #else ! 730: char staticvec1[NSTATICS * sizeof (Lisp_Object *)] = {0}; ! 731: #define staticvec ((Lisp_Object **) staticvec1) ! 732: #endif ! 733: ! 734: /* Put an entry in staticvec, pointing at the variable whose address is given */ ! 735: ! 736: void ! 737: staticpro (varaddress) ! 738: Lisp_Object *varaddress; ! 739: { ! 740: staticvec[staticidx++] = varaddress; ! 741: if (staticidx >= NSTATICS) ! 742: abort (); ! 743: } ! 744: ! 745: struct catchtag ! 746: { ! 747: Lisp_Object tag; ! 748: Lisp_Object val; ! 749: struct catchtag *next; ! 750: /* jmp_buf jmp; /* We don't need this for GC purposes */ ! 751: }; ! 752: ! 753: extern struct catchtag *catchlist; ! 754: ! 755: struct backtrace ! 756: { ! 757: struct backtrace *next; ! 758: Lisp_Object *function; ! 759: Lisp_Object *args; /* Points to vector of args. */ ! 760: int nargs; /* length of vector */ ! 761: /* if nargs is UNEVALLED, args points to slot holding list of unevalled args */ ! 762: char evalargs; ! 763: }; ! 764: ! 765: extern struct backtrace *backtrace_list; ! 766: ! 767: /* Two flags that are set during GC in the `size' component ! 768: of a string or vector. On some machines, these flags ! 769: are defined by the m- file to be different bits. */ ! 770: ! 771: /* On vector, means it has been marked. ! 772: On string size field or a reference to a string, ! 773: means not the last reference in the chain. */ ! 774: ! 775: #ifndef ARRAY_MARK_FLAG ! 776: #define ARRAY_MARK_FLAG ((MARKBIT >> 1) & ~MARKBIT) ! 777: #endif /* no ARRAY_MARK_FLAG */ ! 778: ! 779: /* Any slot that is a Lisp_Object can point to a string ! 780: and thus can be put on a string's reference-chain ! 781: and thus may need to have its ARRAY_MARK_FLAG set. ! 782: This includes the slots whose markbits are used to mark ! 783: the containing objects. */ ! 784: ! 785: #if ARRAY_MARK_FLAG == MARKBIT ! 786: you lose ! 787: #endif ! 788: ! 789: int total_conses, total_markers, total_symbols, total_string_size, total_vector_size; ! 790: int total_free_conses, total_free_markers, total_free_symbols; ! 791: ! 792: static void mark_object (), mark_buffer (); ! 793: static void clear_marks (), gc_sweep (); ! 794: static void compact_strings (); ! 795: ! 796: DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", ! 797: "Reclaim storage for Lisp objects no longer needed.\n\ ! 798: Returns info on amount of space in use:\n\ ! 799: ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\ ! 800: (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS)\n\ ! 801: Garbage collection happens automatically if you cons more than\n\ ! 802: gc-cons-threshold bytes of Lisp data since previous garbage collection.") ! 803: () ! 804: { ! 805: register struct gcpro *tail; ! 806: register struct specbinding *bind; ! 807: struct catchtag *catch; ! 808: struct handler *handler; ! 809: register struct backtrace *backlist; ! 810: register Lisp_Object tem; ! 811: char *omessage = echo_area_contents; ! 812: ! 813: register int i; ! 814: ! 815: if (!noninteractive) ! 816: message1 ("Garbage collecting..."); ! 817: ! 818: /* Don't keep command history around forever */ ! 819: tem = Fnthcdr (make_number (30), Vcommand_history); ! 820: if (CONSP (tem)) ! 821: XCONS (tem)->cdr = Qnil; ! 822: /* Likewise for undo information. */ ! 823: truncate_all_undos (); ! 824: ! 825: gc_in_progress = 1; ! 826: ! 827: /* clear_marks (); */ ! 828: ! 829: /* In each "large string", set the MARKBIT of the size field. ! 830: That enables mark_object to recognize them. */ ! 831: { ! 832: register struct string_block *b; ! 833: for (b = large_string_blocks; b; b = b->next) ! 834: ((struct Lisp_String *)(&b->chars[0]))->size |= MARKBIT; ! 835: } ! 836: ! 837: /* Mark all the special slots that serve as the roots of accessibility. ! 838: ! 839: Usually the special slots to mark are contained in particular structures. ! 840: Then we know no slot is marked twice because the structures don't overlap. ! 841: In some cases, the structures point to the slots to be marked. ! 842: For these, we use MARKBIT to avoid double marking of the slot. */ ! 843: ! 844: for (i = 0; i < staticidx; i++) ! 845: mark_object (staticvec[i]); ! 846: for (tail = gcprolist; tail; tail = tail->next) ! 847: for (i = 0; i < tail->nvars; i++) ! 848: if (!XMARKBIT (tail->var[i])) ! 849: { ! 850: mark_object (&tail->var[i]); ! 851: XMARK (tail->var[i]); ! 852: } ! 853: for (bind = specpdl; bind != specpdl_ptr; bind++) ! 854: { ! 855: mark_object (&bind->symbol); ! 856: mark_object (&bind->old_value); ! 857: } ! 858: for (catch = catchlist; catch; catch = catch->next) ! 859: { ! 860: mark_object (&catch->tag); ! 861: mark_object (&catch->val); ! 862: } ! 863: for (handler = handlerlist; handler; handler = handler->next) ! 864: { ! 865: mark_object (&handler->handler); ! 866: mark_object (&handler->var); ! 867: } ! 868: for (backlist = backtrace_list; backlist; backlist = backlist->next) ! 869: { ! 870: if (!XMARKBIT (*backlist->function)) ! 871: { ! 872: mark_object (backlist->function); ! 873: XMARK (*backlist->function); ! 874: } ! 875: if (backlist->nargs == UNEVALLED || backlist->nargs == MANY) ! 876: i = 0; ! 877: else ! 878: i = backlist->nargs - 1; ! 879: for (; i >= 0; i--) ! 880: if (!XMARKBIT (backlist->args[i])) ! 881: { ! 882: mark_object (&backlist->args[i]); ! 883: XMARK (backlist->args[i]); ! 884: } ! 885: } ! 886: ! 887: gc_sweep (); ! 888: ! 889: /* Clear the mark bits that we set in certain root slots. */ ! 890: ! 891: for (tail = gcprolist; tail; tail = tail->next) ! 892: for (i = 0; i < tail->nvars; i++) ! 893: XUNMARK (tail->var[i]); ! 894: for (backlist = backtrace_list; backlist; backlist = backlist->next) ! 895: { ! 896: XUNMARK (*backlist->function); ! 897: if (backlist->nargs == UNEVALLED || backlist->nargs == MANY) ! 898: i = 0; ! 899: else ! 900: i = backlist->nargs - 1; ! 901: for (; i >= 0; i--) ! 902: XUNMARK (backlist->args[i]); ! 903: } ! 904: XUNMARK (buffer_defaults.name); ! 905: XUNMARK (buffer_local_symbols.name); ! 906: ! 907: /* clear_marks (); */ ! 908: gc_in_progress = 0; ! 909: ! 910: consing_since_gc = 0; ! 911: consing_at_last_truncate = 0; ! 912: if (gc_cons_threshold < 10000) ! 913: gc_cons_threshold = 10000; ! 914: ! 915: if (omessage) ! 916: message1 (omessage); ! 917: else if (!noninteractive) ! 918: message1 ("Garbage collecting...done"); ! 919: ! 920: return Fcons (Fcons (make_number (total_conses), ! 921: make_number (total_free_conses)), ! 922: Fcons (Fcons (make_number (total_symbols), ! 923: make_number (total_free_symbols)), ! 924: Fcons (Fcons (make_number (total_markers), ! 925: make_number (total_free_markers)), ! 926: Fcons (make_number (total_string_size), ! 927: Fcons (make_number (total_vector_size), ! 928: Qnil))))); ! 929: } ! 930: ! 931: #if 0 ! 932: static void ! 933: clear_marks () ! 934: { ! 935: /* Clear marks on all conses */ ! 936: { ! 937: register struct cons_block *cblk; ! 938: register int lim = cons_block_index; ! 939: ! 940: for (cblk = cons_block; cblk; cblk = cblk->next) ! 941: { ! 942: register int i; ! 943: for (i = 0; i < lim; i++) ! 944: XUNMARK (cblk->conses[i].car); ! 945: lim = CONS_BLOCK_SIZE; ! 946: } ! 947: } ! 948: /* Clear marks on all symbols */ ! 949: { ! 950: register struct symbol_block *sblk; ! 951: register int lim = symbol_block_index; ! 952: ! 953: for (sblk = symbol_block; sblk; sblk = sblk->next) ! 954: { ! 955: register int i; ! 956: for (i = 0; i < lim; i++) ! 957: { ! 958: XUNMARK (sblk->symbols[i].plist); ! 959: } ! 960: lim = SYMBOL_BLOCK_SIZE; ! 961: } ! 962: } ! 963: /* Clear marks on all markers */ ! 964: { ! 965: register struct marker_block *sblk; ! 966: register int lim = marker_block_index; ! 967: ! 968: for (sblk = marker_block; sblk; sblk = sblk->next) ! 969: { ! 970: register int i; ! 971: for (i = 0; i < lim; i++) ! 972: XUNMARK (sblk->markers[i].chain); ! 973: lim = MARKER_BLOCK_SIZE; ! 974: } ! 975: } ! 976: /* Clear mark bits on all buffers */ ! 977: { ! 978: register struct buffer *nextb = all_buffers; ! 979: ! 980: while (nextb) ! 981: { ! 982: XUNMARK (nextb->name); ! 983: nextb = nextb->next; ! 984: } ! 985: } ! 986: } ! 987: #endif ! 988: ! 989: /* Mark reference to a Lisp_Object. If the object referred to ! 990: has not been seen yet, recursively mark all the references contained in it. ! 991: ! 992: If the object referenced is a short string, the referrencing slot ! 993: is threaded into a chain of such slots, pointed to from ! 994: the `size' field of the string. The actual string size ! 995: lives in the last slot in the chain. We recognize the end ! 996: because it is < (unsigned) STRING_BLOCK_SIZE. */ ! 997: ! 998: static void ! 999: mark_object (objptr) ! 1000: Lisp_Object *objptr; ! 1001: { ! 1002: register Lisp_Object obj; ! 1003: ! 1004: obj = *objptr; ! 1005: XUNMARK (obj); ! 1006: ! 1007: loop: ! 1008: ! 1009: if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE) ! 1010: && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure) ! 1011: return; ! 1012: ! 1013: #ifdef SWITCH_ENUM_BUG ! 1014: switch ((int) XGCTYPE (obj)) ! 1015: #else ! 1016: switch (XGCTYPE (obj)) ! 1017: #endif ! 1018: { ! 1019: case Lisp_String: ! 1020: { ! 1021: register struct Lisp_String *ptr = XSTRING (obj); ! 1022: ! 1023: if (ptr->size & MARKBIT) ! 1024: /* A large string. Just set ARRAY_MARK_FLAG. */ ! 1025: ptr->size |= ARRAY_MARK_FLAG; ! 1026: else ! 1027: { ! 1028: /* A small string. Put this reference ! 1029: into the chain of references to it. ! 1030: The address OBJPTR is even, so if the address ! 1031: includes MARKBIT, put it in the low bit ! 1032: when we store OBJPTR into the size field. */ ! 1033: ! 1034: if (XMARKBIT (*objptr)) ! 1035: { ! 1036: XFASTINT (*objptr) = ptr->size; ! 1037: XMARK (*objptr); ! 1038: } ! 1039: else ! 1040: XFASTINT (*objptr) = ptr->size; ! 1041: if ((int)objptr & 1) abort (); ! 1042: ptr->size = (int) objptr & ~MARKBIT; ! 1043: if ((int) objptr & MARKBIT) ! 1044: ptr->size ++; ! 1045: } ! 1046: } ! 1047: break; ! 1048: ! 1049: case Lisp_Vector: ! 1050: case Lisp_Window: ! 1051: case Lisp_Process: ! 1052: case Lisp_Window_Configuration: ! 1053: { ! 1054: register struct Lisp_Vector *ptr = XVECTOR (obj); ! 1055: register int size = ptr->size; ! 1056: register int i; ! 1057: ! 1058: if (size & ARRAY_MARK_FLAG) break; /* Already marked */ ! 1059: ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ ! 1060: for (i = 0; i < size; i++) /* and then mark its elements */ ! 1061: mark_object (&ptr->contents[i]); ! 1062: } ! 1063: break; ! 1064: ! 1065: #if 0 ! 1066: case Lisp_Temp_Vector: ! 1067: { ! 1068: register struct Lisp_Vector *ptr = XVECTOR (obj); ! 1069: register int size = ptr->size; ! 1070: register int i; ! 1071: ! 1072: for (i = 0; i < size; i++) /* and then mark its elements */ ! 1073: mark_object (&ptr->contents[i]); ! 1074: } ! 1075: break; ! 1076: #endif 0 ! 1077: ! 1078: case Lisp_Symbol: ! 1079: { ! 1080: register struct Lisp_Symbol *ptr = XSYMBOL (obj); ! 1081: struct Lisp_Symbol *ptrx; ! 1082: ! 1083: if (XMARKBIT (ptr->plist)) break; ! 1084: XMARK (ptr->plist); ! 1085: XSETTYPE (*(Lisp_Object *) &ptr->name, Lisp_String); ! 1086: mark_object (&ptr->name); ! 1087: mark_object ((Lisp_Object *) &ptr->value); ! 1088: mark_object (&ptr->function); ! 1089: mark_object (&ptr->plist); ! 1090: ptr = ptr->next; ! 1091: if (ptr) ! 1092: { ! 1093: ptrx = ptr; /* Use pf ptrx avoids compiler bug on Sun */ ! 1094: XSETSYMBOL (obj, ptrx); ! 1095: goto loop; ! 1096: } ! 1097: } ! 1098: break; ! 1099: ! 1100: case Lisp_Marker: ! 1101: XMARK (XMARKER (obj)->chain); ! 1102: /* DO NOT mark thru the marker's chain. ! 1103: The buffer's markers chain does not preserve markers from gc; ! 1104: instead, markers are removed from the chain when they are freed by gc. */ ! 1105: break; ! 1106: ! 1107: case Lisp_Cons: ! 1108: case Lisp_Buffer_Local_Value: ! 1109: case Lisp_Some_Buffer_Local_Value: ! 1110: { ! 1111: register struct Lisp_Cons *ptr = XCONS (obj); ! 1112: if (XMARKBIT (ptr->car)) break; ! 1113: XMARK (ptr->car); ! 1114: /* If the cdr is nil, avoid recursion for the car. */ ! 1115: if (EQ (ptr->cdr, Qnil)) ! 1116: { ! 1117: objptr = &ptr->car; ! 1118: obj = ptr->car; ! 1119: XUNMARK (obj); ! 1120: goto loop; ! 1121: } ! 1122: /* If the cdr is (INTEGER . nil), mark the cdr first, ! 1123: to avoid recursion for the car. This case occurs ! 1124: in every compiled function. */ ! 1125: if (XTYPE (ptr->cdr) == Lisp_Cons ! 1126: && XGCTYPE (XCONS (ptr->cdr)->car) == Lisp_Int ! 1127: && EQ (XCONS (ptr->cdr)->cdr, Qnil)) ! 1128: { ! 1129: mark_object (&ptr->cdr); ! 1130: objptr = &ptr->car; ! 1131: obj = ptr->car; ! 1132: XUNMARK (obj); ! 1133: goto loop; ! 1134: } ! 1135: mark_object (&ptr->car); ! 1136: objptr = &ptr->cdr; ! 1137: obj = ptr->cdr; ! 1138: goto loop; ! 1139: } ! 1140: ! 1141: case Lisp_Buffer: ! 1142: if (!XMARKBIT (XBUFFER (obj)->name)) ! 1143: mark_buffer (obj); ! 1144: break; ! 1145: ! 1146: case Lisp_Int: ! 1147: case Lisp_Void: ! 1148: case Lisp_Subr: ! 1149: case Lisp_Intfwd: ! 1150: case Lisp_Boolfwd: ! 1151: case Lisp_Objfwd: ! 1152: case Lisp_Buffer_Objfwd: ! 1153: case Lisp_Internal_Stream: ! 1154: /* Don't bother with Lisp_Buffer_Objfwd, ! 1155: since all markable slots in current buffer marked anyway. */ ! 1156: /* Don't need to do Lisp_Objfwd, since the places they point ! 1157: are protected with staticpro. */ ! 1158: break; ! 1159: ! 1160: default: ! 1161: abort (); ! 1162: } ! 1163: } ! 1164: ! 1165: /* Mark the pointers in a buffer structure. */ ! 1166: ! 1167: static void ! 1168: mark_buffer (buf) ! 1169: Lisp_Object buf; ! 1170: { ! 1171: Lisp_Object tem; ! 1172: register struct buffer *buffer = XBUFFER (buf); ! 1173: register Lisp_Object *ptr; ! 1174: ! 1175: /* This is the buffer's markbit */ ! 1176: mark_object (&buffer->name); ! 1177: XMARK (buffer->name); ! 1178: ! 1179: for (ptr = &buffer->name + 1; ! 1180: (char *)ptr < (char *)buffer + sizeof (struct buffer); ! 1181: ptr++) ! 1182: mark_object (ptr); ! 1183: } ! 1184: ! 1185: /* Find all structures not marked, and free them. */ ! 1186: ! 1187: static void ! 1188: gc_sweep () ! 1189: { ! 1190: total_string_size = 0; ! 1191: compact_strings (); ! 1192: ! 1193: /* Put all unmarked conses on free list */ ! 1194: { ! 1195: register struct cons_block *cblk; ! 1196: register int lim = cons_block_index; ! 1197: register int num_free = 0, num_used = 0; ! 1198: ! 1199: cons_free_list = 0; ! 1200: ! 1201: for (cblk = cons_block; cblk; cblk = cblk->next) ! 1202: { ! 1203: register int i; ! 1204: for (i = 0; i < lim; i++) ! 1205: if (!XMARKBIT (cblk->conses[i].car)) ! 1206: { ! 1207: XFASTINT (cblk->conses[i].car) = (int) cons_free_list; ! 1208: num_free++; ! 1209: cons_free_list = &cblk->conses[i]; ! 1210: } ! 1211: else ! 1212: { ! 1213: num_used++; ! 1214: XUNMARK (cblk->conses[i].car); ! 1215: } ! 1216: lim = CONS_BLOCK_SIZE; ! 1217: } ! 1218: total_conses = num_used; ! 1219: total_free_conses = num_free; ! 1220: } ! 1221: ! 1222: /* Put all unmarked symbols on free list */ ! 1223: { ! 1224: register struct symbol_block *sblk; ! 1225: register int lim = symbol_block_index; ! 1226: register int num_free = 0, num_used = 0; ! 1227: ! 1228: symbol_free_list = 0; ! 1229: ! 1230: for (sblk = symbol_block; sblk; sblk = sblk->next) ! 1231: { ! 1232: register int i; ! 1233: for (i = 0; i < lim; i++) ! 1234: if (!XMARKBIT (sblk->symbols[i].plist)) ! 1235: { ! 1236: XFASTINT (sblk->symbols[i].value) = (int) symbol_free_list; ! 1237: symbol_free_list = &sblk->symbols[i]; ! 1238: num_free++; ! 1239: } ! 1240: else ! 1241: { ! 1242: num_used++; ! 1243: sblk->symbols[i].name ! 1244: = XSTRING (*(Lisp_Object *) &sblk->symbols[i].name); ! 1245: XUNMARK (sblk->symbols[i].plist); ! 1246: } ! 1247: lim = SYMBOL_BLOCK_SIZE; ! 1248: } ! 1249: total_symbols = num_used; ! 1250: total_free_symbols = num_free; ! 1251: } ! 1252: ! 1253: #ifndef standalone ! 1254: /* Put all unmarked markers on free list. ! 1255: Dechain each one first from the buffer it points into. */ ! 1256: { ! 1257: register struct marker_block *mblk; ! 1258: struct Lisp_Marker *tem1; ! 1259: register int lim = marker_block_index; ! 1260: register int num_free = 0, num_used = 0; ! 1261: ! 1262: marker_free_list = 0; ! 1263: ! 1264: for (mblk = marker_block; mblk; mblk = mblk->next) ! 1265: { ! 1266: register int i; ! 1267: for (i = 0; i < lim; i++) ! 1268: if (!XMARKBIT (mblk->markers[i].chain)) ! 1269: { ! 1270: Lisp_Object tem; ! 1271: tem1 = &mblk->markers[i]; /* tem1 avoids Sun compiler bug */ ! 1272: XSET (tem, Lisp_Marker, tem1); ! 1273: if (tem1->buffer) ! 1274: unchain_marker (tem); ! 1275: XFASTINT (mblk->markers[i].chain) = (int) marker_free_list; ! 1276: marker_free_list = &mblk->markers[i]; ! 1277: num_free++; ! 1278: } ! 1279: else ! 1280: { ! 1281: num_used++; ! 1282: XUNMARK (mblk->markers[i].chain); ! 1283: } ! 1284: lim = MARKER_BLOCK_SIZE; ! 1285: } ! 1286: ! 1287: total_markers = num_used; ! 1288: total_free_markers = num_free; ! 1289: } ! 1290: ! 1291: /* Free all unmarked buffers */ ! 1292: { ! 1293: register struct buffer *buffer = all_buffers, *prev = 0, *next; ! 1294: ! 1295: while (buffer) ! 1296: if (!XMARKBIT (buffer->name)) ! 1297: { ! 1298: if (prev) ! 1299: prev->next = buffer->next; ! 1300: else ! 1301: all_buffers = buffer->next; ! 1302: next = buffer->next; ! 1303: free (buffer); ! 1304: buffer = next; ! 1305: } ! 1306: else ! 1307: { ! 1308: XUNMARK (buffer->name); ! 1309: prev = buffer, buffer = buffer->next; ! 1310: } ! 1311: } ! 1312: ! 1313: #endif standalone ! 1314: ! 1315: /* Free all unmarked vectors */ ! 1316: { ! 1317: register struct Lisp_Vector *vector = all_vectors, *prev = 0, *next; ! 1318: total_vector_size = 0; ! 1319: ! 1320: while (vector) ! 1321: if (!(vector->size & ARRAY_MARK_FLAG)) ! 1322: { ! 1323: if (prev) ! 1324: prev->next = vector->next; ! 1325: else ! 1326: all_vectors = vector->next; ! 1327: next = vector->next; ! 1328: free (vector); ! 1329: vector = next; ! 1330: } ! 1331: else ! 1332: { ! 1333: vector->size &= ~ARRAY_MARK_FLAG; ! 1334: total_vector_size += vector->size; ! 1335: prev = vector, vector = vector->next; ! 1336: } ! 1337: } ! 1338: ! 1339: /* Free all "large strings" not marked with ARRAY_MARK_FLAG. */ ! 1340: { ! 1341: register struct string_block *sb = large_string_blocks, *prev = 0, *next; ! 1342: ! 1343: while (sb) ! 1344: if (!(((struct Lisp_String *)(&sb->chars[0]))->size & ARRAY_MARK_FLAG)) ! 1345: { ! 1346: if (prev) ! 1347: prev->next = sb->next; ! 1348: else ! 1349: large_string_blocks = sb->next; ! 1350: next = sb->next; ! 1351: free (sb); ! 1352: sb = next; ! 1353: } ! 1354: else ! 1355: { ! 1356: ((struct Lisp_String *)(&sb->chars[0]))->size ! 1357: &= ~ARRAY_MARK_FLAG & ~MARKBIT; ! 1358: total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size; ! 1359: prev = sb, sb = sb->next; ! 1360: } ! 1361: } ! 1362: } ! 1363: ! 1364: /* Compactify strings, relocate references to them, and ! 1365: free any string blocks that become empty. */ ! 1366: ! 1367: static void ! 1368: compact_strings () ! 1369: { ! 1370: /* String block of old strings we are scanning. */ ! 1371: register struct string_block *from_sb; ! 1372: /* A preceding string block (or maybe the same one) ! 1373: where we are copying the still-live strings to. */ ! 1374: register struct string_block *to_sb; ! 1375: int pos; ! 1376: int to_pos; ! 1377: ! 1378: to_sb = first_string_block; ! 1379: to_pos = 0; ! 1380: ! 1381: /* Scan each existing string block sequentially, string by string. */ ! 1382: for (from_sb = first_string_block; from_sb; from_sb = from_sb->next) ! 1383: { ! 1384: pos = 0; ! 1385: /* POS is the index of the next string in the block. */ ! 1386: while (pos < from_sb->pos) ! 1387: { ! 1388: register struct Lisp_String *nextstr ! 1389: = (struct Lisp_String *) &from_sb->chars[pos]; ! 1390: ! 1391: register struct Lisp_String *newaddr; ! 1392: register int size = nextstr->size; ! 1393: ! 1394: /* NEXTSTR is the old address of the next string. ! 1395: Just skip it if it isn't marked. */ ! 1396: if ((unsigned) size > STRING_BLOCK_SIZE) ! 1397: { ! 1398: /* It is marked, so its size field is really a chain of refs. ! 1399: Find the end of the chain, where the actual size lives. */ ! 1400: while ((unsigned) size > STRING_BLOCK_SIZE) ! 1401: { ! 1402: if (size & 1) size ^= MARKBIT | 1; ! 1403: size = *(int *)size & ~MARKBIT; ! 1404: } ! 1405: ! 1406: total_string_size += size; ! 1407: ! 1408: /* If it won't fit in TO_SB, close it out, ! 1409: and move to the next sb. Keep doing so until ! 1410: TO_SB reaches a large enough, empty enough string block. ! 1411: We know that TO_SB cannot advance past FROM_SB here ! 1412: since FROM_SB is large enough to contain this string. ! 1413: Any string blocks skipped here ! 1414: will be patched out and freed later. */ ! 1415: while (to_pos + STRING_FULLSIZE (size) ! 1416: > max (to_sb->pos, STRING_BLOCK_SIZE)) ! 1417: { ! 1418: to_sb->pos = to_pos; ! 1419: to_sb = to_sb->next; ! 1420: to_pos = 0; ! 1421: } ! 1422: /* Compute new address of this string ! 1423: and update TO_POS for the space being used. */ ! 1424: newaddr = (struct Lisp_String *) &to_sb->chars[to_pos]; ! 1425: to_pos += STRING_FULLSIZE (size); ! 1426: ! 1427: /* Copy the string itself to the new place. */ ! 1428: if (nextstr != newaddr) ! 1429: bcopy (nextstr, newaddr, size + 1 + sizeof (int)); ! 1430: ! 1431: /* Go through NEXTSTR's chain of references ! 1432: and make each slot in the chain point to ! 1433: the new address of this string. */ ! 1434: size = newaddr->size; ! 1435: while ((unsigned) size > STRING_BLOCK_SIZE) ! 1436: { ! 1437: register Lisp_Object *objptr; ! 1438: if (size & 1) size ^= MARKBIT | 1; ! 1439: objptr = (Lisp_Object *)size; ! 1440: ! 1441: size = XFASTINT (*objptr) & ~MARKBIT; ! 1442: if (XMARKBIT (*objptr)) ! 1443: { ! 1444: XSET (*objptr, Lisp_String, newaddr); ! 1445: XMARK (*objptr); ! 1446: } ! 1447: else ! 1448: XSET (*objptr, Lisp_String, newaddr); ! 1449: } ! 1450: /* Store the actual size in the size field. */ ! 1451: newaddr->size = size; ! 1452: } ! 1453: pos += STRING_FULLSIZE (size); ! 1454: } ! 1455: } ! 1456: ! 1457: /* Close out the last string block still used and free any that follow. */ ! 1458: to_sb->pos = to_pos; ! 1459: current_string_block = to_sb; ! 1460: ! 1461: from_sb = to_sb->next; ! 1462: to_sb->next = 0; ! 1463: while (from_sb) ! 1464: { ! 1465: to_sb = from_sb->next; ! 1466: free (from_sb); ! 1467: from_sb = to_sb; ! 1468: } ! 1469: ! 1470: /* Free any empty string blocks further back in the chain. ! 1471: This loop will never free first_string_block, but it is very ! 1472: unlikely that that one will become empty, so why bother checking? */ ! 1473: ! 1474: from_sb = first_string_block; ! 1475: while (to_sb = from_sb->next) ! 1476: { ! 1477: if (to_sb->pos == 0) ! 1478: { ! 1479: if (from_sb->next = to_sb->next) ! 1480: from_sb->next->prev = from_sb; ! 1481: free (to_sb); ! 1482: } ! 1483: else ! 1484: from_sb = to_sb; ! 1485: } ! 1486: } ! 1487: ! 1488: truncate_all_undos () ! 1489: { ! 1490: register struct buffer *nextb = all_buffers; ! 1491: ! 1492: consing_at_last_truncate = consing_since_gc; ! 1493: ! 1494: while (nextb) ! 1495: { ! 1496: /* If a buffer's undo list is Qt, that means that undo is ! 1497: turned off in that buffer. Calling truncate_undo_list on ! 1498: Qt tends to return NULL, which effectively turns undo back on. ! 1499: So don't call truncate_undo_list if undo_list is Qt. */ ! 1500: if (! EQ (nextb->undo_list, Qt)) ! 1501: nextb->undo_list ! 1502: = truncate_undo_list (nextb->undo_list, undo_threshold, ! 1503: undo_high_threshold); ! 1504: nextb = nextb->next; ! 1505: } ! 1506: } ! 1507: ! 1508: /* Initialization */ ! 1509: ! 1510: init_alloc_once () ! 1511: { ! 1512: /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ ! 1513: pureptr = 0; ! 1514: all_vectors = 0; ! 1515: init_strings (); ! 1516: init_cons (); ! 1517: init_symbol (); ! 1518: init_marker (); ! 1519: gcprolist = 0; ! 1520: staticidx = 0; ! 1521: consing_since_gc = 0; ! 1522: gc_cons_threshold = 100000; ! 1523: #ifdef VIRT_ADDR_VARIES ! 1524: malloc_sbrk_unused = 1<<22; /* A large number */ ! 1525: malloc_sbrk_used = 100000; /* as reasonable as any number */ ! 1526: #endif /* VIRT_ADDR_VARIES */ ! 1527: } ! 1528: ! 1529: init_alloc () ! 1530: { ! 1531: gcprolist = 0; ! 1532: } ! 1533: ! 1534: void ! 1535: syms_of_alloc () ! 1536: { ! 1537: memory_exhausted_message = Fcons (build_string ("Memory exhausted"), Qnil); ! 1538: staticpro (&memory_exhausted_message); ! 1539: ! 1540: DEFVAR_INT ("gc-cons-threshold", &gc_cons_threshold, ! 1541: "*Number of bytes of consing between garbage collections."); ! 1542: ! 1543: DEFVAR_INT ("pure-bytes-used", &pureptr, ! 1544: "Number of bytes of sharable Lisp data allocated so far."); ! 1545: ! 1546: #if 0 ! 1547: DEFVAR_INT ("data-bytes-used", &malloc_sbrk_used, ! 1548: "Number of bytes of unshared memory allocated in this session."); ! 1549: ! 1550: DEFVAR_INT ("data-bytes-free", &malloc_sbrk_unused, ! 1551: "Number of bytes of unshared memory remaining available in this session."); ! 1552: #endif ! 1553: ! 1554: DEFVAR_LISP ("purify-flag", &Vpurify_flag, ! 1555: "Non-nil means loading Lisp code in order to dump an executable."); ! 1556: ! 1557: DEFVAR_INT ("undo-threshold", &undo_threshold, ! 1558: "Keep no more undo information once it exceeds this size.\n\ ! 1559: This threshold is applied when garbage collection happens.\n\ ! 1560: The size is counted as the number of bytes occupied,\n\ ! 1561: which includes both saved text and other data."); ! 1562: undo_threshold = 15000; ! 1563: DEFVAR_INT ("undo-high-threshold", &undo_high_threshold, ! 1564: "Don't keep more than this much size of undo information.\n\ ! 1565: A command which pushes past this size is itself forgotten.\n\ ! 1566: This threshold is applied when garbage collection happens.\n\ ! 1567: The size is counted as the number of bytes occupied,\n\ ! 1568: which includes both saved text and other data."); ! 1569: undo_high_threshold = 20000; ! 1570: ! 1571: defsubr (&Scons); ! 1572: defsubr (&Slist); ! 1573: defsubr (&Svector); ! 1574: defsubr (&Smake_list); ! 1575: defsubr (&Smake_vector); ! 1576: defsubr (&Smake_string); ! 1577: defsubr (&Smake_symbol); ! 1578: defsubr (&Smake_marker); ! 1579: defsubr (&Spurecopy); ! 1580: defsubr (&Sgarbage_collect); ! 1581: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.