X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/bbc012e0c3a0e91beecb09643956fa09979420ab..d2ad6275c8b11d33d6bbfa9359420d534aa641bc:/src/alloc.c diff --git a/src/alloc.c b/src/alloc.c index f3af3940e1..ea52c98fd2 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1,6 +1,6 @@ /* Storage allocation and gc for GNU Emacs Lisp interpreter. Copyright (C) 1985, 1986, 1988, 1993, 1994, 1995, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -16,8 +16,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ #include #include @@ -49,7 +49,7 @@ Boston, MA 02111-1307, USA. */ #include "keyboard.h" #include "frame.h" #include "blockinput.h" -#include "charset.h" +#include "character.h" #include "syssignal.h" #include @@ -66,6 +66,14 @@ Boston, MA 02111-1307, USA. */ extern POINTER_TYPE *sbrk (); #endif +#ifdef HAVE_FCNTL_H +#define INCLUDED_FCNTL +#include +#endif +#ifndef O_WRONLY +#define O_WRONLY 1 +#endif + #ifdef DOUG_LEA_MALLOC #include @@ -138,6 +146,8 @@ static pthread_mutex_t alloc_mutex; static __malloc_size_t bytes_used_when_full; +static __malloc_size_t bytes_used_when_reconsidered; + /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer to a struct Lisp_String. */ @@ -172,10 +182,21 @@ EMACS_INT misc_objects_consed; EMACS_INT intervals_consed; EMACS_INT strings_consed; -/* Number of bytes of consing since GC before another GC should be done. */ +/* Minimum number of bytes of consing since GC before next GC. */ EMACS_INT gc_cons_threshold; +/* Similar minimum, computed from Vgc_cons_percentage. */ + +EMACS_INT gc_relative_threshold; + +static Lisp_Object Vgc_cons_percentage; + +/* Minimum number of bytes of consing since GC before next GC, + when memory is full. */ + +EMACS_INT memory_full_cons_threshold; + /* Nonzero during GC. */ int gc_in_progress; @@ -207,11 +228,12 @@ static int total_free_conses, total_free_markers, total_free_symbols; static int total_free_floats, total_floats; /* Points to memory space allocated as "spare", to be freed if we run - out of memory. */ + out of memory. We keep one large block, four cons-blocks, and + two string blocks. */ -static char *spare_memory; +char *spare_memory[7]; -/* Amount of spare memory to keep in reserve. */ +/* Amount of spare memory to keep in large reserve block. */ #define SPARE_MEMORY (1 << 14) @@ -344,6 +366,11 @@ enum mem_type MEM_TYPE_WINDOW }; +static POINTER_TYPE *lisp_align_malloc P_ ((size_t, enum mem_type)); +static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type)); +void refill_memory_reserve (); + + #if GC_MARK_STACK || defined GC_MALLOC_CHECK #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES @@ -444,6 +471,7 @@ static void mem_delete P_ ((struct mem_node *)); static void mem_delete_fixup P_ ((struct mem_node *)); static INLINE struct mem_node *mem_find P_ ((void *)); + #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS static void check_gcpros P_ ((void)); #endif @@ -504,37 +532,11 @@ display_malloc_warning () #ifdef DOUG_LEA_MALLOC -# define BYTES_USED (mallinfo ().arena) +# define BYTES_USED (mallinfo ().uordblks) #else # define BYTES_USED _bytes_used #endif - - -/* Called if malloc returns zero. */ - -void -memory_full () -{ - Vmemory_full = Qt; - -#ifndef SYSTEM_MALLOC - bytes_used_when_full = BYTES_USED; -#endif - - /* The first time we get here, free the spare memory. */ - if (spare_memory) - { - free (spare_memory); - spare_memory = 0; - } - - /* This used to call error, but if we've run out of memory, we could - get infinite recursion trying to build the string. */ - while (1) - Fsignal (Qnil, Vmemory_signal_data); -} - - + /* Called if we can't allocate relocatable space for a buffer. */ void @@ -551,8 +553,6 @@ buffer_memory_full () memory_full (); #endif - Vmemory_full = Qt; - /* This used to call error, but if we've run out of memory, we could get infinite recursion trying to build the string. */ while (1) @@ -778,6 +778,9 @@ xfree (block) BLOCK_INPUT; free (block); UNBLOCK_INPUT; + /* We don't call refill_memory_reserve here + because that duplicates doing so in emacs_blocked_free + and the criterion should go there. */ } @@ -1102,6 +1105,9 @@ lisp_align_free (block) } eassert ((aligned & 1) == aligned); eassert (i == (aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1)); +#ifdef HAVE_POSIX_MEMALIGN + eassert ((unsigned long)ABLOCKS_BASE (abase) % BLOCK_ALIGN == 0); +#endif free (ABLOCKS_BASE (abase)); } UNBLOCK_INPUT; @@ -1122,20 +1128,6 @@ allocate_buffer () #ifndef SYSTEM_MALLOC -/* If we released our reserve (due to running out of memory), - and we have a fair amount free once again, - try to set aside another reserve in case we run out once more. - - This is called when a relocatable block is freed in ralloc.c. */ - -void -refill_memory_reserve () -{ - if (spare_memory == 0) - spare_memory = (char *) malloc ((size_t) SPARE_MEMORY); -} - - /* Arranging to disable input signals while we're in malloc. This only works with GNU malloc. To help out systems which can't @@ -1149,21 +1141,24 @@ refill_memory_reserve () #ifndef SYNC_INPUT #ifndef DOUG_LEA_MALLOC -extern void * (*__malloc_hook) P_ ((size_t)); -extern void * (*__realloc_hook) P_ ((void *, size_t)); -extern void (*__free_hook) P_ ((void *)); +extern void * (*__malloc_hook) P_ ((size_t, const void *)); +extern void * (*__realloc_hook) P_ ((void *, size_t, const void *)); +extern void (*__free_hook) P_ ((void *, const void *)); /* Else declared in malloc.h, perhaps with an extra arg. */ #endif /* DOUG_LEA_MALLOC */ -static void * (*old_malloc_hook) (); -static void * (*old_realloc_hook) (); -static void (*old_free_hook) (); +static void * (*old_malloc_hook) P_ ((size_t, const void *)); +static void * (*old_realloc_hook) P_ ((void *, size_t, const void*)); +static void (*old_free_hook) P_ ((void*, const void*)); /* This function is used as the hook for free to call. */ static void -emacs_blocked_free (ptr) +emacs_blocked_free (ptr, ptr2) void *ptr; + const void *ptr2; { + EMACS_INT bytes_used_now; + BLOCK_INPUT_ALLOC; #ifdef GC_MALLOC_CHECK @@ -1192,14 +1187,15 @@ emacs_blocked_free (ptr) /* If we released our reserve (due to running out of memory), and we have a fair amount free once again, try to set aside another reserve in case we run out once more. */ - if (spare_memory == 0 + if (! NILP (Vmemory_full) /* Verify there is enough space that even with the malloc hysteresis this call won't run out again. The code here is correct as long as SPARE_MEMORY is substantially larger than the block size malloc uses. */ && (bytes_used_when_full - > BYTES_USED + max (malloc_hysteresis, 4) * SPARE_MEMORY)) - spare_memory = (char *) malloc ((size_t) SPARE_MEMORY); + > ((bytes_used_when_reconsidered = BYTES_USED) + + max (malloc_hysteresis, 4) * SPARE_MEMORY))) + refill_memory_reserve (); __free_hook = emacs_blocked_free; UNBLOCK_INPUT_ALLOC; @@ -1209,8 +1205,9 @@ emacs_blocked_free (ptr) /* This function is the malloc hook that Emacs uses. */ static void * -emacs_blocked_malloc (size) +emacs_blocked_malloc (size, ptr) size_t size; + const void *ptr; { void *value; @@ -1256,9 +1253,10 @@ emacs_blocked_malloc (size) /* This function is the realloc hook that Emacs uses. */ static void * -emacs_blocked_realloc (ptr, size) +emacs_blocked_realloc (ptr, size, ptr2) void *ptr; size_t size; + const void *ptr2; { void *value; @@ -1424,6 +1422,12 @@ make_interval () { INTERVAL val; + /* eassert (!handling_signal); */ + +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif + if (interval_free_list) { val = interval_free_list; @@ -1445,6 +1449,11 @@ make_interval () } val = &interval_block->intervals[interval_block_index++]; } + +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + consing_since_gc += sizeof (struct interval); intervals_consed++; RESET_INTERVAL (val); @@ -1678,7 +1687,7 @@ static int total_string_size; /* We check for overrun in string data blocks by appending a small "cookie" after each allocated string data block, and check for the - presense of this cookie during GC. */ + presence of this cookie during GC. */ #define GC_STRING_OVERRUN_COOKIE_SIZE 4 static char string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] = @@ -1842,6 +1851,12 @@ allocate_string () { struct Lisp_String *s; + /* eassert (!handling_signal); */ + +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif + /* If the free-list is empty, allocate a new string_block, and add all the Lisp_Strings in it to the free-list. */ if (string_free_list == NULL) @@ -1871,6 +1886,10 @@ allocate_string () s = string_free_list; string_free_list = NEXT_FREE_LISP_STRING (s); +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + /* Probably not strictly necessary, but play it safe. */ bzero (s, sizeof *s); @@ -1918,6 +1937,12 @@ allocate_string_data (s, nchars, nbytes) /* Determine the number of bytes needed to store NBYTES bytes of string data. */ needed = SDATA_SIZE (nbytes); + old_data = s->data ? SDATA_OF_STRING (s) : NULL; + old_nbytes = GC_STRING_BYTES (s); + +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif if (nbytes > LARGE_STRING_BYTES) { @@ -1972,10 +1997,13 @@ allocate_string_data (s, nchars, nbytes) else b = current_sblock; - old_data = s->data ? SDATA_OF_STRING (s) : NULL; - old_nbytes = GC_STRING_BYTES (s); - data = b->next_free; + b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); + +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + data->string = s; s->data = SDATA_DATA (data); #ifdef GC_CHECK_STRING_BYTES @@ -1988,7 +2016,6 @@ allocate_string_data (s, nchars, nbytes) bcopy (string_overrun_cookie, (char *) data + needed, GC_STRING_OVERRUN_COOKIE_SIZE); #endif - b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); /* If S had already data assigned, mark that as free by setting its string back-pointer to null, and recording the size of the data @@ -2241,7 +2268,7 @@ INIT must be an integer that represents a character. */) CHECK_NUMBER (init); c = XINT (init); - if (SINGLE_BYTE_CHAR_P (c)) + if (ASCII_CHAR_P (c)) { nbytes = XINT (length); val = make_uninit_string (nbytes); @@ -2272,7 +2299,7 @@ INIT must be an integer that represents a character. */) DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, - doc: /* Return a new bool-vector of length LENGTH, using INIT for as each element. + doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. LENGTH must be a number. INIT matters only in whether it is t or nil. */) (length, init) Lisp_Object length, init; @@ -2544,7 +2571,7 @@ void free_float (ptr) struct Lisp_Float *ptr; { - *(struct Lisp_Float **)&ptr->data = float_free_list; + ptr->u.chain = float_free_list; float_free_list = ptr; } @@ -2557,12 +2584,18 @@ make_float (float_value) { register Lisp_Object val; + /* eassert (!handling_signal); */ + +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif + if (float_free_list) { /* We use the data field for chaining the free list so that we won't use the same field that has the mark bit. */ XSETFLOAT (val, float_free_list); - float_free_list = *(struct Lisp_Float **)&float_free_list->data; + float_free_list = float_free_list->u.chain; } else { @@ -2582,6 +2615,10 @@ make_float (float_value) float_block_index++; } +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + XFLOAT_DATA (val) = float_value; eassert (!FLOAT_MARKED_P (XFLOAT (val))); consing_since_gc += sizeof (struct Lisp_Float); @@ -2662,7 +2699,7 @@ void free_cons (ptr) struct Lisp_Cons *ptr; { - *(struct Lisp_Cons **)&ptr->cdr = cons_free_list; + ptr->u.chain = cons_free_list; #if GC_MARK_STACK ptr->car = Vdead; #endif @@ -2676,12 +2713,18 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, { register Lisp_Object val; + /* eassert (!handling_signal); */ + +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif + if (cons_free_list) { /* We use the cdr for chaining the free list so that we won't use the same field that has the mark bit. */ XSETCONS (val, cons_free_list); - cons_free_list = *(struct Lisp_Cons **)&cons_free_list->cdr; + cons_free_list = cons_free_list->u.chain; } else { @@ -2700,6 +2743,10 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, cons_block_index++; } +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + XSETCAR (val, car); XSETCDR (val, cdr); eassert (!CONS_MARKED_P (XCONS (val))); @@ -2716,7 +2763,7 @@ check_cons_list () struct Lisp_Cons *tail = cons_free_list; while (tail) - tail = *(struct Lisp_Cons **)&tail->cdr; + tail = tail->u.chain; #endif } @@ -2857,6 +2904,9 @@ allocate_vectorlike (len, type) UNBLOCK_INPUT; #endif + /* This gets triggered by code which I haven't bothered to fix. --Stef */ + /* eassert (!handling_signal); */ + nbytes = sizeof *p + (len - 1) * sizeof p->contents[0]; p = (struct Lisp_Vector *) lisp_malloc (nbytes, type); @@ -2870,8 +2920,17 @@ allocate_vectorlike (len, type) consing_since_gc += nbytes; vector_cells_consed += len; +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif + p->next = all_vectors; all_vectors = p; + +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + ++n_vectors; return p; } @@ -2988,49 +3047,6 @@ See also the function `vector'. */) } -DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0, - doc: /* Return a newly created char-table, with purpose PURPOSE. -Each element is initialized to INIT, which defaults to nil. -PURPOSE should be a symbol which has a `char-table-extra-slots' property. -The property's value should be an integer between 0 and 10. */) - (purpose, init) - register Lisp_Object purpose, init; -{ - Lisp_Object vector; - Lisp_Object n; - CHECK_SYMBOL (purpose); - n = Fget (purpose, Qchar_table_extra_slots); - CHECK_NUMBER (n); - if (XINT (n) < 0 || XINT (n) > 10) - args_out_of_range (n, Qnil); - /* Add 2 to the size for the defalt and parent slots. */ - vector = Fmake_vector (make_number (CHAR_TABLE_STANDARD_SLOTS + XINT (n)), - init); - XCHAR_TABLE (vector)->top = Qt; - XCHAR_TABLE (vector)->parent = Qnil; - XCHAR_TABLE (vector)->purpose = purpose; - XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); - return vector; -} - - -/* Return a newly created sub char table with default value DEFALT. - Since a sub char table does not appear as a top level Emacs Lisp - object, we don't need a Lisp interface to make it. */ - -Lisp_Object -make_sub_char_table (defalt) - Lisp_Object defalt; -{ - Lisp_Object vector - = Fmake_vector (make_number (SUB_CHAR_TABLE_STANDARD_SLOTS), Qnil); - XCHAR_TABLE (vector)->top = Qnil; - XCHAR_TABLE (vector)->defalt = defalt; - XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); - return vector; -} - - DEFUN ("vector", Fvector, Svector, 0, MANY, 0, doc: /* Return a newly created vector with specified arguments as elements. Any number of arguments, even zero arguments, are allowed. @@ -3150,10 +3166,16 @@ Its value and function definition are void, and its property list is nil. */) CHECK_STRING (name); + /* eassert (!handling_signal); */ + +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif + if (symbol_free_list) { XSETSYMBOL (val, symbol_free_list); - symbol_free_list = *(struct Lisp_Symbol **)&symbol_free_list->value; + symbol_free_list = symbol_free_list->next; } else { @@ -3171,6 +3193,10 @@ Its value and function definition are void, and its property list is nil. */) symbol_block_index++; } +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + p = XSYMBOL (val); p->xname = name; p->plist = Qnil; @@ -3230,6 +3256,12 @@ allocate_misc () { Lisp_Object val; + /* eassert (!handling_signal); */ + +#ifndef SYNC_INPUT + BLOCK_INPUT; +#endif + if (marker_free_list) { XSETMISC (val, marker_free_list); @@ -3252,6 +3284,10 @@ allocate_misc () marker_block_index++; } +#ifndef SYNC_INPUT + UNBLOCK_INPUT; +#endif + --total_free_markers; consing_since_gc += sizeof (union Lisp_Misc); misc_objects_consed++; @@ -3362,6 +3398,83 @@ make_event_array (nargs, args) } + +/************************************************************************ + Memory Full Handling + ************************************************************************/ + + +/* Called if malloc returns zero. */ + +void +memory_full () +{ + int i; + + Vmemory_full = Qt; + + memory_full_cons_threshold = sizeof (struct cons_block); + + /* The first time we get here, free the spare memory. */ + for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++) + if (spare_memory[i]) + { + if (i == 0) + free (spare_memory[i]); + else if (i >= 1 && i <= 4) + lisp_align_free (spare_memory[i]); + else + lisp_free (spare_memory[i]); + spare_memory[i] = 0; + } + + /* Record the space now used. When it decreases substantially, + we can refill the memory reserve. */ +#ifndef SYSTEM_MALLOC + bytes_used_when_full = BYTES_USED; +#endif + + /* This used to call error, but if we've run out of memory, we could + get infinite recursion trying to build the string. */ + while (1) + Fsignal (Qnil, Vmemory_signal_data); +} + +/* If we released our reserve (due to running out of memory), + and we have a fair amount free once again, + try to set aside another reserve in case we run out once more. + + This is called when a relocatable block is freed in ralloc.c, + and also directly from this file, in case we're not using ralloc.c. */ + +void +refill_memory_reserve () +{ +#ifndef SYSTEM_MALLOC + if (spare_memory[0] == 0) + spare_memory[0] = (char *) malloc ((size_t) SPARE_MEMORY); + if (spare_memory[1] == 0) + spare_memory[1] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[2] == 0) + spare_memory[2] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[3] == 0) + spare_memory[3] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[4] == 0) + spare_memory[4] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[5] == 0) + spare_memory[5] = (char *) lisp_malloc (sizeof (struct string_block), + MEM_TYPE_STRING); + if (spare_memory[6] == 0) + spare_memory[6] = (char *) lisp_malloc (sizeof (struct string_block), + MEM_TYPE_STRING); + if (spare_memory[0] && spare_memory[1] && spare_memory[5]) + Vmemory_full = Qnil; +#endif +} /************************************************************************ C Stack Marking @@ -4420,10 +4533,96 @@ mark_stack () #endif } - #endif /* GC_MARK_STACK != 0 */ + +/* Return 1 if OBJ is a valid lisp object. + Return 0 if OBJ is NOT a valid lisp object. + Return -1 if we cannot validate OBJ. + This function can be quite slow, + so it should only be used in code for manual debugging. */ + +int +valid_lisp_object_p (obj) + Lisp_Object obj; +{ + void *p; +#if !GC_MARK_STACK + int fd; +#else + struct mem_node *m; +#endif + + if (INTEGERP (obj)) + return 1; + + p = (void *) XPNTR (obj); + if (PURE_POINTER_P (p)) + return 1; + +#if !GC_MARK_STACK + /* We need to determine whether it is safe to access memory at + address P. Obviously, we cannot just access it (we would SEGV + trying), so we trick the o/s to tell us whether p is a valid + pointer. Unfortunately, we cannot use NULL_DEVICE here, as + emacs_write may not validate p in that case. */ + if ((fd = emacs_open ("__Valid__Lisp__Object__", O_CREAT | O_WRONLY | O_TRUNC, 0666)) >= 0) + { + int valid = (emacs_write (fd, (char *)p, 16) == 16); + emacs_close (fd); + unlink ("__Valid__Lisp__Object__"); + return valid; + } + + return -1; +#else + + m = mem_find (p); + + if (m == MEM_NIL) + return 0; + + switch (m->type) + { + case MEM_TYPE_NON_LISP: + return 0; + + case MEM_TYPE_BUFFER: + return live_buffer_p (m, p); + + case MEM_TYPE_CONS: + return live_cons_p (m, p); + + case MEM_TYPE_STRING: + return live_string_p (m, p); + + case MEM_TYPE_MISC: + return live_misc_p (m, p); + + case MEM_TYPE_SYMBOL: + return live_symbol_p (m, p); + + case MEM_TYPE_FLOAT: + return live_float_p (m, p); + + case MEM_TYPE_VECTOR: + case MEM_TYPE_PROCESS: + case MEM_TYPE_HASH_TABLE: + case MEM_TYPE_FRAME: + case MEM_TYPE_WINDOW: + return live_vector_p (m, p); + + default: + break; + } + + return 0; +#endif +} + + + /*********************************************************************** Pure Storage Management @@ -4482,7 +4681,7 @@ void check_pure_size () { if (pure_bytes_used_before_overflow) - message ("Pure Lisp storage overflow (approx. %d bytes needed)", + message ("emacs:0:Pure Lisp storage overflow (approx. %d bytes needed)", (int) (pure_bytes_used + pure_bytes_used_before_overflow)); } @@ -4569,7 +4768,7 @@ make_pure_vector (len) DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, - doc: /* Make a copy of OBJECT in pure storage. + doc: /* Make a copy of object OBJ in pure storage. Recursively copies contents of vectors and cons cells. Does not copy symbols. Copies strings without text properties. */) (obj) @@ -4891,6 +5090,24 @@ returns nil, because real GC can't be done. */) if (gc_cons_threshold < 10000) gc_cons_threshold = 10000; + if (FLOATP (Vgc_cons_percentage)) + { /* Set gc_cons_combined_threshold. */ + EMACS_INT total = 0; + + total += total_conses * sizeof (struct Lisp_Cons); + total += total_symbols * sizeof (struct Lisp_Symbol); + total += total_markers * sizeof (union Lisp_Misc); + total += total_string_size; + total += total_vector_size * sizeof (Lisp_Object); + total += total_floats * sizeof (struct Lisp_Float); + total += total_intervals * sizeof (struct interval); + total += total_strings * sizeof (struct Lisp_String); + + gc_relative_threshold = total * XFLOAT_DATA (Vgc_cons_percentage); + } + else + gc_relative_threshold = 0; + if (garbage_collection_messages) { if (message_p || minibuf_level > 0) @@ -5412,14 +5629,14 @@ mark_object (arg) CHECK_ALLOCATED_AND_LIVE (live_cons_p); CONS_MARK (ptr); /* If the cdr is nil, avoid recursion for the car. */ - if (EQ (ptr->cdr, Qnil)) + if (EQ (ptr->u.cdr, Qnil)) { obj = ptr->car; cdr_count = 0; goto loop; } mark_object (ptr->car); - obj = ptr->cdr; + obj = ptr->u.cdr; cdr_count++; if (cdr_count == mark_object_loop_halt) abort (); @@ -5566,7 +5783,7 @@ gc_sweep () if (!CONS_MARKED_P (&cblk->conses[i])) { this_free++; - *(struct Lisp_Cons **)&cblk->conses[i].cdr = cons_free_list; + cblk->conses[i].u.chain = cons_free_list; cons_free_list = &cblk->conses[i]; #if GC_MARK_STACK cons_free_list->car = Vdead; @@ -5585,7 +5802,7 @@ gc_sweep () { *cprev = cblk->next; /* Unhook from the free list. */ - cons_free_list = *(struct Lisp_Cons **) &cblk->conses[0].cdr; + cons_free_list = cblk->conses[0].u.chain; lisp_align_free (cblk); n_cons_blocks--; } @@ -5616,7 +5833,7 @@ gc_sweep () if (!FLOAT_MARKED_P (&fblk->floats[i])) { this_free++; - *(struct Lisp_Float **)&fblk->floats[i].data = float_free_list; + fblk->floats[i].u.chain = float_free_list; float_free_list = &fblk->floats[i]; } else @@ -5632,7 +5849,7 @@ gc_sweep () { *fprev = fblk->next; /* Unhook from the free list. */ - float_free_list = *(struct Lisp_Float **) &fblk->floats[0].data; + float_free_list = fblk->floats[0].u.chain; lisp_align_free (fblk); n_float_blocks--; } @@ -5720,7 +5937,7 @@ gc_sweep () if (!sym->gcmarkbit && !pure_p) { - *(struct Lisp_Symbol **) &sym->value = symbol_free_list; + sym->next = symbol_free_list; symbol_free_list = sym; #if GC_MARK_STACK symbol_free_list->function = Vdead; @@ -5744,7 +5961,7 @@ gc_sweep () { *sprev = sblk->next; /* Unhook from the free list. */ - symbol_free_list = *(struct Lisp_Symbol **)&sblk->symbols[0].value; + symbol_free_list = sblk->symbols[0].next; lisp_free (sblk); n_symbol_blocks--; } @@ -5972,7 +6189,7 @@ init_alloc_once () malloc_hysteresis = 0; #endif - spare_memory = (char *) malloc (SPARE_MEMORY); + refill_memory_reserve (); ignore_warnings = 0; gcprolist = 0; @@ -5980,6 +6197,8 @@ init_alloc_once () staticidx = 0; consing_since_gc = 0; gc_cons_threshold = 100000 * sizeof (Lisp_Object); + gc_relative_threshold = 0; + #ifdef VIRT_ADDR_VARIES malloc_sbrk_unused = 1<<22; /* A large number */ malloc_sbrk_used = 100000; /* as reasonable as any number */ @@ -6011,7 +6230,15 @@ allocated since the last garbage collection. All data types count. Garbage collection happens automatically only when `eval' is called. By binding this temporarily to a large number, you can effectively -prevent garbage collection during a part of the program. */); +prevent garbage collection during a part of the program. +See also `gc-cons-percentage'. */); + + DEFVAR_LISP ("gc-cons-percentage", &Vgc_cons_percentage, + doc: /* *Portion of the heap used for allocation. +Garbage collection can happen automatically once this portion of the heap +has been allocated since the last garbage collection. +If this portion is smaller than `gc-cons-threshold', this is ignored. */); + Vgc_cons_percentage = make_float (0.1); DEFVAR_INT ("pure-bytes-used", &pure_bytes_used, doc: /* Number of bytes of sharable Lisp data allocated so far. */); @@ -6063,7 +6290,7 @@ This means that certain objects should be allocated in shared (pure) space. */) build_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs")); DEFVAR_LISP ("memory-full", &Vmemory_full, - doc: /* Non-nil means we are handling a memory-full error. */); + doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); Vmemory_full = Qnil; staticpro (&Qgc_cons_threshold); @@ -6084,7 +6311,6 @@ The time is in seconds as a floating point value. */); defsubr (&Smake_byte_code); defsubr (&Smake_list); defsubr (&Smake_vector); - defsubr (&Smake_char_table); defsubr (&Smake_string); defsubr (&Smake_bool_vector); defsubr (&Smake_symbol);