From 28be1ada0fb9a4b51cf361dc45208e764bd34143 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 19 Jun 2012 20:56:28 +0400 Subject: * alloc.c, bytecode.c, ccl.c, coding.c, composite.c, data.c, dosfns.c: * font.c, image.c, keyboard.c, lread.c, menu.c, minibuf.c, msdos.c: * print.c, syntax.c, window.c, xmenu.c, xselect.c: Replace direct access to `contents' member of Lisp_Vector objects with AREF and ASET where appropriate. --- src/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 5c6297faae5..7af3b17078e 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5294,7 +5294,7 @@ Does not copy symbols. Copies strings without text properties. */) size &= PSEUDOVECTOR_SIZE_MASK; vec = XVECTOR (make_pure_vector (size)); for (i = 0; i < size; i++) - vec->contents[i] = Fpurecopy (XVECTOR (obj)->contents[i]); + vec->contents[i] = Fpurecopy (AREF (obj, i)); if (COMPILEDP (obj)) { XSETPVECTYPE (vec, PVEC_COMPILED); -- cgit v1.2.1 From d251c37c729a3c96ad10c5f6675370d371159534 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 22 Jun 2012 09:51:06 +0300 Subject: Enlarge NSTATICS to 0x650. src/alloc.c (NSTATICS): Enlarge to 0x650. Otherwise, Emacs compiled with -DENABLE_CHECKING -DXASSERTS -DGLYPH_DEBUG=1 -DBYTE_CODE_METER aborts in staticpro during startup. (Without -DBYTE_CODE_METER, staticidx goes up to 1597 out of 1600 = 0x640.) --- src/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 7af3b17078e..aba76386dd6 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -431,7 +431,7 @@ struct gcpro *gcprolist; /* Addresses of staticpro'd variables. Initialize it to a nonzero value; otherwise some compilers put it into BSS. */ -#define NSTATICS 0x640 +#define NSTATICS 0x650 static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag}; /* Index of next unused slot in staticvec. */ -- cgit v1.2.1 From d35af63cd671563fd188c3b0a1ef30067027c7aa Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 22 Jun 2012 14:17:42 -0700 Subject: Support higher-resolution time stamps. Fixes: debbugs:9000 --- src/alloc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index aba76386dd6..490632f282f 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5669,12 +5669,14 @@ See Info node `(elisp)Garbage Collection'. */) } /* Accumulate statistics. */ - EMACS_GET_TIME (t2); - EMACS_SUB_TIME (t3, t2, t1); if (FLOATP (Vgc_elapsed)) - Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) + - EMACS_SECS (t3) + - EMACS_USECS (t3) * 1.0e-6); + { + EMACS_GET_TIME (t2); + EMACS_SUB_TIME (t3, t2, t1); + Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) + + EMACS_TIME_TO_DOUBLE (t3)); + } + gcs_done++; return Flist (sizeof total / sizeof *total, total); -- cgit v1.2.1 From 1130ecfcacce9743078221b956cd07b352776442 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 26 Jun 2012 09:00:30 +0400 Subject: * src/alloc.c: Remove build_string. * src/lisp.h: Define build_string as static inline. This provides a better opportunity to optimize away calls to strlen when the function is called with compile-time constant argument. * src/image.c (imagemagick_error): Convert to build_string. * src/w32proc.c (sys_spawnve): Likewise. * src/xterm.c (x_term_init): Likewise. * admin/coccinelle/build_string.cocci: Semantic patch to convert from make_string to build_string. --- src/alloc.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 490632f282f..6f7cc968b81 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -2496,16 +2496,6 @@ make_specified_string (const char *contents, } -/* Make a string from the data at STR, treating it as multibyte if the - data warrants. */ - -Lisp_Object -build_string (const char *str) -{ - return make_string (str, strlen (str)); -} - - /* Return an unibyte Lisp_String set up to hold LENGTH characters occupying LENGTH bytes. */ -- cgit v1.2.1 From 62efea5e881407a178c5c291575facc17dca8a3f Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 26 Jun 2012 18:41:01 +0400 Subject: * alloc.c (allocate_window): Zero out non-Lisp part of newly allocated window. (allocate_process): Likewise for new process. (allocate_terminal): Changed to use offsetof. (allocate_frame): Likewise. * frame.c (make_frame): Omit redundant initialization. * window.c (make_parent_window): Use memset. (make_window): Omit redundant initialization. * process.c (make_process): Omit redundant initialization. * terminal.c (create_terminal): Likewise. --- src/alloc.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 6f7cc968b81..7f9574d43d1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3278,44 +3278,53 @@ allocate_hash_table (void) return ALLOCATE_PSEUDOVECTOR (struct Lisp_Hash_Table, count, PVEC_HASH_TABLE); } - struct window * allocate_window (void) { - return ALLOCATE_PSEUDOVECTOR (struct window, current_matrix, PVEC_WINDOW); -} + struct window *w; + w = ALLOCATE_PSEUDOVECTOR (struct window, current_matrix, PVEC_WINDOW); + /* Users assumes that non-Lisp data is zeroed. */ + memset (&w->current_matrix, 0, + sizeof (*w) - offsetof (struct window, current_matrix)); + return w; +} struct terminal * allocate_terminal (void) { - struct terminal *t = ALLOCATE_PSEUDOVECTOR (struct terminal, - next_terminal, PVEC_TERMINAL); - /* Zero out the non-GC'd fields. FIXME: This should be made unnecessary. */ - memset (&t->next_terminal, 0, - (char*) (t + 1) - (char*) &t->next_terminal); + struct terminal *t; + t = ALLOCATE_PSEUDOVECTOR (struct terminal, next_terminal, PVEC_TERMINAL); + /* Users assumes that non-Lisp data is zeroed. */ + memset (&t->next_terminal, 0, + sizeof (*t) - offsetof (struct terminal, next_terminal)); return t; } struct frame * allocate_frame (void) { - struct frame *f = ALLOCATE_PSEUDOVECTOR (struct frame, - face_cache, PVEC_FRAME); - /* Zero out the non-GC'd fields. FIXME: This should be made unnecessary. */ + struct frame *f; + + f = ALLOCATE_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME); + /* Users assumes that non-Lisp data is zeroed. */ memset (&f->face_cache, 0, - (char *) (f + 1) - (char *) &f->face_cache); + sizeof (*f) - offsetof (struct frame, face_cache)); return f; } - struct Lisp_Process * allocate_process (void) { - return ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS); -} + struct Lisp_Process *p; + p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS); + /* Users assumes that non-Lisp data is zeroed. */ + memset (&p->pid, 0, + sizeof (*p) - offsetof (struct Lisp_Process, pid)); + return p; +} DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, doc: /* Return a newly created vector of length LENGTH, with each element being INIT. -- cgit v1.2.1 From ed6b35106553c615b210a12b51a7ebb57aaa82e4 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 26 Jun 2012 22:49:35 -0500 Subject: alloc.c (mark_memory): Do not check with -faddress-sanitizer when building with Clang. --- src/alloc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 7f9574d43d1..e1fd479699a 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -4621,6 +4621,12 @@ mark_maybe_pointer (void *p) static void mark_memory (void *start, void *end) +#ifdef __clang__ + /* Do not allow -faddress-sanitizer to check this function, since it + crosses the function stack boundary, and thus would yield many + false positives. */ + __attribute__((no_address_safety_analysis)) +#endif { void **pp; int i; -- cgit v1.2.1 From 3fe6dd74d02291b80a35fcc45df2cef91a8dac9f Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 27 Jun 2012 15:19:54 +0400 Subject: * alloc.c (allocate_string): Remove two redundant calls to memset, add explicit initialization where appropriate. --- src/alloc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index e1fd479699a..d7ebd556f00 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1936,13 +1936,14 @@ allocate_string (void) int i; b = (struct string_block *) lisp_malloc (sizeof *b, MEM_TYPE_STRING); - memset (b, 0, sizeof *b); b->next = string_blocks; string_blocks = b; for (i = STRING_BLOCK_SIZE - 1; i >= 0; --i) { s = b->strings + i; + /* Every string on a free list should have NULL data pointer. */ + s->data = NULL; NEXT_FREE_LISP_STRING (s) = string_free_list; string_free_list = s; } @@ -1958,8 +1959,10 @@ allocate_string (void) MALLOC_UNBLOCK_INPUT; - /* Probably not strictly necessary, but play it safe. */ - memset (s, 0, sizeof *s); + /* SIZE and SIZE_BYTE fields will be initialized + by calling allocate_string_data. */ + s->intervals = NULL_INTERVAL; + s->data = NULL; --total_free_strings; ++total_strings; -- cgit v1.2.1 From 43184b7b885b57316e6788fa122465498759707f Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 27 Jun 2012 15:25:56 +0400 Subject: * alloc.c (allocate_string): Fix last change. --- src/alloc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index d7ebd556f00..8111487ace2 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1962,7 +1962,6 @@ allocate_string (void) /* SIZE and SIZE_BYTE fields will be initialized by calling allocate_string_data. */ s->intervals = NULL_INTERVAL; - s->data = NULL; --total_free_strings; ++total_strings; -- cgit v1.2.1 From 246155ebec6d2d2c0243f12b2a23b459fc6c8a99 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 27 Jun 2012 18:35:51 +0400 Subject: * alloc.c (allocate_string): Omit intervals initialization. * alloc.c (make_uninit_multibyte_string): Initialize intervals as in make_pure_string and make_pure_c_string. --- src/alloc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 8111487ace2..a16e3a6d83f 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1959,10 +1959,6 @@ allocate_string (void) MALLOC_UNBLOCK_INPUT; - /* SIZE and SIZE_BYTE fields will be initialized - by calling allocate_string_data. */ - s->intervals = NULL_INTERVAL; - --total_free_strings; ++total_strings; ++strings_consed; @@ -2529,6 +2525,7 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) return empty_multibyte_string; s = allocate_string (); + s->intervals = NULL_INTERVAL; allocate_string_data (s, nchars, nbytes); XSETSTRING (string, s); string_chars_consed += nbytes; -- cgit v1.2.1 From 2014308a5dc2d82a136212e0eb7eeea61838bbe7 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 27 Jun 2012 19:46:48 +0400 Subject: * alloc.c (allocate_string_data): Remove dead code. * xsettings.c (XSETTINGS_FONT_NAME): Move under HAVE_XFT to avoid GCC warning about unused macro. --- src/alloc.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index a16e3a6d83f..17212f8d37d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1991,9 +1991,9 @@ void allocate_string_data (struct Lisp_String *s, EMACS_INT nchars, EMACS_INT nbytes) { - struct sdata *data, *old_data; + struct sdata *data; struct sblock *b; - ptrdiff_t needed, old_nbytes; + ptrdiff_t needed; if (STRING_BYTES_MAX < nbytes) string_overflow (); @@ -2001,8 +2001,6 @@ allocate_string_data (struct Lisp_String *s, /* 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); MALLOC_BLOCK_INPUT; @@ -2072,16 +2070,6 @@ allocate_string_data (struct Lisp_String *s, memcpy ((char *) data + needed, string_overrun_cookie, GC_STRING_OVERRUN_COOKIE_SIZE); #endif - - /* 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 - in it. */ - if (old_data) - { - SDATA_NBYTES (old_data) = old_nbytes; - old_data->string = NULL; - } - consing_since_gc += needed; } -- cgit v1.2.1 From a54e2c050b9cf161cbccc3dd4628f8ef6b64f519 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 28 Jun 2012 11:50:27 +0400 Subject: Generalize run-time debugging checks. * configure.in (ENABLE_CHECKING): Update comment. * src/dispextern.h (XASSERTS): Remove. * src/fontset.c (xassert): Remove. Convert from xassert to eassert. * src/alloc.c: Convert from xassert to eassert. * src/bidi.c: Likewise. * src/dispnew.c: Likewise. * src/fns.c: Likewise. * src/fringe.c: Likewise. * src/ftfont.c: Likewise. * src/gtkutil.c: Likewise. * src/image.c: Likewise. * src/keyboard.c: Likewise. * src/menu.c: Likewise. * src/process.c: Likewise. * src/scroll.c: Likewise. * src/sound.c: Likewise. * src/term.c: Likewise. * src/w32console.c: Likewise. * src/w32fns.c: Likewise. * src/w32term.c: Likewise. * src/window.c: Likewise. * src/xdisp.c: Likewise. * src/xfaces.c: Likewise. * src/xfns.c: Likewise. * src/xselect.c: Likewise. * src/xterm.c: Likewise. --- src/alloc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 17212f8d37d..2570364e6c1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -787,7 +787,7 @@ verify (INT_MAX <= PTRDIFF_MAX); void * xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) { - xassert (0 <= nitems && 0 < item_size); + eassert (0 <= nitems && 0 < item_size); if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems) memory_full (SIZE_MAX); return xmalloc (nitems * item_size); @@ -800,7 +800,7 @@ xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) void * xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) { - xassert (0 <= nitems && 0 < item_size); + eassert (0 <= nitems && 0 < item_size); if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems) memory_full (SIZE_MAX); return xrealloc (pa, nitems * item_size); @@ -850,7 +850,7 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, ptrdiff_t nitems_incr_max = n_max - n; ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max)); - xassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max); + eassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max); if (! pa) *nitems = 0; if (nitems_incr_max < incr) @@ -2220,7 +2220,7 @@ compact_small_strings (void) for (b = oldest_sblock; b; b = b->next) { end = b->next_free; - xassert ((char *) end <= (char *) b + SBLOCK_SIZE); + eassert ((char *) end <= (char *) b + SBLOCK_SIZE); for (from = &b->first_data; from < end; from = from_end) { @@ -2271,7 +2271,7 @@ compact_small_strings (void) /* Copy, and update the string's `data' pointer. */ if (from != to) { - xassert (tb != b || to < from); + eassert (tb != b || to < from); memmove (to, from, nbytes + GC_STRING_EXTRA); to->string->data = SDATA_DATA (to); } -- cgit v1.2.1 From 7d7e0027e7c7ad6584fd44c611b3c77be69391a9 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Thu, 28 Jun 2012 15:09:41 -0400 Subject: * src/editfns.c (region_limit): Clip to narrowing. Fixes: debbugs:11770 --- src/alloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 2570364e6c1..bb57d46ee03 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5384,7 +5384,8 @@ See Info node `(elisp)Garbage Collection'. */) turned off in that buffer. Calling truncate_undo_list on Qt tends to return NULL, which effectively turns undo back on. So don't call truncate_undo_list if undo_list is Qt. */ - if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name)) && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) + if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name)) + && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) truncate_undo_list (nextb); /* Shrink buffer gaps, but skip indirect and dead buffers. */ -- cgit v1.2.1 From cf5c017598d130e76e96c47045372ba4a9ad6404 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 2 Jul 2012 10:23:15 +0400 Subject: * alloc.c (mark_buffer): Simplify. Remove prototype. (mark_object): Add comment. Reorganize marking of vector-like objects. Use CHECK_LIVE for all vector-like ojects except buffers and subroutines when GC_CHECK_MARKED_OBJECTS is defined. Avoid redundant calls to mark_vectorlike for bool vectors. --- src/alloc.c | 237 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 125 insertions(+), 112 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index bb57d46ee03..b059d6c04a6 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -270,7 +270,6 @@ Lisp_Object Qchar_table_extra_slots; static Lisp_Object Qpost_gc_hook; -static void mark_buffer (Lisp_Object); static void mark_terminals (void); static void gc_sweep (void); static Lisp_Object make_pure_vector (ptrdiff_t); @@ -5787,6 +5786,48 @@ mark_char_table (struct Lisp_Vector *ptr) } } +/* Mark the pointers in a buffer structure. */ + +static void +mark_buffer (struct buffer *buffer) +{ + register Lisp_Object *ptr, tmp; + + eassert (!VECTOR_MARKED_P (buffer)); + VECTOR_MARK (buffer); + + MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); + + /* For now, we just don't mark the undo_list. It's done later in + a special way just before the sweep phase, and after stripping + some of its elements that are not needed any more. */ + + if (buffer->overlays_before) + { + XSETMISC (tmp, buffer->overlays_before); + mark_object (tmp); + } + if (buffer->overlays_after) + { + XSETMISC (tmp, buffer->overlays_after); + mark_object (tmp); + } + + /* buffer-local Lisp variables start at `undo_list', + tho only the ones from `name' on are GC'd normally. */ + for (ptr = &buffer->BUFFER_INTERNAL_FIELD (name); + ptr <= &PER_BUFFER_VALUE (buffer, + PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER)); + ptr++) + mark_object (*ptr); + + /* If this is an indirect buffer, mark its base buffer. */ + if (buffer->base_buffer && !VECTOR_MARKED_P (buffer->base_buffer)) + mark_buffer (buffer->base_buffer); +} + +/* Determine type of generic Lisp_Object and mark it accordingly. */ + void mark_object (Lisp_Object arg) { @@ -5863,77 +5904,88 @@ mark_object (Lisp_Object arg) break; case Lisp_Vectorlike: - if (VECTOR_MARKED_P (XVECTOR (obj))) - break; + { + register struct Lisp_Vector *ptr = XVECTOR (obj); + register ptrdiff_t pvectype; + + if (VECTOR_MARKED_P (ptr)) + break; + #ifdef GC_CHECK_MARKED_OBJECTS - m = mem_find (po); - if (m == MEM_NIL && !SUBRP (obj) - && po != &buffer_defaults - && po != &buffer_local_symbols) - abort (); + m = mem_find (po); + if (m == MEM_NIL && !SUBRP (obj) + && po != &buffer_defaults + && po != &buffer_local_symbols) + abort (); #endif /* GC_CHECK_MARKED_OBJECTS */ - if (BUFFERP (obj)) - { + if (ptr->header.size & PSEUDOVECTOR_FLAG) + pvectype = ptr->header.size & PVEC_TYPE_MASK; + else + pvectype = 0; + #ifdef GC_CHECK_MARKED_OBJECTS - if (po != &buffer_defaults && po != &buffer_local_symbols) - { - struct buffer *b; - for (b = all_buffers; b && b != po; b = b->header.next.buffer) - ; - if (b == NULL) - abort (); - } + if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) + CHECK_LIVE (live_vector_p); #endif /* GC_CHECK_MARKED_OBJECTS */ - mark_buffer (obj); - } - else if (SUBRP (obj)) - break; - else if (COMPILEDP (obj)) - /* We could treat this just like a vector, but it is better to - save the COMPILED_CONSTANTS element for last and avoid - recursion there. */ - { - register struct Lisp_Vector *ptr = XVECTOR (obj); - int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; - int i; - CHECK_LIVE (live_vector_p); - VECTOR_MARK (ptr); /* Else mark it */ - for (i = 0; i < size; i++) /* and then mark its elements */ - { + if (pvectype == PVEC_BUFFER) + { +#ifdef GC_CHECK_MARKED_OBJECTS + if (po != &buffer_defaults && po != &buffer_local_symbols) + { + struct buffer *b = all_buffers; + for (; b && b != po; b = b->header.next.buffer) + ; + if (b == NULL) + abort (); + } +#endif /* GC_CHECK_MARKED_OBJECTS */ + mark_buffer ((struct buffer *) ptr); + } + + else if (pvectype == PVEC_COMPILED) + /* We could treat this just like a vector, but it is better + to save the COMPILED_CONSTANTS element for last and avoid + recursion there. */ + { + int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; + int i; + + VECTOR_MARK (ptr); + for (i = 0; i < size; i++) if (i != COMPILED_CONSTANTS) mark_object (ptr->contents[i]); - } - obj = ptr->contents[COMPILED_CONSTANTS]; - goto loop; - } - else if (FRAMEP (obj)) - { - register struct frame *ptr = XFRAME (obj); - mark_vectorlike (XVECTOR (obj)); - mark_face_cache (ptr->face_cache); - } - else if (WINDOWP (obj)) + obj = ptr->contents[COMPILED_CONSTANTS]; + goto loop; + } + + else if (pvectype == PVEC_FRAME) + { + mark_vectorlike (ptr); + mark_face_cache (((struct frame *) ptr)->face_cache); + } + + else if (pvectype == PVEC_WINDOW) + { + struct window *w = (struct window *) ptr; + + mark_vectorlike (ptr); + /* Mark glyphs for leaf windows. Marking window + matrices is sufficient because frame matrices + use the same glyph memory. */ + if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) + { + mark_glyph_matrix (w->current_matrix); + mark_glyph_matrix (w->desired_matrix); + } + } + + else if (pvectype == PVEC_HASH_TABLE) { - register struct Lisp_Vector *ptr = XVECTOR (obj); - struct window *w = XWINDOW (obj); + struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; + mark_vectorlike (ptr); - /* Mark glyphs for leaf windows. Marking window matrices is - sufficient because frame matrices use the same glyph - memory. */ - if (NILP (w->hchild) - && NILP (w->vchild) - && w->current_matrix) - { - mark_glyph_matrix (w->current_matrix); - mark_glyph_matrix (w->desired_matrix); - } - } - else if (HASH_TABLE_P (obj)) - { - struct Lisp_Hash_Table *h = XHASH_TABLE (obj); - mark_vectorlike ((struct Lisp_Vector *)h); /* If hash table is not weak, mark all keys and values. For weak tables, mark only the vector. */ if (NILP (h->weak)) @@ -5941,10 +5993,17 @@ mark_object (Lisp_Object arg) else VECTOR_MARK (XVECTOR (h->key_and_value)); } - else if (CHAR_TABLE_P (obj)) - mark_char_table (XVECTOR (obj)); - else - mark_vectorlike (XVECTOR (obj)); + + else if (pvectype == PVEC_CHAR_TABLE) + mark_char_table (ptr); + + else if (pvectype == PVEC_BOOL_VECTOR) + /* No Lisp_Objects to mark in a bool vector. */ + VECTOR_MARK (ptr); + + else if (pvectype != PVEC_SUBR) + mark_vectorlike (ptr); + } break; case Lisp_Symbol: @@ -6091,52 +6150,6 @@ mark_object (Lisp_Object arg) #undef CHECK_ALLOCATED #undef CHECK_ALLOCATED_AND_LIVE } - -/* Mark the pointers in a buffer structure. */ - -static void -mark_buffer (Lisp_Object buf) -{ - register struct buffer *buffer = XBUFFER (buf); - register Lisp_Object *ptr, tmp; - Lisp_Object base_buffer; - - eassert (!VECTOR_MARKED_P (buffer)); - VECTOR_MARK (buffer); - - MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); - - /* For now, we just don't mark the undo_list. It's done later in - a special way just before the sweep phase, and after stripping - some of its elements that are not needed any more. */ - - if (buffer->overlays_before) - { - XSETMISC (tmp, buffer->overlays_before); - mark_object (tmp); - } - if (buffer->overlays_after) - { - XSETMISC (tmp, buffer->overlays_after); - mark_object (tmp); - } - - /* buffer-local Lisp variables start at `undo_list', - tho only the ones from `name' on are GC'd normally. */ - for (ptr = &buffer->BUFFER_INTERNAL_FIELD (name); - ptr <= &PER_BUFFER_VALUE (buffer, - PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER)); - ptr++) - mark_object (*ptr); - - /* If this is an indirect buffer, mark its base buffer. */ - if (buffer->base_buffer && !VECTOR_MARKED_P (buffer->base_buffer)) - { - XSETBUFFER (base_buffer, buffer->base_buffer); - mark_buffer (base_buffer); - } -} - /* Mark the Lisp pointers in the terminal objects. Called by Fgarbage_collect. */ -- cgit v1.2.1 From 3b3e4caca71abc2df49f95090aaccb96cbb75a41 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 2 Jul 2012 00:36:17 -0700 Subject: * alloc.c (mark_object): Remove "#ifdef GC_CHECK_MARKED_OBJECTS" wrapper that is not needed because the wrapped code is a no-op (zero machine instructions) when GC_CHECK_MARKED_OBJECTS is not defined. This avoids a -Wunused-macros diagnostic with GCC 4.7.1 x86-64. --- src/alloc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index b059d6c04a6..b0945aa30de 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5924,10 +5924,8 @@ mark_object (Lisp_Object arg) else pvectype = 0; -#ifdef GC_CHECK_MARKED_OBJECTS if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) CHECK_LIVE (live_vector_p); -#endif /* GC_CHECK_MARKED_OBJECTS */ if (pvectype == PVEC_BUFFER) { -- cgit v1.2.1 From 36429c89cbd7282a7614a358e5edb4d37f4a3f47 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 3 Jul 2012 07:57:52 +0400 Subject: Cleanup basic buffer management. * buffer.h (struct buffer): Change layout to use generic vector marking code. Fix some comments. Change type of 'clip_changed' to bitfield. Remove unused #ifndef old. (FIRST_FIELD_PER_BUFFER, LAST_FIELD_PER_BUFFER): Remove. (GET_OVERLAYS_AT): Fix indentation. (for_each_per_buffer_object_at): New macro. * buffer.c (clone_per_buffer_values, reset_buffer_local_variables) (Fbuffer_local_variables): Use it. (init_buffer_once, syms_of_buffer): Remove unused #ifndef old. * alloc.c (allocate_buffer): Adjust to match new layout of struct buffer. Fix comment. (mark_overlay): New function. (mark_buffer): Use it. Use mark_vectorlike to mark normal Lisp area of struct buffer. (mark_object): Use it. Adjust marking of misc objects and related comments. --- src/alloc.c | 131 +++++++++++++++++++++++++----------------------------------- 1 file changed, 54 insertions(+), 77 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index b0945aa30de..b329f89d15b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1186,21 +1186,6 @@ lisp_align_free (void *block) MALLOC_UNBLOCK_INPUT; } -/* Return a new buffer structure allocated from the heap with - a call to lisp_malloc. */ - -struct buffer * -allocate_buffer (void) -{ - struct buffer *b - = (struct buffer *) lisp_malloc (sizeof (struct buffer), - MEM_TYPE_BUFFER); - XSETPVECTYPESIZE (b, PVEC_BUFFER, - ((sizeof (struct buffer) + sizeof (EMACS_INT) - 1) - / sizeof (EMACS_INT))); - return b; -} - #ifndef SYSTEM_MALLOC @@ -3258,6 +3243,17 @@ allocate_pseudovector (int memlen, int lisplen, int tag) return v; } +struct buffer * +allocate_buffer (void) +{ + struct buffer *b = lisp_malloc (sizeof (struct buffer), MEM_TYPE_BUFFER); + + XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text) + - header_size) / word_size); + /* Note that the fields of B are not initialized. */ + return b; +} + struct Lisp_Hash_Table * allocate_hash_table (void) { @@ -5786,15 +5782,29 @@ mark_char_table (struct Lisp_Vector *ptr) } } -/* Mark the pointers in a buffer structure. */ +/* Mark the chain of overlays starting at PTR. */ + +static void +mark_overlay (struct Lisp_Overlay *ptr) +{ + for (; ptr && !ptr->gcmarkbit; ptr = ptr->next) + { + ptr->gcmarkbit = 1; + mark_object (ptr->start); + mark_object (ptr->end); + mark_object (ptr->plist); + } +} + +/* Mark Lisp_Objects and special pointers in BUFFER. */ static void mark_buffer (struct buffer *buffer) { - register Lisp_Object *ptr, tmp; + /* This is handled much like other pseudovectors... */ + mark_vectorlike ((struct Lisp_Vector *) buffer); - eassert (!VECTOR_MARKED_P (buffer)); - VECTOR_MARK (buffer); + /* ...but there are some buffer-specific things. */ MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); @@ -5802,24 +5812,8 @@ mark_buffer (struct buffer *buffer) a special way just before the sweep phase, and after stripping some of its elements that are not needed any more. */ - if (buffer->overlays_before) - { - XSETMISC (tmp, buffer->overlays_before); - mark_object (tmp); - } - if (buffer->overlays_after) - { - XSETMISC (tmp, buffer->overlays_after); - mark_object (tmp); - } - - /* buffer-local Lisp variables start at `undo_list', - tho only the ones from `name' on are GC'd normally. */ - for (ptr = &buffer->BUFFER_INTERNAL_FIELD (name); - ptr <= &PER_BUFFER_VALUE (buffer, - PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER)); - ptr++) - mark_object (*ptr); + mark_overlay (buffer->overlays_before); + mark_overlay (buffer->overlays_after); /* If this is an indirect buffer, mark its base buffer. */ if (buffer->base_buffer && !VECTOR_MARKED_P (buffer->base_buffer)) @@ -6061,52 +6055,35 @@ mark_object (Lisp_Object arg) case Lisp_Misc: CHECK_ALLOCATED_AND_LIVE (live_misc_p); - if (XMISCANY (obj)->gcmarkbit) - break; - XMISCANY (obj)->gcmarkbit = 1; - switch (XMISCTYPE (obj)) + if (XMISCTYPE (obj) == Lisp_Misc_Overlay) + mark_overlay (XOVERLAY (obj)); + else { + if (XMISCANY (obj)->gcmarkbit) + break; + XMISCANY (obj)->gcmarkbit = 1; - case Lisp_Misc_Marker: - /* DO NOT mark thru the marker's chain. - The buffer's markers chain does not preserve markers from gc; - instead, markers are removed from the chain when freed by gc. */ - break; + /* Note that we don't mark thru the marker's + chain. The buffer's markers chain does not + preserve markers from GC; instead, markers + are removed from the chain when freed by GC. */ - case Lisp_Misc_Save_Value: #if GC_MARK_STACK - { - register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); - /* If DOGC is set, POINTER is the address of a memory - area containing INTEGER potential Lisp_Objects. */ - if (ptr->dogc) - { - Lisp_Object *p = (Lisp_Object *) ptr->pointer; - ptrdiff_t nelt; - for (nelt = ptr->integer; nelt > 0; nelt--, p++) - mark_maybe_object (*p); - } - } + if (XMISCTYPE (obj) == Lisp_Misc_Save_Value) + { + register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); + /* If DOGC is set, POINTER is the address of a memory + area containing INTEGER potential Lisp_Objects. */ + if (ptr->dogc) + { + Lisp_Object *p = (Lisp_Object *) ptr->pointer; + ptrdiff_t nelt; + for (nelt = ptr->integer; nelt > 0; nelt--, p++) + mark_maybe_object (*p); + } + } #endif - break; - - case Lisp_Misc_Overlay: - { - struct Lisp_Overlay *ptr = XOVERLAY (obj); - mark_object (ptr->start); - mark_object (ptr->end); - mark_object (ptr->plist); - if (ptr->next) - { - XSETMISC (obj, ptr->next); - goto loop; - } - } - break; - - default: - abort (); } break; -- cgit v1.2.1 From 296094c3dde63e458242a8537d1d3c0ca299dd56 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 3 Jul 2012 14:21:01 +0400 Subject: * alloc.c (check_string_bytes): If GC_CHECK_STRING_BYTES is enabled, avoid dereferencing NULL current_sblock if running undumped. --- src/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index b329f89d15b..3306bc4107b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1872,7 +1872,7 @@ check_string_bytes (int all_p) for (b = oldest_sblock; b; b = b->next) check_sblock (b); } - else + else if (current_sblock) check_sblock (current_sblock); } -- cgit v1.2.1 From d12e8f5a194b64e25eb57d5f6ea19f663c0e4f2b Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 3 Jul 2012 15:09:36 +0400 Subject: * alloc.c (allocate_vector_block): Remove redundant calls to mallopt if DOUG_LEA_MALLOC is defined. (allocate_vectorlike): If DOUG_LEA_MALLOC is defined, avoid calls to mallopt if zero_vector is returned. --- src/alloc.c | 58 +++++++++++++++++++++++----------------------------------- 1 file changed, 23 insertions(+), 35 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 3306bc4107b..0d4491e8472 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -2958,17 +2958,7 @@ static struct Lisp_Vector *zero_vector; static struct vector_block * allocate_vector_block (void) { - struct vector_block *block; - -#ifdef DOUG_LEA_MALLOC - mallopt (M_MMAP_MAX, 0); -#endif - - block = xmalloc (sizeof (struct vector_block)); - -#ifdef DOUG_LEA_MALLOC - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); -#endif + struct vector_block *block = xmalloc (sizeof (struct vector_block)); #if GC_MARK_STACK && !defined GC_MALLOC_CHECK mem_insert (block->data, block->data + VECTOR_BLOCK_BYTES, @@ -3166,44 +3156,42 @@ static struct Lisp_Vector * allocate_vectorlike (ptrdiff_t len) { struct Lisp_Vector *p; - size_t nbytes; MALLOC_BLOCK_INPUT; -#ifdef DOUG_LEA_MALLOC - /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed - because mapped region contents are not preserved in - a dumped Emacs. */ - mallopt (M_MMAP_MAX, 0); -#endif - /* This gets triggered by code which I haven't bothered to fix. --Stef */ /* eassert (!handling_signal); */ if (len == 0) + p = zero_vector; + else { - MALLOC_UNBLOCK_INPUT; - return zero_vector; - } + size_t nbytes = header_size + len * word_size; - nbytes = header_size + len * word_size; +#ifdef DOUG_LEA_MALLOC + /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed + because mapped region contents are not preserved in + a dumped Emacs. */ + mallopt (M_MMAP_MAX, 0); +#endif - if (nbytes <= VBLOCK_BYTES_MAX) - p = allocate_vector_from_block (vroundup (nbytes)); - else - { - p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); - p->header.next.vector = large_vectors; - large_vectors = p; - } + if (nbytes <= VBLOCK_BYTES_MAX) + p = allocate_vector_from_block (vroundup (nbytes)); + else + { + p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); + p->header.next.vector = large_vectors; + large_vectors = p; + } #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); + /* Back to a reasonable maximum of mmap'ed areas. */ + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif - consing_since_gc += nbytes; - vector_cells_consed += len; + consing_since_gc += nbytes; + vector_cells_consed += len; + } MALLOC_UNBLOCK_INPUT; -- cgit v1.2.1 From 7555c33f15ef5ae98508daf9b17b03aea379c78f Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 3 Jul 2012 10:37:55 -0400 Subject: * src/alloc.c (mark_object): Revert part of last patch to use `switch'. * src/lisp.h (Lisp_Misc, Lisp_Fwd): Move around to group better. --- src/alloc.c | 66 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 29 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 0d4491e8472..19972d54670 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5730,15 +5730,15 @@ mark_vectorlike (struct Lisp_Vector *ptr) ptrdiff_t i; eassert (!VECTOR_MARKED_P (ptr)); - VECTOR_MARK (ptr); /* Else mark it */ + VECTOR_MARK (ptr); /* Else mark it. */ if (size & PSEUDOVECTOR_FLAG) size &= PSEUDOVECTOR_SIZE_MASK; /* Note that this size is not the memory-footprint size, but only the number of Lisp_Object fields that we should trace. The distinction is used e.g. by Lisp_Process which places extra - non-Lisp_Object fields at the end of the structure. */ - for (i = 0; i < size; i++) /* and then mark its elements */ + non-Lisp_Object fields at the end of the structure... */ + for (i = 0; i < size; i++) /* ...and then mark its elements. */ mark_object (ptr->contents[i]); } @@ -5875,11 +5875,11 @@ mark_object (Lisp_Object arg) if (STRING_MARKED_P (ptr)) break; CHECK_ALLOCATED_AND_LIVE (live_string_p); - MARK_INTERVAL_TREE (ptr->intervals); MARK_STRING (ptr); + MARK_INTERVAL_TREE (ptr->intervals); #ifdef GC_CHECK_STRING_BYTES /* Check that the string size recorded in the string is the - same as the one recorded in the sdata structure. */ + same as the one recorded in the sdata structure. */ CHECK_STRING_BYTES (ptr); #endif /* GC_CHECK_STRING_BYTES */ } @@ -6034,7 +6034,7 @@ mark_object (Lisp_Object arg) ptr = ptr->next; if (ptr) { - ptrx = ptr; /* Use of ptrx avoids compiler bug on Sun */ + ptrx = ptr; /* Use of ptrx avoids compiler bug on Sun. */ XSETSYMBOL (obj, ptrx); goto loop; } @@ -6044,34 +6044,42 @@ mark_object (Lisp_Object arg) case Lisp_Misc: CHECK_ALLOCATED_AND_LIVE (live_misc_p); - if (XMISCTYPE (obj) == Lisp_Misc_Overlay) - mark_overlay (XOVERLAY (obj)); - else + if (XMISCANY (obj)->gcmarkbit) + break; + + switch (XMISCTYPE (obj)) { - if (XMISCANY (obj)->gcmarkbit) - break; + case Lisp_Misc_Marker: + /* DO NOT mark thru the marker's chain. + The buffer's markers chain does not preserve markers from gc; + instead, markers are removed from the chain when freed by gc. */ XMISCANY (obj)->gcmarkbit = 1; + break; - /* Note that we don't mark thru the marker's - chain. The buffer's markers chain does not - preserve markers from GC; instead, markers - are removed from the chain when freed by GC. */ - + case Lisp_Misc_Save_Value: + XMISCANY (obj)->gcmarkbit = 1; #if GC_MARK_STACK - if (XMISCTYPE (obj) == Lisp_Misc_Save_Value) - { - register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); - /* If DOGC is set, POINTER is the address of a memory - area containing INTEGER potential Lisp_Objects. */ - if (ptr->dogc) - { - Lisp_Object *p = (Lisp_Object *) ptr->pointer; - ptrdiff_t nelt; - for (nelt = ptr->integer; nelt > 0; nelt--, p++) - mark_maybe_object (*p); - } - } + { + register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); + /* If DOGC is set, POINTER is the address of a memory + area containing INTEGER potential Lisp_Objects. */ + if (ptr->dogc) + { + Lisp_Object *p = (Lisp_Object *) ptr->pointer; + ptrdiff_t nelt; + for (nelt = ptr->integer; nelt > 0; nelt--, p++) + mark_maybe_object (*p); + } + } #endif + break; + + case Lisp_Misc_Overlay: + mark_overlay (XOVERLAY (obj)); + break; + + default: + abort (); } break; -- cgit v1.2.1 From ca95b3ebc8587780966cee0acfe0f7822e895f83 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 3 Jul 2012 20:35:53 +0400 Subject: Fix block vector allocation code to allow VECTOR_BLOCK_SIZE values which aren't power of 2. * alloc.c (VECTOR_FREE_LIST_SIZE_MASK): New macro. Verify it's value and the value of VECTOR_BLOCK_SIZE. Adjust users accordingly. --- src/alloc.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 19972d54670..b1e2ed0a2ed 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -2869,6 +2869,12 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, #define VECTOR_BLOCK_SIZE 4096 +/* This special value is used to calculate vector size when the vector is + on a free list. It should be VECTOR_BLOCK_SIZE rounded up to nearest + power of two, minus one. */ + +#define VECTOR_FREE_LIST_SIZE_MASK 4095 + /* Handy constants for vectorlike objects. */ enum { @@ -2881,6 +2887,11 @@ enum /* ROUNDUP_SIZE must be a power of 2. */ verify ((roundup_size & (roundup_size - 1)) == 0); +/* Verify assumptions described above. */ +verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); +verify ((VECTOR_FREE_LIST_SIZE_MASK + 1) >= VECTOR_BLOCK_SIZE); +verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); + /* Round up X to nearest mult-of-ROUNDUP_SIZE. */ #define vroundup(x) (((x) + (roundup_size - 1)) & ~(roundup_size - 1)) @@ -2908,7 +2919,7 @@ verify ((roundup_size & (roundup_size - 1)) == 0); this special value ORed with vector's memory footprint size. */ #define VECTOR_FREE_LIST_FLAG (~(ARRAY_MARK_FLAG | PSEUDOVECTOR_FLAG \ - | (VECTOR_BLOCK_SIZE - 1))) + | VECTOR_FREE_LIST_SIZE_MASK)) /* Common shortcut to advance vector pointer over a block data. */ @@ -3087,7 +3098,7 @@ sweep_vectors (void) if ((vector->header.size & VECTOR_FREE_LIST_FLAG) == VECTOR_FREE_LIST_FLAG) vector->header.next.nbytes = - vector->header.size & (VECTOR_BLOCK_SIZE - 1); + vector->header.size & VECTOR_FREE_LIST_SIZE_MASK; next = ADVANCE (vector, vector->header.next.nbytes); @@ -3100,7 +3111,7 @@ sweep_vectors (void) break; if ((next->header.size & VECTOR_FREE_LIST_FLAG) == VECTOR_FREE_LIST_FLAG) - nbytes = next->header.size & (VECTOR_BLOCK_SIZE - 1); + nbytes = next->header.size & VECTOR_FREE_LIST_SIZE_MASK; else nbytes = next->header.next.nbytes; vector->header.next.nbytes += nbytes; @@ -4334,7 +4345,7 @@ live_vector_p (struct mem_node *m, void *p) if ((vector->header.size & VECTOR_FREE_LIST_FLAG) == VECTOR_FREE_LIST_FLAG) vector = ADVANCE (vector, (vector->header.size - & (VECTOR_BLOCK_SIZE - 1))); + & VECTOR_FREE_LIST_SIZE_MASK)); else if (vector == p) return 1; else -- cgit v1.2.1 From ee28be33a535e41c74f3a4d5c0f3878e44366942 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Wed, 4 Jul 2012 10:38:02 -0400 Subject: Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE. * src/lisp.h (enum pvec_type): Use fewer bits. (PSEUDOVECTOR_SIZE_BITS): New constant. (PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK): Use it. (XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR, DEFUN): Adapt code to change in pvec_type. (PSEUDOVECTOR_TYPEP): New macro. (TYPED_PSEUDOVECTORP): Use it. * src/fns.c (internal_equal): Adapt code to extract pvectype. * src/emacs.c (gdb_pvec_type): Update type. * src/alloc.c (PSEUDOVECTOR_NBYTES): New macro. (VECTOR_FREE_LIST_SIZE_MASK): Remove (=> PSEUDOVECTOR_SIZE_MASK). (VECTOR_FREE_LIST_FLAG): Remove (=> PVEC_FREE). (SETUP_ON_FREE_LIST): Use XSETPVECTYPESIZE. (sweep_vectors): Use it. Use local var `total_bytes' instead of abusing vector->header.next.nbytes. (live_vector_p): Use PVEC_TYPE. (mark_object): Adapt code to extract pvectype. Use switch. --- src/alloc.c | 184 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 96 insertions(+), 88 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index b1e2ed0a2ed..bd68f2b31f2 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1529,7 +1529,7 @@ make_interval (void) } -/* Mark Lisp objects in interval I. */ +/* Mark Lisp objects in interval I. */ static void mark_interval (register INTERVAL i, Lisp_Object dummy) @@ -1836,7 +1836,7 @@ check_sblock (struct sblock *b) ptrdiff_t nbytes; /* Check that the string size recorded in the string is the - same as the one recorded in the sdata structure. */ + same as the one recorded in the sdata structure. */ if (from->string) CHECK_STRING_BYTES (from->string); @@ -2869,12 +2869,6 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, #define VECTOR_BLOCK_SIZE 4096 -/* This special value is used to calculate vector size when the vector is - on a free list. It should be VECTOR_BLOCK_SIZE rounded up to nearest - power of two, minus one. */ - -#define VECTOR_FREE_LIST_SIZE_MASK 4095 - /* Handy constants for vectorlike objects. */ enum { @@ -2889,8 +2883,7 @@ verify ((roundup_size & (roundup_size - 1)) == 0); /* Verify assumptions described above. */ verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); -verify ((VECTOR_FREE_LIST_SIZE_MASK + 1) >= VECTOR_BLOCK_SIZE); -verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); +verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); /* Round up X to nearest mult-of-ROUNDUP_SIZE. */ @@ -2915,12 +2908,6 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); #define VECTOR_MAX_FREE_LIST_INDEX \ ((VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1) -/* When the vector is on a free list, vectorlike_header.SIZE is set to - this special value ORed with vector's memory footprint size. */ - -#define VECTOR_FREE_LIST_FLAG (~(ARRAY_MARK_FLAG | PSEUDOVECTOR_FLAG \ - | VECTOR_FREE_LIST_SIZE_MASK)) - /* Common shortcut to advance vector pointer over a block data. */ #define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes))) @@ -2933,7 +2920,7 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); #define SETUP_ON_FREE_LIST(v, nbytes, index) \ do { \ - (v)->header.size = VECTOR_FREE_LIST_FLAG | (nbytes); \ + XSETPVECTYPESIZE (v, PVEC_FREE, nbytes); \ eassert ((nbytes) % roundup_size == 0); \ (index) = VINDEX (nbytes); \ eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ @@ -3065,6 +3052,16 @@ allocate_vector_from_block (size_t nbytes) ((char *) (vector) <= (block)->data \ + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) +/* Number of bytes used by vector-block-allocated object. This is the only + place where we actually use the `nbytes' field of the vector-header. + I.e. we could get rid of the `nbytes' field by computing it based on the + vector-type. */ + +#define PSEUDOVECTOR_NBYTES(vector) \ + (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \ + ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \ + : vector->header.next.nbytes); + /* Reclaim space used by unmarked vectors. */ static void @@ -3093,14 +3090,10 @@ sweep_vectors (void) } else { - ptrdiff_t nbytes; + ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector); + ptrdiff_t total_bytes = nbytes; - if ((vector->header.size & VECTOR_FREE_LIST_FLAG) - == VECTOR_FREE_LIST_FLAG) - vector->header.next.nbytes = - vector->header.size & VECTOR_FREE_LIST_SIZE_MASK; - - next = ADVANCE (vector, vector->header.next.nbytes); + next = ADVANCE (vector, nbytes); /* While NEXT is not marked, try to coalesce with VECTOR, thus making VECTOR of the largest possible size. */ @@ -3109,16 +3102,12 @@ sweep_vectors (void) { if (VECTOR_MARKED_P (next)) break; - if ((next->header.size & VECTOR_FREE_LIST_FLAG) - == VECTOR_FREE_LIST_FLAG) - nbytes = next->header.size & VECTOR_FREE_LIST_SIZE_MASK; - else - nbytes = next->header.next.nbytes; - vector->header.next.nbytes += nbytes; + nbytes = PSEUDOVECTOR_NBYTES (next); + total_bytes += nbytes; next = ADVANCE (next, nbytes); } - eassert (vector->header.next.nbytes % roundup_size == 0); + eassert (total_bytes % roundup_size == 0); if (vector == (struct Lisp_Vector *) block->data && !VECTOR_IN_BLOCK (next, block)) @@ -3126,7 +3115,10 @@ sweep_vectors (void) space was coalesced into the only free vector. */ free_this_block = 1; else - SETUP_ON_FREE_LIST (vector, vector->header.next.nbytes, nbytes); + { + int tmp; + SETUP_ON_FREE_LIST (vector, total_bytes, tmp); + } } } @@ -4342,10 +4334,9 @@ live_vector_p (struct mem_node *m, void *p) while (VECTOR_IN_BLOCK (vector, block) && vector <= (struct Lisp_Vector *) p) { - if ((vector->header.size & VECTOR_FREE_LIST_FLAG) - == VECTOR_FREE_LIST_FLAG) + if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) vector = ADVANCE (vector, (vector->header.size - & VECTOR_FREE_LIST_SIZE_MASK)); + & PSEUDOVECTOR_SIZE_MASK)); else if (vector == p) return 1; else @@ -5913,15 +5904,17 @@ mark_object (Lisp_Object arg) #endif /* GC_CHECK_MARKED_OBJECTS */ if (ptr->header.size & PSEUDOVECTOR_FLAG) - pvectype = ptr->header.size & PVEC_TYPE_MASK; + pvectype = ((ptr->header.size & PVEC_TYPE_MASK) + >> PSEUDOVECTOR_SIZE_BITS); else pvectype = 0; if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) CHECK_LIVE (live_vector_p); - if (pvectype == PVEC_BUFFER) + switch (pvectype) { + case PVEC_BUFFER: #ifdef GC_CHECK_MARKED_OBJECTS if (po != &buffer_defaults && po != &buffer_local_symbols) { @@ -5933,67 +5926,82 @@ mark_object (Lisp_Object arg) } #endif /* GC_CHECK_MARKED_OBJECTS */ mark_buffer ((struct buffer *) ptr); - } + break; - else if (pvectype == PVEC_COMPILED) - /* We could treat this just like a vector, but it is better - to save the COMPILED_CONSTANTS element for last and avoid - recursion there. */ - { - int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; - int i; + case PVEC_COMPILED: + { /* We could treat this just like a vector, but it is better + to save the COMPILED_CONSTANTS element for last and avoid + recursion there. */ + int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; + int i; + + VECTOR_MARK (ptr); + for (i = 0; i < size; i++) + if (i != COMPILED_CONSTANTS) + mark_object (ptr->contents[i]); + if (size > COMPILED_CONSTANTS) + { + obj = ptr->contents[COMPILED_CONSTANTS]; + goto loop; + } + } + break; - VECTOR_MARK (ptr); - for (i = 0; i < size; i++) - if (i != COMPILED_CONSTANTS) - mark_object (ptr->contents[i]); - obj = ptr->contents[COMPILED_CONSTANTS]; - goto loop; - } + case PVEC_FRAME: + { + mark_vectorlike (ptr); + mark_face_cache (((struct frame *) ptr)->face_cache); + } + break; - else if (pvectype == PVEC_FRAME) - { - mark_vectorlike (ptr); - mark_face_cache (((struct frame *) ptr)->face_cache); - } + case PVEC_WINDOW: + { + struct window *w = (struct window *) ptr; - else if (pvectype == PVEC_WINDOW) - { - struct window *w = (struct window *) ptr; + mark_vectorlike (ptr); + /* Mark glyphs for leaf windows. Marking window + matrices is sufficient because frame matrices + use the same glyph memory. */ + if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) + { + mark_glyph_matrix (w->current_matrix); + mark_glyph_matrix (w->desired_matrix); + } + } + break; - mark_vectorlike (ptr); - /* Mark glyphs for leaf windows. Marking window - matrices is sufficient because frame matrices - use the same glyph memory. */ - if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) - { - mark_glyph_matrix (w->current_matrix); - mark_glyph_matrix (w->desired_matrix); - } - } + case PVEC_HASH_TABLE: + { + struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; - else if (pvectype == PVEC_HASH_TABLE) - { - struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; + mark_vectorlike (ptr); + /* If hash table is not weak, mark all keys and values. + For weak tables, mark only the vector. */ + if (NILP (h->weak)) + mark_object (h->key_and_value); + else + VECTOR_MARK (XVECTOR (h->key_and_value)); + } + break; - mark_vectorlike (ptr); - /* If hash table is not weak, mark all keys and values. - For weak tables, mark only the vector. */ - if (NILP (h->weak)) - mark_object (h->key_and_value); - else - VECTOR_MARK (XVECTOR (h->key_and_value)); - } + case PVEC_CHAR_TABLE: + mark_char_table (ptr); + break; + + case PVEC_BOOL_VECTOR: + /* No Lisp_Objects to mark in a bool vector. */ + VECTOR_MARK (ptr); + break; - else if (pvectype == PVEC_CHAR_TABLE) - mark_char_table (ptr); + case PVEC_SUBR: + break; - else if (pvectype == PVEC_BOOL_VECTOR) - /* No Lisp_Objects to mark in a bool vector. */ - VECTOR_MARK (ptr); + case PVEC_FREE: + abort (); - else if (pvectype != PVEC_SUBR) - mark_vectorlike (ptr); + default: + mark_vectorlike (ptr); + } } break; -- cgit v1.2.1 From 356e7178d24ca37e1b75c68489117001229725fe Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 4 Jul 2012 09:52:51 -0700 Subject: * alloc.c (PSEUDOVECTOR_NBYTES): Remove stray ';' that causes compilation to fail on pre-C99 compilers. --- src/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index bd68f2b31f2..ed5d6b5099f 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3060,7 +3060,7 @@ allocate_vector_from_block (size_t nbytes) #define PSEUDOVECTOR_NBYTES(vector) \ (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \ ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \ - : vector->header.next.nbytes); + : vector->header.next.nbytes) /* Reclaim space used by unmarked vectors. */ -- cgit v1.2.1 From 23f86fce48e1cc8118f0ea5cce49d1acfd4364c4 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 5 Jul 2012 10:32:41 +0400 Subject: Cleanup xmalloc. * admin/coccinelle/xzalloc.cocci: Semantic patch to convert calls to xmalloc with following memset to xzalloc. * src/lisp.h (xzalloc): New prototype. Omit needless casts. * src/alloc.c (xzalloc): New function. Omit needless casts. * src/charset.c: Omit needless casts. Convert all calls to malloc with following memset to xzalloc. * src/dispnew.c: Likewise. * src/fringe.c: Likewise. * src/image.c: Likewise. * src/sound.c: Likewise. * src/term.c: Likewise. * src/w32fns.c: Likewise. * src/w32font.c: Likewise. * src/w32term.c: Likewise. * src/xfaces.c: Likewise. * src/xfns.c: Likewise. * src/xterm.c: Likewise. * src/atimer.c: Omit needless casts. * src/buffer.c: Likewise. * src/callproc.c: Likewise. * src/ccl.c: Likewise. * src/coding.c: Likewise. * src/composite.c: Likewise. * src/doc.c: Likewise. * src/doprnt.c: Likewise. * src/editfns.c: Likewise. * src/emacs.c: Likewise. * src/eval.c: Likewise. * src/filelock.c: Likewise. * src/fns.c: Likewise. * src/gtkutil.c: Likewise. * src/keyboard.c: Likewise. * src/lisp.h: Likewise. * src/lread.c: Likewise. * src/minibuf.c: Likewise. * src/msdos.c: Likewise. * src/print.c: Likewise. * src/process.c: Likewise. * src/region-cache.c: Likewise. * src/search.c: Likewise. * src/sysdep.c: Likewise. * src/termcap.c: Likewise. * src/terminal.c: Likewise. * src/tparam.c: Likewise. * src/w16select.c: Likewise. * src/w32.c: Likewise. * src/w32reg.c: Likewise. * src/w32select.c: Likewise. * src/w32uniscribe.c: Likewise. * src/widget.c: Likewise. * src/xdisp.c: Likewise. * src/xmenu.c: Likewise. * src/xrdb.c: Likewise. * src/xselect.c: Likewise. --- src/alloc.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index ed5d6b5099f..6ef0782ca1b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -735,6 +735,22 @@ xmalloc (size_t size) return val; } +/* Like the above, but zeroes out the memory just allocated. */ + +void * +xzalloc (size_t size) +{ + void *val; + + MALLOC_BLOCK_INPUT; + val = malloc (size); + MALLOC_UNBLOCK_INPUT; + + if (!val && size) + memory_full (size); + memset (val, 0, size); + return val; +} /* Like realloc but check for no memory and block interrupt input.. */ @@ -867,7 +883,7 @@ char * xstrdup (const char *s) { size_t len = strlen (s) + 1; - char *p = (char *) xmalloc (len); + char *p = xmalloc (len); memcpy (p, s, len); return p; } @@ -3881,7 +3897,7 @@ mem_insert (void *start, void *end, enum mem_type type) if (x == NULL) abort (); #else - x = (struct mem_node *) xmalloc (sizeof *x); + x = xmalloc (sizeof *x); #endif x->start = start; x->end = end; @@ -5047,7 +5063,7 @@ pure_alloc (size_t size, int type) /* Don't allocate a large amount here, because it might get mmap'd and then its address might not be usable. */ - purebeg = (char *) xmalloc (10000); + purebeg = xmalloc (10000); pure_size = 10000; pure_bytes_used_before_overflow += pure_bytes_used - size; pure_bytes_used = 0; -- cgit v1.2.1 From 38182d901d030c7d65f4aa7a49b583afb30eb9b7 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 5 Jul 2012 11:35:48 -0700 Subject: More xmalloc and related cleanup. * alloc.c, bidi.c, buffer.c, buffer.h, bytecode.c, callint.c: * callproc.c, charset.c, coding.c, composite.c, data.c, dispnew.c: * doc.c, editfns.c, emacs.c, eval.c, fileio.c, filelock.c, fns.c: * font.c, fontset.c, frame.c, fringe.c, ftfont.c, ftxfont.c, gmalloc.c: * gtkutil.c, image.c, keyboard.c, keymap.c, lread.c, macros.c, menu.c: * nsfns.m, nsfont.m, nsmenu.m, nsterm.m, print.c, process.c, ralloc.c: * regex.c, region-cache.c, scroll.c, search.c, sound.c, syntax.c: * sysdep.c, term.c, termcap.c, unexmacosx.c, window.c, xdisp.c: * xfaces.c, xfns.c, xftfont.c, xgselect.c, xmenu.c, xrdb.c, xselect.c: * xterm.c: Omit needless casts involving void * pointers and allocation. Prefer "P = xmalloc (sizeof *P)" to "P = xmalloc (sizeof (TYPE_OF_P))", as the former is more robust if P's type is changed. Prefer xzalloc to xmalloc + memset 0. Simplify malloc-or-realloc to realloc. Don't worry about xmalloc returning a null pointer. Prefer xstrdup to xmalloc + strcpy. * editfns.c (Fmessage_box): Grow message_text by at least 80 when growing it. * keyboard.c (apply_modifiers_uncached): Prefer local array to alloca of a constant. --- src/alloc.c | 75 +++++++++++++++++++++++++++---------------------------------- 1 file changed, 33 insertions(+), 42 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 6ef0782ca1b..695d71c6c94 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -615,7 +615,7 @@ overrun_check_malloc (size_t size) if (SIZE_MAX - overhead < size) abort (); - val = (unsigned char *) malloc (size + overhead); + val = malloc (size + overhead); if (val && check_depth == 1) { memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); @@ -923,7 +923,7 @@ lisp_malloc (size_t nbytes, enum mem_type type) allocated_mem_type = type; #endif - val = (void *) malloc (nbytes); + val = malloc (nbytes); #if ! USE_LSB_TAG /* If the memory just allocated cannot be addressed thru a Lisp @@ -1309,7 +1309,7 @@ emacs_blocked_malloc (size_t size, const void *ptr) __malloc_extra_blocks = malloc_hysteresis; #endif - value = (void *) malloc (size); + value = malloc (size); #ifdef GC_MALLOC_CHECK { @@ -1371,7 +1371,7 @@ emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2) dont_register_blocks = 1; #endif /* GC_MALLOC_CHECK */ - value = (void *) realloc (ptr, size); + value = realloc (ptr, size); #ifdef GC_MALLOC_CHECK dont_register_blocks = 0; @@ -1523,10 +1523,8 @@ make_interval (void) { if (interval_block_index == INTERVAL_BLOCK_SIZE) { - register struct interval_block *newi; - - newi = (struct interval_block *) lisp_malloc (sizeof *newi, - MEM_TYPE_NON_LISP); + struct interval_block *newi + = lisp_malloc (sizeof *newi, MEM_TYPE_NON_LISP); newi->next = interval_block; interval_block = newi; @@ -1932,10 +1930,9 @@ allocate_string (void) add all the Lisp_Strings in it to the free-list. */ if (string_free_list == NULL) { - struct string_block *b; + struct string_block *b = lisp_malloc (sizeof *b, MEM_TYPE_STRING); int i; - b = (struct string_block *) lisp_malloc (sizeof *b, MEM_TYPE_STRING); b->next = string_blocks; string_blocks = b; @@ -2021,7 +2018,7 @@ allocate_string_data (struct Lisp_String *s, mallopt (M_MMAP_MAX, 0); #endif - b = (struct sblock *) lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); + b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); #ifdef DOUG_LEA_MALLOC /* Back to a reasonable maximum of mmap'ed areas. */ @@ -2039,7 +2036,7 @@ allocate_string_data (struct Lisp_String *s, < (needed + GC_STRING_EXTRA))) { /* Not enough room in the current sblock. */ - b = (struct sblock *) lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); + b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); b->next_free = &b->first_data; b->first_data.string = NULL; b->next = NULL; @@ -2619,10 +2616,8 @@ make_float (double float_value) { if (float_block_index == FLOAT_BLOCK_SIZE) { - register struct float_block *new; - - new = (struct float_block *) lisp_align_malloc (sizeof *new, - MEM_TYPE_FLOAT); + struct float_block *new + = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT); new->next = float_block; memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); float_block = new; @@ -2738,9 +2733,8 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, { if (cons_block_index == CONS_BLOCK_SIZE) { - register struct cons_block *new; - new = (struct cons_block *) lisp_align_malloc (sizeof *new, - MEM_TYPE_CONS); + struct cons_block *new + = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); new->next = cons_block; cons_block = new; @@ -2972,7 +2966,7 @@ static struct Lisp_Vector *zero_vector; static struct vector_block * allocate_vector_block (void) { - struct vector_block *block = xmalloc (sizeof (struct vector_block)); + struct vector_block *block = xmalloc (sizeof *block); #if GC_MARK_STACK && !defined GC_MALLOC_CHECK mem_insert (block->data, block->data + VECTOR_BLOCK_BYTES, @@ -3198,7 +3192,7 @@ allocate_vectorlike (ptrdiff_t len) p = allocate_vector_from_block (vroundup (nbytes)); else { - p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); + p = lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); p->header.next.vector = large_vectors; large_vectors = p; } @@ -3253,7 +3247,7 @@ allocate_pseudovector (int memlen, int lisplen, int tag) struct buffer * allocate_buffer (void) { - struct buffer *b = lisp_malloc (sizeof (struct buffer), MEM_TYPE_BUFFER); + struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER); XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text) - header_size) / word_size); @@ -3487,9 +3481,8 @@ Its value and function definition are void, and its property list is nil. */) { if (symbol_block_index == SYMBOL_BLOCK_SIZE) { - struct symbol_block *new; - new = (struct symbol_block *) lisp_malloc (sizeof *new, - MEM_TYPE_SYMBOL); + struct symbol_block *new + = lisp_malloc (sizeof *new, MEM_TYPE_SYMBOL); new->next = symbol_block; symbol_block = new; symbol_block_index = 0; @@ -3580,9 +3573,7 @@ allocate_misc (void) { if (marker_block_index == MARKER_BLOCK_SIZE) { - struct marker_block *new; - new = (struct marker_block *) lisp_malloc (sizeof *new, - MEM_TYPE_MISC); + struct marker_block *new = lisp_malloc (sizeof *new, MEM_TYPE_MISC); new->next = marker_block; marker_block = new; marker_block_index = 0; @@ -3775,25 +3766,25 @@ refill_memory_reserve (void) { #ifndef SYSTEM_MALLOC if (spare_memory[0] == 0) - spare_memory[0] = (char *) malloc (SPARE_MEMORY); + spare_memory[0] = malloc (SPARE_MEMORY); if (spare_memory[1] == 0) - spare_memory[1] = (char *) lisp_align_malloc (sizeof (struct cons_block), + spare_memory[1] = 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); + spare_memory[2] = 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); + spare_memory[3] = 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); + spare_memory[4] = 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); + spare_memory[5] = 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); + spare_memory[6] = lisp_malloc (sizeof (struct string_block), + MEM_TYPE_STRING); if (spare_memory[0] && spare_memory[1] && spare_memory[5]) Vmemory_full = Qnil; #endif @@ -3893,7 +3884,7 @@ mem_insert (void *start, void *end, enum mem_type type) /* Create a new node. */ #ifdef GC_MALLOC_CHECK - x = (struct mem_node *) _malloc_internal (sizeof *x); + x = _malloc_internal (sizeof *x); if (x == NULL) abort (); #else @@ -5441,7 +5432,7 @@ See Info node `(elisp)Garbage Collection'. */) { if (stack_copy_size < stack_size) { - stack_copy = (char *) xrealloc (stack_copy, stack_size); + stack_copy = xrealloc (stack_copy, stack_size); stack_copy_size = stack_size; } memcpy (stack_copy, stack, stack_size); -- cgit v1.2.1 From 657924ff58fc22a6e57dc8366a20dadf97324c63 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 6 Jul 2012 09:07:44 +0400 Subject: Introduce fast path for the widely used marker operation. * alloc.c (build_marker): New function. * lisp.h (build_marker): New prototype. * buffer.c (clone_per_buffer_values, Fmake_indirect_buffer): Use it. * composite.c (autocmp_chars): Likewise. * editfns.c (buildmark): Remove. (Fpoint_marker, Fpoint_min_marker, Fpoint_max_marker) (save_restriction_save): Use build_marker. * marker.c (buf_charpos_to_bytepos, buf_bytepos_to_charpos): Likewise. * window.c (save_window_save): Likewise. --- src/alloc.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 695d71c6c94..88f96c41a15 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3641,6 +3641,33 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, return val; } +/* Return a newly allocated marker which points into BUF + at character position CHARPOS and byte position BYTEPOS. */ + +Lisp_Object +build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) +{ + Lisp_Object obj; + struct Lisp_Marker *m; + + /* No dead buffers here. */ + eassert (!NILP (BVAR (buf, name))); + + /* Every character is at least one byte. */ + eassert (charpos <= bytepos); + + obj = allocate_misc (); + XMISCTYPE (obj) = Lisp_Misc_Marker; + m = XMARKER (obj); + m->buffer = buf; + m->charpos = charpos; + m->bytepos = bytepos; + m->insertion_type = 0; + m->next = BUF_MARKERS (buf); + BUF_MARKERS (buf) = m; + return obj; +} + /* Put MARKER back on the free list after using it temporarily. */ void -- cgit v1.2.1 From a8290ec31c89dfdec85fc9d46000c66c0caa1697 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 9 Jul 2012 16:02:27 +0400 Subject: Use make_formatted_string to avoid double length calculation. * lisp.h (make_formatted_string): New prototype. * alloc.c (make_formatted_string): New function. * buffer.c (Fgenerate_new_buffer_name): Use it. * dbus.c (syms_of_dbusbind): Likewise. * editfns.c (Fcurrent_time_zone): Likewise. * filelock.c (get_boot_time): Likewise. * frame.c (make_terminal_frame, set_term_frame_name) (x_report_frame_params): Likewise. * image.c (gs_load): Likewise. * minibuf.c (get_minibuffer): Likewise. * msdos.c (dos_set_window_size): Likewise. * process.c (make_process): Likewise. * xdisp.c (ensure_echo_area_buffers): Likewise. * xsettings.c (apply_xft_settings): Likewise. --- src/alloc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 88f96c41a15..739ec40c45c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -2517,6 +2517,20 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) return string; } +/* Print arguments to BUF according to a FORMAT, then return + a Lisp_String initialized with the data from BUF. */ + +Lisp_Object +make_formatted_string (char *buf, const char *format, ...) +{ + va_list ap; + ptrdiff_t length; + + va_start (ap, format); + length = vsprintf (buf, format, ap); + va_end (ap); + return make_string (buf, length); +} /*********************************************************************** -- cgit v1.2.1 From 26bccfaebf452511a06c2b19414a73b041b17853 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 9 Jul 2012 09:06:19 -0700 Subject: Minor improvements to make_formatted_string. * alloc.c (make_formatted_string): Prefer int to ptrdiff_t where int is good enough, as vsprintf returns an int. * lisp.h (make_formatted_string): Add ATTRIBUTE_FORMAT_PRINTF. --- src/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 739ec40c45c..a5c2e20d0c9 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -2524,7 +2524,7 @@ Lisp_Object make_formatted_string (char *buf, const char *format, ...) { va_list ap; - ptrdiff_t length; + int length; va_start (ap, format); length = vsprintf (buf, format, ap); -- cgit v1.2.1 From 2a0213a6d0a9e36a388994445837e051d0bbe5f9 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 10 Jul 2012 12:43:46 +0400 Subject: Optimize pure C strings initialization. * lisp.h (make_pure_string): Fix prototype. (build_pure_c_string): New function, defined as static inline. This provides a better opportunity to optimize away calls to strlen when the function is called with compile-time constant argument. * alloc.c (make_pure_c_string): Fix comment. Change to add nchars argument, adjust users accordingly. Use build_pure_c_string where appropriate. * buffer.c, coding.c, data.c, dbusbind.c, fileio.c, fontset.c, frame.c, * keyboard.c, keymap.c, lread.c, search.c, syntax.c, w32fns.c, xdisp.c, * xfaces.c, xfns.c, xterm.c: Use build_pure_c_string where appropriate. --- src/alloc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index a5c2e20d0c9..52d683a1b67 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5212,15 +5212,14 @@ make_pure_string (const char *data, return string; } -/* Return a string a string allocated in pure space. Do not allocate - the string data, just point to DATA. */ +/* Return a string allocated in pure space. Do not + allocate the string data, just point to DATA. */ Lisp_Object -make_pure_c_string (const char *data) +make_pure_c_string (const char *data, ptrdiff_t nchars) { Lisp_Object string; struct Lisp_String *s; - ptrdiff_t nchars = strlen (data); s = (struct Lisp_String *) pure_alloc (sizeof *s, Lisp_String); s->size = nchars; @@ -6842,7 +6841,7 @@ do hash-consing of the objects allocated to pure space. */); not be able to allocate the memory to hold it. */ Vmemory_signal_data = pure_cons (Qerror, - pure_cons (make_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs"), Qnil)); + pure_cons (build_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs"), Qnil)); DEFVAR_LISP ("memory-full", Vmemory_full, doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); -- cgit v1.2.1 From e9a9ae0350689d352c2bdfa3af0eb722f587b966 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 10 Jul 2012 16:24:36 -0700 Subject: EMACS_TIME simplification (Bug#11875). This replaces macros (which typically do not work in GDB) with functions, typedefs and enums, making the code easier to debug. The functional style also makes code easier to read and maintain. * lib-src/profile.c (TV2): Remove no-longer-needed static var. * src/systime.h: Include on all hosts, not just if WINDOWSNT, since 'struct timeval' is needed in general. (EMACS_TIME): Now a typedef, not a macro. (EMACS_TIME_RESOLUTION, LOG10_EMACS_TIME_RESOLUTION): Now constants, not macros. (EMACS_SECS, EMACS_NSECS, EMACS_TIME_SIGN, EMACS_TIME_VALID_P) (EMACS_TIME_FROM_DOUBLE, EMACS_TIME_TO_DOUBLE, EMACS_TIME_EQ) (EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE, EMACS_TIME_LT) (EMACS_TIME_LE): Now functions, not macros. (EMACS_SET_SECS, EMACS_SET_NSECS, EMACS_SET_SECS_NSECS) (EMACS_SET_USECS, EMACS_SET_SECS_USECS): Remove these macros, which are not functions. All uses rewritten to use: (make_emacs_time): New function. (EMACS_SECS_ADDR, EMACS_SET_INVALID_TIME, EMACS_GET_TIME) (EMACS_ADD_TIME, EMACS_SUB_TIME): Remove these macros, which are not functions. All uses rewritten to use the following, respectively: (emacs_secs_addr, invalid_emacs_time, get_emacs_time) (add_emacs_time, sub_emacs_time): New functions. * src/atimer.c: Don't include , as "systime.h" does this. * src/fileio.c (Fcopy_file): * src/xterm.c (XTflash): Get the current time closer to when it's used. * src/makefile.w32-in ($(BLD)/atimer.$(O)): Update dependencies. --- src/alloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 52d683a1b67..89f2c5dbed1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5393,7 +5393,7 @@ See Info node `(elisp)Garbage Collection'. */) int message_p; Lisp_Object total[8]; ptrdiff_t count = SPECPDL_INDEX (); - EMACS_TIME t1, t2, t3; + EMACS_TIME t1; if (abort_on_gc) abort (); @@ -5442,7 +5442,7 @@ See Info node `(elisp)Garbage Collection'. */) } } - EMACS_GET_TIME (t1); + t1 = current_emacs_time (); /* In case user calls debug_print during GC, don't let that cause a recursive GC. */ @@ -5696,8 +5696,8 @@ See Info node `(elisp)Garbage Collection'. */) /* Accumulate statistics. */ if (FLOATP (Vgc_elapsed)) { - EMACS_GET_TIME (t2); - EMACS_SUB_TIME (t3, t2, t1); + EMACS_TIME t2 = current_emacs_time (); + EMACS_TIME t3 = sub_emacs_time (t2, t1); Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) + EMACS_TIME_TO_DOUBLE (t3)); } -- cgit v1.2.1 From b41253a389afdffde3d2551e4c165f0ebbafdf89 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 11 Jul 2012 01:14:27 -0500 Subject: alloc.c (mark_memory): Guard the "no_address_safety_analysis" function attribute, so we only use it if it exists in the compiler. --- src/alloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 89f2c5dbed1..ac200254b8c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -4641,12 +4641,14 @@ mark_maybe_pointer (void *p) static void mark_memory (void *start, void *end) -#ifdef __clang__ +#if defined (__clang__) && defined (__has_feature) +#if __has_feature(address_sanitizer) /* Do not allow -faddress-sanitizer to check this function, since it crosses the function stack boundary, and thus would yield many false positives. */ __attribute__((no_address_safety_analysis)) #endif +#endif { void **pp; int i; -- cgit v1.2.1 From 9730daca4425e2014ff43a3b1b205b598e63c72a Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Sun, 15 Jul 2012 11:57:54 +0400 Subject: Use zero_vector where appropriate. * alloc.c (zero_vector): Define as Lisp_Object. Adjust users accordingly. * lisp.h (zero_vector): New declaration. * font.c (null_vector): Remove. (syms_of_font): Remove initialization and staticpro. (font_list_entities, font_find_for_lface): Change to use zero_vector. * keymap.c (Faccessible_keymaps): Likewise. --- src/alloc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index ac200254b8c..1df775a093b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -2973,7 +2973,7 @@ static struct Lisp_Vector *large_vectors; /* The only vector with 0 slots, allocated from pure space. */ -static struct Lisp_Vector *zero_vector; +Lisp_Object zero_vector; /* Get a new vector block. */ @@ -2997,8 +2997,7 @@ allocate_vector_block (void) static void init_vectors (void) { - zero_vector = pure_alloc (header_size, Lisp_Vectorlike); - zero_vector->header.size = 0; + zero_vector = make_pure_vector (0); } /* Allocate vector from a vector block. */ @@ -3190,7 +3189,7 @@ allocate_vectorlike (ptrdiff_t len) /* eassert (!handling_signal); */ if (len == 0) - p = zero_vector; + p = XVECTOR (zero_vector); else { size_t nbytes = header_size + len * word_size; -- cgit v1.2.1 From fff62aa9aea4f6c2aadcef4cdc203cdf60ba224c Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Sun, 15 Jul 2012 15:17:09 +0400 Subject: Cleanup basic allocation variables and functions. * alloc.c (ignore_warnings, init_intervals, init_float) (init_cons, init_symbol, init_marker): Remove. (interval_block_index): Initialize to INTERVAL_BLOCK_SIZE. (float_block_index): Initialize to FLOAT_BLOCK_SIZE. (cons_block_index): Initialize to CONS_BLOCK_SIZE. (symbol_block_size): Initialize to SYMBOL_BLOCK_SIZE. (marker_block_index): Initialize to MARKER_BLOCK_SIZE. (staticidx, init_alloc_once, init_strings, free_ablock): Remove redundant initialization. * fns.c (init_weak_hash_tables): Remove. * lisp.h (init_weak_hash_tables): Remove prototype. --- src/alloc.c | 97 ++++--------------------------------------------------------- 1 file changed, 6 insertions(+), 91 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 1df775a093b..39c360a67e7 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -258,11 +258,6 @@ static char *stack_copy; static ptrdiff_t stack_copy_size; #endif -/* Non-zero means ignore malloc warnings. Set during initialization. - Currently not used. */ - -static int ignore_warnings; - static Lisp_Object Qgc_cons_threshold; Lisp_Object Qchar_table_extra_slots; @@ -435,7 +430,7 @@ static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag}; /* Index of next unused slot in staticvec. */ -static int staticidx = 0; +static int staticidx; static void *pure_alloc (size_t, int); @@ -1481,7 +1476,7 @@ static struct interval_block *interval_block; /* Index in interval_block above of the next unused interval structure. */ -static int interval_block_index; +static int interval_block_index = INTERVAL_BLOCK_SIZE; /* Number of free and live intervals. */ @@ -1491,18 +1486,6 @@ static EMACS_INT total_free_intervals, total_intervals; static INTERVAL interval_free_list; - -/* Initialize interval allocation. */ - -static void -init_intervals (void) -{ - interval_block = NULL; - interval_block_index = INTERVAL_BLOCK_SIZE; - interval_free_list = 0; -} - - /* Return a new interval. */ INTERVAL @@ -1803,10 +1786,6 @@ static char const string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] = static void init_strings (void) { - total_strings = total_free_strings = total_string_size = 0; - oldest_sblock = current_sblock = large_sblocks = NULL; - string_blocks = NULL; - string_free_list = NULL; empty_unibyte_string = make_pure_string ("", 0, 0, 0); empty_multibyte_string = make_pure_string ("", 0, 0, 1); } @@ -2590,24 +2569,12 @@ static struct float_block *float_block; /* Index of first unused Lisp_Float in the current float_block. */ -static int float_block_index; +static int float_block_index = FLOAT_BLOCK_SIZE; /* Free-list of Lisp_Floats. */ static struct Lisp_Float *float_free_list; - -/* Initialize float allocation. */ - -static void -init_float (void) -{ - float_block = NULL; - float_block_index = FLOAT_BLOCK_SIZE; /* Force alloc of new float_block. */ - float_free_list = 0; -} - - /* Return a new float object with value FLOAT_VALUE. */ Lisp_Object @@ -2696,24 +2663,12 @@ static struct cons_block *cons_block; /* Index of first unused Lisp_Cons in the current block. */ -static int cons_block_index; +static int cons_block_index = CONS_BLOCK_SIZE; /* Free-list of Lisp_Cons structures. */ static struct Lisp_Cons *cons_free_list; - -/* Initialize cons allocation. */ - -static void -init_cons (void) -{ - cons_block = NULL; - cons_block_index = CONS_BLOCK_SIZE; /* Force alloc of new cons_block. */ - cons_free_list = 0; -} - - /* Explicitly free a cons cell by putting it on the free-list. */ void @@ -3453,24 +3408,12 @@ struct symbol_block structure in it. */ static struct symbol_block *symbol_block; -static int symbol_block_index; +static int symbol_block_index = SYMBOL_BLOCK_SIZE; /* List of free symbols. */ static struct Lisp_Symbol *symbol_free_list; - -/* Initialize symbol allocation. */ - -static void -init_symbol (void) -{ - symbol_block = NULL; - symbol_block_index = SYMBOL_BLOCK_SIZE; - symbol_free_list = 0; -} - - DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, doc: /* Return a newly allocated uninterned symbol whose name is NAME. Its value and function definition are void, and its property list is nil. */) @@ -3554,18 +3497,10 @@ struct marker_block }; static struct marker_block *marker_block; -static int marker_block_index; +static int marker_block_index = MARKER_BLOCK_SIZE; static union Lisp_Misc *marker_free_list; -static void -init_marker (void) -{ - marker_block = NULL; - marker_block_index = MARKER_BLOCK_SIZE; - marker_free_list = 0; -} - /* Return a newly allocated Lisp_Misc object, with no substructure. */ Lisp_Object @@ -6713,32 +6648,19 @@ init_alloc_once (void) /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ purebeg = PUREBEG; pure_size = PURESIZE; - pure_bytes_used = 0; - pure_bytes_used_lisp = pure_bytes_used_non_lisp = 0; - pure_bytes_used_before_overflow = 0; - - /* Initialize the list of free aligned blocks. */ - free_ablock = NULL; #if GC_MARK_STACK || defined GC_MALLOC_CHECK mem_init (); Vdead = make_pure_string ("DEAD", 4, 4, 0); #endif - ignore_warnings = 1; #ifdef DOUG_LEA_MALLOC mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */ mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* max. number of mmap'ed areas */ #endif init_strings (); - init_cons (); - init_symbol (); - init_marker (); - init_float (); - init_intervals (); init_vectors (); - init_weak_hash_tables (); #ifdef REL_ALLOC malloc_hysteresis = 32; @@ -6747,14 +6669,7 @@ init_alloc_once (void) #endif refill_memory_reserve (); - - ignore_warnings = 0; - gcprolist = 0; - byte_stack_list = 0; - staticidx = 0; - consing_since_gc = 0; gc_cons_threshold = 100000 * sizeof (Lisp_Object); - gc_relative_threshold = 0; } void -- cgit v1.2.1 From 7098646f5d49eabca79baf013b58911e65bf6d99 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 17 Jul 2012 09:01:33 +0400 Subject: Simple free memory accounting feature. * alloc.c (bytes_free, total_free_vector_bytes): New variable. (sweep_vectors): Accumulate size of free vectors. (Fgarbage_collect): Setup bytes_free. (Fmemory_free): New function. (syms_of_alloc): Register it. --- src/alloc.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 39c360a67e7..fd5111412f7 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -84,6 +84,10 @@ extern void *sbrk (); #define MMAP_MAX_AREAS 100000000 +/* Value of mallinfo ().fordblks as seen at the end of last GC. */ + +static int bytes_free; + #else /* not DOUG_LEA_MALLOC */ /* The following come from gmalloc.c. */ @@ -191,7 +195,7 @@ int abort_on_gc; static EMACS_INT total_conses, total_markers, total_symbols, total_vector_size; static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; -static EMACS_INT total_free_floats, total_floats; +static EMACS_INT total_free_floats, total_floats, total_free_vector_bytes; /* Points to memory space allocated as "spare", to be freed if we run out of memory. We keep one large block, four cons-blocks, and @@ -3048,7 +3052,7 @@ sweep_vectors (void) struct vector_block *block = vector_blocks, **bprev = &vector_blocks; struct Lisp_Vector *vector, *next, **vprev = &large_vectors; - total_vector_size = 0; + total_free_vector_bytes = total_vector_size = 0; memset (vector_free_lists, 0, sizeof (vector_free_lists)); /* Looking through vector blocks. */ @@ -3095,6 +3099,7 @@ sweep_vectors (void) else { int tmp; + total_free_vector_bytes += total_bytes; SETUP_ON_FREE_LIST (vector, total_bytes, tmp); } } @@ -5605,6 +5610,10 @@ See Info node `(elisp)Garbage Collection'. */) total[7] = Fcons (make_number (total_strings), make_number (total_free_strings)); +#ifdef DOUG_LEA_MALLOC + bytes_free = mallinfo ().fordblks; +#endif + #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES { /* Compute average percentage of zombies. */ @@ -6549,6 +6558,37 @@ We divide the value by 1024 to make sure it fits in a Lisp integer. */) return end; } +DEFUN ("memory-free", Fmemory_free, Smemory_free, 0, 0, 0, + doc: /* Return a list of two counters that measure how much free memory +is hold by the Emacs process. Both counters are in KBytes. First +counter shows how much memory holds in a free lists maintained by +the Emacs itself. Second counter shows how much free memory is in +the heap (freed by Emacs but not released back to the operating +system). If the second counter is zero, heap statistics is not +available. Since both counters are updated after each garbage +collection, use (progn (garbage-collect) (memory-free)) to get +accurate numbers. */) + (void) +{ + Lisp_Object data[2]; + + data[0] = make_number + (min (MOST_POSITIVE_FIXNUM, + (total_free_conses * sizeof (struct Lisp_Cons) + + total_free_markers * sizeof (union Lisp_Misc) + + total_free_symbols * sizeof (struct Lisp_Symbol) + + total_free_floats * sizeof (struct Lisp_Float) + + total_free_intervals * sizeof (struct interval) + + total_free_strings * sizeof (struct Lisp_String) + + total_free_vector_bytes) / 1024)); +#ifdef DOUG_LEA_MALLOC + data[1] = make_number (min (MOST_POSITIVE_FIXNUM, bytes_free / 1024)); +#else + data[1] = make_number (0); +#endif + return Flist (2, data); +} + DEFUN ("memory-use-counts", Fmemory_use_counts, Smemory_use_counts, 0, 0, 0, doc: /* Return a list of counters that measure how much consing there has been. Each of these counters increments for a certain kind of object. @@ -6785,6 +6825,7 @@ The time is in seconds as a floating point value. */); defsubr (&Spurecopy); defsubr (&Sgarbage_collect); defsubr (&Smemory_limit); + defsubr (&Smemory_free); defsubr (&Smemory_use_counts); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES -- cgit v1.2.1 From 3900d5de1b3cbb4171db39b5a187b623a7393087 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 17 Jul 2012 11:15:50 +0400 Subject: Fix previous change to make Fmemory_free always accurate. * alloc.c (make_interval): Update total_free_intervals. (make_float): Likewise for total_free_floats. (free_cons, Fcons): Likewise for total_free_conses. (SETUP_ON_FREE_LIST, allocate_vector_from_block): Likewise for total_free_vector_bytes. (Fmake_symbol): Likewise for total_free_symbols. (bytes_free): Remove. --- src/alloc.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index fd5111412f7..6cbd63f716c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -84,10 +84,6 @@ extern void *sbrk (); #define MMAP_MAX_AREAS 100000000 -/* Value of mallinfo ().fordblks as seen at the end of last GC. */ - -static int bytes_free; - #else /* not DOUG_LEA_MALLOC */ /* The following come from gmalloc.c. */ @@ -1516,6 +1512,7 @@ make_interval (void) newi->next = interval_block; interval_block = newi; interval_block_index = 0; + total_free_intervals += INTERVAL_BLOCK_SIZE; } val = &interval_block->intervals[interval_block_index++]; } @@ -1524,6 +1521,7 @@ make_interval (void) consing_since_gc += sizeof (struct interval); intervals_consed++; + total_free_intervals--; RESET_INTERVAL (val); val->gcmarkbit = 0; return val; @@ -2607,6 +2605,7 @@ make_float (double float_value) memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); float_block = new; float_block_index = 0; + total_free_floats += FLOAT_BLOCK_SIZE; } XSETFLOAT (val, &float_block->floats[float_block_index]); float_block_index++; @@ -2618,6 +2617,7 @@ make_float (double float_value) eassert (!FLOAT_MARKED_P (XFLOAT (val))); consing_since_gc += sizeof (struct Lisp_Float); floats_consed++; + total_free_floats--; return val; } @@ -2683,6 +2683,7 @@ free_cons (struct Lisp_Cons *ptr) ptr->car = Vdead; #endif cons_free_list = ptr; + total_free_conses++; } DEFUN ("cons", Fcons, Scons, 2, 2, 0, @@ -2712,6 +2713,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, new->next = cons_block; cons_block = new; cons_block_index = 0; + total_free_conses += CONS_BLOCK_SIZE; } XSETCONS (val, &cons_block->conses[cons_block_index]); cons_block_index++; @@ -2723,6 +2725,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, XSETCDR (val, cdr); eassert (!CONS_MARKED_P (XCONS (val))); consing_since_gc += sizeof (struct Lisp_Cons); + total_free_conses--; cons_cells_consed++; return val; } @@ -2909,6 +2912,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ (v)->header.next.vector = vector_free_lists[index]; \ vector_free_lists[index] = (v); \ + total_free_vector_bytes += (nbytes); \ } while (0) struct vector_block @@ -2979,6 +2983,7 @@ allocate_vector_from_block (size_t nbytes) vector = vector_free_lists[index]; vector_free_lists[index] = vector->header.next.vector; vector->header.next.nbytes = nbytes; + total_free_vector_bytes -= nbytes; return vector; } @@ -2993,6 +2998,7 @@ allocate_vector_from_block (size_t nbytes) vector = vector_free_lists[index]; vector_free_lists[index] = vector->header.next.vector; vector->header.next.nbytes = nbytes; + total_free_vector_bytes -= nbytes; /* Excess bytes are used for the smaller vector, which should be set on an appropriate free list. */ @@ -3099,7 +3105,6 @@ sweep_vectors (void) else { int tmp; - total_free_vector_bytes += total_bytes; SETUP_ON_FREE_LIST (vector, total_bytes, tmp); } } @@ -3447,6 +3452,7 @@ Its value and function definition are void, and its property list is nil. */) new->next = symbol_block; symbol_block = new; symbol_block_index = 0; + total_free_symbols += SYMBOL_BLOCK_SIZE; } XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index].s); symbol_block_index++; @@ -3467,6 +3473,7 @@ Its value and function definition are void, and its property list is nil. */) p->declared_special = 0; consing_since_gc += sizeof (struct Lisp_Symbol); symbols_consed++; + total_free_symbols--; return val; } @@ -5610,10 +5617,6 @@ See Info node `(elisp)Garbage Collection'. */) total[7] = Fcons (make_number (total_strings), make_number (total_free_strings)); -#ifdef DOUG_LEA_MALLOC - bytes_free = mallinfo ().fordblks; -#endif - #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES { /* Compute average percentage of zombies. */ @@ -6565,9 +6568,7 @@ counter shows how much memory holds in a free lists maintained by the Emacs itself. Second counter shows how much free memory is in the heap (freed by Emacs but not released back to the operating system). If the second counter is zero, heap statistics is not -available. Since both counters are updated after each garbage -collection, use (progn (garbage-collect) (memory-free)) to get -accurate numbers. */) +available. */) (void) { Lisp_Object data[2]; @@ -6582,7 +6583,8 @@ accurate numbers. */) + total_free_strings * sizeof (struct Lisp_String) + total_free_vector_bytes) / 1024)); #ifdef DOUG_LEA_MALLOC - data[1] = make_number (min (MOST_POSITIVE_FIXNUM, bytes_free / 1024)); + data[1] = make_number + (min (MOST_POSITIVE_FIXNUM, mallinfo ().fordblks / 1024)); #else data[1] = make_number (0); #endif -- cgit v1.2.1 From cce7fefcabe5794120d08714cbef6bba0c264226 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 17 Jul 2012 13:12:24 +0400 Subject: Cleanup and convert miscellaneous checks to eassert. * alloc.c (mark_interval): Fix comment, partially rephrase old comment from intervals.h (see below). * intervals.c (find_interval, adjust_intervals_for_insertion) (delete_interval, adjust_intervals_for_deletion) (graft_intervals_into_buffer, temp_set_point_both, copy_intervals): Convert to eassert. (adjust_intervals_for_insertion, make_new_interval): Remove obsolete and unused code. * intervals.h (struct interval): Remove obsolete comment. * textprotp.c (erase_properties): Remove unused code. (Fadd_text_properties, set_text_properties_1, Fremove_text_properties) (Fremove_list_of_text_properties): Convert to eassert. --- src/alloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 6cbd63f716c..67ff3459e71 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1533,7 +1533,9 @@ make_interval (void) static void mark_interval (register INTERVAL i, Lisp_Object dummy) { - eassert (!i->gcmarkbit); /* Intervals are never shared. */ + /* Intervals should never be shared. So, if extra internal checking is + enabled, GC aborts if it seems to have visited an interval twice. */ + eassert (!i->gcmarkbit); i->gcmarkbit = 1; mark_object (i->plist); } -- cgit v1.2.1 From b7ffe0402bda8231943066a1ce34e60b3dfdb6e7 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 17 Jul 2012 16:31:29 +0400 Subject: Restore old code in allocate_string_data to avoid Faset breakage. Reported by Julien Danjou in http://lists.gnu.org/archive/html/emacs-devel/2012-07/msg00371.html. * alloc.c (allocate_string_data): Restore old code with minor adjustments, fix comment to explain this subtle issue. --- src/alloc.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 67ff3459e71..f8456e3645f 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1971,9 +1971,9 @@ void allocate_string_data (struct Lisp_String *s, EMACS_INT nchars, EMACS_INT nbytes) { - struct sdata *data; + struct sdata *data, *old_data; struct sblock *b; - ptrdiff_t needed; + ptrdiff_t needed, old_nbytes; if (STRING_BYTES_MAX < nbytes) string_overflow (); @@ -1981,6 +1981,13 @@ allocate_string_data (struct Lisp_String *s, /* Determine the number of bytes needed to store NBYTES bytes of string data. */ needed = SDATA_SIZE (nbytes); + if (s->data) + { + old_data = SDATA_OF_STRING (s); + old_nbytes = GC_STRING_BYTES (s); + } + else + old_data = NULL; MALLOC_BLOCK_INPUT; @@ -2050,6 +2057,16 @@ allocate_string_data (struct Lisp_String *s, memcpy ((char *) data + needed, string_overrun_cookie, GC_STRING_OVERRUN_COOKIE_SIZE); #endif + + /* Note that Faset may call to this function when S has already data + assigned. In this case, mark data as free by setting it's string + back-pointer to null, and record the size of the data in it. */ + if (old_data) + { + SDATA_NBYTES (old_data) = old_nbytes; + old_data->string = NULL; + } + consing_since_gc += needed; } -- cgit v1.2.1 From 6d02fe5b3bf3376f0ea6ecf7fed184fbe84ef1b5 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 17 Jul 2012 09:24:57 -0700 Subject: * alloc.c (Fmemory_free): Account for memory-free's own storage. Round up, not down. Improve doc. --- src/alloc.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index f8456e3645f..7ab3f7b5e9c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -6581,33 +6581,35 @@ We divide the value by 1024 to make sure it fits in a Lisp integer. */) } DEFUN ("memory-free", Fmemory_free, Smemory_free, 0, 0, 0, - doc: /* Return a list of two counters that measure how much free memory -is hold by the Emacs process. Both counters are in KBytes. First -counter shows how much memory holds in a free lists maintained by -the Emacs itself. Second counter shows how much free memory is in -the heap (freed by Emacs but not released back to the operating -system). If the second counter is zero, heap statistics is not -available. */) + doc: /* Return a list (E H) of two measures of free memory. +E counts free lists maintained by Emacs itself. H counts the heap, +freed by Emacs but not released to the operating system; this is zero +if heap statistics are not available. Both counters are in units of +1024 bytes, rounded up. */) (void) { - Lisp_Object data[2]; - - data[0] = make_number - (min (MOST_POSITIVE_FIXNUM, - (total_free_conses * sizeof (struct Lisp_Cons) - + total_free_markers * sizeof (union Lisp_Misc) - + total_free_symbols * sizeof (struct Lisp_Symbol) - + total_free_floats * sizeof (struct Lisp_Float) - + total_free_intervals * sizeof (struct interval) - + total_free_strings * sizeof (struct Lisp_String) - + total_free_vector_bytes) / 1024)); + /* Make the return value first, so that its storage is accounted for. */ + Lisp_Object val = Fmake_list (make_number (2), make_number (0)); + + XSETCAR (val, + (make_number + (min (MOST_POSITIVE_FIXNUM, + ((total_free_conses * sizeof (struct Lisp_Cons) + + total_free_markers * sizeof (union Lisp_Misc) + + total_free_symbols * sizeof (struct Lisp_Symbol) + + total_free_floats * sizeof (struct Lisp_Float) + + total_free_intervals * sizeof (struct interval) + + total_free_strings * sizeof (struct Lisp_String) + + total_free_vector_bytes + + 1023) + >> 10))))); + #ifdef DOUG_LEA_MALLOC - data[1] = make_number - (min (MOST_POSITIVE_FIXNUM, mallinfo ().fordblks / 1024)); -#else - data[1] = make_number (0); + XSETCAR (XCDR (val), + make_number (min (MOST_POSITIVE_FIXNUM, + (mallinfo ().fordblks + 1023) >> 10))); #endif - return Flist (2, data); + return val; } DEFUN ("memory-use-counts", Fmemory_use_counts, Smemory_use_counts, 0, 0, 0, -- cgit v1.2.1 From 3ab6e069695d0dd5bb77133a89f858190ab8550a Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 18 Jul 2012 09:44:36 +0400 Subject: Return more descriptive data from Fgarbage_collect. Suggested by Stefan Monnier in http://lists.gnu.org/archive/html/emacs-devel/2012-07/msg00369.html. * src/alloc.c (bounded_number): New function. (total_buffers, total_vectors): New variable. (total_string_size): Rename to total_string_bytes, adjust users. (total_vector_size): Rename to total_vector_bytes, adjust users. (sweep_vectors): Account total_vectors and total_vector_bytes. (Fgarbage_collect): New return value. Adjust documentation. (gc_sweep): Account total_buffers. (Fmemory_free, Fmemory_use_counts): Use bounded_number. (VECTOR_SIZE): Remove. * src/data.c (Qfloat, Qvector, Qsymbol, Qstring, Qcons): Make global. (Qinterval, Qmisc): New symbols. (syms_of_data): Initialize them. * src/lisp.h (Qinterval, Qsymbol, Qstring, Qmisc, Qvector, Qfloat) (Qcons, Qbuffer): New declarations. * lisp/emacs-lisp/chart.el (chart-emacs-storage): Change to reflect new format of data returned by Fgarbage_collect. --- src/alloc.c | 149 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 92 insertions(+), 57 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 7ab3f7b5e9c..b891d32d164 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -189,9 +189,9 @@ int abort_on_gc; /* Number of live and free conses etc. */ -static EMACS_INT total_conses, total_markers, total_symbols, total_vector_size; +static EMACS_INT total_conses, total_markers, total_symbols, total_buffers; static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; -static EMACS_INT total_free_floats, total_floats, total_free_vector_bytes; +static EMACS_INT total_free_floats, total_floats; /* Points to memory space allocated as "spare", to be freed if we run out of memory. We keep one large block, four cons-blocks, and @@ -1708,7 +1708,7 @@ static EMACS_INT total_strings, total_free_strings; /* Number of bytes used by live strings. */ -static EMACS_INT total_string_size; +static EMACS_INT total_string_bytes; /* Given a pointer to a Lisp_String S which is on the free-list string_free_list, return a pointer to its successor in the @@ -2081,7 +2081,7 @@ sweep_strings (void) string_free_list = NULL; total_strings = total_free_strings = 0; - total_string_size = 0; + total_string_bytes = 0; /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ for (b = string_blocks; b; b = next) @@ -2107,7 +2107,7 @@ sweep_strings (void) UNMARK_BALANCE_INTERVALS (s->intervals); ++total_strings; - total_string_size += STRING_BYTES (s); + total_string_bytes += STRING_BYTES (s); } else { @@ -2957,6 +2957,14 @@ static struct Lisp_Vector *large_vectors; Lisp_Object zero_vector; +/* Number of live vectors. */ + +static EMACS_INT total_vectors; + +/* Number of bytes used by live and free vectors. */ + +static EMACS_INT total_vector_bytes, total_free_vector_bytes; + /* Get a new vector block. */ static struct vector_block * @@ -3047,12 +3055,6 @@ allocate_vector_from_block (size_t nbytes) return vector; } -/* Return how many Lisp_Objects can be stored in V. */ - -#define VECTOR_SIZE(v) ((v)->header.size & PSEUDOVECTOR_FLAG ? \ - (PSEUDOVECTOR_SIZE_MASK & (v)->header.size) : \ - (v)->header.size) - /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ #define VECTOR_IN_BLOCK(vector, block) \ @@ -3077,7 +3079,7 @@ sweep_vectors (void) struct vector_block *block = vector_blocks, **bprev = &vector_blocks; struct Lisp_Vector *vector, *next, **vprev = &large_vectors; - total_free_vector_bytes = total_vector_size = 0; + total_vectors = total_vector_bytes = total_free_vector_bytes = 0; memset (vector_free_lists, 0, sizeof (vector_free_lists)); /* Looking through vector blocks. */ @@ -3092,7 +3094,8 @@ sweep_vectors (void) if (VECTOR_MARKED_P (vector)) { VECTOR_UNMARK (vector); - total_vector_size += VECTOR_SIZE (vector); + total_vectors++; + total_vector_bytes += vector->header.next.nbytes; next = ADVANCE (vector, vector->header.next.nbytes); } else @@ -3148,7 +3151,12 @@ sweep_vectors (void) if (VECTOR_MARKED_P (vector)) { VECTOR_UNMARK (vector); - total_vector_size += VECTOR_SIZE (vector); + total_vectors++; + /* All pseudovectors are small enough to be allocated from + vector blocks. This code should be redesigned if some + pseudovector type grows beyond VBLOCK_BYTES_MAX. */ + eassert (!(vector->header.size & PSEUDOVECTOR_FLAG)); + total_vector_bytes += header_size + vector->header.size * word_size; vprev = &vector->header.next.vector; } else @@ -5339,16 +5347,28 @@ inhibit_garbage_collection (void) return count; } +/* Used to avoid possible overflows when + converting from C to Lisp integers. */ + +static inline Lisp_Object +bounded_number (EMACS_INT number) +{ + return make_number (min (MOST_POSITIVE_FIXNUM, number)); +} DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", doc: /* Reclaim storage for Lisp objects no longer needed. Garbage collection happens automatically if you cons more than `gc-cons-threshold' bytes of Lisp data since previous garbage collection. `garbage-collect' normally returns a list with info on amount of space in use: - ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) - (USED-MISCS . FREE-MISCS) USED-STRING-CHARS USED-VECTOR-SLOTS - (USED-FLOATS . FREE-FLOATS) (USED-INTERVALS . FREE-INTERVALS) - (USED-STRINGS . FREE-STRINGS)) + ((CONS INTERNAL-SIZE USED-CONSES FREE-CONSES) + (SYMBOL INTERNAL-SIZE USED-SYMBOLS FREE-SYMBOLS) + (MISC INTERNAL-SIZE USED-MISCS FREE-MISCS) + (STRING INTERNAL-SIZE USED-STRINGS USED-STRING-BYTES FREE-STRING) + (VECTOR INTERNAL-SIZE USED-VECTORS USED-VECTOR-BYTES FREE-VECTOR-BYTES) + (FLOAT INTERNAL-SIZE USED-FLOATS FREE-FLOATS) + (INTERVAL INTERNAL-SIZE USED-INTERVALS FREE-INTERVALS) + (BUFFER INTERNAL-SIZE USED-BUFFERS)) However, if there was overflow in pure space, `garbage-collect' returns nil, because real GC can't be done. See Info node `(elisp)Garbage Collection'. */) @@ -5595,8 +5615,8 @@ See Info node `(elisp)Garbage Collection'. */) tot += total_conses * sizeof (struct Lisp_Cons); tot += total_symbols * sizeof (struct Lisp_Symbol); tot += total_markers * sizeof (union Lisp_Misc); - tot += total_string_size; - tot += total_vector_size * sizeof (Lisp_Object); + tot += total_string_bytes; + tot += total_vector_bytes; tot += total_floats * sizeof (struct Lisp_Float); tot += total_intervals * sizeof (struct interval); tot += total_strings * sizeof (struct Lisp_String); @@ -5621,20 +5641,38 @@ See Info node `(elisp)Garbage Collection'. */) unbind_to (count, Qnil); - total[0] = Fcons (make_number (total_conses), - make_number (total_free_conses)); - total[1] = Fcons (make_number (total_symbols), - make_number (total_free_symbols)); - total[2] = Fcons (make_number (total_markers), - make_number (total_free_markers)); - total[3] = make_number (total_string_size); - total[4] = make_number (total_vector_size); - total[5] = Fcons (make_number (total_floats), - make_number (total_free_floats)); - total[6] = Fcons (make_number (total_intervals), - make_number (total_free_intervals)); - total[7] = Fcons (make_number (total_strings), - make_number (total_free_strings)); + total[0] = list4 (Qcons, make_number (sizeof (struct Lisp_Cons)), + bounded_number (total_conses), + bounded_number (total_free_conses)); + + total[1] = list4 (Qsymbol, make_number (sizeof (struct Lisp_Symbol)), + bounded_number (total_symbols), + bounded_number (total_free_symbols)); + + total[2] = list4 (Qmisc, make_number (sizeof (union Lisp_Misc)), + bounded_number (total_markers), + bounded_number (total_free_markers)); + + total[3] = list5 (Qstring, make_number (sizeof (struct Lisp_String)), + bounded_number (total_strings), + bounded_number (total_string_bytes), + bounded_number (total_free_strings)); + + total[4] = list5 (Qvector, make_number (sizeof (struct Lisp_Vector)), + bounded_number (total_vectors), + bounded_number (total_vector_bytes), + bounded_number (total_free_vector_bytes)); + + total[5] = list4 (Qfloat, make_number (sizeof (struct Lisp_Float)), + bounded_number (total_floats), + bounded_number (total_free_floats)); + + total[6] = list4 (Qinterval, make_number (sizeof (struct interval)), + bounded_number (total_intervals), + bounded_number (total_free_intervals)); + + total[7] = list3 (Qbuffer, make_number (sizeof (struct buffer)), + bounded_number (total_buffers)); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES { @@ -6535,6 +6573,7 @@ gc_sweep (void) { register struct buffer *buffer = all_buffers, *prev = 0, *next; + total_buffers = 0; while (buffer) if (!VECTOR_MARKED_P (buffer)) { @@ -6550,6 +6589,7 @@ gc_sweep (void) { VECTOR_UNMARK (buffer); UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); + total_buffers++; prev = buffer, buffer = buffer->header.next.buffer; } } @@ -6592,22 +6632,17 @@ if heap statistics are not available. Both counters are in units of Lisp_Object val = Fmake_list (make_number (2), make_number (0)); XSETCAR (val, - (make_number - (min (MOST_POSITIVE_FIXNUM, - ((total_free_conses * sizeof (struct Lisp_Cons) - + total_free_markers * sizeof (union Lisp_Misc) - + total_free_symbols * sizeof (struct Lisp_Symbol) - + total_free_floats * sizeof (struct Lisp_Float) - + total_free_intervals * sizeof (struct interval) - + total_free_strings * sizeof (struct Lisp_String) - + total_free_vector_bytes - + 1023) - >> 10))))); - + bounded_number + ((total_free_conses * sizeof (struct Lisp_Cons) + + total_free_markers * sizeof (union Lisp_Misc) + + total_free_symbols * sizeof (struct Lisp_Symbol) + + total_free_floats * sizeof (struct Lisp_Float) + + total_free_intervals * sizeof (struct interval) + + total_free_strings * sizeof (struct Lisp_String) + + total_free_vector_bytes + + 1023) >> 10)); #ifdef DOUG_LEA_MALLOC - XSETCAR (XCDR (val), - make_number (min (MOST_POSITIVE_FIXNUM, - (mallinfo ().fordblks + 1023) >> 10))); + XSETCAR (XCDR (val), bounded_number ((mallinfo ().fordblks + 1023) >> 10)); #endif return val; } @@ -6629,14 +6664,14 @@ Frames, windows, buffers, and subprocesses count as vectors { Lisp_Object consed[8]; - consed[0] = make_number (min (MOST_POSITIVE_FIXNUM, cons_cells_consed)); - consed[1] = make_number (min (MOST_POSITIVE_FIXNUM, floats_consed)); - consed[2] = make_number (min (MOST_POSITIVE_FIXNUM, vector_cells_consed)); - consed[3] = make_number (min (MOST_POSITIVE_FIXNUM, symbols_consed)); - consed[4] = make_number (min (MOST_POSITIVE_FIXNUM, string_chars_consed)); - consed[5] = make_number (min (MOST_POSITIVE_FIXNUM, misc_objects_consed)); - consed[6] = make_number (min (MOST_POSITIVE_FIXNUM, intervals_consed)); - consed[7] = make_number (min (MOST_POSITIVE_FIXNUM, strings_consed)); + consed[0] = bounded_number (cons_cells_consed); + consed[1] = bounded_number (floats_consed); + consed[2] = bounded_number (vector_cells_consed); + consed[3] = bounded_number (symbols_consed); + consed[4] = bounded_number (string_chars_consed); + consed[5] = bounded_number (misc_objects_consed); + consed[6] = bounded_number (intervals_consed); + consed[7] = bounded_number (strings_consed); return Flist (8, consed); } -- cgit v1.2.1 From 169925ec990b7e22f35eb1e2c25a1b53f49072ff Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 18 Jul 2012 13:46:07 +0400 Subject: Fix sweep_vectors to handle large bool vectors correctly. * alloc.c (sweep_vectors): Account total_vector_bytes for bool vectors larger than VBLOCK_BYTES_MAX. --- src/alloc.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index b891d32d164..0c3f5de6c3e 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3152,11 +3152,27 @@ sweep_vectors (void) { VECTOR_UNMARK (vector); total_vectors++; - /* All pseudovectors are small enough to be allocated from - vector blocks. This code should be redesigned if some - pseudovector type grows beyond VBLOCK_BYTES_MAX. */ - eassert (!(vector->header.size & PSEUDOVECTOR_FLAG)); - total_vector_bytes += header_size + vector->header.size * word_size; + if (vector->header.size & PSEUDOVECTOR_FLAG) + { + if (((vector->header.size & PVEC_TYPE_MASK) + >> PSEUDOVECTOR_SIZE_BITS) == PVEC_BOOL_VECTOR) + { + struct Lisp_Bool_Vector *b + = (struct Lisp_Bool_Vector *) vector; + total_vector_bytes += header_size + sizeof (b->size) + + (b->size + BOOL_VECTOR_BITS_PER_CHAR - 1) + / BOOL_VECTOR_BITS_PER_CHAR; + } + else + /* All other pseudovectors are small enough to be + allocated from vector blocks. This code should + be redesigned if some pseudovector type grows + beyond VBLOCK_BYTES_MAX. */ + abort (); + } + else + total_vector_bytes + += header_size + vector->header.size * word_size; vprev = &vector->header.next.vector; } else -- cgit v1.2.1 From d06714cb449d3eb3f58f4ed79053ca173db286fa Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 18 Jul 2012 10:26:43 -0700 Subject: Remove some struct layout assumptions in bool vectors. * alloc.c (bool_header_size): New constant. (header_size, word_size): Move earlier, as they're now used earlier. Use 'word_size' in a few more places, where it's appropriate. (Fmake_bool_vector, sweep_vectors): Don't assume that there is no padding before the data member of a bool vector. (sweep_vectors): Use PSEUDOVECTOR_TYPEP, in an eassert, rather than doing the check by hand with an abort (). --- src/alloc.c | 55 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 0c3f5de6c3e..29aabdd4616 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -281,6 +281,14 @@ static void sweep_strings (void); static void free_misc (Lisp_Object); extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE; +/* Handy constants for vectorlike objects. */ +enum + { + header_size = offsetof (struct Lisp_Vector, contents), + bool_header_size = offsetof (struct Lisp_Bool_Vector, data), + word_size = sizeof (Lisp_Object) + }; + /* When scanning the C stack for live Lisp objects, Emacs keeps track of what memory allocated via lisp_malloc is intended for what purpose. This enumeration specifies the type of memory. */ @@ -2356,6 +2364,8 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) ptrdiff_t length_in_chars; EMACS_INT length_in_elts; int bits_per_value; + int extra_bool_elts = ((bool_header_size - header_size + word_size - 1) + / word_size); CHECK_NATNUM (length); @@ -2363,9 +2373,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value; - /* We must allocate one more elements than LENGTH_IN_ELTS for the - slot `size' of the struct Lisp_Bool_Vector. */ - val = Fmake_vector (make_number (length_in_elts + 1), Qnil); + val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); /* No Lisp_Object to trace in there. */ XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0); @@ -2874,12 +2882,10 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, #define VECTOR_BLOCK_SIZE 4096 -/* Handy constants for vectorlike objects. */ +/* Align allocation request sizes to be a multiple of ROUNDUP_SIZE. */ enum { - header_size = offsetof (struct Lisp_Vector, contents), - word_size = sizeof (Lisp_Object), - roundup_size = COMMON_MULTIPLE (sizeof (Lisp_Object), + roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? 1 << GCTYPEBITS : 1) }; @@ -2905,7 +2911,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); /* Size of the largest vector allocated from block. */ #define VBLOCK_BYTES_MAX \ - vroundup ((VECTOR_BLOCK_BYTES / 2) - sizeof (Lisp_Object)) + vroundup ((VECTOR_BLOCK_BYTES / 2) - word_size) /* We maintain one free list for each possible block-allocated vector size, and this is the number of free lists we have. */ @@ -3154,25 +3160,21 @@ sweep_vectors (void) total_vectors++; if (vector->header.size & PSEUDOVECTOR_FLAG) { - if (((vector->header.size & PVEC_TYPE_MASK) - >> PSEUDOVECTOR_SIZE_BITS) == PVEC_BOOL_VECTOR) - { - struct Lisp_Bool_Vector *b - = (struct Lisp_Bool_Vector *) vector; - total_vector_bytes += header_size + sizeof (b->size) - + (b->size + BOOL_VECTOR_BITS_PER_CHAR - 1) - / BOOL_VECTOR_BITS_PER_CHAR; - } - else - /* All other pseudovectors are small enough to be - allocated from vector blocks. This code should - be redesigned if some pseudovector type grows - beyond VBLOCK_BYTES_MAX. */ - abort (); + struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) vector; + + /* All non-bool pseudovectors are small enough to be allocated + from vector blocks. This code should be redesigned if some + pseudovector type grows beyond VBLOCK_BYTES_MAX. */ + eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)); + + total_vector_bytes + += (bool_header_size + + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1) + / BOOL_VECTOR_BITS_PER_CHAR)); } else - total_vector_bytes - += header_size + vector->header.size * word_size; + total_vector_bytes += (header_size + + vector->header.size * word_size); vprev = &vector->header.next.vector; } else @@ -5261,8 +5263,7 @@ make_pure_vector (ptrdiff_t len) { Lisp_Object new; struct Lisp_Vector *p; - size_t size = (offsetof (struct Lisp_Vector, contents) - + len * sizeof (Lisp_Object)); + size_t size = header_size + len * word_size; p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike); XSETVECTOR (new, p); -- cgit v1.2.1 From 837131548b13935cc7a2cbb7114bfb0ee44eae76 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 18 Jul 2012 10:29:34 -0700 Subject: * alloc.c (Fmake_bool_vector): Fix off-by-8 bug when invoking (make-bool-vector N t) and N is a positive multiple of 8 -- the last 8 bits were mistakenly cleared. --- src/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 29aabdd4616..a6980e867a7 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -2389,7 +2389,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) /* Clear any extraneous bits in the last byte. */ p->data[length_in_chars - 1] - &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1; + &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1; } return val; -- cgit v1.2.1 From d17337e501a189c1d46f758e10c6c2842cafff17 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 19 Jul 2012 07:55:59 +0400 Subject: New macro to iterate over all buffers, miscellaneous cleanups. * lisp.h (all_buffers): Remove declaration. * buffer.h (all_buffers): Add declaration, with comment. (for_each_buffer): New macro. * alloc.c (Fgarbage_collect, mark_object): Use it. * buffer.c (Fkill_buffer, Fbuffer_swap_text, Fset_buffer_multibyte) (init_buffer): Likewise. * data.c (Fset_default): Likewise. * coding.c (code_conversion_restore): Remove redundant check for dead buffer. * buffer.c (Fkill_buffer): Likewise. Remove obsolete comment. --- src/alloc.c | 146 ++++++++++++++++++++++++++++-------------------------------- 1 file changed, 68 insertions(+), 78 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index a6980e867a7..166f5b72449 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5392,6 +5392,7 @@ See Info node `(elisp)Garbage Collection'. */) (void) { register struct specbinding *bind; + register struct buffer *nextb; char stack_top_variable; ptrdiff_t i; int message_p; @@ -5411,40 +5412,34 @@ See Info node `(elisp)Garbage Collection'. */) /* Don't keep undo information around forever. Do this early on, so it is no problem if the user quits. */ - { - register struct buffer *nextb = all_buffers; - - while (nextb) - { - /* If a buffer's undo list is Qt, that means that undo is - turned off in that buffer. Calling truncate_undo_list on - Qt tends to return NULL, which effectively turns undo back on. - So don't call truncate_undo_list if undo_list is Qt. */ - if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name)) - && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) - truncate_undo_list (nextb); - - /* Shrink buffer gaps, but skip indirect and dead buffers. */ - if (nextb->base_buffer == 0 && !NILP (nextb->BUFFER_INTERNAL_FIELD (name)) - && ! nextb->text->inhibit_shrinking) - { - /* If a buffer's gap size is more than 10% of the buffer - size, or larger than 2000 bytes, then shrink it - accordingly. Keep a minimum size of 20 bytes. */ - int size = min (2000, max (20, (nextb->text->z_byte / 10))); - - if (nextb->text->gap_size > size) - { - struct buffer *save_current = current_buffer; - current_buffer = nextb; - make_gap (-(nextb->text->gap_size - size)); - current_buffer = save_current; - } - } + for_each_buffer (nextb) + { + /* If a buffer's undo list is Qt, that means that undo is + turned off in that buffer. Calling truncate_undo_list on + Qt tends to return NULL, which effectively turns undo back on. + So don't call truncate_undo_list if undo_list is Qt. */ + if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name)) + && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) + truncate_undo_list (nextb); + + /* Shrink buffer gaps, but skip indirect and dead buffers. */ + if (nextb->base_buffer == 0 && !NILP (nextb->BUFFER_INTERNAL_FIELD (name)) + && ! nextb->text->inhibit_shrinking) + { + /* If a buffer's gap size is more than 10% of the buffer + size, or larger than 2000 bytes, then shrink it + accordingly. Keep a minimum size of 20 bytes. */ + int size = min (2000, max (20, (nextb->text->z_byte / 10))); - nextb = nextb->header.next.buffer; - } - } + if (nextb->text->gap_size > size) + { + struct buffer *save_current = current_buffer; + current_buffer = nextb; + make_gap (-(nextb->text->gap_size - size)); + current_buffer = save_current; + } + } + } t1 = current_emacs_time (); @@ -5558,48 +5553,42 @@ See Info node `(elisp)Garbage Collection'. */) Look thru every buffer's undo list for elements that update markers that were not marked, and delete them. */ - { - register struct buffer *nextb = all_buffers; - - while (nextb) - { - /* If a buffer's undo list is Qt, that means that undo is - turned off in that buffer. Calling truncate_undo_list on - Qt tends to return NULL, which effectively turns undo back on. - So don't call truncate_undo_list if undo_list is Qt. */ - if (! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) - { - Lisp_Object tail, prev; - tail = nextb->BUFFER_INTERNAL_FIELD (undo_list); - prev = Qnil; - while (CONSP (tail)) - { - if (CONSP (XCAR (tail)) - && MARKERP (XCAR (XCAR (tail))) - && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) - { - if (NILP (prev)) - nextb->BUFFER_INTERNAL_FIELD (undo_list) = tail = XCDR (tail); - else - { - tail = XCDR (tail); - XSETCDR (prev, tail); - } - } - else - { - prev = tail; - tail = XCDR (tail); - } - } - } - /* Now that we have stripped the elements that need not be in the - undo_list any more, we can finally mark the list. */ - mark_object (nextb->BUFFER_INTERNAL_FIELD (undo_list)); - - nextb = nextb->header.next.buffer; - } - } + for_each_buffer (nextb) + { + /* If a buffer's undo list is Qt, that means that undo is + turned off in that buffer. Calling truncate_undo_list on + Qt tends to return NULL, which effectively turns undo back on. + So don't call truncate_undo_list if undo_list is Qt. */ + if (! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) + { + Lisp_Object tail, prev; + tail = nextb->BUFFER_INTERNAL_FIELD (undo_list); + prev = Qnil; + while (CONSP (tail)) + { + if (CONSP (XCAR (tail)) + && MARKERP (XCAR (XCAR (tail))) + && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) + { + if (NILP (prev)) + nextb->BUFFER_INTERNAL_FIELD (undo_list) = tail = XCDR (tail); + else + { + tail = XCDR (tail); + XSETCDR (prev, tail); + } + } + else + { + prev = tail; + tail = XCDR (tail); + } + } + } + /* Now that we have stripped the elements that need not be in the + undo_list any more, we can finally mark the list. */ + mark_object (nextb->BUFFER_INTERNAL_FIELD (undo_list)); + } gc_sweep (); @@ -5987,9 +5976,10 @@ mark_object (Lisp_Object arg) #ifdef GC_CHECK_MARKED_OBJECTS if (po != &buffer_defaults && po != &buffer_local_symbols) { - struct buffer *b = all_buffers; - for (; b && b != po; b = b->header.next.buffer) - ; + struct buffer *b; + for_each_buffer (b) + if (b == po) + break; if (b == NULL) abort (); } -- cgit v1.2.1 From 9cd47b72e021f76a6e2481d986ce4b0cb0b859d3 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 19 Jul 2012 12:56:53 +0400 Subject: Compact buffers when idle. * lisp/compact.el: New file. * src/buffer.c (compact_buffer, Fcompact_buffer): New function. (syms_of_buffer): Register Fcompact_buffer. * src/alloc.c (Fgarbage_collect): Use compact_buffer. * src/buffer.h (compact_buffer): New prototype. (struct buffer_text): New member. --- src/alloc.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 166f5b72449..233137e368e 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5413,33 +5413,7 @@ See Info node `(elisp)Garbage Collection'. */) /* Don't keep undo information around forever. Do this early on, so it is no problem if the user quits. */ for_each_buffer (nextb) - { - /* If a buffer's undo list is Qt, that means that undo is - turned off in that buffer. Calling truncate_undo_list on - Qt tends to return NULL, which effectively turns undo back on. - So don't call truncate_undo_list if undo_list is Qt. */ - if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name)) - && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) - truncate_undo_list (nextb); - - /* Shrink buffer gaps, but skip indirect and dead buffers. */ - if (nextb->base_buffer == 0 && !NILP (nextb->BUFFER_INTERNAL_FIELD (name)) - && ! nextb->text->inhibit_shrinking) - { - /* If a buffer's gap size is more than 10% of the buffer - size, or larger than 2000 bytes, then shrink it - accordingly. Keep a minimum size of 20 bytes. */ - int size = min (2000, max (20, (nextb->text->z_byte / 10))); - - if (nextb->text->gap_size > size) - { - struct buffer *save_current = current_buffer; - current_buffer = nextb; - make_gap (-(nextb->text->gap_size - size)); - current_buffer = save_current; - } - } - } + compact_buffer (nextb); t1 = current_emacs_time (); -- cgit v1.2.1 From 5b835e1d6e0c6fafc7f27174889358bfde5f2449 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 19 Jul 2012 13:50:01 +0400 Subject: Tweak the value returned from Fgarbage_collect again. * src/alloc.c (Fgarbage_collect): New return value, as confirmed in http://lists.gnu.org/archive/html/emacs-devel/2012-07/msg00418.html. Adjust documentation. (total_vector_bytes): Rename to total_vector_slots, adjust accounting. (total_free_vector_bytes): Rename to total_free_vector_slots, adjust accounting. (Qstring_bytes, Qvector_slots): New symbols. (syms_of_alloc): DEFSYM them. * lisp/emacs-lisp/chart.el (chart-emacs-storage): Adjust again. --- src/alloc.c | 60 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 25 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 233137e368e..c52b0475352 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -258,6 +258,7 @@ static char *stack_copy; static ptrdiff_t stack_copy_size; #endif +static Lisp_Object Qstring_bytes, Qvector_slots; static Lisp_Object Qgc_cons_threshold; Lisp_Object Qchar_table_extra_slots; @@ -2937,7 +2938,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ (v)->header.next.vector = vector_free_lists[index]; \ vector_free_lists[index] = (v); \ - total_free_vector_bytes += (nbytes); \ + total_free_vector_slots += (nbytes) / word_size; \ } while (0) struct vector_block @@ -2967,9 +2968,9 @@ Lisp_Object zero_vector; static EMACS_INT total_vectors; -/* Number of bytes used by live and free vectors. */ +/* Total size of live and free vectors, in Lisp_Object units. */ -static EMACS_INT total_vector_bytes, total_free_vector_bytes; +static EMACS_INT total_vector_slots, total_free_vector_slots; /* Get a new vector block. */ @@ -3016,7 +3017,7 @@ allocate_vector_from_block (size_t nbytes) vector = vector_free_lists[index]; vector_free_lists[index] = vector->header.next.vector; vector->header.next.nbytes = nbytes; - total_free_vector_bytes -= nbytes; + total_free_vector_slots -= nbytes / word_size; return vector; } @@ -3031,7 +3032,7 @@ allocate_vector_from_block (size_t nbytes) vector = vector_free_lists[index]; vector_free_lists[index] = vector->header.next.vector; vector->header.next.nbytes = nbytes; - total_free_vector_bytes -= nbytes; + total_free_vector_slots -= nbytes / word_size; /* Excess bytes are used for the smaller vector, which should be set on an appropriate free list. */ @@ -3085,7 +3086,7 @@ sweep_vectors (void) struct vector_block *block = vector_blocks, **bprev = &vector_blocks; struct Lisp_Vector *vector, *next, **vprev = &large_vectors; - total_vectors = total_vector_bytes = total_free_vector_bytes = 0; + total_vectors = total_vector_slots = total_free_vector_slots = 0; memset (vector_free_lists, 0, sizeof (vector_free_lists)); /* Looking through vector blocks. */ @@ -3101,7 +3102,7 @@ sweep_vectors (void) { VECTOR_UNMARK (vector); total_vectors++; - total_vector_bytes += vector->header.next.nbytes; + total_vector_slots += vector->header.next.nbytes / word_size; next = ADVANCE (vector, vector->header.next.nbytes); } else @@ -3167,14 +3168,14 @@ sweep_vectors (void) pseudovector type grows beyond VBLOCK_BYTES_MAX. */ eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)); - total_vector_bytes + total_vector_slots += (bool_header_size + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1) - / BOOL_VECTOR_BITS_PER_CHAR)); + / BOOL_VECTOR_BITS_PER_CHAR)) / word_size; } else - total_vector_bytes += (header_size - + vector->header.size * word_size); + total_vector_slots + += header_size / word_size + vector->header.size; vprev = &vector->header.next.vector; } else @@ -5381,8 +5382,10 @@ Garbage collection happens automatically if you cons more than ((CONS INTERNAL-SIZE USED-CONSES FREE-CONSES) (SYMBOL INTERNAL-SIZE USED-SYMBOLS FREE-SYMBOLS) (MISC INTERNAL-SIZE USED-MISCS FREE-MISCS) - (STRING INTERNAL-SIZE USED-STRINGS USED-STRING-BYTES FREE-STRING) - (VECTOR INTERNAL-SIZE USED-VECTORS USED-VECTOR-BYTES FREE-VECTOR-BYTES) + (STRING INTERNAL-SIZE USED-STRINGS FREE-STRING) + (STRING-BYTES 1 USED-STRING-BYTES) + (VECTOR INTERNAL-SIZE USED-VECTORS) + (VECTOR-SLOTS INTERNAL-SIZE USED-VECTOR-SLOTS FREE-VECTOR-SLOTS) (FLOAT INTERNAL-SIZE USED-FLOATS FREE-FLOATS) (INTERVAL INTERNAL-SIZE USED-INTERVALS FREE-INTERVALS) (BUFFER INTERNAL-SIZE USED-BUFFERS)) @@ -5396,7 +5399,7 @@ See Info node `(elisp)Garbage Collection'. */) char stack_top_variable; ptrdiff_t i; int message_p; - Lisp_Object total[8]; + Lisp_Object total[10]; ptrdiff_t count = SPECPDL_INDEX (); EMACS_TIME t1; @@ -5596,7 +5599,7 @@ See Info node `(elisp)Garbage Collection'. */) tot += total_symbols * sizeof (struct Lisp_Symbol); tot += total_markers * sizeof (union Lisp_Misc); tot += total_string_bytes; - tot += total_vector_bytes; + tot += total_vector_slots * word_size; tot += total_floats * sizeof (struct Lisp_Float); tot += total_intervals * sizeof (struct interval); tot += total_strings * sizeof (struct Lisp_String); @@ -5633,25 +5636,29 @@ See Info node `(elisp)Garbage Collection'. */) bounded_number (total_markers), bounded_number (total_free_markers)); - total[3] = list5 (Qstring, make_number (sizeof (struct Lisp_String)), + total[3] = list4 (Qstring, make_number (sizeof (struct Lisp_String)), bounded_number (total_strings), - bounded_number (total_string_bytes), bounded_number (total_free_strings)); - total[4] = list5 (Qvector, make_number (sizeof (struct Lisp_Vector)), - bounded_number (total_vectors), - bounded_number (total_vector_bytes), - bounded_number (total_free_vector_bytes)); + total[4] = list3 (Qstring_bytes, make_number (1), + bounded_number (total_string_bytes)); - total[5] = list4 (Qfloat, make_number (sizeof (struct Lisp_Float)), + total[5] = list3 (Qvector, make_number (sizeof (struct Lisp_Vector)), + bounded_number (total_vectors)); + + total[6] = list4 (Qvector_slots, make_number (word_size), + bounded_number (total_vector_slots), + bounded_number (total_free_vector_slots)); + + total[7] = list4 (Qfloat, make_number (sizeof (struct Lisp_Float)), bounded_number (total_floats), bounded_number (total_free_floats)); - total[6] = list4 (Qinterval, make_number (sizeof (struct interval)), + total[8] = list4 (Qinterval, make_number (sizeof (struct interval)), bounded_number (total_intervals), bounded_number (total_free_intervals)); - total[7] = list3 (Qbuffer, make_number (sizeof (struct buffer)), + total[9] = list3 (Qbuffer, make_number (sizeof (struct buffer)), bounded_number (total_buffers)); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES @@ -6620,7 +6627,7 @@ if heap statistics are not available. Both counters are in units of + total_free_floats * sizeof (struct Lisp_Float) + total_free_intervals * sizeof (struct interval) + total_free_strings * sizeof (struct Lisp_String) - + total_free_vector_bytes + + total_free_vector_slots * word_size + 1023) >> 10)); #ifdef DOUG_LEA_MALLOC XSETCAR (XCDR (val), bounded_number ((mallinfo ().fordblks + 1023) >> 10)); @@ -6842,6 +6849,9 @@ do hash-consing of the objects allocated to pure space. */); doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); Vmemory_full = Qnil; + DEFSYM (Qstring_bytes, "string-bytes"); + DEFSYM (Qvector_slots, "vector-slots"); + DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); -- cgit v1.2.1 From 5db81e33629049da22e7d0ff6c28a5cae31edac9 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Thu, 19 Jul 2012 07:39:38 -0400 Subject: * lisp/emacs-lisp/chart.el: Use lexical-binding. (chart-emacs-storage): Don't hardcode the list of entries. * src/alloc.c (Fgarbage_collect): Tweak docstring. --- src/alloc.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index c52b0475352..d24787576e9 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5378,17 +5378,14 @@ DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", doc: /* Reclaim storage for Lisp objects no longer needed. Garbage collection happens automatically if you cons more than `gc-cons-threshold' bytes of Lisp data since previous garbage collection. -`garbage-collect' normally returns a list with info on amount of space in use: - ((CONS INTERNAL-SIZE USED-CONSES FREE-CONSES) - (SYMBOL INTERNAL-SIZE USED-SYMBOLS FREE-SYMBOLS) - (MISC INTERNAL-SIZE USED-MISCS FREE-MISCS) - (STRING INTERNAL-SIZE USED-STRINGS FREE-STRING) - (STRING-BYTES 1 USED-STRING-BYTES) - (VECTOR INTERNAL-SIZE USED-VECTORS) - (VECTOR-SLOTS INTERNAL-SIZE USED-VECTOR-SLOTS FREE-VECTOR-SLOTS) - (FLOAT INTERNAL-SIZE USED-FLOATS FREE-FLOATS) - (INTERVAL INTERNAL-SIZE USED-INTERVALS FREE-INTERVALS) - (BUFFER INTERNAL-SIZE USED-BUFFERS)) +`garbage-collect' normally returns a list with info on amount of space in use, +where each entry has the form (NAME SIZE USED FREE), where: +- NAME is a symbol describing the kind of objects this entry represents, +- SIZE is the number of bytes used by each one, +- USED is the number of those objects that were found live in the heap, +- FREE is the number of those objects that are not live but that Emacs + keeps around for future allocations (maybe because it does not know how + to return them to the OS). However, if there was overflow in pure space, `garbage-collect' returns nil, because real GC can't be done. See Info node `(elisp)Garbage Collection'. */) -- cgit v1.2.1 From 52b852c77d74800aaa1338dc72f786f7e261bfee Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 19 Jul 2012 15:35:58 -0700 Subject: * buffer.h (FOR_EACH_BUFFER): Rename from 'for_each_buffer'. (FOR_EACH_PER_BUFFER_OBJECT_AT): Rename from 'for_each_per_buffer_object_at'. All uses changed. It's better to use upper-case for macros that cannot be implemented as functions, to give the reader a clue that they're special. --- src/alloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index d24787576e9..7158b45a340 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5412,7 +5412,7 @@ See Info node `(elisp)Garbage Collection'. */) /* Don't keep undo information around forever. Do this early on, so it is no problem if the user quits. */ - for_each_buffer (nextb) + FOR_EACH_BUFFER (nextb) compact_buffer (nextb); t1 = current_emacs_time (); @@ -5527,7 +5527,7 @@ See Info node `(elisp)Garbage Collection'. */) Look thru every buffer's undo list for elements that update markers that were not marked, and delete them. */ - for_each_buffer (nextb) + FOR_EACH_BUFFER (nextb) { /* If a buffer's undo list is Qt, that means that undo is turned off in that buffer. Calling truncate_undo_list on @@ -5955,7 +5955,7 @@ mark_object (Lisp_Object arg) if (po != &buffer_defaults && po != &buffer_local_symbols) { struct buffer *b; - for_each_buffer (b) + FOR_EACH_BUFFER (b) if (b == po) break; if (b == NULL) -- cgit v1.2.1 From 765e61e391ee0937ff6b30510b6c4651064fe38e Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 20 Jul 2012 09:28:00 +0400 Subject: Cleanup calls to Fgarbage_collect. * lisp.h (maybe_gc): New prototype. (consing_since_gc, gc_relative_threshold, memory_full_cons_threshold): Remove declarations. * alloc.c (maybe_gc): New function. (consing_since_gc, gc_relative_threshold, memory_full_cons_threshold): Make them static. * bytecode.c (MAYBE_GC): Use maybe_gc. * eval.c (eval_sub, Ffuncall): Likewise. * keyboard.c (read_char): Likewise. Adjust call to maybe_gc to avoid dependency from auto-save feature. --- src/alloc.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 7158b45a340..36040f70b2d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -166,16 +166,16 @@ struct emacs_globals globals; /* Number of bytes of consing done since the last gc. */ -EMACS_INT consing_since_gc; +static EMACS_INT consing_since_gc; /* Similar minimum, computed from Vgc_cons_percentage. */ -EMACS_INT gc_relative_threshold; +static EMACS_INT gc_relative_threshold; /* Minimum number of bytes of consing since GC before next GC, when memory is full. */ -EMACS_INT memory_full_cons_threshold; +static EMACS_INT memory_full_cons_threshold; /* Nonzero during GC. */ @@ -5374,6 +5374,18 @@ bounded_number (EMACS_INT number) return make_number (min (MOST_POSITIVE_FIXNUM, number)); } +/* Check whether it's time for GC, and run it if so. */ + +void +maybe_gc (void) +{ + if ((consing_since_gc > gc_cons_threshold + && consing_since_gc > gc_relative_threshold) + || (!NILP (Vmemory_full) + && consing_since_gc > memory_full_cons_threshold)) + Fgarbage_collect (); +} + DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", doc: /* Reclaim storage for Lisp objects no longer needed. Garbage collection happens automatically if you cons more than -- cgit v1.2.1 From dac616ff9f51b77e399a06863a79446958c4f840 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 20 Jul 2012 17:14:58 +0400 Subject: Make maybe_gc inline. Verify that inlining is always possible (GCC 4.7.1, -O3 -Winline). * lisp.h (consing_since_gc, gc_relative_threshold) (memory_full_cons_threshold): Revert declaration. (maybe_gc): Remove prototype, define as inline. * alloc.c: Remove old commented-out code. (consing_since_gc, gc_relative_threshold) (memory_full_cons_threshold): Revert to global. (maybe_gc): Remove. --- src/alloc.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 36040f70b2d..e7d67e95dbe 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -166,16 +166,16 @@ struct emacs_globals globals; /* Number of bytes of consing done since the last gc. */ -static EMACS_INT consing_since_gc; +EMACS_INT consing_since_gc; /* Similar minimum, computed from Vgc_cons_percentage. */ -static EMACS_INT gc_relative_threshold; +EMACS_INT gc_relative_threshold; /* Minimum number of bytes of consing since GC before next GC, when memory is full. */ -static EMACS_INT memory_full_cons_threshold; +EMACS_INT memory_full_cons_threshold; /* Nonzero during GC. */ @@ -5374,18 +5374,6 @@ bounded_number (EMACS_INT number) return make_number (min (MOST_POSITIVE_FIXNUM, number)); } -/* Check whether it's time for GC, and run it if so. */ - -void -maybe_gc (void) -{ - if ((consing_since_gc > gc_cons_threshold - && consing_since_gc > gc_relative_threshold) - || (!NILP (Vmemory_full) - && consing_since_gc > memory_full_cons_threshold)) - Fgarbage_collect (); -} - DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", doc: /* Reclaim storage for Lisp objects no longer needed. Garbage collection happens automatically if you cons more than @@ -5474,8 +5462,6 @@ See Info node `(elisp)Garbage Collection'. */) gc_in_progress = 1; - /* clear_marks (); */ - /* Mark all the special slots that serve as the roots of accessibility. */ for (i = 0; i < staticidx; i++) @@ -5592,7 +5578,6 @@ See Info node `(elisp)Garbage Collection'. */) CHECK_CONS_LIST (); - /* clear_marks (); */ gc_in_progress = 0; consing_since_gc = 0; -- cgit v1.2.1 From f8643a6b9e35af22b69a84f83df5d9410de82f16 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 20 Jul 2012 18:07:28 +0400 Subject: Extend the value returned by Fgarbage_collect with heap statistics. * alloc.c (Qheap): New symbol. (syms_of_alloc): DEFSYM it. (Fgarbage_collect): If DOUG_LEA_MALLOC, add mallinfo data. (Fmemory_free): Remove. (syms_of_alloc): Don't defsubr it. * buffer.c (Fcompact_buffer): Remove. (syms_of_buffer): Don't defsubr it. --- src/alloc.c | 42 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 30 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index e7d67e95dbe..05e676836c5 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -258,7 +258,7 @@ static char *stack_copy; static ptrdiff_t stack_copy_size; #endif -static Lisp_Object Qstring_bytes, Qvector_slots; +static Lisp_Object Qstring_bytes, Qvector_slots, Qheap; static Lisp_Object Qgc_cons_threshold; Lisp_Object Qchar_table_extra_slots; @@ -5396,7 +5396,7 @@ See Info node `(elisp)Garbage Collection'. */) char stack_top_variable; ptrdiff_t i; int message_p; - Lisp_Object total[10]; + Lisp_Object total[11]; ptrdiff_t count = SPECPDL_INDEX (); EMACS_TIME t1; @@ -5655,6 +5655,15 @@ See Info node `(elisp)Garbage Collection'. */) total[9] = list3 (Qbuffer, make_number (sizeof (struct buffer)), bounded_number (total_buffers)); + total[10] = list4 (Qheap, make_number (1024), +#ifdef DOUG_LEA_MALLOC + bounded_number ((mallinfo ().uordblks + 1023) >> 10), + bounded_number ((mallinfo ().fordblks + 1023) >> 10) +#else + Qnil, Qnil +#endif + ); + #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES { /* Compute average percentage of zombies. */ @@ -6602,33 +6611,6 @@ We divide the value by 1024 to make sure it fits in a Lisp integer. */) return end; } -DEFUN ("memory-free", Fmemory_free, Smemory_free, 0, 0, 0, - doc: /* Return a list (E H) of two measures of free memory. -E counts free lists maintained by Emacs itself. H counts the heap, -freed by Emacs but not released to the operating system; this is zero -if heap statistics are not available. Both counters are in units of -1024 bytes, rounded up. */) - (void) -{ - /* Make the return value first, so that its storage is accounted for. */ - Lisp_Object val = Fmake_list (make_number (2), make_number (0)); - - XSETCAR (val, - bounded_number - ((total_free_conses * sizeof (struct Lisp_Cons) - + total_free_markers * sizeof (union Lisp_Misc) - + total_free_symbols * sizeof (struct Lisp_Symbol) - + total_free_floats * sizeof (struct Lisp_Float) - + total_free_intervals * sizeof (struct interval) - + total_free_strings * sizeof (struct Lisp_String) - + total_free_vector_slots * word_size - + 1023) >> 10)); -#ifdef DOUG_LEA_MALLOC - XSETCAR (XCDR (val), bounded_number ((mallinfo ().fordblks + 1023) >> 10)); -#endif - return val; -} - DEFUN ("memory-use-counts", Fmemory_use_counts, Smemory_use_counts, 0, 0, 0, doc: /* Return a list of counters that measure how much consing there has been. Each of these counters increments for a certain kind of object. @@ -6845,6 +6827,7 @@ do hash-consing of the objects allocated to pure space. */); DEFSYM (Qstring_bytes, "string-bytes"); DEFSYM (Qvector_slots, "vector-slots"); + DEFSYM (Qheap, "heap"); DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); @@ -6868,7 +6851,6 @@ The time is in seconds as a floating point value. */); defsubr (&Spurecopy); defsubr (&Sgarbage_collect); defsubr (&Smemory_limit); - defsubr (&Smemory_free); defsubr (&Smemory_use_counts); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES -- cgit v1.2.1 From 0dd6d66d56e7133818db361cc853fd1d00f2714b Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Sun, 22 Jul 2012 19:13:50 +0400 Subject: Adjust consing_since_gc when objects are explicitly freed. * alloc.c (GC_DEFAULT_THRESHOLD): New macro. (Fgarbage_collect): Use it. Change minimum to 1/10 of default. (free_cons, free_misc): Subtract object size from consing_since_gc. --- src/alloc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 05e676836c5..9f3c2a2ed4b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -161,6 +161,10 @@ static pthread_mutex_t alloc_mutex; #define GC_STRING_BYTES(S) (STRING_BYTES (S)) +/* Default value of gc_cons_threshold (see below). */ + +#define GC_DEFAULT_THRESHOLD (100000 * sizeof (Lisp_Object)) + /* Global variables. */ struct emacs_globals globals; @@ -2711,6 +2715,7 @@ free_cons (struct Lisp_Cons *ptr) ptr->car = Vdead; #endif cons_free_list = ptr; + consing_since_gc -= sizeof *ptr; total_free_conses++; } @@ -3606,7 +3611,7 @@ free_misc (Lisp_Object misc) XMISCTYPE (misc) = Lisp_Misc_Free; XMISC (misc)->u_free.chain = marker_free_list; marker_free_list = XMISC (misc); - + consing_since_gc -= sizeof (union Lisp_Misc); total_free_markers++; } @@ -5581,8 +5586,8 @@ See Info node `(elisp)Garbage Collection'. */) gc_in_progress = 0; consing_since_gc = 0; - if (gc_cons_threshold < 10000) - gc_cons_threshold = 10000; + if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10) + gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10; gc_relative_threshold = 0; if (FLOATP (Vgc_cons_percentage)) @@ -6731,7 +6736,7 @@ init_alloc_once (void) #endif refill_memory_reserve (); - gc_cons_threshold = 100000 * sizeof (Lisp_Object); + gc_cons_threshold = GC_DEFAULT_THRESHOLD; } void -- cgit v1.2.1 From d7a7fda3cc130edb8bc10af96d322d263afbb44a Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 23 Jul 2012 15:15:43 +0400 Subject: Cleanup miscellaneous objects allocation and initialization. * alloc.c (allocate_misc): Change to static. Add argument to specify the subtype. Adjust comment and users. (build_overlay): New function. * buffer.c (copy_overlays, Fmake_overlay): Use it. * lisp.h (struct Lisp_Overlay): Remove obsolete comment. (allocate_misc): Remove prototype. (build_overlay): Add prototype. --- src/alloc.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index 9f3c2a2ed4b..d9c56b5c7c8 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3564,10 +3564,10 @@ static int marker_block_index = MARKER_BLOCK_SIZE; static union Lisp_Misc *marker_free_list; -/* Return a newly allocated Lisp_Misc object, with no substructure. */ +/* Return a newly allocated Lisp_Misc object of specified TYPE. */ -Lisp_Object -allocate_misc (void) +static Lisp_Object +allocate_misc (enum Lisp_Misc_Type type) { Lisp_Object val; @@ -3599,6 +3599,7 @@ allocate_misc (void) --total_free_markers; consing_since_gc += sizeof (union Lisp_Misc); misc_objects_consed++; + XMISCTYPE (val) = type; XMISCANY (val)->gcmarkbit = 0; return val; } @@ -3625,8 +3626,7 @@ make_save_value (void *pointer, ptrdiff_t integer) register Lisp_Object val; register struct Lisp_Save_Value *p; - val = allocate_misc (); - XMISCTYPE (val) = Lisp_Misc_Save_Value; + val = allocate_misc (Lisp_Misc_Save_Value); p = XSAVE_VALUE (val); p->pointer = pointer; p->integer = integer; @@ -3634,6 +3634,21 @@ make_save_value (void *pointer, ptrdiff_t integer) return val; } +/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */ + +Lisp_Object +build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist) +{ + register Lisp_Object overlay; + + overlay = allocate_misc (Lisp_Misc_Overlay); + OVERLAY_START (overlay) = start; + OVERLAY_END (overlay) = end; + OVERLAY_PLIST (overlay) = plist; + XOVERLAY (overlay)->next = NULL; + return overlay; +} + DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, doc: /* Return a newly allocated marker which does not point at any place. */) (void) @@ -3641,8 +3656,7 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, register Lisp_Object val; register struct Lisp_Marker *p; - val = allocate_misc (); - XMISCTYPE (val) = Lisp_Misc_Marker; + val = allocate_misc (Lisp_Misc_Marker); p = XMARKER (val); p->buffer = 0; p->bytepos = 0; @@ -3667,8 +3681,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) /* Every character is at least one byte. */ eassert (charpos <= bytepos); - obj = allocate_misc (); - XMISCTYPE (obj) = Lisp_Misc_Marker; + obj = allocate_misc (Lisp_Misc_Marker); m = XMARKER (obj); m->buffer = buf; m->charpos = charpos; -- cgit v1.2.1 From 5eceb8fb134263b05608532afb33fdf43c1e3713 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 26 Jul 2012 11:35:50 -0700 Subject: Fix export of symbols to GDB. * alloc.c (ARRAY_MARK_FLAG_VAL, PSEUDOVECTOR_FLAG_VAL, VALMASK_VAL) (ARRAY_MARK_FLAG, PSEUDOVECTOR_FLAG, VALMASK): Move these here from emacs.c, as this is a more-suitable home. Had this been done earlier the fix for 1995-05-30T23:07:27Z!kwzh@gnu.org would have avoided some of the problems noted in by Eli Zaretskii, as the scope problems would have been more obvious. * emacs.c (gdb_CHECK_LISP_OBJECT_TYPE, gdb_DATA_SEG_BITS) (gdb_GCTYPEBITS, gdb_USE_LSB_TAG) (CHECK_LISP_OBJECT_TYPE, DATA_SEG_BITS, GCTYPEBITS, USE_LSB_TAG): Remove; now done in lisp.h. * lisp.h (PUBLISH_TO_GDB): New macro. (GCTYPEBITS, USE_LSB_TAG, CHECK_LISP_OBJECT_TYPE, enum pvec_type) (DATA_SEG_BITS): Use it. (GCTYPEBITS, USE_LSB_TAG): Now also an enum, for GDB. (CHECK_LISP_OBJECT_TYPE, DATA_SEG_BITS): Now just an enum, for GDB. * mem-limits.h (EXCEEDS_LISP_PTR): Redo so that DATA_SEG_BITS need not be usable in #if. This simplifies things. --- src/alloc.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index d9c56b5c7c8..ac6cb861c4d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -6875,3 +6875,29 @@ The time is in seconds as a floating point value. */); defsubr (&Sgc_status); #endif } + +/* Make some symbols visible to GDB. These cannot be done as enums, like + GCTYPEBITS or USE_LSB_TAG, since values might not be in 'int' range. + Each symbol X has a corresponding X_VAL symbol, verified to have + the correct value. + + This is last, so that the #undef lines don't mess up later code. */ + +#define ARRAY_MARK_FLAG_VAL PTRDIFF_MIN +#define PSEUDOVECTOR_FLAG_VAL (PTRDIFF_MAX - PTRDIFF_MAX / 2) +#define VALMASK_VAL (USE_LSB_TAG ? -1 << GCTYPEBITS : VAL_MAX) + +verify (ARRAY_MARK_FLAG_VAL == ARRAY_MARK_FLAG); +verify (PSEUDOVECTOR_FLAG_VAL == PSEUDOVECTOR_FLAG); +verify (VALMASK_VAL == VALMASK); + +#undef ARRAY_MARK_FLAG +#undef PSEUDOVECTOR_FLAG +#undef VALMASK + +ptrdiff_t const EXTERNALLY_VISIBLE + ARRAY_MARK_FLAG = ARRAY_MARK_FLAG_VAL, + PSEUDOVECTOR_FLAG = PSEUDOVECTOR_FLAG_VAL; + +EMACS_INT const EXTERNALLY_VISIBLE + VALMASK = VALMASK_VAL; -- cgit v1.2.1