gcov-profile: use static pool for TOPN first
authorMartin Liska <mliska@suse.cz>
Mon, 19 Oct 2020 15:40:00 +0000 (17:40 +0200)
committerMartin Liska <mliska@suse.cz>
Tue, 27 Oct 2020 10:49:54 +0000 (11:49 +0100)
gcc/ChangeLog:

PR gcov-profile/97461
* gcov-io.h (GCOV_PREALLOCATED_KVP): Pre-allocate 64
static counters.

libgcc/ChangeLog:

PR gcov-profile/97461
* libgcov.h (gcov_counter_add): Use first static counters
as it should help to have malloc wrappers set up.

gcc/testsuite/ChangeLog:

PR gcov-profile/97461
* gcc.dg/tree-prof/pr97461.c: New test.

gcc/gcov-io.h
gcc/testsuite/gcc.dg/tree-prof/pr97461.c [new file with mode: 0644]
libgcc/libgcov.h

index 4dba01c78ce5e9c348730253ebf362723e4c3523..4e95c7c82eec5d796c46e09b09a889be63a79fc7 100644 (file)
@@ -293,7 +293,7 @@ GCOV_COUNTERS
 #define GCOV_TOPN_MAXIMUM_TRACKED_VALUES 32
 
 /* Number of pre-allocated gcov_kvp structures.  */
-#define GCOV_PREALLOCATED_KVP 16
+#define GCOV_PREALLOCATED_KVP 64
 
 /* Convert a counter index to a tag.  */
 #define GCOV_TAG_FOR_COUNTER(COUNT)                            \
diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr97461.c b/gcc/testsuite/gcc.dg/tree-prof/pr97461.c
new file mode 100644 (file)
index 0000000..8d21a3e
--- /dev/null
@@ -0,0 +1,58 @@
+/* PR gcov-profile/97461 */
+/* { dg-options "-O2 -ldl" } */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int malloc_depth = 0;
+
+static char memory[128* 1024];
+static size_t memory_p = 0;
+
+void f1(void) {}
+void f2(void) {}
+
+typedef void (*fun_t)(void);
+static const fun_t funs[2] = { f1, f2, };
+
+static void * malloc_impl(size_t size) {
+    void * r = &memory[memory_p];
+    memory_p += size;
+
+    // force TOPN profile
+    funs[size % 2]();
+    return r;
+}
+
+// Override default malloc, check it it get s called recursively
+void * malloc(size_t size) {
+    // Must not be called recursively. Malloc implementation does not support it.
+    if (malloc_depth != 0) __builtin_trap();
+
+    ++malloc_depth;
+      void * r = malloc_impl(size);
+    --malloc_depth;
+    return r;
+}
+
+// Called from gcov
+void *calloc(size_t nmemb, size_t size) {
+    // Must not be called recursively.  Malloc implementation does not support it.
+    if (malloc_depth != 0) __builtin_trap();
+
+    ++malloc_depth;
+      void * r = malloc_impl(size * nmemb);
+      memset(r, 0, size * nmemb);
+    --malloc_depth;
+    return r;
+}
+
+void free(void *ptr){}
+
+int main() {
+    void * p = malloc(8);
+    return p != 0 ? 0 : 1;
+}
index 8be5bebcac08a8f5d761eba75b700f1db8b6ced0..e70cf63b414e8d2339399bb5dad6e6e1dd71fae2 100644 (file)
@@ -404,22 +404,16 @@ gcov_counter_add (gcov_type *counter, gcov_type value,
     *counter += value;
 }
 
-/* Allocate gcov_kvp from heap.  If we are recursively called, then allocate
-   it from a list of pre-allocated pool.  */
+/* Allocate gcov_kvp from statically pre-allocated pool,
+   or use heap otherwise.  */
 
 static inline struct gcov_kvp *
 allocate_gcov_kvp (void)
 {
   struct gcov_kvp *new_node = NULL;
 
-  static
-#if defined(HAVE_CC_TLS)
-__thread
-#endif
-  volatile unsigned in_recursion ATTRIBUTE_UNUSED = 0;
-
 #if !defined(IN_GCOV_TOOL) && !defined(L_gcov_merge_topn)
-  if (__builtin_expect (in_recursion, 0))
+  if (__gcov_kvp_pool_index < GCOV_PREALLOCATED_KVP)
     {
       unsigned index;
 #if GCOV_SUPPORTS_ATOMIC
@@ -430,17 +424,11 @@ __thread
 #endif
       if (index < GCOV_PREALLOCATED_KVP)
        new_node = &__gcov_kvp_pool[index];
-      else
-       /* Do not crash in the situation.  */
-       return NULL;
     }
-  else
 #endif
-    {
-      in_recursion = 1;
-      new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
-      in_recursion = 0;
-    }
+
+  if (new_node == NULL)
+    new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
 
   return new_node;
 }