On 8/23/24 09:39, Jan Hubicka wrote:
Hi,
         1:    4:int notmain(const char *entity)
         -: == inlined from hello.h ==
         1:    6:  if (s)
branch  0 taken 0 (fallthrough)
branch  1 taken 1
     #####:    7:    printf ("hello, %s!\n", s);
     %%%%%:    7-block 3
call    0 never executed
         -:    8:  else
         1:    9:    printf ("hello, world!\n");
         1:    9-block 4
call    0 returned 1
         1:   10:  return 0;
         1:   10-block 5
         -: == inlined from hello.h (end) ==
         -:    5:{
         1:    6:  return hello (entity);
         1:    6-block 7
         -:    7:}

This indeed looks like a reasonable goal.

Thanks, pushed.

gcc/ChangeLog:

        * gcov.cc (release_structures): Release source_lines.
        (slurp): New function.
        (output_lines): Read sources with slurp.
---
  gcc/gcov.cc | 70 ++++++++++++++++++++++++++++++++++++++++-------------
  1 file changed, 53 insertions(+), 17 deletions(-)

diff --git a/gcc/gcov.cc b/gcc/gcov.cc
index e76a314041c..19019f404ee 100644
--- a/gcc/gcov.cc
+++ b/gcc/gcov.cc
@@ -550,6 +550,11 @@ static vector<name_map> names;
     a file being read multiple times.  */
  static vector<char *> processed_files;
+/* The contents of a source file. The nth SOURCE_LINES entry is the
+   contents of the nth SOURCES, or empty if it has not or could not be
+   read.  */
+static vector<vector<const char *>*> source_lines;
+
  /* This holds data summary information.  */
static unsigned object_runs;
@@ -762,6 +767,8 @@ static string make_gcov_file_name (const char *, const char 
*);
  static char *mangle_name (const char *);
  static void release_structures (void);
  extern int main (int, char **);
+static const vector<const char *>&
+slurp (const source_info &src, FILE *gcov_file, const char *line_start);
function_info::function_info (): m_name (NULL), m_demangled_name (NULL),
    ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
@@ -1804,6 +1811,15 @@ release_structures (void)
         it != functions.end (); it++)
      delete (*it);
+ for (vector<const char *> *lines : source_lines)
+    {
+      if (lines)
+       for (const char *line : *lines)
+         free (const_cast <char*> (line));
+      delete (lines);
+    }
+  source_lines.resize (0);
+
    for (fnfilter &filter : filters)
      regfree (&filter.regex);
@@ -3246,6 +3262,41 @@ read_line (FILE *file)
    return pos ? string : NULL;
  }
+/* Get the vector with the contents SRC, possibly from a cache. If
+   the reading fails, a message prefixed with LINE_START is written to
+   GCOV_FILE.  */
+static const vector<const char *>&
+slurp (const source_info &src, FILE *gcov_file,
+       const char *line_start)
+{
+  if (source_lines.size () <= src.index)
+    source_lines.resize (src.index + 1);
+
+  /* Store vector pointers so that the returned references remain
+     stable and won't be broken by successive calls to slurp.  */
+  if (!source_lines[src.index])
+    source_lines[src.index] = new vector<const char *> ();
+
+  if (!source_lines[src.index]->empty ())
+    return *source_lines[src.index];
+
+  FILE *source_file = fopen (src.name, "r");
+  if (!source_file)
+    fnotice (stderr, "Cannot open source file %s\n", src.name);
+  else if (src.file_time == 0)
+    fprintf (gcov_file, "%sSource is newer than graph\n", line_start);
+
+  const char *retval;
+  vector<const char *> &lines = *source_lines[src.index];
+  if (source_file)
+    while ((retval = read_line (source_file)))
+      lines.push_back (xstrdup (retval));
+
+  if (source_file)
+    fclose (source_file);
+  return lines;
So this is basically going to read all sources needed for single
compilation unit (.cc file) into memory at once.  I guess that is OK.
I wonder if we don't want to do something like mmap the source and then
set up source_lines array instead of reading every like into spearate
xstrduped chunk?
But that could be done incrementally, so th epatch is OK.

Honza
+}
+
  /* Pad string S with spaces from left to have total width equal to 9.  */
static void
@@ -3435,9 +3486,6 @@ output_lines (FILE *gcov_file, const source_info *src)
  #define  DEFAULT_LINE_START "        -:    0:"
  #define FN_SEPARATOR "------------------\n"
- FILE *source_file;
-  const char *retval;
-
    /* Print colorization legend.  */
    if (flag_use_colors)
      fprintf (gcov_file, "%s",
@@ -3464,17 +3512,8 @@ output_lines (FILE *gcov_file, const source_info *src)
        fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
      }
- source_file = fopen (src->name, "r");
-  if (!source_file)
-    fnotice (stderr, "Cannot open source file %s\n", src->name);
-  else if (src->file_time == 0)
-    fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
-
-  vector<const char *> source_lines;
-  if (source_file)
-    while ((retval = read_line (source_file)) != NULL)
-      source_lines.push_back (xstrdup (retval));
-
+  const vector<const char *> &source_lines = slurp (*src, gcov_file,
+                                                   DEFAULT_LINE_START);
    unsigned line_start_group = 0;
    vector<function_info *> *fns;
    unsigned filtered_line_end = !filters.empty () ? 0 : source_lines.size ();
@@ -3596,7 +3635,4 @@ output_lines (FILE *gcov_file, const source_info *src)
          line_start_group = 0;
        }
      }
-
-  if (source_file)
-    fclose (source_file);
  }
--
2.39.2

Reply via email to