From 96eacb2c094e88dc38d9d79e454eb1c19f3dc25d Mon Sep 17 00:00:00 2001 From: Helmut Eller Date: Tue, 28 Oct 2025 09:21:23 +0100 Subject: [PATCH] Move the attribute field of charsets to a separate vector This simplifies the GC code, as this was the only field in the charset struct that referenced the GC heap. Without it, we no longer need to trace the charset_table. * src/charset.h (struct charset.attributes): Removed. (charset_attributes_getter): New helper. (CHARSET_ATTRIBUTES): Use it. * src/charset.c (charset_attributes_table): New. (Fdefine_charset_internal): Place attrs in charset_attributes_table. (syms_of_charset): Initialize charset_attributes_table. (mark_charset): Deleted. * src/pdumper.c (dump_charset): Skip attributes field. * src/lisp.h (mark_charset): Deleted. * src/alloc.c (garbage_collect): mark_charset no longer needed. --- src/alloc.c | 1 - src/charset.c | 39 +++++++++++++++++++++++---------------- src/charset.h | 12 +++++++++--- src/lisp.h | 1 - src/pdumper.c | 3 +-- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index c0c24c65737..5da38cadb5d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5866,7 +5866,6 @@ garbage_collect (void) mark_terminals (); mark_kboards (); mark_threads (); - mark_charset (); mark_composite (); mark_profiler (); #ifdef HAVE_PGTK diff --git a/src/charset.c b/src/charset.c index 42dc6a60367..11d181d4032 100644 --- a/src/charset.c +++ b/src/charset.c @@ -65,6 +65,12 @@ struct charset *charset_table; int charset_table_size; int charset_table_used; +/* Table of attribute vectors. charset_attributes_table[id] contains + the attribute vector for the charset at charset_table[id]. + + This is a separate vector to simplify GC. */ +Lisp_Object charset_attributes_table; + /* Special charsets corresponding to symbols. */ int charset_ascii; int charset_eight_bit; @@ -1131,13 +1137,19 @@ usage: (define-charset-internal ...) */) coding_system.charbuf[i] entries, which are 'int'. */ int old_size = charset_table_size; ptrdiff_t new_size = old_size; - struct charset *new_table = - xpalloc (0, &new_size, 1, - min (INT_MAX, MOST_POSITIVE_FIXNUM), - sizeof *charset_table); - memcpy (new_table, charset_table, old_size * sizeof *new_table); - charset_table = new_table; + struct charset *new_table + = xpalloc (0, &new_size, 1, + min (INT_MAX, MOST_POSITIVE_FIXNUM), + sizeof *charset_table); + memcpy (new_table, charset_table, + old_size * sizeof *new_table); + charset_table = new_table; charset_table_size = new_size; + Lisp_Object new_attr_table = make_vector (new_size, Qnil); + for (size_t i = 0; i < old_size; i++) + ASET (new_attr_table, i, + AREF (charset_attributes_table, i)); + charset_attributes_table = new_attr_table; /* FIXME: This leaks memory, as the old charset_table becomes unreachable. If the old charset table is charset_table_init then this leak is intentional; otherwise, it's unclear. @@ -1152,8 +1164,9 @@ usage: (define-charset-internal ...) */) ASET (attrs, charset_id, make_fixnum (id)); charset.id = id; - charset.attributes = attrs; charset_table[id] = charset; + ASET (charset_attributes_table, id, attrs); + eassert (ASIZE (charset_attributes_table) == charset_table_size); if (charset.method == CHARSET_METHOD_MAP) { @@ -2272,15 +2285,6 @@ See also `charset-priority-list' and `set-charset-priority'. */) return charsets; } -/* Not strictly necessary, because all charset attributes are also - reachable from `Vcharset_hash_table`. */ -void -mark_charset (void) -{ - for (int i = 0; i < charset_table_used; i++) - mark_object (charset_table[i].attributes); -} - void init_charset (void) @@ -2383,6 +2387,9 @@ syms_of_charset (void) charset_table_used = 0; PDUMPER_REMEMBER_SCALAR (charset_table_used); + charset_attributes_table = make_vector (charset_table_size, Qnil); + staticpro (&charset_attributes_table); + defsubr (&Scharsetp); defsubr (&Smap_charset_chars); defsubr (&Sdefine_charset_internal); diff --git a/src/charset.h b/src/charset.h index 56ed62b4473..0738217dc0c 100644 --- a/src/charset.h +++ b/src/charset.h @@ -150,8 +150,6 @@ struct charset /* Index to charset_table. */ int id; - Lisp_Object attributes; - /* Dimension of the charset: 1, 2, 3, or 4. */ int dimension; @@ -250,6 +248,8 @@ extern struct charset *charset_table; extern int charset_table_size; extern int charset_table_used; +extern Lisp_Object charset_attributes_table; + #define CHARSET_FROM_ID(id) (charset_table + (id)) extern Lisp_Object Vcharset_ordered_list; @@ -287,8 +287,14 @@ extern int emacs_mule_charset[256]; #define CHARSET_SYMBOL_HASH_INDEX(symbol) \ hash_find (XHASH_TABLE (Vcharset_hash_table), symbol) +INLINE Lisp_Object +charset_attributes_getter (struct charset *charset) +{ + return AREF (charset_attributes_table, charset->id); +} + /* Return the attribute vector of CHARSET. */ -#define CHARSET_ATTRIBUTES(charset) (charset)->attributes +#define CHARSET_ATTRIBUTES(charset) (charset_attributes_getter (charset)) #define CHARSET_ID(charset) ((charset)->id) #define CHARSET_DIMENSION(charset) ((charset)->dimension) diff --git a/src/lisp.h b/src/lisp.h index 37c34dfbe84..cbd61126a74 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4226,7 +4226,6 @@ extern ptrdiff_t multibyte_chars_in_text (const unsigned char *, ptrdiff_t); extern void syms_of_character (void); /* Defined in charset.c. */ -extern void mark_charset (void); extern void init_charset (void); extern void init_charset_once (void); extern void syms_of_charset (void); diff --git a/src/pdumper.c b/src/pdumper.c index c21af24d9f1..3f338db33c6 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -3208,7 +3208,7 @@ dump_object_for_offset (struct dump_context *ctx, Lisp_Object object) static dump_off dump_charset (struct dump_context *ctx, int cs_i) { -#if CHECK_STRUCTS && !defined (HASH_charset_E31F4B5D96) +#if CHECK_STRUCTS && !defined (HASH_charset_C9F4DCA7A7) # error "charset changed. See CHECK_STRUCTS comment in config.h." #endif /* We can't change the alignment here, because ctx->offset is what @@ -3220,7 +3220,6 @@ dump_charset (struct dump_context *ctx, int cs_i) if (cs_i < charset_table_used) /* Don't look at uninitialized data. */ { DUMP_FIELD_COPY (&out, cs, id); - dump_field_lv (ctx, &out, cs, &cs->attributes, WEIGHT_NORMAL); DUMP_FIELD_COPY (&out, cs, dimension); memcpy (out.code_space, &cs->code_space, sizeof (cs->code_space)); if (cs->code_space_mask)