1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/IonSpewer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,434 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifdef DEBUG 1.11 + 1.12 +#include "jit/IonSpewer.h" 1.13 + 1.14 +#include "jsworkers.h" 1.15 + 1.16 +#include "jit/Ion.h" 1.17 + 1.18 +#ifndef ION_SPEW_DIR 1.19 +# if defined(_WIN32) 1.20 +# define ION_SPEW_DIR "" 1.21 +# elif defined(__ANDROID__) 1.22 +# define ION_SPEW_DIR "/data/local/tmp/" 1.23 +# else 1.24 +# define ION_SPEW_DIR "/tmp/" 1.25 +# endif 1.26 +#endif 1.27 + 1.28 +using namespace js; 1.29 +using namespace js::jit; 1.30 + 1.31 +// IonSpewer singleton. 1.32 +static IonSpewer ionspewer; 1.33 + 1.34 +static bool LoggingChecked = false; 1.35 +static uint32_t LoggingBits = 0; 1.36 +static uint32_t filteredOutCompilations = 0; 1.37 + 1.38 +static const char * const ChannelNames[] = 1.39 +{ 1.40 +#define IONSPEW_CHANNEL(name) #name, 1.41 + IONSPEW_CHANNEL_LIST(IONSPEW_CHANNEL) 1.42 +#undef IONSPEW_CHANNEL 1.43 +}; 1.44 + 1.45 +static bool 1.46 +FilterContainsLocation(HandleScript function) 1.47 +{ 1.48 + static const char *filter = getenv("IONFILTER"); 1.49 + 1.50 + // If there is no filter we accept all outputs. 1.51 + if (!filter || !filter[0]) 1.52 + return true; 1.53 + 1.54 + // Disable asm.js output when filter is set. 1.55 + if (!function) 1.56 + return false; 1.57 + 1.58 + const char *filename = function->filename(); 1.59 + const size_t line = function->lineno(); 1.60 + const size_t filelen = strlen(filename); 1.61 + const char *index = strstr(filter, filename); 1.62 + while (index) { 1.63 + if (index == filter || index[-1] == ',') { 1.64 + if (index[filelen] == 0 || index[filelen] == ',') 1.65 + return true; 1.66 + if (index[filelen] == ':' && line != size_t(-1)) { 1.67 + size_t read_line = strtoul(&index[filelen + 1], nullptr, 10); 1.68 + if (read_line == line) 1.69 + return true; 1.70 + } 1.71 + } 1.72 + index = strstr(index + filelen, filename); 1.73 + } 1.74 + return false; 1.75 +} 1.76 + 1.77 +void 1.78 +jit::EnableIonDebugLogging() 1.79 +{ 1.80 + EnableChannel(IonSpew_Logs); 1.81 + ionspewer.init(); 1.82 +} 1.83 + 1.84 +void 1.85 +jit::IonSpewNewFunction(MIRGraph *graph, HandleScript func) 1.86 +{ 1.87 + if (GetIonContext()->runtime->onMainThread()) 1.88 + ionspewer.beginFunction(graph, func); 1.89 +} 1.90 + 1.91 +void 1.92 +jit::IonSpewPass(const char *pass) 1.93 +{ 1.94 + if (GetIonContext()->runtime->onMainThread()) 1.95 + ionspewer.spewPass(pass); 1.96 +} 1.97 + 1.98 +void 1.99 +jit::IonSpewPass(const char *pass, LinearScanAllocator *ra) 1.100 +{ 1.101 + if (GetIonContext()->runtime->onMainThread()) 1.102 + ionspewer.spewPass(pass, ra); 1.103 +} 1.104 + 1.105 +void 1.106 +jit::IonSpewEndFunction() 1.107 +{ 1.108 + if (GetIonContext()->runtime->onMainThread()) 1.109 + ionspewer.endFunction(); 1.110 +} 1.111 + 1.112 + 1.113 +IonSpewer::~IonSpewer() 1.114 +{ 1.115 + if (!inited_) 1.116 + return; 1.117 + 1.118 + c1Spewer.finish(); 1.119 + jsonSpewer.finish(); 1.120 +} 1.121 + 1.122 +bool 1.123 +IonSpewer::init() 1.124 +{ 1.125 + if (inited_) 1.126 + return true; 1.127 + 1.128 + if (!c1Spewer.init(ION_SPEW_DIR "ion.cfg")) 1.129 + return false; 1.130 + if (!jsonSpewer.init(ION_SPEW_DIR "ion.json")) 1.131 + return false; 1.132 + 1.133 + inited_ = true; 1.134 + return true; 1.135 +} 1.136 + 1.137 +bool 1.138 +IonSpewer::isSpewingFunction() const 1.139 +{ 1.140 + return inited_ && graph; 1.141 +} 1.142 + 1.143 +void 1.144 +IonSpewer::beginFunction(MIRGraph *graph, HandleScript function) 1.145 +{ 1.146 + if (!inited_) 1.147 + return; 1.148 + 1.149 + if (!FilterContainsLocation(function)) { 1.150 + JS_ASSERT(!this->graph); 1.151 + // filter out logs during the compilation. 1.152 + filteredOutCompilations++; 1.153 + return; 1.154 + } 1.155 + 1.156 + this->graph = graph; 1.157 + this->function.repoint(function); 1.158 + 1.159 + c1Spewer.beginFunction(graph, function); 1.160 + jsonSpewer.beginFunction(function); 1.161 +} 1.162 + 1.163 +void 1.164 +IonSpewer::spewPass(const char *pass) 1.165 +{ 1.166 + if (!isSpewingFunction()) 1.167 + return; 1.168 + 1.169 + c1Spewer.spewPass(pass); 1.170 + jsonSpewer.beginPass(pass); 1.171 + jsonSpewer.spewMIR(graph); 1.172 + jsonSpewer.spewLIR(graph); 1.173 + jsonSpewer.endPass(); 1.174 +} 1.175 + 1.176 +void 1.177 +IonSpewer::spewPass(const char *pass, LinearScanAllocator *ra) 1.178 +{ 1.179 + if (!isSpewingFunction()) 1.180 + return; 1.181 + 1.182 + c1Spewer.spewPass(pass); 1.183 + c1Spewer.spewIntervals(pass, ra); 1.184 + jsonSpewer.beginPass(pass); 1.185 + jsonSpewer.spewMIR(graph); 1.186 + jsonSpewer.spewLIR(graph); 1.187 + jsonSpewer.spewIntervals(ra); 1.188 + jsonSpewer.endPass(); 1.189 +} 1.190 + 1.191 +void 1.192 +IonSpewer::endFunction() 1.193 +{ 1.194 + if (!isSpewingFunction()) { 1.195 + if (inited_) { 1.196 + JS_ASSERT(filteredOutCompilations != 0); 1.197 + filteredOutCompilations--; 1.198 + } 1.199 + return; 1.200 + } 1.201 + 1.202 + c1Spewer.endFunction(); 1.203 + jsonSpewer.endFunction(); 1.204 + 1.205 + this->graph = nullptr; 1.206 +} 1.207 + 1.208 + 1.209 +FILE *jit::IonSpewFile = nullptr; 1.210 + 1.211 +static bool 1.212 +ContainsFlag(const char *str, const char *flag) 1.213 +{ 1.214 + size_t flaglen = strlen(flag); 1.215 + const char *index = strstr(str, flag); 1.216 + while (index) { 1.217 + if ((index == str || index[-1] == ',') && (index[flaglen] == 0 || index[flaglen] == ',')) 1.218 + return true; 1.219 + index = strstr(index + flaglen, flag); 1.220 + } 1.221 + return false; 1.222 +} 1.223 + 1.224 +void 1.225 +jit::CheckLogging() 1.226 +{ 1.227 + if (LoggingChecked) 1.228 + return; 1.229 + LoggingChecked = true; 1.230 + const char *env = getenv("IONFLAGS"); 1.231 + if (!env) 1.232 + return; 1.233 + if (strstr(env, "help")) { 1.234 + fflush(nullptr); 1.235 + printf( 1.236 + "\n" 1.237 + "usage: IONFLAGS=option,option,option,... where options can be:\n" 1.238 + "\n" 1.239 + " aborts Compilation abort messages\n" 1.240 + " scripts Compiled scripts\n" 1.241 + " mir MIR information\n" 1.242 + " alias Alias analysis\n" 1.243 + " gvn Global Value Numbering\n" 1.244 + " licm Loop invariant code motion\n" 1.245 + " regalloc Register allocation\n" 1.246 + " inline Inlining\n" 1.247 + " snapshots Snapshot information\n" 1.248 + " codegen Native code generation\n" 1.249 + " bailouts Bailouts\n" 1.250 + " caches Inline caches\n" 1.251 + " osi Invalidation\n" 1.252 + " safepoints Safepoints\n" 1.253 + " pools Literal Pools (ARM only for now)\n" 1.254 + " cacheflush Instruction Cache flushes (ARM only for now)\n" 1.255 + " range Range Analysis\n" 1.256 + " logs C1 and JSON visualization logging\n" 1.257 + " trace Generate calls to js::jit::Trace() for effectful instructions\n" 1.258 + " all Everything\n" 1.259 + "\n" 1.260 + " bl-aborts Baseline compiler abort messages\n" 1.261 + " bl-scripts Baseline script-compilation\n" 1.262 + " bl-op Baseline compiler detailed op-specific messages\n" 1.263 + " bl-ic Baseline inline-cache messages\n" 1.264 + " bl-ic-fb Baseline IC fallback stub messages\n" 1.265 + " bl-osr Baseline IC OSR messages\n" 1.266 + " bl-bails Baseline bailouts\n" 1.267 + " bl-dbg-osr Baseline debug mode on stack recompile messages\n" 1.268 + " bl-all All baseline spew\n" 1.269 + "\n" 1.270 + ); 1.271 + exit(0); 1.272 + /*NOTREACHED*/ 1.273 + } 1.274 + if (ContainsFlag(env, "aborts")) 1.275 + EnableChannel(IonSpew_Abort); 1.276 + if (ContainsFlag(env, "alias")) 1.277 + EnableChannel(IonSpew_Alias); 1.278 + if (ContainsFlag(env, "scripts")) 1.279 + EnableChannel(IonSpew_Scripts); 1.280 + if (ContainsFlag(env, "mir")) 1.281 + EnableChannel(IonSpew_MIR); 1.282 + if (ContainsFlag(env, "gvn")) 1.283 + EnableChannel(IonSpew_GVN); 1.284 + if (ContainsFlag(env, "range")) 1.285 + EnableChannel(IonSpew_Range); 1.286 + if (ContainsFlag(env, "licm")) 1.287 + EnableChannel(IonSpew_LICM); 1.288 + if (ContainsFlag(env, "regalloc")) 1.289 + EnableChannel(IonSpew_RegAlloc); 1.290 + if (ContainsFlag(env, "inline")) 1.291 + EnableChannel(IonSpew_Inlining); 1.292 + if (ContainsFlag(env, "snapshots")) 1.293 + EnableChannel(IonSpew_Snapshots); 1.294 + if (ContainsFlag(env, "codegen")) 1.295 + EnableChannel(IonSpew_Codegen); 1.296 + if (ContainsFlag(env, "bailouts")) 1.297 + EnableChannel(IonSpew_Bailouts); 1.298 + if (ContainsFlag(env, "osi")) 1.299 + EnableChannel(IonSpew_Invalidate); 1.300 + if (ContainsFlag(env, "caches")) 1.301 + EnableChannel(IonSpew_InlineCaches); 1.302 + if (ContainsFlag(env, "safepoints")) 1.303 + EnableChannel(IonSpew_Safepoints); 1.304 + if (ContainsFlag(env, "pools")) 1.305 + EnableChannel(IonSpew_Pools); 1.306 + if (ContainsFlag(env, "cacheflush")) 1.307 + EnableChannel(IonSpew_CacheFlush); 1.308 + if (ContainsFlag(env, "logs")) 1.309 + EnableIonDebugLogging(); 1.310 + if (ContainsFlag(env, "trace")) 1.311 + EnableChannel(IonSpew_Trace); 1.312 + if (ContainsFlag(env, "all")) 1.313 + LoggingBits = uint32_t(-1); 1.314 + 1.315 + if (ContainsFlag(env, "bl-aborts")) 1.316 + EnableChannel(IonSpew_BaselineAbort); 1.317 + if (ContainsFlag(env, "bl-scripts")) 1.318 + EnableChannel(IonSpew_BaselineScripts); 1.319 + if (ContainsFlag(env, "bl-op")) 1.320 + EnableChannel(IonSpew_BaselineOp); 1.321 + if (ContainsFlag(env, "bl-ic")) 1.322 + EnableChannel(IonSpew_BaselineIC); 1.323 + if (ContainsFlag(env, "bl-ic-fb")) 1.324 + EnableChannel(IonSpew_BaselineICFallback); 1.325 + if (ContainsFlag(env, "bl-osr")) 1.326 + EnableChannel(IonSpew_BaselineOSR); 1.327 + if (ContainsFlag(env, "bl-bails")) 1.328 + EnableChannel(IonSpew_BaselineBailouts); 1.329 + if (ContainsFlag(env, "bl-dbg-osr")) 1.330 + EnableChannel(IonSpew_BaselineDebugModeOSR); 1.331 + if (ContainsFlag(env, "bl-all")) { 1.332 + EnableChannel(IonSpew_BaselineAbort); 1.333 + EnableChannel(IonSpew_BaselineScripts); 1.334 + EnableChannel(IonSpew_BaselineOp); 1.335 + EnableChannel(IonSpew_BaselineIC); 1.336 + EnableChannel(IonSpew_BaselineICFallback); 1.337 + EnableChannel(IonSpew_BaselineOSR); 1.338 + EnableChannel(IonSpew_BaselineBailouts); 1.339 + EnableChannel(IonSpew_BaselineDebugModeOSR); 1.340 + } 1.341 + 1.342 + IonSpewFile = stderr; 1.343 +} 1.344 + 1.345 +void 1.346 +jit::IonSpewStartVA(IonSpewChannel channel, const char *fmt, va_list ap) 1.347 +{ 1.348 + if (!IonSpewEnabled(channel)) 1.349 + return; 1.350 + 1.351 + IonSpewHeader(channel); 1.352 + vfprintf(stderr, fmt, ap); 1.353 +} 1.354 + 1.355 +void 1.356 +jit::IonSpewContVA(IonSpewChannel channel, const char *fmt, va_list ap) 1.357 +{ 1.358 + if (!IonSpewEnabled(channel)) 1.359 + return; 1.360 + 1.361 + vfprintf(stderr, fmt, ap); 1.362 +} 1.363 + 1.364 +void 1.365 +jit::IonSpewFin(IonSpewChannel channel) 1.366 +{ 1.367 + if (!IonSpewEnabled(channel)) 1.368 + return; 1.369 + 1.370 + fprintf(stderr, "\n"); 1.371 +} 1.372 + 1.373 +void 1.374 +jit::IonSpewVA(IonSpewChannel channel, const char *fmt, va_list ap) 1.375 +{ 1.376 + IonSpewStartVA(channel, fmt, ap); 1.377 + IonSpewFin(channel); 1.378 +} 1.379 + 1.380 +void 1.381 +jit::IonSpew(IonSpewChannel channel, const char *fmt, ...) 1.382 +{ 1.383 + va_list ap; 1.384 + va_start(ap, fmt); 1.385 + IonSpewVA(channel, fmt, ap); 1.386 + va_end(ap); 1.387 +} 1.388 + 1.389 +void 1.390 +jit::IonSpewStart(IonSpewChannel channel, const char *fmt, ...) 1.391 +{ 1.392 + va_list ap; 1.393 + va_start(ap, fmt); 1.394 + IonSpewStartVA(channel, fmt, ap); 1.395 + va_end(ap); 1.396 +} 1.397 +void 1.398 +jit::IonSpewCont(IonSpewChannel channel, const char *fmt, ...) 1.399 +{ 1.400 + va_list ap; 1.401 + va_start(ap, fmt); 1.402 + IonSpewContVA(channel, fmt, ap); 1.403 + va_end(ap); 1.404 +} 1.405 + 1.406 +void 1.407 +jit::IonSpewHeader(IonSpewChannel channel) 1.408 +{ 1.409 + if (!IonSpewEnabled(channel)) 1.410 + return; 1.411 + 1.412 + fprintf(stderr, "[%s] ", ChannelNames[channel]); 1.413 +} 1.414 + 1.415 +bool 1.416 +jit::IonSpewEnabled(IonSpewChannel channel) 1.417 +{ 1.418 + JS_ASSERT(LoggingChecked); 1.419 + return (LoggingBits & (1 << uint32_t(channel))) && !filteredOutCompilations; 1.420 +} 1.421 + 1.422 +void 1.423 +jit::EnableChannel(IonSpewChannel channel) 1.424 +{ 1.425 + JS_ASSERT(LoggingChecked); 1.426 + LoggingBits |= (1 << uint32_t(channel)); 1.427 +} 1.428 + 1.429 +void 1.430 +jit::DisableChannel(IonSpewChannel channel) 1.431 +{ 1.432 + JS_ASSERT(LoggingChecked); 1.433 + LoggingBits &= ~(1 << uint32_t(channel)); 1.434 +} 1.435 + 1.436 +#endif /* DEBUG */ 1.437 +