JSC Sampling Profiler: Come up with a (program counter => CodeOrigin) mapping
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Jan 2016 01:11:05 +0000 (01:11 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Jan 2016 01:11:05 +0000 (01:11 +0000)
commit82195e8bf6c58af34809817be33928201a7dcc33
treeae7a9efbef5f0dad593363829b8b6d83161c7e61
parent7643d2414bd01ead6cfd5b8a16fa56b2ba609d6b
JSC Sampling Profiler: Come up with a (program counter => CodeOrigin) mapping
https://bugs.webkit.org/show_bug.cgi?id=152629

Reviewed by Filip Pizlo.

This patch implements a mapping from PC to CodeOrigin
that lives off of JITed CodeBlocks. We build this mapping
while JITing code, and then we compress it and store
it on the CodeBlock. We only build the mapping if a debugger
has ever been attached to any global object.

CodeBlock consults this mapping when searching for a CodeOrigin
for a given PC, but it also consults other code ranges
off the main path that may own the PC. Specifically, it searches
through inline caches, OSRExits, and LazySlowPaths.

To find PC info for the LLInt, we also save the LLInt pc when
taking a stack trace where the top frame is in LLInt code.

This patch also cleans up code inside the SamplingProfier.
I realized a bug in the SamplingProfiler's implementation.
We used to walk the inline stack while gathering a stack
trace. This is wrong. It's super dangerous to do this because
we might pause the JSC process while it's modifying its
CodeOrigin table. We used to walk the inline stack while
taking a stack trace because doing so could save us from
having to verify a particular stack trace. This patch changes that.
We now have to verify all stack traces taken. This verification step
includes walking the inline stack.

Because we have a PC=>CodeOrigin map, we can now gather more
detailed information about the top-frame we pause. This allows
us to correctly observe inlining. It also allows us to observe
expression-level line/column information for the top frame.
The reason we don't consult this mapping for parent frames is
that all parent frames should set the CallSiteIndex on the call
frame header, which means we can consult that value to get inlining
and expression-level line/column information.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::Label::Label):
(JSC::AbstractMacroAssembler::Label::operator==):
(JSC::AbstractMacroAssembler::Label::isSet):
* assembler/AssemblerBuffer.h:
(JSC::AssemblerLabel::labelAtOffset):
(JSC::AssemblerLabel::operator==):
* b3/B3Generate.cpp:
* b3/B3Origin.h:
(JSC::B3::Origin::data):
(JSC::B3::Origin::operator==):
* b3/B3PCToOriginMap.h: Added.
(JSC::B3::PCToOriginMap::PCToOriginMap):
(JSC::B3::PCToOriginMap::appendItem):
(JSC::B3::PCToOriginMap::ranges):
* b3/B3Procedure.h:
(JSC::B3::Procedure::pcToOriginMap):
(JSC::B3::Procedure::releasePCToOriginMap):
* b3/air/AirGenerate.cpp:
(JSC::B3::Air::generate):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::insertBasicBlockBoundariesForControlFlowProfiler):
(JSC::CodeBlock::setPCToCodeOriginMap):
(JSC::CodeBlock::findPC):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::jitCodeMap):
(JSC::CodeBlock::bytecodeOffset):
* bytecode/CodeOrigin.h:
(JSC::CodeOrigin::operator==):
(JSC::CodeOriginHash::hash):
(JSC::CodeOriginHash::equal):
* bytecode/InlineCallFrame.h:
(JSC::baselineCodeBlockForOriginAndBaselineCodeBlock):
(JSC::CodeOrigin::walkUpInlineStack):
* bytecode/PolymorphicAccess.h:
(JSC::PolymorphicAccess::containsPC):
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::visitWeakReferences):
(JSC::StructureStubInfo::containsPC):
* bytecode/StructureStubInfo.h:
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::hasExpressionInfo):
(JSC::UnlinkedCodeBlock::expressionInfo):
(JSC::UnlinkedCodeBlock::setThisRegister):
* debugger/Debugger.cpp:
(JSC::Debugger::attach):
* dfg/DFGJITCode.cpp:
(JSC::DFG::JITCode::validateReferences):
(JSC::DFG::JITCode::findPC):
* dfg/DFGJITCode.h:
(JSC::DFG::JITCode::commonDataOffset):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::JITCompiler):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded):
(JSC::DFG::JITCompiler::setEndOfMainPath):
(JSC::DFG::JITCompiler::setEndOfCode):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::setStartOfCode):
(JSC::DFG::JITCompiler::setForNode):
(JSC::DFG::JITCompiler::addCallSite):
(JSC::DFG::JITCompiler::pcToCodeOriginMapBuilder):
(JSC::DFG::JITCompiler::setEndOfMainPath): Deleted.
(JSC::DFG::JITCompiler::setEndOfCode): Deleted.
* dfg/DFGSlowPathGenerator.h:
(JSC::DFG::SlowPathGenerator::call):
(JSC::DFG::SlowPathGenerator::origin):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::addSlowPathGenerator):
(JSC::DFG::SpeculativeJIT::runSlowPathGenerators):
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
* dfg/DFGSpeculativeJIT.h:
* ftl/FTLB3Compile.cpp:
(JSC::FTL::compile):
* ftl/FTLJITCode.cpp:
(JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
(JSC::FTL::JITCode::findPC):
* ftl/FTLJITCode.h:
(JSC::FTL::JITCode::b3Code):
* heap/MachineStackMarker.cpp:
(JSC::MachineThreads::Thread::Registers::instructionPointer):
(JSC::MachineThreads::Thread::Registers::llintPC):
(JSC::MachineThreads::Thread::freeRegisters):
* heap/MachineStackMarker.h:
* inspector/agents/InspectorScriptProfilerAgent.cpp:
(Inspector::InspectorScriptProfilerAgent::addEvent):
(Inspector::buildSamples):
(Inspector::InspectorScriptProfilerAgent::trackingComplete):
* jit/JIT.cpp:
(JSC::JIT::JIT):
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JIT.h:
* jit/JITCode.h:
(JSC::JITCode::findPC):
* jit/PCToCodeOriginMap.cpp: Added.
(JSC::PCToCodeOriginMapBuilder::PCToCodeOriginMapBuilder):
(JSC::PCToCodeOriginMapBuilder::appendItem):
(JSC::PCToCodeOriginMap::PCToCodeOriginMap):
(JSC::PCToCodeOriginMap::~PCToCodeOriginMap):
(JSC::PCToCodeOriginMap::memorySize):
(JSC::PCToCodeOriginMap::findPC):
* jit/PCToCodeOriginMap.h: Added.
(JSC::PCToCodeOriginMapBuilder::defaultCodeOrigin):
(JSC::PCToCodeOriginMapBuilder::didBuildMapping):
* jsc.cpp:
(functionSamplingProfilerStackTraces):
* llint/LLIntPCRanges.h:
(JSC::LLInt::isLLIntPC):
* llint/LowLevelInterpreter.asm:
* runtime/Options.h:
* runtime/SamplingProfiler.cpp:
(JSC::reportStats):
(JSC::FrameWalker::FrameWalker):
(JSC::FrameWalker::walk):
(JSC::FrameWalker::resetAtMachineFrame):
(JSC::FrameWalker::isValidFramePointer):
(JSC::SamplingProfiler::SamplingProfiler):
(JSC::SamplingProfiler::~SamplingProfiler):
(JSC::tryGetBytecodeIndex):
(JSC::SamplingProfiler::processUnverifiedStackTraces):
(JSC::SamplingProfiler::visit):
(JSC::SamplingProfiler::noticeVMEntry):
(JSC::SamplingProfiler::clearData):
(JSC::SamplingProfiler::StackFrame::displayName):
(JSC::SamplingProfiler::StackFrame::displayNameForJSONTests):
(JSC::SamplingProfiler::StackFrame::functionStartLine):
(JSC::SamplingProfiler::StackFrame::functionStartColumn):
(JSC::SamplingProfiler::StackFrame::sourceID):
(JSC::SamplingProfiler::StackFrame::url):
(JSC::SamplingProfiler::releaseStackTraces):
(JSC::SamplingProfiler::stackTracesAsJSON):
(WTF::printInternal):
(JSC::SamplingProfiler::StackFrame::startLine): Deleted.
(JSC::SamplingProfiler::StackFrame::startColumn): Deleted.
(JSC::SamplingProfiler::stackTraces): Deleted.
* runtime/SamplingProfiler.h:
(JSC::SamplingProfiler::UnprocessedStackFrame::UnprocessedStackFrame):
(JSC::SamplingProfiler::StackFrame::StackFrame):
(JSC::SamplingProfiler::StackTrace::StackTrace):
(JSC::SamplingProfiler::totalTime):
(JSC::SamplingProfiler::setStopWatch):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
(JSC::VM::setShouldBuildPCToCodeOriginMapping):
(JSC::VM::shouldBuilderPCToCodeOriginMapping):
* tests/stress/sampling-profiler-basic.js:
(platformSupportsSamplingProfiler.top):
(platformSupportsSamplingProfiler.jaz):
(platformSupportsSamplingProfiler.kaz):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@195865 268f45cc-cd09-0410-ab3c-d52691b4dbfc
48 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
Source/JavaScriptCore/assembler/AssemblerBuffer.h
Source/JavaScriptCore/b3/B3Generate.cpp
Source/JavaScriptCore/b3/B3Origin.h
Source/JavaScriptCore/b3/B3PCToOriginMap.h [new file with mode: 0644]
Source/JavaScriptCore/b3/B3Procedure.h
Source/JavaScriptCore/b3/air/AirGenerate.cpp
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/CodeOrigin.h
Source/JavaScriptCore/bytecode/InlineCallFrame.h
Source/JavaScriptCore/bytecode/PolymorphicAccess.h
Source/JavaScriptCore/bytecode/StructureStubInfo.cpp
Source/JavaScriptCore/bytecode/StructureStubInfo.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/debugger/Debugger.cpp
Source/JavaScriptCore/dfg/DFGJITCode.cpp
Source/JavaScriptCore/dfg/DFGJITCode.h
Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.h
Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/ftl/FTLB3Compile.cpp
Source/JavaScriptCore/ftl/FTLJITCode.cpp
Source/JavaScriptCore/ftl/FTLJITCode.h
Source/JavaScriptCore/heap/MachineStackMarker.cpp
Source/JavaScriptCore/heap/MachineStackMarker.h
Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITCode.h
Source/JavaScriptCore/jit/PCToCodeOriginMap.cpp [new file with mode: 0644]
Source/JavaScriptCore/jit/PCToCodeOriginMap.h [new file with mode: 0644]
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/llint/LLIntPCRanges.h
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/runtime/Options.h
Source/JavaScriptCore/runtime/SamplingProfiler.cpp
Source/JavaScriptCore/runtime/SamplingProfiler.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/tests/stress/sampling-profiler-basic.js