Mercurial > emacs
changeset 36435:5a989d353a68
(toplevel): Include process.h.
(enum mem_type): Add MEM_TYPE_PROCESS, MEM_TYPE_HASH_TABLE,
MEM_TYPE_FRAME, MEM_TYPE_WINDOW enumerators.
(allocate_vectorlike): Make it a static function. Add parameter TYPE.
(allocate_vector, allocate_hash_table, allocate_window)
(allocate_frame, allocate_process, allocate_other_vector): New
functions.
(Fmake_vector): Call allocate_vector instead of allocate_vectorlike.
(mark_maybe_pointer): New function.
(mark_memory): Also mark Lisp data to which only pointers
remain and not Lisp_Objects.
(min_heap_address, max_heap_address): New variables.
(mem_find): Return MEM_NIL if START is below min_heap_address or
above max_heap_address.
(mem_insert): Compute min_heap_address and max_heap_address.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Wed, 28 Feb 2001 13:29:33 +0000 |
parents | 40cfe4976f04 |
children | 449e5681ae47 |
files | src/alloc.c |
diffstat | 1 files changed, 252 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/alloc.c Wed Feb 28 13:29:03 2001 +0000 +++ b/src/alloc.c Wed Feb 28 13:29:33 2001 +0000 @@ -39,6 +39,7 @@ #undef HIDE_LISP_IMPLEMENTATION #include "lisp.h" +#include "process.h" #include "intervals.h" #include "puresize.h" #include "buffer.h" @@ -276,7 +277,14 @@ MEM_TYPE_MISC, MEM_TYPE_SYMBOL, MEM_TYPE_FLOAT, - MEM_TYPE_VECTOR + /* Keep the following vector-like types together, with + MEM_TYPE_WINDOW being the last, and MEM_TYPE_VECTOR the + first. Or change the code of live_vector_p, for instance. */ + MEM_TYPE_VECTOR, + MEM_TYPE_PROCESS, + MEM_TYPE_HASH_TABLE, + MEM_TYPE_FRAME, + MEM_TYPE_WINDOW }; #if GC_MARK_STACK || defined GC_MALLOC_CHECK @@ -343,12 +351,17 @@ static struct mem_node *mem_root; +/* Lowest and highest known address in the heap. */ + +static void *min_heap_address, *max_heap_address; + /* Sentinel node of the tree. */ static struct mem_node mem_z; #define MEM_NIL &mem_z static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type)); +static struct Lisp_Vector *allocate_vectorlike P_ ((EMACS_INT, enum mem_type)); static void lisp_free P_ ((POINTER_TYPE *)); static void mark_stack P_ ((void)); static void init_stack P_ ((Lisp_Object *)); @@ -398,6 +411,7 @@ #define ALIGN(SZ, ALIGNMENT) \ (((SZ) + (ALIGNMENT) - 1) & ~((ALIGNMENT) - 1)) + /************************************************************************ Malloc @@ -2195,9 +2209,10 @@ /* Value is a pointer to a newly allocated Lisp_Vector structure with room for LEN Lisp_Objects. */ -struct Lisp_Vector * -allocate_vectorlike (len) +static struct Lisp_Vector * +allocate_vectorlike (len, type) EMACS_INT len; + enum mem_type type; { struct Lisp_Vector *p; size_t nbytes; @@ -2210,7 +2225,7 @@ #endif nbytes = sizeof *p + (len - 1) * sizeof p->contents[0]; - p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTOR); + p = (struct Lisp_Vector *) lisp_malloc (nbytes, type); #ifdef DOUG_LEA_MALLOC /* Back to a reasonable maximum of mmap'ed areas. */ @@ -2228,6 +2243,94 @@ } +/* Allocate a vector with NSLOTS slots. */ + +struct Lisp_Vector * +allocate_vector (nslots) + EMACS_INT nslots; +{ + struct Lisp_Vector *v = allocate_vectorlike (nslots, MEM_TYPE_VECTOR); + v->size = nslots; + return v; +} + + +/* Allocate other vector-like structures. */ + +struct Lisp_Hash_Table * +allocate_hash_table () +{ + EMACS_INT len = VECSIZE (struct Lisp_Hash_Table); + struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_HASH_TABLE); + EMACS_INT i; + + v->size = len; + for (i = 0; i < len; ++i) + v->contents[i] = Qnil; + + return (struct Lisp_Hash_Table *) v; +} + + +struct window * +allocate_window () +{ + EMACS_INT len = VECSIZE (struct window); + struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_WINDOW); + EMACS_INT i; + + for (i = 0; i < len; ++i) + v->contents[i] = Qnil; + v->size = len; + + return (struct window *) v; +} + + +struct frame * +allocate_frame () +{ + EMACS_INT len = VECSIZE (struct frame); + struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_FRAME); + EMACS_INT i; + + for (i = 0; i < len; ++i) + v->contents[i] = make_number (0); + v->size = len; + return (struct frame *) v; +} + + +struct Lisp_Process * +allocate_process () +{ + EMACS_INT len = VECSIZE (struct Lisp_Process); + struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_PROCESS); + EMACS_INT i; + + for (i = 0; i < len; ++i) + v->contents[i] = Qnil; + v->size = len; + + return (struct Lisp_Process *) v; +} + + +struct Lisp_Vector * +allocate_other_vector (len) + EMACS_INT len; +{ + struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_VECTOR); + EMACS_INT i; + + for (i = 0; i < len; ++i) + v->contents[i] = Qnil; + v->size = len; + + return v; +} + + DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, "Return a newly created vector of length LENGTH, with each element being INIT.\n\ See also the function `vector'.") @@ -2242,8 +2345,7 @@ CHECK_NATNUM (length, 0); sizei = XFASTINT (length); - p = allocate_vectorlike (sizei); - p->size = sizei; + p = allocate_vector (sizei); for (index = 0; index < sizei; index++) p->contents[index] = init; @@ -2622,6 +2724,9 @@ { struct mem_node *p; + if (start < min_heap_address || start > max_heap_address) + return MEM_NIL; + /* Make the search always successful to speed up the loop below. */ mem_z.start = start; mem_z.end = (char *) start + 1; @@ -2644,6 +2749,11 @@ { struct mem_node *c, *parent, *x; + if (start < min_heap_address) + min_heap_address = start; + if (end > max_heap_address) + max_heap_address = end; + /* See where in the tree a node for START belongs. In this particular application, it shouldn't happen that a node is already present. For debugging purposes, let's check that. */ @@ -3124,7 +3234,9 @@ struct mem_node *m; void *p; { - return m->type == MEM_TYPE_VECTOR && p == m->start; + return (p == m->start + && m->type >= MEM_TYPE_VECTOR + && m->type <= MEM_TYPE_WINDOW); } @@ -3276,14 +3388,123 @@ } } } + + +/* If P points to Lisp data, mark that as live if it isn't already + marked. */ + +static INLINE void +mark_maybe_pointer (p) + void *p; +{ + struct mem_node *m; + + /* Quickly rule out some values which can't point to Lisp data. We + assume that Lisp data is aligned on even addresses. */ + if ((EMACS_INT) p & 1) + return; + + m = mem_find (p); + if (m != MEM_NIL) + { + Lisp_Object obj = Qnil; + + switch (m->type) + { + case MEM_TYPE_NON_LISP: + /* NOthing to do; not a pointer to Lisp memory. */ + break; -/* Mark Lisp objects in the address range START..END. */ + case MEM_TYPE_BUFFER: + if (live_buffer_p (m, p) + && !XMARKBIT (((struct buffer *) p)->name)) + XSETVECTOR (obj, p); + break; + + case MEM_TYPE_CONS: + if (live_cons_p (m, p) + && !XMARKBIT (((struct Lisp_Cons *) p)->car)) + XSETCONS (obj, p); + break; + + case MEM_TYPE_STRING: + if (live_string_p (m, p) + && !STRING_MARKED_P ((struct Lisp_String *) p)) + XSETSTRING (obj, p); + break; + + case MEM_TYPE_MISC: + if (live_misc_p (m, p)) + { + Lisp_Object tem; + XSETMISC (tem, p); + + switch (XMISCTYPE (tem)) + { + case Lisp_Misc_Marker: + if (!XMARKBIT (XMARKER (tem)->chain)) + obj = tem; + break; + + case Lisp_Misc_Buffer_Local_Value: + case Lisp_Misc_Some_Buffer_Local_Value: + if (!XMARKBIT (XBUFFER_LOCAL_VALUE (tem)->realvalue)) + obj = tem; + break; + + case Lisp_Misc_Overlay: + if (!XMARKBIT (XOVERLAY (tem)->plist)) + obj = tem; + break; + } + } + break; + + case MEM_TYPE_SYMBOL: + if (live_symbol_p (m, p) + && !XMARKBIT (((struct Lisp_Symbol *) p)->plist)) + XSETSYMBOL (obj, p); + break; + + case MEM_TYPE_FLOAT: + if (live_float_p (m, p) + && !XMARKBIT (((struct Lisp_Float *) p)->type)) + XSETFLOAT (obj, p); + break; + + case MEM_TYPE_VECTOR: + case MEM_TYPE_PROCESS: + case MEM_TYPE_HASH_TABLE: + case MEM_TYPE_FRAME: + case MEM_TYPE_WINDOW: + if (live_vector_p (m, p)) + { + Lisp_Object tem; + XSETVECTOR (tem, p); + if (!GC_SUBRP (tem) + && !(XVECTOR (tem)->size & ARRAY_MARK_FLAG)) + obj = tem; + } + break; + + default: + abort (); + } + + if (!GC_NILP (obj)) + mark_object (&obj); + } +} + + +/* Mark Lisp objects referenced from the address range START..END. */ static void mark_memory (start, end) void *start, *end; { Lisp_Object *p; + void **pp; #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES nzombies = 0; @@ -3297,9 +3518,31 @@ start = end; end = tem; } - + + /* Mark Lisp_Objects. */ for (p = (Lisp_Object *) start; (void *) p < end; ++p) mark_maybe_object (*p); + + /* Mark Lisp data pointed to. This is necessary because, in some + situations, the C compiler optimizes Lisp objects away, so that + only a pointer to them remains. Example: + + DEFUN ("testme", Ftestme, Stestme, 0, 0, 0, "") + () + { + Lisp_Object obj = build_string ("test"); + struct Lisp_String *s = XSTRING (obj); + Fgarbage_collect (); + fprintf (stderr, "test `%s'\n", s->data); + return Qnil; + } + + Here, `obj' isn't really used, and the compiler optimizes it + away. The only reference to the life string is through the + pointer `s'. */ + + for (pp = (void **) start; (void *) pp < end; ++pp) + mark_maybe_pointer (*pp); }