aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2025-09-16 18:57:51 +0200
committerMattias EngdegÄrd2025-09-17 12:49:14 +0200
commitde4ca2bdb1ae69a6ad0c4fc0473f2823e74f7f2b (patch)
treeb9222093ec43a83656dc94bb1a8e75ce1d0799ae
parent08b2d53e48fc8f8081bfa5fe5465dc99dbb7407d (diff)
downloademacs-de4ca2bdb1ae69a6ad0c4fc0473f2823e74f7f2b.tar.gz
emacs-de4ca2bdb1ae69a6ad0c4fc0473f2823e74f7f2b.zip
Turn some checking macros into functions in the GC marker code
This rids us of a bunch of unhygienic macros with free variables and makes the marking code actually readable again. Even better, it is all processed by the compiler even when the checks are disabled. * src/alloc.c (CHECK_ALLOCATED, CHECK_LIVE, CHECK_ALLOCATED_AND_LIVE) (CHECK_ALLOCATED_AND_LIVE_SYMBOL): Transform macros into... (check_live, check_allocated_and_live, check_allocated_and_live_symbol) (check_allocated_and_live_vectorlike): ...functions. Callers adapted.
-rw-r--r--src/alloc.c161
1 files changed, 80 insertions, 81 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 9ace6f01856..4ed76d9d368 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -120,6 +120,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
120#if defined ENABLE_CHECKING && !defined GC_CHECK_MARKED_OBJECTS 120#if defined ENABLE_CHECKING && !defined GC_CHECK_MARKED_OBJECTS
121# define GC_CHECK_MARKED_OBJECTS 1 121# define GC_CHECK_MARKED_OBJECTS 1
122#endif 122#endif
123#ifndef GC_CHECK_MARKED_OBJECTS
124# define GC_CHECK_MARKED_OBJECTS 0
125#endif
123 126
124/* GC_MALLOC_CHECK defined means perform validity checks of malloc'd 127/* GC_MALLOC_CHECK defined means perform validity checks of malloc'd
125 memory. Can do this only if using gmalloc.c and if not checking 128 memory. Can do this only if using gmalloc.c and if not checking
@@ -6389,6 +6392,75 @@ mark_stack_push_values (Lisp_Object *values, ptrdiff_t n)
6389 .u.values = values}; 6392 .u.values = values};
6390} 6393}
6391 6394
6395/* When GC_CHECK_MARKED_OBJECTS is set, perform some sanity checks on
6396 the objects marked here. Abort if we encounter an object we know is
6397 bogus. This increases GC time by ~80%. */
6398
6399/* Check that the object pointed to by PO is alive, using predicate
6400 function LIVEP. */
6401static inline void
6402check_live (bool (*livep) (struct mem_node *m, void *p), enum mem_type mtype,
6403 void *po, struct mem_node *m)
6404{
6405 if (GC_CHECK_MARKED_OBJECTS)
6406 {
6407 if (pdumper_object_p (po))
6408 return;
6409 if (!(m->type == mtype && livep (m, po)))
6410 emacs_abort ();
6411 }
6412}
6413
6414/* Check that the object pointed to by PO is known to be a Lisp
6415 structure allocated from the heap, and that it is alive. */
6416static inline void
6417check_allocated_and_live (bool (*livep) (struct mem_node *m, void *p),
6418 enum mem_type mtype,
6419 void *po)
6420{
6421 if (GC_CHECK_MARKED_OBJECTS)
6422 {
6423 if (pdumper_object_p (po))
6424 {
6425 if (!pdumper_object_p_precise (po))
6426 emacs_abort ();
6427 return;
6428 }
6429 struct mem_node *m = mem_find (po);
6430 if (m == MEM_NIL)
6431 emacs_abort ();
6432 check_live (livep, mtype, po, m);
6433 }
6434}
6435
6436/* Like check_allocated_and_live but for symbols. */
6437static inline void
6438check_allocated_and_live_symbol (void *po, struct Lisp_Symbol *sym)
6439{
6440 if (GC_CHECK_MARKED_OBJECTS)
6441 if (!c_symbol_p (sym))
6442 check_allocated_and_live (live_symbol_p, MEM_TYPE_SYMBOL, po);
6443}
6444
6445/* Like check_allocated_and_live but for vectorlike. */
6446static inline void
6447check_allocated_and_live_vectorlike (void *po, Lisp_Object obj)
6448{
6449 if (GC_CHECK_MARKED_OBJECTS)
6450 {
6451 if (!pdumper_object_p (po) && !SUBRP (obj) && !main_thread_p (po))
6452 {
6453 struct mem_node *m = mem_find (po);
6454 if (m == MEM_NIL)
6455 emacs_abort ();
6456 if (m->type == MEM_TYPE_VECTORLIKE)
6457 check_live (live_large_vector_p, MEM_TYPE_VECTORLIKE, po, m);
6458 else
6459 check_live (live_small_vector_p, MEM_TYPE_VECTOR_BLOCK, po, m);
6460 }
6461 }
6462}
6463
6392/* Traverse and mark objects on the mark stack above BASE_SP. 6464/* Traverse and mark objects on the mark stack above BASE_SP.
6393 6465
6394 Traversal is depth-first using the mark stack for most common 6466 Traversal is depth-first using the mark stack for most common
@@ -6397,9 +6469,6 @@ mark_stack_push_values (Lisp_Object *values, ptrdiff_t n)
6397static void 6469static void
6398process_mark_stack (ptrdiff_t base_sp) 6470process_mark_stack (ptrdiff_t base_sp)
6399{ 6471{
6400#if GC_CHECK_MARKED_OBJECTS
6401 struct mem_node *m = NULL;
6402#endif
6403#if GC_CDR_COUNT 6472#if GC_CDR_COUNT
6404 ptrdiff_t cdr_count = 0; 6473 ptrdiff_t cdr_count = 0;
6405#endif 6474#endif
@@ -6410,66 +6479,12 @@ process_mark_stack (ptrdiff_t base_sp)
6410 { 6479 {
6411 Lisp_Object obj = mark_stack_pop (); 6480 Lisp_Object obj = mark_stack_pop ();
6412 mark_obj: ; 6481 mark_obj: ;
6482 void *po = XPNTR (obj);
6413#if GC_REMEMBER_LAST_MARKED 6483#if GC_REMEMBER_LAST_MARKED
6414 last_marked[last_marked_index++] = obj; 6484 last_marked[last_marked_index++] = obj;
6415 last_marked_index &= LAST_MARKED_SIZE - 1; 6485 last_marked_index &= LAST_MARKED_SIZE - 1;
6416#endif 6486#endif
6417 6487
6418 /* Perform some sanity checks on the objects marked here. Abort if
6419 we encounter an object we know is bogus. This increases GC time
6420 by ~80%. */
6421#if GC_CHECK_MARKED_OBJECTS
6422 void *po = XPNTR (obj);
6423
6424 /* Check that the object pointed to by PO is known to be a Lisp
6425 structure allocated from the heap. */
6426#define CHECK_ALLOCATED() \
6427 do { \
6428 if (pdumper_object_p (po)) \
6429 { \
6430 if (!pdumper_object_p_precise (po)) \
6431 emacs_abort (); \
6432 break; \
6433 } \
6434 m = mem_find (po); \
6435 if (m == MEM_NIL) \
6436 emacs_abort (); \
6437 } while (0)
6438
6439 /* Check that the object pointed to by PO is live, using predicate
6440 function LIVEP. */
6441#define CHECK_LIVE(LIVEP, MEM_TYPE) \
6442 do { \
6443 if (pdumper_object_p (po)) \
6444 break; \
6445 if (! (m->type == MEM_TYPE && LIVEP (m, po))) \
6446 emacs_abort (); \
6447 } while (0)
6448
6449 /* Check both of the above conditions, for non-symbols. */
6450#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) \
6451 do { \
6452 CHECK_ALLOCATED (); \
6453 CHECK_LIVE (LIVEP, MEM_TYPE); \
6454 } while (false)
6455
6456 /* Check both of the above conditions, for symbols. */
6457#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() \
6458 do { \
6459 if (!c_symbol_p (ptr)) \
6460 { \
6461 CHECK_ALLOCATED (); \
6462 CHECK_LIVE (live_symbol_p, MEM_TYPE_SYMBOL); \
6463 } \
6464 } while (false)
6465
6466#else /* not GC_CHECK_MARKED_OBJECTS */
6467
6468#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) ((void) 0)
6469#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0)
6470
6471#endif /* not GC_CHECK_MARKED_OBJECTS */
6472
6473 switch (XTYPE (obj)) 6488 switch (XTYPE (obj))
6474 { 6489 {
6475 case Lisp_String: 6490 case Lisp_String:
@@ -6477,7 +6492,7 @@ process_mark_stack (ptrdiff_t base_sp)
6477 register struct Lisp_String *ptr = XSTRING (obj); 6492 register struct Lisp_String *ptr = XSTRING (obj);
6478 if (string_marked_p (ptr)) 6493 if (string_marked_p (ptr))
6479 break; 6494 break;
6480 CHECK_ALLOCATED_AND_LIVE (live_string_p, MEM_TYPE_STRING); 6495 check_allocated_and_live (live_string_p, MEM_TYPE_STRING, po);
6481 set_string_marked (ptr); 6496 set_string_marked (ptr);
6482 mark_interval_tree (ptr->u.s.intervals); 6497 mark_interval_tree (ptr->u.s.intervals);
6483#ifdef GC_CHECK_STRING_BYTES 6498#ifdef GC_CHECK_STRING_BYTES
@@ -6498,18 +6513,7 @@ process_mark_stack (ptrdiff_t base_sp)
6498 enum pvec_type pvectype 6513 enum pvec_type pvectype
6499 = PSEUDOVECTOR_TYPE (ptr); 6514 = PSEUDOVECTOR_TYPE (ptr);
6500 6515
6501#ifdef GC_CHECK_MARKED_OBJECTS 6516 check_allocated_and_live_vectorlike (po, obj);
6502 if (!pdumper_object_p (po) && !SUBRP (obj) && !main_thread_p (po))
6503 {
6504 m = mem_find (po);
6505 if (m == MEM_NIL)
6506 emacs_abort ();
6507 if (m->type == MEM_TYPE_VECTORLIKE)
6508 CHECK_LIVE (live_large_vector_p, MEM_TYPE_VECTORLIKE);
6509 else
6510 CHECK_LIVE (live_small_vector_p, MEM_TYPE_VECTOR_BLOCK);
6511 }
6512#endif
6513 6517
6514 switch (pvectype) 6518 switch (pvectype)
6515 { 6519 {
@@ -6612,7 +6616,7 @@ process_mark_stack (ptrdiff_t base_sp)
6612 nextsym: 6616 nextsym:
6613 if (symbol_marked_p (ptr)) 6617 if (symbol_marked_p (ptr))
6614 break; 6618 break;
6615 CHECK_ALLOCATED_AND_LIVE_SYMBOL (); 6619 check_allocated_and_live_symbol (po, ptr);
6616 set_symbol_marked (ptr); 6620 set_symbol_marked (ptr);
6617 /* Attempt to catch bogus objects. */ 6621 /* Attempt to catch bogus objects. */
6618 eassert (valid_lisp_object_p (ptr->u.s.function)); 6622 eassert (valid_lisp_object_p (ptr->u.s.function));
@@ -6657,9 +6661,8 @@ process_mark_stack (ptrdiff_t base_sp)
6657 mark_interval_tree (string_intervals (ptr->u.s.name)); 6661 mark_interval_tree (string_intervals (ptr->u.s.name));
6658 /* Inner loop to mark next symbol in this bucket, if any. */ 6662 /* Inner loop to mark next symbol in this bucket, if any. */
6659 ptr = ptr->u.s.next; 6663 ptr = ptr->u.s.next;
6660#if GC_CHECK_MARKED_OBJECTS 6664 if (GC_CHECK_MARKED_OBJECTS)
6661 po = ptr; 6665 po = ptr;
6662#endif
6663 if (ptr) 6666 if (ptr)
6664 goto nextsym; 6667 goto nextsym;
6665 } 6668 }
@@ -6670,7 +6673,7 @@ process_mark_stack (ptrdiff_t base_sp)
6670 struct Lisp_Cons *ptr = XCONS (obj); 6673 struct Lisp_Cons *ptr = XCONS (obj);
6671 if (cons_marked_p (ptr)) 6674 if (cons_marked_p (ptr))
6672 break; 6675 break;
6673 CHECK_ALLOCATED_AND_LIVE (live_cons_p, MEM_TYPE_CONS); 6676 check_allocated_and_live (live_cons_p, MEM_TYPE_CONS, po);
6674 set_cons_marked (ptr); 6677 set_cons_marked (ptr);
6675 /* Avoid growing the stack if the cdr is nil. 6678 /* Avoid growing the stack if the cdr is nil.
6676 In any case, make sure the car is expanded first. */ 6679 In any case, make sure the car is expanded first. */
@@ -6693,7 +6696,7 @@ process_mark_stack (ptrdiff_t base_sp)
6693 struct Lisp_Float *f = XFLOAT (obj); 6696 struct Lisp_Float *f = XFLOAT (obj);
6694 if (!f) 6697 if (!f)
6695 break; /* for HASH_UNUSED_ENTRY_KEY */ 6698 break; /* for HASH_UNUSED_ENTRY_KEY */
6696 CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT); 6699 check_allocated_and_live (live_float_p, MEM_TYPE_FLOAT, po);
6697 /* Do not mark floats stored in a dump image: these floats are 6700 /* Do not mark floats stored in a dump image: these floats are
6698 "cold" and do not have mark bits. */ 6701 "cold" and do not have mark bits. */
6699 if (pdumper_object_p (f)) 6702 if (pdumper_object_p (f))
@@ -6711,10 +6714,6 @@ process_mark_stack (ptrdiff_t base_sp)
6711 emacs_abort (); 6714 emacs_abort ();
6712 } 6715 }
6713 } 6716 }
6714
6715#undef CHECK_LIVE
6716#undef CHECK_ALLOCATED
6717#undef CHECK_ALLOCATED_AND_LIVE
6718} 6717}
6719 6718
6720void 6719void