Ignore:
Timestamp:
Dec 4, 2012, 5:26:13 PM (13 years ago)
Author:
[email protected]
Message:

JSC should be able to report profiling data associated with the IR dumps and disassembly
https://bugs.webkit.org/show_bug.cgi?id=102999

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

Added a new profiler to JSC. It's simply called "Profiler" in anticipation of it
ultimately replacing the previous profiling infrastructure. This profiler counts the
number of times that a bytecode executes in various engines, and will record both the
counts and all disassembly and bytecode dumps, into a database that can be at any
time turned into either a JS object using any global object or global data of your
choice, or can be turned into a JSON string, or saved to a file.

Currently the only use of this is the new '-p <file>' flag to the jsc command-line.

The profiler is always compiled in and normally incurs no execution time cost, but is
only activated when you create a Profiler::Database and install it in
JSGlobalData::m_perBytecodeProfiler. From that point on, all code blocks will be
compiled along with disassembly and bytecode dumps stored into the Profiler::Database,
and all code blocks will have execution counts, which are also stored in the database.
The database will continue to keep information about code blocks alive even after they
are otherwise GC'd.

This currently still has some glitches, like the fact that it only counts executions
in the JITs. Doing execution counting in the LLInt might require a bit of a rethink
about how the counting is expressed - currently it is implicit in bytecode, so there
is no easy way to "turn it on" in the LLInt. Also, right now there is no information
recorded about OSR exits or out-of-line stubs. But, even so, it's quite cool, and
gives you a peek into what JSC is doing that would otherwise not be possible.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Target.pri:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::~CodeBlock):

  • bytecode/CodeBlock.h:

(CodeBlock):
(JSC::CodeBlock::baselineVersion):

  • bytecode/CodeOrigin.cpp:

(JSC::InlineCallFrame::baselineCodeBlock):
(JSC):

  • bytecode/CodeOrigin.h:

(InlineCallFrame):

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::execute):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGDisassembler.cpp:

(JSC::DFG::Disassembler::dump):
(DFG):
(JSC::DFG::Disassembler::reportToProfiler):
(JSC::DFG::Disassembler::dumpHeader):
(JSC::DFG::Disassembler::append):
(JSC::DFG::Disassembler::createDumpList):

  • dfg/DFGDisassembler.h:

(Disassembler):
(JSC::DFG::Disassembler::DumpedOp::DumpedOp):
(DumpedOp):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::Graph):
(JSC::DFG::Graph::dumpCodeOrigin):
(JSC::DFG::Graph::dump):

  • dfg/DFGGraph.h:

(Graph):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::JITCompiler):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):

  • dfg/DFGNode.h:

(Node):
(JSC::DFG::Node::hasExecutionCounter):
(JSC::DFG::Node::executionCounter):

  • dfg/DFGNodeType.h:

(DFG):

  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • jit/JIT.cpp:

(JSC::JIT::JIT):
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompile):

  • jit/JIT.h:

(JIT):

  • jit/JITDisassembler.cpp:

(JSC::JITDisassembler::dump):
(JSC::JITDisassembler::reportToProfiler):
(JSC):
(JSC::JITDisassembler::dumpHeader):
(JSC::JITDisassembler::firstSlowLabel):
(JSC::JITDisassembler::dumpVectorForInstructions):
(JSC::JITDisassembler::dumpForInstructions):
(JSC::JITDisassembler::reportInstructions):

  • jit/JITDisassembler.h:

(JITDisassembler):
(DumpedOp):

  • jsc.cpp:

(CommandLine::CommandLine):
(CommandLine):
(printUsageStatement):
(CommandLine::parseArguments):
(jscmain):

  • profiler/ProfilerBytecode.cpp: Added.

(Profiler):
(JSC::Profiler::Bytecode::toJS):

  • profiler/ProfilerBytecode.h: Added.

(Profiler):
(Bytecode):
(JSC::Profiler::Bytecode::Bytecode):
(JSC::Profiler::Bytecode::bytecodeIndex):
(JSC::Profiler::Bytecode::description):
(JSC::Profiler::getBytecodeIndexForBytecode):

  • profiler/ProfilerBytecodes.cpp: Added.

(Profiler):
(JSC::Profiler::Bytecodes::Bytecodes):
(JSC::Profiler::Bytecodes::~Bytecodes):
(JSC::Profiler::Bytecodes::indexForBytecodeIndex):
(JSC::Profiler::Bytecodes::forBytecodeIndex):
(JSC::Profiler::Bytecodes::dump):
(JSC::Profiler::Bytecodes::toJS):

  • profiler/ProfilerBytecodes.h: Added.

(Profiler):
(Bytecodes):
(JSC::Profiler::Bytecodes::append):
(JSC::Profiler::Bytecodes::id):
(JSC::Profiler::Bytecodes::hash):
(JSC::Profiler::Bytecodes::size):
(JSC::Profiler::Bytecodes::at):

  • profiler/ProfilerCompilation.cpp: Added.

