js/src/devtools/vprof/vprof.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial