Joshua, > Le 25 févr. 2021 à 06:54, Akim Demaille <[email protected]> a écrit : > > Thanks for the fix! However, this is doing a lot of malloc/free for a > handful of file names. I'll rather see if there's a means to have a cache > for this.
I don't have time to finish this now, but this message is to make sure we aren't both working on it. Here's what I have currently. It appears to work. commit 6c47c14f0c245a70ed5a32048b50b678b7f8bb8a Author: Akim Demaille <[email protected]> Date: Thu Feb 25 08:31:50 2021 +0100 WIP: cache the mapped file names * #: . * #: . * #: . * #: . * #: . * #: . * #: . * #: . diff --git a/bootstrap.conf b/bootstrap.conf index 51777601b..6f1a3fc61 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -27,6 +27,7 @@ gnulib_modules=' getopt-gnu gettext-h git-version-gen gitlog-to-changelog gpl-3.0 intprops inttypes isnan javacomp-script + hash-map javaexec-script ldexpl libtextstyle-optional @@ -58,7 +59,7 @@ gnulib_modules=' xconcat-filename xhash xlist - xmemdup0 + xmap xmemdup0 xstrndup fprintf-posix printf-posix snprintf-posix sprintf-posix diff --git a/lib/.gitignore b/lib/.gitignore index 5d7f60e5b..00843d68f 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -162,10 +162,14 @@ /gl_anytreehash_list2.h /gl_array_list.c /gl_array_list.h +/gl_hash_map.c +/gl_hash_map.h /gl_linked_list.c /gl_linked_list.h /gl_list.c /gl_list.h +/gl_map.c +/gl_map.h /gl_oset.c /gl_oset.h /gl_rbtree_ordered.h @@ -175,6 +179,8 @@ /gl_rbtreehash_list.h /gl_xlist.c /gl_xlist.h +/gl_xmap.c +/gl_xmap.h /gnulib.mk /hard-locale.c /hard-locale.h diff --git a/lib/malloc/.gitignore b/lib/malloc/.gitignore new file mode 100644 index 000000000..6f3f8a3ba --- /dev/null +++ b/lib/malloc/.gitignore @@ -0,0 +1,5 @@ +/scratch_buffer.h +/scratch_buffer_dupfree.c +/scratch_buffer_grow.c +/scratch_buffer_grow_preserve.c +/scratch_buffer_set_array_size.c diff --git a/src/files.c b/src/files.c index c0d5d1ca7..7ffec3254 100644 --- a/src/files.c +++ b/src/files.c @@ -26,6 +26,8 @@ #include <error.h> #include <get-errno.h> #include <gl_array_list.h> +#include <gl_hash_map.h> +#include <gl_xmap.h> #include <gl_xlist.h> #include <quote.h> #include <quotearg.h> @@ -58,7 +60,6 @@ char *spec_graph_file = NULL; /* for -g. */ char *spec_html_file = NULL; /* for --html. */ char *spec_xml_file = NULL; /* for -x. */ char *spec_header_file = NULL; /* for --header. */ -char *spec_mapped_header_file = NULL; char *parser_file_name; /* All computed output file names. */ @@ -95,7 +96,6 @@ uniqstr grammar_file = NULL; char *all_but_ext; static char *all_but_tab_ext; char *dir_prefix; -char *mapped_dir_prefix; /* C source file extension (the parser source). */ static char *src_extension = NULL; @@ -109,6 +109,10 @@ struct prefix_map }; static gl_list_t prefix_maps = NULL; + +/* Map file names to prefix-mapped file names. */ +static gl_map_t mapped_files = NULL; + /*-----------------------------------------------------------------. | Return a newly allocated string composed of the concatenation of | @@ -172,11 +176,10 @@ xfdopen (int fd, char const *mode) return res; } -/* Given an input file path, returns a dynamically allocated string that - contains the path with the file prefix mapping rules applied, or NULL if - the input was NULL. */ -char * -map_file_name (char const *filename) +/* The mapped name of FILENAME, allocated, if there are prefix maps. + Otherwise NULL. */ +static char * +map_file_name_alloc (char const *filename) { if (!filename) return NULL; @@ -209,6 +212,49 @@ map_file_name (char const *filename) return s; } +static bool +string_equals (const void *x1, const void *x2) +{ + const char *s1 = x1; + const char *s2 = x2; + return STREQ (s1, s2); +} + +/* A hash function for NUL-terminated char* strings using + the method described by Bruno Haible. + See https://www.haible.de/bruno/hashfunc.html. */ +static size_t +string_hash (const void *x) +{ +#define SIZE_BITS (sizeof (size_t) * CHAR_BIT) + + const char *s = x; + size_t h = 0; + + for (; *s; s++) + h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); + + return h; +} + +const char * +map_file_name (char const *filename) +{ + if (!prefix_maps) + return filename; + if (!mapped_files) + mapped_files + = gl_map_nx_create_empty (GL_HASH_MAP, + string_equals, string_hash, NULL, NULL); + const void *res = gl_map_get (mapped_files, filename); + if (!res) + { + res = map_file_name_alloc (filename); + gl_map_put (mapped_files, filename, map_file_name_alloc (filename)); + } + return res; +} + static void prefix_map_free (struct prefix_map *p) { @@ -446,9 +492,6 @@ compute_output_file_names (void) output_file_name_check (&spec_verbose_file, false); } - spec_mapped_header_file = map_file_name (spec_header_file); - mapped_dir_prefix = map_file_name (dir_prefix); - free (all_but_tab_ext); free (src_extension); free (header_extension); @@ -536,10 +579,8 @@ output_file_names_free (void) free (spec_html_file); free (spec_xml_file); free (spec_header_file); - free (spec_mapped_header_file); free (parser_file_name); free (dir_prefix); - free (mapped_dir_prefix); for (int i = 0; i < generated_files_size; i++) free (generated_files[i].name); free (generated_files); @@ -547,4 +588,6 @@ output_file_names_free (void) if (prefix_maps) gl_list_free (prefix_maps); + if (mapped_files) + gl_map_free (mapped_files); } diff --git a/src/files.h b/src/files.h index e84497115..385847739 100644 --- a/src/files.h +++ b/src/files.h @@ -53,15 +53,9 @@ extern char *spec_xml_file; /* File name specified with --header. */ extern char *spec_header_file; -/* File name specified with --header, adjusted for mapped prefixes. */ -extern char *spec_mapped_header_file; - /* Directory prefix of output file names. */ extern char *dir_prefix; -/* Directory prefix of output file name, adjusted for mapped prefixes. */ -extern char *mapped_dir_prefix; - /* The file name as given on the command line. Not named "input_file" because Flex uses this name for an argument, and therefore GCC warns about a name clash. */ @@ -94,7 +88,13 @@ FILE *xfopen (const char *name, char const *mode); void xfclose (FILE *ptr); FILE *xfdopen (int fd, char const *mode); -char *map_file_name (char const *filename); +/* Given an input file path, return a string that contains the path + with the file prefix mapping rules applied, or NULL if the input + was NULL. Do not free the return value. */ +const char *map_file_name (char const *filename); + +/* Add a new file prefix mapping. If a file path starts with + oldprefix, it will be replaced with newprefix. */ void add_prefix_map (char const *oldprefix, char const *newprefix); #endif /* !FILES_H_ */ diff --git a/src/muscle-tab.c b/src/muscle-tab.c index 3e7657ca1..0654a3f10 100644 --- a/src/muscle-tab.c +++ b/src/muscle-tab.c @@ -204,10 +204,8 @@ static void muscle_syncline_grow (char const *key, location loc) { obstack_printf (&muscle_obstack, "]b4_syncline(%d, ", loc.start.line); - char *f = map_file_name (loc.start.file); obstack_quote (&muscle_obstack, - quotearg_style (c_quoting_style, f)); - free (f); + quotearg_style (c_quoting_style, map_file_name (loc.start.file))); obstack_sgrow (&muscle_obstack, ")dnl\n["); char const *extension = obstack_finish0 (&muscle_obstack); muscle_grow (key, extension, "", ""); diff --git a/src/output.c b/src/output.c index 34dbc6714..4b1bb0d8e 100644 --- a/src/output.c +++ b/src/output.c @@ -531,9 +531,7 @@ user_actions_output (FILE *out) { fprintf (out, "b4_syncline(%d, ", rules[r].action_loc.start.line); - char *f = map_file_name (rules[r].action_loc.start.file); - string_output (out, f); - free(f); + string_output (out, map_file_name (rules[r].action_loc.start.file)); fprintf (out, ")dnl\n"); } fprintf (out, "[%*s%s]],\n[[", @@ -631,10 +629,8 @@ prepare_symbol_definitions (void) if (p->code) { - char *f = map_file_name (p->location.start.file); SET_KEY2 (pname, "file"); - MUSCLE_INSERT_C_STRING (key, f); - free (f); + MUSCLE_INSERT_C_STRING (key, map_file_name (p->location.start.file)); SET_KEY2 (pname, "line"); MUSCLE_INSERT_INT (key, p->location.start.line); @@ -852,6 +848,9 @@ prepare (void) MUSCLE_INSERT_STRING ("file_name_all_but_ext", all_but_ext); + const char *spec_mapped_header_file = map_file_name (spec_header_file); + const char *mapped_dir_prefix = map_file_name (dir_prefix); + #define DEFINE(Name) MUSCLE_INSERT_STRING (#Name, Name ? Name : "") DEFINE (dir_prefix); DEFINE (mapped_dir_prefix); diff --git a/src/scan-skel.l b/src/scan-skel.l index 1ec125af5..20049cfb3 100644 --- a/src/scan-skel.l +++ b/src/scan-skel.l @@ -269,7 +269,5 @@ fail_for_invalid_at (char const *at) static void output_mapped_file (char const *name) { - char *f = map_file_name (name); - fputs (quotearg_style (c_quoting_style, f), yyout); - free (f); + fputs (quotearg_style (c_quoting_style, map_file_name (name)), yyout); }
