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