diff options
author | Robin Burchell <robin.burchell@viroteck.net> | 2015-07-28 12:41:31 +0000 |
---|---|---|
committer | Robin Burchell <robin.burchell@viroteck.net> | 2015-08-21 14:39:30 +0000 |
commit | 45ea8df187d5dbe2776d793752d1eb3bf34b8fb3 (patch) | |
tree | 8a1f51f2e4c620b888b0a895d92b1452c761473d | |
parent | 6328dd2d2743ed540efea89742261f24552d7611 (diff) | |
download | qtdeclarative-45ea8df187d5dbe2776d793752d1eb3bf34b8fb3.tar.gz qtdeclarative-45ea8df187d5dbe2776d793752d1eb3bf34b8fb3.tar.bz2 qtdeclarative-45ea8df187d5dbe2776d793752d1eb3bf34b8fb3.zip |
Implement support for providing information to Linux's perf JIT interface.
For more information on what this is, see:
https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
[ChangeLog][QtQml][Profiling] QtQml can now write additional information so that
perf is able to give function names of JavaScript methods when profiling. To
enable this, set the environment variable QV4_PROFILE_WRITE_PERF_MAP=1 when
running the process in question.
Change-Id: I187c9b0792f40d93c89a986c0edb3c4487095cb7
Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index acead2088..5dfd891b8 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -45,6 +45,7 @@ #include "qv4binop_p.h" #include <QtCore/QBuffer> +#include <QtCore/QCoreApplication> #include <assembler/LinkBuffer.h> #include <WTFStubs.h> @@ -120,6 +121,19 @@ static void printDisassembledOutputWithCalls(QByteArray processedOutput, const Q qDebug("%s", processedOutput.constData()); } +#if defined(Q_OS_LINUX) +static FILE *pmap; + +static void qt_closePmap() +{ + if (pmap) { + fclose(pmap); + pmap = 0; + } +} + +#endif + JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) { Label endOfCode = label(); @@ -167,6 +181,8 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) *codeSize = linkBuffer.offsetOf(endOfCode); + QByteArray name; + JSC::MacroAssemblerCodeRef codeRef; static bool showCode = !qgetenv("QV4_SHOW_ASM").isNull(); @@ -175,7 +191,7 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) buf.open(QIODevice::WriteOnly); WTF::setDataFile(new QIODevicePrintStream(&buf)); - QByteArray name = _function->name->toUtf8(); + name = _function->name->toUtf8(); if (name.isEmpty()) { name = QByteArray::number(quintptr(_function), 16); name.prepend("IR::Function(0x"); @@ -189,6 +205,50 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) codeRef = linkBuffer.finalizeCodeWithoutDisassembly(); } +#if defined(Q_OS_LINUX) + // This implements writing of JIT'd addresses so that perf can find the + // symbol names. + // + // Perf expects the mapping to be in a certain place and have certain + // content, for more information, see: + // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt + static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP"); + static bool profileInitialized = false; + if (doProfile && !profileInitialized) { + profileInitialized = true; + + char pname[PATH_MAX]; + snprintf(pname, PATH_MAX - 1, "/tmp/perf-%lu.map", + (unsigned long)QCoreApplication::applicationPid()); + + pmap = fopen(pname, "w"); + if (!pmap) + qWarning("QV4: Can't write %s, call stacks will not contain JavaScript function names", pname); + + // make sure we clean up nicely + std::atexit(qt_closePmap); + } + + if (pmap) { + // this may have been pre-populated, if QV4_SHOW_ASM was on + if (name.isEmpty()) { + name = _function->name->toUtf8(); + if (name.isEmpty()) { + name = QByteArray::number(quintptr(_function), 16); + name.prepend("IR::Function(0x"); + name.append(")"); + } + } + + fprintf(pmap, "%llx %x %.*s\n", + (long long unsigned int)codeRef.code().executableAddress(), + *codeSize, + name.length(), + name.constData()); + fflush(pmap); + } +#endif + return codeRef; } |