1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/devtools/vprof/vprof.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,275 @@ 1.4 +/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// 1.10 +// Here are a few examples of using the value-profiling utility: 1.11 +// 1.12 +// _vprof (e); 1.13 +// at the end of program execution, you'll get a dump of the source location of this probe, 1.14 +// its min, max, average, the total sum of all instances of e, and the total number of times this probe was called. 1.15 +// 1.16 +// _vprof (x > 0); 1.17 +// shows how many times and what percentage of the cases x was > 0, 1.18 +// that is the probablitiy that x > 0. 1.19 +// 1.20 +// _vprof (n % 2 == 0); 1.21 +// shows how many times n was an even number 1.22 +// as well as th probablitiy of n being an even number. 1.23 +// 1.24 +// _hprof (n, 4, 1000, 5000, 5001, 10000); 1.25 +// gives you the histogram of n over the given 4 bucket boundaries: 1.26 +// # cases < 1000 1.27 +// # cases >= 1000 and < 5000 1.28 +// # cases >= 5000 and < 5001 1.29 +// # cases >= 5001 and < 10000 1.30 +// # cases >= 10000 1.31 +// 1.32 +// _nvprof ("event name", value); 1.33 +// all instances with the same name are merged 1.34 +// so, you can call _vprof with the same event name at difference places 1.35 +// 1.36 +// _vprof (e, myProbe); 1.37 +// value profile e and call myProbe (void* vprofID) at the profiling point. 1.38 +// inside the probe, the client has the predefined variables: 1.39 +// _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers 1.40 +// _IVAR1, ..., IVAR4 general integer registrs 1.41 +// _I64VAR1, ..., I64VAR4 general integer64 registrs 1.42 +// _DVAR1, ..., _DVAR4 general double registers 1.43 +// _GENPTR a generic pointer that can be used by the client 1.44 +// the number of registers can be changed in vprof.h 1.45 +// 1.46 + 1.47 +#ifndef devtools_vprof_vprof_h 1.48 +#define devtools_vprof_vprof_h 1.49 +// 1.50 +// If the application for which you want to use vprof is threaded, THREADED must be defined as 1, otherwise define it as 0 1.51 +// 1.52 +// If your application is not threaded, define THREAD_SAFE 0, 1.53 +// 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 1.54 +// 1.55 +#define THREADED 0 1.56 +#define THREAD_SAFE 0 1.57 + 1.58 +#include "VMPI.h" 1.59 + 1.60 +// Note, this is not supported in configurations with more than one AvmCore running 1.61 +// in the same process. 1.62 + 1.63 +// portable align macro 1.64 +#if defined(_MSC_VER) 1.65 + #define vprof_align8(t) __declspec(align(8)) t 1.66 +#elif defined(__GNUC__) 1.67 + #define vprof_align8(t) t __attribute__ ((aligned (8))) 1.68 +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 1.69 + #define vprof_align8(t) t __attribute__ ((aligned (8))) 1.70 +#elif defined(VMCFG_SYMBIAN) 1.71 + #define vprof_align8(t) t __attribute__ ((aligned (8))) 1.72 +#endif 1.73 + 1.74 +#ifdef __cplusplus 1.75 +extern "C" { 1.76 +#endif 1.77 + 1.78 +int initValueProfile(void** id, char* file, int line, ...); 1.79 +int profileValue(void* id, int64_t value); 1.80 +int initHistProfile(void** id, char* file, int line, int nbins, ...); 1.81 +int histValue(void* id, int64_t value); 1.82 +uint64_t readTimestampCounter(); 1.83 + 1.84 +#ifdef __cplusplus 1.85 +} 1.86 +#endif 1.87 + 1.88 +//#define DOPROF 1.89 + 1.90 +#ifndef DOPROF 1.91 +#define _nvprof(e,v) 1.92 +#ifndef VMCFG_SYMBIAN 1.93 +#define _vprof(v,...) 1.94 +#define _hprof(v,n,...) 1.95 +#define _nhprof(e,v,n,...) 1.96 +#define _ntprof_begin(e) 1.97 +#define _ntprof_end(e) 1.98 +#define _jvprof_init(id,...) 1.99 +#define _jnvprof_init(id,e,...) 1.100 +#define _jhprof_init(id,n,...) 1.101 +#define _jnhprof_init(id,e,n,...) 1.102 +#define _jvprof(id,v) 1.103 +#define _jhprof(id,v) 1.104 +#endif // ! VMCFG_SYMBIAN 1.105 +#else 1.106 + 1.107 +// Historical/compatibility note: 1.108 +// The macros below were originally written using conditional expressions, not if/else. The original author 1.109 +// said that this was done to allow _vprof and _nvprof to be used in an expression context, but the old code 1.110 +// had already wrapped the macro bodies in { }, so it is not clear how this could have worked. At present, 1.111 +// the profiling macros must appear in a statement context only. 1.112 + 1.113 +#define _vprof(v,...) \ 1.114 +do { \ 1.115 + static void* id = 0; \ 1.116 + if (id == 0) \ 1.117 + initValueProfile(&id, __FILE__, __LINE__, ##__VA_ARGS__, NULL); \ 1.118 + profileValue(id, (int64_t) (v)); \ 1.119 +} while (0) 1.120 + 1.121 +#define _nvprof(e,v) \ 1.122 +do { \ 1.123 + static void* id = 0; \ 1.124 + if (id == 0) \ 1.125 + initValueProfile(&id, (char*) (e), -1, NULL); \ 1.126 + profileValue(id, (int64_t) (v)); \ 1.127 +} while (0) 1.128 + 1.129 +#define _hprof(v,n,...) \ 1.130 +do { \ 1.131 + static void* id = 0; \ 1.132 + if (id == 0) \ 1.133 + initHistProfile(&id, __FILE__, __LINE__, (int) (n), ##__VA_ARGS__); \ 1.134 + histValue(id, (int64_t) (v)); \ 1.135 +} while (0) 1.136 + 1.137 +#define _nhprof(e,v,n,...) \ 1.138 +do { \ 1.139 + static void* id = 0; \ 1.140 + if (id == 0) \ 1.141 + initHistProfile(&id, (char*) (e), -1, (int) (n), ##__VA_ARGS__); \ 1.142 + histValue(id, (int64_t) (v)); \ 1.143 +} while (0) 1.144 + 1.145 +// Profile execution time between _ntprof_begin(e) and _ntprof_end(e). 1.146 +// The tag 'e' must match at the beginning and end of the region to 1.147 +// be timed. Regions may be nested or overlap arbitrarily, as it is 1.148 +// the tag alone that defines the begin/end correspondence. 1.149 + 1.150 +#define _ntprof_begin(e) \ 1.151 +do { \ 1.152 + static void* id = 0; \ 1.153 + if (id == 0) \ 1.154 + initValueProfile(&id, (char*)(e), -1, NULL); \ 1.155 + ((entry_t)id)->i64var[0] = readTimestampCounter(); \ 1.156 +} while (0) 1.157 + 1.158 +// Assume 2.6 Ghz CPU 1.159 +#define TICKS_PER_USEC 2600 1.160 + 1.161 +#define _ntprof_end(e) \ 1.162 +do { \ 1.163 + static void* id = 0; \ 1.164 + uint64_t stop = readTimestampCounter(); \ 1.165 + if (id == 0) \ 1.166 + initValueProfile(&id, (char*)(e), -1, NULL); \ 1.167 + uint64_t start = ((entry_t)id)->i64var[0]; \ 1.168 + uint64_t usecs = (stop - start) / TICKS_PER_USEC; \ 1.169 + profileValue(id, usecs); \ 1.170 +} while (0) 1.171 + 1.172 +// These macros separate the creation of a profile record from its later usage. 1.173 +// They are intended for profiling JIT-generated code. Once created, the JIT can 1.174 +// bind a pointer to the profile record into the generated code, which can then 1.175 +// record profile events during execution. 1.176 + 1.177 +#define _jvprof_init(id,...) \ 1.178 + if (*(id) == 0) \ 1.179 + initValueProfile((id), __FILE__, __LINE__, ##__VA_ARGS__, NULL) 1.180 + 1.181 +#define _jnvprof_init(id,e,...) \ 1.182 + if (*(id) == 0) \ 1.183 + initValueProfile((id), (char*) (e), -1, ##__VA_ARGS__, NULL) 1.184 + 1.185 +#define _jhprof_init(id,n,...) \ 1.186 + if (*(id) == 0) \ 1.187 + initHistProfile((id), __FILE__, __LINE__, (int) (n), ##__VA_ARGS__) 1.188 + 1.189 +#define _jnhprof_init(id,e,n,...) \ 1.190 + if (*(id) == 0) \ 1.191 + initHistProfile((id), (char*) (e), -1, (int) (n), ##__VA_ARGS__) 1.192 + 1.193 +// Calls to the _jvprof and _jhprof macros must be wrapped in a non-inline 1.194 +// function in order to be invoked from JIT-compiled code. 1.195 + 1.196 +#define _jvprof(id,v) \ 1.197 + profileValue((id), (int64_t) (v)) 1.198 + 1.199 +#define _jhprof(id,v) \ 1.200 + histValue((id), (int64_t) (v)) 1.201 + 1.202 +#endif 1.203 + 1.204 +#define NUM_EVARS 4 1.205 + 1.206 +enum { 1.207 + LOCK_IS_FREE = 0, 1.208 + LOCK_IS_TAKEN = 1 1.209 +}; 1.210 + 1.211 +extern 1.212 +#ifdef __cplusplus 1.213 +"C" 1.214 +#endif 1.215 +long _InterlockedCompareExchange ( 1.216 + long volatile * Destination, 1.217 + long Exchange, 1.218 + long Comperand 1.219 +); 1.220 + 1.221 +typedef struct hist hist; 1.222 + 1.223 +typedef struct hist { 1.224 + int nbins; 1.225 + int64_t* lb; 1.226 + int64_t* count; 1.227 +} *hist_t; 1.228 + 1.229 +typedef struct entry entry; 1.230 + 1.231 +typedef struct entry { 1.232 + long lock; 1.233 + char* file; 1.234 + int line; 1.235 + int64_t value; 1.236 + int64_t count; 1.237 + int64_t sum; 1.238 + int64_t min; 1.239 + int64_t max; 1.240 + void (*func)(void*); 1.241 + hist* h; 1.242 + 1.243 + entry* next; 1.244 + 1.245 + // exposed to the clients 1.246 + void* genptr; 1.247 + int ivar[NUM_EVARS]; 1.248 + vprof_align8(int64_t) i64var[NUM_EVARS]; 1.249 + vprof_align8(double) dvar[NUM_EVARS]; 1.250 + // 1.251 + 1.252 + char pad[128]; // avoid false sharing 1.253 +} *entry_t; 1.254 + 1.255 +#define _VAL ((entry_t)vprofID)->value 1.256 +#define _COUNT ((entry_t)vprofID)->count 1.257 +#define _SUM ((entry_t)vprofID)->sum 1.258 +#define _MIN ((entry_t)vprofID)->min 1.259 +#define _MAX ((entry_t)vprofID)->max 1.260 + 1.261 +#define _GENPTR ((entry_t)vprofID)->genptr 1.262 + 1.263 +#define _IVAR0 ((entry_t)vprofID)->ivar[0] 1.264 +#define _IVAR1 ((entry_t)vprofID)->ivar[1] 1.265 +#define _IVAR2 ((entry_t)vprofID)->ivar[2] 1.266 +#define _IVAR3 ((entry_t)vprofID)->ivar[3] 1.267 + 1.268 +#define _I64VAR0 ((entry_t)vprofID)->i64var[0] 1.269 +#define _I64VAR1 ((entry_t)vprofID)->i64var[1] 1.270 +#define _I64VAR2 ((entry_t)vprofID)->i64var[2] 1.271 +#define _I64VAR3 ((entry_t)vprofID)->i64var[3] 1.272 + 1.273 +#define _DVAR0 ((entry_t)vprofID)->dvar[0] 1.274 +#define _DVAR1 ((entry_t)vprofID)->dvar[1] 1.275 +#define _DVAR2 ((entry_t)vprofID)->dvar[2] 1.276 +#define _DVAR3 ((entry_t)vprofID)->dvar[3] 1.277 + 1.278 +#endif /* devtools_vprof_vprof_h */