Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "VMPI.h"
8 // Note, this is not supported in configurations with more than one AvmCore running
9 // in the same process.
11 #ifdef WIN32
12 #include "windows.h"
13 #else
14 #define __cdecl
15 #include <stdarg.h>
16 #include <string.h>
17 #endif
19 #include "vprof.h"
21 #ifndef MIN
22 #define MIN(x,y) ((x) <= (y) ? x : y)
23 #endif
24 #ifndef MAX
25 #define MAX(x,y) ((x) >= (y) ? x : y)
26 #endif
28 #ifndef MAXINT
29 #define MAXINT int(unsigned(-1)>>1)
30 #endif
32 #ifndef MAXINT64
33 #define MAXINT64 int64_t(uint64_t(-1)>>1)
34 #endif
36 #ifndef __STDC_WANT_SECURE_LIB__
37 #define sprintf_s(b,size,fmt,...) sprintf((b),(fmt),__VA_ARGS__)
38 #endif
40 #if THREADED
41 #define DO_LOCK(lock) Lock(lock); {
42 #define DO_UNLOCK(lock) }; Unlock(lock)
43 #else
44 #define DO_LOCK(lock) { (void)(lock);
45 #define DO_UNLOCK(lock) }
46 #endif
48 #if THREAD_SAFE
49 #define LOCK(lock) DO_LOCK(lock)
50 #define UNLOCK(lock) DO_UNLOCK(lock)
51 #else
52 #define LOCK(lock) { (void)(lock);
53 #define UNLOCK(lock) }
54 #endif
56 static entry* entries = nullptr;
57 static bool notInitialized = true;
58 static long glock = LOCK_IS_FREE;
60 #define Lock(lock) while (_InterlockedCompareExchange(lock, LOCK_IS_TAKEN, LOCK_IS_FREE) == LOCK_IS_TAKEN){};
61 #define Unlock(lock) _InterlockedCompareExchange(lock, LOCK_IS_FREE, LOCK_IS_TAKEN);
63 #if defined(WIN32)
64 static void vprof_printf(const char* format, ...)
65 {
66 va_list args;
67 va_start(args, format);
69 char buf[1024];
70 vsnprintf(buf, sizeof(buf), format, args);
72 va_end(args);
74 printf(buf);
75 ::OutputDebugStringA(buf);
76 }
77 #else
78 #define vprof_printf printf
79 #endif
81 static inline entry* reverse (entry* s)
82 {
83 entry_t e, n, p;
85 p = nullptr;
86 for (e = s; e; e = n) {
87 n = e->next;
88 e->next = p;
89 p = e;
90 }
92 return p;
93 }
95 static char* f (double d)
96 {
97 static char s[80];
98 char* p;
99 sprintf_s (s, sizeof(s), "%lf", d);
100 p = s+VMPI_strlen(s)-1;
101 while (*p == '0') {
102 *p = '\0';
103 p--;
104 if (p == s) break;
105 }
106 if (*p == '.') *p = '\0';
107 return s;
108 }
110 static void dumpProfile (void)
111 {
112 entry_t e;
114 entries = reverse(entries);
115 vprof_printf ("event avg [min : max] total count\n");
116 for (e = entries; e; e = e->next) {
117 if (e->count == 0) continue; // ignore entries with zero count.
118 vprof_printf ("%s", e->file);
119 if (e->line >= 0) {
120 vprof_printf (":%d", e->line);
121 }
122 vprof_printf (" %s [%lld : %lld] %lld %lld ",
123 f(((double)e->sum)/((double)e->count)), (long long int)e->min, (long long int)e->max, (long long int)e->sum, (long long int)e->count);
124 if (e->h) {
125 int j = MAXINT;
126 for (j = 0; j < e->h->nbins; j ++) {
127 vprof_printf ("(%lld < %lld) ", (long long int)e->h->count[j], (long long int)e->h->lb[j]);
128 }
129 vprof_printf ("(%lld >= %lld) ", (long long int)e->h->count[e->h->nbins], (long long int)e->h->lb[e->h->nbins-1]);
130 }
131 if (e->func) {
132 int j;
133 for (j = 0; j < NUM_EVARS; j++) {
134 if (e->ivar[j] != 0) {
135 vprof_printf ("IVAR%d %d ", j, e->ivar[j]);
136 }
137 }
138 for (j = 0; j < NUM_EVARS; j++) {
139 if (e->i64var[j] != 0) {
140 vprof_printf ("I64VAR%d %lld ", j, (long long int)e->i64var[j]);
141 }
142 }
143 for (j = 0; j < NUM_EVARS; j++) {
144 if (e->dvar[j] != 0) {
145 vprof_printf ("DVAR%d %lf ", j, e->dvar[j]);
146 }
147 }
148 }
149 vprof_printf ("\n");
150 }
151 entries = reverse(entries);
152 }
154 static inline entry_t findEntry (char* file, int line)
155 {
156 for (entry_t e = entries; e; e = e->next) {
157 if ((e->line == line) && (VMPI_strcmp (e->file, file) == 0)) {
158 return e;
159 }
160 }
161 return nullptr;
162 }
164 // Initialize the location pointed to by 'id' to a new value profile entry
165 // associated with 'file' and 'line', or do nothing if already initialized.
166 // An optional final argument provides a user-defined probe function.
168 int initValueProfile(void** id, char* file, int line, ...)
169 {
170 DO_LOCK (&glock);
171 entry_t e = (entry_t) *id;
172 if (notInitialized) {
173 atexit (dumpProfile);
174 notInitialized = false;
175 }
177 if (e == nullptr) {
178 e = findEntry (file, line);
179 if (e) {
180 *id = e;
181 }
182 }
184 if (e == nullptr) {
185 va_list va;
186 e = (entry_t) malloc (sizeof(entry));
187 e->lock = LOCK_IS_FREE;
188 e->file = file;
189 e->line = line;
190 e->value = 0;
191 e->sum = 0;
192 e->count = 0;
193 e->min = 0;
194 e->max = 0;
195 // optional probe function argument
196 va_start (va, line);
197 e->func = (void (__cdecl*)(void*)) va_arg (va, void*);
198 va_end (va);
199 e->h = nullptr;
200 e->genptr = nullptr;
201 VMPI_memset (&e->ivar, 0, sizeof(e->ivar));
202 VMPI_memset (&e->i64var, 0, sizeof(e->i64var));
203 VMPI_memset (&e->dvar, 0, sizeof(e->dvar));
204 e->next = entries;
205 entries = e;
206 *id = e;
207 }
208 DO_UNLOCK (&glock);
210 return 0;
211 }
213 // Record a value profile event.
215 int profileValue(void* id, int64_t value)
216 {
217 entry_t e = (entry_t) id;
218 long* lock = &(e->lock);
219 LOCK (lock);
220 e->value = value;
221 if (e->count == 0) {
222 e->sum = value;
223 e->count = 1;
224 e->min = value;
225 e->max = value;
226 } else {
227 e->sum += value;
228 e->count ++;
229 e->min = MIN (e->min, value);
230 e->max = MAX (e->max, value);
231 }
232 if (e->func) e->func (e);
233 UNLOCK (lock);
235 return 0;
236 }
238 // Initialize the location pointed to by 'id' to a new histogram profile entry
239 // associated with 'file' and 'line', or do nothing if already initialized.
241 int initHistProfile(void** id, char* file, int line, int nbins, ...)
242 {
243 DO_LOCK (&glock);
244 entry_t e = (entry_t) *id;
245 if (notInitialized) {
246 atexit (dumpProfile);
247 notInitialized = false;
248 }
250 if (e == nullptr) {
251 e = findEntry (file, line);
252 if (e) {
253 *id = e;
254 }
255 }
257 if (e == nullptr) {
258 va_list va;
259 hist_t h;
260 int b, n, s;
261 int64_t* lb;
263 e = (entry_t) malloc (sizeof(entry));
264 e->lock = LOCK_IS_FREE;
265 e->file = file;
266 e->line = line;
267 e->value = 0;
268 e->sum = 0;
269 e->count = 0;
270 e->min = 0;
271 e->max = 0;
272 e->func = nullptr;
273 e->h = h = (hist_t) malloc (sizeof(hist));
274 n = 1+MAX(nbins,0);
275 h->nbins = n-1;
276 s = n*sizeof(int64_t);
277 lb = (int64_t*) malloc (s);
278 h->lb = lb;
279 VMPI_memset (h->lb, 0, s);
280 h->count = (int64_t*) malloc (s);
281 VMPI_memset (h->count, 0, s);
283 va_start (va, nbins);
284 for (b = 0; b < nbins; b++) {
285 //lb[b] = va_arg (va, int64_t);
286 lb[b] = va_arg (va, int);
287 }
288 lb[b] = MAXINT64;
289 va_end (va);
291 e->genptr = nullptr;
292 VMPI_memset (&e->ivar, 0, sizeof(e->ivar));
293 VMPI_memset (&e->i64var, 0, sizeof(e->i64var));
294 VMPI_memset (&e->dvar, 0, sizeof(e->dvar));
295 e->next = entries;
296 entries = e;
297 *id = e;
298 }
299 DO_UNLOCK (&glock);
301 return 0;
302 }
304 // Record a histogram profile event.
306 int histValue(void* id, int64_t value)
307 {
308 entry_t e = (entry_t) id;
309 long* lock = &(e->lock);
310 hist_t h = e->h;
311 int nbins = h->nbins;
312 int64_t* lb = h->lb;
313 int b;
315 LOCK (lock);
316 e->value = value;
317 if (e->count == 0) {
318 e->sum = value;
319 e->count = 1;
320 e->min = value;
321 e->max = value;
322 } else {
323 e->sum += value;
324 e->count ++;
325 e->min = MIN (e->min, value);
326 e->max = MAX (e->max, value);
327 }
328 for (b = 0; b < nbins; b ++) {
329 if (value < lb[b]) break;
330 }
331 h->count[b] ++;
332 UNLOCK (lock);
334 return 0;
335 }
337 #if defined(_MSC_VER) && defined(_M_IX86)
338 uint64_t readTimestampCounter()
339 {
340 // read the cpu cycle counter. 1 tick = 1 cycle on IA32
341 _asm rdtsc;
342 }
343 #elif defined(__GNUC__) && (__i386__ || __x86_64__)
344 uint64_t readTimestampCounter()
345 {
346 uint32_t lo, hi;
347 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
348 return (uint64_t(hi) << 32) | lo;
349 }
350 #else
351 // add stub for platforms without it, so fat builds don't fail
352 uint64_t readTimestampCounter() { return 0; }
353 #endif