diff options
Diffstat (limited to 'src/alloc.c')
-rw-r--r-- | src/alloc.c | 145 |
1 files changed, 66 insertions, 79 deletions
diff --git a/src/alloc.c b/src/alloc.c index ce2a9fe1aa0..8307c74c106 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -453,6 +453,7 @@ no_sanitize_memcpy (void *dest, void const *src, size_t size) #endif /* MAX_SAVE_STACK > 0 */ +static struct Lisp_Vector *allocate_clear_vector (ptrdiff_t, bool); static void unchain_finalizer (struct Lisp_Finalizer *); static void mark_terminals (void); static void gc_sweep (void); @@ -708,7 +709,7 @@ buffer_memory_full (ptrdiff_t nbytes) where Emacs would crash if malloc returned a non-GCALIGNED pointer. */ enum { LISP_ALIGNMENT = alignof (union { union emacs_align_type x; GCALIGNED_UNION_MEMBER }) }; -verify (LISP_ALIGNMENT % GCALIGNMENT == 0); +static_assert (LISP_ALIGNMENT % GCALIGNMENT == 0); /* True if malloc (N) is known to return storage suitably aligned for Lisp objects whenever N is a multiple of LISP_ALIGNMENT. In @@ -838,7 +839,7 @@ xfree (void *block) /* Other parts of Emacs pass large int values to allocator functions expecting ptrdiff_t. This is portable in practice, but check it to be safe. */ -verify (INT_MAX <= PTRDIFF_MAX); +static_assert (INT_MAX <= PTRDIFF_MAX); /* Allocate an array of NITEMS items, each of size ITEM_SIZE. @@ -998,6 +999,7 @@ record_xmalloc (size_t size) allocated memory block (for strings, for conses, ...). */ #if ! USE_LSB_TAG +extern void *lisp_malloc_loser; void *lisp_malloc_loser EXTERNALLY_VISIBLE; #endif @@ -1074,7 +1076,7 @@ lisp_free (void *block) #else /* !HAVE_UNEXEC */ # define BLOCK_ALIGN (1 << 15) #endif -verify (POWER_OF_2 (BLOCK_ALIGN)); +static_assert (POWER_OF_2 (BLOCK_ALIGN)); /* Use aligned_alloc if it or a simple substitute is available. Aligned allocation is incompatible with unexmacosx.c, so don't use @@ -1094,11 +1096,11 @@ aligned_alloc (size_t alignment, size_t size) { /* POSIX says the alignment must be a power-of-2 multiple of sizeof (void *). Verify this for all arguments this function is given. */ - verify (BLOCK_ALIGN % sizeof (void *) == 0 - && POWER_OF_2 (BLOCK_ALIGN / sizeof (void *))); - verify (MALLOC_IS_LISP_ALIGNED - || (LISP_ALIGNMENT % sizeof (void *) == 0 - && POWER_OF_2 (LISP_ALIGNMENT / sizeof (void *)))); + static_assert (BLOCK_ALIGN % sizeof (void *) == 0 + && POWER_OF_2 (BLOCK_ALIGN / sizeof (void *))); + static_assert (MALLOC_IS_LISP_ALIGNED + || (LISP_ALIGNMENT % sizeof (void *) == 0 + && POWER_OF_2 (LISP_ALIGNMENT / sizeof (void *)))); eassert (alignment == BLOCK_ALIGN || (!MALLOC_IS_LISP_ALIGNED && alignment == LISP_ALIGNMENT)); @@ -1219,7 +1221,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) #endif #ifdef USE_ALIGNED_ALLOC - verify (ABLOCKS_BYTES % BLOCK_ALIGN == 0); + static_assert (ABLOCKS_BYTES % BLOCK_ALIGN == 0); abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES); #else base = malloc (ABLOCKS_BYTES); @@ -1403,8 +1405,8 @@ lmalloc (size_t size, bool clearit) if (laligned (p, size) && (MALLOC_0_IS_NONNULL || size || p)) return p; free (p); - size_t bigger = size + LISP_ALIGNMENT; - if (size < bigger) + size_t bigger; + if (!ckd_add (&bigger, size, LISP_ALIGNMENT)) size = bigger; } } @@ -1417,8 +1419,8 @@ lrealloc (void *p, size_t size) p = realloc (p, size); if (laligned (p, size) && (size || p)) return p; - size_t bigger = size + LISP_ALIGNMENT; - if (size < bigger) + size_t bigger; + if (!ckd_add (&bigger, size, LISP_ALIGNMENT)) size = bigger; } } @@ -2405,30 +2407,39 @@ bool_vector_fill (Lisp_Object a, Lisp_Object init) return a; } -/* Return a newly allocated, uninitialized bool vector of size NBITS. */ +/* Return a newly allocated, bool vector of size NBITS. If CLEARIT, + clear its slots; otherwise the vector's slots are uninitialized. */ Lisp_Object -make_uninit_bool_vector (EMACS_INT nbits) +make_clear_bool_vector (EMACS_INT nbits, bool clearit) { + eassert (0 <= nbits && nbits <= BOOL_VECTOR_LENGTH_MAX); Lisp_Object val; - EMACS_INT words = bool_vector_words (nbits); - EMACS_INT word_bytes = words * sizeof (bits_word); - EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes + ptrdiff_t words = bool_vector_words (nbits); + ptrdiff_t word_bytes = words * sizeof (bits_word); + ptrdiff_t needed_elements = ((bool_header_size - header_size + word_bytes + word_size - 1) / word_size); - if (PTRDIFF_MAX < needed_elements) - memory_full (SIZE_MAX); struct Lisp_Bool_Vector *p - = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); + = (struct Lisp_Bool_Vector *) allocate_clear_vector (needed_elements, + clearit); + /* Clear padding at end; but only if necessary, to avoid polluting the + data cache. */ + if (!clearit && nbits % BITS_PER_BITS_WORD != 0) + p->data[words - 1] = 0; + XSETVECTOR (val, p); XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); p->size = nbits; + return val; +} - /* Clear padding at the end. */ - if (words) - p->data[words - 1] = 0; +/* Return a newly allocated, uninitialized bool vector of size NBITS. */ - return val; +Lisp_Object +make_uninit_bool_vector (EMACS_INT nbits) +{ + return make_clear_bool_vector (nbits, false); } DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, @@ -2436,11 +2447,12 @@ DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, LENGTH must be a number. INIT matters only in whether it is t or nil. */) (Lisp_Object length, Lisp_Object init) { - Lisp_Object val; - CHECK_FIXNAT (length); - val = make_uninit_bool_vector (XFIXNAT (length)); - return bool_vector_fill (val, init); + EMACS_INT len = XFIXNAT (length); + if (BOOL_VECTOR_LENGTH_MAX < len) + memory_full (SIZE_MAX); + Lisp_Object val = make_clear_bool_vector (len, NILP (init)); + return NILP (init) ? val : bool_vector_fill (val, init); } DEFUN ("bool-vector", Fbool_vector, Sbool_vector, 0, MANY, 0, @@ -2449,13 +2461,12 @@ Allows any number of arguments, including zero. usage: (bool-vector &rest OBJECTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - ptrdiff_t i; - Lisp_Object vector; - - vector = make_uninit_bool_vector (nargs); - for (i = 0; i < nargs; i++) - bool_vector_set (vector, i, !NILP (args[i])); - + if (BOOL_VECTOR_LENGTH_MAX < nargs) + memory_full (SIZE_MAX); + Lisp_Object vector = make_clear_bool_vector (nargs, true); + for (ptrdiff_t i = 0; i < nargs; i++) + if (!NILP (args[i])) + bool_vector_set (vector, i, true); return vector; } @@ -3037,7 +3048,7 @@ enum { VECTOR_BLOCK_SIZE = 4096 }; enum { roundup_size = COMMON_MULTIPLE (LISP_ALIGNMENT, word_size) }; /* Verify assumption described above. */ -verify (VECTOR_BLOCK_SIZE % roundup_size == 0); +static_assert (VECTOR_BLOCK_SIZE % roundup_size == 0); /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */ #define vroundup_ct(x) ROUNDUP (x, roundup_size) @@ -3051,7 +3062,7 @@ enum {VECTOR_BLOCK_BYTES = VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *))}; /* The current code expects to be able to represent an unused block by a single PVEC_FREE object, whose size is limited by the header word. (Of course we could use multiple such objects.) */ -verify (VECTOR_BLOCK_BYTES <= (word_size << PSEUDOVECTOR_REST_BITS)); +static_assert (VECTOR_BLOCK_BYTES <= (word_size << PSEUDOVECTOR_REST_BITS)); /* Size of the minimal vector allocated from block. */ @@ -3308,7 +3319,7 @@ vectorlike_nbytes (const union vectorlike_header *hdr) ptrdiff_t word_bytes = (bool_vector_words (bv->size) * sizeof (bits_word)); ptrdiff_t boolvec_bytes = bool_header_size + word_bytes; - verify (header_size <= bool_header_size); + static_assert (header_size <= bool_header_size); nwords = (boolvec_bytes - header_size + word_size - 1) / word_size; } else @@ -3688,7 +3699,7 @@ allocate_pseudovector (int memlen, int lisplen, /* Catch bogus values. */ enum { size_max = (1 << PSEUDOVECTOR_SIZE_BITS) - 1 }; enum { rest_max = (1 << PSEUDOVECTOR_REST_BITS) - 1 }; - verify (size_max + rest_max <= VECTOR_ELTS_MAX); + static_assert (size_max + rest_max <= VECTOR_ELTS_MAX); eassert (0 <= tag && tag <= PVEC_TAG_MAX); eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen); eassert (lisplen <= size_max); @@ -6842,9 +6853,11 @@ mark_glyph_matrix (struct glyph_matrix *matrix) struct glyph *end_glyph = glyph + row->used[area]; for (; glyph < end_glyph; ++glyph) - if (STRINGP (glyph->object) - && !string_marked_p (XSTRING (glyph->object))) - mark_object (glyph->object); + { + if (STRINGP (glyph->object) + && !string_marked_p (XSTRING (glyph->object))) + mark_object (glyph->object); + } } } } @@ -6997,33 +7010,6 @@ mark_face_cache (struct face_cache *c) } } -/* Remove killed buffers or items whose car is a killed buffer from - LIST, and mark other items. Return changed LIST, which is marked. */ - -static Lisp_Object -mark_discard_killed_buffers (Lisp_Object list) -{ - Lisp_Object tail, *prev = &list; - - for (tail = list; CONSP (tail) && !cons_marked_p (XCONS (tail)); - tail = XCDR (tail)) - { - Lisp_Object tem = XCAR (tail); - if (CONSP (tem)) - tem = XCAR (tem); - if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem))) - *prev = XCDR (tail); - else - { - set_cons_marked (XCONS (tail)); - mark_object (XCAR (tail)); - prev = xcdr_addr (tail); - } - } - mark_object (tail); - return list; -} - static void mark_frame (struct Lisp_Vector *ptr) { @@ -7078,15 +7064,6 @@ mark_window (struct Lisp_Vector *ptr) mark_glyph_matrix (w->current_matrix); mark_glyph_matrix (w->desired_matrix); } - - /* Filter out killed buffers from both buffer lists - in attempt to help GC to reclaim killed buffers faster. - We can do it elsewhere for live windows, but this is the - best place to do it for dead windows. */ - wset_prev_buffers - (w, mark_discard_killed_buffers (w->prev_buffers)); - wset_next_buffers - (w, mark_discard_killed_buffers (w->next_buffers)); } /* Entry of the mark stack. */ @@ -8321,6 +8298,9 @@ N should be nonnegative. */); DEFSYM (QCemergency, ":emergency"); } +/* The below is for being able to do platform-specific stuff in .gdbinit + without risking error messages from GDB about missing types and + variables on other platforms. */ #ifdef HAVE_X_WINDOWS enum defined_HAVE_X_WINDOWS { defined_HAVE_X_WINDOWS = true }; #else @@ -8333,6 +8313,12 @@ enum defined_HAVE_PGTK { defined_HAVE_PGTK = true }; enum defined_HAVE_PGTK { defined_HAVE_PGTK = false }; #endif +#ifdef WINDOWSNT +enum defined_WINDOWSNT { defined_WINDOWSNT = true }; +#else +enum defined_WINDOWSNT { defined_WINDOWSNT = false }; +#endif + /* When compiled with GCC, GDB might say "No enum type named pvec_type" if we don't have at least one symbol with that type, and then xbacktrace could fail. Similarly for the other enums and @@ -8353,6 +8339,7 @@ extern union enums_for_gdb enum pvec_type pvec_type; enum defined_HAVE_X_WINDOWS defined_HAVE_X_WINDOWS; enum defined_HAVE_PGTK defined_HAVE_PGTK; + enum defined_WINDOWSNT defined_WINDOWSNT; } const gdb_make_enums_visible; union enums_for_gdb const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0}; #endif /* __GNUC__ */ |