(Profiler):
(JSC::Profiler::Compilation::Compilation):
(JSC::Profiler::Compilation::~Compilation):
(JSC::Profiler::Compilation::addDescription):
(JSC::Profiler::Compilation::executionCounterFor):
(JSC::Profiler::Compilation::toJS):

  • profiler/ProfilerCompilation.h: Added.

(Profiler):
(Compilation):
(JSC::Profiler::Compilation::bytecodes):
(JSC::Profiler::Compilation::kind):

  • profiler/ProfilerCompilationKind.cpp: Added.

(WTF):
(WTF::printInternal):

  • profiler/ProfilerCompilationKind.h: Added.

(Profiler):
(WTF):

  • profiler/ProfilerCompiledBytecode.cpp: Added.

(Profiler):
(JSC::Profiler::CompiledBytecode::CompiledBytecode):
(JSC::Profiler::CompiledBytecode::~CompiledBytecode):
(JSC::Profiler::CompiledBytecode::toJS):

  • profiler/ProfilerCompiledBytecode.h: Added.

(Profiler):
(CompiledBytecode):
(JSC::Profiler::CompiledBytecode::originStack):
(JSC::Profiler::CompiledBytecode::description):

  • profiler/ProfilerDatabase.cpp: Added.

(Profiler):
(JSC::Profiler::Database::Database):
(JSC::Profiler::Database::~Database):
(JSC::Profiler::Database::addBytecodes):
(JSC::Profiler::Database::ensureBytecodesFor):
(JSC::Profiler::Database::notifyDestruction):
(JSC::Profiler::Database::newCompilation):
(JSC::Profiler::Database::toJS):
(JSC::Profiler::Database::toJSON):
(JSC::Profiler::Database::save):

  • profiler/ProfilerDatabase.h: Added.

(Profiler):
(Database):

  • profiler/ProfilerExecutionCounter.h: Added.

(Profiler):
(ExecutionCounter):
(JSC::Profiler::ExecutionCounter::ExecutionCounter):
(JSC::Profiler::ExecutionCounter::address):
(JSC::Profiler::ExecutionCounter::count):

  • profiler/ProfilerOrigin.cpp: Added.

(Profiler):
(JSC::Profiler::Origin::Origin):
(JSC::Profiler::Origin::dump):
(JSC::Profiler::Origin::toJS):

  • profiler/ProfilerOrigin.h: Added.

(JSC):
(Profiler):
(Origin):
(JSC::Profiler::Origin::Origin):
(JSC::Profiler::Origin::operator!):
(JSC::Profiler::Origin::bytecodes):
(JSC::Profiler::Origin::bytecodeIndex):
(JSC::Profiler::Origin::operator!=):
(JSC::Profiler::Origin::operator==):
(JSC::Profiler::Origin::hash):
(JSC::Profiler::Origin::isHashTableDeletedValue):
(JSC::Profiler::OriginHash::hash):
(JSC::Profiler::OriginHash::equal):
(OriginHash):
(WTF):

  • profiler/ProfilerOriginStack.cpp: Added.

(Profiler):
(JSC::Profiler::OriginStack::OriginStack):
(JSC::Profiler::OriginStack::~OriginStack):
(JSC::Profiler::OriginStack::append):
(JSC::Profiler::OriginStack::operator==):
(JSC::Profiler::OriginStack::hash):
(JSC::Profiler::OriginStack::dump):
(JSC::Profiler::OriginStack::toJS):

  • profiler/ProfilerOriginStack.h: Added.

(JSC):
(Profiler):
(OriginStack):
(JSC::Profiler::OriginStack::OriginStack):
(JSC::Profiler::OriginStack::operator!):
(JSC::Profiler::OriginStack::size):
(JSC::Profiler::OriginStack::fromBottom):
(JSC::Profiler::OriginStack::fromTop):
(JSC::Profiler::OriginStack::isHashTableDeletedValue):
(JSC::Profiler::OriginStackHash::hash):
(JSC::Profiler::OriginStackHash::equal):
(OriginStackHash):
(WTF):

  • runtime/CommonIdentifiers.h:
  • runtime/ExecutionHarness.h:

(JSC::prepareForExecution):
(JSC::prepareFunctionForExecution):

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):

  • runtime/JSGlobalData.h:

(JSGlobalData):

  • runtime/Options.h:

(JSC):

Source/WTF:

Made some minor changes to support the new profiler. FileOutputStream now has an
open() method, and DataLog uses it. StringPrintStream has a reset() method, which
allows you to reuse the same StringPrintStream for creating multiple strings.
SegmentedVector now has a const operator[]. And, WTFString now can do fromUTF8() on
a CString directly.

  • wtf/DataLog.cpp:

(WTF::initializeLogFileOnce):

  • wtf/FilePrintStream.cpp:

(WTF::FilePrintStream::open):
(WTF):

  • wtf/FilePrintStream.h:
  • wtf/SegmentedVector.h:

