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