summaryrefslogtreecommitdiff
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c150
1 files changed, 111 insertions, 39 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 5ad80973949..a3410be7e26 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -125,6 +125,7 @@ union emacs_align_type
struct Lisp_Overlay Lisp_Overlay;
struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
struct Lisp_Subr Lisp_Subr;
+ struct Lisp_Sqlite Lisp_Sqlite;
struct Lisp_User_Ptr Lisp_User_Ptr;
struct Lisp_Vector Lisp_Vector;
struct terminal terminal;
@@ -591,7 +592,7 @@ pointer_align (void *ptr, int alignment)
static ATTRIBUTE_NO_SANITIZE_UNDEFINED void *
XPNTR (Lisp_Object a)
{
- return (SYMBOLP (a)
+ return (BARE_SYMBOL_P (a)
? (char *) lispsym + (XLI (a) - LISP_WORD_TAG (Lisp_Symbol))
: (char *) XLP (a) - (XLI (a) & ~VALMASK));
}
@@ -765,7 +766,7 @@ xmalloc (size_t size)
val = lmalloc (size, false);
MALLOC_UNBLOCK_INPUT;
- if (!val && size)
+ if (!val)
memory_full (size);
MALLOC_PROBE (size);
return val;
@@ -782,7 +783,7 @@ xzalloc (size_t size)
val = lmalloc (size, true);
MALLOC_UNBLOCK_INPUT;
- if (!val && size)
+ if (!val)
memory_full (size);
MALLOC_PROBE (size);
return val;
@@ -796,15 +797,15 @@ xrealloc (void *block, size_t size)
void *val;
MALLOC_BLOCK_INPUT;
- /* We must call malloc explicitly when BLOCK is 0, since some
- reallocs don't do this. */
+ /* Call lmalloc when BLOCK is null, for the benefit of long-obsolete
+ platforms lacking support for realloc (NULL, size). */
if (! block)
val = lmalloc (size, false);
else
val = lrealloc (block, size);
MALLOC_UNBLOCK_INPUT;
- if (!val && size)
+ if (!val)
memory_full (size);
MALLOC_PROBE (size);
return val;
@@ -988,8 +989,7 @@ record_xmalloc (size_t size)
/* Like malloc but used for allocating Lisp data. NBYTES is the
number of bytes to allocate, TYPE describes the intended use of the
- allocated memory block (for strings, for conses, ...).
- NBYTES must be positive. */
+ allocated memory block (for strings, for conses, ...). */
#if ! USE_LSB_TAG
void *lisp_malloc_loser EXTERNALLY_VISIBLE;
@@ -1330,16 +1330,20 @@ laligned (void *p, size_t size)
|| size % LISP_ALIGNMENT != 0);
}
-/* Like malloc and realloc except that if SIZE is Lisp-aligned, make
- sure the result is too, if necessary by reallocating (typically
- with larger and larger sizes) until the allocator returns a
- Lisp-aligned pointer. Code that needs to allocate C heap memory
+/* Like malloc and realloc except return null only on failure,
+ the result is Lisp-aligned if SIZE is, and lrealloc's pointer
+ argument must be nonnull. Code allocating C heap memory
for a Lisp object should use one of these functions to obtain a
pointer P; that way, if T is an enum Lisp_Type value and L ==
make_lisp_ptr (P, T), then XPNTR (L) == P and XTYPE (L) == T.
+ If CLEARIT, arrange for the allocated memory to be cleared.
+ This might use calloc, as calloc can be faster than malloc+memset.
+
On typical modern platforms these functions' loops do not iterate.
- On now-rare (and perhaps nonexistent) platforms, the loops in
+ On now-rare (and perhaps nonexistent) platforms, the code can loop,
+ reallocating (typically with larger and larger sizes) until the
+ allocator returns a Lisp-aligned pointer. This loop in
theory could repeat forever. If an infinite loop is possible on a
platform, a build would surely loop and the builder can then send
us a bug report. Adding a counter to try to detect any such loop
@@ -1353,8 +1357,13 @@ lmalloc (size_t size, bool clearit)
if (! MALLOC_IS_LISP_ALIGNED && size % LISP_ALIGNMENT == 0)
{
void *p = aligned_alloc (LISP_ALIGNMENT, size);
- if (clearit && p)
- memclear (p, size);
+ if (p)
+ {
+ if (clearit)
+ memclear (p, size);
+ }
+ else if (! (MALLOC_0_IS_NONNULL || size))
+ return aligned_alloc (LISP_ALIGNMENT, LISP_ALIGNMENT);
return p;
}
#endif
@@ -1362,7 +1371,7 @@ lmalloc (size_t size, bool clearit)
while (true)
{
void *p = clearit ? calloc (1, size) : malloc (size);
- if (laligned (p, size))
+ if (laligned (p, size) && (MALLOC_0_IS_NONNULL || size || p))
return p;
free (p);
size_t bigger = size + LISP_ALIGNMENT;
@@ -1377,7 +1386,7 @@ lrealloc (void *p, size_t size)
while (true)
{
p = realloc (p, size);
- if (laligned (p, size))
+ if (laligned (p, size) && (size || p))
return p;
size_t bigger = size + LISP_ALIGNMENT;
if (size < bigger)
@@ -1844,7 +1853,8 @@ allocate_string (void)
static void
allocate_string_data (struct Lisp_String *s,
- EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
+ EMACS_INT nchars, EMACS_INT nbytes, bool clearit,
+ bool immovable)
{
sdata *data;
struct sblock *b;
@@ -1858,7 +1868,7 @@ allocate_string_data (struct Lisp_String *s,
MALLOC_BLOCK_INPUT;
- if (nbytes > LARGE_STRING_BYTES)
+ if (nbytes > LARGE_STRING_BYTES || immovable)
{
size_t size = FLEXSIZEOF (struct sblock, data, needed);
@@ -1958,7 +1968,7 @@ resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
}
else
{
- allocate_string_data (XSTRING (string), nchars, new_nbytes, false);
+ allocate_string_data (XSTRING (string), nchars, new_nbytes, false, false);
unsigned char *new_data = SDATA (string);
new_charaddr = new_data + cidx_byte;
memcpy (new_charaddr + new_clen, data + cidx_byte + clen,
@@ -2474,7 +2484,7 @@ make_clear_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
s = allocate_string ();
s->u.s.intervals = NULL;
- allocate_string_data (s, nchars, nbytes, clearit);
+ allocate_string_data (s, nchars, nbytes, clearit, false);
XSETSTRING (string, s);
string_chars_consed += nbytes;
return string;
@@ -2504,6 +2514,29 @@ make_formatted_string (char *buf, const char *format, ...)
return make_string (buf, length);
}
+/* Pin a unibyte string in place so that it won't move during GC. */
+void
+pin_string (Lisp_Object string)
+{
+ eassert (STRINGP (string) && !STRING_MULTIBYTE (string));
+ struct Lisp_String *s = XSTRING (string);
+ ptrdiff_t size = STRING_BYTES (s);
+ unsigned char *data = s->u.s.data;
+
+ if (!(size > LARGE_STRING_BYTES
+ || PURE_P (data) || pdumper_object_p (data)
+ || s->u.s.size_byte == -3))
+ {
+ eassert (s->u.s.size_byte == -1);
+ sdata *old_sdata = SDATA_OF_STRING (s);
+ allocate_string_data (s, size, size, false, true);
+ memcpy (s->u.s.data, data, size);
+ old_sdata->string = NULL;
+ SDATA_NBYTES (old_sdata) = size;
+ }
+ s->u.s.size_byte = -3;
+}
+
/***********************************************************************
Float Allocation
@@ -3506,6 +3539,8 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
&& FIXNATP (args[COMPILED_STACK_DEPTH])))
error ("Invalid byte-code object");
+ pin_string (args[COMPILED_BYTECODE]); // Bytecode must be immovable.
+
/* We used to purecopy everything here, if purify-flag was set. This worked
OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
dangerous, since make-byte-code is used during execution to build
@@ -3590,13 +3625,13 @@ static struct Lisp_Symbol *symbol_free_list;
static void
set_symbol_name (Lisp_Object sym, Lisp_Object name)
{
- XSYMBOL (sym)->u.s.name = name;
+ XBARE_SYMBOL (sym)->u.s.name = name;
}
void
init_symbol (Lisp_Object val, Lisp_Object name)
{
- struct Lisp_Symbol *p = XSYMBOL (val);
+ struct Lisp_Symbol *p = XBARE_SYMBOL (val);
set_symbol_name (val, name);
set_symbol_plist (val, Qnil);
p->u.s.redirect = SYMBOL_PLAINVAL;
@@ -3659,6 +3694,21 @@ make_misc_ptr (void *a)
return make_lisp_ptr (p, Lisp_Vectorlike);
}
+/* Return a new symbol with position with the specified SYMBOL and POSITION. */
+Lisp_Object
+build_symbol_with_pos (Lisp_Object symbol, Lisp_Object position)
+{
+ Lisp_Object val;
+ struct Lisp_Symbol_With_Pos *p
+ = (struct Lisp_Symbol_With_Pos *) allocate_vector (2);
+ XSETVECTOR (val, p);
+ XSETPVECTYPESIZE (XVECTOR (val), PVEC_SYMBOL_WITH_POS, 2, 0);
+ p->sym = symbol;
+ p->pos = position;
+
+ return val;
+}
+
/* Return a new overlay with specified START, END and PLIST. */
Lisp_Object
@@ -3841,7 +3891,7 @@ run_finalizer_handler (Lisp_Object args)
static void
run_finalizer_function (Lisp_Object function)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#ifdef HAVE_PDUMPER
++number_finalizers_run;
#endif
@@ -3879,6 +3929,7 @@ count as reachable for the purpose of deciding whether to run
FUNCTION. FUNCTION will be run once per finalizer object. */)
(Lisp_Object function)
{
+ CHECK_TYPE (FUNCTIONP (function), Qfunctionp, function);
struct Lisp_Finalizer *finalizer
= ALLOCATE_PSEUDOVECTOR (struct Lisp_Finalizer, function, PVEC_FINALIZER);
finalizer->function = function;
@@ -4874,8 +4925,8 @@ mark_maybe_pointer (void *p, bool symbol_only)
miss objects if __alignof__ were used. */
#define GC_POINTER_ALIGNMENT alignof (void *)
-/* Mark Lisp objects referenced from the address range START+OFFSET..END
- or END+OFFSET..START. */
+/* Mark Lisp objects referenced from the address range START..END
+ or END..START. */
static void ATTRIBUTE_NO_SANITIZE_ADDRESS
mark_memory (void const *start, void const *end)
@@ -5202,7 +5253,7 @@ valid_lisp_object_p (Lisp_Object obj)
if (PURE_P (p))
return 1;
- if (SYMBOLP (obj) && c_symbol_p (p))
+ if (BARE_SYMBOL_P (obj) && c_symbol_p (p))
return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0;
if (p == &buffer_defaults || p == &buffer_local_symbols)
@@ -5628,14 +5679,18 @@ purecopy (Lisp_Object obj)
memcpy (vec, objp, nbytes);
for (i = 0; i < size; i++)
vec->contents[i] = purecopy (vec->contents[i]);
+ // Byte code strings must be pinned.
+ if (COMPILEDP (obj) && size >= 2 && STRINGP (vec->contents[1])
+ && !STRING_MULTIBYTE (vec->contents[1]))
+ pin_string (vec->contents[1]);
XSETVECTOR (obj, vec);
}
- else if (SYMBOLP (obj))
+ else if (BARE_SYMBOL_P (obj))
{
- if (!XSYMBOL (obj)->u.s.pinned && !c_symbol_p (XSYMBOL (obj)))
+ if (!XBARE_SYMBOL (obj)->u.s.pinned && !c_symbol_p (XBARE_SYMBOL (obj)))
{ /* We can't purify them, but they appear in many pure objects.
Mark them as `pinned' so we know to mark them at every GC cycle. */
- XSYMBOL (obj)->u.s.pinned = true;
+ XBARE_SYMBOL (obj)->u.s.pinned = true;
symbol_block_pinned = symbol_block;
}
/* Don't hash-cons it. */
@@ -5689,10 +5744,10 @@ allow_garbage_collection (intmax_t consing)
garbage_collection_inhibited--;
}
-ptrdiff_t
+specpdl_ref
inhibit_garbage_collection (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_intmax (allow_garbage_collection, consing_until_gc);
garbage_collection_inhibited++;
consing_until_gc = HI_THRESHOLD;
@@ -6052,7 +6107,7 @@ garbage_collect (void)
Lisp_Object tail, buffer;
char stack_top_variable;
bool message_p;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct timespec start;
eassert (weak_hash_tables == NULL);
@@ -6136,11 +6191,18 @@ garbage_collect (void)
mark_terminals ();
mark_kboards ();
mark_threads ();
+#ifdef HAVE_PGTK
+ mark_pgtkterm ();
+#endif
#ifdef USE_GTK
xg_mark_data ();
#endif
+#ifdef HAVE_HAIKU
+ mark_haiku_display ();
+#endif
+
#ifdef HAVE_WINDOW_SYSTEM
mark_fringe_data ();
#endif
@@ -6203,7 +6265,7 @@ garbage_collect (void)
if (!NILP (Vpost_gc_hook))
{
- ptrdiff_t gc_count = inhibit_garbage_collection ();
+ specpdl_ref gc_count = inhibit_garbage_collection ();
safe_run_hooks (Qpost_gc_hook);
unbind_to (gc_count, Qnil);
}
@@ -6256,7 +6318,10 @@ For further details, see Info node `(elisp)Garbage Collection'. */)
if (garbage_collection_inhibited)
return Qnil;
+ specpdl_ref count = SPECPDL_INDEX ();
+ specbind (Qsymbols_with_pos_enabled, Qnil);
garbage_collect ();
+ unbind_to (count, Qnil);
struct gcstat gcst = gcstat;
Lisp_Object total[] = {
@@ -6395,7 +6460,7 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
Lisp_Object val = ptr->contents[i];
if (FIXNUMP (val) ||
- (SYMBOLP (val) && symbol_marked_p (XSYMBOL (val))))
+ (BARE_SYMBOL_P (val) && symbol_marked_p (XBARE_SYMBOL (val))))
continue;
if (SUB_CHAR_TABLE_P (val))
{
@@ -6799,7 +6864,7 @@ mark_object (Lisp_Object arg)
case Lisp_Symbol:
{
- struct Lisp_Symbol *ptr = XSYMBOL (obj);
+ struct Lisp_Symbol *ptr = XBARE_SYMBOL (obj);
nextsym:
if (symbol_marked_p (ptr))
break;
@@ -6920,7 +6985,7 @@ survives_gc_p (Lisp_Object obj)
break;
case Lisp_Symbol:
- survives_p = symbol_marked_p (XSYMBOL (obj));
+ survives_p = symbol_marked_p (XBARE_SYMBOL (obj));
break;
case Lisp_String:
@@ -7337,7 +7402,7 @@ arenas. */)
static bool
symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj)
{
- struct Lisp_Symbol *sym = XSYMBOL (symbol);
+ struct Lisp_Symbol *sym = XBARE_SYMBOL (symbol);
Lisp_Object val = find_symbol_value (symbol);
return (EQ (val, obj)
|| EQ (sym->u.s.function, obj)
@@ -7356,7 +7421,7 @@ Lisp_Object
which_symbols (Lisp_Object obj, EMACS_INT find_max)
{
struct symbol_block *sblk;
- ptrdiff_t gc_count = inhibit_garbage_collection ();
+ specpdl_ref gc_count = inhibit_garbage_collection ();
Lisp_Object found = Qnil;
if (! deadp (obj))
@@ -7708,6 +7773,12 @@ enum defined_HAVE_X_WINDOWS { defined_HAVE_X_WINDOWS = true };
enum defined_HAVE_X_WINDOWS { defined_HAVE_X_WINDOWS = false };
#endif
+#ifdef HAVE_PGTK
+enum defined_HAVE_PGTK { defined_HAVE_PGTK = true };
+#else
+enum defined_HAVE_PGTK { defined_HAVE_PGTK = 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
@@ -7727,5 +7798,6 @@ union
enum More_Lisp_Bits More_Lisp_Bits;
enum pvec_type pvec_type;
enum defined_HAVE_X_WINDOWS defined_HAVE_X_WINDOWS;
+ enum defined_HAVE_PGTK defined_HAVE_PGTK;
} const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0};
#endif /* __GNUC__ */