-
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