diff options
Diffstat (limited to 'gcc-4.9/libgcc/libgcov-profiler.c')
-rw-r--r-- | gcc-4.9/libgcc/libgcov-profiler.c | 136 |
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; } } |