diff options
Diffstat (limited to 'src/alloc.c')
-rw-r--r-- | src/alloc.c | 217 |
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; |