js/src/devtools/vprof/vprof.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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

mercurial