diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-12-11 22:24:18 +0000 |
---|---|---|
committer | <> | 2014-07-24 09:30:59 +0000 |
commit | 59e2936f588aa945e8dcd6c737523c299067e9d0 (patch) | |
tree | 97e74980cc54baa19de5faa11f5a50a0121a48ea /js/src/TraceLogging.cpp | |
download | mozjs24-master.tar.gz |
Imported from /home/lorry/working-area/delta_mozilla_mozjs24/mozjs-24.2.0.tar.bz2.HEADmozjs-24.2.0master
Diffstat (limited to 'js/src/TraceLogging.cpp')
-rw-r--r-- | js/src/TraceLogging.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/js/src/TraceLogging.cpp b/js/src/TraceLogging.cpp new file mode 100644 index 0000000..e82bde2 --- /dev/null +++ b/js/src/TraceLogging.cpp @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "TraceLogging.h" +#include <cstdarg> +#include <cstdio> +#include <cstdlib> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +using namespace js; + +#ifndef TRACE_LOG_DIR +# if defined(_WIN32) +# define TRACE_LOG_DIR "" +# else +# define TRACE_LOG_DIR "/tmp/" +# endif +#endif + +#if defined(__i386__) +static __inline__ uint64_t +js::rdtsc(void) +{ + uint64_t x; + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); + return x; +} +#elif defined(__x86_64__) +static __inline__ uint64_t +js::rdtsc(void) +{ + unsigned hi, lo; + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 ); +} +#elif defined(__powerpc__) +static __inline__ uint64_t +js::rdtsc(void) +{ + uint64_t result=0; + uint32_t upper, lower,tmp; + __asm__ volatile( + "0: \n" + "\tmftbu %0 \n" + "\tmftb %1 \n" + "\tmftbu %2 \n" + "\tcmpw %2,%0 \n" + "\tbne 0b \n" + : "=r"(upper),"=r"(lower),"=r"(tmp) + ); + result = upper; + result = result<<32; + result = result|lower; + + return(result); +} +#endif + +const char* const TraceLogging::type_name[] = { + "start,ion_compile", + "stop,ion_compile", + "start,ion_cannon", + "stop,ion_cannon", + "stop,ion_cannon_bailout", + "start,ion_side_cannon", + "stop,ion_side_cannon", + "stop,ion_side_cannon_bailout", + "start,yarr_jit_execute", + "stop,yarr_jit_execute", + "start,jm_safepoint", + "stop,jm_safepoint", + "start,jm_normal", + "stop,jm_normal", + "start,jm_compile", + "stop,jm_compile", + "start,gc", + "stop,gc", + "start,interpreter", + "stop,interpreter" +}; +TraceLogging* TraceLogging::_defaultLogger = NULL; + +TraceLogging::TraceLogging() + : loggingTime(0), + entries(NULL), + curEntry(0), + numEntries(1000000), + fileno(0), + out(NULL) +{ +} + +TraceLogging::~TraceLogging() +{ + if (out != NULL) { + fclose(out); + out = NULL; + } + + if (entries != NULL) { + flush(); + js_free(entries); + entries = NULL; + } +} + +void +TraceLogging::grow() +{ + Entry* nentries = (Entry*) js_realloc(entries, numEntries*2*sizeof(Entry)); + + // Allocating a bigger array failed. + // Keep using the current storage, but remove all entries by flushing them. + if (nentries == NULL) { + flush(); + return; + } + + entries = nentries; + numEntries *= 2; +} + +void +TraceLogging::log(Type type, const char* file, unsigned int lineno) +{ + uint64_t now = rdtsc(); + + // Create array containing the entries if not existing. + if (entries == NULL) { + entries = (Entry*) js_malloc(numEntries*sizeof(Entry)); + if (entries == NULL) + return; + } + + // Copy the logging information, + // because original could already be freed before writing the log file. + char *copy = NULL; + if (file != NULL) + copy = strdup(file); + + entries[curEntry++] = Entry(now - loggingTime, copy, lineno, type); + + // Increase length when not enough place in the array + if (curEntry >= numEntries) + grow(); + + // Save the time spend logging the information in order to discard this time from the logged time. + // Especially needed when increasing the array or flushing the information. + loggingTime += rdtsc()-now; +} + +void +TraceLogging::log(Type type, JSScript* script) +{ + this->log(type, script->filename, script->lineno); +} + +void +TraceLogging::log(const char* log) +{ + this->log(INFO, log, 0); +} + +void +TraceLogging::log(Type type) +{ + this->log(type, NULL, 0); +} + +void +TraceLogging::flush() +{ + // Open the logging file, when not opened yet. + if (out == NULL) + out = fopen(TRACE_LOG_DIR "tracelogging.log", "w"); + + // Print all log entries into the file + for (unsigned int i = 0; i < curEntry; i++) { + int written; + if (entries[i].type() == INFO) { + written = fprintf(out, "INFO,%s\n", entries[i].file()); + } else { + if (entries[i].file() == NULL) { + written = fprintf(out, "%llu,%s\n", + (unsigned long long)entries[i].tick(), + type_name[entries[i].type()]); + } else { + written = fprintf(out, "%llu,%s,%s:%d\n", + (unsigned long long)entries[i].tick(), + type_name[entries[i].type()], + entries[i].file(), + entries[i].lineno()); + } + } + + // A logging file can only be 2GB of length (fwrite limit). + // When we exceed this limit, the writing will fail. + // In that case try creating a extra file to write the log entries. + if (written < 0) { + fclose(out); + if (fileno >= 9999) + exit(-1); + + char filename[21 + sizeof(TRACE_LOG_DIR)]; + sprintf (filename, TRACE_LOG_DIR "tracelogging-%d.log", ++fileno); + out = fopen(filename, "w"); + i--; // Try to print message again + continue; + } + + if (entries[i].file() != NULL) { + js_free(entries[i].file()); + entries[i].file_ = NULL; + } + } + curEntry = 0; +} + +TraceLogging* +TraceLogging::defaultLogger() +{ + if (_defaultLogger == NULL) { + _defaultLogger = new TraceLogging(); + atexit (releaseDefaultLogger); + } + return _defaultLogger; +} + +void +TraceLogging::releaseDefaultLogger() +{ + if (_defaultLogger != NULL) { + delete _defaultLogger; + _defaultLogger = NULL; + } +} + +/* Helper functions for asm calls */ +void +js::TraceLog(TraceLogging* logger, TraceLogging::Type type, JSScript* script) +{ + logger->log(type, script); +} + +void +js::TraceLog(TraceLogging* logger, const char* log) +{ + logger->log(log); +} + +void +js::TraceLog(TraceLogging* logger, TraceLogging::Type type) +{ + logger->log(type); +} |