aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorDaniel Colascione2019-01-15 17:36:54 -0500
committerDaniel Colascione2019-01-15 17:37:36 -0500
commitd12e5d003d503025c1c9b0335d6518a6c3bdfae1 (patch)
tree41829446caca2d488e723843046c4f5b8931d8f8 /src/alloc.c
parent2a3bd6798e9670828f0402079fcc116d6d6b042d (diff)
downloademacs-d12e5d003d503025c1c9b0335d6518a6c3bdfae1.tar.gz
emacs-d12e5d003d503025c1c9b0335d6518a6c3bdfae1.zip
Add portable dumper
Add a new portable dumper as an alternative to unexec. Use it by default. * src/dmpstruct.awk: New file. * src/doc.c (get_doc_string): use will_dump_p(). * src/editfns.c (styled_format): silence compiler warning with UNINIT. * src/emacs-module.c (syms_of_module): staticpro ltv_mark. * src/emacs.c (gflags): new variable. (init_cmdargs): unwrap (string_starts_with_p, find_argument, dump_error_to_string) (load_pdump): new functions. (main): detect pdumper and --temacs invocation; actually load portable dump when detected; set gflags as appropriate; changes to init functions throughout to avoid passing explicit 'initialized' argument. * src/eval.c (inhibit_lisp_code): remove unused variable. (init_eval_once_for_pdumper): new function. (init_eval_once): call it. * src/filelock.c: CANNOT_DUMP -> will_dump_p() * src/fingerprint-dummy.c: new file * src/fingerprint.h: new file * src/fns.c: CANNOT_DUMP -> will_dump_p(), etc. (weak_hash_tables): remove (hashfn_equal, hashfn_eql): un-staticify (make_hash_table): set new 'next_weak' hash table field; drop global weak_hash_tables logic. (copy_hash_table): drop global weak_hash_tables logic. (hash_table_rehash): new function. (hash_lookup, hash_put, hash_remove_from_table, hash_clear): rehash if needed. (sweep_weak_table): un-staticify; explain logic; bool-ify. (sweep_weak_hash_tables): remove function. * src/font.c (syms_of_font): remember pdumper stuff. * src/fontset.c (syms_of_fontset): remember pdumper stuff. * src/frame.c (make_initial_frame): don't reset Vframe_list. (init_frame_once_for_pdumper, init_frame_once): new functions. (syms_of_frame): remove redundant staticpro. * src/fringe.c (init_fringe_once_for_pdumper): new functin. (init_fringe_once): call it. * src/ftcrfont.c (syms_of_ftcrfont_for_pdumper): new function. (syms_of_ftcrfont): call it. * src/ftfont.c (syms_of_ftfont_for_pdumper): new function. (syms_of_ftfont): call it. * src/ftxont.c (syms_of_ftxfont_for_pdumper): new function. (syms_of_ftxfont): call it. * src/gmalloc.c: adjust for pdumper througout (DUMPED): remove weird custom dumped indicator. * src/gnutls.c (syms_of_gnutls): pdumper note for gnutls_global_initialized. * src/image.c (syms_of_image): add pdumper comment, initializer note. * src/insdel.c (prepare_to_modify_buffer_1): account for buffer contents possibly being in dump image. * src/keyboard.c (syms_of_keyboard_for_pdumper): new function. (syms_of_keyboard): staticpro more; call pdumper syms function. * src/lisp.h: add comments throughout (gflags): declare. (will_dump_p, will_bootstrap_p, will_dump_with_pdumper_p) (dumped_with_pdumper_p, will_dump_with_unexec_p) (dumped_with_unexec_p, definitely_will_not_unexec_p): new functions. (POWER_OF_2, ROUNDUP): move macros. (PSEUDOVECTOR_TYPE, PSEUDOVECTOR_TYPEP): take vectorlike header pointer instead of vector; constify. (Lisp_Hash_Table): add comment about need to rehash on access; add comment for next_weak. (HASH_KEY, HASH_VALUE, HASH_HASH, HASH_TABLE_SIZE): const-ify. (hash_table_rehash): declare. (hash_rehash_needed_p, hash_rehash_if_needed): new functions. (finalizers, doomed_finalizers): declare extern. (SUBR_SECTION_ATTRIBUTE): new macro. (staticvec, staticidx): un-static-ify. (sweep_weak_hash_tables): remove declaration. (sweep_weak_table): declare. (hashfn_eql, hashfn_equal): declare. (number_finalizers_run): new variable. (Vdead): externify when ENABLE_CHECKING. (gc_root_type): new enumeration. (gc_root_visitor): new struct. (visit_static_gc_roots): declare. (vectorlike_nbytes): declare. (vector_nbytes): define as trivial inline function wrapper for vectorlike_nbytes. (init_obarray_once): change signature. (primary_thread): extern-ify. (init_buffer): change signature. (init_frame_once): declare. * src/lread.c (readevalloop): adjust for new dumped predicates. (init_obarray_once): new function. (ndefsubr): new variable. (defsubr): increment it. (load_path_check): adjust for pdumper. (load_path_default): use pdumper functions; adjust for dump search. * src/macfont.m (macfont_init_font_change_handler): avoid shadowing global. (syms_of_macfont_for_pdumper): new function. (syms_of_macfont): call it. * src/menu.c (syms_of_menu): staticpro more stuff. * src/minibuf.c (Ftry_completion): rehash if needed. (init_minibuf_once_for_pdumper): new function. (init_minibuf_once): call it. * src/nsfont.m (syms_of_nsfns): staticpro more. * src/nsfont.m (syms_of_nsfont_for_pdumper): new function. (syms_of_nsfont): call it. * src/nsterm.m (syms_of_nsfont): remember pdumper stuff. * src/pdumper.c: new file. * src/pdumper.h: new file. * src/process.c (init_process_emacs): use new pdumper functions instead of CANNOT_DUMP. * src/profiler.c (syms_of_profiler_for_pdumper): new function. (syms_of_profiler_for_pdumper): call it. * src/search.c (syms_of_search_for_pdumper): new function. (syms_of_search_for_pdumper): call it. * src/sheap.c (bss_sbrk_did_unexec): remove. * src/sheap.h (bss_sbrk_did_unexec): remove. * src/syntax.c (syms_of_syntax): don't redundantly staticpro re_match_object. * src/sysdep.c: use will_dump_with_unexec_p() instead of bss hack thing. * src/syssignals.h (init_sigsegv): declare. * src/systime.h (init_timefns): remove bool from signature. * src/textprop.c (syms_of_textprop): move staticpro. * src/thread.c (main_thread_p): constify. * src/thread.h (main_thread_p): constify. * src/timefns.c (init_timefns): remove bool from signature. (syms_of_timefns_for_pdumper): new function. (syms_of_timefns): call it. * src/w32.c: rearrange code. * src/w32.h (w32_relocate): declare. * src/w32fns.c (syms_of_w32fns): add pdumper note. * src/w32font.c (syms_of_w32font_for_pdumper): new function. (syms_of_w32font): call it. * src/w32heap.c (using_dynamic_heap): new variable. (init_heap): use it. * src/w32menu.c (syms_of_w32menu): add pdumper note. * src/w32proc.c (ctrl_c_handler, mainCRTStartup, _start, open_input_file) (rva_to_section, close_file_data): move here. * src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper): new function. (syms_of_w32uniscribe): call it. * src/window.c (init_window_once_for_pdumper): new function. (init_window_once): call it; staticpro more stuff. * src/xfont.c (syms_of_xfont_for_pdumper): new function. (syms_of_xfont): call it. * src/xftfont.c (syms_of_xftfont_for_pdumper): new function. (syms_of_xftfont): call it. * src/xmenu.c (syms_of_xmenu_for_pdumper): new function. (syms_of_xmenu): call it. * src/xselect.c (syms_of_xselect_for_pdumper): new function. (syms_of_xselect): call it. * src/xsettings.c (syms_of_xsettings): add more pdumper notes. * src/term.c (syms_of_xterm): add pdumper note. * src/dispnew.c (init_faces_initial): new function. (init_display_interactive): rename from init_display; use will_dump_p instead of !initialized. Initialize faces early for pdumper if needed. (init_display): new function. (syms_of_display_for_pdumper): new function. (syms_of_display): call it. * src/dbusbind.c (syms_of_dbusbind): Add TODO for bus reset on pdumper load. * src/data.c (Fdefalias): Use will_dump_p instead of Vpurify_flag. (Fmake_variable_buffer_local): silence compiler warning with -Og by making valcontents UNINIT. (arith_driver): silence compiler warning with UNINIT. * src/conf_post.h (ATTRIBUTE_SECTION): new macro. * src/composite.c (composition_gstring_put_cache): rehash hash table if needed. * src/coding.c (init_coding_once, syms_of_coding): remember pdumper stuff. * src/charset.h (charset_table_size, charset_table_user): declare. * src/charset.c (charset_table_used, charset_table_size): un-static. (init_charset_oncem, syms_of_charset): remember pdumper stuff. * src/category.c (category_table_version): remove obsolete variable. * src/callint.c (syms_of_callint): staticpro 'preserved_fns' (init_callproc): use will_dump_p instead of !CANNOT_DUMP. * src/bytecode.c (exec_byte_code): rehash table tables if needed * src/buffer.c (alloc_buffer_text, free_buffer_text): account for pdumper (init_buffer_once): add TODO; remember stuff for pdumper. (init_buffer): don't take initialized argument; adjust for pdumper. * src/atimer.c (init_atimer): initialize subr only if !initialized. * src/alloc.c: (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): new accessor routines. Use them instead of raw GC access throughout. (Vdead): make non-static when ENABLE_CHECKING. (vectorlike_nbytes): rename of 'vector_nbytes'; take a vectorlike header as input instead of a vector. (number_finalizers_run): new internal C variable. (mark_maybe_object): check for pdumper objects. (valid_pointer_p): don't be gratuitously inefficient under rr(1). (make_pure_c_string): add support for size_byte = -2 mode indicating that string data points into Emacs image rodata. (visit_vectorlike_root): visits GC roots embedded in vectorlike objects. (visit_buffer_root): visits GC roots embedded in our totally-not-a-buffer buffer global objects. (visit_static_gc_roots): visit GC roots in the Emacs data section. (mark_object_root_visitor): root callback used for conventional GC marking (weak_hash_tables): new internal variable for tracking found weak hash tables during GC. (mark_and_sweep_weak_table_contents): new weak hash table marking. (garbage_collect_1): use new GC root visitor machinery. (mark_vectorlike): accept a vectorlike_header instead of a Lisp_Vector. (mark_frame, mark_window, mark_hash_table): new functions. (mark_object): initialize 'm'; check for pdumper objects and use new mark-bit accessors throughout. Remove some object-specific marking code and move to helper functions above. (survives_gc_p): check for pdumper objects. (gc-sweep): clear pdumper mark bits. (init_alloc_once_for_pdumper): new helper function for early init called both during normal init and pdumper load. (init_alloc_once): pdumper integration. * src/Makefile.in: Rewrite dumping for pdumper; add pdumper.o; invoke temacs with --temacs command line option; build dmpstruct.h from dmpstruct.awk; stop relying on CANNOT_DUMP; clean up pdumper intermediate files during build. * nextstep/Makefile.in: build emacs.pdmp into NS packages * lisp/startup.el: account for new '--temacs' and '--dump-file' command line option. * lisp/loadup.el: rewrite early init to account for pdumper; use injected 'dump-mode' variable (set via the new '--temacs' option) instead of parsing command line. * lisp/cus-start.el: Check 'dump-mode' instead of 'purify-flag', since the new 'dump-mode' * lib-src/make-fingerprint.c: new program * lib-src/Makefile.in: built make-fingerprint utility program * configure.ac: Add --with-pdumper toggle to control pdumper support; add --with-unexec toggle to control unexec support. Add --with-dumping option to control which dumping strategy we use by default. Adjust for pdumper throughout. Check for posix_madvise. * Makefile.in: Add @DUMPING@ substitution; add pdumper mode. * .gitignore: Add make-fingerprint, temacs.in, fingerprint.c, dmpstruct.h, and pdumper dump files.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c815
1 files changed, 577 insertions, 238 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 31e8da70161..8054aa5ae59 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -44,6 +44,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
44#include "keyboard.h" 44#include "keyboard.h"
45#include "frame.h" 45#include "frame.h"
46#include "blockinput.h" 46#include "blockinput.h"
47#include "pdumper.h"
47#include "termhooks.h" /* For struct terminal. */ 48#include "termhooks.h" /* For struct terminal. */
48#ifdef HAVE_WINDOW_SYSTEM 49#ifdef HAVE_WINDOW_SYSTEM
49#include TERM_HEADER 50#include TERM_HEADER
@@ -65,16 +66,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
65# include <malloc.h> 66# include <malloc.h>
66#endif 67#endif
67 68
68#if (defined ENABLE_CHECKING \ 69#if defined HAVE_VALGRIND_VALGRIND_H && !defined USE_VALGRIND
69 && defined HAVE_VALGRIND_VALGRIND_H \
70 && !defined USE_VALGRIND)
71# define USE_VALGRIND 1 70# define USE_VALGRIND 1
72#endif 71#endif
73 72
74#if USE_VALGRIND 73#if USE_VALGRIND
75#include <valgrind/valgrind.h> 74#include <valgrind/valgrind.h>
76#include <valgrind/memcheck.h> 75#include <valgrind/memcheck.h>
77static bool valgrind_p;
78#endif 76#endif
79 77
80/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. 78/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
@@ -194,9 +192,6 @@ alloc_unexec_pre (void)
194 if (!malloc_state_ptr) 192 if (!malloc_state_ptr)
195 fatal ("malloc_get_state: %s", strerror (errno)); 193 fatal ("malloc_get_state: %s", strerror (errno));
196# endif 194# endif
197# ifdef HYBRID_MALLOC
198 bss_sbrk_did_unexec = true;
199# endif
200} 195}
201 196
202void 197void
@@ -205,22 +200,19 @@ alloc_unexec_post (void)
205# ifdef DOUG_LEA_MALLOC 200# ifdef DOUG_LEA_MALLOC
206 free (malloc_state_ptr); 201 free (malloc_state_ptr);
207# endif 202# endif
208# ifdef HYBRID_MALLOC
209 bss_sbrk_did_unexec = false;
210# endif
211} 203}
212#endif 204#endif
213 205
214/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer 206/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer
215 to a struct Lisp_String. */ 207 to a struct Lisp_String. */
216 208
217#define MARK_STRING(S) ((S)->u.s.size |= ARRAY_MARK_FLAG) 209#define XMARK_STRING(S) ((S)->u.s.size |= ARRAY_MARK_FLAG)
218#define UNMARK_STRING(S) ((S)->u.s.size &= ~ARRAY_MARK_FLAG) 210#define XUNMARK_STRING(S) ((S)->u.s.size &= ~ARRAY_MARK_FLAG)
219#define STRING_MARKED_P(S) (((S)->u.s.size & ARRAY_MARK_FLAG) != 0) 211#define XSTRING_MARKED_P(S) (((S)->u.s.size & ARRAY_MARK_FLAG) != 0)
220 212
221#define VECTOR_MARK(V) ((V)->header.size |= ARRAY_MARK_FLAG) 213#define XMARK_VECTOR(V) ((V)->header.size |= ARRAY_MARK_FLAG)
222#define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG) 214#define XUNMARK_VECTOR(V) ((V)->header.size &= ~ARRAY_MARK_FLAG)
223#define VECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0) 215#define XVECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0)
224 216
225/* Default value of gc_cons_threshold (see below). */ 217/* Default value of gc_cons_threshold (see below). */
226 218
@@ -242,6 +234,12 @@ byte_ct gc_relative_threshold;
242 234
243byte_ct memory_full_cons_threshold; 235byte_ct memory_full_cons_threshold;
244 236
237#ifdef HAVE_PDUMPER
238/* Number of finalizers run: used to loop over GC until we stop
239 generating garbage. */
240int number_finalizers_run;
241#endif
242
245/* True during GC. */ 243/* True during GC. */
246 244
247bool gc_in_progress; 245bool gc_in_progress;
@@ -375,6 +373,27 @@ static void compact_small_strings (void);
375static void free_large_strings (void); 373static void free_large_strings (void);
376extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE; 374extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
377 375
376/* Forward declare mark accessor functions: they're used all over the
377 place. */
378
379inline static bool vector_marked_p (const struct Lisp_Vector *v);
380inline static void set_vector_marked (struct Lisp_Vector *v);
381
382inline static bool vectorlike_marked_p (const union vectorlike_header *v);
383inline static void set_vectorlike_marked (union vectorlike_header *v);
384
385inline static bool cons_marked_p (const struct Lisp_Cons *c);
386inline static void set_cons_marked (struct Lisp_Cons *c);
387
388inline static bool string_marked_p (const struct Lisp_String *s);
389inline static void set_string_marked (struct Lisp_String *s);
390
391inline static bool symbol_marked_p (const struct Lisp_Symbol *s);
392inline static void set_symbol_marked (struct Lisp_Symbol *s);
393
394inline static bool interval_marked_p (INTERVAL i);
395inline static void set_interval_marked (INTERVAL i);
396
378/* When scanning the C stack for live Lisp objects, Emacs keeps track of 397/* When scanning the C stack for live Lisp objects, Emacs keeps track of
379 what memory allocated via lisp_malloc and lisp_align_malloc is intended 398 what memory allocated via lisp_malloc and lisp_align_malloc is intended
380 for what purpose. This enumeration specifies the type of memory. */ 399 for what purpose. This enumeration specifies the type of memory. */
@@ -400,7 +419,10 @@ enum mem_type
400/* A unique object in pure space used to make some Lisp objects 419/* A unique object in pure space used to make some Lisp objects
401 on free lists recognizable in O(1). */ 420 on free lists recognizable in O(1). */
402 421
403static Lisp_Object Vdead; 422#ifndef ENABLE_CHECKING
423static
424#endif
425Lisp_Object Vdead;
404#define DEADP(x) EQ (x, Vdead) 426#define DEADP(x) EQ (x, Vdead)
405 427
406#ifdef GC_MALLOC_CHECK 428#ifdef GC_MALLOC_CHECK
@@ -478,30 +500,21 @@ static struct mem_node *mem_find (void *);
478#endif 500#endif
479 501
480/* Addresses of staticpro'd variables. Initialize it to a nonzero 502/* Addresses of staticpro'd variables. Initialize it to a nonzero
481 value; otherwise some compilers put it into BSS. */ 503 value if we might dump; otherwise some compilers put it into
504 BSS. */
482 505
483enum { NSTATICS = 2048 }; 506Lisp_Object *staticvec[NSTATICS]
484static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag}; 507#ifndef CANNOT_DUMP
508= {&Vpurify_flag}
509#endif
510 ;
485 511
486/* Index of next unused slot in staticvec. */ 512/* Index of next unused slot in staticvec. */
487 513
488static int staticidx; 514int staticidx;
489 515
490static void *pure_alloc (size_t, int); 516static void *pure_alloc (size_t, int);
491 517
492/* True if N is a power of 2. N should be positive. */
493
494#define POWER_OF_2(n) (((n) & ((n) - 1)) == 0)
495
496/* Return X rounded to the next multiple of Y. Y should be positive,
497 and Y - 1 + X should not overflow. Arguments should not have side
498 effects, as they are evaluated more than once. Tune for Y being a
499 power of 2. */
500
501#define ROUNDUP(x, y) (POWER_OF_2 (y) \
502 ? ((y) - 1 + (x)) & ~ ((y) - 1) \
503 : ((y) - 1 + (x)) - ((y) - 1 + (x)) % (y))
504
505/* Return PTR rounded up to the next multiple of ALIGNMENT. */ 518/* Return PTR rounded up to the next multiple of ALIGNMENT. */
506 519
507static void * 520static void *
@@ -571,18 +584,18 @@ mmap_lisp_allowed_p (void)
571 over our address space. We also can't use mmap for lisp objects 584 over our address space. We also can't use mmap for lisp objects
572 if we might dump: unexec doesn't preserve the contents of mmapped 585 if we might dump: unexec doesn't preserve the contents of mmapped
573 regions. */ 586 regions. */
574 return pointers_fit_in_lispobj_p () && !might_dump; 587 return pointers_fit_in_lispobj_p () && !will_dump_with_unexec_p ();
575} 588}
576#endif 589#endif
577 590
578/* Head of a circularly-linked list of extant finalizers. */ 591/* Head of a circularly-linked list of extant finalizers. */
579static struct Lisp_Finalizer finalizers; 592struct Lisp_Finalizer finalizers;
580 593
581/* Head of a circularly-linked list of finalizers that must be invoked 594/* Head of a circularly-linked list of finalizers that must be invoked
582 because we deemed them unreachable. This list must be global, and 595 because we deemed them unreachable. This list must be global, and
583 not a local inside garbage_collect_1, in case we GC again while 596 not a local inside garbage_collect_1, in case we GC again while
584 running finalizers. */ 597 running finalizers. */
585static struct Lisp_Finalizer doomed_finalizers; 598struct Lisp_Finalizer doomed_finalizers;
586 599
587 600
588/************************************************************************ 601/************************************************************************
@@ -931,6 +944,8 @@ xfree (void *block)
931{ 944{
932 if (!block) 945 if (!block)
933 return; 946 return;
947 if (pdumper_object_p (block))
948 return;
934 MALLOC_BLOCK_INPUT; 949 MALLOC_BLOCK_INPUT;
935 free (block); 950 free (block);
936 MALLOC_UNBLOCK_INPUT; 951 MALLOC_UNBLOCK_INPUT;
@@ -1153,6 +1168,9 @@ lisp_malloc (size_t nbytes, enum mem_type type)
1153static void 1168static void
1154lisp_free (void *block) 1169lisp_free (void *block)
1155{ 1170{
1171 if (pdumper_object_p (block))
1172 return;
1173
1156 MALLOC_BLOCK_INPUT; 1174 MALLOC_BLOCK_INPUT;
1157 free (block); 1175 free (block);
1158#ifndef GC_MALLOC_CHECK 1176#ifndef GC_MALLOC_CHECK
@@ -1569,22 +1587,23 @@ make_interval (void)
1569/* Mark Lisp objects in interval I. */ 1587/* Mark Lisp objects in interval I. */
1570 1588
1571static void 1589static void
1572mark_interval (INTERVAL i, void *dummy) 1590mark_interval_tree_1 (INTERVAL i, void *dummy)
1573{ 1591{
1574 /* Intervals should never be shared. So, if extra internal checking is 1592 /* Intervals should never be shared. So, if extra internal checking is
1575 enabled, GC aborts if it seems to have visited an interval twice. */ 1593 enabled, GC aborts if it seems to have visited an interval twice. */
1576 eassert (!i->gcmarkbit); 1594 eassert (!interval_marked_p (i));
1577 i->gcmarkbit = 1; 1595 set_interval_marked (i);
1578 mark_object (i->plist); 1596 mark_object (i->plist);
1579} 1597}
1580 1598
1581/* Mark the interval tree rooted in I. */ 1599/* Mark the interval tree rooted in I. */
1582 1600
1583#define MARK_INTERVAL_TREE(i) \ 1601static void
1584 do { \ 1602mark_interval_tree (INTERVAL i)
1585 if (i && !i->gcmarkbit) \ 1603{
1586 traverse_intervals_noorder (i, mark_interval, NULL); \ 1604 if (i && !interval_marked_p (i))
1587 } while (0) 1605 traverse_intervals_noorder (i, mark_interval_tree_1, NULL);
1606}
1588 1607
1589/*********************************************************************** 1608/***********************************************************************
1590 String Allocation 1609 String Allocation
@@ -1820,7 +1839,9 @@ static void
1820init_strings (void) 1839init_strings (void)
1821{ 1840{
1822 empty_unibyte_string = make_pure_string ("", 0, 0, 0); 1841 empty_unibyte_string = make_pure_string ("", 0, 0, 0);
1842 staticpro (&empty_unibyte_string);
1823 empty_multibyte_string = make_pure_string ("", 0, 0, 1); 1843 empty_multibyte_string = make_pure_string ("", 0, 0, 1);
1844 staticpro (&empty_multibyte_string);
1824} 1845}
1825 1846
1826 1847
@@ -2114,10 +2135,10 @@ sweep_strings (void)
2114 if (s->u.s.data) 2135 if (s->u.s.data)
2115 { 2136 {
2116 /* String was not on free-list before. */ 2137 /* String was not on free-list before. */
2117 if (STRING_MARKED_P (s)) 2138 if (XSTRING_MARKED_P (s))
2118 { 2139 {
2119 /* String is live; unmark it and its intervals. */ 2140 /* String is live; unmark it and its intervals. */
2120 UNMARK_STRING (s); 2141 XUNMARK_STRING (s);
2121 2142
2122 /* Do not use string_(set|get)_intervals here. */ 2143 /* Do not use string_(set|get)_intervals here. */
2123 s->u.s.intervals = balance_intervals (s->u.s.intervals); 2144 s->u.s.intervals = balance_intervals (s->u.s.intervals);
@@ -2619,7 +2640,8 @@ make_formatted_string (char *buf, const char *format, ...)
2619 &= ~((bits_word) 1 << ((n) % BITS_PER_BITS_WORD))) 2640 &= ~((bits_word) 1 << ((n) % BITS_PER_BITS_WORD)))
2620 2641
2621#define FLOAT_BLOCK(fptr) \ 2642#define FLOAT_BLOCK(fptr) \
2622 ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1))) 2643 (eassert (!pdumper_object_p (fptr)), \
2644 ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1))))
2623 2645
2624#define FLOAT_INDEX(fptr) \ 2646#define FLOAT_INDEX(fptr) \
2625 ((((uintptr_t) (fptr)) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Float)) 2647 ((((uintptr_t) (fptr)) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Float))
@@ -2632,13 +2654,13 @@ struct float_block
2632 struct float_block *next; 2654 struct float_block *next;
2633}; 2655};
2634 2656
2635#define FLOAT_MARKED_P(fptr) \ 2657#define XFLOAT_MARKED_P(fptr) \
2636 GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr))) 2658 GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2637 2659
2638#define FLOAT_MARK(fptr) \ 2660#define XFLOAT_MARK(fptr) \
2639 SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr))) 2661 SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2640 2662
2641#define FLOAT_UNMARK(fptr) \ 2663#define XFLOAT_UNMARK(fptr) \
2642 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr))) 2664 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2643 2665
2644/* Current float_block. */ 2666/* Current float_block. */
@@ -2686,7 +2708,7 @@ make_float (double float_value)
2686 MALLOC_UNBLOCK_INPUT; 2708 MALLOC_UNBLOCK_INPUT;
2687 2709
2688 XFLOAT_INIT (val, float_value); 2710 XFLOAT_INIT (val, float_value);
2689 eassert (!FLOAT_MARKED_P (XFLOAT (val))); 2711 eassert (!XFLOAT_MARKED_P (XFLOAT (val)));
2690 consing_since_gc += sizeof (struct Lisp_Float); 2712 consing_since_gc += sizeof (struct Lisp_Float);
2691 floats_consed++; 2713 floats_consed++;
2692 total_free_floats--; 2714 total_free_floats--;
@@ -2711,7 +2733,8 @@ make_float (double float_value)
2711 / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1)) 2733 / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1))
2712 2734
2713#define CONS_BLOCK(fptr) \ 2735#define CONS_BLOCK(fptr) \
2714 ((struct cons_block *) ((uintptr_t) (fptr) & ~(BLOCK_ALIGN - 1))) 2736 (eassert (!pdumper_object_p (fptr)), \
2737 ((struct cons_block *) ((uintptr_t) (fptr) & ~(BLOCK_ALIGN - 1))))
2715 2738
2716#define CONS_INDEX(fptr) \ 2739#define CONS_INDEX(fptr) \
2717 (((uintptr_t) (fptr) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Cons)) 2740 (((uintptr_t) (fptr) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Cons))
@@ -2724,13 +2747,13 @@ struct cons_block
2724 struct cons_block *next; 2747 struct cons_block *next;
2725}; 2748};
2726 2749
2727#define CONS_MARKED_P(fptr) \ 2750#define XCONS_MARKED_P(fptr) \
2728 GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr))) 2751 GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
2729 2752
2730#define CONS_MARK(fptr) \ 2753#define XMARK_CONS(fptr) \
2731 SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr))) 2754 SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
2732 2755
2733#define CONS_UNMARK(fptr) \ 2756#define XUNMARK_CONS(fptr) \
2734 UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr))) 2757 UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
2735 2758
2736/* Current cons_block. */ 2759/* Current cons_block. */
@@ -2803,7 +2826,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2803 2826
2804 XSETCAR (val, car); 2827 XSETCAR (val, car);
2805 XSETCDR (val, cdr); 2828 XSETCDR (val, cdr);
2806 eassert (!CONS_MARKED_P (XCONS (val))); 2829 eassert (!XCONS_MARKED_P (XCONS (val)));
2807 consing_since_gc += sizeof (struct Lisp_Cons); 2830 consing_since_gc += sizeof (struct Lisp_Cons);
2808 total_free_conses--; 2831 total_free_conses--;
2809 cons_cells_consed++; 2832 cons_cells_consed++;
@@ -3103,6 +3126,7 @@ static void
3103init_vectors (void) 3126init_vectors (void)
3104{ 3127{
3105 zero_vector = make_pure_vector (0); 3128 zero_vector = make_pure_vector (0);
3129 staticpro (&zero_vector);
3106} 3130}
3107 3131
3108/* Allocate vector from a vector block. */ 3132/* Allocate vector from a vector block. */
@@ -3173,17 +3197,17 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3173 3197
3174/* Return the memory footprint of V in bytes. */ 3198/* Return the memory footprint of V in bytes. */
3175 3199
3176static ptrdiff_t 3200ptrdiff_t
3177vector_nbytes (struct Lisp_Vector *v) 3201vectorlike_nbytes (const union vectorlike_header *hdr)
3178{ 3202{
3179 ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; 3203 ptrdiff_t size = hdr->size & ~ARRAY_MARK_FLAG;
3180 ptrdiff_t nwords; 3204 ptrdiff_t nwords;
3181 3205
3182 if (size & PSEUDOVECTOR_FLAG) 3206 if (size & PSEUDOVECTOR_FLAG)
3183 { 3207 {
3184 if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) 3208 if (PSEUDOVECTOR_TYPEP (hdr, PVEC_BOOL_VECTOR))
3185 { 3209 {
3186 struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; 3210 struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) hdr;
3187 ptrdiff_t word_bytes = (bool_vector_words (bv->size) 3211 ptrdiff_t word_bytes = (bool_vector_words (bv->size)
3188 * sizeof (bits_word)); 3212 * sizeof (bits_word));
3189 ptrdiff_t boolvec_bytes = bool_header_size + word_bytes; 3213 ptrdiff_t boolvec_bytes = bool_header_size + word_bytes;
@@ -3281,9 +3305,9 @@ sweep_vectors (void)
3281 for (vector = (struct Lisp_Vector *) block->data; 3305 for (vector = (struct Lisp_Vector *) block->data;
3282 VECTOR_IN_BLOCK (vector, block); vector = next) 3306 VECTOR_IN_BLOCK (vector, block); vector = next)
3283 { 3307 {
3284 if (VECTOR_MARKED_P (vector)) 3308 if (XVECTOR_MARKED_P (vector))
3285 { 3309 {
3286 VECTOR_UNMARK (vector); 3310 XUNMARK_VECTOR (vector);
3287 total_vectors++; 3311 total_vectors++;
3288 ptrdiff_t nbytes = vector_nbytes (vector); 3312 ptrdiff_t nbytes = vector_nbytes (vector);
3289 total_vector_slots += nbytes / word_size; 3313 total_vector_slots += nbytes / word_size;
@@ -3304,7 +3328,7 @@ sweep_vectors (void)
3304 total_bytes += nbytes; 3328 total_bytes += nbytes;
3305 next = ADVANCE (next, nbytes); 3329 next = ADVANCE (next, nbytes);
3306 } 3330 }
3307 while (VECTOR_IN_BLOCK (next, block) && !VECTOR_MARKED_P (next)); 3331 while (VECTOR_IN_BLOCK (next, block) && !vector_marked_p (next));
3308 3332
3309 eassert (total_bytes % roundup_size == 0); 3333 eassert (total_bytes % roundup_size == 0);
3310 3334
@@ -3335,9 +3359,9 @@ sweep_vectors (void)
3335 for (lv = large_vectors; lv; lv = *lvprev) 3359 for (lv = large_vectors; lv; lv = *lvprev)
3336 { 3360 {
3337 vector = large_vector_vec (lv); 3361 vector = large_vector_vec (lv);
3338 if (VECTOR_MARKED_P (vector)) 3362 if (XVECTOR_MARKED_P (vector))
3339 { 3363 {
3340 VECTOR_UNMARK (vector); 3364 XUNMARK_VECTOR (vector);
3341 total_vectors++; 3365 total_vectors++;
3342 if (vector->header.size & PSEUDOVECTOR_FLAG) 3366 if (vector->header.size & PSEUDOVECTOR_FLAG)
3343 total_vector_slots += vector_nbytes (vector) / word_size; 3367 total_vector_slots += vector_nbytes (vector) / word_size;
@@ -3847,7 +3871,7 @@ mark_finalizer_list (struct Lisp_Finalizer *head)
3847 finalizer != head; 3871 finalizer != head;
3848 finalizer = finalizer->next) 3872 finalizer = finalizer->next)
3849 { 3873 {
3850 VECTOR_MARK (finalizer); 3874 set_vectorlike_marked (&finalizer->header);
3851 mark_object (finalizer->function); 3875 mark_object (finalizer->function);
3852 } 3876 }
3853} 3877}
@@ -3864,7 +3888,8 @@ queue_doomed_finalizers (struct Lisp_Finalizer *dest,
3864 while (finalizer != src) 3888 while (finalizer != src)
3865 { 3889 {
3866 struct Lisp_Finalizer *next = finalizer->next; 3890 struct Lisp_Finalizer *next = finalizer->next;
3867 if (!VECTOR_MARKED_P (finalizer) && !NILP (finalizer->function)) 3891 if (!vectorlike_marked_p (&finalizer->header)
3892 && !NILP (finalizer->function))
3868 { 3893 {
3869 unchain_finalizer (finalizer); 3894 unchain_finalizer (finalizer);
3870 finalizer_insert (dest, finalizer); 3895 finalizer_insert (dest, finalizer);
@@ -3885,6 +3910,9 @@ static void
3885run_finalizer_function (Lisp_Object function) 3910run_finalizer_function (Lisp_Object function)
3886{ 3911{
3887 ptrdiff_t count = SPECPDL_INDEX (); 3912 ptrdiff_t count = SPECPDL_INDEX ();
3913#ifdef HAVE_PDUMPER
3914 ++number_finalizers_run;
3915#endif
3888 3916
3889 specbind (Qinhibit_quit, Qt); 3917 specbind (Qinhibit_quit, Qt);
3890 internal_condition_case_1 (call0, function, Qt, run_finalizer_handler); 3918 internal_condition_case_1 (call0, function, Qt, run_finalizer_handler);
@@ -3929,6 +3957,126 @@ FUNCTION. FUNCTION will be run once per finalizer object. */)
3929 3957
3930 3958
3931/************************************************************************ 3959/************************************************************************
3960 Mark bit access functions
3961 ************************************************************************/
3962
3963/* With the rare exception of functions implementing block-based
3964 allocation of various types, you should not directly test or set GC
3965 mark bits on objects. Some objects might live in special memory
3966 regions (e.g., a dump image) and might store their mark bits
3967 elsewhere. */
3968
3969static bool
3970vector_marked_p (const struct Lisp_Vector *v)
3971{
3972 if (pdumper_object_p (v))
3973 {
3974 /* Look at cold_start first so that we don't have to fault in
3975 the vector header just to tell that it's a bool vector. */
3976 if (pdumper_cold_object_p (v))
3977 {
3978 eassert (PSEUDOVECTOR_TYPE (v) == PVEC_BOOL_VECTOR);
3979 return true;
3980 }
3981 return pdumper_marked_p (v);
3982 }
3983 return XVECTOR_MARKED_P (v);
3984}
3985
3986static void
3987set_vector_marked (struct Lisp_Vector *v)
3988{
3989 if (pdumper_object_p (v))
3990 {
3991 eassert (PSEUDOVECTOR_TYPE (v) != PVEC_BOOL_VECTOR);
3992 pdumper_set_marked (v);
3993 }
3994 else
3995 XMARK_VECTOR (v);
3996}
3997
3998static bool
3999vectorlike_marked_p (const union vectorlike_header *header)
4000{
4001 return vector_marked_p ((const struct Lisp_Vector *) header);
4002}
4003
4004static void
4005set_vectorlike_marked (union vectorlike_header *header)
4006{
4007 set_vector_marked ((struct Lisp_Vector *) header);
4008}
4009
4010static bool
4011cons_marked_p (const struct Lisp_Cons *c)
4012{
4013 return pdumper_object_p (c)
4014 ? pdumper_marked_p (c)
4015 : XCONS_MARKED_P (c);
4016}
4017
4018static void
4019set_cons_marked (struct Lisp_Cons *c)
4020{
4021 if (pdumper_object_p (c))
4022 pdumper_set_marked (c);
4023 else
4024 XMARK_CONS (c);
4025}
4026
4027static bool
4028string_marked_p (const struct Lisp_String *s)
4029{
4030 return pdumper_object_p (s)
4031 ? pdumper_marked_p (s)
4032 : XSTRING_MARKED_P (s);
4033}
4034
4035static void
4036set_string_marked (struct Lisp_String *s)
4037{
4038 if (pdumper_object_p (s))
4039 pdumper_set_marked (s);
4040 else
4041 XMARK_STRING (s);
4042}
4043
4044static bool
4045symbol_marked_p (const struct Lisp_Symbol *s)
4046{
4047 return pdumper_object_p (s)
4048 ? pdumper_marked_p (s)
4049 : s->u.s.gcmarkbit;
4050}
4051
4052static void
4053set_symbol_marked (struct Lisp_Symbol *s)
4054{
4055 if (pdumper_object_p (s))
4056 pdumper_set_marked (s);
4057 else
4058 s->u.s.gcmarkbit = true;
4059}
4060
4061static bool
4062interval_marked_p (INTERVAL i)
4063{
4064 return pdumper_object_p (i)
4065 ? pdumper_marked_p (i)
4066 : i->gcmarkbit;
4067}
4068
4069static void
4070set_interval_marked (INTERVAL i)
4071{
4072 if (pdumper_object_p (i))
4073 pdumper_set_marked (i);
4074 else
4075 i->gcmarkbit = true;
4076}
4077
4078
4079/************************************************************************
3932 Memory Full Handling 4080 Memory Full Handling
3933 ************************************************************************/ 4081 ************************************************************************/
3934 4082
@@ -4626,14 +4774,29 @@ static void
4626mark_maybe_object (Lisp_Object obj) 4774mark_maybe_object (Lisp_Object obj)
4627{ 4775{
4628#if USE_VALGRIND 4776#if USE_VALGRIND
4629 if (valgrind_p) 4777 VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
4630 VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
4631#endif 4778#endif
4632 4779
4633 if (FIXNUMP (obj)) 4780 if (FIXNUMP (obj))
4634 return; 4781 return;
4635 4782
4636 void *po = XPNTR (obj); 4783 void *po = XPNTR (obj);
4784
4785 /* If the pointer is in the dumped image and the dump has a record
4786 of the object starting at the place where the pointer points, we
4787 definitely have an object. If the pointer is in the dumped image
4788 and the dump has no idea what the pointer is pointing at, we
4789 definitely _don't_ have an object. */
4790 if (pdumper_object_p (po))
4791 {
4792 /* Don't use pdumper_object_p_precise here! It doesn't check the
4793 tag bits. OBJ here might be complete garbage, so we need to
4794 verify both the pointer and the tag. */
4795 if (XTYPE (obj) == pdumper_find_object_type (po))
4796 mark_object (obj);
4797 return;
4798 }
4799
4637 struct mem_node *m = mem_find (po); 4800 struct mem_node *m = mem_find (po);
4638 4801
4639 if (m != MEM_NIL) 4802 if (m != MEM_NIL)
@@ -4703,9 +4866,8 @@ mark_maybe_pointer (void *p)
4703{ 4866{
4704 struct mem_node *m; 4867 struct mem_node *m;
4705 4868
4706#if USE_VALGRIND 4869#ifdef USE_VALGRIND
4707 if (valgrind_p) 4870 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
4708 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
4709#endif 4871#endif
4710 4872
4711 if (sizeof (Lisp_Object) == sizeof (void *) || !HAVE_MODULES) 4873 if (sizeof (Lisp_Object) == sizeof (void *) || !HAVE_MODULES)
@@ -4720,6 +4882,17 @@ mark_maybe_pointer (void *p)
4720 p = (void *) ((uintptr_t) p & ~((1 << GCTYPEBITS) - 1)); 4882 p = (void *) ((uintptr_t) p & ~((1 << GCTYPEBITS) - 1));
4721 } 4883 }
4722 4884
4885 if (pdumper_object_p (p))
4886 {
4887 enum Lisp_Type type = pdumper_find_object_type (p);
4888 if (type != PDUMPER_NO_OBJECT)
4889 mark_object ((type == Lisp_Symbol)
4890 ? make_lisp_symbol(p)
4891 : make_lisp_ptr(p, type));
4892 /* See mark_maybe_object for why we can confidently return. */
4893 return;
4894 }
4895
4723 m = mem_find (p); 4896 m = mem_find (p);
4724 if (m != MEM_NIL) 4897 if (m != MEM_NIL)
4725 { 4898 {
@@ -5076,6 +5249,12 @@ valid_pointer_p (void *p)
5076 return p ? -1 : 0; 5249 return p ? -1 : 0;
5077 5250
5078 int fd[2]; 5251 int fd[2];
5252 static int under_rr_state;
5253
5254 if (!under_rr_state)
5255 under_rr_state = getenv ("RUNNING_UNDER_RR") ? -1 : 1;
5256 if (under_rr_state < 0)
5257 return under_rr_state;
5079 5258
5080 /* Obviously, we cannot just access it (we would SEGV trying), so we 5259 /* Obviously, we cannot just access it (we would SEGV trying), so we
5081 trick the o/s to tell us whether p is a valid pointer. 5260 trick the o/s to tell us whether p is a valid pointer.
@@ -5115,6 +5294,9 @@ valid_lisp_object_p (Lisp_Object obj)
5115 if (p == &buffer_defaults || p == &buffer_local_symbols) 5294 if (p == &buffer_defaults || p == &buffer_local_symbols)
5116 return 2; 5295 return 2;
5117 5296
5297 if (pdumper_object_p (p))
5298 return pdumper_object_p_precise (p) ? 1 : 0;
5299
5118 struct mem_node *m = mem_find (p); 5300 struct mem_node *m = mem_find (p);
5119 5301
5120 if (m == MEM_NIL) 5302 if (m == MEM_NIL)
@@ -5324,7 +5506,7 @@ make_pure_c_string (const char *data, ptrdiff_t nchars)
5324 Lisp_Object string; 5506 Lisp_Object string;
5325 struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); 5507 struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String);
5326 s->u.s.size = nchars; 5508 s->u.s.size = nchars;
5327 s->u.s.size_byte = -1; 5509 s->u.s.size_byte = -2;
5328 s->u.s.data = (unsigned char *) data; 5510 s->u.s.data = (unsigned char *) data;
5329 s->u.s.intervals = NULL; 5511 s->u.s.intervals = NULL;
5330 XSETSTRING (string, s); 5512 XSETSTRING (string, s);
@@ -5617,7 +5799,7 @@ compact_font_cache_entry (Lisp_Object entry)
5617 5799
5618 /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]). */ 5800 /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]). */
5619 if (CONSP (obj) && GC_FONT_SPEC_P (XCAR (obj)) 5801 if (CONSP (obj) && GC_FONT_SPEC_P (XCAR (obj))
5620 && !VECTOR_MARKED_P (GC_XFONT_SPEC (XCAR (obj))) 5802 && !vectorlike_marked_p (&GC_XFONT_SPEC (XCAR (obj))->header)
5621 /* Don't use VECTORP here, as that calls ASIZE, which could 5803 /* Don't use VECTORP here, as that calls ASIZE, which could
5622 hit assertion violation during GC. */ 5804 hit assertion violation during GC. */
5623 && (VECTORLIKEP (XCDR (obj)) 5805 && (VECTORLIKEP (XCDR (obj))
@@ -5633,7 +5815,8 @@ compact_font_cache_entry (Lisp_Object entry)
5633 { 5815 {
5634 Lisp_Object objlist; 5816 Lisp_Object objlist;
5635 5817
5636 if (VECTOR_MARKED_P (GC_XFONT_ENTITY (AREF (obj_cdr, i)))) 5818 if (vectorlike_marked_p (
5819 &GC_XFONT_ENTITY (AREF (obj_cdr, i))->header))
5637 break; 5820 break;
5638 5821
5639 objlist = AREF (AREF (obj_cdr, i), FONT_OBJLIST_INDEX); 5822 objlist = AREF (AREF (obj_cdr, i), FONT_OBJLIST_INDEX);
@@ -5643,7 +5826,7 @@ compact_font_cache_entry (Lisp_Object entry)
5643 struct font *font = GC_XFONT_OBJECT (val); 5826 struct font *font = GC_XFONT_OBJECT (val);
5644 5827
5645 if (!NILP (AREF (val, FONT_TYPE_INDEX)) 5828 if (!NILP (AREF (val, FONT_TYPE_INDEX))
5646 && VECTOR_MARKED_P(font)) 5829 && vectorlike_marked_p(&font->header))
5647 break; 5830 break;
5648 } 5831 }
5649 if (CONSP (objlist)) 5832 if (CONSP (objlist))
@@ -5712,7 +5895,7 @@ compact_undo_list (Lisp_Object list)
5712 { 5895 {
5713 if (CONSP (XCAR (tail)) 5896 if (CONSP (XCAR (tail))
5714 && MARKERP (XCAR (XCAR (tail))) 5897 && MARKERP (XCAR (XCAR (tail)))
5715 && !VECTOR_MARKED_P (XMARKER (XCAR (XCAR (tail))))) 5898 && !vectorlike_marked_p (&XMARKER (XCAR (XCAR (tail)))->header))
5716 *prev = XCDR (tail); 5899 *prev = XCDR (tail);
5717 else 5900 else
5718 prev = xcdr_addr (tail); 5901 prev = xcdr_addr (tail);
@@ -5745,6 +5928,105 @@ mark_pinned_symbols (void)
5745 } 5928 }
5746} 5929}
5747 5930
5931static void
5932visit_vectorlike_root (struct gc_root_visitor visitor,
5933 struct Lisp_Vector *ptr,
5934 enum gc_root_type type)
5935{
5936 ptrdiff_t size = ptr->header.size;
5937 ptrdiff_t i;
5938
5939 if (size & PSEUDOVECTOR_FLAG)
5940 size &= PSEUDOVECTOR_SIZE_MASK;
5941 for (i = 0; i < size; i++)
5942 visitor.visit (&ptr->contents[i], type, visitor.data);
5943}
5944
5945static void
5946visit_buffer_root (struct gc_root_visitor visitor,
5947 struct buffer *buffer,
5948 enum gc_root_type type)
5949{
5950 /* Buffers that are roots don't have intervals, an undo list, or
5951 other constructs that real buffers have. */
5952 eassert (buffer->base_buffer == NULL);
5953 eassert (buffer->overlays_before == NULL);
5954 eassert (buffer->overlays_after == NULL);
5955
5956 /* Visit the buffer-locals. */
5957 visit_vectorlike_root (visitor, (struct Lisp_Vector *) buffer, type);
5958}
5959
5960/* Visit GC roots stored in the Emacs data section. Used by both core
5961 GC and by the portable dumping code.
5962
5963 There are other GC roots of course, but these roots are dynamic
5964 runtime data structures that pdump doesn't care about and so we can
5965 continue to mark those directly in garbage_collect_1. */
5966void
5967visit_static_gc_roots (struct gc_root_visitor visitor)
5968{
5969 visit_buffer_root (visitor,
5970 &buffer_defaults,
5971 GC_ROOT_BUFFER_LOCAL_DEFAULT);
5972 visit_buffer_root (visitor,
5973 &buffer_local_symbols,
5974 GC_ROOT_BUFFER_LOCAL_NAME);
5975
5976 for (int i = 0; i < ARRAYELTS (lispsym); i++)
5977 {
5978 Lisp_Object sptr = builtin_lisp_symbol (i);
5979 visitor.visit (&sptr, GC_ROOT_C_SYMBOL, visitor.data);
5980 }
5981
5982 for (int i = 0; i < staticidx; i++)
5983 visitor.visit (staticvec[i], GC_ROOT_STATICPRO, visitor.data);
5984}
5985
5986static void
5987mark_object_root_visitor (Lisp_Object *root_ptr,
5988 enum gc_root_type type,
5989 void *data)
5990{
5991 mark_object (*root_ptr);
5992}
5993
5994/* List of weak hash tables we found during marking the Lisp heap.
5995 Will be NULL on entry to garbage_collect_1 and after it
5996 returns. */
5997static struct Lisp_Hash_Table *weak_hash_tables;
5998
5999NO_INLINE /* For better stack traces */
6000static void
6001mark_and_sweep_weak_table_contents (void)
6002{
6003 struct Lisp_Hash_Table *h;
6004 bool marked;
6005
6006 /* Mark all keys and values that are in use. Keep on marking until
6007 there is no more change. This is necessary for cases like
6008 value-weak table A containing an entry X -> Y, where Y is used in a
6009 key-weak table B, Z -> Y. If B comes after A in the list of weak
6010 tables, X -> Y might be removed from A, although when looking at B
6011 one finds that it shouldn't. */
6012 do
6013 {
6014 marked = false;
6015 for (h = weak_hash_tables; h; h = h->next_weak)
6016 marked |= sweep_weak_table (h, false);
6017 }
6018 while (marked);
6019
6020 /* Remove hash table entries that aren't used. */
6021 while (weak_hash_tables)
6022 {
6023 h = weak_hash_tables;
6024 weak_hash_tables = h->next_weak;
6025 h->next_weak = NULL;
6026 sweep_weak_table (h, true);
6027 }
6028}
6029
5748/* Subroutine of Fgarbage_collect that does most of the work. It is a 6030/* Subroutine of Fgarbage_collect that does most of the work. It is a
5749 separate function so that we could limit mark_stack in searching 6031 separate function so that we could limit mark_stack in searching
5750 the stack frames below this function, thus avoiding the rare cases 6032 the stack frames below this function, thus avoiding the rare cases
@@ -5757,13 +6039,14 @@ garbage_collect_1 (void *end)
5757{ 6039{
5758 struct buffer *nextb; 6040 struct buffer *nextb;
5759 char stack_top_variable; 6041 char stack_top_variable;
5760 ptrdiff_t i;
5761 bool message_p; 6042 bool message_p;
5762 ptrdiff_t count = SPECPDL_INDEX (); 6043 ptrdiff_t count = SPECPDL_INDEX ();
5763 struct timespec start; 6044 struct timespec start;
5764 Lisp_Object retval = Qnil; 6045 Lisp_Object retval = Qnil;
5765 byte_ct tot_before = 0; 6046 byte_ct tot_before = 0;
5766 6047
6048 eassert (weak_hash_tables == NULL);
6049
5767 /* Can't GC if pure storage overflowed because we can't determine 6050 /* Can't GC if pure storage overflowed because we can't determine
5768 if something is a pure object or not. */ 6051 if something is a pure object or not. */
5769 if (pure_bytes_used_before_overflow) 6052 if (pure_bytes_used_before_overflow)
@@ -5839,14 +6122,10 @@ garbage_collect_1 (void *end)
5839 6122
5840 /* Mark all the special slots that serve as the roots of accessibility. */ 6123 /* Mark all the special slots that serve as the roots of accessibility. */
5841 6124
5842 mark_buffer (&buffer_defaults); 6125 struct gc_root_visitor visitor;
5843 mark_buffer (&buffer_local_symbols); 6126 memset (&visitor, 0, sizeof (visitor));
5844 6127 visitor.visit = mark_object_root_visitor;
5845 for (i = 0; i < ARRAYELTS (lispsym); i++) 6128 visit_static_gc_roots (visitor);
5846 mark_object (builtin_lisp_symbol (i));
5847
5848 for (i = 0; i < staticidx; i++)
5849 mark_object (*staticvec[i]);
5850 6129
5851 mark_pinned_objects (); 6130 mark_pinned_objects ();
5852 mark_pinned_symbols (); 6131 mark_pinned_symbols ();
@@ -5891,11 +6170,11 @@ garbage_collect_1 (void *end)
5891 queue_doomed_finalizers (&doomed_finalizers, &finalizers); 6170 queue_doomed_finalizers (&doomed_finalizers, &finalizers);
5892 mark_finalizer_list (&doomed_finalizers); 6171 mark_finalizer_list (&doomed_finalizers);
5893 6172
5894 gc_sweep (); 6173 /* Must happen after all other marking and before gc_sweep. */
6174 mark_and_sweep_weak_table_contents ();
6175 eassert (weak_hash_tables == NULL);
5895 6176
5896 /* Clear the mark bits that we set in certain root slots. */ 6177 gc_sweep ();
5897 VECTOR_UNMARK (&buffer_defaults);
5898 VECTOR_UNMARK (&buffer_local_symbols);
5899 6178
5900 unmark_main_thread (); 6179 unmark_main_thread ();
5901 6180
@@ -6043,7 +6322,7 @@ mark_glyph_matrix (struct glyph_matrix *matrix)
6043 6322
6044 for (; glyph < end_glyph; ++glyph) 6323 for (; glyph < end_glyph; ++glyph)
6045 if (STRINGP (glyph->object) 6324 if (STRINGP (glyph->object)
6046 && !STRING_MARKED_P (XSTRING (glyph->object))) 6325 && !string_marked_p (XSTRING (glyph->object)))
6047 mark_object (glyph->object); 6326 mark_object (glyph->object);
6048 } 6327 }
6049 } 6328 }
@@ -6060,13 +6339,18 @@ static int last_marked_index;
6060ptrdiff_t mark_object_loop_halt EXTERNALLY_VISIBLE; 6339ptrdiff_t mark_object_loop_halt EXTERNALLY_VISIBLE;
6061 6340
6062static void 6341static void
6063mark_vectorlike (struct Lisp_Vector *ptr) 6342mark_vectorlike (union vectorlike_header *header)
6064{ 6343{
6344 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header;
6065 ptrdiff_t size = ptr->header.size; 6345 ptrdiff_t size = ptr->header.size;
6066 ptrdiff_t i; 6346 ptrdiff_t i;
6067 6347
6068 eassert (!VECTOR_MARKED_P (ptr)); 6348 eassert (!vector_marked_p (ptr));
6069 VECTOR_MARK (ptr); /* Else mark it. */ 6349
6350 /* Bool vectors have a different case in mark_object. */
6351 eassert (PSEUDOVECTOR_TYPE (ptr) != PVEC_BOOL_VECTOR);
6352
6353 set_vector_marked (ptr); /* Else mark it. */
6070 if (size & PSEUDOVECTOR_FLAG) 6354 if (size & PSEUDOVECTOR_FLAG)
6071 size &= PSEUDOVECTOR_SIZE_MASK; 6355 size &= PSEUDOVECTOR_SIZE_MASK;
6072 6356
@@ -6089,17 +6373,18 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
6089 /* Consult the Lisp_Sub_Char_Table layout before changing this. */ 6373 /* Consult the Lisp_Sub_Char_Table layout before changing this. */
6090 int i, idx = (pvectype == PVEC_SUB_CHAR_TABLE ? SUB_CHAR_TABLE_OFFSET : 0); 6374 int i, idx = (pvectype == PVEC_SUB_CHAR_TABLE ? SUB_CHAR_TABLE_OFFSET : 0);
6091 6375
6092 eassert (!VECTOR_MARKED_P (ptr)); 6376 eassert (!vector_marked_p (ptr));
6093 VECTOR_MARK (ptr); 6377 set_vector_marked (ptr);
6094 for (i = idx; i < size; i++) 6378 for (i = idx; i < size; i++)
6095 { 6379 {
6096 Lisp_Object val = ptr->contents[i]; 6380 Lisp_Object val = ptr->contents[i];
6097 6381
6098 if (FIXNUMP (val) || (SYMBOLP (val) && XSYMBOL (val)->u.s.gcmarkbit)) 6382 if (FIXNUMP (val) ||
6383 (SYMBOLP (val) && symbol_marked_p (XSYMBOL (val))))
6099 continue; 6384 continue;
6100 if (SUB_CHAR_TABLE_P (val)) 6385 if (SUB_CHAR_TABLE_P (val))
6101 { 6386 {
6102 if (! VECTOR_MARKED_P (XVECTOR (val))) 6387 if (! vector_marked_p (XVECTOR (val)))
6103 mark_char_table (XVECTOR (val), PVEC_SUB_CHAR_TABLE); 6388 mark_char_table (XVECTOR (val), PVEC_SUB_CHAR_TABLE);
6104 } 6389 }
6105 else 6390 else
@@ -6113,7 +6398,7 @@ mark_compiled (struct Lisp_Vector *ptr)
6113{ 6398{
6114 int i, size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; 6399 int i, size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
6115 6400
6116 VECTOR_MARK (ptr); 6401 set_vector_marked (ptr);
6117 for (i = 0; i < size; i++) 6402 for (i = 0; i < size; i++)
6118 if (i != COMPILED_CONSTANTS) 6403 if (i != COMPILED_CONSTANTS)
6119 mark_object (ptr->contents[i]); 6404 mark_object (ptr->contents[i]);
@@ -6125,12 +6410,12 @@ mark_compiled (struct Lisp_Vector *ptr)
6125static void 6410static void
6126mark_overlay (struct Lisp_Overlay *ptr) 6411mark_overlay (struct Lisp_Overlay *ptr)
6127{ 6412{
6128 for (; ptr && !VECTOR_MARKED_P (ptr); ptr = ptr->next) 6413 for (; ptr && !vectorlike_marked_p (&ptr->header); ptr = ptr->next)
6129 { 6414 {
6130 VECTOR_MARK (ptr); 6415 set_vectorlike_marked (&ptr->header);
6131 /* These two are always markers and can be marked fast. */ 6416 /* These two are always markers and can be marked fast. */
6132 VECTOR_MARK (XMARKER (ptr->start)); 6417 set_vectorlike_marked (&XMARKER (ptr->start)->header);
6133 VECTOR_MARK (XMARKER (ptr->end)); 6418 set_vectorlike_marked (&XMARKER (ptr->end)->header);
6134 mark_object (ptr->plist); 6419 mark_object (ptr->plist);
6135 } 6420 }
6136} 6421}
@@ -6141,11 +6426,11 @@ static void
6141mark_buffer (struct buffer *buffer) 6426mark_buffer (struct buffer *buffer)
6142{ 6427{
6143 /* This is handled much like other pseudovectors... */ 6428 /* This is handled much like other pseudovectors... */
6144 mark_vectorlike ((struct Lisp_Vector *) buffer); 6429 mark_vectorlike (&buffer->header);
6145 6430
6146 /* ...but there are some buffer-specific things. */ 6431 /* ...but there are some buffer-specific things. */
6147 6432
6148 MARK_INTERVAL_TREE (buffer_intervals (buffer)); 6433 mark_interval_tree (buffer_intervals (buffer));
6149 6434
6150 /* For now, we just don't mark the undo_list. It's done later in 6435 /* For now, we just don't mark the undo_list. It's done later in
6151 a special way just before the sweep phase, and after stripping 6436 a special way just before the sweep phase, and after stripping
@@ -6155,7 +6440,8 @@ mark_buffer (struct buffer *buffer)
6155 mark_overlay (buffer->overlays_after); 6440 mark_overlay (buffer->overlays_after);
6156 6441
6157 /* If this is an indirect buffer, mark its base buffer. */ 6442 /* If this is an indirect buffer, mark its base buffer. */
6158 if (buffer->base_buffer && !VECTOR_MARKED_P (buffer->base_buffer)) 6443 if (buffer->base_buffer &&
6444 !vectorlike_marked_p (&buffer->base_buffer->header))
6159 mark_buffer (buffer->base_buffer); 6445 mark_buffer (buffer->base_buffer);
6160} 6446}
6161 6447
@@ -6174,8 +6460,8 @@ mark_face_cache (struct face_cache *c)
6174 6460
6175 if (face) 6461 if (face)
6176 { 6462 {
6177 if (face->font && !VECTOR_MARKED_P (face->font)) 6463 if (face->font && !vectorlike_marked_p (&face->font->header))
6178 mark_vectorlike ((struct Lisp_Vector *) face->font); 6464 mark_vectorlike (&face->font->header);
6179 6465
6180 for (j = 0; j < LFACE_VECTOR_SIZE; ++j) 6466 for (j = 0; j < LFACE_VECTOR_SIZE; ++j)
6181 mark_object (face->lface[j]); 6467 mark_object (face->lface[j]);
@@ -6206,7 +6492,7 @@ mark_discard_killed_buffers (Lisp_Object list)
6206{ 6492{
6207 Lisp_Object tail, *prev = &list; 6493 Lisp_Object tail, *prev = &list;
6208 6494
6209 for (tail = list; CONSP (tail) && !CONS_MARKED_P (XCONS (tail)); 6495 for (tail = list; CONSP (tail) && !cons_marked_p (XCONS (tail));
6210 tail = XCDR (tail)) 6496 tail = XCDR (tail))
6211 { 6497 {
6212 Lisp_Object tem = XCAR (tail); 6498 Lisp_Object tem = XCAR (tail);
@@ -6216,7 +6502,7 @@ mark_discard_killed_buffers (Lisp_Object list)
6216 *prev = XCDR (tail); 6502 *prev = XCDR (tail);
6217 else 6503 else
6218 { 6504 {
6219 CONS_MARK (XCONS (tail)); 6505 set_cons_marked (XCONS (tail));
6220 mark_object (XCAR (tail)); 6506 mark_object (XCAR (tail));
6221 prev = xcdr_addr (tail); 6507 prev = xcdr_addr (tail);
6222 } 6508 }
@@ -6225,6 +6511,72 @@ mark_discard_killed_buffers (Lisp_Object list)
6225 return list; 6511 return list;
6226} 6512}
6227 6513
6514static void
6515mark_frame (struct Lisp_Vector *ptr)
6516{
6517 struct frame *f = (struct frame *) ptr;
6518 mark_vectorlike (&ptr->header);
6519 mark_face_cache (f->face_cache);
6520#ifdef HAVE_WINDOW_SYSTEM
6521 if (FRAME_WINDOW_P (f) && FRAME_X_OUTPUT (f))
6522 {
6523 struct font *font = FRAME_FONT (f);
6524
6525 if (font && !vectorlike_marked_p (&font->header))
6526 mark_vectorlike (&font->header);
6527 }
6528#endif
6529}
6530
6531static void
6532mark_window (struct Lisp_Vector *ptr)
6533{
6534 struct window *w = (struct window *) ptr;
6535
6536 mark_vectorlike (&ptr->header);
6537
6538 /* Mark glyph matrices, if any. Marking window
6539 matrices is sufficient because frame matrices
6540 use the same glyph memory. */
6541 if (w->current_matrix)
6542 {
6543 mark_glyph_matrix (w->current_matrix);
6544 mark_glyph_matrix (w->desired_matrix);
6545 }
6546
6547 /* Filter out killed buffers from both buffer lists
6548 in attempt to help GC to reclaim killed buffers faster.
6549 We can do it elsewhere for live windows, but this is the
6550 best place to do it for dead windows. */
6551 wset_prev_buffers
6552 (w, mark_discard_killed_buffers (w->prev_buffers));
6553 wset_next_buffers
6554 (w, mark_discard_killed_buffers (w->next_buffers));
6555}
6556
6557static void
6558mark_hash_table (struct Lisp_Vector *ptr)
6559{
6560 struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
6561
6562 mark_vectorlike (&h->header);
6563 mark_object (h->test.name);
6564 mark_object (h->test.user_hash_function);
6565 mark_object (h->test.user_cmp_function);
6566 /* If hash table is not weak, mark all keys and values. For weak
6567 tables, mark only the vector and not its contents --- that's what
6568 makes it weak. */
6569 if (NILP (h->weak))
6570 mark_object (h->key_and_value);
6571 else
6572 {
6573 eassert (h->next_weak == NULL);
6574 h->next_weak = weak_hash_tables;
6575 weak_hash_tables = h;
6576 set_vector_marked (XVECTOR (h->key_and_value));
6577 }
6578}
6579
6228/* Determine type of generic Lisp_Object and mark it accordingly. 6580/* Determine type of generic Lisp_Object and mark it accordingly.
6229 6581
6230 This function implements a straightforward depth-first marking 6582 This function implements a straightforward depth-first marking
@@ -6239,7 +6591,7 @@ mark_object (Lisp_Object arg)
6239 register Lisp_Object obj; 6591 register Lisp_Object obj;
6240 void *po; 6592 void *po;
6241#if GC_CHECK_MARKED_OBJECTS 6593#if GC_CHECK_MARKED_OBJECTS
6242 struct mem_node *m; 6594 struct mem_node *m = NULL;
6243#endif 6595#endif
6244 ptrdiff_t cdr_count = 0; 6596 ptrdiff_t cdr_count = 0;
6245 6597
@@ -6262,6 +6614,12 @@ mark_object (Lisp_Object arg)
6262 structure allocated from the heap. */ 6614 structure allocated from the heap. */
6263#define CHECK_ALLOCATED() \ 6615#define CHECK_ALLOCATED() \
6264 do { \ 6616 do { \
6617 if (pdumper_object_p(po)) \
6618 { \
6619 if (!pdumper_object_p_precise (po)) \
6620 emacs_abort (); \
6621 break; \
6622 } \
6265 m = mem_find (po); \ 6623 m = mem_find (po); \
6266 if (m == MEM_NIL) \ 6624 if (m == MEM_NIL) \
6267 emacs_abort (); \ 6625 emacs_abort (); \
@@ -6271,6 +6629,8 @@ mark_object (Lisp_Object arg)
6271 function LIVEP. */ 6629 function LIVEP. */
6272#define CHECK_LIVE(LIVEP) \ 6630#define CHECK_LIVE(LIVEP) \
6273 do { \ 6631 do { \
6632 if (pdumper_object_p(po)) \
6633 break; \
6274 if (!LIVEP (m, po)) \ 6634 if (!LIVEP (m, po)) \
6275 emacs_abort (); \ 6635 emacs_abort (); \
6276 } while (0) 6636 } while (0)
@@ -6305,11 +6665,11 @@ mark_object (Lisp_Object arg)
6305 case Lisp_String: 6665 case Lisp_String:
6306 { 6666 {
6307 register struct Lisp_String *ptr = XSTRING (obj); 6667 register struct Lisp_String *ptr = XSTRING (obj);
6308 if (STRING_MARKED_P (ptr)) 6668 if (string_marked_p (ptr))
6309 break; 6669 break;
6310 CHECK_ALLOCATED_AND_LIVE (live_string_p); 6670 CHECK_ALLOCATED_AND_LIVE (live_string_p);
6311 MARK_STRING (ptr); 6671 set_string_marked (ptr);
6312 MARK_INTERVAL_TREE (ptr->u.s.intervals); 6672 mark_interval_tree (ptr->u.s.intervals);
6313#ifdef GC_CHECK_STRING_BYTES 6673#ifdef GC_CHECK_STRING_BYTES
6314 /* Check that the string size recorded in the string is the 6674 /* Check that the string size recorded in the string is the
6315 same as the one recorded in the sdata structure. */ 6675 same as the one recorded in the sdata structure. */
@@ -6322,22 +6682,25 @@ mark_object (Lisp_Object arg)
6322 { 6682 {
6323 register struct Lisp_Vector *ptr = XVECTOR (obj); 6683 register struct Lisp_Vector *ptr = XVECTOR (obj);
6324 6684
6325 if (VECTOR_MARKED_P (ptr)) 6685 if (vector_marked_p (ptr))
6326 break; 6686 break;
6327 6687
6328#if GC_CHECK_MARKED_OBJECTS 6688#ifdef GC_CHECK_MARKED_OBJECTS
6329 m = mem_find (po); 6689 if (!pdumper_object_p(po))
6330 if (m == MEM_NIL && !SUBRP (obj) && !main_thread_p (po)) 6690 {
6331 emacs_abort (); 6691 m = mem_find (po);
6692 if (m == MEM_NIL && !SUBRP (obj) && !main_thread_p (po))
6693 emacs_abort ();
6694 }
6332#endif /* GC_CHECK_MARKED_OBJECTS */ 6695#endif /* GC_CHECK_MARKED_OBJECTS */
6333 6696
6334 enum pvec_type pvectype 6697 enum pvec_type pvectype
6335 = PSEUDOVECTOR_TYPE (ptr); 6698 = PSEUDOVECTOR_TYPE (ptr);
6336 6699
6337 if (pvectype != PVEC_SUBR 6700 if (pvectype != PVEC_SUBR &&
6338 && pvectype != PVEC_BUFFER 6701 pvectype != PVEC_BUFFER &&
6339 && !main_thread_p (po)) 6702 !main_thread_p (po))
6340 CHECK_LIVE (live_vector_p); 6703 CHECK_LIVE (live_vector_p);
6341 6704
6342 switch (pvectype) 6705 switch (pvectype)
6343 { 6706 {
@@ -6353,77 +6716,28 @@ mark_object (Lisp_Object arg)
6353 } 6716 }
6354#endif /* GC_CHECK_MARKED_OBJECTS */ 6717#endif /* GC_CHECK_MARKED_OBJECTS */
6355 mark_buffer ((struct buffer *) ptr); 6718 mark_buffer ((struct buffer *) ptr);
6356 break; 6719 break;
6357 6720
6358 case PVEC_COMPILED: 6721 case PVEC_COMPILED:
6359 /* Although we could treat this just like a vector, mark_compiled 6722 /* Although we could treat this just like a vector, mark_compiled
6360 returns the COMPILED_CONSTANTS element, which is marked at the 6723 returns the COMPILED_CONSTANTS element, which is marked at the
6361 next iteration of goto-loop here. This is done to avoid a few 6724 next iteration of goto-loop here. This is done to avoid a few
6362 recursive calls to mark_object. */ 6725 recursive calls to mark_object. */
6363 obj = mark_compiled (ptr); 6726 obj = mark_compiled (ptr);
6364 if (!NILP (obj)) 6727 if (!NILP (obj))
6365 goto loop; 6728 goto loop;
6366 break; 6729 break;
6367 6730
6368 case PVEC_FRAME: 6731 case PVEC_FRAME:
6369 { 6732 mark_frame (ptr);
6370 struct frame *f = (struct frame *) ptr; 6733 break;
6371 6734
6372 mark_vectorlike (ptr); 6735 case PVEC_WINDOW:
6373 mark_face_cache (f->face_cache); 6736 mark_window (ptr);
6374#ifdef HAVE_WINDOW_SYSTEM 6737 break;
6375 if (FRAME_WINDOW_P (f) && FRAME_X_OUTPUT (f))
6376 {
6377 struct font *font = FRAME_FONT (f);
6378
6379 if (font && !VECTOR_MARKED_P (font))
6380 mark_vectorlike ((struct Lisp_Vector *) font);
6381 }
6382#endif
6383 }
6384 break;
6385
6386 case PVEC_WINDOW:
6387 {
6388 struct window *w = (struct window *) ptr;
6389
6390 mark_vectorlike (ptr);
6391
6392 /* Mark glyph matrices, if any. Marking window
6393 matrices is sufficient because frame matrices
6394 use the same glyph memory. */
6395 if (w->current_matrix)
6396 {
6397 mark_glyph_matrix (w->current_matrix);
6398 mark_glyph_matrix (w->desired_matrix);
6399 }
6400
6401 /* Filter out killed buffers from both buffer lists
6402 in attempt to help GC to reclaim killed buffers faster.
6403 We can do it elsewhere for live windows, but this is the
6404 best place to do it for dead windows. */
6405 wset_prev_buffers
6406 (w, mark_discard_killed_buffers (w->prev_buffers));
6407 wset_next_buffers
6408 (w, mark_discard_killed_buffers (w->next_buffers));
6409 }
6410 break;
6411 6738
6412 case PVEC_HASH_TABLE: 6739 case PVEC_HASH_TABLE:
6413 { 6740 mark_hash_table (ptr);
6414 struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
6415
6416 mark_vectorlike (ptr);
6417 mark_object (h->test.name);
6418 mark_object (h->test.user_hash_function);
6419 mark_object (h->test.user_cmp_function);
6420 /* If hash table is not weak, mark all keys and values.
6421 For weak tables, mark only the vector. */
6422 if (NILP (h->weak))
6423 mark_object (h->key_and_value);
6424 else
6425 VECTOR_MARK (XVECTOR (h->key_and_value));
6426 }
6427 break; 6741 break;
6428 6742
6429 case PVEC_CHAR_TABLE: 6743 case PVEC_CHAR_TABLE:
@@ -6431,7 +6745,17 @@ mark_object (Lisp_Object arg)
6431 mark_char_table (ptr, (enum pvec_type) pvectype); 6745 mark_char_table (ptr, (enum pvec_type) pvectype);
6432 break; 6746 break;
6433 6747
6434 case PVEC_OVERLAY: 6748 case PVEC_BOOL_VECTOR:
6749 /* bool vectors in a dump are permanently "marked", since
6750 they're in the old section and don't have mark bits.
6751 If we're looking at a dumped bool vector, we should
6752 have aborted above when we called vector_marked_p(), so
6753 we should never get here. */
6754 eassert (!pdumper_object_p (ptr));
6755 set_vector_marked (ptr);
6756 break;
6757
6758 case PVEC_OVERLAY:
6435 mark_overlay (XOVERLAY (obj)); 6759 mark_overlay (XOVERLAY (obj));
6436 break; 6760 break;
6437 6761
@@ -6444,7 +6768,7 @@ mark_object (Lisp_Object arg)
6444 default: 6768 default:
6445 /* A regular vector, or a pseudovector needing no special 6769 /* A regular vector, or a pseudovector needing no special
6446 treatment. */ 6770 treatment. */
6447 mark_vectorlike (ptr); 6771 mark_vectorlike (&ptr->header);
6448 } 6772 }
6449 } 6773 }
6450 break; 6774 break;
@@ -6453,10 +6777,10 @@ mark_object (Lisp_Object arg)
6453 { 6777 {
6454 struct Lisp_Symbol *ptr = XSYMBOL (obj); 6778 struct Lisp_Symbol *ptr = XSYMBOL (obj);
6455 nextsym: 6779 nextsym:
6456 if (ptr->u.s.gcmarkbit) 6780 if (symbol_marked_p (ptr))
6457 break; 6781 break;
6458 CHECK_ALLOCATED_AND_LIVE_SYMBOL (); 6782 CHECK_ALLOCATED_AND_LIVE_SYMBOL ();
6459 ptr->u.s.gcmarkbit = 1; 6783 set_symbol_marked(ptr);
6460 /* Attempt to catch bogus objects. */ 6784 /* Attempt to catch bogus objects. */
6461 eassert (valid_lisp_object_p (ptr->u.s.function)); 6785 eassert (valid_lisp_object_p (ptr->u.s.function));
6462 mark_object (ptr->u.s.function); 6786 mark_object (ptr->u.s.function);
@@ -6483,8 +6807,8 @@ mark_object (Lisp_Object arg)
6483 default: emacs_abort (); 6807 default: emacs_abort ();
6484 } 6808 }
6485 if (!PURE_P (XSTRING (ptr->u.s.name))) 6809 if (!PURE_P (XSTRING (ptr->u.s.name)))
6486 MARK_STRING (XSTRING (ptr->u.s.name)); 6810 set_string_marked (XSTRING (ptr->u.s.name));
6487 MARK_INTERVAL_TREE (string_intervals (ptr->u.s.name)); 6811 mark_interval_tree (string_intervals (ptr->u.s.name));
6488 /* Inner loop to mark next symbol in this bucket, if any. */ 6812 /* Inner loop to mark next symbol in this bucket, if any. */
6489 po = ptr = ptr->u.s.next; 6813 po = ptr = ptr->u.s.next;
6490 if (ptr) 6814 if (ptr)
@@ -6495,10 +6819,10 @@ mark_object (Lisp_Object arg)
6495 case Lisp_Cons: 6819 case Lisp_Cons:
6496 { 6820 {
6497 struct Lisp_Cons *ptr = XCONS (obj); 6821 struct Lisp_Cons *ptr = XCONS (obj);
6498 if (CONS_MARKED_P (ptr)) 6822 if (cons_marked_p (ptr))
6499 break; 6823 break;
6500 CHECK_ALLOCATED_AND_LIVE (live_cons_p); 6824 CHECK_ALLOCATED_AND_LIVE (live_cons_p);
6501 CONS_MARK (ptr); 6825 set_cons_marked (ptr);
6502 /* If the cdr is nil, avoid recursion for the car. */ 6826 /* If the cdr is nil, avoid recursion for the car. */
6503 if (NILP (ptr->u.s.u.cdr)) 6827 if (NILP (ptr->u.s.u.cdr))
6504 { 6828 {
@@ -6516,7 +6840,12 @@ mark_object (Lisp_Object arg)
6516 6840
6517 case Lisp_Float: 6841 case Lisp_Float:
6518 CHECK_ALLOCATED_AND_LIVE (live_float_p); 6842 CHECK_ALLOCATED_AND_LIVE (live_float_p);
6519 FLOAT_MARK (XFLOAT (obj)); 6843 /* Do not mark floats stored in a dump image: these floats are
6844 "cold" and do not have mark bits. */
6845 if (pdumper_object_p (XFLOAT (obj)))
6846 eassert (pdumper_cold_object_p (XFLOAT (obj)));
6847 else if (!XFLOAT_MARKED_P (XFLOAT (obj)))
6848 XFLOAT_MARK (XFLOAT (obj));
6520 break; 6849 break;
6521 6850
6522 case_Lisp_Int: 6851 case_Lisp_Int:
@@ -6530,6 +6859,7 @@ mark_object (Lisp_Object arg)
6530#undef CHECK_ALLOCATED 6859#undef CHECK_ALLOCATED
6531#undef CHECK_ALLOCATED_AND_LIVE 6860#undef CHECK_ALLOCATED_AND_LIVE
6532} 6861}
6862
6533/* Mark the Lisp pointers in the terminal objects. 6863/* Mark the Lisp pointers in the terminal objects.
6534 Called by Fgarbage_collect. */ 6864 Called by Fgarbage_collect. */
6535 6865
@@ -6546,13 +6876,11 @@ mark_terminals (void)
6546 gets marked. */ 6876 gets marked. */
6547 mark_image_cache (t->image_cache); 6877 mark_image_cache (t->image_cache);
6548#endif /* HAVE_WINDOW_SYSTEM */ 6878#endif /* HAVE_WINDOW_SYSTEM */
6549 if (!VECTOR_MARKED_P (t)) 6879 if (!vectorlike_marked_p (&t->header))
6550 mark_vectorlike ((struct Lisp_Vector *)t); 6880 mark_vectorlike (&t->header);
6551 } 6881 }
6552} 6882}
6553 6883
6554
6555
6556/* Value is non-zero if OBJ will survive the current GC because it's 6884/* Value is non-zero if OBJ will survive the current GC because it's
6557 either marked or does not need to be marked to survive. */ 6885 either marked or does not need to be marked to survive. */
6558 6886
@@ -6564,27 +6892,29 @@ survives_gc_p (Lisp_Object obj)
6564 switch (XTYPE (obj)) 6892 switch (XTYPE (obj))
6565 { 6893 {
6566 case_Lisp_Int: 6894 case_Lisp_Int:
6567 survives_p = 1; 6895 survives_p = true;
6568 break; 6896 break;
6569 6897
6570 case Lisp_Symbol: 6898 case Lisp_Symbol:
6571 survives_p = XSYMBOL (obj)->u.s.gcmarkbit; 6899 survives_p = symbol_marked_p (XSYMBOL (obj));
6572 break; 6900 break;
6573 6901
6574 case Lisp_String: 6902 case Lisp_String:
6575 survives_p = STRING_MARKED_P (XSTRING (obj)); 6903 survives_p = string_marked_p (XSTRING (obj));
6576 break; 6904 break;
6577 6905
6578 case Lisp_Vectorlike: 6906 case Lisp_Vectorlike:
6579 survives_p = SUBRP (obj) || VECTOR_MARKED_P (XVECTOR (obj)); 6907 survives_p = SUBRP (obj) || vector_marked_p (XVECTOR (obj));
6580 break; 6908 break;
6581 6909
6582 case Lisp_Cons: 6910 case Lisp_Cons:
6583 survives_p = CONS_MARKED_P (XCONS (obj)); 6911 survives_p = cons_marked_p (XCONS (obj));
6584 break; 6912 break;
6585 6913
6586 case Lisp_Float: 6914 case Lisp_Float:
6587 survives_p = FLOAT_MARKED_P (XFLOAT (obj)); 6915 survives_p =
6916 XFLOAT_MARKED_P (XFLOAT (obj)) ||
6917 pdumper_object_p (XFLOAT (obj));
6588 break; 6918 break;
6589 6919
6590 default: 6920 default:
@@ -6638,7 +6968,7 @@ sweep_conses (void)
6638 { 6968 {
6639 struct Lisp_Cons *acons 6969 struct Lisp_Cons *acons
6640 = ptr_bounds_copy (&cblk->conses[pos], cblk); 6970 = ptr_bounds_copy (&cblk->conses[pos], cblk);
6641 if (!CONS_MARKED_P (acons)) 6971 if (!XCONS_MARKED_P (acons))
6642 { 6972 {
6643 this_free++; 6973 this_free++;
6644 cblk->conses[pos].u.s.u.chain = cons_free_list; 6974 cblk->conses[pos].u.s.u.chain = cons_free_list;
@@ -6648,7 +6978,7 @@ sweep_conses (void)
6648 else 6978 else
6649 { 6979 {
6650 num_used++; 6980 num_used++;
6651 CONS_UNMARK (acons); 6981 XUNMARK_CONS (acons);
6652 } 6982 }
6653 } 6983 }
6654 } 6984 }
@@ -6691,7 +7021,7 @@ sweep_floats (void)
6691 for (int i = 0; i < lim; i++) 7021 for (int i = 0; i < lim; i++)
6692 { 7022 {
6693 struct Lisp_Float *afloat = ptr_bounds_copy (&fblk->floats[i], fblk); 7023 struct Lisp_Float *afloat = ptr_bounds_copy (&fblk->floats[i], fblk);
6694 if (!FLOAT_MARKED_P (afloat)) 7024 if (!XFLOAT_MARKED_P (afloat))
6695 { 7025 {
6696 this_free++; 7026 this_free++;
6697 fblk->floats[i].u.chain = float_free_list; 7027 fblk->floats[i].u.chain = float_free_list;
@@ -6700,7 +7030,7 @@ sweep_floats (void)
6700 else 7030 else
6701 { 7031 {
6702 num_used++; 7032 num_used++;
6703 FLOAT_UNMARK (afloat); 7033 XFLOAT_UNMARK (afloat);
6704 } 7034 }
6705 } 7035 }
6706 lim = FLOAT_BLOCK_SIZE; 7036 lim = FLOAT_BLOCK_SIZE;
@@ -6850,7 +7180,7 @@ unchain_dead_markers (struct buffer *buffer)
6850 struct Lisp_Marker *this, **prev = &BUF_MARKERS (buffer); 7180 struct Lisp_Marker *this, **prev = &BUF_MARKERS (buffer);
6851 7181
6852 while ((this = *prev)) 7182 while ((this = *prev))
6853 if (VECTOR_MARKED_P (this)) 7183 if (vectorlike_marked_p (&this->header))
6854 prev = &this->next; 7184 prev = &this->next;
6855 else 7185 else
6856 { 7186 {
@@ -6867,14 +7197,15 @@ sweep_buffers (void)
6867 7197
6868 total_buffers = 0; 7198 total_buffers = 0;
6869 for (buffer = all_buffers; buffer; buffer = *bprev) 7199 for (buffer = all_buffers; buffer; buffer = *bprev)
6870 if (!VECTOR_MARKED_P (buffer)) 7200 if (!vectorlike_marked_p (&buffer->header))
6871 { 7201 {
6872 *bprev = buffer->next; 7202 *bprev = buffer->next;
6873 lisp_free (buffer); 7203 lisp_free (buffer);
6874 } 7204 }
6875 else 7205 else
6876 { 7206 {
6877 VECTOR_UNMARK (buffer); 7207 if (!pdumper_object_p (buffer))
7208 XUNMARK_VECTOR (buffer);
6878 /* Do not use buffer_(set|get)_intervals here. */ 7209 /* Do not use buffer_(set|get)_intervals here. */
6879 buffer->text->intervals = balance_intervals (buffer->text->intervals); 7210 buffer->text->intervals = balance_intervals (buffer->text->intervals);
6880 unchain_dead_markers (buffer); 7211 unchain_dead_markers (buffer);
@@ -6887,10 +7218,6 @@ sweep_buffers (void)
6887static void 7218static void
6888gc_sweep (void) 7219gc_sweep (void)
6889{ 7220{
6890 /* Remove or mark entries in weak hash tables.
6891 This must be done before any object is unmarked. */
6892 sweep_weak_hash_tables ();
6893
6894 sweep_strings (); 7221 sweep_strings ();
6895 check_string_bytes (!noninteractive); 7222 check_string_bytes (!noninteractive);
6896 sweep_conses (); 7223 sweep_conses ();
@@ -6899,6 +7226,7 @@ gc_sweep (void)
6899 sweep_symbols (); 7226 sweep_symbols ();
6900 sweep_buffers (); 7227 sweep_buffers ();
6901 sweep_vectors (); 7228 sweep_vectors ();
7229 pdumper_clear_marks ();
6902 check_string_bytes (!noninteractive); 7230 check_string_bytes (!noninteractive);
6903} 7231}
6904 7232
@@ -7151,19 +7479,34 @@ verify_alloca (void)
7151 7479
7152/* Initialization. */ 7480/* Initialization. */
7153 7481
7482static void init_alloc_once_for_pdumper (void);
7483
7154void 7484void
7155init_alloc_once (void) 7485init_alloc_once (void)
7156{ 7486{
7487 gc_cons_threshold = GC_DEFAULT_THRESHOLD;
7157 /* Even though Qt's contents are not set up, its address is known. */ 7488 /* Even though Qt's contents are not set up, its address is known. */
7158 Vpurify_flag = Qt; 7489 Vpurify_flag = Qt;
7159 7490
7160 purebeg = PUREBEG; 7491 PDUMPER_REMEMBER_SCALAR (buffer_defaults.header);
7161 pure_size = PURESIZE; 7492 PDUMPER_REMEMBER_SCALAR (buffer_local_symbols.header);
7493
7494 /* Call init_alloc_once_for_pdumper now so we run mem_init early.
7495 Keep in mind that when we reload from a dump, we'll run _only_
7496 init_alloc_once_for_pdumper and not init_alloc_once at all. */
7497 pdumper_do_now_and_after_load (init_alloc_once_for_pdumper);
7162 7498
7163 verify_alloca (); 7499 verify_alloca ();
7164 init_finalizer_list (&finalizers);
7165 init_finalizer_list (&doomed_finalizers);
7166 7500
7501 init_strings ();
7502 init_vectors ();
7503}
7504
7505static void
7506init_alloc_once_for_pdumper (void)
7507{
7508 purebeg = PUREBEG;
7509 pure_size = PURESIZE;
7167 mem_init (); 7510 mem_init ();
7168 Vdead = make_pure_string ("DEAD", 4, 4, 0); 7511 Vdead = make_pure_string ("DEAD", 4, 4, 0);
7169 7512
@@ -7172,11 +7515,11 @@ init_alloc_once (void)
7172 mallopt (M_MMAP_THRESHOLD, 64 * 1024); /* Mmap threshold. */ 7515 mallopt (M_MMAP_THRESHOLD, 64 * 1024); /* Mmap threshold. */
7173 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* Max. number of mmap'ed areas. */ 7516 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* Max. number of mmap'ed areas. */
7174#endif 7517#endif
7175 init_strings ();
7176 init_vectors ();
7177 7518
7519
7520 init_finalizer_list (&finalizers);
7521 init_finalizer_list (&doomed_finalizers);
7178 refill_memory_reserve (); 7522 refill_memory_reserve ();
7179 gc_cons_threshold = GC_DEFAULT_THRESHOLD;
7180} 7523}
7181 7524
7182void 7525void
@@ -7184,10 +7527,6 @@ init_alloc (void)
7184{ 7527{
7185 Vgc_elapsed = make_float (0.0); 7528 Vgc_elapsed = make_float (0.0);
7186 gcs_done = 0; 7529 gcs_done = 0;
7187
7188#if USE_VALGRIND
7189 valgrind_p = RUNNING_ON_VALGRIND != 0;
7190#endif
7191} 7530}
7192 7531
7193void 7532void