diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 146 |
1 files changed, 109 insertions, 37 deletions
diff --git a/src/alloc.c b/src/alloc.c index bb8e97f8737..be98cfd5f53 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -297,20 +297,20 @@ static ptrdiff_t pure_bytes_used_non_lisp; | |||
| 297 | 297 | ||
| 298 | static intptr_t garbage_collection_inhibited; | 298 | static intptr_t garbage_collection_inhibited; |
| 299 | 299 | ||
| 300 | /* The GC threshold in bytes, the last time it was calculated | ||
| 301 | from gc-cons-threshold and gc-cons-percentage. */ | ||
| 302 | static intmax_t gc_threshold; | ||
| 303 | |||
| 300 | /* If nonzero, this is a warning delivered by malloc and not yet | 304 | /* If nonzero, this is a warning delivered by malloc and not yet |
| 301 | displayed. */ | 305 | displayed. */ |
| 302 | 306 | ||
| 303 | const char *pending_malloc_warning; | 307 | const char *pending_malloc_warning; |
| 304 | 308 | ||
| 305 | #if 0 /* Normally, pointer sanity only on request... */ | 309 | /* Pointer sanity only on request. FIXME: Code depending on |
| 310 | SUSPICIOUS_OBJECT_CHECKING is obsolete; remove it entirely. */ | ||
| 306 | #ifdef ENABLE_CHECKING | 311 | #ifdef ENABLE_CHECKING |
| 307 | #define SUSPICIOUS_OBJECT_CHECKING 1 | 312 | #define SUSPICIOUS_OBJECT_CHECKING 1 |
| 308 | #endif | 313 | #endif |
| 309 | #endif | ||
| 310 | |||
| 311 | /* ... but unconditionally use SUSPICIOUS_OBJECT_CHECKING while the GC | ||
| 312 | bug is unresolved. */ | ||
| 313 | #define SUSPICIOUS_OBJECT_CHECKING 1 | ||
| 314 | 314 | ||
| 315 | #ifdef SUSPICIOUS_OBJECT_CHECKING | 315 | #ifdef SUSPICIOUS_OBJECT_CHECKING |
| 316 | struct suspicious_free_record | 316 | struct suspicious_free_record |
| @@ -327,8 +327,8 @@ static int suspicious_free_history_index; | |||
| 327 | static void *find_suspicious_object_in_range (void *begin, void *end); | 327 | static void *find_suspicious_object_in_range (void *begin, void *end); |
| 328 | static void detect_suspicious_free (void *ptr); | 328 | static void detect_suspicious_free (void *ptr); |
| 329 | #else | 329 | #else |
| 330 | # define find_suspicious_object_in_range(begin, end) NULL | 330 | # define find_suspicious_object_in_range(begin, end) ((void *) NULL) |
| 331 | # define detect_suspicious_free(ptr) (void) | 331 | # define detect_suspicious_free(ptr) ((void) 0) |
| 332 | #endif | 332 | #endif |
| 333 | 333 | ||
| 334 | /* Maximum amount of C stack to save when a GC happens. */ | 334 | /* Maximum amount of C stack to save when a GC happens. */ |
| @@ -4621,11 +4621,11 @@ mark_maybe_pointer (void *p) | |||
| 4621 | 4621 | ||
| 4622 | if (pdumper_object_p (p)) | 4622 | if (pdumper_object_p (p)) |
| 4623 | { | 4623 | { |
| 4624 | enum Lisp_Type type = pdumper_find_object_type (p); | 4624 | int type = pdumper_find_object_type (p); |
| 4625 | if (type != PDUMPER_NO_OBJECT) | 4625 | if (pdumper_valid_object_type_p (type)) |
| 4626 | mark_object ((type == Lisp_Symbol) | 4626 | mark_object (type == Lisp_Symbol |
| 4627 | ? make_lisp_symbol(p) | 4627 | ? make_lisp_symbol (p) |
| 4628 | : make_lisp_ptr(p, type)); | 4628 | : make_lisp_ptr (p, type)); |
| 4629 | /* See mark_maybe_object for why we can confidently return. */ | 4629 | /* See mark_maybe_object for why we can confidently return. */ |
| 4630 | return; | 4630 | return; |
| 4631 | } | 4631 | } |
| @@ -5290,9 +5290,10 @@ make_pure_float (double num) | |||
| 5290 | space. */ | 5290 | space. */ |
| 5291 | 5291 | ||
| 5292 | static Lisp_Object | 5292 | static Lisp_Object |
| 5293 | make_pure_bignum (struct Lisp_Bignum *value) | 5293 | make_pure_bignum (Lisp_Object value) |
| 5294 | { | 5294 | { |
| 5295 | size_t i, nlimbs = mpz_size (value->value); | 5295 | mpz_t const *n = xbignum_val (value); |
| 5296 | size_t i, nlimbs = mpz_size (*n); | ||
| 5296 | size_t nbytes = nlimbs * sizeof (mp_limb_t); | 5297 | size_t nbytes = nlimbs * sizeof (mp_limb_t); |
| 5297 | mp_limb_t *pure_limbs; | 5298 | mp_limb_t *pure_limbs; |
| 5298 | mp_size_t new_size; | 5299 | mp_size_t new_size; |
| @@ -5303,10 +5304,10 @@ make_pure_bignum (struct Lisp_Bignum *value) | |||
| 5303 | int limb_alignment = alignof (mp_limb_t); | 5304 | int limb_alignment = alignof (mp_limb_t); |
| 5304 | pure_limbs = pure_alloc (nbytes, - limb_alignment); | 5305 | pure_limbs = pure_alloc (nbytes, - limb_alignment); |
| 5305 | for (i = 0; i < nlimbs; ++i) | 5306 | for (i = 0; i < nlimbs; ++i) |
| 5306 | pure_limbs[i] = mpz_getlimbn (value->value, i); | 5307 | pure_limbs[i] = mpz_getlimbn (*n, i); |
| 5307 | 5308 | ||
| 5308 | new_size = nlimbs; | 5309 | new_size = nlimbs; |
| 5309 | if (mpz_sgn (value->value) < 0) | 5310 | if (mpz_sgn (*n) < 0) |
| 5310 | new_size = -new_size; | 5311 | new_size = -new_size; |
| 5311 | 5312 | ||
| 5312 | mpz_roinit_n (b->value, pure_limbs, new_size); | 5313 | mpz_roinit_n (b->value, pure_limbs, new_size); |
| @@ -5456,7 +5457,7 @@ purecopy (Lisp_Object obj) | |||
| 5456 | return obj; | 5457 | return obj; |
| 5457 | } | 5458 | } |
| 5458 | else if (BIGNUMP (obj)) | 5459 | else if (BIGNUMP (obj)) |
| 5459 | obj = make_pure_bignum (XBIGNUM (obj)); | 5460 | obj = make_pure_bignum (obj); |
| 5460 | else | 5461 | else |
| 5461 | { | 5462 | { |
| 5462 | AUTO_STRING (fmt, "Don't know how to purify: %S"); | 5463 | AUTO_STRING (fmt, "Don't know how to purify: %S"); |
| @@ -5784,6 +5785,77 @@ mark_and_sweep_weak_table_contents (void) | |||
| 5784 | } | 5785 | } |
| 5785 | } | 5786 | } |
| 5786 | 5787 | ||
| 5788 | /* Return the number of bytes to cons between GCs, assuming | ||
| 5789 | gc-cons-threshold is THRESHOLD and gc-cons-percentage is | ||
| 5790 | PERCENTAGE. */ | ||
| 5791 | static intmax_t | ||
| 5792 | consing_threshold (intmax_t threshold, Lisp_Object percentage) | ||
| 5793 | { | ||
| 5794 | if (!NILP (Vmemory_full)) | ||
| 5795 | return memory_full_cons_threshold; | ||
| 5796 | else | ||
| 5797 | { | ||
| 5798 | threshold = max (threshold, GC_DEFAULT_THRESHOLD / 10); | ||
| 5799 | if (FLOATP (percentage)) | ||
| 5800 | { | ||
| 5801 | double tot = (XFLOAT_DATA (percentage) | ||
| 5802 | * total_bytes_of_live_objects ()); | ||
| 5803 | if (threshold < tot) | ||
| 5804 | { | ||
| 5805 | if (tot < INTMAX_MAX) | ||
| 5806 | threshold = tot; | ||
| 5807 | else | ||
| 5808 | threshold = INTMAX_MAX; | ||
| 5809 | } | ||
| 5810 | } | ||
| 5811 | return threshold; | ||
| 5812 | } | ||
| 5813 | } | ||
| 5814 | |||
| 5815 | /* Adjust consing_until_gc, assuming gc-cons-threshold is THRESHOLD and | ||
| 5816 | gc-cons-percentage is PERCENTAGE. */ | ||
| 5817 | static Lisp_Object | ||
| 5818 | bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage) | ||
| 5819 | { | ||
| 5820 | /* If consing_until_gc is negative leave it alone, since this prevents | ||
| 5821 | negative integer overflow and a GC would have been done soon anyway. */ | ||
| 5822 | if (0 <= consing_until_gc) | ||
| 5823 | { | ||
| 5824 | threshold = consing_threshold (threshold, percentage); | ||
| 5825 | intmax_t sum; | ||
| 5826 | if (INT_ADD_WRAPV (consing_until_gc, threshold - gc_threshold, &sum)) | ||
| 5827 | { | ||
| 5828 | /* Scale the threshold down so that consing_until_gc does | ||
| 5829 | not overflow. */ | ||
| 5830 | sum = INTMAX_MAX; | ||
| 5831 | threshold = INTMAX_MAX - consing_until_gc + gc_threshold; | ||
| 5832 | } | ||
| 5833 | consing_until_gc = sum; | ||
| 5834 | gc_threshold = threshold; | ||
| 5835 | } | ||
| 5836 | |||
| 5837 | return Qnil; | ||
| 5838 | } | ||
| 5839 | |||
| 5840 | /* Watch changes to gc-cons-threshold. */ | ||
| 5841 | static Lisp_Object | ||
| 5842 | watch_gc_cons_threshold (Lisp_Object symbol, Lisp_Object newval, | ||
| 5843 | Lisp_Object operation, Lisp_Object where) | ||
| 5844 | { | ||
| 5845 | intmax_t threshold; | ||
| 5846 | if (! (INTEGERP (newval) && integer_to_intmax (newval, &threshold))) | ||
| 5847 | return Qnil; | ||
| 5848 | return bump_consing_until_gc (threshold, Vgc_cons_percentage); | ||
| 5849 | } | ||
| 5850 | |||
| 5851 | /* Watch changes to gc-cons-percentage. */ | ||
| 5852 | static Lisp_Object | ||
| 5853 | watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval, | ||
| 5854 | Lisp_Object operation, Lisp_Object where) | ||
| 5855 | { | ||
| 5856 | return bump_consing_until_gc (gc_cons_threshold, newval); | ||
| 5857 | } | ||
| 5858 | |||
| 5787 | /* Subroutine of Fgarbage_collect that does most of the work. */ | 5859 | /* Subroutine of Fgarbage_collect that does most of the work. */ |
| 5788 | static bool | 5860 | static bool |
| 5789 | garbage_collect_1 (struct gcstat *gcst) | 5861 | garbage_collect_1 (struct gcstat *gcst) |
| @@ -5926,25 +5998,8 @@ garbage_collect_1 (struct gcstat *gcst) | |||
| 5926 | 5998 | ||
| 5927 | unblock_input (); | 5999 | unblock_input (); |
| 5928 | 6000 | ||
| 5929 | if (!NILP (Vmemory_full)) | 6001 | consing_until_gc = gc_threshold |
| 5930 | consing_until_gc = memory_full_cons_threshold; | 6002 | = consing_threshold (gc_cons_threshold, Vgc_cons_percentage); |
| 5931 | else | ||
| 5932 | { | ||
| 5933 | intmax_t threshold = max (gc_cons_threshold, GC_DEFAULT_THRESHOLD / 10); | ||
| 5934 | if (FLOATP (Vgc_cons_percentage)) | ||
| 5935 | { | ||
| 5936 | double tot = (XFLOAT_DATA (Vgc_cons_percentage) | ||
| 5937 | * total_bytes_of_live_objects ()); | ||
| 5938 | if (threshold < tot) | ||
| 5939 | { | ||
| 5940 | if (tot < INTMAX_MAX) | ||
| 5941 | threshold = tot; | ||
| 5942 | else | ||
| 5943 | threshold = INTMAX_MAX; | ||
| 5944 | } | ||
| 5945 | } | ||
| 5946 | consing_until_gc = threshold; | ||
| 5947 | } | ||
| 5948 | 6003 | ||
| 5949 | if (garbage_collection_messages && NILP (Vmemory_full)) | 6004 | if (garbage_collection_messages && NILP (Vmemory_full)) |
| 5950 | { | 6005 | { |
| @@ -7365,6 +7420,7 @@ do hash-consing of the objects allocated to pure space. */); | |||
| 7365 | DEFSYM (Qheap, "heap"); | 7420 | DEFSYM (Qheap, "heap"); |
| 7366 | DEFSYM (QAutomatic_GC, "Automatic GC"); | 7421 | DEFSYM (QAutomatic_GC, "Automatic GC"); |
| 7367 | 7422 | ||
| 7423 | DEFSYM (Qgc_cons_percentage, "gc-cons-percentage"); | ||
| 7368 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); | 7424 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); |
| 7369 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); | 7425 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); |
| 7370 | 7426 | ||
| @@ -7398,6 +7454,22 @@ N should be nonnegative. */); | |||
| 7398 | defsubr (&Smemory_info); | 7454 | defsubr (&Smemory_info); |
| 7399 | defsubr (&Smemory_use_counts); | 7455 | defsubr (&Smemory_use_counts); |
| 7400 | defsubr (&Ssuspicious_object); | 7456 | defsubr (&Ssuspicious_object); |
| 7457 | |||
| 7458 | Lisp_Object watcher; | ||
| 7459 | |||
| 7460 | static union Aligned_Lisp_Subr Swatch_gc_cons_threshold = | ||
| 7461 | {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) }, | ||
| 7462 | { .a4 = watch_gc_cons_threshold }, | ||
| 7463 | 4, 4, "watch_gc_cons_threshold", 0, 0}}; | ||
| 7464 | XSETSUBR (watcher, &Swatch_gc_cons_threshold.s); | ||
| 7465 | Fadd_variable_watcher (Qgc_cons_threshold, watcher); | ||
| 7466 | |||
| 7467 | static union Aligned_Lisp_Subr Swatch_gc_cons_percentage = | ||
| 7468 | {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) }, | ||
| 7469 | { .a4 = watch_gc_cons_percentage }, | ||
| 7470 | 4, 4, "watch_gc_cons_percentage", 0, 0}}; | ||
| 7471 | XSETSUBR (watcher, &Swatch_gc_cons_percentage.s); | ||
| 7472 | Fadd_variable_watcher (Qgc_cons_percentage, watcher); | ||
| 7401 | } | 7473 | } |
| 7402 | 7474 | ||
| 7403 | #ifdef HAVE_X_WINDOWS | 7475 | #ifdef HAVE_X_WINDOWS |