This source file includes following definitions.
- malloc_initialize_hook
- alloc_unexec_pre
- alloc_unexec_post
- my_heap_start
- no_sanitize_memcpy
- which_symbols
- deadp
- pointer_align
- XPNTR
- XFLOAT_INIT
- tally_consing
- pointers_fit_in_lispobj_p
- mmap_lisp_allowed_p
- malloc_warning
- display_malloc_warning
- buffer_memory_full
- malloc_block_input
- malloc_unblock_input
- lmalloc
- xzalloc
- xrealloc
- xfree
- xnmalloc
- xnrealloc
- xpalloc
- xstrdup
- xlispstrdup
- dupstring
- xputenv
- record_xmalloc
- lisp_malloc
- lisp_free
- aligned_alloc
- lisp_align_malloc
- lisp_align_free
- laligned
- lmalloc
- lrealloc
- make_interval
- mark_interval_tree_1
- mark_interval_tree
- sdata_size
- init_strings
- string_bytes
- check_sblock
- check_string_bytes
- check_string_free_list
- allocate_string
- allocate_string_data
- resize_string_data
- sweep_strings
- free_large_strings
- compact_small_strings
- string_overflow
- bool_vector_fill
- make_uninit_bool_vector
- make_string
- make_unibyte_string
- make_multibyte_string
- make_string_from_bytes
- make_specified_string
- make_clear_string
- make_uninit_string
- make_clear_multibyte_string
- make_uninit_multibyte_string
- make_formatted_string
- pin_string
- make_float
- free_cons
- list1
- list2
- list3
- list4
- list5
- cons_listn
- listn
- pure_listn
- next_vector
- set_next_vector
- ADVANCE
- VINDEX
- large_vector_vec
- setup_on_free_list
- allocate_vector_block
- init_vectors
- allocate_vector_from_block
- vectorlike_nbytes
- cleanup_vector
- sweep_vectors
- allocate_vectorlike
- allocate_clear_vector
- allocate_vector
- allocate_nil_vector
- allocate_pseudovector
- allocate_buffer
- allocate_record
- make_vector
- set_symbol_name
- init_symbol
- DEFUN
- make_misc_ptr
- build_symbol_with_pos
- build_overlay
- DEFUN
- build_marker
- make_event_array
- make_user_ptr
- init_finalizer_list
- finalizer_insert
- unchain_finalizer
- mark_finalizer_list
- queue_doomed_finalizers
- run_finalizer_handler
- run_finalizer_function
- run_finalizers
- DEFUN
- vector_marked_p
- set_vector_marked
- vectorlike_marked_p
- set_vectorlike_marked
- cons_marked_p
- set_cons_marked
- string_marked_p
- set_string_marked
- symbol_marked_p
- set_symbol_marked
- interval_marked_p
- set_interval_marked
- memory_full
- refill_memory_reserve
- mem_init
- mem_find
- mem_insert
- mem_insert_fixup
- mem_rotate_left
- mem_rotate_right
- mem_delete
- mem_delete_fixup
- live_string_holding
- live_string_p
- live_cons_holding
- live_cons_p
- live_symbol_holding
- live_symbol_p
- live_float_holding
- live_float_p
- live_vector_pointer
- live_large_vector_holding
- live_large_vector_p
- live_small_vector_holding
- live_small_vector_p
- mark_maybe_pointer
- mark_memory
- test_setjmp
- test_setjmp
- mark_c_stack
- flush_stack_call_func1
- valid_pointer_p
- valid_lisp_object_p
- pure_alloc
- check_pure_size
- find_string_data_in_pure
- make_pure_string
- make_pure_c_string
- pure_cons
- make_pure_float
- make_pure_bignum
- make_pure_vector
- purecopy_hash_table
- DEFUN
- purecopy
- staticpro
- allow_garbage_collection
- inhibit_garbage_collection
- object_bytes
- total_bytes_of_live_objects
- compact_font_cache_entry
- compact_font_caches
- compact_undo_list
- mark_pinned_objects
- android_make_lisp_symbol
- mark_pinned_symbols
- visit_vectorlike_root
- visit_buffer_root
- visit_static_gc_roots
- mark_object_root_visitor
- mark_and_sweep_weak_table_contents
- consing_threshold
- bump_consing_until_gc
- watch_gc_cons_threshold
- watch_gc_cons_percentage
- maybe_garbage_collect
- garbage_collect
- DEFUN
- DEFUN
- mark_glyph_matrix
- mark_vectorlike
- mark_char_table
- mark_overlay
- mark_overlays
- mark_buffer
- mark_face_cache
- mark_localized_symbol
- mark_discard_killed_buffers
- mark_frame
- mark_window
- mark_stack_empty_p
- mark_stack_pop
- grow_mark_stack
- mark_stack_push_value
- mark_stack_push_values
- process_mark_stack
- mark_object
- mark_objects
- mark_terminals
- survives_gc_p
- sweep_conses
- sweep_floats
- sweep_intervals
- sweep_symbols
- unchain_dead_markers
- sweep_buffers
- gc_sweep
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- symbol_uses_obj
- which_symbols
- find_suspicious_object_in_range
- note_suspicious_free
- detect_suspicious_free
- DEFUN
- die
- verify_alloca
- init_alloc_once
- init_alloc_once_for_pdumper
- init_alloc
- syms_of_alloc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <errno.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <limits.h>
26 #include <signal.h>
27
28 #ifdef HAVE_PTHREAD
29 #include <pthread.h>
30 #endif
31
32 #include "lisp.h"
33 #include "bignum.h"
34 #include "dispextern.h"
35 #include "intervals.h"
36 #include "puresize.h"
37 #include "sheap.h"
38 #include "sysstdio.h"
39 #include "systime.h"
40 #include "character.h"
41 #include "buffer.h"
42 #include "window.h"
43 #include "keyboard.h"
44 #include "frame.h"
45 #include "blockinput.h"
46 #include "pdumper.h"
47 #include "termhooks.h"
48 #include "itree.h"
49 #ifdef HAVE_WINDOW_SYSTEM
50 #include TERM_HEADER
51 #endif
52
53 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
54 #include "sfntfont.h"
55 #endif
56
57 #ifdef HAVE_TREE_SITTER
58 #include "treesit.h"
59 #endif
60
61 #include <flexmember.h>
62 #include <verify.h>
63 #include <execinfo.h>
64
65 #ifdef HAVE_LINUX_SYSINFO
66 #include <sys/sysinfo.h>
67 #endif
68
69 #ifdef MSDOS
70 #include "dosfns.h"
71 #endif
72
73 #ifdef HAVE_MALLOC_H
74 # include <malloc.h>
75 #endif
76
77 #if (defined ENABLE_CHECKING \
78 && defined HAVE_VALGRIND_VALGRIND_H && !defined USE_VALGRIND)
79 # define USE_VALGRIND 1
80 #endif
81
82 #if USE_VALGRIND
83 #include <valgrind/valgrind.h>
84 #include <valgrind/memcheck.h>
85 #endif
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 #if ADDRESS_SANITIZER && defined HAVE_SANITIZER_ASAN_INTERFACE_H \
111 && !defined GC_ASAN_POISON_OBJECTS
112 # define GC_ASAN_POISON_OBJECTS 1
113 # include <sanitizer/asan_interface.h>
114 #else
115 # define GC_ASAN_POISON_OBJECTS 0
116 #endif
117
118
119
120
121
122 #if defined ENABLE_CHECKING && !defined GC_CHECK_MARKED_OBJECTS
123 # define GC_CHECK_MARKED_OBJECTS 1
124 #endif
125
126
127
128
129
130 #if (defined SYSTEM_MALLOC || defined DOUG_LEA_MALLOC \
131 || defined HYBRID_MALLOC || GC_CHECK_MARKED_OBJECTS)
132 #undef GC_MALLOC_CHECK
133 #endif
134
135 #include <unistd.h>
136 #include <fcntl.h>
137
138 #ifdef USE_GTK
139 # include "gtkutil.h"
140 #endif
141 #ifdef WINDOWSNT
142 #include "w32.h"
143 #include "w32heap.h"
144 #endif
145
146
147
148
149
150
151 union emacs_align_type
152 {
153 struct frame frame;
154 struct Lisp_Bignum Lisp_Bignum;
155 struct Lisp_Bool_Vector Lisp_Bool_Vector;
156 struct Lisp_Char_Table Lisp_Char_Table;
157 struct Lisp_CondVar Lisp_CondVar;
158 struct Lisp_Finalizer Lisp_Finalizer;
159 struct Lisp_Float Lisp_Float;
160 struct Lisp_Hash_Table Lisp_Hash_Table;
161 struct Lisp_Marker Lisp_Marker;
162 struct Lisp_Misc_Ptr Lisp_Misc_Ptr;
163 struct Lisp_Mutex Lisp_Mutex;
164 struct Lisp_Overlay Lisp_Overlay;
165 struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
166 struct Lisp_Subr Lisp_Subr;
167 struct Lisp_Sqlite Lisp_Sqlite;
168 struct Lisp_User_Ptr Lisp_User_Ptr;
169 struct Lisp_Vector Lisp_Vector;
170 struct terminal terminal;
171 struct thread_state thread_state;
172 struct window window;
173
174
175
176
177 #if 0
178 struct Lisp_Module_Function Lisp_Module_Function;
179 struct Lisp_Process Lisp_Process;
180 struct save_window_data save_window_data;
181 struct scroll_bar scroll_bar;
182 struct xwidget_view xwidget_view;
183 struct xwidget xwidget;
184 #endif
185 };
186
187
188
189
190
191
192
193
194
195
196
197
198
199 #define MALLOC_SIZE_NEAR(n) \
200 (ROUNDUP (max (n, sizeof (size_t)), MALLOC_ALIGNMENT) - sizeof (size_t))
201 #ifdef __i386
202 enum { MALLOC_ALIGNMENT = 16 };
203 #else
204 enum { MALLOC_ALIGNMENT = max (2 * sizeof (size_t), alignof (long double)) };
205 #endif
206
207 #ifdef DOUG_LEA_MALLOC
208
209
210
211
212 # define MMAP_MAX_AREAS 100000000
213
214
215
216 static void *malloc_state_ptr;
217
218
219
220
221 static void
222 malloc_initialize_hook (void)
223 {
224 static bool malloc_using_checking;
225
226 if (! initialized)
227 {
228 # ifdef GNU_LINUX
229 my_heap_start ();
230 # endif
231 malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
232 }
233 else
234 {
235 if (!malloc_using_checking)
236 {
237
238
239
240 char **p = environ;
241 if (p)
242 for (; *p; p++)
243 if (strncmp (*p, "MALLOC_CHECK_=", 14) == 0)
244 {
245 do
246 *p = p[1];
247 while (*++p);
248
249 break;
250 }
251 }
252
253 if (malloc_set_state (malloc_state_ptr) != 0)
254 emacs_abort ();
255 alloc_unexec_post ();
256 }
257 }
258
259
260
261 typedef void (*voidfuncptr) (void);
262 # ifndef __MALLOC_HOOK_VOLATILE
263 # define __MALLOC_HOOK_VOLATILE
264 # endif
265 voidfuncptr __MALLOC_HOOK_VOLATILE __malloc_initialize_hook EXTERNALLY_VISIBLE
266 = malloc_initialize_hook;
267
268 #endif
269
270 #if defined DOUG_LEA_MALLOC || defined HAVE_UNEXEC
271
272
273
274 void
275 alloc_unexec_pre (void)
276 {
277 # ifdef DOUG_LEA_MALLOC
278 malloc_state_ptr = malloc_get_state ();
279 if (!malloc_state_ptr)
280 fatal ("malloc_get_state: %s", strerror (errno));
281 # endif
282 }
283
284 void
285 alloc_unexec_post (void)
286 {
287 # ifdef DOUG_LEA_MALLOC
288 free (malloc_state_ptr);
289 # endif
290 }
291
292 # ifdef GNU_LINUX
293
294
295 void *
296 my_heap_start (void)
297 {
298 static void *start;
299 if (! start)
300 start = sbrk (0);
301 return start;
302 }
303 # endif
304
305 #endif
306
307
308
309
310 #define XMARK_STRING(S) ((S)->u.s.size |= ARRAY_MARK_FLAG)
311 #define XUNMARK_STRING(S) ((S)->u.s.size &= ~ARRAY_MARK_FLAG)
312 #define XSTRING_MARKED_P(S) (((S)->u.s.size & ARRAY_MARK_FLAG) != 0)
313
314 #define XMARK_VECTOR(V) ((V)->header.size |= ARRAY_MARK_FLAG)
315 #define XUNMARK_VECTOR(V) ((V)->header.size &= ~ARRAY_MARK_FLAG)
316 #define XVECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0)
317
318
319
320 #define GC_DEFAULT_THRESHOLD (100000 * word_size)
321
322
323 struct emacs_globals globals;
324
325
326
327 EMACS_INT consing_until_gc;
328
329 #ifdef HAVE_PDUMPER
330
331
332 int number_finalizers_run;
333 #endif
334
335
336
337 bool gc_in_progress;
338
339
340
341
342
343 typedef uintptr_t byte_ct;
344 typedef intptr_t object_ct;
345
346
347
348
349 #define HI_THRESHOLD (EMACS_INT_MAX / 2)
350
351
352
353 static struct gcstat
354 {
355 object_ct total_conses, total_free_conses;
356 object_ct total_symbols, total_free_symbols;
357 object_ct total_strings, total_free_strings;
358 byte_ct total_string_bytes;
359 object_ct total_vectors, total_vector_slots, total_free_vector_slots;
360 object_ct total_floats, total_free_floats;
361 object_ct total_intervals, total_free_intervals;
362 object_ct total_buffers;
363 } gcstat;
364
365
366
367
368
369 static char *spare_memory[7];
370
371
372
373
374 #define SPARE_MEMORY (1 << 14)
375
376
377
378
379
380
381
382 EMACS_INT pure[(PURESIZE + sizeof (EMACS_INT) - 1) / sizeof (EMACS_INT)] = {1,};
383 #define PUREBEG (char *) pure
384
385
386
387 static char *purebeg;
388 static ptrdiff_t pure_size;
389
390
391
392
393 static ptrdiff_t pure_bytes_used_before_overflow;
394
395
396
397 static ptrdiff_t pure_bytes_used_lisp;
398
399
400
401 static ptrdiff_t pure_bytes_used_non_lisp;
402
403
404
405 intptr_t garbage_collection_inhibited;
406
407
408
409 static EMACS_INT gc_threshold;
410
411
412
413
414 const char *pending_malloc_warning;
415
416
417
418 #ifdef ENABLE_CHECKING
419 #define SUSPICIOUS_OBJECT_CHECKING 1
420 #endif
421
422 #ifdef SUSPICIOUS_OBJECT_CHECKING
423 struct suspicious_free_record
424 {
425 void *suspicious_object;
426 void *backtrace[128];
427 };
428 static void *suspicious_objects[32];
429 static int suspicious_object_index;
430 struct suspicious_free_record suspicious_free_history[64] EXTERNALLY_VISIBLE;
431 static int suspicious_free_history_index;
432
433
434 static void *find_suspicious_object_in_range (void *begin, void *end);
435 static void detect_suspicious_free (void *ptr);
436 #else
437 # define find_suspicious_object_in_range(begin, end) ((void *) NULL)
438 # define detect_suspicious_free(ptr) ((void) 0)
439 #endif
440
441
442
443 #ifndef MAX_SAVE_STACK
444 #define MAX_SAVE_STACK 16000
445 #endif
446
447
448
449 #if MAX_SAVE_STACK > 0
450 static char *stack_copy;
451 static ptrdiff_t stack_copy_size;
452
453
454
455
456 static void * ATTRIBUTE_NO_SANITIZE_ADDRESS
457 no_sanitize_memcpy (void *dest, void const *src, size_t size)
458 {
459 if (! ADDRESS_SANITIZER)
460 return memcpy (dest, src, size);
461 else
462 {
463 size_t i;
464 char *d = dest;
465 char const *s = src;
466 for (i = 0; i < size; i++)
467 d[i] = s[i];
468 return dest;
469 }
470 }
471
472 #endif
473
474 static void unchain_finalizer (struct Lisp_Finalizer *);
475 static void mark_terminals (void);
476 static void gc_sweep (void);
477 static Lisp_Object make_pure_vector (ptrdiff_t);
478 static void mark_buffer (struct buffer *);
479
480 #if !defined REL_ALLOC || defined SYSTEM_MALLOC || defined HYBRID_MALLOC
481 static void refill_memory_reserve (void);
482 #endif
483 static void compact_small_strings (void);
484 static void free_large_strings (void);
485 extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
486
487 static bool vector_marked_p (struct Lisp_Vector const *);
488 static bool vectorlike_marked_p (union vectorlike_header const *);
489 static void set_vectorlike_marked (union vectorlike_header *);
490 static bool interval_marked_p (INTERVAL);
491 static void set_interval_marked (INTERVAL);
492
493
494
495
496
497 enum mem_type
498 {
499 MEM_TYPE_NON_LISP,
500 MEM_TYPE_CONS,
501 MEM_TYPE_STRING,
502 MEM_TYPE_SYMBOL,
503 MEM_TYPE_FLOAT,
504
505
506
507 MEM_TYPE_VECTORLIKE,
508
509 MEM_TYPE_VECTOR_BLOCK,
510
511 MEM_TYPE_SPARE
512 };
513
514 static bool
515 deadp (Lisp_Object x)
516 {
517 return BASE_EQ (x, dead_object ());
518 }
519
520 #ifdef GC_MALLOC_CHECK
521
522 enum mem_type allocated_mem_type;
523
524 #endif
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550 struct mem_node
551 {
552
553
554 struct mem_node *left, *right;
555
556
557 struct mem_node *parent;
558
559
560 void *start, *end;
561
562
563 enum {MEM_BLACK, MEM_RED} color;
564
565
566 enum mem_type type;
567 };
568
569
570
571 static struct mem_node *mem_root;
572
573
574
575 static void *min_heap_address, *max_heap_address;
576
577
578
579 static struct mem_node mem_z;
580 #define MEM_NIL &mem_z
581
582 static struct mem_node *mem_insert (void *, void *, enum mem_type);
583 static void mem_insert_fixup (struct mem_node *);
584 static void mem_rotate_left (struct mem_node *);
585 static void mem_rotate_right (struct mem_node *);
586 static void mem_delete (struct mem_node *);
587 static void mem_delete_fixup (struct mem_node *);
588 static struct mem_node *mem_find (void *);
589
590
591
592
593
594 Lisp_Object const *staticvec[NSTATICS]
595 #ifdef HAVE_UNEXEC
596 = {&Vpurify_flag}
597 #endif
598 ;
599
600
601
602 int staticidx;
603
604 static void *pure_alloc (size_t, int);
605
606
607
608 static void *
609 pointer_align (void *ptr, int alignment)
610 {
611 return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
612 }
613
614
615
616 static ATTRIBUTE_NO_SANITIZE_UNDEFINED void *
617 XPNTR (Lisp_Object a)
618 {
619 return (BARE_SYMBOL_P (a)
620 ? (char *) lispsym + (XLI (a) - LISP_WORD_TAG (Lisp_Symbol))
621 : (char *) XLP (a) - (XLI (a) & ~VALMASK));
622 }
623
624 static void
625 XFLOAT_INIT (Lisp_Object f, double n)
626 {
627 XFLOAT (f)->u.data = n;
628 }
629
630
631
632
633 static void
634 tally_consing (ptrdiff_t nbytes)
635 {
636 consing_until_gc -= nbytes;
637 }
638
639 #ifdef DOUG_LEA_MALLOC
640 static bool
641 pointers_fit_in_lispobj_p (void)
642 {
643 return (UINTPTR_MAX <= VAL_MAX) || USE_LSB_TAG;
644 }
645
646 static bool
647 mmap_lisp_allowed_p (void)
648 {
649
650
651
652
653
654 return pointers_fit_in_lispobj_p () && !will_dump_with_unexec_p ();
655 }
656 #endif
657
658
659 struct Lisp_Finalizer finalizers;
660
661
662
663
664
665 struct Lisp_Finalizer doomed_finalizers;
666
667
668
669
670
671
672 #if defined SIGDANGER || (!defined SYSTEM_MALLOC && !defined HYBRID_MALLOC)
673
674
675
676 void
677 malloc_warning (const char *str)
678 {
679 pending_malloc_warning = str;
680 }
681
682 #endif
683
684
685
686 void
687 display_malloc_warning (void)
688 {
689 call3 (intern ("display-warning"),
690 intern ("alloc"),
691 build_string (pending_malloc_warning),
692 intern (":emergency"));
693 pending_malloc_warning = 0;
694 }
695
696
697
698 void
699 buffer_memory_full (ptrdiff_t nbytes)
700 {
701
702
703
704
705
706
707
708 #ifndef REL_ALLOC
709 memory_full (nbytes);
710 #else
711
712
713 xsignal (Qnil, Vmemory_signal_data);
714 #endif
715 }
716
717
718
719
720 #define COMMON_MULTIPLE(a, b) \
721 ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b))
722
723
724
725
726
727 enum { LISP_ALIGNMENT = alignof (union { union emacs_align_type x;
728 GCALIGNED_UNION_MEMBER }) };
729 verify (LISP_ALIGNMENT % GCALIGNMENT == 0);
730
731
732
733
734
735
736
737
738 enum { MALLOC_IS_LISP_ALIGNED = alignof (max_align_t) % LISP_ALIGNMENT == 0 };
739
740
741
742
743
744
745
746
747
748 #ifdef XMALLOC_BLOCK_INPUT_CHECK
749 bool block_input_in_memory_allocators EXTERNALLY_VISIBLE;
750 static void
751 malloc_block_input (void)
752 {
753 if (block_input_in_memory_allocators)
754 block_input ();
755 }
756 static void
757 malloc_unblock_input (void)
758 {
759 if (block_input_in_memory_allocators)
760 {
761 int err = errno;
762 unblock_input ();
763 errno = err;
764 }
765 }
766 # define MALLOC_BLOCK_INPUT malloc_block_input ()
767 # define MALLOC_UNBLOCK_INPUT malloc_unblock_input ()
768 #else
769 # define MALLOC_BLOCK_INPUT ((void) 0)
770 # define MALLOC_UNBLOCK_INPUT ((void) 0)
771 #endif
772
773 #define MALLOC_PROBE(size) \
774 do { \
775 if (profiler_memory_running) \
776 malloc_probe (size); \
777 } while (0)
778
779 static void *lmalloc (size_t, bool) ATTRIBUTE_MALLOC_SIZE ((1));
780 static void *lrealloc (void *, size_t);
781
782
783
784 void *
785 xmalloc (size_t size)
786 {
787 void *val;
788
789 MALLOC_BLOCK_INPUT;
790 val = lmalloc (size, false);
791 MALLOC_UNBLOCK_INPUT;
792
793 if (!val)
794 memory_full (size);
795 MALLOC_PROBE (size);
796 return val;
797 }
798
799
800
801 void *
802 xzalloc (size_t size)
803 {
804 void *val;
805
806 MALLOC_BLOCK_INPUT;
807 val = lmalloc (size, true);
808 MALLOC_UNBLOCK_INPUT;
809
810 if (!val)
811 memory_full (size);
812 MALLOC_PROBE (size);
813 return val;
814 }
815
816
817
818 void *
819 xrealloc (void *block, size_t size)
820 {
821 void *val;
822
823 MALLOC_BLOCK_INPUT;
824
825
826 if (! block)
827 val = lmalloc (size, false);
828 else
829 val = lrealloc (block, size);
830 MALLOC_UNBLOCK_INPUT;
831
832 if (!val)
833 memory_full (size);
834 MALLOC_PROBE (size);
835 return val;
836 }
837
838
839
840
841 void
842 xfree (void *block)
843 {
844 if (!block)
845 return;
846 if (pdumper_object_p (block))
847 return;
848 MALLOC_BLOCK_INPUT;
849 free (block);
850 MALLOC_UNBLOCK_INPUT;
851
852
853 }
854
855
856
857
858
859 verify (INT_MAX <= PTRDIFF_MAX);
860
861
862
863
864
865 void *
866 xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
867 {
868 eassert (0 <= nitems && 0 < item_size);
869 ptrdiff_t nbytes;
870 if (ckd_mul (&nbytes, nitems, item_size) || SIZE_MAX < nbytes)
871 memory_full (SIZE_MAX);
872 return xmalloc (nbytes);
873 }
874
875
876
877
878
879 void *
880 xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
881 {
882 eassert (0 <= nitems && 0 < item_size);
883 ptrdiff_t nbytes;
884 if (ckd_mul (&nbytes, nitems, item_size) || SIZE_MAX < nbytes)
885 memory_full (SIZE_MAX);
886 return xrealloc (pa, nbytes);
887 }
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913 void *
914 xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
915 ptrdiff_t nitems_max, ptrdiff_t item_size)
916 {
917 ptrdiff_t n0 = *nitems;
918 eassume (0 < item_size && 0 < nitems_incr_min && 0 <= n0 && -1 <= nitems_max);
919
920
921
922
923 enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
924
925
926
927
928
929
930 ptrdiff_t n, nbytes;
931 if (ckd_add (&n, n0, n0 >> 1))
932 n = PTRDIFF_MAX;
933 if (0 <= nitems_max && nitems_max < n)
934 n = nitems_max;
935
936 ptrdiff_t adjusted_nbytes
937 = ((ckd_mul (&nbytes, n, item_size) || SIZE_MAX < nbytes)
938 ? min (PTRDIFF_MAX, SIZE_MAX)
939 : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
940 if (adjusted_nbytes)
941 {
942 n = adjusted_nbytes / item_size;
943 nbytes = adjusted_nbytes - adjusted_nbytes % item_size;
944 }
945
946 if (! pa)
947 *nitems = 0;
948 if (n - n0 < nitems_incr_min
949 && (ckd_add (&n, n0, nitems_incr_min)
950 || (0 <= nitems_max && nitems_max < n)
951 || ckd_mul (&nbytes, n, item_size)))
952 memory_full (SIZE_MAX);
953 pa = xrealloc (pa, nbytes);
954 *nitems = n;
955 return pa;
956 }
957
958
959
960
961 char *
962 xstrdup (const char *s)
963 {
964 ptrdiff_t size;
965 eassert (s);
966 size = strlen (s) + 1;
967 return memcpy (xmalloc (size), s, size);
968 }
969
970
971
972 char *
973 xlispstrdup (Lisp_Object string)
974 {
975 ptrdiff_t size = SBYTES (string) + 1;
976 return memcpy (xmalloc (size), SSDATA (string), size);
977 }
978
979
980
981
982
983
984 void
985 dupstring (char **ptr, char const *string)
986 {
987 char *old = *ptr;
988 *ptr = string ? xstrdup (string) : 0;
989 xfree (old);
990 }
991
992
993
994
995
996 void
997 xputenv (char const *string)
998 {
999 if (putenv ((char *) string) != 0)
1000 memory_full (0);
1001 }
1002
1003
1004
1005 void *
1006 record_xmalloc (size_t size)
1007 {
1008 void *p = xmalloc (size);
1009 record_unwind_protect_ptr (xfree, p);
1010 return p;
1011 }
1012
1013
1014
1015
1016
1017
1018 #if ! USE_LSB_TAG
1019 void *lisp_malloc_loser EXTERNALLY_VISIBLE;
1020 #endif
1021
1022 static void *
1023 lisp_malloc (size_t nbytes, bool clearit, enum mem_type type)
1024 {
1025 register void *val;
1026
1027 MALLOC_BLOCK_INPUT;
1028
1029 #ifdef GC_MALLOC_CHECK
1030 allocated_mem_type = type;
1031 #endif
1032
1033 val = lmalloc (nbytes, clearit);
1034
1035 #if ! USE_LSB_TAG
1036
1037
1038
1039 if (val && type != MEM_TYPE_NON_LISP)
1040 {
1041 Lisp_Object tem;
1042 XSETCONS (tem, (char *) val + nbytes - 1);
1043 if ((char *) XCONS (tem) != (char *) val + nbytes - 1)
1044 {
1045 lisp_malloc_loser = val;
1046 free (val);
1047 val = 0;
1048 }
1049 }
1050 #endif
1051
1052 #ifndef GC_MALLOC_CHECK
1053 if (val && type != MEM_TYPE_NON_LISP)
1054 mem_insert (val, (char *) val + nbytes, type);
1055 #endif
1056
1057 MALLOC_UNBLOCK_INPUT;
1058 if (!val)
1059 memory_full (nbytes);
1060 MALLOC_PROBE (nbytes);
1061 return val;
1062 }
1063
1064
1065
1066
1067 static void
1068 lisp_free (void *block)
1069 {
1070 if (pdumper_object_p (block))
1071 return;
1072
1073 MALLOC_BLOCK_INPUT;
1074 #ifndef GC_MALLOC_CHECK
1075 struct mem_node *m = mem_find (block);
1076 #endif
1077 free (block);
1078 #ifndef GC_MALLOC_CHECK
1079 mem_delete (m);
1080 #endif
1081 MALLOC_UNBLOCK_INPUT;
1082 }
1083
1084
1085
1086
1087
1088
1089
1090 #ifdef HAVE_UNEXEC
1091 # define BLOCK_ALIGN (1 << 10)
1092 #else
1093 # define BLOCK_ALIGN (1 << 15)
1094 #endif
1095 verify (POWER_OF_2 (BLOCK_ALIGN));
1096
1097
1098
1099
1100
1101 #if ! (defined DARWIN_OS && defined HAVE_UNEXEC)
1102 # if (defined HAVE_ALIGNED_ALLOC \
1103 || (defined HYBRID_MALLOC \
1104 ? defined HAVE_POSIX_MEMALIGN \
1105 : !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC))
1106 # define USE_ALIGNED_ALLOC 1
1107 # elif !defined HYBRID_MALLOC && defined HAVE_POSIX_MEMALIGN
1108 # define USE_ALIGNED_ALLOC 1
1109 # define aligned_alloc my_aligned_alloc
1110 static void *
1111 aligned_alloc (size_t alignment, size_t size)
1112 {
1113
1114
1115 verify (BLOCK_ALIGN % sizeof (void *) == 0
1116 && POWER_OF_2 (BLOCK_ALIGN / sizeof (void *)));
1117 verify (MALLOC_IS_LISP_ALIGNED
1118 || (LISP_ALIGNMENT % sizeof (void *) == 0
1119 && POWER_OF_2 (LISP_ALIGNMENT / sizeof (void *))));
1120 eassert (alignment == BLOCK_ALIGN
1121 || (!MALLOC_IS_LISP_ALIGNED && alignment == LISP_ALIGNMENT));
1122
1123 void *p;
1124 return posix_memalign (&p, alignment, size) == 0 ? p : 0;
1125 }
1126 # endif
1127 #endif
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139 #define BLOCK_PADDING 0
1140 #define BLOCK_BYTES \
1141 (BLOCK_ALIGN - sizeof (struct ablocks *) - BLOCK_PADDING)
1142
1143
1144
1145 #define ABLOCKS_SIZE 16
1146
1147
1148 struct ablock
1149 {
1150 union
1151 {
1152 char payload[BLOCK_BYTES];
1153 struct ablock *next_free;
1154 } x;
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165 struct ablocks *abase;
1166
1167
1168
1169 #if BLOCK_PADDING
1170 char padding[BLOCK_PADDING];
1171 #endif
1172 };
1173
1174
1175 struct ablocks
1176 {
1177 struct ablock blocks[ABLOCKS_SIZE];
1178 };
1179
1180
1181 #define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING)
1182
1183 #define ABLOCK_ABASE(block) \
1184 (((uintptr_t) (block)->abase) <= (1 + 2 * ABLOCKS_SIZE) \
1185 ? (struct ablocks *) (block) \
1186 : (block)->abase)
1187
1188
1189 #define ABLOCKS_BUSY(a_base) ((a_base)->blocks[0].abase)
1190
1191
1192 #ifdef USE_ALIGNED_ALLOC
1193 #define ABLOCKS_BASE(abase) (abase)
1194 #else
1195 #define ABLOCKS_BASE(abase) \
1196 (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1])
1197 #endif
1198
1199 #if GC_ASAN_POISON_OBJECTS
1200 # define ASAN_POISON_ABLOCK(b) \
1201 __asan_poison_memory_region (&(b)->x, sizeof ((b)->x))
1202 # define ASAN_UNPOISON_ABLOCK(b) \
1203 __asan_unpoison_memory_region (&(b)->x, sizeof ((b)->x))
1204 #else
1205 # define ASAN_POISON_ABLOCK(b) ((void) 0)
1206 # define ASAN_UNPOISON_ABLOCK(b) ((void) 0)
1207 #endif
1208
1209
1210 static struct ablock *free_ablock;
1211
1212
1213
1214
1215 static void *
1216 lisp_align_malloc (size_t nbytes, enum mem_type type)
1217 {
1218 void *base, *val;
1219 struct ablocks *abase;
1220
1221 eassert (nbytes <= BLOCK_BYTES);
1222
1223 MALLOC_BLOCK_INPUT;
1224
1225 #ifdef GC_MALLOC_CHECK
1226 allocated_mem_type = type;
1227 #endif
1228
1229 if (!free_ablock)
1230 {
1231 int i;
1232 bool aligned;
1233
1234 #ifdef DOUG_LEA_MALLOC
1235 if (!mmap_lisp_allowed_p ())
1236 mallopt (M_MMAP_MAX, 0);
1237 #endif
1238
1239 #ifdef USE_ALIGNED_ALLOC
1240 verify (ABLOCKS_BYTES % BLOCK_ALIGN == 0);
1241 abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES);
1242 #else
1243 base = malloc (ABLOCKS_BYTES);
1244 abase = pointer_align (base, BLOCK_ALIGN);
1245 #endif
1246
1247 if (base == 0)
1248 {
1249 MALLOC_UNBLOCK_INPUT;
1250 memory_full (ABLOCKS_BYTES);
1251 }
1252
1253 aligned = (base == abase);
1254 if (!aligned)
1255 ((void **) abase)[-1] = base;
1256
1257 #ifdef DOUG_LEA_MALLOC
1258 if (!mmap_lisp_allowed_p ())
1259 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
1260 #endif
1261
1262 #if ! USE_LSB_TAG
1263
1264
1265
1266 if (type != MEM_TYPE_NON_LISP)
1267 {
1268 Lisp_Object tem;
1269 char *end = (char *) base + ABLOCKS_BYTES - 1;
1270 XSETCONS (tem, end);
1271 if ((char *) XCONS (tem) != end)
1272 {
1273 lisp_malloc_loser = base;
1274 free (base);
1275 MALLOC_UNBLOCK_INPUT;
1276 memory_full (SIZE_MAX);
1277 }
1278 }
1279 #endif
1280
1281
1282
1283 for (i = 0; i < (aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1); i++)
1284 {
1285 abase->blocks[i].abase = abase;
1286 abase->blocks[i].x.next_free = free_ablock;
1287 ASAN_POISON_ABLOCK (&abase->blocks[i]);
1288 free_ablock = &abase->blocks[i];
1289 }
1290 intptr_t ialigned = aligned;
1291 ABLOCKS_BUSY (abase) = (struct ablocks *) ialigned;
1292
1293 eassert ((uintptr_t) abase % BLOCK_ALIGN == 0);
1294 eassert (ABLOCK_ABASE (&abase->blocks[3]) == abase);
1295 eassert (ABLOCK_ABASE (&abase->blocks[0]) == abase);
1296 eassert (ABLOCKS_BASE (abase) == base);
1297 eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned);
1298 }
1299
1300 ASAN_UNPOISON_ABLOCK (free_ablock);
1301 abase = ABLOCK_ABASE (free_ablock);
1302 ABLOCKS_BUSY (abase)
1303 = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
1304 val = free_ablock;
1305 free_ablock = free_ablock->x.next_free;
1306
1307 #ifndef GC_MALLOC_CHECK
1308 if (type != MEM_TYPE_NON_LISP)
1309 mem_insert (val, (char *) val + nbytes, type);
1310 #endif
1311
1312 MALLOC_UNBLOCK_INPUT;
1313
1314 MALLOC_PROBE (nbytes);
1315
1316 eassert (0 == ((uintptr_t) val) % BLOCK_ALIGN);
1317 return val;
1318 }
1319
1320 static void
1321 lisp_align_free (void *block)
1322 {
1323 struct ablock *ablock = block;
1324 struct ablocks *abase = ABLOCK_ABASE (ablock);
1325
1326 MALLOC_BLOCK_INPUT;
1327 #ifndef GC_MALLOC_CHECK
1328 mem_delete (mem_find (block));
1329 #endif
1330
1331 ablock->x.next_free = free_ablock;
1332 ASAN_POISON_ABLOCK (ablock);
1333 free_ablock = ablock;
1334
1335 intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2;
1336 eassume (0 <= busy && busy <= 2 * ABLOCKS_SIZE - 1);
1337 ABLOCKS_BUSY (abase) = (struct ablocks *) busy;
1338
1339 if (busy < 2)
1340 {
1341 int i = 0;
1342 bool aligned = busy;
1343 struct ablock **tem = &free_ablock;
1344 struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1];
1345 while (*tem)
1346 {
1347 #if GC_ASAN_POISON_OBJECTS
1348 __asan_unpoison_memory_region (&(*tem)->x,
1349 sizeof ((*tem)->x));
1350 #endif
1351 if (*tem >= (struct ablock *) abase && *tem < atop)
1352 {
1353 i++;
1354 *tem = (*tem)->x.next_free;
1355 }
1356 else
1357 tem = &(*tem)->x.next_free;
1358 }
1359 eassert ((aligned & 1) == aligned);
1360 eassert (i == (aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1));
1361 #ifdef USE_POSIX_MEMALIGN
1362 eassert ((uintptr_t) ABLOCKS_BASE (abase) % BLOCK_ALIGN == 0);
1363 #endif
1364 free (ABLOCKS_BASE (abase));
1365 }
1366 MALLOC_UNBLOCK_INPUT;
1367 }
1368
1369
1370
1371
1372
1373 static bool
1374 laligned (void *p, size_t size)
1375 {
1376 return (MALLOC_IS_LISP_ALIGNED || (intptr_t) p % LISP_ALIGNMENT == 0
1377 || size % LISP_ALIGNMENT != 0);
1378 }
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400 static void *
1401 lmalloc (size_t size, bool clearit)
1402 {
1403 #ifdef USE_ALIGNED_ALLOC
1404 if (! MALLOC_IS_LISP_ALIGNED && size % LISP_ALIGNMENT == 0)
1405 {
1406 void *p = aligned_alloc (LISP_ALIGNMENT, size);
1407 if (p)
1408 {
1409 if (clearit)
1410 memclear (p, size);
1411 }
1412 else if (! (MALLOC_0_IS_NONNULL || size))
1413 return aligned_alloc (LISP_ALIGNMENT, LISP_ALIGNMENT);
1414 return p;
1415 }
1416 #endif
1417
1418 while (true)
1419 {
1420 void *p = clearit ? calloc (1, size) : malloc (size);
1421 if (laligned (p, size) && (MALLOC_0_IS_NONNULL || size || p))
1422 return p;
1423 free (p);
1424 size_t bigger = size + LISP_ALIGNMENT;
1425 if (size < bigger)
1426 size = bigger;
1427 }
1428 }
1429
1430 static void *
1431 lrealloc (void *p, size_t size)
1432 {
1433 while (true)
1434 {
1435 p = realloc (p, size);
1436 if (laligned (p, size) && (size || p))
1437 return p;
1438 size_t bigger = size + LISP_ALIGNMENT;
1439 if (size < bigger)
1440 size = bigger;
1441 }
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451 enum { INTERVAL_BLOCK_SIZE
1452 = ((MALLOC_SIZE_NEAR (1024) - sizeof (struct interval_block *))
1453 / sizeof (struct interval)) };
1454
1455
1456
1457
1458 struct interval_block
1459 {
1460
1461 struct interval intervals[INTERVAL_BLOCK_SIZE];
1462 struct interval_block *next;
1463 };
1464
1465
1466
1467
1468 static struct interval_block *interval_block;
1469
1470
1471
1472
1473 static int interval_block_index = INTERVAL_BLOCK_SIZE;
1474
1475
1476
1477 static INTERVAL interval_free_list;
1478
1479 #if GC_ASAN_POISON_OBJECTS
1480 # define ASAN_POISON_INTERVAL_BLOCK(b) \
1481 __asan_poison_memory_region ((b)->intervals, \
1482 sizeof ((b)->intervals))
1483 # define ASAN_UNPOISON_INTERVAL_BLOCK(b) \
1484 __asan_unpoison_memory_region ((b)->intervals, \
1485 sizeof ((b)->intervals))
1486 # define ASAN_POISON_INTERVAL(i) \
1487 __asan_poison_memory_region ((i), sizeof (*(i)))
1488 # define ASAN_UNPOISON_INTERVAL(i) \
1489 __asan_unpoison_memory_region ((i), sizeof (*(i)))
1490 #else
1491 # define ASAN_POISON_INTERVAL_BLOCK(b) ((void) 0)
1492 # define ASAN_UNPOISON_INTERVAL_BLOCK(b) ((void) 0)
1493 # define ASAN_POISON_INTERVAL(i) ((void) 0)
1494 # define ASAN_UNPOISON_INTERVAL(i) ((void) 0)
1495 #endif
1496
1497
1498
1499 INTERVAL
1500 make_interval (void)
1501 {
1502 INTERVAL val;
1503
1504 MALLOC_BLOCK_INPUT;
1505
1506 if (interval_free_list)
1507 {
1508 val = interval_free_list;
1509 ASAN_UNPOISON_INTERVAL (val);
1510 interval_free_list = INTERVAL_PARENT (interval_free_list);
1511 }
1512 else
1513 {
1514 if (interval_block_index == INTERVAL_BLOCK_SIZE)
1515 {
1516 struct interval_block *newi
1517 = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP);
1518
1519 newi->next = interval_block;
1520 ASAN_POISON_INTERVAL_BLOCK (newi);
1521 interval_block = newi;
1522 interval_block_index = 0;
1523 }
1524 val = &interval_block->intervals[interval_block_index++];
1525 ASAN_UNPOISON_INTERVAL (val);
1526 }
1527
1528 MALLOC_UNBLOCK_INPUT;
1529
1530 tally_consing (sizeof (struct interval));
1531 intervals_consed++;
1532 RESET_INTERVAL (val);
1533 val->gcmarkbit = 0;
1534 return val;
1535 }
1536
1537
1538
1539
1540 static void
1541 mark_interval_tree_1 (INTERVAL i, void *dummy)
1542 {
1543
1544
1545 eassert (!interval_marked_p (i));
1546 set_interval_marked (i);
1547 mark_object (i->plist);
1548 }
1549
1550
1551
1552 static void
1553 mark_interval_tree (INTERVAL i)
1554 {
1555 if (i && !interval_marked_p (i))
1556 traverse_intervals_noorder (i, mark_interval_tree_1, NULL);
1557 }
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588 enum { SBLOCK_SIZE = MALLOC_SIZE_NEAR (8192) };
1589
1590
1591
1592
1593 #define LARGE_STRING_BYTES 1024
1594
1595
1596
1597 struct sdata
1598 {
1599
1600
1601
1602
1603
1604
1605 struct Lisp_String *string;
1606
1607 #ifdef GC_CHECK_STRING_BYTES
1608 ptrdiff_t nbytes;
1609 #endif
1610
1611 unsigned char data[FLEXIBLE_ARRAY_MEMBER];
1612 };
1613
1614
1615
1616
1617 typedef union
1618 {
1619 struct Lisp_String *string;
1620
1621
1622
1623
1624
1625
1626
1627
1628 #if 0
1629 struct sdata u;
1630 #endif
1631
1632
1633 struct
1634 {
1635 struct Lisp_String *string;
1636 ptrdiff_t nbytes;
1637 } n;
1638 } sdata;
1639
1640 #define SDATA_NBYTES(S) (S)->n.nbytes
1641 #define SDATA_DATA(S) ((struct sdata *) (S))->data
1642
1643 enum { SDATA_DATA_OFFSET = offsetof (struct sdata, data) };
1644
1645
1646
1647
1648
1649
1650 struct sblock
1651 {
1652
1653 struct sblock *next;
1654
1655
1656
1657 sdata *next_free;
1658
1659
1660 sdata data[FLEXIBLE_ARRAY_MEMBER];
1661 };
1662
1663
1664
1665 enum { STRING_BLOCK_SIZE
1666 = ((MALLOC_SIZE_NEAR (1024) - sizeof (struct string_block *))
1667 / sizeof (struct Lisp_String)) };
1668
1669
1670
1671
1672 struct string_block
1673 {
1674
1675 struct Lisp_String strings[STRING_BLOCK_SIZE];
1676 struct string_block *next;
1677 };
1678
1679
1680
1681
1682
1683 static struct sblock *oldest_sblock, *current_sblock;
1684
1685
1686
1687 static struct sblock *large_sblocks;
1688
1689
1690
1691 static struct string_block *string_blocks;
1692
1693
1694
1695 static struct Lisp_String *string_free_list;
1696
1697
1698
1699
1700
1701 #define NEXT_FREE_LISP_STRING(S) ((S)->u.next)
1702
1703
1704
1705
1706
1707
1708 #define SDATA_OF_STRING(S) ((sdata *) ((S)->u.s.data - SDATA_DATA_OFFSET))
1709
1710
1711 #ifdef GC_CHECK_STRING_OVERRUN
1712
1713
1714
1715
1716 # define GC_STRING_OVERRUN_COOKIE_SIZE ROUNDUP (4, alignof (sdata))
1717 static char const string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] =
1718 { '\xde', '\xad', '\xbe', '\xef', };
1719
1720 #else
1721 # define GC_STRING_OVERRUN_COOKIE_SIZE 0
1722 #endif
1723
1724
1725
1726
1727
1728 static ptrdiff_t
1729 sdata_size (ptrdiff_t n)
1730 {
1731
1732
1733 ptrdiff_t unaligned_size = max (SDATA_DATA_OFFSET + n + 1,
1734 sizeof (sdata));
1735 int sdata_align = max (FLEXALIGNOF (struct sdata), alignof (sdata));
1736 return (unaligned_size + sdata_align - 1) & ~(sdata_align - 1);
1737 }
1738
1739
1740 #define GC_STRING_EXTRA GC_STRING_OVERRUN_COOKIE_SIZE
1741
1742
1743
1744
1745
1746
1747 static ptrdiff_t const STRING_BYTES_MAX =
1748 min (STRING_BYTES_BOUND,
1749 ((SIZE_MAX
1750 - GC_STRING_EXTRA
1751 - offsetof (struct sblock, data)
1752 - SDATA_DATA_OFFSET)
1753 & ~(sizeof (EMACS_INT) - 1)));
1754
1755
1756
1757 static void
1758 init_strings (void)
1759 {
1760 empty_unibyte_string = make_pure_string ("", 0, 0, 0);
1761 staticpro (&empty_unibyte_string);
1762 empty_multibyte_string = make_pure_string ("", 0, 0, 1);
1763 staticpro (&empty_multibyte_string);
1764 }
1765
1766 #if GC_ASAN_POISON_OBJECTS
1767
1768
1769
1770
1771 # define ASAN_PREPARE_DEAD_SDATA(s, size) \
1772 do { \
1773 __asan_poison_memory_region ((s), sdata_size ((size))); \
1774 __asan_unpoison_memory_region (&(((s))->string), \
1775 sizeof (struct Lisp_String *)); \
1776 __asan_unpoison_memory_region (&SDATA_NBYTES ((s)), \
1777 sizeof (SDATA_NBYTES ((s)))); \
1778 } while (false)
1779
1780 # define ASAN_PREPARE_LIVE_SDATA(s, nbytes) \
1781 __asan_unpoison_memory_region ((s), sdata_size ((nbytes)))
1782 # define ASAN_POISON_SBLOCK_DATA(b, size) \
1783 __asan_poison_memory_region ((b)->data, (size))
1784 # define ASAN_POISON_STRING_BLOCK(b) \
1785 __asan_poison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1786 # define ASAN_UNPOISON_STRING_BLOCK(b) \
1787 __asan_unpoison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1788 # define ASAN_POISON_STRING(s) \
1789 __asan_poison_memory_region ((s), sizeof (*(s)))
1790 # define ASAN_UNPOISON_STRING(s) \
1791 __asan_unpoison_memory_region ((s), sizeof (*(s)))
1792 #else
1793 # define ASAN_PREPARE_DEAD_SDATA(s, size) ((void) 0)
1794 # define ASAN_PREPARE_LIVE_SDATA(s, nbytes) ((void) 0)
1795 # define ASAN_POISON_SBLOCK_DATA(b, size) ((void) 0)
1796 # define ASAN_POISON_STRING_BLOCK(b) ((void) 0)
1797 # define ASAN_UNPOISON_STRING_BLOCK(b) ((void) 0)
1798 # define ASAN_POISON_STRING(s) ((void) 0)
1799 # define ASAN_UNPOISON_STRING(s) ((void) 0)
1800 #endif
1801
1802 #ifdef GC_CHECK_STRING_BYTES
1803
1804 static int check_string_bytes_count;
1805
1806
1807
1808
1809 ptrdiff_t
1810 string_bytes (struct Lisp_String *s)
1811 {
1812 ptrdiff_t nbytes =
1813 (s->u.s.size_byte < 0 ? s->u.s.size & ~ARRAY_MARK_FLAG : s->u.s.size_byte);
1814
1815 if (!PURE_P (s) && !pdumper_object_p (s) && s->u.s.data
1816 && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s)))
1817 emacs_abort ();
1818 return nbytes;
1819 }
1820
1821
1822
1823 static void
1824 check_sblock (struct sblock *b)
1825 {
1826 sdata *end = b->next_free;
1827
1828 for (sdata *from = b->data; from < end; )
1829 {
1830 ptrdiff_t nbytes = sdata_size (from->string
1831 ? string_bytes (from->string)
1832 : SDATA_NBYTES (from));
1833 from = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
1834 }
1835 }
1836
1837
1838
1839
1840
1841
1842 static void
1843 check_string_bytes (bool all_p)
1844 {
1845 if (all_p)
1846 {
1847 struct sblock *b;
1848
1849 for (b = large_sblocks; b; b = b->next)
1850 {
1851 struct Lisp_String *s = b->data[0].string;
1852 if (s)
1853 string_bytes (s);
1854 }
1855
1856 for (b = oldest_sblock; b; b = b->next)
1857 check_sblock (b);
1858 }
1859 else if (current_sblock)
1860 check_sblock (current_sblock);
1861 }
1862
1863 #else
1864
1865 #define check_string_bytes(all) ((void) 0)
1866
1867 #endif
1868
1869 #ifdef GC_CHECK_STRING_FREE_LIST
1870
1871
1872
1873
1874 static void
1875 check_string_free_list (void)
1876 {
1877 struct Lisp_String *s;
1878
1879
1880 s = string_free_list;
1881 while (s != NULL)
1882 {
1883 if ((uintptr_t) s < 1024)
1884 emacs_abort ();
1885 s = NEXT_FREE_LISP_STRING (s);
1886 }
1887 }
1888 #else
1889 #define check_string_free_list()
1890 #endif
1891
1892
1893
1894 static struct Lisp_String *
1895 allocate_string (void)
1896 {
1897 struct Lisp_String *s;
1898
1899 MALLOC_BLOCK_INPUT;
1900
1901
1902
1903 if (string_free_list == NULL)
1904 {
1905 struct string_block *b = lisp_malloc (sizeof *b, false, MEM_TYPE_STRING);
1906 int i;
1907
1908 b->next = string_blocks;
1909 string_blocks = b;
1910
1911 for (i = STRING_BLOCK_SIZE - 1; i >= 0; --i)
1912 {
1913 s = b->strings + i;
1914
1915 s->u.s.data = NULL;
1916 NEXT_FREE_LISP_STRING (s) = string_free_list;
1917 string_free_list = s;
1918 }
1919 ASAN_POISON_STRING_BLOCK (b);
1920 }
1921
1922 check_string_free_list ();
1923
1924
1925 s = string_free_list;
1926 ASAN_UNPOISON_STRING (s);
1927 string_free_list = NEXT_FREE_LISP_STRING (s);
1928
1929 MALLOC_UNBLOCK_INPUT;
1930
1931 ++strings_consed;
1932 tally_consing (sizeof *s);
1933
1934 #ifdef GC_CHECK_STRING_BYTES
1935 if (!noninteractive)
1936 {
1937 if (++check_string_bytes_count == 200)
1938 {
1939 check_string_bytes_count = 0;
1940 check_string_bytes (1);
1941 }
1942 else
1943 check_string_bytes (0);
1944 }
1945 #endif
1946
1947 return s;
1948 }
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959 static void
1960 allocate_string_data (struct Lisp_String *s,
1961 EMACS_INT nchars, EMACS_INT nbytes, bool clearit,
1962 bool immovable)
1963 {
1964 sdata *data;
1965 struct sblock *b;
1966
1967 if (STRING_BYTES_MAX < nbytes)
1968 string_overflow ();
1969
1970
1971
1972 ptrdiff_t needed = sdata_size (nbytes);
1973
1974 MALLOC_BLOCK_INPUT;
1975
1976 if (nbytes > LARGE_STRING_BYTES || immovable)
1977 {
1978 size_t size = FLEXSIZEOF (struct sblock, data, needed);
1979
1980 #ifdef DOUG_LEA_MALLOC
1981 if (!mmap_lisp_allowed_p ())
1982 mallopt (M_MMAP_MAX, 0);
1983 #endif
1984
1985 b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP);
1986 ASAN_POISON_SBLOCK_DATA (b, size);
1987
1988 #ifdef DOUG_LEA_MALLOC
1989 if (!mmap_lisp_allowed_p ())
1990 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
1991 #endif
1992
1993 data = b->data;
1994 b->next = large_sblocks;
1995 b->next_free = data;
1996 large_sblocks = b;
1997 }
1998 else
1999 {
2000 b = current_sblock;
2001
2002 if (b == NULL
2003 || (SBLOCK_SIZE - GC_STRING_EXTRA
2004 < (char *) b->next_free - (char *) b + needed))
2005 {
2006
2007 b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP);
2008 ASAN_POISON_SBLOCK_DATA (b, SBLOCK_SIZE);
2009
2010 data = b->data;
2011 b->next = NULL;
2012 b->next_free = data;
2013
2014 if (current_sblock)
2015 current_sblock->next = b;
2016 else
2017 oldest_sblock = b;
2018 current_sblock = b;
2019 }
2020
2021 data = b->next_free;
2022
2023 if (clearit)
2024 {
2025 #if GC_ASAN_POISON_OBJECTS
2026
2027
2028 __asan_unpoison_memory_region (SDATA_DATA (data), nbytes);
2029 #endif
2030 memset (SDATA_DATA (data), 0, nbytes);
2031 }
2032 }
2033
2034 ASAN_PREPARE_LIVE_SDATA (data, nbytes);
2035 data->string = s;
2036 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
2037 eassert ((uintptr_t) b->next_free % alignof (sdata) == 0);
2038
2039 MALLOC_UNBLOCK_INPUT;
2040
2041 s->u.s.data = SDATA_DATA (data);
2042 #ifdef GC_CHECK_STRING_BYTES
2043 SDATA_NBYTES (data) = nbytes;
2044 #endif
2045 s->u.s.size = nchars;
2046 s->u.s.size_byte = nbytes;
2047 s->u.s.data[nbytes] = '\0';
2048 #ifdef GC_CHECK_STRING_OVERRUN
2049 memcpy ((char *) data + needed, string_overrun_cookie,
2050 GC_STRING_OVERRUN_COOKIE_SIZE);
2051 #endif
2052
2053 tally_consing (needed);
2054 }
2055
2056
2057
2058
2059
2060
2061
2062 unsigned char *
2063 resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
2064 int clen, int new_clen)
2065 {
2066 eassume (STRING_MULTIBYTE (string));
2067 sdata *old_sdata = SDATA_OF_STRING (XSTRING (string));
2068 ptrdiff_t nchars = SCHARS (string);
2069 ptrdiff_t nbytes = SBYTES (string);
2070 ptrdiff_t new_nbytes = nbytes + (new_clen - clen);
2071 unsigned char *data = SDATA (string);
2072 unsigned char *new_charaddr;
2073
2074 if (sdata_size (nbytes) == sdata_size (new_nbytes))
2075 {
2076
2077
2078 XSTRING (string)->u.s.size_byte = new_nbytes;
2079 #ifdef GC_CHECK_STRING_BYTES
2080 SDATA_NBYTES (old_sdata) = new_nbytes;
2081 #endif
2082 new_charaddr = data + cidx_byte;
2083 memmove (new_charaddr + new_clen, new_charaddr + clen,
2084 nbytes - (cidx_byte + (clen - 1)));
2085 }
2086 else
2087 {
2088 allocate_string_data (XSTRING (string), nchars, new_nbytes, false, false);
2089 unsigned char *new_data = SDATA (string);
2090 new_charaddr = new_data + cidx_byte;
2091 memcpy (new_charaddr + new_clen, data + cidx_byte + clen,
2092 nbytes - (cidx_byte + clen));
2093 memcpy (new_data, data, cidx_byte);
2094
2095
2096
2097 SDATA_NBYTES (old_sdata) = nbytes;
2098 old_sdata->string = NULL;
2099 }
2100
2101 clear_string_char_byte_cache ();
2102
2103 return new_charaddr;
2104 }
2105
2106
2107
2108
2109 NO_INLINE
2110 static void
2111 sweep_strings (void)
2112 {
2113 struct string_block *b, *next;
2114 struct string_block *live_blocks = NULL;
2115
2116 string_free_list = NULL;
2117 gcstat.total_strings = gcstat.total_free_strings = 0;
2118 gcstat.total_string_bytes = 0;
2119
2120
2121 for (b = string_blocks; b; b = next)
2122 {
2123 int i, nfree = 0;
2124 struct Lisp_String *free_list_before = string_free_list;
2125
2126 ASAN_UNPOISON_STRING_BLOCK (b);
2127
2128 next = b->next;
2129
2130 for (i = 0; i < STRING_BLOCK_SIZE; ++i)
2131 {
2132 struct Lisp_String *s = b->strings + i;
2133
2134 ASAN_UNPOISON_STRING (s);
2135
2136 if (s->u.s.data)
2137 {
2138
2139 if (XSTRING_MARKED_P (s))
2140 {
2141
2142 XUNMARK_STRING (s);
2143
2144
2145 s->u.s.intervals = balance_intervals (s->u.s.intervals);
2146
2147 gcstat.total_strings++;
2148 gcstat.total_string_bytes += STRING_BYTES (s);
2149 }
2150 else
2151 {
2152
2153 sdata *data = SDATA_OF_STRING (s);
2154
2155
2156
2157
2158 #ifdef GC_CHECK_STRING_BYTES
2159 if (string_bytes (s) != SDATA_NBYTES (data))
2160 emacs_abort ();
2161 #else
2162 data->n.nbytes = STRING_BYTES (s);
2163 #endif
2164 data->string = NULL;
2165
2166
2167
2168 s->u.s.data = NULL;
2169
2170
2171 NEXT_FREE_LISP_STRING (s) = string_free_list;
2172 ASAN_POISON_STRING (s);
2173 ASAN_PREPARE_DEAD_SDATA (data, SDATA_NBYTES (data));
2174 string_free_list = s;
2175 ++nfree;
2176 }
2177 }
2178 else
2179 {
2180
2181 NEXT_FREE_LISP_STRING (s) = string_free_list;
2182 ASAN_POISON_STRING (s);
2183
2184 string_free_list = s;
2185 ++nfree;
2186 }
2187 }
2188
2189
2190
2191 if (nfree == STRING_BLOCK_SIZE
2192 && gcstat.total_free_strings > STRING_BLOCK_SIZE)
2193 {
2194 lisp_free (b);
2195 string_free_list = free_list_before;
2196 }
2197 else
2198 {
2199 gcstat.total_free_strings += nfree;
2200 b->next = live_blocks;
2201 live_blocks = b;
2202 }
2203 }
2204
2205 check_string_free_list ();
2206
2207 string_blocks = live_blocks;
2208 free_large_strings ();
2209 compact_small_strings ();
2210
2211 check_string_free_list ();
2212 }
2213
2214
2215
2216
2217 static void
2218 free_large_strings (void)
2219 {
2220 struct sblock *b, *next;
2221 struct sblock *live_blocks = NULL;
2222
2223 for (b = large_sblocks; b; b = next)
2224 {
2225 next = b->next;
2226
2227 if (b->data[0].string == NULL)
2228 lisp_free (b);
2229 else
2230 {
2231 b->next = live_blocks;
2232 live_blocks = b;
2233 }
2234 }
2235
2236 large_sblocks = live_blocks;
2237 }
2238
2239
2240
2241
2242
2243 static void
2244 compact_small_strings (void)
2245 {
2246
2247
2248 struct sblock *tb = oldest_sblock;
2249 if (tb)
2250 {
2251 sdata *tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
2252 sdata *to = tb->data;
2253
2254
2255
2256
2257 struct sblock *b = tb;
2258 do
2259 {
2260 sdata *end = b->next_free;
2261 eassert ((char *) end <= (char *) b + SBLOCK_SIZE);
2262
2263 for (sdata *from = b->data; from < end; )
2264 {
2265
2266
2267 ptrdiff_t nbytes;
2268 struct Lisp_String *s = from->string;
2269
2270 #ifdef GC_CHECK_STRING_BYTES
2271
2272
2273 if (s && string_bytes (s) != SDATA_NBYTES (from))
2274 emacs_abort ();
2275 #endif
2276
2277 nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from);
2278 eassert (nbytes <= LARGE_STRING_BYTES);
2279
2280 ptrdiff_t size = sdata_size (nbytes);
2281 sdata *from_end = (sdata *) ((char *) from
2282 + size + GC_STRING_EXTRA);
2283
2284 #ifdef GC_CHECK_STRING_OVERRUN
2285 if (memcmp (string_overrun_cookie,
2286 (char *) from_end - GC_STRING_OVERRUN_COOKIE_SIZE,
2287 GC_STRING_OVERRUN_COOKIE_SIZE))
2288 emacs_abort ();
2289 #endif
2290
2291
2292 if (s)
2293 {
2294
2295 sdata *to_end = (sdata *) ((char *) to
2296 + size + GC_STRING_EXTRA);
2297 if (to_end > tb_end)
2298 {
2299 tb->next_free = to;
2300 tb = tb->next;
2301 tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
2302 to = tb->data;
2303 to_end = (sdata *) ((char *) to + size + GC_STRING_EXTRA);
2304 }
2305
2306
2307 if (from != to)
2308 {
2309 eassert (tb != b || to < from);
2310 ASAN_PREPARE_LIVE_SDATA (to, nbytes);
2311 memmove (to, from, size + GC_STRING_EXTRA);
2312 to->string->u.s.data = SDATA_DATA (to);
2313 }
2314
2315
2316 to = to_end;
2317 }
2318 from = from_end;
2319 }
2320 b = b->next;
2321 }
2322 while (b);
2323
2324
2325
2326 for (b = tb->next; b; )
2327 {
2328 struct sblock *next = b->next;
2329 lisp_free (b);
2330 b = next;
2331 }
2332
2333 tb->next_free = to;
2334 tb->next = NULL;
2335 }
2336
2337 current_sblock = tb;
2338 }
2339
2340 void
2341 string_overflow (void)
2342 {
2343 error ("Maximum string size exceeded");
2344 }
2345
2346 static Lisp_Object make_clear_string (EMACS_INT, bool);
2347 static Lisp_Object make_clear_multibyte_string (EMACS_INT, EMACS_INT, bool);
2348
2349 DEFUN ("make-string", Fmake_string, Smake_string, 2, 3, 0,
2350 doc:
2351
2352
2353
2354 )
2355 (Lisp_Object length, Lisp_Object init, Lisp_Object multibyte)
2356 {
2357 Lisp_Object val;
2358 EMACS_INT nbytes;
2359
2360 CHECK_FIXNAT (length);
2361 CHECK_CHARACTER (init);
2362
2363 int c = XFIXNAT (init);
2364 bool clearit = !c;
2365
2366 if (ASCII_CHAR_P (c) && NILP (multibyte))
2367 {
2368 nbytes = XFIXNUM (length);
2369 val = make_clear_string (nbytes, clearit);
2370 if (nbytes && !clearit)
2371 {
2372 memset (SDATA (val), c, nbytes);
2373 SDATA (val)[nbytes] = 0;
2374 }
2375 }
2376 else
2377 {
2378 unsigned char str[MAX_MULTIBYTE_LENGTH];
2379 ptrdiff_t len = CHAR_STRING (c, str);
2380 EMACS_INT string_len = XFIXNUM (length);
2381
2382 if (ckd_mul (&nbytes, len, string_len))
2383 string_overflow ();
2384 val = make_clear_multibyte_string (string_len, nbytes, clearit);
2385 if (!clearit)
2386 {
2387 unsigned char *beg = SDATA (val), *end = beg + nbytes;
2388 for (unsigned char *p = beg; p < end; p += len)
2389 {
2390
2391 if (p == beg)
2392 memcpy (p, str, len);
2393 else
2394 {
2395
2396
2397 len = min (p - beg, end - p);
2398 memcpy (p, beg, len);
2399 }
2400 }
2401 }
2402 }
2403
2404 return val;
2405 }
2406
2407
2408
2409
2410 Lisp_Object
2411 bool_vector_fill (Lisp_Object a, Lisp_Object init)
2412 {
2413 EMACS_INT nbits = bool_vector_size (a);
2414 if (0 < nbits)
2415 {
2416 unsigned char *data = bool_vector_uchar_data (a);
2417 int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1;
2418 ptrdiff_t nbytes = bool_vector_bytes (nbits);
2419 int last_mask = ~ (~0u << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1));
2420 memset (data, pattern, nbytes - 1);
2421 data[nbytes - 1] = pattern & last_mask;
2422 }
2423 return a;
2424 }
2425
2426
2427
2428 Lisp_Object
2429 make_uninit_bool_vector (EMACS_INT nbits)
2430 {
2431 Lisp_Object val;
2432 EMACS_INT words = bool_vector_words (nbits);
2433 EMACS_INT word_bytes = words * sizeof (bits_word);
2434 EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes
2435 + word_size - 1)
2436 / word_size);
2437 if (PTRDIFF_MAX < needed_elements)
2438 memory_full (SIZE_MAX);
2439 struct Lisp_Bool_Vector *p
2440 = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
2441 XSETVECTOR (val, p);
2442 XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
2443 p->size = nbits;
2444
2445
2446 if (words)
2447 p->data[words - 1] = 0;
2448
2449 return val;
2450 }
2451
2452 DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
2453 doc:
2454 )
2455 (Lisp_Object length, Lisp_Object init)
2456 {
2457 Lisp_Object val;
2458
2459 CHECK_FIXNAT (length);
2460 val = make_uninit_bool_vector (XFIXNAT (length));
2461 return bool_vector_fill (val, init);
2462 }
2463
2464 DEFUN ("bool-vector", Fbool_vector, Sbool_vector, 0, MANY, 0,
2465 doc:
2466
2467 )
2468 (ptrdiff_t nargs, Lisp_Object *args)
2469 {
2470 ptrdiff_t i;
2471 Lisp_Object vector;
2472
2473 vector = make_uninit_bool_vector (nargs);
2474 for (i = 0; i < nargs; i++)
2475 bool_vector_set (vector, i, !NILP (args[i]));
2476
2477 return vector;
2478 }
2479
2480
2481
2482
2483
2484 Lisp_Object
2485 make_string (const char *contents, ptrdiff_t nbytes)
2486 {
2487 register Lisp_Object val;
2488 ptrdiff_t nchars, multibyte_nbytes;
2489
2490 parse_str_as_multibyte ((const unsigned char *) contents, nbytes,
2491 &nchars, &multibyte_nbytes);
2492 if (nbytes == nchars || nbytes != multibyte_nbytes)
2493
2494
2495 val = make_unibyte_string (contents, nbytes);
2496 else
2497 val = make_multibyte_string (contents, nchars, nbytes);
2498 return val;
2499 }
2500
2501
2502
2503 Lisp_Object
2504 make_unibyte_string (const char *contents, ptrdiff_t length)
2505 {
2506 register Lisp_Object val;
2507 val = make_uninit_string (length);
2508 memcpy (SDATA (val), contents, length);
2509 return val;
2510 }
2511
2512
2513
2514
2515
2516 Lisp_Object
2517 make_multibyte_string (const char *contents,
2518 ptrdiff_t nchars, ptrdiff_t nbytes)
2519 {
2520 register Lisp_Object val;
2521 val = make_uninit_multibyte_string (nchars, nbytes);
2522 memcpy (SDATA (val), contents, nbytes);
2523 return val;
2524 }
2525
2526
2527
2528
2529
2530 Lisp_Object
2531 make_string_from_bytes (const char *contents,
2532 ptrdiff_t nchars, ptrdiff_t nbytes)
2533 {
2534 register Lisp_Object val;
2535 val = make_uninit_multibyte_string (nchars, nbytes);
2536 memcpy (SDATA (val), contents, nbytes);
2537 if (SBYTES (val) == SCHARS (val))
2538 STRING_SET_UNIBYTE (val);
2539 return val;
2540 }
2541
2542
2543
2544
2545
2546
2547
2548 Lisp_Object
2549 make_specified_string (const char *contents,
2550 ptrdiff_t nchars, ptrdiff_t nbytes, bool multibyte)
2551 {
2552 Lisp_Object val;
2553
2554 if (nchars < 0)
2555 {
2556 if (multibyte)
2557 nchars = multibyte_chars_in_text ((const unsigned char *) contents,
2558 nbytes);
2559 else
2560 nchars = nbytes;
2561 }
2562 val = make_uninit_multibyte_string (nchars, nbytes);
2563 memcpy (SDATA (val), contents, nbytes);
2564 if (!multibyte)
2565 STRING_SET_UNIBYTE (val);
2566 return val;
2567 }
2568
2569
2570
2571
2572
2573
2574 static Lisp_Object
2575 make_clear_string (EMACS_INT length, bool clearit)
2576 {
2577 Lisp_Object val;
2578
2579 if (!length)
2580 return empty_unibyte_string;
2581 val = make_clear_multibyte_string (length, length, clearit);
2582 STRING_SET_UNIBYTE (val);
2583 return val;
2584 }
2585
2586
2587
2588
2589 Lisp_Object
2590 make_uninit_string (EMACS_INT length)
2591 {
2592 return make_clear_string (length, false);
2593 }
2594
2595
2596
2597
2598
2599
2600 static Lisp_Object
2601 make_clear_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
2602 {
2603 Lisp_Object string;
2604 struct Lisp_String *s;
2605
2606 if (nchars < 0)
2607 emacs_abort ();
2608 if (!nbytes)
2609 return empty_multibyte_string;
2610
2611 s = allocate_string ();
2612 s->u.s.intervals = NULL;
2613 allocate_string_data (s, nchars, nbytes, clearit, false);
2614 XSETSTRING (string, s);
2615 string_chars_consed += nbytes;
2616 return string;
2617 }
2618
2619
2620
2621
2622 Lisp_Object
2623 make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes)
2624 {
2625 return make_clear_multibyte_string (nchars, nbytes, false);
2626 }
2627
2628
2629
2630
2631 Lisp_Object
2632 make_formatted_string (char *buf, const char *format, ...)
2633 {
2634 va_list ap;
2635 int length;
2636
2637 va_start (ap, format);
2638 length = vsprintf (buf, format, ap);
2639 va_end (ap);
2640 return make_string (buf, length);
2641 }
2642
2643
2644 void
2645 pin_string (Lisp_Object string)
2646 {
2647 eassert (STRINGP (string) && !STRING_MULTIBYTE (string));
2648 struct Lisp_String *s = XSTRING (string);
2649 ptrdiff_t size = STRING_BYTES (s);
2650 unsigned char *data = s->u.s.data;
2651
2652 if (!(size > LARGE_STRING_BYTES
2653 || PURE_P (data) || pdumper_object_p (data)
2654 || s->u.s.size_byte == -3))
2655 {
2656 eassert (s->u.s.size_byte == -1);
2657 sdata *old_sdata = SDATA_OF_STRING (s);
2658 allocate_string_data (s, size, size, false, true);
2659 memcpy (s->u.s.data, data, size);
2660 old_sdata->string = NULL;
2661 SDATA_NBYTES (old_sdata) = size;
2662 ASAN_PREPARE_DEAD_SDATA (old_sdata, size);
2663 }
2664 s->u.s.size_byte = -3;
2665 }
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677 #define FLOAT_BLOCK_SIZE \
2678 (((BLOCK_BYTES - sizeof (struct float_block *) \
2679 \
2680 - (sizeof (struct Lisp_Float) - sizeof (bits_word))) * CHAR_BIT) \
2681 / (sizeof (struct Lisp_Float) * CHAR_BIT + 1))
2682
2683 #define GETMARKBIT(block,n) \
2684 (((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \
2685 >> ((n) % BITS_PER_BITS_WORD)) \
2686 & 1)
2687
2688 #define SETMARKBIT(block,n) \
2689 ((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \
2690 |= (bits_word) 1 << ((n) % BITS_PER_BITS_WORD))
2691
2692 #define UNSETMARKBIT(block,n) \
2693 ((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \
2694 &= ~((bits_word) 1 << ((n) % BITS_PER_BITS_WORD)))
2695
2696 #define FLOAT_BLOCK(fptr) \
2697 (eassert (!pdumper_object_p (fptr)), \
2698 ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1))))
2699
2700 #define FLOAT_INDEX(fptr) \
2701 ((((uintptr_t) (fptr)) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Float))
2702
2703 struct float_block
2704 {
2705
2706 struct Lisp_Float floats[FLOAT_BLOCK_SIZE];
2707 bits_word gcmarkbits[1 + FLOAT_BLOCK_SIZE / BITS_PER_BITS_WORD];
2708 struct float_block *next;
2709 };
2710
2711 #define XFLOAT_MARKED_P(fptr) \
2712 GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2713
2714 #define XFLOAT_MARK(fptr) \
2715 SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2716
2717 #define XFLOAT_UNMARK(fptr) \
2718 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2719
2720 #if GC_ASAN_POISON_OBJECTS
2721 # define ASAN_POISON_FLOAT_BLOCK(fblk) \
2722 __asan_poison_memory_region ((fblk)->floats, \
2723 sizeof ((fblk)->floats))
2724 # define ASAN_UNPOISON_FLOAT_BLOCK(fblk) \
2725 __asan_unpoison_memory_region ((fblk)->floats, \
2726 sizeof ((fblk)->floats))
2727 # define ASAN_POISON_FLOAT(p) \
2728 __asan_poison_memory_region ((p), sizeof (struct Lisp_Float))
2729 # define ASAN_UNPOISON_FLOAT(p) \
2730 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Float))
2731 #else
2732 # define ASAN_POISON_FLOAT_BLOCK(fblk) ((void) 0)
2733 # define ASAN_UNPOISON_FLOAT_BLOCK(fblk) ((void) 0)
2734 # define ASAN_POISON_FLOAT(p) ((void) 0)
2735 # define ASAN_UNPOISON_FLOAT(p) ((void) 0)
2736 #endif
2737
2738
2739
2740 static struct float_block *float_block;
2741
2742
2743
2744 static int float_block_index = FLOAT_BLOCK_SIZE;
2745
2746
2747
2748 static struct Lisp_Float *float_free_list;
2749
2750
2751
2752 Lisp_Object
2753 make_float (double float_value)
2754 {
2755 register Lisp_Object val;
2756
2757 MALLOC_BLOCK_INPUT;
2758
2759 if (float_free_list)
2760 {
2761 XSETFLOAT (val, float_free_list);
2762 ASAN_UNPOISON_FLOAT (float_free_list);
2763 float_free_list = float_free_list->u.chain;
2764 }
2765 else
2766 {
2767 if (float_block_index == FLOAT_BLOCK_SIZE)
2768 {
2769 struct float_block *new
2770 = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT);
2771 new->next = float_block;
2772 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2773 ASAN_POISON_FLOAT_BLOCK (new);
2774 float_block = new;
2775 float_block_index = 0;
2776 }
2777 ASAN_UNPOISON_FLOAT (&float_block->floats[float_block_index]);
2778 XSETFLOAT (val, &float_block->floats[float_block_index]);
2779 float_block_index++;
2780 }
2781
2782 MALLOC_UNBLOCK_INPUT;
2783
2784 XFLOAT_INIT (val, float_value);
2785 eassert (!XFLOAT_MARKED_P (XFLOAT (val)));
2786 tally_consing (sizeof (struct Lisp_Float));
2787 floats_consed++;
2788 return val;
2789 }
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802 #define CONS_BLOCK_SIZE \
2803 (((BLOCK_BYTES - sizeof (struct cons_block *) \
2804 \
2805 - (sizeof (struct Lisp_Cons) - sizeof (bits_word))) * CHAR_BIT) \
2806 / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1))
2807
2808 #define CONS_BLOCK(fptr) \
2809 (eassert (!pdumper_object_p (fptr)), \
2810 ((struct cons_block *) ((uintptr_t) (fptr) & ~(BLOCK_ALIGN - 1))))
2811
2812 #define CONS_INDEX(fptr) \
2813 (((uintptr_t) (fptr) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Cons))
2814
2815 struct cons_block
2816 {
2817
2818 struct Lisp_Cons conses[CONS_BLOCK_SIZE];
2819 bits_word gcmarkbits[1 + CONS_BLOCK_SIZE / BITS_PER_BITS_WORD];
2820 struct cons_block *next;
2821 };
2822
2823 #define XCONS_MARKED_P(fptr) \
2824 GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
2825
2826 #define XMARK_CONS(fptr) \
2827 SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
2828
2829 #define XUNMARK_CONS(fptr) \
2830 UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
2831
2832
2833
2834
2835 enum { memory_full_cons_threshold = sizeof (struct cons_block) };
2836
2837
2838
2839 static struct cons_block *cons_block;
2840
2841
2842
2843 static int cons_block_index = CONS_BLOCK_SIZE;
2844
2845
2846
2847 static struct Lisp_Cons *cons_free_list;
2848
2849 #if GC_ASAN_POISON_OBJECTS
2850 # define ASAN_POISON_CONS_BLOCK(b) \
2851 __asan_poison_memory_region ((b)->conses, sizeof ((b)->conses))
2852 # define ASAN_POISON_CONS(p) \
2853 __asan_poison_memory_region ((p), sizeof (struct Lisp_Cons))
2854 # define ASAN_UNPOISON_CONS(p) \
2855 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Cons))
2856 #else
2857 # define ASAN_POISON_CONS_BLOCK(b) ((void) 0)
2858 # define ASAN_POISON_CONS(p) ((void) 0)
2859 # define ASAN_UNPOISON_CONS(p) ((void) 0)
2860 #endif
2861
2862
2863
2864 void
2865 free_cons (struct Lisp_Cons *ptr)
2866 {
2867 ptr->u.s.u.chain = cons_free_list;
2868 ptr->u.s.car = dead_object ();
2869 cons_free_list = ptr;
2870 ptrdiff_t nbytes = sizeof *ptr;
2871 tally_consing (-nbytes);
2872 ASAN_POISON_CONS (ptr);
2873 }
2874
2875 DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2876 doc: )
2877 (Lisp_Object car, Lisp_Object cdr)
2878 {
2879 register Lisp_Object val;
2880
2881 MALLOC_BLOCK_INPUT;
2882
2883 if (cons_free_list)
2884 {
2885 ASAN_UNPOISON_CONS (cons_free_list);
2886 XSETCONS (val, cons_free_list);
2887 cons_free_list = cons_free_list->u.s.u.chain;
2888 }
2889 else
2890 {
2891 if (cons_block_index == CONS_BLOCK_SIZE)
2892 {
2893 struct cons_block *new
2894 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
2895 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2896 ASAN_POISON_CONS_BLOCK (new);
2897 new->next = cons_block;
2898 cons_block = new;
2899 cons_block_index = 0;
2900 }
2901 ASAN_UNPOISON_CONS (&cons_block->conses[cons_block_index]);
2902 XSETCONS (val, &cons_block->conses[cons_block_index]);
2903 cons_block_index++;
2904 }
2905
2906 MALLOC_UNBLOCK_INPUT;
2907
2908 XSETCAR (val, car);
2909 XSETCDR (val, cdr);
2910 eassert (!XCONS_MARKED_P (XCONS (val)));
2911 consing_until_gc -= sizeof (struct Lisp_Cons);
2912 cons_cells_consed++;
2913 return val;
2914 }
2915
2916
2917
2918 Lisp_Object
2919 list1 (Lisp_Object arg1)
2920 {
2921 return Fcons (arg1, Qnil);
2922 }
2923
2924 Lisp_Object
2925 list2 (Lisp_Object arg1, Lisp_Object arg2)
2926 {
2927 return Fcons (arg1, Fcons (arg2, Qnil));
2928 }
2929
2930
2931 Lisp_Object
2932 list3 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
2933 {
2934 return Fcons (arg1, Fcons (arg2, Fcons (arg3, Qnil)));
2935 }
2936
2937 Lisp_Object
2938 list4 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4)
2939 {
2940 return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4, Qnil))));
2941 }
2942
2943 Lisp_Object
2944 list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4,
2945 Lisp_Object arg5)
2946 {
2947 return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4,
2948 Fcons (arg5, Qnil)))));
2949 }
2950
2951
2952
2953 static Lisp_Object
2954 cons_listn (ptrdiff_t count, Lisp_Object arg,
2955 Lisp_Object (*cons) (Lisp_Object, Lisp_Object), va_list ap)
2956 {
2957 eassume (0 < count);
2958 Lisp_Object val = cons (arg, Qnil);
2959 Lisp_Object tail = val;
2960 for (ptrdiff_t i = 1; i < count; i++)
2961 {
2962 Lisp_Object elem = cons (va_arg (ap, Lisp_Object), Qnil);
2963 XSETCDR (tail, elem);
2964 tail = elem;
2965 }
2966 return val;
2967 }
2968
2969
2970 Lisp_Object
2971 listn (ptrdiff_t count, Lisp_Object arg1, ...)
2972 {
2973 va_list ap;
2974 va_start (ap, arg1);
2975 Lisp_Object val = cons_listn (count, arg1, Fcons, ap);
2976 va_end (ap);
2977 return val;
2978 }
2979
2980
2981 Lisp_Object
2982 pure_listn (ptrdiff_t count, Lisp_Object arg1, ...)
2983 {
2984 va_list ap;
2985 va_start (ap, arg1);
2986 Lisp_Object val = cons_listn (count, arg1, pure_cons, ap);
2987 va_end (ap);
2988 return val;
2989 }
2990
2991 DEFUN ("list", Flist, Slist, 0, MANY, 0,
2992 doc:
2993
2994 )
2995 (ptrdiff_t nargs, Lisp_Object *args)
2996 {
2997 register Lisp_Object val;
2998 val = Qnil;
2999
3000 while (nargs > 0)
3001 {
3002 nargs--;
3003 val = Fcons (args[nargs], val);
3004 }
3005 return val;
3006 }
3007
3008
3009 DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
3010 doc: )
3011 (Lisp_Object length, Lisp_Object init)
3012 {
3013 Lisp_Object val = Qnil;
3014 CHECK_FIXNAT (length);
3015
3016 for (EMACS_INT size = XFIXNAT (length); 0 < size; size--)
3017 {
3018 val = Fcons (init, val);
3019 rarely_quit (size);
3020 }
3021
3022 return val;
3023 }
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036 static struct Lisp_Vector *
3037 next_vector (struct Lisp_Vector *v)
3038 {
3039 return XUNTAG (v->contents[0], Lisp_Int0, struct Lisp_Vector);
3040 }
3041
3042 static void
3043 set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p)
3044 {
3045 v->contents[0] = make_lisp_ptr (p, Lisp_Int0);
3046 }
3047
3048
3049
3050
3051
3052 enum { VECTOR_BLOCK_SIZE = 4096 };
3053
3054
3055 enum { roundup_size = COMMON_MULTIPLE (LISP_ALIGNMENT, word_size) };
3056
3057
3058 verify (VECTOR_BLOCK_SIZE % roundup_size == 0);
3059 verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
3060
3061
3062 #define vroundup_ct(x) ROUNDUP (x, roundup_size)
3063
3064 #define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x))
3065
3066
3067
3068 enum {VECTOR_BLOCK_BYTES = VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *))};
3069
3070
3071
3072 enum { VBLOCK_BYTES_MIN = vroundup_ct (header_size + sizeof (Lisp_Object)) };
3073
3074
3075
3076 enum { VBLOCK_BYTES_MAX = vroundup_ct ((VECTOR_BLOCK_BYTES / 2) - word_size) };
3077
3078
3079
3080
3081 enum { VECTOR_MAX_FREE_LIST_INDEX =
3082 (VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1 };
3083
3084
3085
3086 static struct Lisp_Vector *
3087 ADVANCE (struct Lisp_Vector *v, ptrdiff_t nbytes)
3088 {
3089 void *vv = v;
3090 char *cv = vv;
3091 void *p = cv + nbytes;
3092 return p;
3093 }
3094
3095
3096
3097 static ptrdiff_t
3098 VINDEX (ptrdiff_t nbytes)
3099 {
3100 eassume (VBLOCK_BYTES_MIN <= nbytes);
3101 return (nbytes - VBLOCK_BYTES_MIN) / roundup_size;
3102 }
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114 struct large_vector
3115 {
3116 struct large_vector *next;
3117 };
3118
3119 enum
3120 {
3121 large_vector_offset = ROUNDUP (sizeof (struct large_vector), LISP_ALIGNMENT)
3122 };
3123
3124 static struct Lisp_Vector *
3125 large_vector_vec (struct large_vector *p)
3126 {
3127 return (struct Lisp_Vector *) ((char *) p + large_vector_offset);
3128 }
3129
3130
3131
3132
3133 struct vector_block
3134 {
3135 char data[VECTOR_BLOCK_BYTES];
3136 struct vector_block *next;
3137 };
3138
3139
3140
3141 static struct vector_block *vector_blocks;
3142
3143
3144
3145
3146 static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX];
3147
3148
3149
3150 static struct large_vector *large_vectors;
3151
3152
3153
3154 Lisp_Object zero_vector;
3155
3156 #if GC_ASAN_POISON_OBJECTS
3157 # define ASAN_POISON_VECTOR_CONTENTS(v, bytes) \
3158 __asan_poison_memory_region ((v)->contents, (bytes))
3159 # define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) \
3160 __asan_unpoison_memory_region ((v)->contents, (bytes))
3161 # define ASAN_UNPOISON_VECTOR_BLOCK(b) \
3162 __asan_unpoison_memory_region ((b)->data, sizeof ((b)->data))
3163 #else
3164 # define ASAN_POISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3165 # define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3166 # define ASAN_UNPOISON_VECTOR_BLOCK(b) ((void) 0)
3167 #endif
3168
3169
3170
3171 static void
3172 setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
3173 {
3174 eassume (header_size <= nbytes);
3175 ptrdiff_t nwords = (nbytes - header_size) / word_size;
3176 XSETPVECTYPESIZE (v, PVEC_FREE, 0, nwords);
3177 eassert (nbytes % roundup_size == 0);
3178 ptrdiff_t vindex = VINDEX (nbytes);
3179 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
3180 set_next_vector (v, vector_free_lists[vindex]);
3181 ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
3182 vector_free_lists[vindex] = v;
3183 }
3184
3185
3186
3187 static struct vector_block *
3188 allocate_vector_block (void)
3189 {
3190 struct vector_block *block = xmalloc (sizeof *block);
3191
3192 #ifndef GC_MALLOC_CHECK
3193 mem_insert (block->data, block->data + VECTOR_BLOCK_BYTES,
3194 MEM_TYPE_VECTOR_BLOCK);
3195 #endif
3196
3197 block->next = vector_blocks;
3198 vector_blocks = block;
3199 return block;
3200 }
3201
3202
3203
3204 static void
3205 init_vectors (void)
3206 {
3207 zero_vector = make_pure_vector (0);
3208 staticpro (&zero_vector);
3209 }
3210
3211
3212
3213 static struct Lisp_Vector *
3214 allocate_vector_from_block (ptrdiff_t nbytes)
3215 {
3216 struct Lisp_Vector *vector;
3217 struct vector_block *block;
3218 size_t index, restbytes;
3219
3220 eassume (VBLOCK_BYTES_MIN <= nbytes && nbytes <= VBLOCK_BYTES_MAX);
3221 eassume (nbytes % roundup_size == 0);
3222
3223
3224
3225 index = VINDEX (nbytes);
3226 if (vector_free_lists[index])
3227 {
3228 vector = vector_free_lists[index];
3229 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3230 vector_free_lists[index] = next_vector (vector);
3231 return vector;
3232 }
3233
3234
3235
3236
3237 for (index = VINDEX (nbytes + VBLOCK_BYTES_MIN);
3238 index < VECTOR_MAX_FREE_LIST_INDEX; index++)
3239 if (vector_free_lists[index])
3240 {
3241
3242 vector = vector_free_lists[index];
3243 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3244 vector_free_lists[index] = next_vector (vector);
3245
3246
3247
3248 restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
3249 eassert (restbytes % roundup_size == 0);
3250 #if GC_ASAN_POISON_OBJECTS
3251
3252 __asan_unpoison_memory_region (ADVANCE (vector, nbytes),
3253 restbytes);
3254 #endif
3255 setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
3256 return vector;
3257 }
3258
3259
3260 block = allocate_vector_block ();
3261
3262
3263 vector = (struct Lisp_Vector *) block->data;
3264
3265
3266
3267 restbytes = VECTOR_BLOCK_BYTES - nbytes;
3268 if (restbytes >= VBLOCK_BYTES_MIN)
3269 {
3270 eassert (restbytes % roundup_size == 0);
3271 setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
3272 }
3273 return vector;
3274 }
3275
3276
3277
3278 #define VECTOR_IN_BLOCK(vector, block) \
3279 ((char *) (vector) <= (block)->data \
3280 + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN)
3281
3282
3283
3284 ptrdiff_t
3285 vectorlike_nbytes (const union vectorlike_header *hdr)
3286 {
3287 ptrdiff_t size = hdr->size & ~ARRAY_MARK_FLAG;
3288 ptrdiff_t nwords;
3289
3290 if (size & PSEUDOVECTOR_FLAG)
3291 {
3292 if (PSEUDOVECTOR_TYPEP (hdr, PVEC_BOOL_VECTOR))
3293 {
3294 struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) hdr;
3295 ptrdiff_t word_bytes = (bool_vector_words (bv->size)
3296 * sizeof (bits_word));
3297 ptrdiff_t boolvec_bytes = bool_header_size + word_bytes;
3298 verify (header_size <= bool_header_size);
3299 nwords = (boolvec_bytes - header_size + word_size - 1) / word_size;
3300 }
3301 else
3302 nwords = ((size & PSEUDOVECTOR_SIZE_MASK)
3303 + ((size & PSEUDOVECTOR_REST_MASK)
3304 >> PSEUDOVECTOR_SIZE_BITS));
3305 }
3306 else
3307 nwords = size;
3308 return vroundup (header_size + word_size * nwords);
3309 }
3310
3311
3312
3313
3314
3315 #define PSEUDOVEC_STRUCT(p, t) \
3316 verify_expr ((header_size + VECSIZE (struct t) * word_size \
3317 <= VBLOCK_BYTES_MAX), \
3318 (struct t *) (p))
3319
3320
3321
3322
3323 static void
3324 cleanup_vector (struct Lisp_Vector *vector)
3325 {
3326 detect_suspicious_free (vector);
3327
3328 if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BIGNUM))
3329 mpz_clear (PSEUDOVEC_STRUCT (vector, Lisp_Bignum)->value);
3330 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_OVERLAY))
3331 {
3332 struct Lisp_Overlay *ol = PSEUDOVEC_STRUCT (vector, Lisp_Overlay);
3333 xfree (ol->interval);
3334 }
3335 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FINALIZER))
3336 unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer));
3337 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT))
3338 {
3339 if ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX)
3340 {
3341 struct font *font = PSEUDOVEC_STRUCT (vector, font);
3342 struct font_driver const *drv = font->driver;
3343
3344
3345
3346 if (drv)
3347 {
3348
3349 eassert (valid_font_driver (drv));
3350 drv->close_font (font);
3351 }
3352 }
3353
3354 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
3355
3356
3357 if (((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
3358 == FONT_ENTITY_MAX)
3359 && PSEUDOVEC_STRUCT (vector, font_entity)->is_android)
3360 android_finalize_font_entity (PSEUDOVEC_STRUCT (vector, font_entity));
3361 #endif
3362 }
3363 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD))
3364 finalize_one_thread (PSEUDOVEC_STRUCT (vector, thread_state));
3365 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MUTEX))
3366 finalize_one_mutex (PSEUDOVEC_STRUCT (vector, Lisp_Mutex));
3367 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR))
3368 finalize_one_condvar (PSEUDOVEC_STRUCT (vector, Lisp_CondVar));
3369 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MARKER))
3370 {
3371
3372 eassert (! PSEUDOVEC_STRUCT (vector, Lisp_Marker)->buffer);
3373 }
3374 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_USER_PTR))
3375 {
3376 struct Lisp_User_Ptr *uptr = PSEUDOVEC_STRUCT (vector, Lisp_User_Ptr);
3377 if (uptr->finalizer)
3378 uptr->finalizer (uptr->p);
3379 }
3380 #ifdef HAVE_TREE_SITTER
3381 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_TS_PARSER))
3382 treesit_delete_parser (PSEUDOVEC_STRUCT (vector, Lisp_TS_Parser));
3383 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_TS_COMPILED_QUERY))
3384 treesit_delete_query (PSEUDOVEC_STRUCT (vector, Lisp_TS_Query));
3385 #endif
3386 #ifdef HAVE_MODULES
3387 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MODULE_FUNCTION))
3388 {
3389 ATTRIBUTE_MAY_ALIAS struct Lisp_Module_Function *function
3390 = (struct Lisp_Module_Function *) vector;
3391 module_finalize_function (function);
3392 }
3393 #endif
3394 #ifdef HAVE_NATIVE_COMP
3395 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_NATIVE_COMP_UNIT))
3396 {
3397 struct Lisp_Native_Comp_Unit *cu =
3398 PSEUDOVEC_STRUCT (vector, Lisp_Native_Comp_Unit);
3399 unload_comp_unit (cu);
3400 }
3401 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_SUBR))
3402 {
3403 struct Lisp_Subr *subr =
3404 PSEUDOVEC_STRUCT (vector, Lisp_Subr);
3405 if (!NILP (subr->native_comp_u))
3406 {
3407
3408
3409 xfree ((char *)subr->symbol_name);
3410 xfree (subr->native_c_name);
3411 }
3412 }
3413 #endif
3414 }
3415
3416
3417
3418 NO_INLINE
3419 static void
3420 sweep_vectors (void)
3421 {
3422 struct vector_block *block, **bprev = &vector_blocks;
3423 struct large_vector *lv, **lvprev = &large_vectors;
3424 struct Lisp_Vector *vector, *next;
3425
3426 gcstat.total_vectors = 0;
3427 gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0;
3428 memset (vector_free_lists, 0, sizeof (vector_free_lists));
3429
3430
3431
3432 for (block = vector_blocks; block; block = *bprev)
3433 {
3434 bool free_this_block = false;
3435
3436 for (vector = (struct Lisp_Vector *) block->data;
3437 VECTOR_IN_BLOCK (vector, block); vector = next)
3438 {
3439 ASAN_UNPOISON_VECTOR_BLOCK (block);
3440 if (XVECTOR_MARKED_P (vector))
3441 {
3442 XUNMARK_VECTOR (vector);
3443 gcstat.total_vectors++;
3444 ptrdiff_t nbytes = vector_nbytes (vector);
3445 gcstat.total_vector_slots += nbytes / word_size;
3446 next = ADVANCE (vector, nbytes);
3447 }
3448 else
3449 {
3450 ptrdiff_t total_bytes = 0;
3451
3452
3453
3454
3455 next = vector;
3456 do
3457 {
3458 cleanup_vector (next);
3459 ptrdiff_t nbytes = vector_nbytes (next);
3460 total_bytes += nbytes;
3461 next = ADVANCE (next, nbytes);
3462 }
3463 while (VECTOR_IN_BLOCK (next, block) && !vector_marked_p (next));
3464
3465 eassert (total_bytes % roundup_size == 0);
3466
3467 if (vector == (struct Lisp_Vector *) block->data
3468 && !VECTOR_IN_BLOCK (next, block))
3469
3470
3471 free_this_block = true;
3472 else
3473 {
3474 setup_on_free_list (vector, total_bytes);
3475 gcstat.total_free_vector_slots += total_bytes / word_size;
3476 }
3477 }
3478 }
3479
3480 if (free_this_block)
3481 {
3482 *bprev = block->next;
3483 #ifndef GC_MALLOC_CHECK
3484 mem_delete (mem_find (block->data));
3485 #endif
3486 xfree (block);
3487 }
3488 else
3489 bprev = &block->next;
3490 }
3491
3492
3493
3494 for (lv = large_vectors; lv; lv = *lvprev)
3495 {
3496 vector = large_vector_vec (lv);
3497 if (XVECTOR_MARKED_P (vector))
3498 {
3499 XUNMARK_VECTOR (vector);
3500 gcstat.total_vectors++;
3501 gcstat.total_vector_slots
3502 += (vector->header.size & PSEUDOVECTOR_FLAG
3503 ? vector_nbytes (vector) / word_size
3504 : header_size / word_size + vector->header.size);
3505 lvprev = &lv->next;
3506 }
3507 else
3508 {
3509 *lvprev = lv->next;
3510 lisp_free (lv);
3511 }
3512 }
3513 }
3514
3515
3516
3517
3518 #define VECTOR_ELTS_MAX \
3519 ((ptrdiff_t) \
3520 min (((min (PTRDIFF_MAX, SIZE_MAX) - header_size - large_vector_offset) \
3521 / word_size), \
3522 MOST_POSITIVE_FIXNUM))
3523
3524
3525
3526
3527
3528 static struct Lisp_Vector *
3529 allocate_vectorlike (ptrdiff_t len, bool clearit)
3530 {
3531 eassert (0 < len && len <= VECTOR_ELTS_MAX);
3532 ptrdiff_t nbytes = header_size + len * word_size;
3533 struct Lisp_Vector *p;
3534
3535 MALLOC_BLOCK_INPUT;
3536
3537 #ifdef DOUG_LEA_MALLOC
3538 if (!mmap_lisp_allowed_p ())
3539 mallopt (M_MMAP_MAX, 0);
3540 #endif
3541
3542 if (nbytes <= VBLOCK_BYTES_MAX)
3543 {
3544 p = allocate_vector_from_block (vroundup (nbytes));
3545 if (clearit)
3546 memclear (p, nbytes);
3547 }
3548 else
3549 {
3550 struct large_vector *lv = lisp_malloc (large_vector_offset + nbytes,
3551 clearit, MEM_TYPE_VECTORLIKE);
3552 lv->next = large_vectors;
3553 large_vectors = lv;
3554 p = large_vector_vec (lv);
3555 }
3556
3557 #ifdef DOUG_LEA_MALLOC
3558 if (!mmap_lisp_allowed_p ())
3559 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
3560 #endif
3561
3562 if (find_suspicious_object_in_range (p, (char *) p + nbytes))
3563 emacs_abort ();
3564
3565 tally_consing (nbytes);
3566 vector_cells_consed += len;
3567
3568 MALLOC_UNBLOCK_INPUT;
3569
3570 return p;
3571 }
3572
3573
3574
3575
3576
3577 static struct Lisp_Vector *
3578 allocate_clear_vector (ptrdiff_t len, bool clearit)
3579 {
3580 if (len == 0)
3581 return XVECTOR (zero_vector);
3582 if (VECTOR_ELTS_MAX < len)
3583 memory_full (SIZE_MAX);
3584 struct Lisp_Vector *v = allocate_vectorlike (len, clearit);
3585 v->header.size = len;
3586 return v;
3587 }
3588
3589
3590
3591 struct Lisp_Vector *
3592 allocate_vector (ptrdiff_t len)
3593 {
3594 return allocate_clear_vector (len, false);
3595 }
3596
3597
3598
3599 struct Lisp_Vector *
3600 allocate_nil_vector (ptrdiff_t len)
3601 {
3602 return allocate_clear_vector (len, true);
3603 }
3604
3605
3606
3607
3608 struct Lisp_Vector *
3609 allocate_pseudovector (int memlen, int lisplen,
3610 int zerolen, enum pvec_type tag)
3611 {
3612
3613 enum { size_max = (1 << PSEUDOVECTOR_SIZE_BITS) - 1 };
3614 enum { rest_max = (1 << PSEUDOVECTOR_REST_BITS) - 1 };
3615 verify (size_max + rest_max <= VECTOR_ELTS_MAX);
3616 eassert (0 <= tag && tag <= PVEC_FONT);
3617 eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen);
3618 eassert (lisplen <= size_max);
3619 eassert (memlen <= size_max + rest_max);
3620
3621 struct Lisp_Vector *v = allocate_vectorlike (memlen, false);
3622
3623 memclear (v->contents, zerolen * word_size);
3624 XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
3625 return v;
3626 }
3627
3628 struct buffer *
3629 allocate_buffer (void)
3630 {
3631 struct buffer *b
3632 = ALLOCATE_PSEUDOVECTOR (struct buffer, cursor_in_non_selected_windows_,
3633 PVEC_BUFFER);
3634 BUFFER_PVEC_INIT (b);
3635
3636 return b;
3637 }
3638
3639
3640
3641
3642
3643 static struct Lisp_Vector *
3644 allocate_record (EMACS_INT count)
3645 {
3646 if (count > PSEUDOVECTOR_SIZE_MASK)
3647 error ("Attempt to allocate a record of %"pI"d slots; max is %d",
3648 count, PSEUDOVECTOR_SIZE_MASK);
3649 struct Lisp_Vector *p = allocate_vectorlike (count, false);
3650 p->header.size = count;
3651 XSETPVECTYPE (p, PVEC_RECORD);
3652 return p;
3653 }
3654
3655
3656 DEFUN ("make-record", Fmake_record, Smake_record, 3, 3, 0,
3657 doc:
3658
3659
3660 )
3661 (Lisp_Object type, Lisp_Object slots, Lisp_Object init)
3662 {
3663 CHECK_FIXNAT (slots);
3664 EMACS_INT size = XFIXNAT (slots) + 1;
3665 struct Lisp_Vector *p = allocate_record (size);
3666 p->contents[0] = type;
3667 for (ptrdiff_t i = 1; i < size; i++)
3668 p->contents[i] = init;
3669 return make_lisp_ptr (p, Lisp_Vectorlike);
3670 }
3671
3672
3673 DEFUN ("record", Frecord, Srecord, 1, MANY, 0,
3674 doc:
3675
3676
3677
3678 )
3679 (ptrdiff_t nargs, Lisp_Object *args)
3680 {
3681 struct Lisp_Vector *p = allocate_record (nargs);
3682 memcpy (p->contents, args, nargs * sizeof *args);
3683 return make_lisp_ptr (p, Lisp_Vectorlike);
3684 }
3685
3686
3687 DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
3688 doc:
3689 )
3690 (Lisp_Object length, Lisp_Object init)
3691 {
3692 CHECK_TYPE (FIXNATP (length) && XFIXNAT (length) <= PTRDIFF_MAX,
3693 Qwholenump, length);
3694 return make_vector (XFIXNAT (length), init);
3695 }
3696
3697
3698
3699 Lisp_Object
3700 make_vector (ptrdiff_t length, Lisp_Object init)
3701 {
3702 bool clearit = NIL_IS_ZERO && NILP (init);
3703 struct Lisp_Vector *p = allocate_clear_vector (length, clearit);
3704 if (!clearit)
3705 for (ptrdiff_t i = 0; i < length; i++)
3706 p->contents[i] = init;
3707 return make_lisp_ptr (p, Lisp_Vectorlike);
3708 }
3709
3710 DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
3711 doc:
3712
3713 )
3714 (ptrdiff_t nargs, Lisp_Object *args)
3715 {
3716 Lisp_Object val = make_uninit_vector (nargs);
3717 struct Lisp_Vector *p = XVECTOR (val);
3718 memcpy (p->contents, args, nargs * sizeof *args);
3719 return val;
3720 }
3721
3722 DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0,
3723 doc:
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737 )
3738 (ptrdiff_t nargs, Lisp_Object *args)
3739 {
3740 if (! ((FIXNUMP (args[COMPILED_ARGLIST])
3741 || CONSP (args[COMPILED_ARGLIST])
3742 || NILP (args[COMPILED_ARGLIST]))
3743 && STRINGP (args[COMPILED_BYTECODE])
3744 && !STRING_MULTIBYTE (args[COMPILED_BYTECODE])
3745 && VECTORP (args[COMPILED_CONSTANTS])
3746 && FIXNATP (args[COMPILED_STACK_DEPTH])))
3747 error ("Invalid byte-code object");
3748
3749
3750 pin_string (args[COMPILED_BYTECODE]);
3751
3752
3753
3754
3755
3756
3757
3758
3759 Lisp_Object val = Fvector (nargs, args);
3760 XSETPVECTYPE (XVECTOR (val), PVEC_COMPILED);
3761 return val;
3762 }
3763
3764 DEFUN ("make-closure", Fmake_closure, Smake_closure, 1, MANY, 0,
3765 doc:
3766
3767
3768 )
3769 (ptrdiff_t nargs, Lisp_Object *args)
3770 {
3771 Lisp_Object protofun = args[0];
3772 CHECK_TYPE (COMPILEDP (protofun), Qbyte_code_function_p, protofun);
3773
3774
3775
3776
3777 Lisp_Object proto_constvec = AREF (protofun, COMPILED_CONSTANTS);
3778 ptrdiff_t constsize = ASIZE (proto_constvec);
3779 ptrdiff_t nvars = nargs - 1;
3780 if (nvars > constsize)
3781 error ("Closure vars do not fit in constvec");
3782 Lisp_Object constvec = make_uninit_vector (constsize);
3783 memcpy (XVECTOR (constvec)->contents, args + 1, nvars * word_size);
3784 memcpy (XVECTOR (constvec)->contents + nvars,
3785 XVECTOR (proto_constvec)->contents + nvars,
3786 (constsize - nvars) * word_size);
3787
3788
3789 ptrdiff_t protosize = PVSIZE (protofun);
3790 struct Lisp_Vector *v = allocate_vectorlike (protosize, false);
3791 v->header = XVECTOR (protofun)->header;
3792 memcpy (v->contents, XVECTOR (protofun)->contents, protosize * word_size);
3793 v->contents[COMPILED_CONSTANTS] = constvec;
3794 return make_lisp_ptr (v, Lisp_Vectorlike);
3795 }
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806 #define SYMBOL_BLOCK_SIZE \
3807 ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol))
3808
3809 struct symbol_block
3810 {
3811
3812 struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE];
3813 struct symbol_block *next;
3814 };
3815
3816 #if GC_ASAN_POISON_OBJECTS
3817 # define ASAN_POISON_SYMBOL_BLOCK(s) \
3818 __asan_poison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3819 # define ASAN_UNPOISON_SYMBOL_BLOCK(s) \
3820 __asan_unpoison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3821 # define ASAN_POISON_SYMBOL(sym) \
3822 __asan_poison_memory_region ((sym), sizeof (*(sym)))
3823 # define ASAN_UNPOISON_SYMBOL(sym) \
3824 __asan_unpoison_memory_region ((sym), sizeof (*(sym)))
3825
3826 #else
3827 # define ASAN_POISON_SYMBOL_BLOCK(s) ((void) 0)
3828 # define ASAN_UNPOISON_SYMBOL_BLOCK(s) ((void) 0)
3829 # define ASAN_POISON_SYMBOL(sym) ((void) 0)
3830 # define ASAN_UNPOISON_SYMBOL(sym) ((void) 0)
3831 #endif
3832
3833
3834
3835
3836 static struct symbol_block *symbol_block;
3837 static int symbol_block_index = SYMBOL_BLOCK_SIZE;
3838
3839
3840
3841
3842
3843
3844 static struct symbol_block *symbol_block_pinned;
3845
3846
3847
3848 static struct Lisp_Symbol *symbol_free_list;
3849
3850 static void
3851 set_symbol_name (Lisp_Object sym, Lisp_Object name)
3852 {
3853 XBARE_SYMBOL (sym)->u.s.name = name;
3854 }
3855
3856 void
3857 init_symbol (Lisp_Object val, Lisp_Object name)
3858 {
3859 struct Lisp_Symbol *p = XBARE_SYMBOL (val);
3860 set_symbol_name (val, name);
3861 set_symbol_plist (val, Qnil);
3862 p->u.s.redirect = SYMBOL_PLAINVAL;
3863 SET_SYMBOL_VAL (p, Qunbound);
3864 set_symbol_function (val, Qnil);
3865 set_symbol_next (val, NULL);
3866 p->u.s.gcmarkbit = false;
3867 p->u.s.interned = SYMBOL_UNINTERNED;
3868 p->u.s.trapped_write = SYMBOL_UNTRAPPED_WRITE;
3869 p->u.s.declared_special = false;
3870 p->u.s.pinned = false;
3871 }
3872
3873 DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
3874 doc:
3875 )
3876 (Lisp_Object name)
3877 {
3878 Lisp_Object val;
3879
3880 CHECK_STRING (name);
3881
3882 MALLOC_BLOCK_INPUT;
3883
3884 if (symbol_free_list)
3885 {
3886 ASAN_UNPOISON_SYMBOL (symbol_free_list);
3887 XSETSYMBOL (val, symbol_free_list);
3888 symbol_free_list = symbol_free_list->u.s.next;
3889 }
3890 else
3891 {
3892 if (symbol_block_index == SYMBOL_BLOCK_SIZE)
3893 {
3894 struct symbol_block *new
3895 = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL);
3896 ASAN_POISON_SYMBOL_BLOCK (new);
3897 new->next = symbol_block;
3898 symbol_block = new;
3899 symbol_block_index = 0;
3900 }
3901
3902 ASAN_UNPOISON_SYMBOL (&symbol_block->symbols[symbol_block_index]);
3903 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
3904 symbol_block_index++;
3905 }
3906
3907 MALLOC_UNBLOCK_INPUT;
3908
3909 init_symbol (val, name);
3910 tally_consing (sizeof (struct Lisp_Symbol));
3911 symbols_consed++;
3912 return val;
3913 }
3914
3915
3916
3917 Lisp_Object
3918 make_misc_ptr (void *a)
3919 {
3920 struct Lisp_Misc_Ptr *p = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Misc_Ptr,
3921 PVEC_MISC_PTR);
3922 p->pointer = a;
3923 return make_lisp_ptr (p, Lisp_Vectorlike);
3924 }
3925
3926
3927 Lisp_Object
3928 build_symbol_with_pos (Lisp_Object symbol, Lisp_Object position)
3929 {
3930 Lisp_Object val;
3931 struct Lisp_Symbol_With_Pos *p
3932 = (struct Lisp_Symbol_With_Pos *) allocate_vector (2);
3933 XSETVECTOR (val, p);
3934 XSETPVECTYPESIZE (XVECTOR (val), PVEC_SYMBOL_WITH_POS, 2, 0);
3935 p->sym = symbol;
3936 p->pos = position;
3937
3938 return val;
3939 }
3940
3941
3942
3943 Lisp_Object
3944 build_overlay (bool front_advance, bool rear_advance,
3945 Lisp_Object plist)
3946 {
3947 struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, plist,
3948 PVEC_OVERLAY);
3949 Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike);
3950 struct itree_node *node = xmalloc (sizeof (*node));
3951 itree_node_init (node, front_advance, rear_advance, overlay);
3952 p->interval = node;
3953 p->buffer = NULL;
3954 set_overlay_plist (overlay, plist);
3955 return overlay;
3956 }
3957
3958 DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
3959 doc: )
3960 (void)
3961 {
3962 struct Lisp_Marker *p = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Marker,
3963 PVEC_MARKER);
3964 p->buffer = 0;
3965 p->bytepos = 0;
3966 p->charpos = 0;
3967 p->next = NULL;
3968 p->insertion_type = 0;
3969 p->need_adjustment = 0;
3970 return make_lisp_ptr (p, Lisp_Vectorlike);
3971 }
3972
3973
3974
3975
3976 Lisp_Object
3977 build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
3978 {
3979
3980 eassert (BUFFER_LIVE_P (buf));
3981
3982
3983 eassert (charpos <= bytepos);
3984
3985 struct Lisp_Marker *m = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Marker,
3986 PVEC_MARKER);
3987 m->buffer = buf;
3988 m->charpos = charpos;
3989 m->bytepos = bytepos;
3990 m->insertion_type = 0;
3991 m->need_adjustment = 0;
3992 m->next = BUF_MARKERS (buf);
3993 BUF_MARKERS (buf) = m;
3994 return make_lisp_ptr (m, Lisp_Vectorlike);
3995 }
3996
3997
3998
3999
4000
4001
4002
4003
4004 Lisp_Object
4005 make_event_array (ptrdiff_t nargs, Lisp_Object *args)
4006 {
4007 ptrdiff_t i;
4008
4009 for (i = 0; i < nargs; i++)
4010
4011
4012
4013 if (!FIXNUMP (args[i])
4014 || (XFIXNUM (args[i]) & ~(-CHAR_META)) >= 0200)
4015 return Fvector (nargs, args);
4016
4017
4018
4019 {
4020 Lisp_Object result;
4021
4022 result = Fmake_string (make_fixnum (nargs), make_fixnum (0), Qnil);
4023 for (i = 0; i < nargs; i++)
4024 {
4025 SSET (result, i, XFIXNUM (args[i]));
4026
4027 if (XFIXNUM (args[i]) & CHAR_META)
4028 SSET (result, i, SREF (result, i) | 0x80);
4029 }
4030
4031 return result;
4032 }
4033 }
4034
4035 #ifdef HAVE_MODULES
4036
4037 Lisp_Object
4038 make_user_ptr (void (*finalizer) (void *), void *p)
4039 {
4040 struct Lisp_User_Ptr *uptr
4041 = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_User_Ptr, PVEC_USER_PTR);
4042 uptr->finalizer = finalizer;
4043 uptr->p = p;
4044 return make_lisp_ptr (uptr, Lisp_Vectorlike);
4045 }
4046 #endif
4047
4048 static void
4049 init_finalizer_list (struct Lisp_Finalizer *head)
4050 {
4051 head->prev = head->next = head;
4052 }
4053
4054
4055
4056 static void
4057 finalizer_insert (struct Lisp_Finalizer *element,
4058 struct Lisp_Finalizer *finalizer)
4059 {
4060 eassert (finalizer->prev == NULL);
4061 eassert (finalizer->next == NULL);
4062 finalizer->next = element;
4063 finalizer->prev = element->prev;
4064 finalizer->prev->next = finalizer;
4065 element->prev = finalizer;
4066 }
4067
4068 static void
4069 unchain_finalizer (struct Lisp_Finalizer *finalizer)
4070 {
4071 if (finalizer->prev != NULL)
4072 {
4073 eassert (finalizer->next != NULL);
4074 finalizer->prev->next = finalizer->next;
4075 finalizer->next->prev = finalizer->prev;
4076 finalizer->prev = finalizer->next = NULL;
4077 }
4078 }
4079
4080 static void
4081 mark_finalizer_list (struct Lisp_Finalizer *head)
4082 {
4083 for (struct Lisp_Finalizer *finalizer = head->next;
4084 finalizer != head;
4085 finalizer = finalizer->next)
4086 {
4087 set_vectorlike_marked (&finalizer->header);
4088 mark_object (finalizer->function);
4089 }
4090 }
4091
4092
4093
4094
4095
4096 static void
4097 queue_doomed_finalizers (struct Lisp_Finalizer *dest,
4098 struct Lisp_Finalizer *src)
4099 {
4100 struct Lisp_Finalizer *finalizer = src->next;
4101 while (finalizer != src)
4102 {
4103 struct Lisp_Finalizer *next = finalizer->next;
4104 if (!vectorlike_marked_p (&finalizer->header)
4105 && !NILP (finalizer->function))
4106 {
4107 unchain_finalizer (finalizer);
4108 finalizer_insert (dest, finalizer);
4109 }
4110
4111 finalizer = next;
4112 }
4113 }
4114
4115 static Lisp_Object
4116 run_finalizer_handler (Lisp_Object args)
4117 {
4118 add_to_log ("finalizer failed: %S", args);
4119 return Qnil;
4120 }
4121
4122 static void
4123 run_finalizer_function (Lisp_Object function)
4124 {
4125 specpdl_ref count = SPECPDL_INDEX ();
4126 #ifdef HAVE_PDUMPER
4127 ++number_finalizers_run;
4128 #endif
4129
4130 specbind (Qinhibit_quit, Qt);
4131 internal_condition_case_1 (call0, function, Qt, run_finalizer_handler);
4132 unbind_to (count, Qnil);
4133 }
4134
4135 static void
4136 run_finalizers (struct Lisp_Finalizer *finalizers)
4137 {
4138 struct Lisp_Finalizer *finalizer;
4139 Lisp_Object function;
4140
4141 while (finalizers->next != finalizers)
4142 {
4143 finalizer = finalizers->next;
4144 unchain_finalizer (finalizer);
4145 function = finalizer->function;
4146 if (!NILP (function))
4147 {
4148 finalizer->function = Qnil;
4149 run_finalizer_function (function);
4150 }
4151 }
4152 }
4153
4154 DEFUN ("make-finalizer", Fmake_finalizer, Smake_finalizer, 1, 1, 0,
4155 doc:
4156
4157
4158
4159
4160 )
4161 (Lisp_Object function)
4162 {
4163 CHECK_TYPE (FUNCTIONP (function), Qfunctionp, function);
4164 struct Lisp_Finalizer *finalizer
4165 = ALLOCATE_PSEUDOVECTOR (struct Lisp_Finalizer, function, PVEC_FINALIZER);
4166 finalizer->function = function;
4167 finalizer->prev = finalizer->next = NULL;
4168 finalizer_insert (&finalizers, finalizer);
4169 return make_lisp_ptr (finalizer, Lisp_Vectorlike);
4170 }
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183 static bool
4184 vector_marked_p (const struct Lisp_Vector *v)
4185 {
4186 if (pdumper_object_p (v))
4187 {
4188
4189
4190 if (pdumper_cold_object_p (v))
4191 {
4192 eassert (PSEUDOVECTOR_TYPE (v) == PVEC_BOOL_VECTOR);
4193 return true;
4194 }
4195 return pdumper_marked_p (v);
4196 }
4197 return XVECTOR_MARKED_P (v);
4198 }
4199
4200 static void
4201 set_vector_marked (struct Lisp_Vector *v)
4202 {
4203 if (pdumper_object_p (v))
4204 {
4205 eassert (PSEUDOVECTOR_TYPE (v) != PVEC_BOOL_VECTOR);
4206 pdumper_set_marked (v);
4207 }
4208 else
4209 XMARK_VECTOR (v);
4210 }
4211
4212 static bool
4213 vectorlike_marked_p (const union vectorlike_header *header)
4214 {
4215 return vector_marked_p ((const struct Lisp_Vector *) header);
4216 }
4217
4218 static void
4219 set_vectorlike_marked (union vectorlike_header *header)
4220 {
4221 set_vector_marked ((struct Lisp_Vector *) header);
4222 }
4223
4224 static bool
4225 cons_marked_p (const struct Lisp_Cons *c)
4226 {
4227 return pdumper_object_p (c)
4228 ? pdumper_marked_p (c)
4229 : XCONS_MARKED_P (c);
4230 }
4231
4232 static void
4233 set_cons_marked (struct Lisp_Cons *c)
4234 {
4235 if (pdumper_object_p (c))
4236 pdumper_set_marked (c);
4237 else
4238 XMARK_CONS (c);
4239 }
4240
4241 static bool
4242 string_marked_p (const struct Lisp_String *s)
4243 {
4244 return pdumper_object_p (s)
4245 ? pdumper_marked_p (s)
4246 : XSTRING_MARKED_P (s);
4247 }
4248
4249 static void
4250 set_string_marked (struct Lisp_String *s)
4251 {
4252 if (pdumper_object_p (s))
4253 pdumper_set_marked (s);
4254 else
4255 XMARK_STRING (s);
4256 }
4257
4258 static bool
4259 symbol_marked_p (const struct Lisp_Symbol *s)
4260 {
4261 return pdumper_object_p (s)
4262 ? pdumper_marked_p (s)
4263 : s->u.s.gcmarkbit;
4264 }
4265
4266 static void
4267 set_symbol_marked (struct Lisp_Symbol *s)
4268 {
4269 if (pdumper_object_p (s))
4270 pdumper_set_marked (s);
4271 else
4272 s->u.s.gcmarkbit = true;
4273 }
4274
4275 static bool
4276 interval_marked_p (INTERVAL i)
4277 {
4278 return pdumper_object_p (i)
4279 ? pdumper_marked_p (i)
4280 : i->gcmarkbit;
4281 }
4282
4283 static void
4284 set_interval_marked (INTERVAL i)
4285 {
4286 if (pdumper_object_p (i))
4287 pdumper_set_marked (i);
4288 else
4289 i->gcmarkbit = true;
4290 }
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305 void
4306 memory_full (size_t nbytes)
4307 {
4308 if (!initialized)
4309 fatal ("memory exhausted");
4310
4311
4312 bool enough_free_memory = false;
4313 if (SPARE_MEMORY < nbytes)
4314 {
4315 void *p;
4316
4317 MALLOC_BLOCK_INPUT;
4318 p = malloc (SPARE_MEMORY);
4319 if (p)
4320 {
4321 free (p);
4322 enough_free_memory = true;
4323 }
4324 MALLOC_UNBLOCK_INPUT;
4325 }
4326
4327 if (! enough_free_memory)
4328 {
4329 Vmemory_full = Qt;
4330 consing_until_gc = min (consing_until_gc, memory_full_cons_threshold);
4331
4332
4333 for (int i = 0; i < ARRAYELTS (spare_memory); i++)
4334 if (spare_memory[i])
4335 {
4336 if (i == 0)
4337 free (spare_memory[i]);
4338 else if (i >= 1 && i <= 4)
4339 lisp_align_free (spare_memory[i]);
4340 else
4341 lisp_free (spare_memory[i]);
4342 spare_memory[i] = 0;
4343 }
4344 }
4345
4346
4347
4348 xsignal (Qnil, Vmemory_signal_data);
4349 }
4350
4351
4352
4353
4354
4355
4356
4357
4358 void
4359 refill_memory_reserve (void)
4360 {
4361 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
4362 if (spare_memory[0] == 0)
4363 spare_memory[0] = malloc (SPARE_MEMORY);
4364 if (spare_memory[1] == 0)
4365 spare_memory[1] = lisp_align_malloc (sizeof (struct cons_block),
4366 MEM_TYPE_SPARE);
4367 if (spare_memory[2] == 0)
4368 spare_memory[2] = lisp_align_malloc (sizeof (struct cons_block),
4369 MEM_TYPE_SPARE);
4370 if (spare_memory[3] == 0)
4371 spare_memory[3] = lisp_align_malloc (sizeof (struct cons_block),
4372 MEM_TYPE_SPARE);
4373 if (spare_memory[4] == 0)
4374 spare_memory[4] = lisp_align_malloc (sizeof (struct cons_block),
4375 MEM_TYPE_SPARE);
4376 if (spare_memory[5] == 0)
4377 spare_memory[5] = lisp_malloc (sizeof (struct string_block),
4378 false, MEM_TYPE_SPARE);
4379 if (spare_memory[6] == 0)
4380 spare_memory[6] = lisp_malloc (sizeof (struct string_block),
4381 false, MEM_TYPE_SPARE);
4382 if (spare_memory[0] && spare_memory[1] && spare_memory[5])
4383 Vmemory_full = Qnil;
4384 #endif
4385 }
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404 static void
4405 mem_init (void)
4406 {
4407 mem_z.left = mem_z.right = MEM_NIL;
4408 mem_z.parent = NULL;
4409 mem_z.color = MEM_BLACK;
4410 mem_z.start = mem_z.end = NULL;
4411 mem_root = MEM_NIL;
4412 }
4413
4414
4415
4416
4417
4418 static struct mem_node *
4419 mem_find (void *start)
4420 {
4421 struct mem_node *p;
4422
4423 if (start < min_heap_address || start > max_heap_address)
4424 return MEM_NIL;
4425
4426
4427 mem_z.start = start;
4428 mem_z.end = (char *) start + 1;
4429
4430 p = mem_root;
4431 while (start < p->start || start >= p->end)
4432 p = start < p->start ? p->left : p->right;
4433 return p;
4434 }
4435
4436
4437
4438
4439
4440
4441 static struct mem_node *
4442 mem_insert (void *start, void *end, enum mem_type type)
4443 {
4444 struct mem_node *c, *parent, *x;
4445
4446 if (min_heap_address == NULL || start < min_heap_address)
4447 min_heap_address = start;
4448 if (max_heap_address == NULL || end > max_heap_address)
4449 max_heap_address = end;
4450
4451
4452
4453
4454 c = mem_root;
4455 parent = NULL;
4456
4457 while (c != MEM_NIL)
4458 {
4459 parent = c;
4460 c = start < c->start ? c->left : c->right;
4461 }
4462
4463
4464 #ifdef GC_MALLOC_CHECK
4465 x = malloc (sizeof *x);
4466 if (x == NULL)
4467 emacs_abort ();
4468 #else
4469 x = xmalloc (sizeof *x);
4470 #endif
4471 x->start = start;
4472 x->end = end;
4473 x->type = type;
4474 x->parent = parent;
4475 x->left = x->right = MEM_NIL;
4476 x->color = MEM_RED;
4477
4478
4479 if (parent)
4480 {
4481 if (start < parent->start)
4482 parent->left = x;
4483 else
4484 parent->right = x;
4485 }
4486 else
4487 mem_root = x;
4488
4489
4490 mem_insert_fixup (x);
4491
4492 return x;
4493 }
4494
4495
4496
4497
4498
4499 static void
4500 mem_insert_fixup (struct mem_node *x)
4501 {
4502 while (x != mem_root && x->parent->color == MEM_RED)
4503 {
4504
4505
4506
4507 if (x->parent == x->parent->parent->left)
4508 {
4509
4510
4511 struct mem_node *y = x->parent->parent->right;
4512
4513 if (y->color == MEM_RED)
4514 {
4515
4516
4517
4518 x->parent->color = MEM_BLACK;
4519 y->color = MEM_BLACK;
4520 x->parent->parent->color = MEM_RED;
4521 x = x->parent->parent;
4522 }
4523 else
4524 {
4525
4526
4527 if (x == x->parent->right)
4528 {
4529 x = x->parent;
4530 mem_rotate_left (x);
4531 }
4532
4533 x->parent->color = MEM_BLACK;
4534 x->parent->parent->color = MEM_RED;
4535 mem_rotate_right (x->parent->parent);
4536 }
4537 }
4538 else
4539 {
4540
4541 struct mem_node *y = x->parent->parent->left;
4542
4543 if (y->color == MEM_RED)
4544 {
4545 x->parent->color = MEM_BLACK;
4546 y->color = MEM_BLACK;
4547 x->parent->parent->color = MEM_RED;
4548 x = x->parent->parent;
4549 }
4550 else
4551 {
4552 if (x == x->parent->left)
4553 {
4554 x = x->parent;
4555 mem_rotate_right (x);
4556 }
4557
4558 x->parent->color = MEM_BLACK;
4559 x->parent->parent->color = MEM_RED;
4560 mem_rotate_left (x->parent->parent);
4561 }
4562 }
4563 }
4564
4565
4566
4567 mem_root->color = MEM_BLACK;
4568 }
4569
4570
4571
4572
4573
4574
4575
4576
4577 static void
4578 mem_rotate_left (struct mem_node *x)
4579 {
4580 struct mem_node *y;
4581
4582
4583 y = x->right;
4584 x->right = y->left;
4585 if (y->left != MEM_NIL)
4586 y->left->parent = x;
4587
4588
4589 if (y != MEM_NIL)
4590 y->parent = x->parent;
4591
4592
4593 if (x->parent)
4594 {
4595 if (x == x->parent->left)
4596 x->parent->left = y;
4597 else
4598 x->parent->right = y;
4599 }
4600 else
4601 mem_root = y;
4602
4603
4604 y->left = x;
4605 if (x != MEM_NIL)
4606 x->parent = y;
4607 }
4608
4609
4610
4611
4612
4613
4614
4615
4616 static void
4617 mem_rotate_right (struct mem_node *x)
4618 {
4619 struct mem_node *y = x->left;
4620
4621 x->left = y->right;
4622 if (y->right != MEM_NIL)
4623 y->right->parent = x;
4624
4625 if (y != MEM_NIL)
4626 y->parent = x->parent;
4627 if (x->parent)
4628 {
4629 if (x == x->parent->right)
4630 x->parent->right = y;
4631 else
4632 x->parent->left = y;
4633 }
4634 else
4635 mem_root = y;
4636
4637 y->right = x;
4638 if (x != MEM_NIL)
4639 x->parent = y;
4640 }
4641
4642
4643
4644
4645 static void
4646 mem_delete (struct mem_node *z)
4647 {
4648 struct mem_node *x, *y;
4649
4650 if (!z || z == MEM_NIL)
4651 return;
4652
4653 if (z->left == MEM_NIL || z->right == MEM_NIL)
4654 y = z;
4655 else
4656 {
4657 y = z->right;
4658 while (y->left != MEM_NIL)
4659 y = y->left;
4660 }
4661
4662 if (y->left != MEM_NIL)
4663 x = y->left;
4664 else
4665 x = y->right;
4666
4667 x->parent = y->parent;
4668 if (y->parent)
4669 {
4670 if (y == y->parent->left)
4671 y->parent->left = x;
4672 else
4673 y->parent->right = x;
4674 }
4675 else
4676 mem_root = x;
4677
4678 if (y != z)
4679 {
4680 z->start = y->start;
4681 z->end = y->end;
4682 z->type = y->type;
4683 }
4684
4685 if (y->color == MEM_BLACK)
4686 mem_delete_fixup (x);
4687
4688 #ifdef GC_MALLOC_CHECK
4689 free (y);
4690 #else
4691 xfree (y);
4692 #endif
4693 }
4694
4695
4696
4697
4698
4699 static void
4700 mem_delete_fixup (struct mem_node *x)
4701 {
4702 while (x != mem_root && x->color == MEM_BLACK)
4703 {
4704 if (x == x->parent->left)
4705 {
4706 struct mem_node *w = x->parent->right;
4707
4708 if (w->color == MEM_RED)
4709 {
4710 w->color = MEM_BLACK;
4711 x->parent->color = MEM_RED;
4712 mem_rotate_left (x->parent);
4713 w = x->parent->right;
4714 }
4715
4716 if (w->left->color == MEM_BLACK && w->right->color == MEM_BLACK)
4717 {
4718 w->color = MEM_RED;
4719 x = x->parent;
4720 }
4721 else
4722 {
4723 if (w->right->color == MEM_BLACK)
4724 {
4725 w->left->color = MEM_BLACK;
4726 w->color = MEM_RED;
4727 mem_rotate_right (w);
4728 w = x->parent->right;
4729 }
4730 w->color = x->parent->color;
4731 x->parent->color = MEM_BLACK;
4732 w->right->color = MEM_BLACK;
4733 mem_rotate_left (x->parent);
4734 x = mem_root;
4735 }
4736 }
4737 else
4738 {
4739 struct mem_node *w = x->parent->left;
4740
4741 if (w->color == MEM_RED)
4742 {
4743 w->color = MEM_BLACK;
4744 x->parent->color = MEM_RED;
4745 mem_rotate_right (x->parent);
4746 w = x->parent->left;
4747 }
4748
4749 if (w->right->color == MEM_BLACK && w->left->color == MEM_BLACK)
4750 {
4751 w->color = MEM_RED;
4752 x = x->parent;
4753 }
4754 else
4755 {
4756 if (w->left->color == MEM_BLACK)
4757 {
4758 w->right->color = MEM_BLACK;
4759 w->color = MEM_RED;
4760 mem_rotate_left (w);
4761 w = x->parent->left;
4762 }
4763
4764 w->color = x->parent->color;
4765 x->parent->color = MEM_BLACK;
4766 w->left->color = MEM_BLACK;
4767 mem_rotate_right (x->parent);
4768 x = mem_root;
4769 }
4770 }
4771 }
4772
4773 x->color = MEM_BLACK;
4774 }
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786 static struct Lisp_String *
4787 live_string_holding (struct mem_node *m, void *p)
4788 {
4789 eassert (m->type == MEM_TYPE_STRING);
4790 #if GC_ASAN_POISON_OBJECTS
4791 if (__asan_address_is_poisoned (p))
4792 return NULL;
4793 #endif
4794
4795 struct string_block *b = m->start;
4796 char *cp = p;
4797 ptrdiff_t offset = cp - (char *) &b->strings[0];
4798
4799
4800
4801 if (0 <= offset && offset < sizeof b->strings)
4802 {
4803 ptrdiff_t off = offset % sizeof b->strings[0];
4804 if (off == Lisp_String
4805 || off == 0
4806 || off == offsetof (struct Lisp_String, u.s.size_byte)
4807 || off == offsetof (struct Lisp_String, u.s.intervals)
4808 || off == offsetof (struct Lisp_String, u.s.data))
4809 {
4810 struct Lisp_String *s = p = cp -= off;
4811 #if GC_ASAN_POISON_OBJECTS
4812 if (__asan_region_is_poisoned (s, sizeof (*s)))
4813 return NULL;
4814 #endif
4815 if (s->u.s.data)
4816 return s;
4817 }
4818 }
4819 return NULL;
4820 }
4821
4822 static bool
4823 live_string_p (struct mem_node *m, void *p)
4824 {
4825 return live_string_holding (m, p) == p;
4826 }
4827
4828
4829
4830
4831
4832 static struct Lisp_Cons *
4833 live_cons_holding (struct mem_node *m, void *p)
4834 {
4835 eassert (m->type == MEM_TYPE_CONS);
4836 #if GC_ASAN_POISON_OBJECTS
4837 if (__asan_address_is_poisoned (p))
4838 return NULL;
4839 #endif
4840
4841 struct cons_block *b = m->start;
4842 char *cp = p;
4843 ptrdiff_t offset = cp - (char *) &b->conses[0];
4844
4845
4846
4847
4848 if (0 <= offset && offset < sizeof b->conses
4849 && (b != cons_block
4850 || offset / sizeof b->conses[0] < cons_block_index))
4851 {
4852 ptrdiff_t off = offset % sizeof b->conses[0];
4853 if (off == Lisp_Cons
4854 || off == 0
4855 || off == offsetof (struct Lisp_Cons, u.s.u.cdr))
4856 {
4857 struct Lisp_Cons *s = p = cp -= off;
4858 #if GC_ASAN_POISON_OBJECTS
4859 if (__asan_region_is_poisoned (s, sizeof (*s)))
4860 return NULL;
4861 #endif
4862 if (!deadp (s->u.s.car))
4863 return s;
4864 }
4865 }
4866 return NULL;
4867 }
4868
4869 static bool
4870 live_cons_p (struct mem_node *m, void *p)
4871 {
4872 return live_cons_holding (m, p) == p;
4873 }
4874
4875
4876
4877
4878
4879
4880 static struct Lisp_Symbol *
4881 live_symbol_holding (struct mem_node *m, void *p)
4882 {
4883 eassert (m->type == MEM_TYPE_SYMBOL);
4884 #if GC_ASAN_POISON_OBJECTS
4885 if (__asan_address_is_poisoned (p))
4886 return NULL;
4887 #endif
4888 struct symbol_block *b = m->start;
4889 char *cp = p;
4890 ptrdiff_t offset = cp - (char *) &b->symbols[0];
4891
4892
4893
4894
4895 if (0 <= offset && offset < sizeof b->symbols
4896 && (b != symbol_block
4897 || offset / sizeof b->symbols[0] < symbol_block_index))
4898 {
4899 ptrdiff_t off = offset % sizeof b->symbols[0];
4900 if (off == Lisp_Symbol
4901
4902
4903
4904 || (Lisp_Symbol != 0 && off == 0)
4905
4906 || off == offsetof (struct Lisp_Symbol, u.s.name)
4907 || off == offsetof (struct Lisp_Symbol, u.s.val)
4908 || off == offsetof (struct Lisp_Symbol, u.s.function)
4909 || off == offsetof (struct Lisp_Symbol, u.s.plist)
4910 || off == offsetof (struct Lisp_Symbol, u.s.next))
4911 {
4912 struct Lisp_Symbol *s = p = cp -= off;
4913 #if GC_ASAN_POISON_OBJECTS
4914 if (__asan_region_is_poisoned (s, sizeof (*s)))
4915 return NULL;
4916 #endif
4917 if (!deadp (s->u.s.function))
4918 return s;
4919 }
4920 }
4921 return NULL;
4922 }
4923
4924 static bool
4925 live_symbol_p (struct mem_node *m, void *p)
4926 {
4927 return live_symbol_holding (m, p) == p;
4928 }
4929
4930
4931
4932
4933
4934
4935 static struct Lisp_Float *
4936 live_float_holding (struct mem_node *m, void *p)
4937 {
4938 eassert (m->type == MEM_TYPE_FLOAT);
4939 #if GC_ASAN_POISON_OBJECTS
4940 if (__asan_address_is_poisoned (p))
4941 return NULL;
4942 #endif
4943
4944 struct float_block *b = m->start;
4945 char *cp = p;
4946 ptrdiff_t offset = cp - (char *) &b->floats[0];
4947
4948
4949
4950
4951 if (0 <= offset && offset < sizeof b->floats)
4952 {
4953 int off = offset % sizeof b->floats[0];
4954 if ((off == Lisp_Float || off == 0)
4955 && (b != float_block
4956 || offset / sizeof b->floats[0] < float_block_index))
4957 {
4958 struct Lisp_Float *f = (struct Lisp_Float *) (cp - off);
4959 #if GC_ASAN_POISON_OBJECTS
4960 if (__asan_region_is_poisoned (f, sizeof (*f)))
4961 return NULL;
4962 #endif
4963 return f;
4964 }
4965 }
4966 return NULL;
4967 }
4968
4969 static bool
4970 live_float_p (struct mem_node *m, void *p)
4971 {
4972 return live_float_holding (m, p) == p;
4973 }
4974
4975
4976
4977 static struct Lisp_Vector *
4978 live_vector_pointer (struct Lisp_Vector *vector, void *p)
4979 {
4980 void *vvector = vector;
4981 char *cvector = vvector;
4982 char *cp = p;
4983 ptrdiff_t offset = cp - cvector;
4984 return ((offset == Lisp_Vectorlike
4985 || offset == 0
4986 || (sizeof vector->header <= offset
4987 && offset < vector_nbytes (vector)
4988 && (! (vector->header.size & PSEUDOVECTOR_FLAG)
4989 ? (offsetof (struct Lisp_Vector, contents) <= offset
4990 && (((offset - offsetof (struct Lisp_Vector, contents))
4991 % word_size)
4992 == 0))
4993
4994
4995
4996 : (! PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)
4997 || offset == offsetof (struct Lisp_Bool_Vector, size)
4998 || (offsetof (struct Lisp_Bool_Vector, data) <= offset
4999 && (((offset
5000 - offsetof (struct Lisp_Bool_Vector, data))
5001 % sizeof (bits_word))
5002 == 0))))))
5003 ? vector : NULL);
5004 }
5005
5006
5007
5008
5009
5010 static struct Lisp_Vector *
5011 live_large_vector_holding (struct mem_node *m, void *p)
5012 {
5013 eassert (m->type == MEM_TYPE_VECTORLIKE);
5014 return live_vector_pointer (large_vector_vec (m->start), p);
5015 }
5016
5017 static bool
5018 live_large_vector_p (struct mem_node *m, void *p)
5019 {
5020 return live_large_vector_holding (m, p) == p;
5021 }
5022
5023
5024
5025
5026
5027 static struct Lisp_Vector *
5028 live_small_vector_holding (struct mem_node *m, void *p)
5029 {
5030 eassert (m->type == MEM_TYPE_VECTOR_BLOCK);
5031 struct Lisp_Vector *vp = p;
5032 struct vector_block *block = m->start;
5033 struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data;
5034
5035
5036
5037
5038
5039
5040 while (VECTOR_IN_BLOCK (vector, block) && vector <= vp)
5041 {
5042 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
5043 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
5044 return live_vector_pointer (vector, vp);
5045 vector = next;
5046 }
5047 return NULL;
5048 }
5049
5050 static bool
5051 live_small_vector_p (struct mem_node *m, void *p)
5052 {
5053 return live_small_vector_holding (m, p) == p;
5054 }
5055
5056
5057
5058
5059 static void
5060 mark_maybe_pointer (void *p, bool symbol_only)
5061 {
5062 struct mem_node *m;
5063
5064 #if USE_VALGRIND
5065 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
5066 #endif
5067
5068
5069
5070
5071
5072
5073 if (pdumper_object_p (p))
5074 {
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084 uintptr_t mask = VALMASK & UINTPTR_MAX;
5085 uintptr_t masked_p = (uintptr_t) p & mask;
5086 void *po = (void *) masked_p;
5087 char *cp = p;
5088 char *cpo = po;
5089
5090
5091
5092 int type = pdumper_find_object_type (po);
5093 if (pdumper_valid_object_type_p (type)
5094 && (!USE_LSB_TAG || p == po || cp - cpo == type))
5095 {
5096 if (type == Lisp_Symbol)
5097 mark_object (make_lisp_symbol (po));
5098 else if (!symbol_only)
5099 mark_object (make_lisp_ptr (po, type));
5100 }
5101 return;
5102 }
5103
5104 m = mem_find (p);
5105 if (m != MEM_NIL)
5106 {
5107 Lisp_Object obj;
5108
5109 switch (m->type)
5110 {
5111 case MEM_TYPE_NON_LISP:
5112 case MEM_TYPE_SPARE:
5113
5114 return;
5115
5116 case MEM_TYPE_CONS:
5117 {
5118 if (symbol_only)
5119 return;
5120 struct Lisp_Cons *h = live_cons_holding (m, p);
5121 if (!h)
5122 return;
5123 obj = make_lisp_ptr (h, Lisp_Cons);
5124 }
5125 break;
5126
5127 case MEM_TYPE_STRING:
5128 {
5129 if (symbol_only)
5130 return;
5131 struct Lisp_String *h = live_string_holding (m, p);
5132 if (!h)
5133 return;
5134 obj = make_lisp_ptr (h, Lisp_String);
5135 }
5136 break;
5137
5138 case MEM_TYPE_SYMBOL:
5139 {
5140 struct Lisp_Symbol *h = live_symbol_holding (m, p);
5141 if (!h)
5142 return;
5143 obj = make_lisp_symbol (h);
5144 }
5145 break;
5146
5147 case MEM_TYPE_FLOAT:
5148 {
5149 if (symbol_only)
5150 return;
5151 struct Lisp_Float *h = live_float_holding (m, p);
5152 if (!h)
5153 return;
5154 obj = make_lisp_ptr (h, Lisp_Float);
5155 }
5156 break;
5157
5158 case MEM_TYPE_VECTORLIKE:
5159 {
5160 if (symbol_only)
5161 return;
5162 struct Lisp_Vector *h = live_large_vector_holding (m, p);
5163 if (!h)
5164 return;
5165 obj = make_lisp_ptr (h, Lisp_Vectorlike);
5166 }
5167 break;
5168
5169 case MEM_TYPE_VECTOR_BLOCK:
5170 {
5171 if (symbol_only)
5172 return;
5173 struct Lisp_Vector *h = live_small_vector_holding (m, p);
5174 if (!h)
5175 return;
5176 obj = make_lisp_ptr (h, Lisp_Vectorlike);
5177 }
5178 break;
5179
5180 default:
5181 emacs_abort ();
5182 }
5183
5184 mark_object (obj);
5185 }
5186 }
5187
5188
5189
5190
5191
5192 #define GC_POINTER_ALIGNMENT alignof (void *)
5193
5194
5195
5196
5197 void ATTRIBUTE_NO_SANITIZE_ADDRESS
5198 mark_memory (void const *start, void const *end)
5199 {
5200 char const *pp;
5201
5202
5203
5204 if (end < start)
5205 {
5206 void const *tem = start;
5207 start = end;
5208 end = tem;
5209 }
5210
5211 eassert (((uintptr_t) start) % GC_POINTER_ALIGNMENT == 0);
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231 for (pp = start; (void const *) pp < end; pp += GC_POINTER_ALIGNMENT)
5232 {
5233 void *p = *(void *const *) pp;
5234 mark_maybe_pointer (p, false);
5235
5236
5237
5238
5239
5240
5241 intptr_t ip;
5242 ckd_add (&ip, (intptr_t) p, (intptr_t) lispsym);
5243 mark_maybe_pointer ((void *) ip, true);
5244 }
5245 }
5246
5247 #ifndef HAVE___BUILTIN_UNWIND_INIT
5248
5249 # ifdef GC_SETJMP_WORKS
5250 static void
5251 test_setjmp (void)
5252 {
5253 }
5254 # else
5255
5256 static bool setjmp_tested_p;
5257 static int longjmps_done;
5258
5259 # define SETJMP_WILL_LIKELY_WORK "\
5260 \n\
5261 Emacs garbage collector has been changed to use conservative stack\n\
5262 marking. Emacs has determined that the method it uses to do the\n\
5263 marking will likely work on your system, but this isn't sure.\n\
5264 \n\
5265 If you are a system-programmer, or can get the help of a local wizard\n\
5266 who is, please take a look at the function mark_c_stack in alloc.c, and\n\
5267 verify that the methods used are appropriate for your system.\n\
5268 \n\
5269 Please mail the result to <emacs-devel@gnu.org>.\n\
5270 "
5271
5272 # define SETJMP_WILL_NOT_WORK "\
5273 \n\
5274 Emacs garbage collector has been changed to use conservative stack\n\
5275 marking. Emacs has determined that the default method it uses to do the\n\
5276 marking will not work on your system. We will need a system-dependent\n\
5277 solution for your system.\n\
5278 \n\
5279 Please take a look at the function mark_c_stack in alloc.c, and\n\
5280 try to find a way to make it work on your system.\n\
5281 \n\
5282 Note that you may get false negatives, depending on the compiler.\n\
5283 In particular, you need to use -O with GCC for this test.\n\
5284 \n\
5285 Please mail the result to <emacs-devel@gnu.org>.\n\
5286 "
5287
5288
5289
5290
5291
5292
5293
5294
5295 static void
5296 test_setjmp (void)
5297 {
5298 if (setjmp_tested_p)
5299 return;
5300 setjmp_tested_p = true;
5301 char buf[10];
5302 register int x;
5303 sys_jmp_buf jbuf;
5304
5305
5306 sprintf (buf, "1");
5307 x = strlen (buf);
5308 x = 2 * x - 1;
5309
5310 sys_setjmp (jbuf);
5311 if (longjmps_done == 1)
5312 {
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323 if (x == 1)
5324 fputs (SETJMP_WILL_LIKELY_WORK, stderr);
5325 else
5326 {
5327 fputs (SETJMP_WILL_NOT_WORK, stderr);
5328 exit (1);
5329 }
5330 }
5331
5332 ++longjmps_done;
5333 x = 2;
5334 if (longjmps_done == 1)
5335 sys_longjmp (jbuf, 1);
5336 }
5337 # endif
5338 #endif
5339
5340
5341
5342 typedef union
5343 {
5344
5345
5346 Lisp_Object o;
5347 void *p;
5348 #ifndef HAVE___BUILTIN_UNWIND_INIT
5349 sys_jmp_buf j;
5350 char c;
5351 #endif
5352 } stacktop_sentry;
5353
5354
5355
5356
5357
5358 #ifdef HAVE___BUILTIN_UNWIND_INIT
5359 # define SET_STACK_TOP_ADDRESS(p) \
5360 stacktop_sentry sentry; \
5361 *(p) = NEAR_STACK_TOP (&sentry)
5362 #else
5363 # define SET_STACK_TOP_ADDRESS(p) \
5364 stacktop_sentry sentry; \
5365 test_setjmp (); \
5366 sys_setjmp (sentry.j); \
5367 *(p) = NEAR_STACK_TOP (&sentry + (stack_bottom < &sentry.c))
5368 #endif
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411 void
5412 mark_c_stack (char const *bottom, char const *end)
5413 {
5414
5415
5416
5417 mark_memory (bottom, end);
5418
5419
5420
5421 #ifdef GC_MARK_SECONDARY_STACK
5422 GC_MARK_SECONDARY_STACK ();
5423 #endif
5424 }
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451 NO_INLINE void
5452 flush_stack_call_func1 (void (*func) (void *arg), void *arg)
5453 {
5454 void *end;
5455 struct thread_state *self = current_thread;
5456 SET_STACK_TOP_ADDRESS (&end);
5457 self->stack_top = end;
5458 func (arg);
5459 eassert (current_thread == self);
5460 }
5461
5462
5463 static int
5464 valid_pointer_p (void *p)
5465 {
5466 #ifdef WINDOWSNT
5467 return w32_valid_pointer_p (p, 16);
5468 #else
5469
5470 if (ADDRESS_SANITIZER)
5471 return p ? -1 : 0;
5472
5473 int fd[2];
5474 static int under_rr_state;
5475
5476 if (!under_rr_state)
5477 under_rr_state = getenv ("RUNNING_UNDER_RR") ? -1 : 1;
5478 if (under_rr_state < 0)
5479 return under_rr_state;
5480
5481
5482
5483
5484
5485
5486 if (emacs_pipe (fd) == 0)
5487 {
5488 bool valid = emacs_write (fd[1], p, 16) == 16;
5489 emacs_close (fd[1]);
5490 emacs_close (fd[0]);
5491 return valid;
5492 }
5493
5494 return -1;
5495 #endif
5496 }
5497
5498
5499
5500
5501
5502
5503 int
5504 valid_lisp_object_p (Lisp_Object obj)
5505 {
5506 if (FIXNUMP (obj))
5507 return 1;
5508
5509 void *p = XPNTR (obj);
5510 if (PURE_P (p))
5511 return 1;
5512
5513 if (BARE_SYMBOL_P (obj) && c_symbol_p (p))
5514 return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0;
5515
5516 if (p == &buffer_defaults || p == &buffer_local_symbols)
5517 return 2;
5518
5519 if (pdumper_object_p (p))
5520 return pdumper_object_p_precise (p) ? 1 : 0;
5521
5522 struct mem_node *m = mem_find (p);
5523
5524 if (m == MEM_NIL)
5525 {
5526 int valid = valid_pointer_p (p);
5527 if (valid <= 0)
5528 return valid;
5529
5530
5531 if (SUBRP (obj) || STRINGP (obj) || CONSP (obj))
5532 return 1;
5533
5534 return 0;
5535 }
5536
5537 switch (m->type)
5538 {
5539 case MEM_TYPE_NON_LISP:
5540 case MEM_TYPE_SPARE:
5541 return 0;
5542
5543 case MEM_TYPE_CONS:
5544 return live_cons_p (m, p);
5545
5546 case MEM_TYPE_STRING:
5547 return live_string_p (m, p);
5548
5549 case MEM_TYPE_SYMBOL:
5550 return live_symbol_p (m, p);
5551
5552 case MEM_TYPE_FLOAT:
5553 return live_float_p (m, p);
5554
5555 case MEM_TYPE_VECTORLIKE:
5556 return live_large_vector_p (m, p);
5557
5558 case MEM_TYPE_VECTOR_BLOCK:
5559 return live_small_vector_p (m, p);
5560
5561 default:
5562 break;
5563 }
5564
5565 return 0;
5566 }
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583 static void *
5584 pure_alloc (size_t size, int type)
5585 {
5586 void *result;
5587 static bool pure_overflow_warned = false;
5588
5589 again:
5590 if (type >= 0)
5591 {
5592
5593
5594 result = pointer_align (purebeg + pure_bytes_used_lisp, LISP_ALIGNMENT);
5595 pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size;
5596 }
5597 else
5598 {
5599
5600
5601 ptrdiff_t unaligned_non_lisp = pure_bytes_used_non_lisp + size;
5602 char *unaligned = purebeg + pure_size - unaligned_non_lisp;
5603 int decr = (intptr_t) unaligned & (-1 - type);
5604 pure_bytes_used_non_lisp = unaligned_non_lisp + decr;
5605 result = unaligned - decr;
5606 }
5607 pure_bytes_used = pure_bytes_used_lisp + pure_bytes_used_non_lisp;
5608
5609 if (pure_bytes_used <= pure_size)
5610 return result;
5611
5612 if (!pure_overflow_warned)
5613 {
5614 message ("Pure Lisp storage overflowed");
5615 pure_overflow_warned = true;
5616 }
5617
5618
5619
5620
5621 int small_amount = 10000;
5622 eassert (size <= small_amount - LISP_ALIGNMENT);
5623 purebeg = xzalloc (small_amount);
5624 pure_size = small_amount;
5625 pure_bytes_used_before_overflow += pure_bytes_used - size;
5626 pure_bytes_used = 0;
5627 pure_bytes_used_lisp = pure_bytes_used_non_lisp = 0;
5628
5629
5630
5631 garbage_collection_inhibited++;
5632 goto again;
5633 }
5634
5635
5636
5637 void
5638 check_pure_size (void)
5639 {
5640 if (pure_bytes_used_before_overflow)
5641 message (("emacs:0:Pure Lisp storage overflow (approx. %jd"
5642 " bytes needed)"),
5643 pure_bytes_used + pure_bytes_used_before_overflow);
5644 }
5645
5646
5647
5648
5649
5650 static char *
5651 find_string_data_in_pure (const char *data, ptrdiff_t nbytes)
5652 {
5653 int i;
5654 ptrdiff_t skip, bm_skip[256], last_char_skip, infinity, start, start_max;
5655 const unsigned char *p;
5656 char *non_lisp_beg;
5657
5658 if (pure_bytes_used_non_lisp <= nbytes)
5659 return NULL;
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669 #if defined __i386__ \
5670 && defined HAVE_ANDROID \
5671 && !defined ANDROID_STUBIFY \
5672 && !defined (__clang__)
5673 if ((intptr_t) data & 15)
5674 return NULL;
5675 #endif
5676
5677
5678 skip = nbytes + 1;
5679 for (i = 0; i < 256; i++)
5680 bm_skip[i] = skip;
5681
5682 p = (const unsigned char *) data;
5683 while (--skip > 0)
5684 bm_skip[*p++] = skip;
5685
5686 last_char_skip = bm_skip['\0'];
5687
5688 non_lisp_beg = purebeg + pure_size - pure_bytes_used_non_lisp;
5689 start_max = pure_bytes_used_non_lisp - (nbytes + 1);
5690
5691
5692
5693 infinity = pure_bytes_used_non_lisp + 1;
5694 bm_skip['\0'] = infinity;
5695
5696 p = (const unsigned char *) non_lisp_beg + nbytes;
5697 start = 0;
5698 do
5699 {
5700
5701 do
5702 {
5703 start += bm_skip[*(p + start)];
5704 }
5705 while (start <= start_max);
5706
5707 if (start < infinity)
5708
5709 return NULL;
5710
5711
5712
5713 start -= infinity;
5714
5715
5716 if (memcmp (data, non_lisp_beg + start, nbytes) == 0)
5717
5718 return non_lisp_beg + start;
5719
5720 start += last_char_skip;
5721 }
5722 while (start <= start_max);
5723
5724 return NULL;
5725 }
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736 Lisp_Object
5737 make_pure_string (const char *data,
5738 ptrdiff_t nchars, ptrdiff_t nbytes, bool multibyte)
5739 {
5740 Lisp_Object string;
5741 struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String);
5742 s->u.s.data = (unsigned char *) find_string_data_in_pure (data, nbytes);
5743 if (s->u.s.data == NULL)
5744 {
5745 s->u.s.data = pure_alloc (nbytes + 1, -1);
5746 memcpy (s->u.s.data, data, nbytes);
5747 s->u.s.data[nbytes] = '\0';
5748 }
5749 s->u.s.size = nchars;
5750 s->u.s.size_byte = multibyte ? nbytes : -1;
5751 s->u.s.intervals = NULL;
5752 XSETSTRING (string, s);
5753 return string;
5754 }
5755
5756
5757
5758
5759 Lisp_Object
5760 make_pure_c_string (const char *data, ptrdiff_t nchars)
5761 {
5762 Lisp_Object string;
5763 struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String);
5764 s->u.s.size = nchars;
5765 s->u.s.size_byte = -2;
5766 s->u.s.data = (unsigned char *) data;
5767 s->u.s.intervals = NULL;
5768 XSETSTRING (string, s);
5769 return string;
5770 }
5771
5772 static Lisp_Object purecopy (Lisp_Object obj);
5773
5774
5775
5776
5777 Lisp_Object
5778 pure_cons (Lisp_Object car, Lisp_Object cdr)
5779 {
5780 Lisp_Object new;
5781 struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons);
5782 XSETCONS (new, p);
5783 XSETCAR (new, purecopy (car));
5784 XSETCDR (new, purecopy (cdr));
5785 return new;
5786 }
5787
5788
5789
5790
5791 static Lisp_Object
5792 make_pure_float (double num)
5793 {
5794 Lisp_Object new;
5795 struct Lisp_Float *p = pure_alloc (sizeof *p, Lisp_Float);
5796 XSETFLOAT (new, p);
5797 XFLOAT_INIT (new, num);
5798 return new;
5799 }
5800
5801
5802
5803
5804 static Lisp_Object
5805 make_pure_bignum (Lisp_Object value)
5806 {
5807 mpz_t const *n = xbignum_val (value);
5808 size_t i, nlimbs = mpz_size (*n);
5809 size_t nbytes = nlimbs * sizeof (mp_limb_t);
5810 mp_limb_t *pure_limbs;
5811 mp_size_t new_size;
5812
5813 struct Lisp_Bignum *b = pure_alloc (sizeof *b, Lisp_Vectorlike);
5814 XSETPVECTYPESIZE (b, PVEC_BIGNUM, 0, VECSIZE (struct Lisp_Bignum));
5815
5816 int limb_alignment = alignof (mp_limb_t);
5817 pure_limbs = pure_alloc (nbytes, - limb_alignment);
5818 for (i = 0; i < nlimbs; ++i)
5819 pure_limbs[i] = mpz_getlimbn (*n, i);
5820
5821 new_size = nlimbs;
5822 if (mpz_sgn (*n) < 0)
5823 new_size = -new_size;
5824
5825 mpz_roinit_n (b->value, pure_limbs, new_size);
5826
5827 return make_lisp_ptr (b, Lisp_Vectorlike);
5828 }
5829
5830
5831
5832
5833 static Lisp_Object
5834 make_pure_vector (ptrdiff_t len)
5835 {
5836 Lisp_Object new;
5837 size_t size = header_size + len * word_size;
5838 struct Lisp_Vector *p = pure_alloc (size, Lisp_Vectorlike);
5839 XSETVECTOR (new, p);
5840 XVECTOR (new)->header.size = len;
5841 return new;
5842 }
5843
5844
5845
5846 static struct Lisp_Hash_Table *
5847 purecopy_hash_table (struct Lisp_Hash_Table *table)
5848 {
5849 eassert (NILP (table->weak));
5850 eassert (table->purecopy);
5851
5852 struct Lisp_Hash_Table *pure = pure_alloc (sizeof *pure, Lisp_Vectorlike);
5853 struct hash_table_test pure_test = table->test;
5854
5855
5856 pure_test.name = purecopy (table->test.name);
5857 pure_test.user_hash_function = purecopy (table->test.user_hash_function);
5858 pure_test.user_cmp_function = purecopy (table->test.user_cmp_function);
5859
5860 pure->header = table->header;
5861 pure->weak = purecopy (Qnil);
5862 pure->hash = purecopy (table->hash);
5863 pure->next = purecopy (table->next);
5864 pure->index = purecopy (table->index);
5865 pure->count = table->count;
5866 pure->next_free = table->next_free;
5867 pure->purecopy = table->purecopy;
5868 eassert (!pure->mutable);
5869 pure->rehash_threshold = table->rehash_threshold;
5870 pure->rehash_size = table->rehash_size;
5871 pure->key_and_value = purecopy (table->key_and_value);
5872 pure->test = pure_test;
5873
5874 return pure;
5875 }
5876
5877 DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
5878 doc:
5879
5880 )
5881 (register Lisp_Object obj)
5882 {
5883 if (NILP (Vpurify_flag))
5884 return obj;
5885 else if (MARKERP (obj) || OVERLAYP (obj) || SYMBOLP (obj))
5886
5887 return obj;
5888 else
5889 return purecopy (obj);
5890 }
5891
5892
5893 static struct pinned_object
5894 {
5895 Lisp_Object object;
5896 struct pinned_object *next;
5897 } *pinned_objects;
5898
5899 static Lisp_Object
5900 purecopy (Lisp_Object obj)
5901 {
5902 if (FIXNUMP (obj)
5903 || (! SYMBOLP (obj) && PURE_P (XPNTR (obj)))
5904 || SUBRP (obj))
5905 return obj;
5906
5907 if (STRINGP (obj) && XSTRING (obj)->u.s.intervals)
5908 message_with_string ("Dropping text-properties while making string `%s' pure",
5909 obj, true);
5910
5911 if (HASH_TABLE_P (Vpurify_flag))
5912 {
5913 Lisp_Object tmp = Fgethash (obj, Vpurify_flag, Qnil);
5914 if (!NILP (tmp))
5915 return tmp;
5916 }
5917
5918 if (CONSP (obj))
5919 obj = pure_cons (XCAR (obj), XCDR (obj));
5920 else if (FLOATP (obj))
5921 obj = make_pure_float (XFLOAT_DATA (obj));
5922 else if (STRINGP (obj))
5923 obj = make_pure_string (SSDATA (obj), SCHARS (obj),
5924 SBYTES (obj),
5925 STRING_MULTIBYTE (obj));
5926 else if (HASH_TABLE_P (obj))
5927 {
5928 struct Lisp_Hash_Table *table = XHASH_TABLE (obj);
5929
5930
5931
5932 if (!NILP (table->weak) || !table->purecopy)
5933 {
5934
5935
5936 struct pinned_object *o = xmalloc (sizeof *o);
5937 o->object = obj;
5938 o->next = pinned_objects;
5939 pinned_objects = o;
5940 return obj;
5941 }
5942
5943 struct Lisp_Hash_Table *h = purecopy_hash_table (table);
5944 XSET_HASH_TABLE (obj, h);
5945 }
5946 else if (COMPILEDP (obj) || VECTORP (obj) || RECORDP (obj))
5947 {
5948 struct Lisp_Vector *objp = XVECTOR (obj);
5949 ptrdiff_t nbytes = vector_nbytes (objp);
5950 struct Lisp_Vector *vec = pure_alloc (nbytes, Lisp_Vectorlike);
5951 register ptrdiff_t i;
5952 ptrdiff_t size = ASIZE (obj);
5953 if (size & PSEUDOVECTOR_FLAG)
5954 size &= PSEUDOVECTOR_SIZE_MASK;
5955 memcpy (vec, objp, nbytes);
5956 for (i = 0; i < size; i++)
5957 vec->contents[i] = purecopy (vec->contents[i]);
5958
5959 if (COMPILEDP (obj) && size >= 2 && STRINGP (vec->contents[1])
5960 && !STRING_MULTIBYTE (vec->contents[1]))
5961 pin_string (vec->contents[1]);
5962 XSETVECTOR (obj, vec);
5963 }
5964 else if (BARE_SYMBOL_P (obj))
5965 {
5966 if (!XBARE_SYMBOL (obj)->u.s.pinned && !c_symbol_p (XBARE_SYMBOL (obj)))
5967 {
5968
5969 XBARE_SYMBOL (obj)->u.s.pinned = true;
5970 symbol_block_pinned = symbol_block;
5971 }
5972
5973 return obj;
5974 }
5975 else if (BIGNUMP (obj))
5976 obj = make_pure_bignum (obj);
5977 else
5978 {
5979 AUTO_STRING (fmt, "Don't know how to purify: %S");
5980 Fsignal (Qerror, list1 (CALLN (Fformat, fmt, obj)));
5981 }
5982
5983 if (HASH_TABLE_P (Vpurify_flag))
5984 Fputhash (obj, obj, Vpurify_flag);
5985
5986 return obj;
5987 }
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998 void
5999 staticpro (Lisp_Object const *varaddress)
6000 {
6001 for (int i = 0; i < staticidx; i++)
6002 eassert (staticvec[i] != varaddress);
6003 if (staticidx >= NSTATICS)
6004 fatal ("NSTATICS too small; try increasing and recompiling Emacs.");
6005 staticvec[staticidx++] = varaddress;
6006 }
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016 static void
6017 allow_garbage_collection (intmax_t consing)
6018 {
6019 consing_until_gc = consing - (HI_THRESHOLD - consing_until_gc);
6020 garbage_collection_inhibited--;
6021 }
6022
6023 specpdl_ref
6024 inhibit_garbage_collection (void)
6025 {
6026 specpdl_ref count = SPECPDL_INDEX ();
6027 record_unwind_protect_intmax (allow_garbage_collection, consing_until_gc);
6028 garbage_collection_inhibited++;
6029 consing_until_gc = HI_THRESHOLD;
6030 return count;
6031 }
6032
6033
6034
6035
6036 static byte_ct
6037 object_bytes (object_ct n, size_t s)
6038 {
6039 byte_ct b = s;
6040 return n * b;
6041 }
6042
6043
6044
6045 static byte_ct
6046 total_bytes_of_live_objects (void)
6047 {
6048 byte_ct tot = 0;
6049 tot += object_bytes (gcstat.total_conses, sizeof (struct Lisp_Cons));
6050 tot += object_bytes (gcstat.total_symbols, sizeof (struct Lisp_Symbol));
6051 tot += gcstat.total_string_bytes;
6052 tot += object_bytes (gcstat.total_vector_slots, word_size);
6053 tot += object_bytes (gcstat.total_floats, sizeof (struct Lisp_Float));
6054 tot += object_bytes (gcstat.total_intervals, sizeof (struct interval));
6055 tot += object_bytes (gcstat.total_strings, sizeof (struct Lisp_String));
6056 return tot;
6057 }
6058
6059 #ifdef HAVE_WINDOW_SYSTEM
6060
6061
6062
6063
6064 static Lisp_Object
6065 compact_font_cache_entry (Lisp_Object entry)
6066 {
6067 Lisp_Object tail, *prev = &entry;
6068
6069 for (tail = entry; CONSP (tail); tail = XCDR (tail))
6070 {
6071 bool drop = 0;
6072 Lisp_Object obj = XCAR (tail);
6073
6074
6075 if (CONSP (obj) && GC_FONT_SPEC_P (XCAR (obj))
6076 && !vectorlike_marked_p (&GC_XFONT_SPEC (XCAR (obj))->header)
6077
6078
6079 && (VECTORLIKEP (XCDR (obj))
6080 && ! (gc_asize (XCDR (obj)) & PSEUDOVECTOR_FLAG)))
6081 {
6082 ptrdiff_t i, size = gc_asize (XCDR (obj));
6083 Lisp_Object obj_cdr = XCDR (obj);
6084
6085
6086
6087
6088 for (i = 0; i < size; i++)
6089 {
6090 Lisp_Object objlist;
6091
6092 if (vectorlike_marked_p (
6093 &GC_XFONT_ENTITY (AREF (obj_cdr, i))->header))
6094 break;
6095
6096 objlist = AREF (AREF (obj_cdr, i), FONT_OBJLIST_INDEX);
6097 for (; CONSP (objlist); objlist = XCDR (objlist))
6098 {
6099 Lisp_Object val = XCAR (objlist);
6100 struct font *font = GC_XFONT_OBJECT (val);
6101
6102 if (!NILP (AREF (val, FONT_TYPE_INDEX))
6103 && vectorlike_marked_p (&font->header))
6104 break;
6105 }
6106 if (CONSP (objlist))
6107 {
6108
6109 break;
6110 }
6111 }
6112
6113 if (i == size)
6114 {
6115
6116
6117 drop = 1;
6118 }
6119 }
6120 if (drop)
6121 *prev = XCDR (tail);
6122 else
6123 prev = xcdr_addr (tail);
6124 }
6125 return entry;
6126 }
6127
6128
6129
6130
6131 static void
6132 compact_font_caches (void)
6133 {
6134 struct terminal *t;
6135
6136 for (t = terminal_list; t; t = t->next_terminal)
6137 {
6138 Lisp_Object cache = TERMINAL_FONT_CACHE (t);
6139
6140
6141
6142 if (!inhibit_compacting_font_caches
6143 && CONSP (cache))
6144 {
6145 Lisp_Object entry;
6146
6147 for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry))
6148 XSETCAR (entry, compact_font_cache_entry (XCAR (entry)));
6149 }
6150 mark_object (cache);
6151 }
6152 }
6153
6154 #else
6155
6156 #define compact_font_caches() (void)(0)
6157
6158 #endif
6159
6160
6161
6162
6163 static Lisp_Object
6164 compact_undo_list (Lisp_Object list)
6165 {
6166 Lisp_Object tail, *prev = &list;
6167
6168 for (tail = list; CONSP (tail); tail = XCDR (tail))
6169 {
6170 if (CONSP (XCAR (tail))
6171 && MARKERP (XCAR (XCAR (tail)))
6172 && !vectorlike_marked_p (&XMARKER (XCAR (XCAR (tail)))->header))
6173 *prev = XCDR (tail);
6174 else
6175 prev = xcdr_addr (tail);
6176 }
6177 return list;
6178 }
6179
6180 static void
6181 mark_pinned_objects (void)
6182 {
6183 for (struct pinned_object *pobj = pinned_objects; pobj; pobj = pobj->next)
6184 mark_object (pobj->object);
6185 }
6186
6187 #if defined HAVE_ANDROID && !defined (__clang__)
6188
6189
6190
6191
6192 #define make_lisp_symbol android_make_lisp_symbol
6193
6194 static Lisp_Object
6195 android_make_lisp_symbol (struct Lisp_Symbol *sym)
6196 {
6197 intptr_t symoffset;
6198
6199 symoffset = (intptr_t) sym;
6200 INT_SUBTRACT_WRAPV (symoffset, (intptr_t) &lispsym,
6201 &symoffset);
6202
6203 {
6204 Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
6205 return a;
6206 }
6207 }
6208
6209 #endif
6210
6211 static void
6212 mark_pinned_symbols (void)
6213 {
6214 struct symbol_block *sblk;
6215 int lim;
6216 struct Lisp_Symbol *sym, *end;
6217
6218 if (symbol_block_pinned == symbol_block)
6219 lim = symbol_block_index;
6220 else
6221 lim = SYMBOL_BLOCK_SIZE;
6222
6223 for (sblk = symbol_block_pinned; sblk; sblk = sblk->next)
6224 {
6225 sym = sblk->symbols, end = sym + lim;
6226 for (; sym < end; ++sym)
6227 if (sym->u.s.pinned)
6228 mark_object (make_lisp_symbol (sym));
6229
6230 lim = SYMBOL_BLOCK_SIZE;
6231 }
6232 }
6233
6234 static void
6235 visit_vectorlike_root (struct gc_root_visitor visitor,
6236 struct Lisp_Vector *ptr,
6237 enum gc_root_type type)
6238 {
6239 ptrdiff_t size = ptr->header.size;
6240 ptrdiff_t i;
6241
6242 if (size & PSEUDOVECTOR_FLAG)
6243 size &= PSEUDOVECTOR_SIZE_MASK;
6244 for (i = 0; i < size; i++)
6245 visitor.visit (&ptr->contents[i], type, visitor.data);
6246 }
6247
6248 static void
6249 visit_buffer_root (struct gc_root_visitor visitor,
6250 struct buffer *buffer,
6251 enum gc_root_type type)
6252 {
6253
6254
6255 eassert (buffer->base_buffer == NULL);
6256 eassert (buffer->overlays == NULL);
6257
6258
6259 visit_vectorlike_root (visitor, (struct Lisp_Vector *) buffer, type);
6260 }
6261
6262
6263
6264
6265
6266
6267
6268 void
6269 visit_static_gc_roots (struct gc_root_visitor visitor)
6270 {
6271 visit_buffer_root (visitor,
6272 &buffer_defaults,
6273 GC_ROOT_BUFFER_LOCAL_DEFAULT);
6274 visit_buffer_root (visitor,
6275 &buffer_local_symbols,
6276 GC_ROOT_BUFFER_LOCAL_NAME);
6277
6278 for (int i = 0; i < ARRAYELTS (lispsym); i++)
6279 {
6280 Lisp_Object sptr = builtin_lisp_symbol (i);
6281 visitor.visit (&sptr, GC_ROOT_C_SYMBOL, visitor.data);
6282 }
6283
6284 for (int i = 0; i < staticidx; i++)
6285 visitor.visit (staticvec[i], GC_ROOT_STATICPRO, visitor.data);
6286 }
6287
6288 static void
6289 mark_object_root_visitor (Lisp_Object const *root_ptr,
6290 enum gc_root_type type,
6291 void *data)
6292 {
6293 mark_object (*root_ptr);
6294 }
6295
6296
6297
6298 static struct Lisp_Hash_Table *weak_hash_tables;
6299
6300 NO_INLINE
6301 static void
6302 mark_and_sweep_weak_table_contents (void)
6303 {
6304 struct Lisp_Hash_Table *h;
6305 bool marked;
6306
6307
6308
6309
6310
6311
6312
6313 do
6314 {
6315 marked = false;
6316 for (h = weak_hash_tables; h; h = h->next_weak)
6317 marked |= sweep_weak_table (h, false);
6318 }
6319 while (marked);
6320
6321
6322 while (weak_hash_tables)
6323 {
6324 h = weak_hash_tables;
6325 weak_hash_tables = h->next_weak;
6326 h->next_weak = NULL;
6327 sweep_weak_table (h, true);
6328 }
6329 }
6330
6331
6332
6333
6334
6335 static EMACS_INT
6336 consing_threshold (intmax_t threshold, Lisp_Object percentage,
6337 intmax_t since_gc)
6338 {
6339 if (!NILP (Vmemory_full))
6340 return memory_full_cons_threshold;
6341 else
6342 {
6343 threshold = max (threshold, GC_DEFAULT_THRESHOLD / 10);
6344 if (FLOATP (percentage))
6345 {
6346 double tot = (XFLOAT_DATA (percentage)
6347 * (total_bytes_of_live_objects () + since_gc));
6348 if (threshold < tot)
6349 {
6350 if (tot < HI_THRESHOLD)
6351 return tot;
6352 else
6353 return HI_THRESHOLD;
6354 }
6355 }
6356 return min (threshold, HI_THRESHOLD);
6357 }
6358 }
6359
6360
6361
6362
6363 static EMACS_INT
6364 bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage)
6365 {
6366
6367
6368 EMACS_INT since_gc = (gc_threshold - consing_until_gc) >> 1;
6369 EMACS_INT new_gc_threshold = consing_threshold (threshold, percentage,
6370 since_gc);
6371 consing_until_gc += new_gc_threshold - gc_threshold;
6372 gc_threshold = new_gc_threshold;
6373 return consing_until_gc;
6374 }
6375
6376
6377 static Lisp_Object
6378 watch_gc_cons_threshold (Lisp_Object symbol, Lisp_Object newval,
6379 Lisp_Object operation, Lisp_Object where)
6380 {
6381 intmax_t threshold;
6382 if (! (INTEGERP (newval) && integer_to_intmax (newval, &threshold)))
6383 return Qnil;
6384 bump_consing_until_gc (threshold, Vgc_cons_percentage);
6385 return Qnil;
6386 }
6387
6388
6389 static Lisp_Object
6390 watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval,
6391 Lisp_Object operation, Lisp_Object where)
6392 {
6393 bump_consing_until_gc (gc_cons_threshold, newval);
6394 return Qnil;
6395 }
6396
6397
6398
6399
6400 void
6401 maybe_garbage_collect (void)
6402 {
6403 if (bump_consing_until_gc (gc_cons_threshold, Vgc_cons_percentage) < 0)
6404 garbage_collect ();
6405 }
6406
6407 static inline bool mark_stack_empty_p (void);
6408
6409
6410 void
6411 garbage_collect (void)
6412 {
6413 Lisp_Object tail, buffer;
6414 char stack_top_variable;
6415 bool message_p;
6416 specpdl_ref count = SPECPDL_INDEX ();
6417 struct timespec start;
6418
6419 eassert (weak_hash_tables == NULL);
6420
6421 if (garbage_collection_inhibited)
6422 return;
6423
6424 eassert(mark_stack_empty_p ());
6425
6426
6427 record_in_backtrace (QAutomatic_GC, 0, 0);
6428
6429
6430
6431 FOR_EACH_LIVE_BUFFER (tail, buffer)
6432 compact_buffer (XBUFFER (buffer));
6433
6434 byte_ct tot_before = (profiler_memory_running
6435 ? total_bytes_of_live_objects ()
6436 : (byte_ct) -1);
6437
6438 start = current_timespec ();
6439
6440
6441
6442 consing_until_gc = HI_THRESHOLD;
6443
6444
6445
6446
6447 if (NILP (Vmemory_full))
6448 {
6449 message_p = push_message ();
6450 record_unwind_protect_void (pop_message_unwind);
6451 }
6452 else
6453 message_p = false;
6454
6455
6456 #if MAX_SAVE_STACK > 0
6457 if (NILP (Vpurify_flag))
6458 {
6459 char const *stack;
6460 ptrdiff_t stack_size;
6461 if (&stack_top_variable < stack_bottom)
6462 {
6463 stack = &stack_top_variable;
6464 stack_size = stack_bottom - &stack_top_variable;
6465 }
6466 else
6467 {
6468 stack = stack_bottom;
6469 stack_size = &stack_top_variable - stack_bottom;
6470 }
6471 if (stack_size <= MAX_SAVE_STACK)
6472 {
6473 if (stack_copy_size < stack_size)
6474 {
6475 stack_copy = xrealloc (stack_copy, stack_size);
6476 stack_copy_size = stack_size;
6477 }
6478 no_sanitize_memcpy (stack_copy, stack, stack_size);
6479 }
6480 }
6481 #endif
6482
6483 if (garbage_collection_messages)
6484 message1_nolog ("Garbage collecting...");
6485
6486 block_input ();
6487
6488 shrink_regexp_cache ();
6489
6490 gc_in_progress = 1;
6491
6492
6493
6494 struct gc_root_visitor visitor = { .visit = mark_object_root_visitor };
6495 visit_static_gc_roots (visitor);
6496
6497 mark_pinned_objects ();
6498 mark_pinned_symbols ();
6499 mark_lread ();
6500 mark_terminals ();
6501 mark_kboards ();
6502 mark_threads ();
6503 #ifdef HAVE_PGTK
6504 mark_pgtkterm ();
6505 #endif
6506
6507 #ifdef USE_GTK
6508 xg_mark_data ();
6509 #endif
6510
6511 #ifdef HAVE_HAIKU
6512 mark_haiku_display ();
6513 #endif
6514
6515 #ifdef HAVE_WINDOW_SYSTEM
6516 mark_fringe_data ();
6517 #endif
6518
6519 #ifdef HAVE_X_WINDOWS
6520 mark_xterm ();
6521 mark_xselect ();
6522 #endif
6523
6524 #ifdef HAVE_ANDROID
6525 mark_androidterm ();
6526 #ifndef ANDROID_STUBIFY
6527 mark_sfntfont ();
6528 #endif
6529 #endif
6530
6531 #ifdef HAVE_NS
6532 mark_nsterm ();
6533 #endif
6534
6535
6536
6537
6538
6539 compact_font_caches ();
6540
6541 FOR_EACH_LIVE_BUFFER (tail, buffer)
6542 {
6543 struct buffer *nextb = XBUFFER (buffer);
6544 if (!EQ (BVAR (nextb, undo_list), Qt))
6545 bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list)));
6546
6547
6548 mark_object (BVAR (nextb, undo_list));
6549 }
6550
6551
6552
6553
6554
6555
6556
6557
6558 queue_doomed_finalizers (&doomed_finalizers, &finalizers);
6559 mark_finalizer_list (&doomed_finalizers);
6560
6561
6562 mark_and_sweep_weak_table_contents ();
6563 eassert (weak_hash_tables == NULL);
6564
6565 eassert (mark_stack_empty_p ());
6566
6567 gc_sweep ();
6568
6569 unmark_main_thread ();
6570
6571 gc_in_progress = 0;
6572
6573 consing_until_gc = gc_threshold
6574 = consing_threshold (gc_cons_threshold, Vgc_cons_percentage, 0);
6575
6576
6577
6578 unblock_input ();
6579
6580 if (garbage_collection_messages && NILP (Vmemory_full))
6581 {
6582 if (message_p || minibuf_level > 0)
6583 restore_message ();
6584 else
6585 message1_nolog ("Garbage collecting...done");
6586 }
6587
6588 unbind_to (count, Qnil);
6589
6590
6591 run_finalizers (&doomed_finalizers);
6592
6593 #ifdef HAVE_WINDOW_SYSTEM
6594
6595 image_prune_animation_caches (false);
6596 #endif
6597
6598 if (!NILP (Vpost_gc_hook))
6599 {
6600 specpdl_ref gc_count = inhibit_garbage_collection ();
6601 safe_run_hooks (Qpost_gc_hook);
6602 unbind_to (gc_count, Qnil);
6603 }
6604
6605
6606 if (FLOATP (Vgc_elapsed))
6607 {
6608 static struct timespec gc_elapsed;
6609 gc_elapsed = timespec_add (gc_elapsed,
6610 timespec_sub (current_timespec (), start));
6611 Vgc_elapsed = make_float (timespectod (gc_elapsed));
6612 }
6613
6614 gcs_done++;
6615
6616
6617 if (tot_before != (byte_ct) -1)
6618 {
6619 byte_ct tot_after = total_bytes_of_live_objects ();
6620 if (tot_after < tot_before)
6621 malloc_probe (min (tot_before - tot_after, SIZE_MAX));
6622 }
6623 }
6624
6625 DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
6626 doc:
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647 )
6648 (void)
6649 {
6650 if (garbage_collection_inhibited)
6651 return Qnil;
6652
6653 specpdl_ref count = SPECPDL_INDEX ();
6654 specbind (Qsymbols_with_pos_enabled, Qnil);
6655 garbage_collect ();
6656 unbind_to (count, Qnil);
6657 struct gcstat gcst = gcstat;
6658
6659 Lisp_Object total[] = {
6660 list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)),
6661 make_int (gcst.total_conses),
6662 make_int (gcst.total_free_conses)),
6663 list4 (Qsymbols, make_fixnum (sizeof (struct Lisp_Symbol)),
6664 make_int (gcst.total_symbols),
6665 make_int (gcst.total_free_symbols)),
6666 list4 (Qstrings, make_fixnum (sizeof (struct Lisp_String)),
6667 make_int (gcst.total_strings),
6668 make_int (gcst.total_free_strings)),
6669 list3 (Qstring_bytes, make_fixnum (1),
6670 make_int (gcst.total_string_bytes)),
6671 list3 (Qvectors,
6672 make_fixnum (header_size + sizeof (Lisp_Object)),
6673 make_int (gcst.total_vectors)),
6674 list4 (Qvector_slots, make_fixnum (word_size),
6675 make_int (gcst.total_vector_slots),
6676 make_int (gcst.total_free_vector_slots)),
6677 list4 (Qfloats, make_fixnum (sizeof (struct Lisp_Float)),
6678 make_int (gcst.total_floats),
6679 make_int (gcst.total_free_floats)),
6680 list4 (Qintervals, make_fixnum (sizeof (struct interval)),
6681 make_int (gcst.total_intervals),
6682 make_int (gcst.total_free_intervals)),
6683 list3 (Qbuffers, make_fixnum (sizeof (struct buffer)),
6684 make_int (gcst.total_buffers)),
6685
6686 #ifdef DOUG_LEA_MALLOC
6687 list4 (Qheap, make_fixnum (1024),
6688 make_int ((mallinfo ().uordblks + 1023) >> 10),
6689 make_int ((mallinfo ().fordblks + 1023) >> 10)),
6690 #endif
6691 };
6692 return CALLMANY (Flist, total);
6693 }
6694
6695 DEFUN ("garbage-collect-maybe", Fgarbage_collect_maybe,
6696 Sgarbage_collect_maybe, 1, 1, 0,
6697 doc:
6698
6699
6700
6701
6702
6703 )
6704 (Lisp_Object factor)
6705 {
6706 CHECK_FIXNAT (factor);
6707 EMACS_INT fact = XFIXNAT (factor);
6708
6709 EMACS_INT since_gc = gc_threshold - consing_until_gc;
6710 if (fact >= 1 && since_gc > gc_threshold / fact)
6711 {
6712 garbage_collect ();
6713 return Qt;
6714 }
6715 else
6716 return Qnil;
6717 }
6718
6719
6720
6721
6722 static void
6723 mark_glyph_matrix (struct glyph_matrix *matrix)
6724 {
6725 struct glyph_row *row = matrix->rows;
6726 struct glyph_row *end = row + matrix->nrows;
6727
6728 for (; row < end; ++row)
6729 if (row->enabled_p)
6730 {
6731 int area;
6732 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
6733 {
6734 struct glyph *glyph = row->glyphs[area];
6735 struct glyph *end_glyph = glyph + row->used[area];
6736
6737 for (; glyph < end_glyph; ++glyph)
6738 if (STRINGP (glyph->object)
6739 && !string_marked_p (XSTRING (glyph->object)))
6740 mark_object (glyph->object);
6741 }
6742 }
6743 }
6744
6745
6746 #define GC_REMEMBER_LAST_MARKED 0
6747
6748 #if GC_REMEMBER_LAST_MARKED
6749 enum { LAST_MARKED_SIZE = 1 << 9 };
6750 Lisp_Object last_marked[LAST_MARKED_SIZE] EXTERNALLY_VISIBLE;
6751 static int last_marked_index;
6752 #endif
6753
6754
6755 #define GC_CDR_COUNT 0
6756
6757 #if GC_CDR_COUNT
6758
6759
6760
6761
6762 ptrdiff_t mark_object_loop_halt EXTERNALLY_VISIBLE;
6763 #endif
6764
6765 static void
6766 mark_vectorlike (union vectorlike_header *header)
6767 {
6768 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header;
6769 ptrdiff_t size = ptr->header.size;
6770
6771 eassert (!vector_marked_p (ptr));
6772
6773
6774 eassert (PSEUDOVECTOR_TYPE (ptr) != PVEC_BOOL_VECTOR);
6775
6776 set_vector_marked (ptr);
6777 if (size & PSEUDOVECTOR_FLAG)
6778 size &= PSEUDOVECTOR_SIZE_MASK;
6779
6780
6781
6782
6783
6784 mark_objects (ptr->contents, size);
6785 }
6786
6787
6788
6789
6790
6791 static void
6792 mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
6793 {
6794 int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
6795
6796 int i, idx = (pvectype == PVEC_SUB_CHAR_TABLE ? SUB_CHAR_TABLE_OFFSET : 0);
6797
6798 eassert (!vector_marked_p (ptr));
6799 set_vector_marked (ptr);
6800 for (i = idx; i < size; i++)
6801 {
6802 Lisp_Object val = ptr->contents[i];
6803
6804 if (FIXNUMP (val) ||
6805 (BARE_SYMBOL_P (val) && symbol_marked_p (XBARE_SYMBOL (val))))
6806 continue;
6807 if (SUB_CHAR_TABLE_P (val))
6808 {
6809 if (! vector_marked_p (XVECTOR (val)))
6810 mark_char_table (XVECTOR (val), PVEC_SUB_CHAR_TABLE);
6811 }
6812 else
6813 mark_object (val);
6814 }
6815 }
6816
6817
6818
6819 static void
6820 mark_overlay (struct Lisp_Overlay *ov)
6821 {
6822
6823
6824 eassert (BASE_EQ (ov->interval->data, make_lisp_ptr (ov, Lisp_Vectorlike)));
6825 set_vectorlike_marked (&ov->header);
6826 mark_object (ov->plist);
6827 }
6828
6829
6830
6831 static void
6832 mark_overlays (struct itree_node *node)
6833 {
6834 if (node == NULL)
6835 return;
6836 mark_object (node->data);
6837 mark_overlays (node->left);
6838 mark_overlays (node->right);
6839 }
6840
6841
6842
6843 static void
6844 mark_buffer (struct buffer *buffer)
6845 {
6846
6847 mark_vectorlike (&buffer->header);
6848
6849
6850
6851 mark_interval_tree (buffer_intervals (buffer));
6852
6853
6854
6855
6856
6857
6858
6859 if (!BUFFER_LIVE_P (buffer))
6860 mark_object (BVAR (buffer, undo_list));
6861
6862 if (!itree_empty_p (buffer->overlays))
6863 mark_overlays (buffer->overlays->root);
6864
6865
6866 if (buffer->base_buffer &&
6867 !vectorlike_marked_p (&buffer->base_buffer->header))
6868 mark_buffer (buffer->base_buffer);
6869 }
6870
6871
6872
6873 NO_INLINE
6874 static void
6875 mark_face_cache (struct face_cache *c)
6876 {
6877 if (c)
6878 {
6879 for (int i = 0; i < c->used; i++)
6880 {
6881 struct face *face = FACE_FROM_ID_OR_NULL (c->f, i);
6882
6883 if (face)
6884 {
6885 if (face->font && !vectorlike_marked_p (&face->font->header))
6886 mark_vectorlike (&face->font->header);
6887
6888 mark_objects (face->lface, LFACE_VECTOR_SIZE);
6889 }
6890 }
6891 }
6892 }
6893
6894 NO_INLINE
6895 static void
6896 mark_localized_symbol (struct Lisp_Symbol *ptr)
6897 {
6898 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
6899 Lisp_Object where = blv->where;
6900
6901 if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))))
6902 swap_in_global_binding (ptr);
6903 mark_object (blv->where);
6904 mark_object (blv->valcell);
6905 mark_object (blv->defcell);
6906 }
6907
6908
6909
6910
6911 static Lisp_Object
6912 mark_discard_killed_buffers (Lisp_Object list)
6913 {
6914 Lisp_Object tail, *prev = &list;
6915
6916 for (tail = list; CONSP (tail) && !cons_marked_p (XCONS (tail));
6917 tail = XCDR (tail))
6918 {
6919 Lisp_Object tem = XCAR (tail);
6920 if (CONSP (tem))
6921 tem = XCAR (tem);
6922 if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem)))
6923 *prev = XCDR (tail);
6924 else
6925 {
6926 set_cons_marked (XCONS (tail));
6927 mark_object (XCAR (tail));
6928 prev = xcdr_addr (tail);
6929 }
6930 }
6931 mark_object (tail);
6932 return list;
6933 }
6934
6935 static void
6936 mark_frame (struct Lisp_Vector *ptr)
6937 {
6938 struct frame *f = (struct frame *) ptr;
6939 #ifdef HAVE_TEXT_CONVERSION
6940 struct text_conversion_action *tem;
6941 #endif
6942
6943
6944 mark_vectorlike (&ptr->header);
6945 mark_face_cache (f->face_cache);
6946 #ifdef HAVE_WINDOW_SYSTEM
6947 if (FRAME_WINDOW_P (f) && FRAME_OUTPUT_DATA (f))
6948 {
6949 struct font *font = FRAME_FONT (f);
6950
6951 if (font && !vectorlike_marked_p (&font->header))
6952 mark_vectorlike (&font->header);
6953 }
6954 #endif
6955
6956 #ifdef HAVE_TEXT_CONVERSION
6957 mark_object (f->conversion.compose_region_start);
6958 mark_object (f->conversion.compose_region_end);
6959 mark_object (f->conversion.compose_region_overlay);
6960
6961 for (tem = f->conversion.actions; tem; tem = tem->next)
6962 mark_object (tem->data);
6963 #endif
6964 }
6965
6966 static void
6967 mark_window (struct Lisp_Vector *ptr)
6968 {
6969 struct window *w = (struct window *) ptr;
6970
6971 mark_vectorlike (&ptr->header);
6972
6973
6974
6975
6976 if (w->current_matrix)
6977 {
6978 mark_glyph_matrix (w->current_matrix);
6979 mark_glyph_matrix (w->desired_matrix);
6980 }
6981
6982
6983
6984
6985
6986 wset_prev_buffers
6987 (w, mark_discard_killed_buffers (w->prev_buffers));
6988 wset_next_buffers
6989 (w, mark_discard_killed_buffers (w->next_buffers));
6990 }
6991
6992
6993 struct mark_entry
6994 {
6995 ptrdiff_t n;
6996 union {
6997 Lisp_Object value;
6998 Lisp_Object *values;
6999 } u;
7000 };
7001
7002
7003
7004 struct mark_stack
7005 {
7006 struct mark_entry *stack;
7007 ptrdiff_t size;
7008 ptrdiff_t sp;
7009 };
7010
7011 static struct mark_stack mark_stk = {NULL, 0, 0};
7012
7013 static inline bool
7014 mark_stack_empty_p (void)
7015 {
7016 return mark_stk.sp <= 0;
7017 }
7018
7019
7020 static inline Lisp_Object
7021 mark_stack_pop (void)
7022 {
7023 eassume (!mark_stack_empty_p ());
7024 struct mark_entry *e = &mark_stk.stack[mark_stk.sp - 1];
7025 if (e->n == 0)
7026 {
7027 --mark_stk.sp;
7028 return e->u.value;
7029 }
7030
7031
7032 e->n--;
7033 if (e->n == 0)
7034 --mark_stk.sp;
7035 return (++e->u.values)[-1];
7036 }
7037
7038 NO_INLINE static void
7039 grow_mark_stack (void)
7040 {
7041 struct mark_stack *ms = &mark_stk;
7042 eassert (ms->sp == ms->size);
7043 ptrdiff_t min_incr = ms->sp == 0 ? 8192 : 1;
7044 ms->stack = xpalloc (ms->stack, &ms->size, min_incr, -1, sizeof *ms->stack);
7045 eassert (ms->sp < ms->size);
7046 }
7047
7048
7049 static inline void
7050 mark_stack_push_value (Lisp_Object value)
7051 {
7052 if (mark_stk.sp >= mark_stk.size)
7053 grow_mark_stack ();
7054 mark_stk.stack[mark_stk.sp++] = (struct mark_entry){.n = 0, .u.value = value};
7055 }
7056
7057
7058 static inline void
7059 mark_stack_push_values (Lisp_Object *values, ptrdiff_t n)
7060 {
7061 eassume (n >= 0);
7062 if (n == 0)
7063 return;
7064 if (mark_stk.sp >= mark_stk.size)
7065 grow_mark_stack ();
7066 mark_stk.stack[mark_stk.sp++] = (struct mark_entry){.n = n,
7067 .u.values = values};
7068 }
7069
7070
7071
7072
7073
7074
7075 static void
7076 process_mark_stack (ptrdiff_t base_sp)
7077 {
7078 #if GC_CHECK_MARKED_OBJECTS
7079 struct mem_node *m = NULL;
7080 #endif
7081 #if GC_CDR_COUNT
7082 ptrdiff_t cdr_count = 0;
7083 #endif
7084
7085 eassume (mark_stk.sp >= base_sp && base_sp >= 0);
7086
7087 while (mark_stk.sp > base_sp)
7088 {
7089 Lisp_Object obj = mark_stack_pop ();
7090 mark_obj: ;
7091 void *po = XPNTR (obj);
7092 if (PURE_P (po))
7093 continue;
7094
7095 #if GC_REMEMBER_LAST_MARKED
7096 last_marked[last_marked_index++] = obj;
7097 last_marked_index &= LAST_MARKED_SIZE - 1;
7098 #endif
7099
7100
7101
7102
7103 #if GC_CHECK_MARKED_OBJECTS
7104
7105
7106
7107 #define CHECK_ALLOCATED() \
7108 do { \
7109 if (pdumper_object_p (po)) \
7110 { \
7111 if (!pdumper_object_p_precise (po)) \
7112 emacs_abort (); \
7113 break; \
7114 } \
7115 m = mem_find (po); \
7116 if (m == MEM_NIL) \
7117 emacs_abort (); \
7118 } while (0)
7119
7120
7121
7122 #define CHECK_LIVE(LIVEP, MEM_TYPE) \
7123 do { \
7124 if (pdumper_object_p (po)) \
7125 break; \
7126 if (! (m->type == MEM_TYPE && LIVEP (m, po))) \
7127 emacs_abort (); \
7128 } while (0)
7129
7130
7131 #define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) \
7132 do { \
7133 CHECK_ALLOCATED (); \
7134 CHECK_LIVE (LIVEP, MEM_TYPE); \
7135 } while (false)
7136
7137
7138 #define CHECK_ALLOCATED_AND_LIVE_SYMBOL() \
7139 do { \
7140 if (!c_symbol_p (ptr)) \
7141 { \
7142 CHECK_ALLOCATED (); \
7143 CHECK_LIVE (live_symbol_p, MEM_TYPE_SYMBOL); \
7144 } \
7145 } while (false)
7146
7147 #else
7148
7149 #define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) ((void) 0)
7150 #define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0)
7151
7152 #endif
7153
7154 switch (XTYPE (obj))
7155 {
7156 case Lisp_String:
7157 {
7158 register struct Lisp_String *ptr = XSTRING (obj);
7159 if (string_marked_p (ptr))
7160 break;
7161 CHECK_ALLOCATED_AND_LIVE (live_string_p, MEM_TYPE_STRING);
7162 set_string_marked (ptr);
7163 mark_interval_tree (ptr->u.s.intervals);
7164 #ifdef GC_CHECK_STRING_BYTES
7165
7166
7167 string_bytes (ptr);
7168 #endif
7169 }
7170 break;
7171
7172 case Lisp_Vectorlike:
7173 {
7174 register struct Lisp_Vector *ptr = XVECTOR (obj);
7175
7176 if (vector_marked_p (ptr))
7177 break;
7178
7179 enum pvec_type pvectype
7180 = PSEUDOVECTOR_TYPE (ptr);
7181
7182 #ifdef GC_CHECK_MARKED_OBJECTS
7183 if (!pdumper_object_p (po) && !SUBRP (obj) && !main_thread_p (po))
7184 {
7185 m = mem_find (po);
7186 if (m == MEM_NIL)
7187 emacs_abort ();
7188 if (m->type == MEM_TYPE_VECTORLIKE)
7189 CHECK_LIVE (live_large_vector_p, MEM_TYPE_VECTORLIKE);
7190 else
7191 CHECK_LIVE (live_small_vector_p, MEM_TYPE_VECTOR_BLOCK);
7192 }
7193 #endif
7194
7195 switch (pvectype)
7196 {
7197 case PVEC_BUFFER:
7198 mark_buffer ((struct buffer *) ptr);
7199 break;
7200
7201 case PVEC_FRAME:
7202 mark_frame (ptr);
7203 break;
7204
7205 case PVEC_WINDOW:
7206 mark_window (ptr);
7207 break;
7208
7209 case PVEC_HASH_TABLE:
7210 {
7211 struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *)ptr;
7212 ptrdiff_t size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
7213 set_vector_marked (ptr);
7214 mark_stack_push_values (ptr->contents, size);
7215 mark_stack_push_value (h->test.name);
7216 mark_stack_push_value (h->test.user_hash_function);
7217 mark_stack_push_value (h->test.user_cmp_function);
7218 if (NILP (h->weak))
7219 mark_stack_push_value (h->key_and_value);
7220 else
7221 {
7222
7223
7224 eassert (h->next_weak == NULL);
7225 h->next_weak = weak_hash_tables;
7226 weak_hash_tables = h;
7227 set_vector_marked (XVECTOR (h->key_and_value));
7228 }
7229 break;
7230 }
7231
7232 case PVEC_CHAR_TABLE:
7233 case PVEC_SUB_CHAR_TABLE:
7234 mark_char_table (ptr, (enum pvec_type) pvectype);
7235 break;
7236
7237 case PVEC_BOOL_VECTOR:
7238
7239
7240
7241
7242
7243 eassert (!pdumper_object_p (ptr));
7244 set_vector_marked (ptr);
7245 break;
7246
7247 case PVEC_OVERLAY:
7248 mark_overlay (XOVERLAY (obj));
7249 break;
7250
7251 case PVEC_SUBR:
7252 #ifdef HAVE_NATIVE_COMP
7253 if (SUBR_NATIVE_COMPILEDP (obj))
7254 {
7255 set_vector_marked (ptr);
7256 struct Lisp_Subr *subr = XSUBR (obj);
7257 mark_stack_push_value (subr->intspec.native);
7258 mark_stack_push_value (subr->command_modes);
7259 mark_stack_push_value (subr->native_comp_u);
7260 mark_stack_push_value (subr->lambda_list);
7261 mark_stack_push_value (subr->type);
7262 }
7263 #endif
7264 break;
7265
7266 case PVEC_FREE:
7267 emacs_abort ();
7268
7269 default:
7270 {
7271
7272
7273 ptrdiff_t size = ptr->header.size;
7274 if (size & PSEUDOVECTOR_FLAG)
7275 size &= PSEUDOVECTOR_SIZE_MASK;
7276 set_vector_marked (ptr);
7277 mark_stack_push_values (ptr->contents, size);
7278 }
7279 break;
7280 }
7281 }
7282 break;
7283
7284 case Lisp_Symbol:
7285 {
7286 struct Lisp_Symbol *ptr = XBARE_SYMBOL (obj);
7287 nextsym:
7288 if (symbol_marked_p (ptr))
7289 break;
7290 CHECK_ALLOCATED_AND_LIVE_SYMBOL ();
7291 set_symbol_marked (ptr);
7292
7293 eassert (valid_lisp_object_p (ptr->u.s.function));
7294 mark_stack_push_value (ptr->u.s.function);
7295 mark_stack_push_value (ptr->u.s.plist);
7296 switch (ptr->u.s.redirect)
7297 {
7298 case SYMBOL_PLAINVAL:
7299 mark_stack_push_value (SYMBOL_VAL (ptr));
7300 break;
7301 case SYMBOL_VARALIAS:
7302 {
7303 Lisp_Object tem;
7304 XSETSYMBOL (tem, SYMBOL_ALIAS (ptr));
7305 mark_stack_push_value (tem);
7306 break;
7307 }
7308 case SYMBOL_LOCALIZED:
7309 mark_localized_symbol (ptr);
7310 break;
7311 case SYMBOL_FORWARDED:
7312
7313
7314
7315
7316 break;
7317 default: emacs_abort ();
7318 }
7319 if (!PURE_P (XSTRING (ptr->u.s.name)))
7320 set_string_marked (XSTRING (ptr->u.s.name));
7321 mark_interval_tree (string_intervals (ptr->u.s.name));
7322
7323 po = ptr = ptr->u.s.next;
7324 if (ptr)
7325 goto nextsym;
7326 }
7327 break;
7328
7329 case Lisp_Cons:
7330 {
7331 struct Lisp_Cons *ptr = XCONS (obj);
7332 if (cons_marked_p (ptr))
7333 break;
7334 CHECK_ALLOCATED_AND_LIVE (live_cons_p, MEM_TYPE_CONS);
7335 set_cons_marked (ptr);
7336
7337
7338 if (!NILP (ptr->u.s.u.cdr))
7339 {
7340 mark_stack_push_value (ptr->u.s.u.cdr);
7341 #if GC_CDR_COUNT
7342 cdr_count++;
7343 if (cdr_count == mark_object_loop_halt)
7344 emacs_abort ();
7345 #endif
7346 }
7347
7348 obj = ptr->u.s.car;
7349 goto mark_obj;
7350 }
7351
7352 case Lisp_Float:
7353 CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
7354
7355
7356 if (pdumper_object_p (XFLOAT (obj)))
7357 eassert (pdumper_cold_object_p (XFLOAT (obj)));
7358 else if (!XFLOAT_MARKED_P (XFLOAT (obj)))
7359 XFLOAT_MARK (XFLOAT (obj));
7360 break;
7361
7362 case_Lisp_Int:
7363 break;
7364
7365 default:
7366 emacs_abort ();
7367 }
7368 }
7369
7370 #undef CHECK_LIVE
7371 #undef CHECK_ALLOCATED
7372 #undef CHECK_ALLOCATED_AND_LIVE
7373 }
7374
7375 void
7376 mark_object (Lisp_Object obj)
7377 {
7378 ptrdiff_t sp = mark_stk.sp;
7379 mark_stack_push_value (obj);
7380 process_mark_stack (sp);
7381 }
7382
7383 void
7384 mark_objects (Lisp_Object *objs, ptrdiff_t n)
7385 {
7386 ptrdiff_t sp = mark_stk.sp;
7387 mark_stack_push_values (objs, n);
7388 process_mark_stack (sp);
7389 }
7390
7391
7392
7393
7394 static void
7395 mark_terminals (void)
7396 {
7397 struct terminal *t;
7398 for (t = terminal_list; t; t = t->next_terminal)
7399 {
7400 eassert (t->name != NULL);
7401 #ifdef HAVE_WINDOW_SYSTEM
7402
7403
7404
7405 mark_image_cache (t->image_cache);
7406 #endif
7407 if (!vectorlike_marked_p (&t->header))
7408 mark_vectorlike (&t->header);
7409 }
7410 }
7411
7412
7413
7414
7415 bool
7416 survives_gc_p (Lisp_Object obj)
7417 {
7418 bool survives_p;
7419
7420 switch (XTYPE (obj))
7421 {
7422 case_Lisp_Int:
7423 survives_p = true;
7424 break;
7425
7426 case Lisp_Symbol:
7427 survives_p = symbol_marked_p (XBARE_SYMBOL (obj));
7428 break;
7429
7430 case Lisp_String:
7431 survives_p = string_marked_p (XSTRING (obj));
7432 break;
7433
7434 case Lisp_Vectorlike:
7435 survives_p =
7436 (SUBRP (obj) && !SUBR_NATIVE_COMPILEDP (obj)) ||
7437 vector_marked_p (XVECTOR (obj));
7438 break;
7439
7440 case Lisp_Cons:
7441 survives_p = cons_marked_p (XCONS (obj));
7442 break;
7443
7444 case Lisp_Float:
7445 survives_p =
7446 XFLOAT_MARKED_P (XFLOAT (obj)) ||
7447 pdumper_object_p (XFLOAT (obj));
7448 break;
7449
7450 default:
7451 emacs_abort ();
7452 }
7453
7454 return survives_p || PURE_P (XPNTR (obj));
7455 }
7456
7457
7458
7459
7460 NO_INLINE
7461 static void
7462 sweep_conses (void)
7463 {
7464 struct cons_block **cprev = &cons_block;
7465 int lim = cons_block_index;
7466 object_ct num_free = 0, num_used = 0;
7467
7468 cons_free_list = 0;
7469
7470 for (struct cons_block *cblk; (cblk = *cprev); )
7471 {
7472 int i = 0;
7473 int this_free = 0;
7474 int ilim = (lim + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD;
7475
7476
7477 for (i = 0; i < ilim; i++)
7478 {
7479 if (cblk->gcmarkbits[i] == BITS_WORD_MAX)
7480 {
7481
7482 cblk->gcmarkbits[i] = 0;
7483 num_used += BITS_PER_BITS_WORD;
7484 }
7485 else
7486 {
7487
7488
7489 int start, pos, stop;
7490
7491 start = i * BITS_PER_BITS_WORD;
7492 stop = lim - start;
7493 if (stop > BITS_PER_BITS_WORD)
7494 stop = BITS_PER_BITS_WORD;
7495 stop += start;
7496
7497 for (pos = start; pos < stop; pos++)
7498 {
7499 struct Lisp_Cons *acons = &cblk->conses[pos];
7500 if (!XCONS_MARKED_P (acons))
7501 {
7502 ASAN_UNPOISON_CONS (&cblk->conses[pos]);
7503 this_free++;
7504 cblk->conses[pos].u.s.u.chain = cons_free_list;
7505 cons_free_list = &cblk->conses[pos];
7506 cons_free_list->u.s.car = dead_object ();
7507 ASAN_POISON_CONS (&cblk->conses[pos]);
7508 }
7509 else
7510 {
7511 num_used++;
7512 XUNMARK_CONS (acons);
7513 }
7514 }
7515 }
7516 }
7517
7518 lim = CONS_BLOCK_SIZE;
7519
7520
7521
7522 if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE)
7523 {
7524 *cprev = cblk->next;
7525
7526 ASAN_UNPOISON_CONS (&cblk->conses[0]);
7527 cons_free_list = cblk->conses[0].u.s.u.chain;
7528 lisp_align_free (cblk);
7529 }
7530 else
7531 {
7532 num_free += this_free;
7533 cprev = &cblk->next;
7534 }
7535 }
7536 gcstat.total_conses = num_used;
7537 gcstat.total_free_conses = num_free;
7538 }
7539
7540 NO_INLINE
7541 static void
7542 sweep_floats (void)
7543 {
7544 struct float_block **fprev = &float_block;
7545 int lim = float_block_index;
7546 object_ct num_free = 0, num_used = 0;
7547
7548 float_free_list = 0;
7549
7550 for (struct float_block *fblk; (fblk = *fprev); )
7551 {
7552 int this_free = 0;
7553 ASAN_UNPOISON_FLOAT_BLOCK (fblk);
7554 for (int i = 0; i < lim; i++)
7555 {
7556 struct Lisp_Float *afloat = &fblk->floats[i];
7557 if (!XFLOAT_MARKED_P (afloat))
7558 {
7559 this_free++;
7560 fblk->floats[i].u.chain = float_free_list;
7561 ASAN_POISON_FLOAT (&fblk->floats[i]);
7562 float_free_list = &fblk->floats[i];
7563 }
7564 else
7565 {
7566 num_used++;
7567 XFLOAT_UNMARK (afloat);
7568 }
7569 }
7570 lim = FLOAT_BLOCK_SIZE;
7571
7572
7573
7574 if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE)
7575 {
7576 *fprev = fblk->next;
7577
7578 ASAN_UNPOISON_FLOAT (&fblk->floats[0]);
7579 float_free_list = fblk->floats[0].u.chain;
7580 lisp_align_free (fblk);
7581 }
7582 else
7583 {
7584 num_free += this_free;
7585 fprev = &fblk->next;
7586 }
7587 }
7588 gcstat.total_floats = num_used;
7589 gcstat.total_free_floats = num_free;
7590 }
7591
7592 NO_INLINE
7593 static void
7594 sweep_intervals (void)
7595 {
7596 struct interval_block **iprev = &interval_block;
7597 int lim = interval_block_index;
7598 object_ct num_free = 0, num_used = 0;
7599
7600 interval_free_list = 0;
7601
7602 for (struct interval_block *iblk; (iblk = *iprev); )
7603 {
7604 int this_free = 0;
7605 ASAN_UNPOISON_INTERVAL_BLOCK (iblk);
7606 for (int i = 0; i < lim; i++)
7607 {
7608 if (!iblk->intervals[i].gcmarkbit)
7609 {
7610 set_interval_parent (&iblk->intervals[i], interval_free_list);
7611 interval_free_list = &iblk->intervals[i];
7612 ASAN_POISON_INTERVAL (&iblk->intervals[i]);
7613 this_free++;
7614 }
7615 else
7616 {
7617 num_used++;
7618 iblk->intervals[i].gcmarkbit = 0;
7619 }
7620 }
7621 lim = INTERVAL_BLOCK_SIZE;
7622
7623
7624
7625 if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE)
7626 {
7627 *iprev = iblk->next;
7628
7629 ASAN_UNPOISON_INTERVAL (&iblk->intervals[0]);
7630 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
7631 lisp_free (iblk);
7632 }
7633 else
7634 {
7635 num_free += this_free;
7636 iprev = &iblk->next;
7637 }
7638 }
7639 gcstat.total_intervals = num_used;
7640 gcstat.total_free_intervals = num_free;
7641 }
7642
7643 NO_INLINE
7644 static void
7645 sweep_symbols (void)
7646 {
7647 struct symbol_block *sblk;
7648 struct symbol_block **sprev = &symbol_block;
7649 int lim = symbol_block_index;
7650 object_ct num_free = 0, num_used = ARRAYELTS (lispsym);
7651
7652 symbol_free_list = NULL;
7653
7654 for (int i = 0; i < ARRAYELTS (lispsym); i++)
7655 lispsym[i].u.s.gcmarkbit = 0;
7656
7657 for (sblk = symbol_block; sblk; sblk = *sprev)
7658 {
7659 ASAN_UNPOISON_SYMBOL_BLOCK (sblk);
7660
7661 int this_free = 0;
7662 struct Lisp_Symbol *sym = sblk->symbols;
7663 struct Lisp_Symbol *end = sym + lim;
7664
7665 for (; sym < end; ++sym)
7666 {
7667 if (!sym->u.s.gcmarkbit)
7668 {
7669 if (sym->u.s.redirect == SYMBOL_LOCALIZED)
7670 {
7671 xfree (SYMBOL_BLV (sym));
7672
7673
7674
7675
7676
7677 sym->u.s.redirect = SYMBOL_PLAINVAL;
7678 }
7679 sym->u.s.next = symbol_free_list;
7680 symbol_free_list = sym;
7681 symbol_free_list->u.s.function = dead_object ();
7682 ASAN_POISON_SYMBOL (sym);
7683 ++this_free;
7684 }
7685 else
7686 {
7687 ++num_used;
7688 sym->u.s.gcmarkbit = 0;
7689
7690 eassert (valid_lisp_object_p (sym->u.s.function));
7691 }
7692 }
7693
7694 lim = SYMBOL_BLOCK_SIZE;
7695
7696
7697
7698 if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE)
7699 {
7700 *sprev = sblk->next;
7701
7702 ASAN_UNPOISON_SYMBOL (&sblk->symbols[0]);
7703 symbol_free_list = sblk->symbols[0].u.s.next;
7704 lisp_free (sblk);
7705 }
7706 else
7707 {
7708 num_free += this_free;
7709 sprev = &sblk->next;
7710 }
7711 }
7712 gcstat.total_symbols = num_used;
7713 gcstat.total_free_symbols = num_free;
7714 }
7715
7716
7717
7718 static void
7719 unchain_dead_markers (struct buffer *buffer)
7720 {
7721 struct Lisp_Marker *this, **prev = &BUF_MARKERS (buffer);
7722
7723 while ((this = *prev))
7724 if (vectorlike_marked_p (&this->header))
7725 prev = &this->next;
7726 else
7727 {
7728 this->buffer = NULL;
7729 *prev = this->next;
7730 }
7731 }
7732
7733 NO_INLINE
7734 static void
7735 sweep_buffers (void)
7736 {
7737 Lisp_Object tail, buf;
7738
7739 gcstat.total_buffers = 0;
7740 FOR_EACH_LIVE_BUFFER (tail, buf)
7741 {
7742 struct buffer *buffer = XBUFFER (buf);
7743
7744 buffer->text->intervals = balance_intervals (buffer->text->intervals);
7745 unchain_dead_markers (buffer);
7746 gcstat.total_buffers++;
7747 }
7748 }
7749
7750
7751 static void
7752 gc_sweep (void)
7753 {
7754 sweep_strings ();
7755 check_string_bytes (!noninteractive);
7756 sweep_conses ();
7757 sweep_floats ();
7758 sweep_intervals ();
7759 sweep_symbols ();
7760 sweep_buffers ();
7761 sweep_vectors ();
7762 pdumper_clear_marks ();
7763 check_string_bytes (!noninteractive);
7764 }
7765
7766 DEFUN ("memory-info", Fmemory_info, Smemory_info, 0, 0, 0,
7767 doc:
7768
7769
7770
7771
7772 )
7773 (void)
7774 {
7775 Lisp_Object handler
7776 = Ffind_file_name_handler (BVAR (current_buffer, directory),
7777 Qmemory_info);
7778 if (!NILP (handler))
7779 return call1 (handler, Qmemory_info);
7780
7781 #if defined HAVE_LINUX_SYSINFO
7782 struct sysinfo si;
7783 uintmax_t units;
7784
7785 if (sysinfo (&si))
7786 return Qnil;
7787 #ifdef LINUX_SYSINFO_UNIT
7788 units = si.mem_unit;
7789 #else
7790 units = 1;
7791 #endif
7792 return list4i ((uintmax_t) si.totalram * units / 1024,
7793 (uintmax_t) si.freeram * units / 1024,
7794 (uintmax_t) si.totalswap * units / 1024,
7795 (uintmax_t) si.freeswap * units / 1024);
7796 #elif defined WINDOWSNT
7797 unsigned long long totalram, freeram, totalswap, freeswap;
7798
7799 if (w32_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0)
7800 return list4i ((uintmax_t) totalram / 1024,
7801 (uintmax_t) freeram / 1024,
7802 (uintmax_t) totalswap / 1024,
7803 (uintmax_t) freeswap / 1024);
7804 else
7805 return Qnil;
7806 #elif defined MSDOS
7807 unsigned long totalram, freeram, totalswap, freeswap;
7808
7809 if (dos_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0)
7810 return list4i ((uintmax_t) totalram / 1024,
7811 (uintmax_t) freeram / 1024,
7812 (uintmax_t) totalswap / 1024,
7813 (uintmax_t) freeswap / 1024);
7814 else
7815 return Qnil;
7816 #else
7817
7818 return Qnil;
7819 #endif
7820 }
7821
7822
7823
7824 DEFUN ("memory-use-counts", Fmemory_use_counts, Smemory_use_counts, 0, 0, 0,
7825 doc:
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835 )
7836 (void)
7837 {
7838 return list (make_int (cons_cells_consed),
7839 make_int (floats_consed),
7840 make_int (vector_cells_consed),
7841 make_int (symbols_consed),
7842 make_int (string_chars_consed),
7843 make_int (intervals_consed),
7844 make_int (strings_consed));
7845 }
7846
7847 #if defined GNU_LINUX && defined __GLIBC__ && \
7848 (__GLIBC__ > 2 || __GLIBC_MINOR__ >= 10)
7849 DEFUN ("malloc-info", Fmalloc_info, Smalloc_info, 0, 0, "",
7850 doc:
7851
7852
7853 )
7854 (void)
7855 {
7856 if (malloc_info (0, stderr))
7857 error ("malloc_info failed: %s", emacs_strerror (errno));
7858 return Qnil;
7859 }
7860 #endif
7861
7862 #ifdef HAVE_MALLOC_TRIM
7863 DEFUN ("malloc-trim", Fmalloc_trim, Smalloc_trim, 0, 1, "",
7864 doc:
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874 )
7875 (Lisp_Object leave_padding)
7876 {
7877 int pad = 0;
7878
7879 if (! NILP (leave_padding))
7880 {
7881 CHECK_FIXNAT (leave_padding);
7882 pad = XFIXNUM (leave_padding);
7883 }
7884
7885
7886 if (malloc_trim (pad) == 1)
7887 return Qt;
7888 else
7889 return Qnil;
7890 }
7891 #endif
7892
7893 static bool
7894 symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj)
7895 {
7896 struct Lisp_Symbol *sym = XBARE_SYMBOL (symbol);
7897 Lisp_Object val = find_symbol_value (symbol);
7898 return (EQ (val, obj)
7899 || EQ (sym->u.s.function, obj)
7900 || (!NILP (sym->u.s.function)
7901 && COMPILEDP (sym->u.s.function)
7902 && EQ (AREF (sym->u.s.function, COMPILED_BYTECODE), obj))
7903 || (!NILP (val)
7904 && COMPILEDP (val)
7905 && EQ (AREF (val, COMPILED_BYTECODE), obj)));
7906 }
7907
7908
7909
7910
7911 Lisp_Object
7912 which_symbols (Lisp_Object obj, EMACS_INT find_max)
7913 {
7914 struct symbol_block *sblk;
7915 specpdl_ref gc_count = inhibit_garbage_collection ();
7916 Lisp_Object found = Qnil;
7917
7918 if (! deadp (obj))
7919 {
7920 for (int i = 0; i < ARRAYELTS (lispsym); i++)
7921 {
7922 Lisp_Object sym = builtin_lisp_symbol (i);
7923 if (symbol_uses_obj (sym, obj))
7924 {
7925 found = Fcons (sym, found);
7926 if (--find_max == 0)
7927 goto out;
7928 }
7929 }
7930
7931 for (sblk = symbol_block; sblk; sblk = sblk->next)
7932 {
7933 struct Lisp_Symbol *asym = sblk->symbols;
7934 int bn;
7935
7936 for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, asym++)
7937 {
7938 if (sblk == symbol_block && bn >= symbol_block_index)
7939 break;
7940
7941 Lisp_Object sym = make_lisp_symbol (asym);
7942 if (symbol_uses_obj (sym, obj))
7943 {
7944 found = Fcons (sym, found);
7945 if (--find_max == 0)
7946 goto out;
7947 }
7948 }
7949 }
7950 }
7951
7952 out:
7953 return unbind_to (gc_count, found);
7954 }
7955
7956 #ifdef SUSPICIOUS_OBJECT_CHECKING
7957
7958 static void *
7959 find_suspicious_object_in_range (void *begin, void *end)
7960 {
7961 char *begin_a = begin;
7962 char *end_a = end;
7963 int i;
7964
7965 for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
7966 {
7967 char *suspicious_object = suspicious_objects[i];
7968 if (begin_a <= suspicious_object && suspicious_object < end_a)
7969 return suspicious_object;
7970 }
7971
7972 return NULL;
7973 }
7974
7975 static void
7976 note_suspicious_free (void *ptr)
7977 {
7978 struct suspicious_free_record *rec;
7979
7980 rec = &suspicious_free_history[suspicious_free_history_index++];
7981 if (suspicious_free_history_index ==
7982 ARRAYELTS (suspicious_free_history))
7983 {
7984 suspicious_free_history_index = 0;
7985 }
7986
7987 memset (rec, 0, sizeof (*rec));
7988 rec->suspicious_object = ptr;
7989 backtrace (&rec->backtrace[0], ARRAYELTS (rec->backtrace));
7990 }
7991
7992 static void
7993 detect_suspicious_free (void *ptr)
7994 {
7995 int i;
7996
7997 eassert (ptr != NULL);
7998
7999 for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
8000 if (suspicious_objects[i] == ptr)
8001 {
8002 note_suspicious_free (ptr);
8003 suspicious_objects[i] = NULL;
8004 }
8005 }
8006
8007 #endif
8008
8009 DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0,
8010 doc:
8011
8012
8013 )
8014 (Lisp_Object obj)
8015 {
8016 #ifdef SUSPICIOUS_OBJECT_CHECKING
8017
8018 if (VECTORLIKEP (obj))
8019 {
8020 suspicious_objects[suspicious_object_index++] = XVECTOR (obj);
8021 if (suspicious_object_index == ARRAYELTS (suspicious_objects))
8022 suspicious_object_index = 0;
8023 }
8024 #endif
8025 return obj;
8026 }
8027
8028 #ifdef ENABLE_CHECKING
8029
8030 bool suppress_checking;
8031
8032 void
8033 die (const char *msg, const char *file, int line)
8034 {
8035 fprintf (stderr, "\r\n%s:%d: Emacs fatal error: assertion failed: %s\r\n",
8036 file, line, msg);
8037 terminate_due_to_signal (SIGABRT, INT_MAX);
8038 }
8039
8040 #endif
8041
8042 #if defined (ENABLE_CHECKING) && USE_STACK_LISP_OBJECTS
8043
8044
8045
8046
8047 NO_INLINE static void
8048 verify_alloca (void)
8049 {
8050 int i;
8051 enum { ALLOCA_CHECK_MAX = 256 };
8052
8053 for (i = sizeof (struct Lisp_Cons); i <= ALLOCA_CHECK_MAX; i++)
8054 {
8055 void *ptr = alloca (i);
8056 make_lisp_ptr (ptr, Lisp_Cons);
8057 }
8058 }
8059
8060 #else
8061
8062 #define verify_alloca() ((void) 0)
8063
8064 #endif
8065
8066
8067
8068 static void init_alloc_once_for_pdumper (void);
8069
8070 void
8071 init_alloc_once (void)
8072 {
8073 gc_cons_threshold = GC_DEFAULT_THRESHOLD;
8074
8075 Vpurify_flag = Qt;
8076
8077 PDUMPER_REMEMBER_SCALAR (buffer_defaults.header);
8078 PDUMPER_REMEMBER_SCALAR (buffer_local_symbols.header);
8079
8080
8081
8082
8083 pdumper_do_now_and_after_load (init_alloc_once_for_pdumper);
8084
8085 verify_alloca ();
8086
8087 init_strings ();
8088 init_vectors ();
8089 }
8090
8091 static void
8092 init_alloc_once_for_pdumper (void)
8093 {
8094 purebeg = PUREBEG;
8095 pure_size = PURESIZE;
8096 mem_init ();
8097
8098 #ifdef DOUG_LEA_MALLOC
8099 mallopt (M_TRIM_THRESHOLD, 128 * 1024);
8100 mallopt (M_MMAP_THRESHOLD, 64 * 1024);
8101 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
8102 #endif
8103
8104
8105 init_finalizer_list (&finalizers);
8106 init_finalizer_list (&doomed_finalizers);
8107 refill_memory_reserve ();
8108 }
8109
8110 void
8111 init_alloc (void)
8112 {
8113 Vgc_elapsed = make_float (0.0);
8114 gcs_done = 0;
8115 }
8116
8117 void
8118 syms_of_alloc (void)
8119 {
8120 DEFVAR_INT ("gc-cons-threshold", gc_cons_threshold,
8121 doc:
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132 );
8133
8134 DEFVAR_LISP ("gc-cons-percentage", Vgc_cons_percentage,
8135 doc:
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145 );
8146 Vgc_cons_percentage = make_float (0.1);
8147
8148 DEFVAR_INT ("pure-bytes-used", pure_bytes_used,
8149 doc: );
8150
8151 DEFVAR_INT ("cons-cells-consed", cons_cells_consed,
8152 doc: );
8153
8154 DEFVAR_INT ("floats-consed", floats_consed,
8155 doc: );
8156
8157 DEFVAR_INT ("vector-cells-consed", vector_cells_consed,
8158 doc: );
8159
8160 DEFVAR_INT ("symbols-consed", symbols_consed,
8161 doc: );
8162 symbols_consed += ARRAYELTS (lispsym);
8163
8164 DEFVAR_INT ("string-chars-consed", string_chars_consed,
8165 doc: );
8166
8167 DEFVAR_INT ("intervals-consed", intervals_consed,
8168 doc: );
8169
8170 DEFVAR_INT ("strings-consed", strings_consed,
8171 doc: );
8172
8173 DEFVAR_LISP ("purify-flag", Vpurify_flag,
8174 doc:
8175
8176
8177 );
8178
8179 DEFVAR_BOOL ("garbage-collection-messages", garbage_collection_messages,
8180 doc: );
8181 garbage_collection_messages = 0;
8182
8183 DEFVAR_LISP ("post-gc-hook", Vpost_gc_hook,
8184 doc: );
8185 Vpost_gc_hook = Qnil;
8186 DEFSYM (Qpost_gc_hook, "post-gc-hook");
8187
8188 DEFVAR_LISP ("memory-signal-data", Vmemory_signal_data,
8189 doc: );
8190
8191
8192 Vmemory_signal_data
8193 = pure_list (Qerror,
8194 build_pure_c_string ("Memory exhausted--use"
8195 " M-x save-some-buffers then"
8196 " exit and restart Emacs"));
8197
8198 DEFVAR_LISP ("memory-full", Vmemory_full,
8199 doc: );
8200 Vmemory_full = Qnil;
8201
8202 DEFSYM (Qmemory_info, "memory-info");
8203
8204 DEFSYM (Qconses, "conses");
8205 DEFSYM (Qsymbols, "symbols");
8206 DEFSYM (Qstrings, "strings");
8207 DEFSYM (Qvectors, "vectors");
8208 DEFSYM (Qfloats, "floats");
8209 DEFSYM (Qintervals, "intervals");
8210 DEFSYM (Qbuffers, "buffers");
8211 DEFSYM (Qstring_bytes, "string-bytes");
8212 DEFSYM (Qvector_slots, "vector-slots");
8213 DEFSYM (Qheap, "heap");
8214 DEFSYM (QAutomatic_GC, "Automatic GC");
8215
8216 DEFSYM (Qgc_cons_percentage, "gc-cons-percentage");
8217 DEFSYM (Qgc_cons_threshold, "gc-cons-threshold");
8218 DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots");
8219
8220 DEFVAR_LISP ("gc-elapsed", Vgc_elapsed,
8221 doc:
8222 );
8223 DEFVAR_INT ("gcs-done", gcs_done,
8224 doc: );
8225
8226 DEFVAR_INT ("integer-width", integer_width,
8227 doc:
8228
8229 );
8230
8231 defsubr (&Scons);
8232 defsubr (&Slist);
8233 defsubr (&Svector);
8234 defsubr (&Srecord);
8235 defsubr (&Sbool_vector);
8236 defsubr (&Smake_byte_code);
8237 defsubr (&Smake_closure);
8238 defsubr (&Smake_list);
8239 defsubr (&Smake_vector);
8240 defsubr (&Smake_record);
8241 defsubr (&Smake_string);
8242 defsubr (&Smake_bool_vector);
8243 defsubr (&Smake_symbol);
8244 defsubr (&Smake_marker);
8245 defsubr (&Smake_finalizer);
8246 defsubr (&Spurecopy);
8247 defsubr (&Sgarbage_collect);
8248 defsubr (&Sgarbage_collect_maybe);
8249 defsubr (&Smemory_info);
8250 defsubr (&Smemory_use_counts);
8251 #if defined GNU_LINUX && defined __GLIBC__ && \
8252 (__GLIBC__ > 2 || __GLIBC_MINOR__ >= 10)
8253
8254 defsubr (&Smalloc_info);
8255 #endif
8256 #ifdef HAVE_MALLOC_TRIM
8257 defsubr (&Smalloc_trim);
8258 #endif
8259 defsubr (&Ssuspicious_object);
8260
8261 Lisp_Object watcher;
8262
8263 static union Aligned_Lisp_Subr Swatch_gc_cons_threshold =
8264 {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
8265 { .a4 = watch_gc_cons_threshold },
8266 4, 4, "watch_gc_cons_threshold", {0}, lisp_h_Qnil}};
8267 XSETSUBR (watcher, &Swatch_gc_cons_threshold.s);
8268 Fadd_variable_watcher (Qgc_cons_threshold, watcher);
8269
8270 static union Aligned_Lisp_Subr Swatch_gc_cons_percentage =
8271 {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
8272 { .a4 = watch_gc_cons_percentage },
8273 4, 4, "watch_gc_cons_percentage", {0}, lisp_h_Qnil}};
8274 XSETSUBR (watcher, &Swatch_gc_cons_percentage.s);
8275 Fadd_variable_watcher (Qgc_cons_percentage, watcher);
8276 }
8277
8278 #ifdef HAVE_X_WINDOWS
8279 enum defined_HAVE_X_WINDOWS { defined_HAVE_X_WINDOWS = true };
8280 #else
8281 enum defined_HAVE_X_WINDOWS { defined_HAVE_X_WINDOWS = false };
8282 #endif
8283
8284 #ifdef HAVE_PGTK
8285 enum defined_HAVE_PGTK { defined_HAVE_PGTK = true };
8286 #else
8287 enum defined_HAVE_PGTK { defined_HAVE_PGTK = false };
8288 #endif
8289
8290
8291
8292
8293
8294 #ifdef __GNUC__
8295 union
8296 {
8297 enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS;
8298 enum char_table_specials char_table_specials;
8299 enum char_bits char_bits;
8300 enum CHECK_LISP_OBJECT_TYPE CHECK_LISP_OBJECT_TYPE;
8301 enum DEFAULT_HASH_SIZE DEFAULT_HASH_SIZE;
8302 enum Lisp_Bits Lisp_Bits;
8303 enum Lisp_Compiled Lisp_Compiled;
8304 enum maxargs maxargs;
8305 enum MAX_ALLOCA MAX_ALLOCA;
8306 enum More_Lisp_Bits More_Lisp_Bits;
8307 enum pvec_type pvec_type;
8308 enum defined_HAVE_X_WINDOWS defined_HAVE_X_WINDOWS;
8309 enum defined_HAVE_PGTK defined_HAVE_PGTK;
8310 } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0};
8311 #endif