summaryrefslogtreecommitdiff
path: root/js/src/TraceLogging.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-12-11 22:24:18 +0000
committer <>2014-07-24 09:30:59 +0000
commit59e2936f588aa945e8dcd6c737523c299067e9d0 (patch)
tree97e74980cc54baa19de5faa11f5a50a0121a48ea /js/src/TraceLogging.cpp
downloadmozjs24-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.cpp260
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);
+}