summaryrefslogtreecommitdiff
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c217
1 files changed, 147 insertions, 70 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 53ba85d88b7..2ffd2415447 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -359,8 +359,16 @@ static struct gcstat
object_ct total_floats, total_free_floats;
object_ct total_intervals, total_free_intervals;
object_ct total_buffers;
+
+ /* Size of the ancillary arrays of live hash-table and obarray objects.
+ The objects themselves are not included (counted as vectors above). */
+ byte_ct total_hash_table_bytes;
} gcstat;
+/* Total size of ancillary arrays of all allocated hash-table and obarray
+ objects, both dead and alive. This number is always kept up-to-date. */
+static ptrdiff_t hash_table_allocated_bytes = 0;
+
/* 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
two string blocks. */
@@ -1458,9 +1466,9 @@ static INTERVAL interval_free_list;
__asan_unpoison_memory_region ((b)->intervals, \
sizeof ((b)->intervals))
# define ASAN_POISON_INTERVAL(i) \
- __asan_poison_memory_region ((i), sizeof (*(i)))
+ __asan_poison_memory_region (i, sizeof *(i))
# define ASAN_UNPOISON_INTERVAL(i) \
- __asan_unpoison_memory_region ((i), sizeof (*(i)))
+ __asan_unpoison_memory_region (i, sizeof *(i))
#else
# define ASAN_POISON_INTERVAL_BLOCK(b) ((void) 0)
# define ASAN_UNPOISON_INTERVAL_BLOCK(b) ((void) 0)
@@ -1744,25 +1752,25 @@ init_strings (void)
*/
# define ASAN_PREPARE_DEAD_SDATA(s, size) \
do { \
- __asan_poison_memory_region ((s), sdata_size ((size))); \
- __asan_unpoison_memory_region (&(((s))->string), \
+ __asan_poison_memory_region (s, sdata_size (size)); \
+ __asan_unpoison_memory_region (&(s)->string, \
sizeof (struct Lisp_String *)); \
- __asan_unpoison_memory_region (&SDATA_NBYTES ((s)), \
- sizeof (SDATA_NBYTES ((s)))); \
+ __asan_unpoison_memory_region (&SDATA_NBYTES (s), \
+ sizeof SDATA_NBYTES (s)); \
} while (false)
/* Prepare s for storing string data for NBYTES bytes. */
# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) \
- __asan_unpoison_memory_region ((s), sdata_size ((nbytes)))
+ __asan_unpoison_memory_region (s, sdata_size (nbytes))
# define ASAN_POISON_SBLOCK_DATA(b, size) \
- __asan_poison_memory_region ((b)->data, (size))
+ __asan_poison_memory_region ((b)->data, size)
# define ASAN_POISON_STRING_BLOCK(b) \
__asan_poison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
# define ASAN_UNPOISON_STRING_BLOCK(b) \
__asan_unpoison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
# define ASAN_POISON_STRING(s) \
- __asan_poison_memory_region ((s), sizeof (*(s)))
+ __asan_poison_memory_region (s, sizeof *(s))
# define ASAN_UNPOISON_STRING(s) \
- __asan_unpoison_memory_region ((s), sizeof (*(s)))
+ __asan_unpoison_memory_region (s, sizeof *(s))
#else
# define ASAN_PREPARE_DEAD_SDATA(s, size) ((void) 0)
# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) ((void) 0)
@@ -2683,13 +2691,13 @@ struct float_block
};
#define XFLOAT_MARKED_P(fptr) \
- GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
+ GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX (fptr))
#define XFLOAT_MARK(fptr) \
- SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
+ SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX (fptr))
#define XFLOAT_UNMARK(fptr) \
- UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
+ UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX (fptr))
#if GC_ASAN_POISON_OBJECTS
# define ASAN_POISON_FLOAT_BLOCK(fblk) \
@@ -2699,9 +2707,9 @@ struct float_block
__asan_unpoison_memory_region ((fblk)->floats, \
sizeof ((fblk)->floats))
# define ASAN_POISON_FLOAT(p) \
- __asan_poison_memory_region ((p), sizeof (struct Lisp_Float))
+ __asan_poison_memory_region (p, sizeof (struct Lisp_Float))
# define ASAN_UNPOISON_FLOAT(p) \
- __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Float))
+ __asan_unpoison_memory_region (p, sizeof (struct Lisp_Float))
#else
# define ASAN_POISON_FLOAT_BLOCK(fblk) ((void) 0)
# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) ((void) 0)
@@ -2795,13 +2803,13 @@ struct cons_block
};
#define XCONS_MARKED_P(fptr) \
- GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
+ GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX (fptr))
#define XMARK_CONS(fptr) \
- SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
+ SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX (fptr))
#define XUNMARK_CONS(fptr) \
- UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
+ UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX (fptr))
/* Minimum number of bytes of consing since GC before next GC,
when memory is full. */
@@ -2824,9 +2832,9 @@ static struct Lisp_Cons *cons_free_list;
# define ASAN_POISON_CONS_BLOCK(b) \
__asan_poison_memory_region ((b)->conses, sizeof ((b)->conses))
# define ASAN_POISON_CONS(p) \
- __asan_poison_memory_region ((p), sizeof (struct Lisp_Cons))
+ __asan_poison_memory_region (p, sizeof (struct Lisp_Cons))
# define ASAN_UNPOISON_CONS(p) \
- __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Cons))
+ __asan_unpoison_memory_region (p, sizeof (struct Lisp_Cons))
#else
# define ASAN_POISON_CONS_BLOCK(b) ((void) 0)
# define ASAN_POISON_CONS(p) ((void) 0)
@@ -3144,11 +3152,11 @@ Lisp_Object zero_vector;
#if GC_ASAN_POISON_OBJECTS
# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) \
- __asan_poison_memory_region ((v)->contents, (bytes))
+ __asan_poison_memory_region ((v)->contents, bytes)
# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) \
- __asan_unpoison_memory_region ((v)->contents, (bytes))
+ __asan_unpoison_memory_region ((v)->contents, bytes)
# define ASAN_UNPOISON_VECTOR_BLOCK(b) \
- __asan_unpoison_memory_region ((b)->data, sizeof ((b)->data))
+ __asan_unpoison_memory_region ((b)->data, sizeof (b)->data)
#else
# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
@@ -3430,6 +3438,32 @@ cleanup_vector (struct Lisp_Vector *vector)
}
#endif
break;
+ case PVEC_HASH_TABLE:
+ {
+ struct Lisp_Hash_Table *h = PSEUDOVEC_STRUCT (vector, Lisp_Hash_Table);
+ if (h->table_size > 0)
+ {
+ eassert (h->index_bits > 0);
+ xfree (h->index);
+ xfree (h->key_and_value);
+ xfree (h->next);
+ xfree (h->hash);
+ ptrdiff_t bytes = (h->table_size * (2 * sizeof *h->key_and_value
+ + sizeof *h->hash
+ + sizeof *h->next)
+ + hash_table_index_size (h) * sizeof *h->index);
+ hash_table_allocated_bytes -= bytes;
+ }
+ }
+ break;
+ case PVEC_OBARRAY:
+ {
+ struct Lisp_Obarray *o = PSEUDOVEC_STRUCT (vector, Lisp_Obarray);
+ xfree (o->buckets);
+ ptrdiff_t bytes = obarray_size (o) * sizeof *o->buckets;
+ hash_table_allocated_bytes -= bytes;
+ }
+ break;
/* Keep the switch exhaustive. */
case PVEC_NORMAL_VECTOR:
case PVEC_FREE:
@@ -3440,7 +3474,6 @@ cleanup_vector (struct Lisp_Vector *vector)
case PVEC_WINDOW:
case PVEC_BOOL_VECTOR:
case PVEC_BUFFER:
- case PVEC_HASH_TABLE:
case PVEC_TERMINAL:
case PVEC_WINDOW_CONFIGURATION:
case PVEC_OTHER:
@@ -3554,6 +3587,8 @@ sweep_vectors (void)
lisp_free (lv);
}
}
+
+ gcstat.total_hash_table_bytes = hash_table_allocated_bytes;
}
/* Maximum number of elements in a vector. This is a macro so that it
@@ -3860,9 +3895,9 @@ struct symbol_block
# define ASAN_UNPOISON_SYMBOL_BLOCK(s) \
__asan_unpoison_memory_region ((s)->symbols, sizeof ((s)->symbols))
# define ASAN_POISON_SYMBOL(sym) \
- __asan_poison_memory_region ((sym), sizeof (*(sym)))
+ __asan_poison_memory_region (sym, sizeof *(sym))
# define ASAN_UNPOISON_SYMBOL(sym) \
- __asan_unpoison_memory_region ((sym), sizeof (*(sym)))
+ __asan_unpoison_memory_region (sym, sizeof *(sym))
#else
# define ASAN_POISON_SYMBOL_BLOCK(s) ((void) 0)
@@ -5606,6 +5641,29 @@ valid_lisp_object_p (Lisp_Object obj)
return 0;
}
+/* Like xmalloc, but makes allocation count toward the total consing
+ and hash table or obarray usage.
+ Return NULL for a zero-sized allocation. */
+void *
+hash_table_alloc_bytes (ptrdiff_t nbytes)
+{
+ if (nbytes == 0)
+ return NULL;
+ tally_consing (nbytes);
+ hash_table_allocated_bytes += nbytes;
+ return xmalloc (nbytes);
+}
+
+/* Like xfree, but makes allocation count toward the total consing. */
+void
+hash_table_free_bytes (void *p, ptrdiff_t nbytes)
+{
+ tally_consing (-nbytes);
+ hash_table_allocated_bytes -= nbytes;
+ xfree (p);
+}
+
+
/***********************************************************************
Pure Storage Management
***********************************************************************/
@@ -5887,30 +5945,35 @@ make_pure_vector (ptrdiff_t len)
static struct Lisp_Hash_Table *
purecopy_hash_table (struct Lisp_Hash_Table *table)
{
- eassert (NILP (table->weak));
+ eassert (table->weakness == Weak_None);
eassert (table->purecopy);
struct Lisp_Hash_Table *pure = pure_alloc (sizeof *pure, Lisp_Vectorlike);
- struct hash_table_test pure_test = table->test;
-
- /* Purecopy the hash table test. */
- pure_test.name = purecopy (table->test.name);
- pure_test.user_hash_function = purecopy (table->test.user_hash_function);
- pure_test.user_cmp_function = purecopy (table->test.user_cmp_function);
-
- pure->header = table->header;
- pure->weak = purecopy (Qnil);
- pure->hash = purecopy (table->hash);
- pure->next = purecopy (table->next);
- pure->index = purecopy (table->index);
- pure->count = table->count;
- pure->next_free = table->next_free;
- pure->purecopy = table->purecopy;
- eassert (!pure->mutable);
- pure->rehash_threshold = table->rehash_threshold;
- pure->rehash_size = table->rehash_size;
- pure->key_and_value = purecopy (table->key_and_value);
- pure->test = pure_test;
+ *pure = *table;
+ pure->mutable = false;
+
+ if (table->table_size > 0)
+ {
+ ptrdiff_t hash_bytes = table->table_size * sizeof *table->hash;
+ pure->hash = pure_alloc (hash_bytes, -(int)sizeof *table->hash);
+ memcpy (pure->hash, table->hash, hash_bytes);
+
+ ptrdiff_t next_bytes = table->table_size * sizeof *table->next;
+ pure->next = pure_alloc (next_bytes, -(int)sizeof *table->next);
+ memcpy (pure->next, table->next, next_bytes);
+
+ ptrdiff_t nvalues = table->table_size * 2;
+ ptrdiff_t kv_bytes = nvalues * sizeof *table->key_and_value;
+ pure->key_and_value = pure_alloc (kv_bytes,
+ -(int)sizeof *table->key_and_value);
+ for (ptrdiff_t i = 0; i < nvalues; i++)
+ pure->key_and_value[i] = purecopy (table->key_and_value[i]);
+
+ ptrdiff_t index_bytes = hash_table_index_size (table)
+ * sizeof *table->index;
+ pure->index = pure_alloc (index_bytes, -(int)sizeof *table->index);
+ memcpy (pure->index, table->index, index_bytes);
+ }
return pure;
}
@@ -5970,7 +6033,7 @@ purecopy (Lisp_Object obj)
/* Do not purify hash tables which haven't been defined with
:purecopy as non-nil or are weak - they aren't guaranteed to
not change. */
- if (!NILP (table->weak) || !table->purecopy)
+ if (table->weakness != Weak_None || !table->purecopy)
{
/* Instead, add the hash table to the list of pinned objects,
so that it will be marked during GC. */
@@ -5981,8 +6044,7 @@ purecopy (Lisp_Object obj)
return obj; /* Don't hash cons it. */
}
- struct Lisp_Hash_Table *h = purecopy_hash_table (table);
- XSET_HASH_TABLE (obj, h);
+ obj = make_lisp_hash_table (purecopy_hash_table (table));
}
else if (COMPILEDP (obj) || VECTORP (obj) || RECORDP (obj))
{
@@ -6094,6 +6156,7 @@ total_bytes_of_live_objects (void)
tot += object_bytes (gcstat.total_floats, sizeof (struct Lisp_Float));
tot += object_bytes (gcstat.total_intervals, sizeof (struct interval));
tot += object_bytes (gcstat.total_strings, sizeof (struct Lisp_String));
+ tot += gcstat.total_hash_table_bytes;
return tot;
}
@@ -6238,11 +6301,10 @@ android_make_lisp_symbol (struct Lisp_Symbol *sym)
intptr_t symoffset;
symoffset = (intptr_t) sym;
- INT_SUBTRACT_WRAPV (symoffset, (intptr_t) &lispsym,
- &symoffset);
+ ckd_sub (&symoffset, symoffset, (intptr_t) &lispsym);
{
- Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
+ Lisp_Object a = TAG_PTR_INITIALLY (Lisp_Symbol, symoffset);
return a;
}
}
@@ -6541,6 +6603,9 @@ garbage_collect (void)
mark_terminals ();
mark_kboards ();
mark_threads ();
+ mark_charset ();
+ mark_composite ();
+ mark_profiler ();
#ifdef HAVE_PGTK
mark_pgtkterm ();
#endif
@@ -6572,6 +6637,7 @@ garbage_collect (void)
#ifdef HAVE_NS
mark_nsterm ();
#endif
+ mark_fns ();
/* Everything is now marked, except for the data in font caches,
undo lists, and finalizers. The first two are compacted by
@@ -7236,26 +7302,32 @@ process_mark_stack (ptrdiff_t base_sp)
case PVEC_HASH_TABLE:
{
struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *)ptr;
- ptrdiff_t size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
set_vector_marked (ptr);
- mark_stack_push_values (ptr->contents, size);
- mark_stack_push_value (h->test.name);
- mark_stack_push_value (h->test.user_hash_function);
- mark_stack_push_value (h->test.user_cmp_function);
- if (NILP (h->weak))
- mark_stack_push_value (h->key_and_value);
+ if (h->weakness == Weak_None)
+ /* The values pushed here may include
+ HASH_UNUSED_ENTRY_KEY, which this function must
+ cope with. */
+ mark_stack_push_values (h->key_and_value,
+ 2 * h->table_size);
else
{
- /* For weak tables, mark only the vector and not its
+ /* For weak tables, don't mark the
contents --- that's what makes it weak. */
eassert (h->next_weak == NULL);
h->next_weak = weak_hash_tables;
weak_hash_tables = h;
- set_vector_marked (XVECTOR (h->key_and_value));
}
break;
}
+ case PVEC_OBARRAY:
+ {
+ struct Lisp_Obarray *o = (struct Lisp_Obarray *)ptr;
+ set_vector_marked (ptr);
+ mark_stack_push_values (o->buckets, obarray_size (o));
+ break;
+ }
+
case PVEC_CHAR_TABLE:
case PVEC_SUB_CHAR_TABLE:
mark_char_table (ptr, (enum pvec_type) pvectype);
@@ -7387,14 +7459,19 @@ process_mark_stack (ptrdiff_t base_sp)
}
case Lisp_Float:
- CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
- /* Do not mark floats stored in a dump image: these floats are
- "cold" and do not have mark bits. */
- if (pdumper_object_p (XFLOAT (obj)))
- eassert (pdumper_cold_object_p (XFLOAT (obj)));
- else if (!XFLOAT_MARKED_P (XFLOAT (obj)))
- XFLOAT_MARK (XFLOAT (obj));
- break;
+ {
+ struct Lisp_Float *f = XFLOAT (obj);
+ if (!f)
+ break; /* for HASH_UNUSED_ENTRY_KEY */
+ CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
+ /* Do not mark floats stored in a dump image: these floats are
+ "cold" and do not have mark bits. */
+ if (pdumper_object_p (f))
+ eassert (pdumper_cold_object_p (f));
+ else if (!XFLOAT_MARKED_P (f))
+ XFLOAT_MARK (f);
+ break;
+ }
case_Lisp_Int:
break;