aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc/libgcov-profiler.c
diff options
context:
space:
mode:
authorYiran Wang <yiran@google.com>2015-06-23 15:33:17 -0700
committerYiran Wang <yiran@google.com>2015-06-29 10:56:28 -0700
commit1d9fec7937f45dde5e04cac966a2d9a12f2fc15a (patch)
tree3fbcd18a379a05fd6d43491a107e1f36bc61b185 /gcc-4.9/libgcc/libgcov-profiler.c
parentf378ebf14df0952eae870c9865bab8326aa8f137 (diff)
downloadtoolchain_gcc-1d9fec7937f45dde5e04cac966a2d9a12f2fc15a.tar.gz
toolchain_gcc-1d9fec7937f45dde5e04cac966a2d9a12f2fc15a.tar.bz2
toolchain_gcc-1d9fec7937f45dde5e04cac966a2d9a12f2fc15a.zip
Synchronize with google/gcc-4_9 to r224707 (from r214835)
Change-Id: I3d6f06fc613c8f8b6a82143dc44b7338483aac5d
Diffstat (limited to 'gcc-4.9/libgcc/libgcov-profiler.c')
-rw-r--r--gcc-4.9/libgcc/libgcov-profiler.c136
1 files changed, 89 insertions, 47 deletions
diff --git a/gcc-4.9/libgcc/libgcov-profiler.c b/gcc-4.9/libgcc/libgcov-profiler.c
index 3057b6157..7552adac8 100644
--- a/gcc-4.9/libgcc/libgcov-profiler.c
+++ b/gcc-4.9/libgcc/libgcov-profiler.c
@@ -221,13 +221,29 @@ __gcov_indirect_call_profiler_atomic_v2 (gcov_type value, void* cur_func)
the descriptors to see if they point to the same function. */
if (cur_func == __gcov_indirect_call_callee
|| (VTABLE_USES_DESCRIPTORS && __gcov_indirect_call_callee
- && *(void **) cur_func == *(void **) __gcov_indirect_call_callee))
+ && *(void **) cur_func == *(void **) __gcov_indirect_call_callee))
__gcov_one_value_profiler_body_atomic (__gcov_indirect_call_counters, value);
}
#endif
+/*
+#if defined(L_gcov_direct_call_profiler) || defined(L_gcov_indirect_call_topn_profiler)
+__attribute__ ((weak)) gcov_unsigned_t __gcov_lipo_sampling_period;
+#endif
+*/
+
+extern gcov_unsigned_t __gcov_lipo_sampling_period;
+
#ifdef L_gcov_indirect_call_topn_profiler
+
+#include "gthr.h"
+
+#ifdef __GTHREAD_MUTEX_INIT
+__thread int in_profiler;
+ATTRIBUTE_HIDDEN __gthread_mutex_t __indir_topn_val_mx = __GTHREAD_MUTEX_INIT;
+#endif
+
/* Tries to keep track the most frequent N values in the counters where
N is specified by parameter TOPN_VAL. To track top N values, 2*N counter
entries are used.
@@ -252,10 +268,18 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value,
/* There are 2*topn_val values tracked, each value takes two slots in the
counter array */
- for ( i = 0; i < (topn_val << 2); i += 2)
+#ifdef __GTHREAD_MUTEX_INIT
+ /* If this is reentry, return. */
+ if (in_profiler == 1)
+ return;
+
+ in_profiler = 1;
+ __gthread_mutex_lock (&__indir_topn_val_mx);
+#endif
+ for (i = 0; i < topn_val << 2; i += 2)
{
entry = &value_array[i];
- if ( entry[0] == value)
+ if (entry[0] == value)
{
entry[1]++ ;
found = 1;
@@ -271,7 +295,13 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value,
}
if (found)
- return;
+ {
+ in_profiler = 0;
+#ifdef __GTHREAD_MUTEX_INIT
+ __gthread_mutex_unlock (&__indir_topn_val_mx);
+#endif
+ return;
+ }
/* lfu_entry is either an empty entry or an entry
with lowest count, which will be evicted. */
@@ -280,56 +310,49 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value,
#define GCOV_ICALL_COUNTER_CLEAR_THRESHOLD 3000
- /* Too many evictions -- time to clear bottom entries to
+ /* Too many evictions -- time to clear bottom entries to
avoid hot values bumping each other out. */
- if ( !have_zero_count
- && ++*num_eviction >= GCOV_ICALL_COUNTER_CLEAR_THRESHOLD)
+ if (!have_zero_count
+ && ++*num_eviction >= GCOV_ICALL_COUNTER_CLEAR_THRESHOLD)
{
unsigned i, j;
- gcov_type *p, minv;
- gcov_type* tmp_cnts
- = (gcov_type *)alloca (topn_val * sizeof(gcov_type));
+ gcov_type **p;
+ gcov_type **tmp_cnts
+ = (gcov_type **)alloca (topn_val * sizeof(gcov_type *));
*num_eviction = 0;
- for ( i = 0; i < topn_val; i++ )
- tmp_cnts[i] = 0;
-
/* Find the largest topn_val values from the group of
- 2*topn_val values and put them into tmp_cnts. */
+ 2*topn_val values and put the addresses into tmp_cnts. */
+ for (i = 0; i < topn_val; i++)
+ tmp_cnts[i] = &value_array[i * 2 + 1];
- for ( i = 0; i < 2 * topn_val; i += 2 )
+ for (i = topn_val * 2; i < topn_val << 2; i += 2)
{
- p = 0;
- for ( j = 0; j < topn_val; j++ )
- {
- if ( !p || tmp_cnts[j] < *p )
- p = &tmp_cnts[j];
- }
- if ( value_array[i + 1] > *p )
- *p = value_array[i + 1];
+ p = &tmp_cnts[0];
+ for (j = 1; j < topn_val; j++)
+ if (*tmp_cnts[j] > **p)
+ p = &tmp_cnts[j];
+ if (value_array[i + 1] < **p)
+ *p = &value_array[i + 1];
}
- minv = tmp_cnts[0];
- for ( j = 1; j < topn_val; j++ )
- {
- if (tmp_cnts[j] < minv)
- minv = tmp_cnts[j];
- }
- /* Zero out low value entries */
- for ( i = 0; i < 2 * topn_val; i += 2 )
+ /* Zero out low value entries. */
+ for (i = 0; i < topn_val; i++)
{
- if (value_array[i + 1] < minv)
- {
- value_array[i] = 0;
- value_array[i + 1] = 0;
- }
+ *tmp_cnts[i] = 0;
+ *(tmp_cnts[i] - 1) = 0;
}
}
+
+#ifdef __GTHREAD_MUTEX_INIT
+ in_profiler = 0;
+ __gthread_mutex_unlock (&__indir_topn_val_mx);
+#endif
}
#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
-__thread
+__thread
#endif
gcov_type *__gcov_indirect_call_topn_counters ATTRIBUTE_HIDDEN;
@@ -338,6 +361,11 @@ __thread
#endif
void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN;
+#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
+__thread
+#endif
+gcov_unsigned_t __gcov_indirect_call_sampling_counter ATTRIBUTE_HIDDEN;
+
#ifdef TARGET_VTABLE_USES_DESCRIPTORS
#define VTABLE_USES_DESCRIPTORS 1
#else
@@ -355,12 +383,16 @@ __gcov_indirect_call_topn_profiler (void *cur_func,
the descriptors to see if they point to the same function. */
if (cur_func == callee_func
|| (VTABLE_USES_DESCRIPTORS && callee_func
- && *(void **) cur_func == *(void **) callee_func))
+ && *(void **) cur_func == *(void **) callee_func))
{
- gcov_type global_id
- = ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident;
- global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id);
- __gcov_topn_value_profiler_body (counter, global_id, GCOV_ICALL_TOPN_VAL);
+ if (++__gcov_indirect_call_sampling_counter >= __gcov_lipo_sampling_period)
+ {
+ __gcov_indirect_call_sampling_counter = 0;
+ gcov_type global_id
+ = ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident;
+ global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id);
+ __gcov_topn_value_profiler_body (counter, global_id, GCOV_ICALL_TOPN_VAL);
+ }
__gcov_indirect_call_topn_callee = 0;
}
}
@@ -376,7 +408,13 @@ gcov_type *__gcov_direct_call_counters ATTRIBUTE_HIDDEN;
__thread
#endif
void *__gcov_direct_call_callee ATTRIBUTE_HIDDEN;
+#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
+__thread
+#endif
+gcov_unsigned_t __gcov_direct_call_sampling_counter ATTRIBUTE_HIDDEN;
+
/* Direct call profiler. */
+
void
__gcov_direct_call_profiler (void *cur_func,
void *cur_module_gcov_info,
@@ -384,11 +422,15 @@ __gcov_direct_call_profiler (void *cur_func,
{
if (cur_func == __gcov_direct_call_callee)
{
- gcov_type global_id
- = ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident;
- global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id);
- __gcov_direct_call_counters[0] = global_id;
- __gcov_direct_call_counters[1]++;
+ if (++__gcov_direct_call_sampling_counter >= __gcov_lipo_sampling_period)
+ {
+ __gcov_direct_call_sampling_counter = 0;
+ gcov_type global_id
+ = ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident;
+ global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id);
+ __gcov_direct_call_counters[0] = global_id;
+ __gcov_direct_call_counters[1]++;
+ }
__gcov_direct_call_callee = 0;
}
}