(WTF::SegmentedVector::at):
(SegmentedVector):
(WTF::SegmentedVector::operator[]):

  • wtf/StringPrintStream.cpp:

(WTF::StringPrintStream::reset):
(WTF):

  • wtf/StringPrintStream.h:

(StringPrintStream):

  • wtf/text/WTFString.cpp:

(WTF::String::fromUTF8):
(WTF):

  • wtf/text/WTFString.h:

(String):

Tools:

Added a tool that allows you to grok the output from JSC's new profiler. Currently,
this still gets confused a bit about the execution counts of a method running
standalone versus a method running inlined, but other than that, it's pretty cool.
See the attached "sampling profiling session" attached to the bug to see it in
action.

Also had to feed EFL's build system.

  • DumpRenderTree/efl/CMakeLists.txt:
  • Scripts/display-profiler-output: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGDisassembler.cpp

    r136276 r136601  
    4343void Disassembler::dump(PrintStream& out, LinkBuffer& linkBuffer)
    4444{
    45     m_graph.m_dominators.computeIfNecessary(m_graph);
     45    Vector<DumpedOp> ops = createDumpList(linkBuffer);
     46    for (unsigned i = 0; i < ops.size(); ++i)
     47        out.print(ops[i].text);
     48}
     49
     50void Disassembler::dump(LinkBuffer& linkBuffer)
     51{
     52    dump(WTF::dataFile(), linkBuffer);
     53}
     54
     55void Disassembler::reportToProfiler(Profiler::Compilation* compilation, LinkBuffer& linkBuffer)
     56{
     57    Vector<DumpedOp> ops = createDumpList(linkBuffer);
    4658   
     59    for (unsigned i = 0; i < ops.size(); ++i) {
     60        Profiler::OriginStack stack;
     61       
     62        if (ops[i].codeOrigin.isSet())
     63            stack = Profiler::OriginStack(*m_graph.m_globalData.m_perBytecodeProfiler, m_graph.m_codeBlock, ops[i].codeOrigin);
     64       
     65        compilation->addDescription(Profiler::CompiledBytecode(stack, ops[i].text));
     66    }
     67}
     68
     69void Disassembler::dumpHeader(PrintStream& out, LinkBuffer& linkBuffer)
     70{
    4771    out.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), ", instruction count = ", m_graph.m_codeBlock->instructionCount(), ":\n");
    4872    out.print("    Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n");
     73}
     74
     75void Disassembler::append(Vector<Disassembler::DumpedOp>& result, StringPrintStream& out, CodeOrigin& previousOrigin)
     76{
     77    result.append(DumpedOp(previousOrigin, out.toCString()));
     78    previousOrigin = CodeOrigin();
     79    out.reset();
     80}
     81
     82Vector<Disassembler::DumpedOp> Disassembler::createDumpList(LinkBuffer& linkBuffer)
     83{
     84    StringPrintStream out;
     85    Vector<DumpedOp> result;
     86   
     87    CodeOrigin previousOrigin = CodeOrigin();
     88    dumpHeader(out, linkBuffer);
     89    append(result, out, previousOrigin);
     90   
     91    m_graph.m_dominators.computeIfNecessary(m_graph);
    4992   
    5093    const char* prefix = "    ";
     
    58101            continue;
    59102        dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_labelForBlockIndex[blockIndex], lastNodeIndex);
     103        append(result, out, previousOrigin);
    60104        m_graph.dumpBlockHeader(out, prefix, blockIndex, Graph::DumpLivePhisOnly);
     105        append(result, out, previousOrigin);
    61106        NodeIndex lastNodeIndexForDisassembly = block->at(0);
    62107        for (size_t i = 0; i < block->size(); ++i) {
     
    77122            }
    78123            dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, currentLabel, lastNodeIndexForDisassembly);
    79             m_graph.dumpCodeOrigin(out, prefix, lastNodeIndex, block->at(i));
     124            append(result, out, previousOrigin);
     125            previousOrigin = m_graph[block->at(i)].codeOrigin;
     126            if (m_graph.dumpCodeOrigin(out, prefix, lastNodeIndex, block->at(i))) {
     127                append(result, out, previousOrigin);
     128                previousOrigin = m_graph[block->at(i)].codeOrigin;
     129            }
    80130            m_graph.dump(out, prefix, block->at(i));
    81131            lastNodeIndex = block->at(i);
     
    84134    }
    85135    dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfMainPath, lastNodeIndex);
     136    append(result, out, previousOrigin);
    86137    out.print(prefix, "(End Of Main Path)\n");
     138    append(result, out, previousOrigin);
    87139    dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfCode, NoNode);
    88 }
    89 
    90 void Disassembler::dump(LinkBuffer& linkBuffer)
    91 {
    92     dump(WTF::dataFile(), linkBuffer);
     140    append(result, out, previousOrigin);
     141   
     142    return result;
    93143}
    94144
Note: See TracChangeset for help on using the changeset viewer.