Annotation of GNUtools/emacs/src/alloc.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.