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