Skip to content
  • fpizlo@apple.com's avatar
    JSC should be able to report profiling data associated with the IR dumps and disassembly · 4a81fa41
    fpizlo@apple.com authored
    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.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@136601 268f45cc-cd09-0410-ab3c-d52691b4dbfc
    4a81fa41