diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 86 |
1 files changed, 75 insertions, 11 deletions
diff --git a/src/alloc.c b/src/alloc.c index 636b4972c84..7432163db25 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -359,8 +359,16 @@ static struct gcstat | |||
| 359 | object_ct total_floats, total_free_floats; | 359 | object_ct total_floats, total_free_floats; |
| 360 | object_ct total_intervals, total_free_intervals; | 360 | object_ct total_intervals, total_free_intervals; |
| 361 | object_ct total_buffers; | 361 | object_ct total_buffers; |
| 362 | |||
| 363 | /* Size of the ancillary arrays of live hash-table objects. | ||
| 364 | The objects themselves are not included (counted as vectors above). */ | ||
| 365 | byte_ct total_hash_table_bytes; | ||
| 362 | } gcstat; | 366 | } gcstat; |
| 363 | 367 | ||
| 368 | /* Total size of ancillary arrays of all allocated hash-table objects, | ||
| 369 | both dead and alive. This number is always kept up-to-date. */ | ||
| 370 | static ptrdiff_t hash_table_allocated_bytes = 0; | ||
| 371 | |||
| 364 | /* Points to memory space allocated as "spare", to be freed if we run | 372 | /* Points to memory space allocated as "spare", to be freed if we run |
| 365 | out of memory. We keep one large block, four cons-blocks, and | 373 | out of memory. We keep one large block, four cons-blocks, and |
| 366 | two string blocks. */ | 374 | two string blocks. */ |
| @@ -3430,6 +3438,23 @@ cleanup_vector (struct Lisp_Vector *vector) | |||
| 3430 | } | 3438 | } |
| 3431 | #endif | 3439 | #endif |
| 3432 | break; | 3440 | break; |
| 3441 | case PVEC_HASH_TABLE: | ||
| 3442 | { | ||
| 3443 | struct Lisp_Hash_Table *h = PSEUDOVEC_STRUCT (vector, Lisp_Hash_Table); | ||
| 3444 | if (h->table_size > 0) | ||
| 3445 | { | ||
| 3446 | eassert (h->index_size > 1); | ||
| 3447 | xfree (h->index); | ||
| 3448 | xfree (h->key_and_value); | ||
| 3449 | xfree (h->next); | ||
| 3450 | xfree (h->hash); | ||
| 3451 | ptrdiff_t bytes = (h->table_size * (2 * sizeof *h->key_and_value | ||
| 3452 | + sizeof *h->hash | ||
| 3453 | + sizeof *h->next) | ||
| 3454 | + h->index_size * sizeof *h->index); | ||
| 3455 | hash_table_allocated_bytes -= bytes; | ||
| 3456 | } | ||
| 3457 | } | ||
| 3433 | /* Keep the switch exhaustive. */ | 3458 | /* Keep the switch exhaustive. */ |
| 3434 | case PVEC_NORMAL_VECTOR: | 3459 | case PVEC_NORMAL_VECTOR: |
| 3435 | case PVEC_FREE: | 3460 | case PVEC_FREE: |
| @@ -3440,7 +3465,6 @@ cleanup_vector (struct Lisp_Vector *vector) | |||
| 3440 | case PVEC_WINDOW: | 3465 | case PVEC_WINDOW: |
| 3441 | case PVEC_BOOL_VECTOR: | 3466 | case PVEC_BOOL_VECTOR: |
| 3442 | case PVEC_BUFFER: | 3467 | case PVEC_BUFFER: |
| 3443 | case PVEC_HASH_TABLE: | ||
| 3444 | case PVEC_TERMINAL: | 3468 | case PVEC_TERMINAL: |
| 3445 | case PVEC_WINDOW_CONFIGURATION: | 3469 | case PVEC_WINDOW_CONFIGURATION: |
| 3446 | case PVEC_OTHER: | 3470 | case PVEC_OTHER: |
| @@ -3554,6 +3578,8 @@ sweep_vectors (void) | |||
| 3554 | lisp_free (lv); | 3578 | lisp_free (lv); |
| 3555 | } | 3579 | } |
| 3556 | } | 3580 | } |
| 3581 | |||
| 3582 | gcstat.total_hash_table_bytes = hash_table_allocated_bytes; | ||
| 3557 | } | 3583 | } |
| 3558 | 3584 | ||
| 3559 | /* Maximum number of elements in a vector. This is a macro so that it | 3585 | /* Maximum number of elements in a vector. This is a macro so that it |
| @@ -5606,6 +5632,28 @@ valid_lisp_object_p (Lisp_Object obj) | |||
| 5606 | return 0; | 5632 | return 0; |
| 5607 | } | 5633 | } |
| 5608 | 5634 | ||
| 5635 | /* Like xmalloc, but makes allocation count toward the total consing. | ||
| 5636 | Return NULL for a zero-sized allocation. */ | ||
| 5637 | void * | ||
| 5638 | hash_table_alloc_bytes (ptrdiff_t nbytes) | ||
| 5639 | { | ||
| 5640 | if (nbytes == 0) | ||
| 5641 | return NULL; | ||
| 5642 | tally_consing (nbytes); | ||
| 5643 | hash_table_allocated_bytes += nbytes; | ||
| 5644 | return xmalloc (nbytes); | ||
| 5645 | } | ||
| 5646 | |||
| 5647 | /* Like xfree, but makes allocation count toward the total consing. */ | ||
| 5648 | void | ||
| 5649 | hash_table_free_bytes (void *p, ptrdiff_t nbytes) | ||
| 5650 | { | ||
| 5651 | tally_consing (-nbytes); | ||
| 5652 | hash_table_allocated_bytes -= nbytes; | ||
| 5653 | xfree (p); | ||
| 5654 | } | ||
| 5655 | |||
| 5656 | |||
| 5609 | /*********************************************************************** | 5657 | /*********************************************************************** |
| 5610 | Pure Storage Management | 5658 | Pure Storage Management |
| 5611 | ***********************************************************************/ | 5659 | ***********************************************************************/ |
| @@ -5897,10 +5945,28 @@ purecopy_hash_table (struct Lisp_Hash_Table *table) | |||
| 5897 | pure->test.name = purecopy (table->test.name); | 5945 | pure->test.name = purecopy (table->test.name); |
| 5898 | pure->test.user_hash_function = purecopy (table->test.user_hash_function); | 5946 | pure->test.user_hash_function = purecopy (table->test.user_hash_function); |
| 5899 | pure->test.user_cmp_function = purecopy (table->test.user_cmp_function); | 5947 | pure->test.user_cmp_function = purecopy (table->test.user_cmp_function); |
| 5900 | pure->hash = purecopy (table->hash); | 5948 | |
| 5901 | pure->next = purecopy (table->next); | 5949 | if (table->table_size > 0) |
| 5902 | pure->index = purecopy (table->index); | 5950 | { |
| 5903 | pure->key_and_value = purecopy (table->key_and_value); | 5951 | ptrdiff_t hash_bytes = table->table_size * sizeof *table->hash; |
| 5952 | pure->hash = pure_alloc (hash_bytes, -(int)sizeof *table->hash); | ||
| 5953 | memcpy (pure->hash, table->hash, hash_bytes); | ||
| 5954 | |||
| 5955 | ptrdiff_t next_bytes = table->table_size * sizeof *table->next; | ||
| 5956 | pure->next = pure_alloc (next_bytes, -(int)sizeof *table->next); | ||
| 5957 | memcpy (pure->next, table->next, next_bytes); | ||
| 5958 | |||
| 5959 | ptrdiff_t nvalues = table->table_size * 2; | ||
| 5960 | ptrdiff_t kv_bytes = nvalues * sizeof *table->key_and_value; | ||
| 5961 | pure->key_and_value = pure_alloc (kv_bytes, | ||
| 5962 | -(int)sizeof *table->key_and_value); | ||
| 5963 | for (ptrdiff_t i = 0; i < nvalues; i++) | ||
| 5964 | pure->key_and_value[i] = purecopy (table->key_and_value[i]); | ||
| 5965 | |||
| 5966 | ptrdiff_t index_bytes = table->index_size * sizeof *table->index; | ||
| 5967 | pure->index = pure_alloc (index_bytes, -(int)sizeof *table->index); | ||
| 5968 | memcpy (pure->index, table->index, index_bytes); | ||
| 5969 | } | ||
| 5904 | 5970 | ||
| 5905 | return pure; | 5971 | return pure; |
| 5906 | } | 5972 | } |
| @@ -6084,6 +6150,7 @@ total_bytes_of_live_objects (void) | |||
| 6084 | tot += object_bytes (gcstat.total_floats, sizeof (struct Lisp_Float)); | 6150 | tot += object_bytes (gcstat.total_floats, sizeof (struct Lisp_Float)); |
| 6085 | tot += object_bytes (gcstat.total_intervals, sizeof (struct interval)); | 6151 | tot += object_bytes (gcstat.total_intervals, sizeof (struct interval)); |
| 6086 | tot += object_bytes (gcstat.total_strings, sizeof (struct Lisp_String)); | 6152 | tot += object_bytes (gcstat.total_strings, sizeof (struct Lisp_String)); |
| 6153 | tot += gcstat.total_hash_table_bytes; | ||
| 6087 | return tot; | 6154 | return tot; |
| 6088 | } | 6155 | } |
| 6089 | 6156 | ||
| @@ -7227,23 +7294,20 @@ process_mark_stack (ptrdiff_t base_sp) | |||
| 7227 | case PVEC_HASH_TABLE: | 7294 | case PVEC_HASH_TABLE: |
| 7228 | { | 7295 | { |
| 7229 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *)ptr; | 7296 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *)ptr; |
| 7230 | ptrdiff_t size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; | ||
| 7231 | set_vector_marked (ptr); | 7297 | set_vector_marked (ptr); |
| 7232 | mark_stack_push_values (ptr->contents, size); | ||
| 7233 | mark_stack_push_value (h->test.name); | 7298 | mark_stack_push_value (h->test.name); |
| 7234 | mark_stack_push_value (h->test.user_hash_function); | 7299 | mark_stack_push_value (h->test.user_hash_function); |
| 7235 | mark_stack_push_value (h->test.user_cmp_function); | 7300 | mark_stack_push_value (h->test.user_cmp_function); |
| 7236 | if (h->weakness == Weak_None) | 7301 | if (h->weakness == Weak_None) |
| 7237 | mark_stack_push_value (h->key_and_value); | 7302 | mark_stack_push_values (h->key_and_value, |
| 7303 | 2 * h->table_size); | ||
| 7238 | else | 7304 | else |
| 7239 | { | 7305 | { |
| 7240 | /* For weak tables, mark only the vector and not its | 7306 | /* For weak tables, don't mark the |
| 7241 | contents --- that's what makes it weak. */ | 7307 | contents --- that's what makes it weak. */ |
| 7242 | eassert (h->next_weak == NULL); | 7308 | eassert (h->next_weak == NULL); |
| 7243 | h->next_weak = weak_hash_tables; | 7309 | h->next_weak = weak_hash_tables; |
| 7244 | weak_hash_tables = h; | 7310 | weak_hash_tables = h; |
| 7245 | if (!PURE_P (h->key_and_value)) | ||
| 7246 | set_vector_marked (XVECTOR (h->key_and_value)); | ||
| 7247 | } | 7311 | } |
| 7248 | break; | 7312 | break; |
| 7249 | } | 7313 | } |