Annotation of 43BSDReno/contrib/emacs-18.55/src/alloc.c, revision 1.1.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 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: }

unix.superglobalmegacorp.com

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