From 8f9c59f8c51cd771a5baf06e1a5f309432a0dba3 Mon Sep 17 00:00:00 2001 From: Helmut Eller Date: Tue, 11 Jun 2024 21:14:21 +0200 Subject: [PATCH 2/3] Dump IGC_OBJ_STRING_DATA with headers This makes the mirroring code more uniform. * src/pdumper.c (dump_cold_string): Emit headers. * src/igc.c (igc_dump_finish_obj): Handle objects in pure space. (builtin_obj_type_and_hash): Renamed from builtin_obj_type. (pure_obj_type_and_hash): New helper. (is_builtin_obj_type): Abort for unrecognized cases. (mirror_string): Don't copy strings in the cold dump. --- src/igc.c | 68 ++++++++++++++++++++++++++++++++------------------- src/pdumper.c | 8 ++++++ 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/igc.c b/src/igc.c index ce389f1d2d5..713be9308dd 100644 --- a/src/igc.c +++ b/src/igc.c @@ -109,6 +109,9 @@ #define igc_assert(expr) \ #define igc_static_assert(x) verify (x) #define igc_const_cast(type, expr) ((type) (expr)) +#define NOT_IMPLEMENTED() \ + igc_assert_fail (__FILE__, __LINE__, "not implemented") + #define IGC_TAG_MASK (~VALMASK) /* Using mps_arena_has_addr is expensive. so try to do something that is @@ -3579,17 +3582,42 @@ is_builtin_subr (enum igc_obj_type type, void *client) } static enum igc_obj_type -builtin_obj_type (enum igc_obj_type type, void *client) +builtin_obj_type_and_hash (size_t *hash, enum igc_obj_type type, void *client) { if (c_symbol_p (client)) - return IGC_OBJ_BUILTIN_SYMBOL; + return *hash = igc_hash (make_lisp_symbol (client)), + IGC_OBJ_BUILTIN_SYMBOL; if (client == &main_thread) - return IGC_OBJ_BUILTIN_THREAD; + return *hash = igc_hash (make_lisp_ptr (client, Lisp_Vectorlike)), + IGC_OBJ_BUILTIN_THREAD; if (is_builtin_subr (type, client)) - return IGC_OBJ_BUILTIN_SUBR; + return *hash = igc_hash (make_lisp_ptr (client, Lisp_Vectorlike)), + IGC_OBJ_BUILTIN_SUBR; emacs_abort (); } +static enum igc_obj_type +pure_obj_type_and_hash (size_t *hash_o, enum igc_obj_type type, void *client) +{ + switch (type) + { + case IGC_OBJ_STRING: + return *hash_o = igc_hash (make_lisp_ptr (client, Lisp_String)), type; + case IGC_OBJ_VECTOR: + return *hash_o = igc_hash (make_lisp_ptr (client, Lisp_Vectorlike)), + type; + case IGC_OBJ_CONS: + return *hash_o = igc_hash (make_lisp_ptr (client, Lisp_Cons)), type; + case IGC_OBJ_STRING_DATA: + return *hash_o = (uintptr_t)client & IGC_HASH_MASK, type; + case IGC_OBJ_FLOAT: + return *hash_o = igc_hash (make_lisp_ptr (client, Lisp_Float)), type; + default: + NOT_IMPLEMENTED (); + emacs_abort (); + } +} + static bool is_builtin_obj_type (enum igc_obj_type type) { @@ -3625,16 +3653,17 @@ is_builtin_obj_type (enum igc_obj_type type) case IGC_OBJ_BUILTIN_SUBR: return true; } + emacs_abort(); } char * -igc_dump_finish_obj (void *client, enum igc_obj_type type, - char *base, char *end) +igc_dump_finish_obj (void *client, enum igc_obj_type type, char *base, + char *end) { if (client == NULL) return end; - struct igc_header *out = (struct igc_header *) base; + struct igc_header *out = (struct igc_header *)base; if (is_mps (client)) { struct igc_header *h = client_to_base (client); @@ -3643,13 +3672,15 @@ igc_dump_finish_obj (void *client, enum igc_obj_type type, *out = *h; return base + to_bytes (h->nwords); } - size_t client_size = end - base - sizeof *out; size_t nbytes = obj_size (client_size); size_t nwords = to_words (nbytes); - type = builtin_obj_type (type, client); - *out = (struct igc_header) - { .obj_type = type, .hash = igc_hash (client), .nwords = nwords }; + size_t hash; + type = is_pure (client) ? pure_obj_type_and_hash (&hash, type, client) + : builtin_obj_type_and_hash (&hash, type, client); + *out = (struct igc_header){ .obj_type = type, + .hash = hash, + .nwords = nwords }; return base + nbytes; } @@ -3973,17 +4004,7 @@ mirror_symbol (struct igc_mirror *m, struct Lisp_Symbol *sym) static void mirror_string (struct igc_mirror *m, struct Lisp_String *s) { - /* FIXME: IGC_OBJ_STRING_DATA is currently not used in the dump, which - means string data has no igc_header in the dump. We could leave - the string data alone. Not sure what's best. */ - if (s->u.s.size_byte != -2) - { - igc_assert (pdumper_object_p (s->u.s.data)); - ptrdiff_t nbytes = STRING_BYTES (s); - unsigned char *data = alloc_string_data (nbytes, false); - memcpy (data, s->u.s.data, nbytes + 1); - s->u.s.data = data; - } + IGC_MIRROR_RAW (m, &s->u.s.data); IGC_MIRROR_RAW (m, &s->u.s.intervals); } @@ -3999,9 +4020,6 @@ mirror_interval (struct igc_mirror *m, struct interval *i) IGC_MIRROR_OBJ (m, &i->plist); } -#define NOT_IMPLEMENTED() \ - igc_assert_fail (__FILE__, __LINE__, "not implemented") - static void mirror_itree_tree (struct igc_mirror *m, struct itree_tree *t) { diff --git a/src/pdumper.c b/src/pdumper.c index b487bc39b43..aecb7ab1a16 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -3556,11 +3556,19 @@ dump_cold_string (struct dump_context *ctx, Lisp_Object string) error ("string too large"); dump_off total_size = ptrdiff_t_to_dump_off (SBYTES (string) + 1); eassert (total_size > 0); + +# ifdef HAVE_MPS + dump_align_output (ctx, DUMP_ALIGNMENT); + dump_igc_start_obj (ctx, IGC_OBJ_STRING_DATA, XSTRING (string)->u.s.data); +# endif dump_remember_fixup_ptr_raw (ctx, string_offset + dump_offsetof (struct Lisp_String, u.s.data), ctx->offset); dump_write (ctx, XSTRING (string)->u.s.data, total_size); +# ifdef HAVE_MPS + dump_igc_finish_obj (ctx); +# endif } static void -- 2.39.2