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