libgcov-profiler.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* Routines required for instrumenting a program. */
  2. /* Compile this one with gcc. */
  3. /* Copyright (C) 1989-2015 Free Software Foundation, Inc.
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU General Public License as published by the Free
  7. Software Foundation; either version 3, or (at your option) any later
  8. version.
  9. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. #include "libgcov.h"
  21. #if !defined(inhibit_libc)
  22. #ifdef L_gcov_interval_profiler
  23. /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
  24. corresponding counter in COUNTERS. If the VALUE is above or below
  25. the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
  26. instead. */
  27. void
  28. __gcov_interval_profiler (gcov_type *counters, gcov_type value,
  29. int start, unsigned steps)
  30. {
  31. gcov_type delta = value - start;
  32. if (delta < 0)
  33. counters[steps + 1]++;
  34. else if (delta >= steps)
  35. counters[steps]++;
  36. else
  37. counters[delta]++;
  38. }
  39. #endif
  40. #ifdef L_gcov_pow2_profiler
  41. /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
  42. COUNTERS[0] is incremented. */
  43. void
  44. __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
  45. {
  46. if (value & (value - 1))
  47. counters[0]++;
  48. else
  49. counters[1]++;
  50. }
  51. #endif
  52. /* Tries to determine the most common value among its inputs. Checks if the
  53. value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
  54. is incremented. If this is not the case and COUNTERS[1] is not zero,
  55. COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
  56. VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
  57. function is called more than 50% of the time with one value, this value
  58. will be in COUNTERS[0] in the end.
  59. In any case, COUNTERS[2] is incremented. */
  60. static inline void
  61. __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
  62. {
  63. if (value == counters[0])
  64. counters[1]++;
  65. else if (counters[1] == 0)
  66. {
  67. counters[1] = 1;
  68. counters[0] = value;
  69. }
  70. else
  71. counters[1]--;
  72. counters[2]++;
  73. }
  74. #ifdef L_gcov_one_value_profiler
  75. void
  76. __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
  77. {
  78. __gcov_one_value_profiler_body (counters, value);
  79. }
  80. #endif
  81. #ifdef L_gcov_indirect_call_topn_profiler
  82. /* Tries to keep track the most frequent N values in the counters where
  83. N is specified by parameter TOPN_VAL. To track top N values, 2*N counter
  84. entries are used.
  85. counter[0] --- the accumative count of the number of times one entry in
  86. in the counters gets evicted/replaced due to limited capacity.
  87. When this value reaches a threshold, the bottom N values are
  88. cleared.
  89. counter[1] through counter[2*N] records the top 2*N values collected so far.
  90. Each value is represented by two entries: count[2*i+1] is the ith value, and
  91. count[2*i+2] is the number of times the value is seen. */
  92. static void
  93. __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value)
  94. {
  95. unsigned i, found = 0, have_zero_count = 0;
  96. gcov_type *entry;
  97. gcov_type *lfu_entry = &counters[1];
  98. gcov_type *value_array = &counters[1];
  99. gcov_type *num_eviction = &counters[0];
  100. gcov_unsigned_t topn_val = GCOV_ICALL_TOPN_VAL;
  101. /* There are 2*topn_val values tracked, each value takes two slots in the
  102. counter array. */
  103. for (i = 0; i < (topn_val << 2); i += 2)
  104. {
  105. entry = &value_array[i];
  106. if (entry[0] == value)
  107. {
  108. entry[1]++ ;
  109. found = 1;
  110. break;
  111. }
  112. else if (entry[1] == 0)
  113. {
  114. lfu_entry = entry;
  115. have_zero_count = 1;
  116. }
  117. else if (entry[1] < lfu_entry[1])
  118. lfu_entry = entry;
  119. }
  120. if (found)
  121. return;
  122. /* lfu_entry is either an empty entry or an entry
  123. with lowest count, which will be evicted. */
  124. lfu_entry[0] = value;
  125. lfu_entry[1] = 1;
  126. #define GCOV_ICALL_COUNTER_CLEAR_THRESHOLD 3000
  127. /* Too many evictions -- time to clear bottom entries to
  128. avoid hot values bumping each other out. */
  129. if (!have_zero_count
  130. && ++*num_eviction >= GCOV_ICALL_COUNTER_CLEAR_THRESHOLD)
  131. {
  132. unsigned i, j;
  133. gcov_type *p, minv;
  134. gcov_type* tmp_cnts
  135. = (gcov_type *)alloca (topn_val * sizeof (gcov_type));
  136. *num_eviction = 0;
  137. for (i = 0; i < topn_val; i++)
  138. tmp_cnts[i] = 0;
  139. /* Find the largest topn_val values from the group of
  140. 2*topn_val values and put them into tmp_cnts. */
  141. for (i = 0; i < 2 * topn_val; i += 2)
  142. {
  143. p = 0;
  144. for (j = 0; j < topn_val; j++)
  145. {
  146. if (!p || tmp_cnts[j] < *p)
  147. p = &tmp_cnts[j];
  148. }
  149. if (value_array[i + 1] > *p)
  150. *p = value_array[i + 1];
  151. }
  152. minv = tmp_cnts[0];
  153. for (j = 1; j < topn_val; j++)
  154. {
  155. if (tmp_cnts[j] < minv)
  156. minv = tmp_cnts[j];
  157. }
  158. /* Zero out low value entries. */
  159. for (i = 0; i < 2 * topn_val; i += 2)
  160. {
  161. if (value_array[i + 1] < minv)
  162. {
  163. value_array[i] = 0;
  164. value_array[i + 1] = 0;
  165. }
  166. }
  167. }
  168. }
  169. /* These two variables are used to actually track caller and callee. Keep
  170. them in TLS memory so races are not common (they are written to often).
  171. The variables are set directly by GCC instrumented code, so declaration
  172. here must match one in tree-profile.c. */
  173. #if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
  174. __thread
  175. #endif
  176. gcov_type *__gcov_indirect_call_topn_counters ATTRIBUTE_HIDDEN;
  177. #if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
  178. __thread
  179. #endif
  180. void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN;
  181. #ifdef TARGET_VTABLE_USES_DESCRIPTORS
  182. #define VTABLE_USES_DESCRIPTORS 1
  183. #else
  184. #define VTABLE_USES_DESCRIPTORS 0
  185. #endif
  186. /* This fucntion is instrumented at function entry to track topn indirect
  187. calls to CUR_FUNC. */
  188. void
  189. __gcov_indirect_call_topn_profiler (gcov_type value, void* cur_func)
  190. {
  191. void *callee_func = __gcov_indirect_call_topn_callee;
  192. /* If the C++ virtual tables contain function descriptors then one
  193. function may have multiple descriptors and we need to dereference
  194. the descriptors to see if they point to the same function. */
  195. if (cur_func == callee_func
  196. || (VTABLE_USES_DESCRIPTORS && callee_func
  197. && *(void **) cur_func == *(void **) callee_func))
  198. __gcov_topn_value_profiler_body (__gcov_indirect_call_topn_counters, value);
  199. }
  200. #endif
  201. #ifdef L_gcov_indirect_call_profiler
  202. /* This function exist only for workaround of binutils bug 14342.
  203. Once this compatibility hack is obsolette, it can be removed. */
  204. /* By default, the C++ compiler will use function addresses in the
  205. vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
  206. tells the compiler to use function descriptors instead. The value
  207. of this macro says how many words wide the descriptor is (normally 2).
  208. It is assumed that the address of a function descriptor may be treated
  209. as a pointer to a function. */
  210. /* Tries to determine the most common value among its inputs. */
  211. void
  212. __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
  213. void* cur_func, void* callee_func)
  214. {
  215. /* If the C++ virtual tables contain function descriptors then one
  216. function may have multiple descriptors and we need to dereference
  217. the descriptors to see if they point to the same function. */
  218. if (cur_func == callee_func
  219. || (__LIBGCC_VTABLE_USES_DESCRIPTORS__ && callee_func
  220. && *(void **) cur_func == *(void **) callee_func))
  221. __gcov_one_value_profiler_body (counter, value);
  222. }
  223. #endif
  224. #ifdef L_gcov_indirect_call_profiler_v2
  225. /* These two variables are used to actually track caller and callee. Keep
  226. them in TLS memory so races are not common (they are written to often).
  227. The variables are set directly by GCC instrumented code, so declaration
  228. here must match one in tree-profile.c */
  229. #if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
  230. __thread
  231. #endif
  232. void * __gcov_indirect_call_callee;
  233. #if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
  234. __thread
  235. #endif
  236. gcov_type * __gcov_indirect_call_counters;
  237. /* By default, the C++ compiler will use function addresses in the
  238. vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
  239. tells the compiler to use function descriptors instead. The value
  240. of this macro says how many words wide the descriptor is (normally 2).
  241. It is assumed that the address of a function descriptor may be treated
  242. as a pointer to a function. */
  243. /* Tries to determine the most common value among its inputs. */
  244. void
  245. __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func)
  246. {
  247. /* If the C++ virtual tables contain function descriptors then one
  248. function may have multiple descriptors and we need to dereference
  249. the descriptors to see if they point to the same function. */
  250. if (cur_func == __gcov_indirect_call_callee
  251. || (__LIBGCC_VTABLE_USES_DESCRIPTORS__ && __gcov_indirect_call_callee
  252. && *(void **) cur_func == *(void **) __gcov_indirect_call_callee))
  253. __gcov_one_value_profiler_body (__gcov_indirect_call_counters, value);
  254. }
  255. #endif
  256. #ifdef L_gcov_time_profiler
  257. /* Counter for first visit of each function. */
  258. static gcov_type function_counter;
  259. /* Sets corresponding COUNTERS if there is no value. */
  260. void
  261. __gcov_time_profiler (gcov_type* counters)
  262. {
  263. if (!counters[0])
  264. counters[0] = ++function_counter;
  265. }
  266. #endif
  267. #ifdef L_gcov_average_profiler
  268. /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
  269. to saturate up. */
  270. void
  271. __gcov_average_profiler (gcov_type *counters, gcov_type value)
  272. {
  273. counters[0] += value;
  274. counters[1] ++;
  275. }
  276. #endif
  277. #ifdef L_gcov_ior_profiler
  278. /* Bitwise-OR VALUE into COUNTER. */
  279. void
  280. __gcov_ior_profiler (gcov_type *counters, gcov_type value)
  281. {
  282. *counters |= value;
  283. }
  284. #endif
  285. #endif /* inhibit_libc */