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