tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

vprof.h (9666B)


      1 /* -*- Mode: C++; c-basic-offset: 2; 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/. */
      5 
      6 //
      7 //  Here are a few examples of using the value-profiling utility:
      8 //
      9 //  _vprof (e);
     10 //    at the end of program execution, you'll get a dump of the source location
     11 //    of this probe, its min, max, average, the total sum of all instances of e,
     12 //    and the total number of times this probe was called.
     13 //
     14 //  _vprof (x > 0);
     15 //    shows how many times and what percentage of the cases x was > 0,
     16 //    that is the probablitiy that x > 0.
     17 //
     18 // _vprof (n % 2 == 0);
     19 //    shows how many times n was an even number
     20 //    as well as th probablitiy of n being an even number.
     21 //
     22 // _hprof (n, 4, 1000, 5000, 5001, 10000);
     23 //    gives you the histogram of n over the given 4 bucket boundaries:
     24 //        # cases <  1000
     25 //        # cases >= 1000 and < 5000
     26 //        # cases >= 5000 and < 5001
     27 //        # cases >= 5001 and < 10000
     28 //        # cases >= 10000
     29 //
     30 // _nvprof ("event name", value);
     31 //    all instances with the same name are merged
     32 //    so, you can call _vprof with the same event name at difference places
     33 //
     34 // _vprof (e, myProbe);
     35 //    value profile e and call myProbe (void* vprofID) at the profiling point.
     36 //    inside the probe, the client has the predefined variables:
     37 //    _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers
     38 //    _IVAR1, ..., IVAR4      general integer registrs
     39 //    _I64VAR1, ..., I64VAR4  general integer64 registrs
     40 //    _DVAR1, ..., _DVAR4     general double registers
     41 //    _GENPTR a generic pointer that can be used by the client
     42 //    the number of registers can be changed in vprof.h
     43 //
     44 
     45 #ifndef devtools_vprof_vprof_h
     46 #define devtools_vprof_vprof_h
     47 //
     48 // If the application for which you want to use vprof is threaded, THREADED must
     49 // be defined as 1, otherwise define it as 0
     50 //
     51 // If your application is not threaded, define THREAD_SAFE 0,
     52 // otherwise, you have the option of setting THREAD_SAFE to 1 which results in
     53 // exact counts or to 0 which results in a much more efficient but non-exact
     54 // counts
     55 //
     56 #define THREADED 0
     57 #define THREAD_SAFE 0
     58 
     59 #include "VMPI.h"
     60 
     61 // Note, this is not supported in configurations with more than one AvmCore
     62 // running in the same process.
     63 
     64 // portable align macro
     65 #if defined(_MSC_VER)
     66 #  define vprof_align8(t) __declspec(align(8)) t
     67 #elif defined(__GNUC__)
     68 #  define vprof_align8(t) t __attribute__((aligned(8)))
     69 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
     70 #  define vprof_align8(t) t __attribute__((aligned(8)))
     71 #elif defined(VMCFG_SYMBIAN)
     72 #  define vprof_align8(t) t __attribute__((aligned(8)))
     73 #endif
     74 
     75 #ifdef __cplusplus
     76 extern "C" {
     77 #endif
     78 
     79 int initValueProfile(void** id, char* file, int line, ...);
     80 int profileValue(void* id, int64_t value);
     81 int initHistProfile(void** id, char* file, int line, int nbins, ...);
     82 int histValue(void* id, int64_t value);
     83 uint64_t readTimestampCounter();
     84 
     85 #ifdef __cplusplus
     86 }
     87 #endif
     88 
     89 // #define DOPROF
     90 
     91 #ifndef DOPROF
     92 #  define _nvprof(e, v)
     93 #  ifndef VMCFG_SYMBIAN
     94 #    define _vprof(v, ...)
     95 #    define _hprof(v, n, ...)
     96 #    define _nhprof(e, v, n, ...)
     97 #    define _ntprof_begin(e)
     98 #    define _ntprof_end(e)
     99 #    define _jvprof_init(id, ...)
    100 #    define _jnvprof_init(id, e, ...)
    101 #    define _jhprof_init(id, n, ...)
    102 #    define _jnhprof_init(id, e, n, ...)
    103 #    define _jvprof(id, v)
    104 #    define _jhprof(id, v)
    105 #  endif  // ! VMCFG_SYMBIAN
    106 #else
    107 
    108 // Historical/compatibility note:
    109 // The macros below were originally written using conditional expressions, not
    110 // if/else.  The original author said that this was done to allow _vprof and
    111 // _nvprof to be used in an expression context, but the old code had already
    112 // wrapped the macro bodies in { }, so it is not clear how this could have
    113 // worked.  At present, the profiling macros must appear in a statement context
    114 // only.
    115 
    116 #  define _vprof(v, ...)                                                \
    117    do {                                                                \
    118      static void* id = 0;                                              \
    119      if (id == 0)                                                      \
    120        initValueProfile(&id, __FILE__, __LINE__, ##__VA_ARGS__, NULL); \
    121      profileValue(id, (int64_t)(v));                                   \
    122    } while (0)
    123 
    124 #  define _nvprof(e, v)                                         \
    125    do {                                                        \
    126      static void* id = 0;                                      \
    127      if (id == 0) initValueProfile(&id, (char*)(e), -1, NULL); \
    128      profileValue(id, (int64_t)(v));                           \
    129    } while (0)
    130 
    131 #  define _hprof(v, n, ...)                                                \
    132    do {                                                                   \
    133      static void* id = 0;                                                 \
    134      if (id == 0)                                                         \
    135        initHistProfile(&id, __FILE__, __LINE__, (int)(n), ##__VA_ARGS__); \
    136      histValue(id, (int64_t)(v));                                         \
    137    } while (0)
    138 
    139 #  define _nhprof(e, v, n, ...)                                        \
    140    do {                                                               \
    141      static void* id = 0;                                             \
    142      if (id == 0)                                                     \
    143        initHistProfile(&id, (char*)(e), -1, (int)(n), ##__VA_ARGS__); \
    144      histValue(id, (int64_t)(v));                                     \
    145    } while (0)
    146 
    147 // Profile execution time between _ntprof_begin(e) and _ntprof_end(e).
    148 // The tag 'e' must match at the beginning and end of the region to
    149 // be timed.  Regions may be nested or overlap arbitrarily, as it is
    150 // the tag alone that defines the begin/end correspondence.
    151 
    152 #  define _ntprof_begin(e)                                      \
    153    do {                                                        \
    154      static void* id = 0;                                      \
    155      if (id == 0) initValueProfile(&id, (char*)(e), -1, NULL); \
    156      ((entry_t)id)->i64var[0] = readTimestampCounter();        \
    157    } while (0)
    158 
    159 // Assume 2.6 Ghz CPU
    160 #  define TICKS_PER_USEC 2600
    161 
    162 #  define _ntprof_end(e)                                        \
    163    do {                                                        \
    164      static void* id = 0;                                      \
    165      uint64_t stop = readTimestampCounter();                   \
    166      if (id == 0) initValueProfile(&id, (char*)(e), -1, NULL); \
    167      uint64_t start = ((entry_t)id)->i64var[0];                \
    168      uint64_t usecs = (stop - start) / TICKS_PER_USEC;         \
    169      profileValue(id, usecs);                                  \
    170    } while (0)
    171 
    172 // These macros separate the creation of a profile record from its later usage.
    173 // They are intended for profiling JIT-generated code.  Once created, the JIT
    174 // can bind a pointer to the profile record into the generated code, which can
    175 // then record profile events during execution.
    176 
    177 #  define _jvprof_init(id, ...) \
    178    if (*(id) == 0)             \
    179    initValueProfile((id), __FILE__, __LINE__, ##__VA_ARGS__, NULL)
    180 
    181 #  define _jnvprof_init(id, e, ...) \
    182    if (*(id) == 0) initValueProfile((id), (char*)(e), -1, ##__VA_ARGS__, NULL)
    183 
    184 #  define _jhprof_init(id, n, ...) \
    185    if (*(id) == 0)                \
    186    initHistProfile((id), __FILE__, __LINE__, (int)(n), ##__VA_ARGS__)
    187 
    188 #  define _jnhprof_init(id, e, n, ...) \
    189    if (*(id) == 0)                    \
    190    initHistProfile((id), (char*)(e), -1, (int)(n), ##__VA_ARGS__)
    191 
    192 // Calls to the _jvprof and _jhprof macros must be wrapped in a non-inline
    193 // function in order to be invoked from JIT-compiled code.
    194 
    195 #  define _jvprof(id, v) profileValue((id), (int64_t)(v))
    196 
    197 #  define _jhprof(id, v) histValue((id), (int64_t)(v))
    198 
    199 #endif
    200 
    201 #define NUM_EVARS 4
    202 
    203 enum { LOCK_IS_FREE = 0, LOCK_IS_TAKEN = 1 };
    204 
    205 extern
    206 #ifdef __cplusplus
    207    "C"
    208 #endif
    209    long
    210    _InterlockedCompareExchange(long volatile* Destination, long Exchange,
    211                                long Comperand);
    212 
    213 typedef struct hist hist;
    214 
    215 typedef struct hist {
    216  int nbins;
    217  int64_t* lb;
    218  int64_t* count;
    219 }* hist_t;
    220 
    221 typedef struct entry entry;
    222 
    223 typedef struct entry {
    224  long lock;
    225  char* file;
    226  int line;
    227  int64_t value;
    228  int64_t count;
    229  int64_t sum;
    230  int64_t min;
    231  int64_t max;
    232  void (*func)(void*);
    233  hist* h;
    234 
    235  entry* next;
    236 
    237  // exposed to the clients
    238  void* genptr;
    239  int ivar[NUM_EVARS];
    240  vprof_align8(int64_t) i64var[NUM_EVARS];
    241  vprof_align8(double) dvar[NUM_EVARS];
    242  //
    243 
    244  char pad[128];  // avoid false sharing
    245 }* entry_t;
    246 
    247 #define _VAL ((entry_t)vprofID)->value
    248 #define _COUNT ((entry_t)vprofID)->count
    249 #define _SUM ((entry_t)vprofID)->sum
    250 #define _MIN ((entry_t)vprofID)->min
    251 #define _MAX ((entry_t)vprofID)->max
    252 
    253 #define _GENPTR ((entry_t)vprofID)->genptr
    254 
    255 #define _IVAR0 ((entry_t)vprofID)->ivar[0]
    256 #define _IVAR1 ((entry_t)vprofID)->ivar[1]
    257 #define _IVAR2 ((entry_t)vprofID)->ivar[2]
    258 #define _IVAR3 ((entry_t)vprofID)->ivar[3]
    259 
    260 #define _I64VAR0 ((entry_t)vprofID)->i64var[0]
    261 #define _I64VAR1 ((entry_t)vprofID)->i64var[1]
    262 #define _I64VAR2 ((entry_t)vprofID)->i64var[2]
    263 #define _I64VAR3 ((entry_t)vprofID)->i64var[3]
    264 
    265 #define _DVAR0 ((entry_t)vprofID)->dvar[0]
    266 #define _DVAR1 ((entry_t)vprofID)->dvar[1]
    267 #define _DVAR2 ((entry_t)vprofID)->dvar[2]
    268 #define _DVAR3 ((entry_t)vprofID)->dvar[3]
    269 
    270 #endif /* devtools_vprof_vprof_h */