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