<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[195865] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/195865">195865</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-01-29 17:11:05 -0800 (Fri, 29 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSC Sampling Profiler: Come up with a (program counter =&gt; 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=&gt;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):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAssemblerBufferh">trunk/Source/JavaScriptCore/assembler/AssemblerBuffer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Generatecpp">trunk/Source/JavaScriptCore/b3/B3Generate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Originh">trunk/Source/JavaScriptCore/b3/B3Origin.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedureh">trunk/Source/JavaScriptCore/b3/B3Procedure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGeneratecpp">trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeOriginh">trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeInlineCallFrameh">trunk/Source/JavaScriptCore/bytecode/InlineCallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccessh">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfocpp">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfoh">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggercpp">trunk/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCodecpp">trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCodeh">trunk/Source/JavaScriptCore/dfg/DFGJITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilerh">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSlowPathGeneratorh">trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Compilecpp">trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITCodecpp">trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITCodeh">trunk/Source/JavaScriptCore/ftl/FTLJITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMachineStackMarkercpp">trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMachineStackMarkerh">trunk/Source/JavaScriptCore/heap/MachineStackMarker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorScriptProfilerAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCodeh">trunk/Source/JavaScriptCore/jit/JITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntPCRangesh">trunk/Source/JavaScriptCore/llint/LLIntPCRanges.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSamplingProfilercpp">trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSamplingProfilerh">trunk/Source/JavaScriptCore/runtime/SamplingProfiler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssamplingprofilerbasicjs">trunk/Source/JavaScriptCore/tests/stress/sampling-profiler-basic.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3B3PCToOriginMaph">trunk/Source/JavaScriptCore/b3/B3PCToOriginMap.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitPCToCodeOriginMapcpp">trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitPCToCodeOriginMaph">trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -511,6 +511,7 @@
</span><span class="cx">     jit/JITSubGenerator.cpp
</span><span class="cx">     jit/JITThunks.cpp
</span><span class="cx">     jit/JITToDFGDeferredCompilationCallback.cpp
</span><ins>+    jit/PCToCodeOriginMap.cpp
</ins><span class="cx">     jit/PolymorphicCallStubRoutine.cpp
</span><span class="cx">     jit/Reg.cpp
</span><span class="cx">     jit/RegisterAtOffset.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -1,5 +1,205 @@
</span><span class="cx"> 2016-01-29  Saam barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        JSC Sampling Profiler: Come up with a (program counter =&gt; 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=&gt;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):
+
+2016-01-29  Saam barati  &lt;sbarati@apple.com&gt;
+
</ins><span class="cx">         Remove our notion of having a single activation register
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=153673
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -670,6 +670,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\jit\JITThunks.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\jit\JITToDFGDeferredCompilationCallback.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\jit\SetupVarargsFrame.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\jit\PCToCodeOriginMap.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\jit\PolymorphicCallStubRoutine.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\jit\Reg.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\jit\RegisterAtOffset.cpp&quot; /&gt;
</span><span class="lines">@@ -1502,7 +1503,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\JITToDFGDeferredCompilationCallback.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\JITWriteBarrier.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\JSInterfaceJIT.h&quot; /&gt;
</span><del>-    &lt;ClInclude Include=&quot;..\jit\SetupVarargsFrame.h&quot; /&gt;
</del><ins>+    &lt;ClInclude Include=&quot;..\jit\PCToCodeOriginMap.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\jit\PolymorphicCallStubRoutine.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\Reg.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\RegisterAtOffset.h&quot; /&gt;
</span><span class="lines">@@ -1511,6 +1512,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\RegisterSet.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\Repatch.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\ScratchRegisterAllocator.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\jit\SetupVarargsFrame.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\jit\SnippetOperand.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\SpecializedThunkJIT.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\jit\TempRegisterSet.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -1911,6 +1911,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\jit\BinarySwitch.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;jit&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\jit\PCToCodeOriginMap.cpp&quot;&gt;
+      &lt;Filter&gt;jit&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\jit\PolymorphicCallStubRoutine.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;jit&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="lines">@@ -4596,6 +4599,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPreciseLocalClobberize.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\jit\PCToCodeOriginMap.h&quot;&gt;
+      &lt;Filter&gt;jit&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\jit\PolymorphicCallStubRoutine.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;jit&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -1305,9 +1305,12 @@
</span><span class="cx">                 70ECA6071AFDBEA200449739 /* TemplateRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */; };
</span><span class="cx">                 70ECA6081AFDBEA200449739 /* TemplateRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6031AFDBEA200449739 /* TemplateRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 70ECA6091AFDBEA200449739 /* TemplateRegistryKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                792CB3491C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */; };
+                792CB34A1C4EED5C00D13AF3 /* PCToCodeOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 796465681B952FF0003059EE /* GetPutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */; };
</span><span class="cx">                 797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 79C4B15D1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */; };
</span><span class="cx">                 79C4B15E1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */ = {isa = PBXBuildFile; fileRef = 79CFC6EF1C33B10000C768EA /* LLIntPCRanges.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -3502,9 +3505,12 @@
</span><span class="cx">                 70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateRegistry.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 70ECA6031AFDBEA200449739 /* TemplateRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistry.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistryKey.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCToCodeOriginMap.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCToCodeOriginMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 796465681B952FF0003059EE /* GetPutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetPutInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalLexicalEnvironment.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalLexicalEnvironment.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PCToOriginMap.h; path = b3/B3PCToOriginMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLiveCatchVariablePreservationPhase.cpp; path = dfg/DFGLiveCatchVariablePreservationPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLiveCatchVariablePreservationPhase.h; path = dfg/DFGLiveCatchVariablePreservationPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79CFC6EF1C33B10000C768EA /* LLIntPCRanges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntPCRanges.h; path = llint/LLIntPCRanges.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4844,6 +4850,7 @@
</span><span class="cx">                                 0FEC84DC1BDACDAC0080FF74 /* B3PatchpointSpecial.h */,
</span><span class="cx">                                 0FEC84DD1BDACDAC0080FF74 /* B3PatchpointValue.cpp */,
</span><span class="cx">                                 0FEC84DE1BDACDAC0080FF74 /* B3PatchpointValue.h */,
</span><ins>+                                799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */,
</ins><span class="cx">                                 0FEC84DF1BDACDAC0080FF74 /* B3PhaseScope.cpp */,
</span><span class="cx">                                 0FEC84E01BDACDAC0080FF74 /* B3PhaseScope.h */,
</span><span class="cx">                                 0F37308A1C0BD29100052BFA /* B3PhiChildren.cpp */,
</span><span class="lines">@@ -5155,6 +5162,8 @@
</span><span class="cx">                                 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */,
</span><span class="cx">                                 A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */,
</span><span class="cx">                                 A76C51741182748D00715B05 /* JSInterfaceJIT.h */,
</span><ins>+                                792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */,
+                                792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */,
</ins><span class="cx">                                 0FE834151A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp */,
</span><span class="cx">                                 0FE834161A6EF97B00D04847 /* PolymorphicCallStubRoutine.h */,
</span><span class="cx">                                 0FA7A8E918B413C80052371D /* Reg.cpp */,
</span><span class="lines">@@ -7031,6 +7040,8 @@
</span><span class="cx">                                 0FEC85761BDACDC70080FF74 /* AirCode.h in Headers */,
</span><span class="cx">                                 0F3730931C0D67EE00052BFA /* AirUseCounts.h in Headers */,
</span><span class="cx">                                 0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */,
</span><ins>+                                799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */,
+                                792CB34A1C4EED5C00D13AF3 /* PCToCodeOriginMap.h in Headers */,
</ins><span class="cx">                                 79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */,
</span><span class="cx">                                 79D5CD5B1C1106A900CECA07 /* SamplingProfiler.h in Headers */,
</span><span class="cx">                                 0F6183311C45BF070072450B /* AirLowerMacros.h in Headers */,
</span><span class="lines">@@ -8978,6 +8989,7 @@
</span><span class="cx">                                 0F8F14351ADF090100ED792C /* DFGMovHintRemovalPhase.cpp in Sources */,
</span><span class="cx">                                 0FF2CD5B1B61A4F8004955A8 /* DFGMultiGetByOffsetData.cpp in Sources */,
</span><span class="cx">                                 A737810D1799EA2E00817533 /* DFGNaturalLoops.cpp in Sources */,
</span><ins>+                                792CB3491C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp in Sources */,
</ins><span class="cx">                                 0FF0F19C16B72A03005DF95B /* DFGNode.cpp in Sources */,
</span><span class="cx">                                 0FB3878F1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.cpp in Sources */,
</span><span class="cx">                                 0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -396,6 +396,8 @@
</span><span class="cx">             masm-&gt;invalidateAllTempRegisters();
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        bool operator==(const Label&amp; other) const { return m_label == other.m_label; }
+
</ins><span class="cx">         bool isSet() const { return m_label.isSet(); }
</span><span class="cx">     private:
</span><span class="cx">         AssemblerLabel m_label;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAssemblerBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AssemblerBuffer.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AssemblerBuffer.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/assembler/AssemblerBuffer.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -56,6 +56,8 @@
</span><span class="cx">             return AssemblerLabel(m_offset + offset);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        bool operator==(const AssemblerLabel&amp; other) const { return m_offset == other.m_offset; }
+
</ins><span class="cx">         uint32_t m_offset;
</span><span class="cx">     };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Generatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Generate.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> #include &quot;B3ReduceStrength.h&quot;
</span><span class="cx"> #include &quot;B3TimingScope.h&quot;
</span><span class="cx"> #include &quot;B3Validate.h&quot;
</span><ins>+#include &quot;PCToCodeOriginMap.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Originh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Origin.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Origin.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/b3/B3Origin.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -47,6 +47,8 @@
</span><span class="cx"> 
</span><span class="cx">     const void* data() const { return m_data; }
</span><span class="cx"> 
</span><ins>+    bool operator==(const Origin&amp; other) const { return m_data == other.m_data; }
+
</ins><span class="cx">     // You should avoid using this. Use OriginDump instead.
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3PCToOriginMaph"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3PCToOriginMap.h (0 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3PCToOriginMap.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3PCToOriginMap.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef B3PCToOriginMap_h
+#define B3PCToOriginMap_h
+
+#if ENABLE(B3_JIT)
+
+#include &quot;B3Origin.h&quot;
+#include &quot;MacroAssembler.h&quot;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC { namespace B3 {
+
+class PCToOriginMap {
+    WTF_MAKE_NONCOPYABLE(PCToOriginMap);
+public:
+    PCToOriginMap()
+    { }
+
+    PCToOriginMap(PCToOriginMap&amp;&amp; other)
+        : m_ranges(WTFMove(other.m_ranges))
+    { }
+
+    struct OriginRange {
+        MacroAssembler::Label label;
+        Origin origin;
+    };
+
+    void appendItem(MacroAssembler::Label label, Origin origin)
+    {
+        if (m_ranges.size()) {
+            if (m_ranges.last().label == label)
+                return;
+        }
+
+        m_ranges.append(OriginRange{label, origin});
+    }
+
+    const Vector&lt;OriginRange&gt;&amp; ranges() const  { return m_ranges; }
+
+private:
+    Vector&lt;OriginRange&gt; m_ranges;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3PCToOriginMap_h
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3OpaqueByproducts.h&quot;
</span><span class="cx"> #include &quot;B3Origin.h&quot;
</span><ins>+#include &quot;B3PCToOriginMap.h&quot;
</ins><span class="cx"> #include &quot;B3StackSlotKind.h&quot;
</span><span class="cx"> #include &quot;B3Type.h&quot;
</span><span class="cx"> #include &quot;B3ValueKey.h&quot;
</span><span class="lines">@@ -361,6 +362,9 @@
</span><span class="cx">     JS_EXPORT_PRIVATE unsigned frameSize() const;
</span><span class="cx">     const RegisterAtOffsetList&amp; calleeSaveRegisters() const;
</span><span class="cx"> 
</span><ins>+    PCToOriginMap&amp; pcToOriginMap() { return m_pcToOriginMap; }
+    PCToOriginMap releasePCToOriginMap() { return WTFMove(m_pcToOriginMap); }
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class BlockInsertionSet;
</span><span class="cx">     
</span><span class="lines">@@ -383,6 +387,7 @@
</span><span class="cx">     RefPtr&lt;SharedTask&lt;void(PrintStream&amp;, Origin)&gt;&gt; m_originPrinter;
</span><span class="cx">     const void* m_frontendData;
</span><span class="cx">     ValuesCollection m_valuesCollection;
</span><ins>+    PCToOriginMap m_pcToOriginMap;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGeneratecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> #include &quot;AirValidate.h&quot;
</span><span class="cx"> #include &quot;B3Common.h&quot;
</span><span class="cx"> #include &quot;B3IndexMap.h&quot;
</span><ins>+#include &quot;B3Procedure.h&quot;
</ins><span class="cx"> #include &quot;B3TimingScope.h&quot;
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> #include &quot;DisallowMacroScratchRegisterUsage.h&quot;
</span><span class="lines">@@ -171,12 +172,23 @@
</span><span class="cx">         blockJumps[target].append(jump);
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    PCToOriginMap&amp; pcToOriginMap = code.proc().pcToOriginMap();
+    auto addItem = [&amp;] (Inst&amp; inst) {
+        if (!inst.origin) {
+            pcToOriginMap.appendItem(jit.label(), Origin());
+            return;
+        }
+        pcToOriginMap.appendItem(jit.label(), inst.origin-&gt;origin());
+    };
+
</ins><span class="cx">     for (BasicBlock* block : code) {
</span><span class="cx">         blockJumps[block].link(&amp;jit);
</span><span class="cx">         blockLabels[block] = jit.label();
</span><span class="cx">         ASSERT(block-&gt;size() &gt;= 1);
</span><span class="cx">         for (unsigned i = 0; i &lt; block-&gt;size() - 1; ++i) {
</span><del>-            CCallHelpers::Jump jump = block-&gt;at(i).generate(jit, context);
</del><ins>+            Inst&amp; inst = block-&gt;at(i);
+            addItem(inst);
+            CCallHelpers::Jump jump = inst.generate(jit, context);
</ins><span class="cx">             ASSERT_UNUSED(jump, !jump.isSet());
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -184,6 +196,8 @@
</span><span class="cx">             &amp;&amp; block-&gt;successorBlock(0) == code.findNextBlock(block))
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><ins>+        addItem(block-&gt;last());
+
</ins><span class="cx">         if (isReturn(block-&gt;last().opcode)) {
</span><span class="cx">             // We currently don't represent the full prologue/epilogue in Air, so we need to
</span><span class="cx">             // have this override.
</span><span class="lines">@@ -198,6 +212,7 @@
</span><span class="cx">             } else
</span><span class="cx">                 jit.emitFunctionEpilogueWithEmptyFrame();
</span><span class="cx">             jit.ret();
</span><ins>+            addItem(block-&gt;last());
</ins><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -218,10 +233,14 @@
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        addItem(block-&gt;last());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    pcToOriginMap.appendItem(jit.label(), Origin());
+    // FIXME: Make late paths have Origins: https://bugs.webkit.org/show_bug.cgi?id=153689
</ins><span class="cx">     for (auto&amp; latePath : context.latePaths)
</span><span class="cx">         latePath-&gt;run(jit, context);
</span><ins>+    pcToOriginMap.appendItem(jit.label(), Origin());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx"> #include &quot;LLIntEntrypoint.h&quot;
</span><span class="cx"> #include &quot;LowLevelInterpreter.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;PCToCodeOriginMap.h&quot;
</ins><span class="cx"> #include &quot;PolymorphicAccess.h&quot;
</span><span class="cx"> #include &quot;ProfilerDatabase.h&quot;
</span><span class="cx"> #include &quot;ReduceWhitespace.h&quot;
</span><span class="lines">@@ -4267,4 +4268,30 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(JIT)
+void CodeBlock::setPCToCodeOriginMap(std::unique_ptr&lt;PCToCodeOriginMap&gt;&amp;&amp; map) 
+{ 
+    m_pcToCodeOriginMap = WTFMove(map);
+}
+
+Optional&lt;CodeOrigin&gt; CodeBlock::findPC(void* pc)
+{
+    if (m_pcToCodeOriginMap) {
+        if (Optional&lt;CodeOrigin&gt; codeOrigin = m_pcToCodeOriginMap-&gt;findPC(pc))
+            return codeOrigin;
+    }
+
+    for (Bag&lt;StructureStubInfo&gt;::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
+        StructureStubInfo* stub = *iter;
+        if (stub-&gt;containsPC(pc))
+            return Optional&lt;CodeOrigin&gt;(stub-&gt;codeOrigin);
+    }
+
+    if (Optional&lt;CodeOrigin&gt; codeOrigin = m_jitCode-&gt;findPC(this, pc))
+        return codeOrigin;
+
+    return Nullopt;
+}
+#endif // ENABLE(JIT)
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -84,6 +84,7 @@
</span><span class="cx"> class RegisterAtOffsetList;
</span><span class="cx"> class TypeLocation;
</span><span class="cx"> class JSModuleEnvironment;
</span><ins>+class PCToCodeOriginMap;
</ins><span class="cx"> 
</span><span class="cx"> enum ReoptimizationMode { DontCountReoptimization, CountReoptimization };
</span><span class="cx"> 
</span><span class="lines">@@ -273,7 +274,7 @@
</span><span class="cx">     {
</span><span class="cx">         return m_jitCodeMap.get();
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     unsigned bytecodeOffset(Instruction* returnAddress)
</span><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(returnAddress &gt;= instructions().begin() &amp;&amp; returnAddress &lt; instructions().end());
</span><span class="lines">@@ -914,6 +915,11 @@
</span><span class="cx"> 
</span><span class="cx">     CallSiteIndex newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite);
</span><span class="cx"> 
</span><ins>+#if ENABLE(JIT)
+    void setPCToCodeOriginMap(std::unique_ptr&lt;PCToCodeOriginMap&gt;&amp;&amp;);
+    Optional&lt;CodeOrigin&gt; findPC(void* pc);
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     void finalizeLLIntInlineCaches();
</span><span class="cx">     void finalizeBaselineJITInlineCaches();
</span><span class="lines">@@ -1032,6 +1038,7 @@
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     SentinelLinkedList&lt;CallLinkInfo, BasicRawSentinelNode&lt;CallLinkInfo&gt;&gt; m_incomingCalls;
</span><span class="cx">     SentinelLinkedList&lt;PolymorphicCallNode, BasicRawSentinelNode&lt;PolymorphicCallNode&gt;&gt; m_incomingPolymorphicCalls;
</span><ins>+    std::unique_ptr&lt;PCToCodeOriginMap&gt; m_pcToCodeOriginMap;
</ins><span class="cx"> #endif
</span><span class="cx">     std::unique_ptr&lt;CompactJITCodeMap&gt; m_jitCodeMap;
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeOriginh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -102,6 +102,9 @@
</span><span class="cx">     bool isApproximatelyEqualTo(const CodeOrigin&amp; other) const;
</span><span class="cx">     
</span><span class="cx">     unsigned approximateHash() const;
</span><ins>+
+    template &lt;typename Function&gt;
+    void walkUpInlineStack(const Function&amp;);
</ins><span class="cx">     
</span><span class="cx">     // Get the inline stack. This is slow, and is intended for debugging only.
</span><span class="cx">     Vector&lt;CodeOrigin&gt; inlineStack() const;
</span><span class="lines">@@ -127,7 +130,7 @@
</span><span class="cx">     return bytecodeIndex == other.bytecodeIndex
</span><span class="cx">         &amp;&amp; inlineCallFrame == other.inlineCallFrame;
</span><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> struct CodeOriginHash {
</span><span class="cx">     static unsigned hash(const CodeOrigin&amp; key) { return key.hash(); }
</span><span class="cx">     static bool equal(const CodeOrigin&amp; a, const CodeOrigin&amp; b) { return a == b; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeInlineCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/InlineCallFrame.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/InlineCallFrame.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/InlineCallFrame.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -246,6 +246,18 @@
</span><span class="cx">     return baselineCodeBlock;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template &lt;typename Function&gt;
+inline void CodeOrigin::walkUpInlineStack(const Function&amp; function)
+{
+    CodeOrigin codeOrigin = *this;
+    while (true) {
+        function(codeOrigin);
+        if (!codeOrigin.inlineCallFrame)
+            break;
+        codeOrigin = codeOrigin.inlineCallFrame-&gt;directCaller;
+    }
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -324,7 +324,15 @@
</span><span class="cx">     void aboutToDie();
</span><span class="cx"> 
</span><span class="cx">     void dump(PrintStream&amp; out) const;
</span><ins>+    bool containsPC(void* pc) const
+    { 
+        if (!m_stubRoutine)
+            return false;
</ins><span class="cx"> 
</span><ins>+        uintptr_t pcAsInt = bitwise_cast&lt;uintptr_t&gt;(pc);
+        return m_stubRoutine-&gt;startAddress() &lt;= pcAsInt &amp;&amp; pcAsInt &lt;= m_stubRoutine-&gt;endAddress();
+    }
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class AccessCase;
</span><span class="cx">     friend class CodeBlock;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -184,6 +184,13 @@
</span><span class="cx">     reset(codeBlock);
</span><span class="cx">     resetByGC = true;
</span><span class="cx"> }
</span><ins>+
+bool StructureStubInfo::containsPC(void* pc) const
+{
+    if (cacheType != CacheType::Stub)
+        return false;
+    return u.stub-&gt;containsPC(pc);
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -122,6 +122,8 @@
</span><span class="cx">     CodeOrigin codeOrigin;
</span><span class="cx">     CallSiteIndex callSiteIndex;
</span><span class="cx"> 
</span><ins>+    bool containsPC(void* pc) const;
+
</ins><span class="cx">     union {
</span><span class="cx">         struct {
</span><span class="cx">             WriteBarrierBase&lt;Structure&gt; baseObjectStructure;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -129,6 +129,7 @@
</span><span class="cx">     void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot);
</span><span class="cx"> 
</span><span class="cx">     bool hasExpressionInfo() { return m_expressionInfo.size(); }
</span><ins>+    const Vector&lt;ExpressionRangeInfo&gt;&amp; expressionInfo() { return m_expressionInfo; }
</ins><span class="cx"> 
</span><span class="cx">     // Special registers
</span><span class="cx">     void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -145,6 +145,8 @@
</span><span class="cx">     globalObject-&gt;setDebugger(this);
</span><span class="cx">     m_globalObjects.add(globalObject);
</span><span class="cx"> 
</span><ins>+    m_vm.setShouldBuildPCToCodeOriginMapping();
+
</ins><span class="cx">     // Call sourceParsed because it will execute JavaScript in the inspector.
</span><span class="cx">     GatherSourceProviders gatherSourceProviders(globalObject);
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -215,6 +215,18 @@
</span><span class="cx">     minifiedDFG.validateReferences(trackedReferences);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Optional&lt;CodeOrigin&gt; JITCode::findPC(CodeBlock*, void* pc)
+{
+    for (OSRExit&amp; exit : osrExit) {
+        if (ExecutableMemoryHandle* handle = exit.m_code.executableMemory()) {
+            if (handle-&gt;start() &lt;= pc &amp;&amp; pc &lt; handle-&gt;end())
+                return Optional&lt;CodeOrigin&gt;(exit.m_codeOriginForExitProfile);
+        }
+    }
+
+    return Nullopt;
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCode.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCode.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCode.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -124,6 +124,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     static ptrdiff_t commonDataOffset() { return OBJECT_OFFSETOF(JITCode, common); }
</span><ins>+
+    Optional&lt;CodeOrigin&gt; findPC(CodeBlock*, void* pc) override;
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     friend class JITCompiler; // Allow JITCompiler to call setCodeRef().
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx">     , m_graph(dfg)
</span><span class="cx">     , m_jitCode(adoptRef(new JITCode()))
</span><span class="cx">     , m_blockHeads(dfg.numBlocks())
</span><ins>+    , m_pcToCodeOriginMapBuilder(dfg.m_vm)
</ins><span class="cx"> {
</span><span class="cx">     if (shouldDumpDisassembly() || m_graph.m_vm.m_perBytecodeProfiler)
</span><span class="cx">         m_disassembler = std::make_unique&lt;Disassembler&gt;(dfg);
</span><span class="lines">@@ -305,6 +306,9 @@
</span><span class="cx">             m_codeBlock-&gt;appendExceptionHandler(newExceptionHandler);
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
+    if (m_pcToCodeOriginMapBuilder.didBuildMapping())
+        m_codeBlock-&gt;setPCToCodeOriginMap(std::make_unique&lt;PCToCodeOriginMap&gt;(WTFMove(m_pcToCodeOriginMapBuilder), linkBuffer));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JITCompiler::compile()
</span><span class="lines">@@ -339,7 +343,8 @@
</span><span class="cx">     m_speculative-&gt;callOperationWithCallFrameRollbackOnException(operationThrowStackOverflowError, m_codeBlock);
</span><span class="cx"> 
</span><span class="cx">     // Generate slow path code.
</span><del>-    m_speculative-&gt;runSlowPathGenerators();
</del><ins>+    m_speculative-&gt;runSlowPathGenerators(m_pcToCodeOriginMapBuilder);
+    m_pcToCodeOriginMapBuilder.appendItem(label(), PCToCodeOriginMapBuilder::defaultCodeOrigin());
</ins><span class="cx">     
</span><span class="cx">     compileExceptionHandlers();
</span><span class="cx">     linkOSRExits();
</span><span class="lines">@@ -432,7 +437,8 @@
</span><span class="cx">     jump(fromArityCheck);
</span><span class="cx">     
</span><span class="cx">     // Generate slow path code.
</span><del>-    m_speculative-&gt;runSlowPathGenerators();
</del><ins>+    m_speculative-&gt;runSlowPathGenerators(m_pcToCodeOriginMapBuilder);
+    m_pcToCodeOriginMapBuilder.appendItem(label(), PCToCodeOriginMapBuilder::defaultCodeOrigin());
</ins><span class="cx">     
</span><span class="cx">     compileExceptionHandlers();
</span><span class="cx">     linkOSRExits();
</span><span class="lines">@@ -596,6 +602,22 @@
</span><span class="cx">     return callSite;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JITCompiler::setEndOfMainPath()
+{
+    m_pcToCodeOriginMapBuilder.appendItem(labelIgnoringWatchpoints(), m_speculative-&gt;m_origin.semantic);
+    if (LIKELY(!m_disassembler))
+        return;
+    m_disassembler-&gt;setEndOfMainPath(labelIgnoringWatchpoints());
+}
+
+void JITCompiler::setEndOfCode()
+{
+    m_pcToCodeOriginMapBuilder.appendItem(labelIgnoringWatchpoints(), PCToCodeOriginMapBuilder::defaultCodeOrigin());
+    if (LIKELY(!m_disassembler))
+        return;
+    m_disassembler-&gt;setEndOfCode(labelIgnoringWatchpoints());
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx"> #include &quot;JITInlineCacheGenerator.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><ins>+#include &quot;PCToCodeOriginMap.h&quot;
</ins><span class="cx"> #include &quot;TempRegisterSet.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -118,6 +119,7 @@
</span><span class="cx">     // Methods to set labels for the disassembler.
</span><span class="cx">     void setStartOfCode()
</span><span class="cx">     {
</span><ins>+        m_pcToCodeOriginMapBuilder.appendItem(labelIgnoringWatchpoints(), CodeOrigin(0, nullptr));
</ins><span class="cx">         if (LIKELY(!m_disassembler))
</span><span class="cx">             return;
</span><span class="cx">         m_disassembler-&gt;setStartOfCode(labelIgnoringWatchpoints());
</span><span class="lines">@@ -137,20 +139,9 @@
</span><span class="cx">         m_disassembler-&gt;setForNode(node, labelIgnoringWatchpoints());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void setEndOfMainPath()
-    {
-        if (LIKELY(!m_disassembler))
-            return;
-        m_disassembler-&gt;setEndOfMainPath(labelIgnoringWatchpoints());
-    }
</del><ins>+    void setEndOfMainPath();
+    void setEndOfCode();
</ins><span class="cx">     
</span><del>-    void setEndOfCode()
-    {
-        if (LIKELY(!m_disassembler))
-            return;
-        m_disassembler-&gt;setEndOfCode(labelIgnoringWatchpoints());
-    }
-    
</del><span class="cx">     CallSiteIndex addCallSite(CodeOrigin codeOrigin)
</span><span class="cx">     {
</span><span class="cx">         return m_jitCode-&gt;common.addCodeOrigin(codeOrigin);
</span><span class="lines">@@ -265,6 +256,8 @@
</span><span class="cx"> 
</span><span class="cx">     CallSiteIndex recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(const CodeOrigin&amp;, unsigned eventStreamIndex);
</span><span class="cx"> 
</span><ins>+    PCToCodeOriginMapBuilder&amp; pcToCodeOriginMapBuilder() { return m_pcToCodeOriginMapBuilder; }
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class OSRExitJumpPlaceholder;
</span><span class="cx">     
</span><span class="lines">@@ -328,6 +321,7 @@
</span><span class="cx">     Call m_callArityFixup;
</span><span class="cx">     Label m_arityCheck;
</span><span class="cx">     std::unique_ptr&lt;SpeculativeJIT&gt; m_speculative;
</span><ins>+    PCToCodeOriginMapBuilder m_pcToCodeOriginMapBuilder;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSlowPathGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -62,6 +62,9 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
</span><span class="cx">         return MacroAssembler::Call();
</span><span class="cx">     }
</span><ins>+
+    const NodeOrigin&amp; origin() const  { return m_origin; }
+
</ins><span class="cx"> protected:
</span><span class="cx">     virtual void generateInternal(SpeculativeJIT*) = 0;
</span><span class="cx">     MacroAssembler::Label m_label;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -330,10 +330,12 @@
</span><span class="cx">     m_slowPathGenerators.append(WTFMove(slowPathGenerator));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::runSlowPathGenerators()
</del><ins>+void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder&amp; pcToCodeOriginMapBuilder)
</ins><span class="cx"> {
</span><del>-    for (unsigned i = 0; i &lt; m_slowPathGenerators.size(); ++i)
</del><ins>+    for (unsigned i = 0; i &lt; m_slowPathGenerators.size(); ++i) {
+        pcToCodeOriginMapBuilder.appendItem(m_jit.label(), m_slowPathGenerators[i]-&gt;origin().semantic);
</ins><span class="cx">         m_slowPathGenerators[i]-&gt;generate(this);
</span><ins>+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // On Windows we need to wrap fmod; on other platforms we can call it directly.
</span><span class="lines">@@ -1504,6 +1506,8 @@
</span><span class="cx">         if (Options::validateDFGExceptionHandling() &amp;&amp; mayExit(m_jit.graph(), m_currentNode) != DoesNotExit)
</span><span class="cx">             m_jit.jitReleaseAssertNoException();
</span><span class="cx"> 
</span><ins>+        m_jit.pcToCodeOriginMapBuilder().appendItem(m_jit.label(), m_origin.semantic);
+
</ins><span class="cx">         compile(m_currentNode);
</span><span class="cx">         
</span><span class="cx">         if (belongsInMinifiedGraph(m_currentNode-&gt;op()))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -317,7 +317,7 @@
</span><span class="cx">     GeneratedOperandType checkGeneratedTypeForToInt32(Node*);
</span><span class="cx"> 
</span><span class="cx">     void addSlowPathGenerator(std::unique_ptr&lt;SlowPathGenerator&gt;);
</span><del>-    void runSlowPathGenerators();
</del><ins>+    void runSlowPathGenerators(PCToCodeOriginMapBuilder&amp;);
</ins><span class="cx">     
</span><span class="cx">     void compile(Node*);
</span><span class="cx">     void noticeOSRBirth(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Compilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> #include &quot;FTLUnwindInfo.h&quot;
</span><span class="cx"> #include &quot;JITSubGenerator.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><ins>+#include &quot;PCToCodeOriginMap.h&quot;
</ins><span class="cx"> #include &quot;ScratchRegisterAllocator.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="lines">@@ -140,6 +141,10 @@
</span><span class="cx">         state.allocationFailed = true;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    
+    B3::PCToOriginMap originMap = state.proc-&gt;releasePCToOriginMap();
+    if (vm.shouldBuilderPCToCodeOriginMapping())
+        codeBlock-&gt;setPCToCodeOriginMap(std::make_unique&lt;PCToCodeOriginMap&gt;(PCToCodeOriginMapBuilder(vm, WTFMove(originMap)), *state.finalizer-&gt;b3CodeLinkBuffer));
</ins><span class="cx"> 
</span><span class="cx">     state.generatedFunction = bitwise_cast&lt;GeneratedFunction&gt;(
</span><span class="cx">         state.finalizer-&gt;b3CodeLinkBuffer-&gt;entrypoint().executableAddress());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -186,6 +186,25 @@
</span><span class="cx">     return RegisterSet();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Optional&lt;CodeOrigin&gt; JITCode::findPC(CodeBlock* codeBlock, void* pc)
+{
+    for (OSRExit&amp; exit : osrExit) {
+        if (ExecutableMemoryHandle* handle = exit.m_code.executableMemory()) {
+            if (handle-&gt;start() &lt;= pc &amp;&amp; pc &lt; handle-&gt;end())
+                return Optional&lt;CodeOrigin&gt;(exit.m_codeOriginForExitProfile);
+        }
+    }
+
+    for (std::unique_ptr&lt;LazySlowPath&gt;&amp; lazySlowPath : lazySlowPaths) {
+        if (ExecutableMemoryHandle* handle = lazySlowPath-&gt;stub().executableMemory()) {
+            if (handle-&gt;start() &lt;= pc &amp;&amp; pc &lt; handle-&gt;end())
+                return Optional&lt;CodeOrigin&gt;(codeBlock-&gt;codeOrigin(lazySlowPath-&gt;callSiteIndex()));
+        }
+    }
+
+    return Nullopt;
+}
+
</ins><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITCode.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -82,6 +82,8 @@
</span><span class="cx"> 
</span><span class="cx">     RegisterSet liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex) override;
</span><span class="cx"> 
</span><ins>+    Optional&lt;CodeOrigin&gt; findPC(CodeBlock*, void* pc) override;
+
</ins><span class="cx"> #if FTL_USES_B3
</span><span class="cx">     CodeRef b3Code() const { return m_b3Code; }
</span><span class="cx"> #else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMachineStackMarkercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -23,9 +23,12 @@
</span><span class="cx"> #include &quot;MachineStackMarker.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ConservativeRoots.h&quot;
</span><ins>+#include &quot;GPRInfo.h&quot;
</ins><span class="cx"> #include &quot;Heap.h&quot;
</span><span class="cx"> #include &quot;JSArray.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;LLIntPCRanges.h&quot;
+#include &quot;MacroAssembler.h&quot;
</ins><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> #include &lt;setjmp.h&gt;
</span><span class="cx"> #include &lt;stdlib.h&gt;
</span><span class="lines">@@ -577,6 +580,64 @@
</span><span class="cx"> #error Need a way to get the instruction pointer for another thread on this platform
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><ins>+void* MachineThreads::Thread::Registers::llintPC() const
+{
+    // LLInt uses regT4 as PC.
+#if OS(DARWIN)
+
+#if __DARWIN_UNIX03
+
+#if CPU(X86)
+    static_assert(LLInt::LLIntPC == X86Registers::esi, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;(regs.__esi);
+#elif CPU(X86_64)
+    static_assert(LLInt::LLIntPC == X86Registers::r8, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;(regs.__r8);
+#elif CPU(ARM)
+    static_assert(LLInt::LLIntPC == ARMRegisters::r8, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;(regs.__r[8]);
+#elif CPU(ARM64)
+    static_assert(LLInt::LLIntPC == ARM64Registers::x4, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;(regs.__x[4]);
+#else
+#error Unknown Architecture
+#endif
+
+#else // !__DARWIN_UNIX03
+#if CPU(X86)
+    static_assert(LLInt::LLIntPC == X86Registers::esi, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;(regs.esi);
+#elif CPU(X86_64)
+    static_assert(LLInt::LLIntPC == X86Registers::r8, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;(regs.r8);
+#else
+#error Unknown Architecture
+#endif
+
+#endif // __DARWIN_UNIX03
+
+// end OS(DARWIN)
+#elif OS(WINDOWS)
+
+#if CPU(ARM)
+    static_assert(LLInt::LLIntPC == ARMRegisters::r8, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;((uintptr_t) regs.R8);
+#elif CPU(MIPS)
+#error Dont know what to do with mips. Do we even need this?
+#elif CPU(X86)
+    static_assert(LLInt::LLIntPC == X86Registers::esi, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;((uintptr_t) regs.Esi);
+#elif CPU(X86_64)
+    static_assert(LLInt::LLIntPC == X86Registers::r10, &quot;Wrong LLInt PC.&quot;);
+    return reinterpret_cast&lt;void*&gt;((uintptr_t) regs.R10);
+#else
+#error Unknown Architecture
+#endif
+
+#else
+#error Need a way to get the LLIntPC for another thread on this platform
+#endif
+}
</ins><span class="cx"> #endif // ENABLE(SAMPLING_PROFILER)
</span><span class="cx"> 
</span><span class="cx"> void MachineThreads::Thread::freeRegisters(Thread::Registers&amp; registers)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMachineStackMarkerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MachineStackMarker.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MachineStackMarker.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/heap/MachineStackMarker.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx"> #if ENABLE(SAMPLING_PROFILER)
</span><span class="cx">             void* framePointer() const;
</span><span class="cx">             void* instructionPointer() const;
</span><ins>+            void* llintPC() const;
</ins><span class="cx"> #endif // ENABLE(SAMPLING_PROFILER)
</span><span class="cx">             
</span><span class="cx"> #if OS(DARWIN)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorScriptProfilerAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -157,7 +157,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SAMPLING_PROFILER)
</span><del>-static Ref&lt;Protocol::ScriptProfiler::Samples&gt; buildSamples(Vector&lt;SamplingProfiler::StackTrace&gt;&amp; samplingProfilerStackTraces, double totalTime)
</del><ins>+static Ref&lt;Protocol::ScriptProfiler::Samples&gt; buildSamples(Vector&lt;SamplingProfiler::StackTrace&gt;&amp;&amp; samplingProfilerStackTraces, double totalTime)
</ins><span class="cx"> {
</span><span class="cx">     Ref&lt;Protocol::Array&lt;Protocol::ScriptProfiler::StackTrace&gt;&gt; stackTraces = Protocol::Array&lt;Protocol::ScriptProfiler::StackTrace&gt;::create();
</span><span class="cx">     for (SamplingProfiler::StackTrace&amp; stackTrace : samplingProfilerStackTraces) {
</span><span class="lines">@@ -166,8 +166,8 @@
</span><span class="cx">             Ref&lt;Protocol::ScriptProfiler::StackFrame&gt; frame = Protocol::ScriptProfiler::StackFrame::create()
</span><span class="cx">                 .setSourceID(String::number(stackFrame.sourceID()))
</span><span class="cx">                 .setName(stackFrame.displayName())
</span><del>-                .setLine(stackFrame.startLine())
-                .setColumn(stackFrame.startColumn())
</del><ins>+                .setLine(stackFrame.functionStartLine())
+                .setColumn(stackFrame.functionStartColumn())
</ins><span class="cx">                 .setUrl(stackFrame.url())
</span><span class="cx">                 .release();
</span><span class="cx">             frames-&gt;addItem(WTFMove(frame));
</span><span class="lines">@@ -194,8 +194,8 @@
</span><span class="cx">         RELEASE_ASSERT(samplingProfiler);
</span><span class="cx">         LockHolder locker(samplingProfiler-&gt;getLock());
</span><span class="cx">         samplingProfiler-&gt;stop(locker);
</span><del>-        Ref&lt;Protocol::ScriptProfiler::Samples&gt; samples = buildSamples(samplingProfiler-&gt;stackTraces(locker), samplingProfiler-&gt;totalTime(locker));
-        samplingProfiler-&gt;clearData(locker);
</del><ins>+        Vector&lt;SamplingProfiler::StackTrace&gt; stackTraces = samplingProfiler-&gt;releaseStackTraces(locker);
+        Ref&lt;Protocol::ScriptProfiler::Samples&gt; samples = buildSamples(WTFMove(stackTraces), samplingProfiler-&gt;totalTime(locker));
</ins><span class="cx"> 
</span><span class="cx">         locker.unlockEarly();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="cx"> #include &quot;MaxFrameExtentForSlowPathCall.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;PCToCodeOriginMap.h&quot;
</ins><span class="cx"> #include &quot;ProfilerDatabase.h&quot;
</span><span class="cx"> #include &quot;ResultType.h&quot;
</span><span class="cx"> #include &quot;SamplingTool.h&quot;
</span><span class="lines">@@ -69,6 +70,7 @@
</span><span class="cx">     , m_byValInstructionIndex(UINT_MAX)
</span><span class="cx">     , m_callLinkInfoIndex(UINT_MAX)
</span><span class="cx">     , m_randomGenerator(cryptographicallyRandomNumber())
</span><ins>+    , m_pcToCodeOriginMapBuilder(*vm)
</ins><span class="cx">     , m_canBeOptimized(false)
</span><span class="cx">     , m_shouldEmitProfiling(false)
</span><span class="cx"> {
</span><span class="lines">@@ -158,6 +160,8 @@
</span><span class="cx">         Instruction* currentInstruction = instructionsBegin + m_bytecodeOffset;
</span><span class="cx">         ASSERT_WITH_MESSAGE(m_interpreter-&gt;isOpcode(currentInstruction-&gt;u.opcode), &quot;privateCompileMainPass gone bad @ %d&quot;, m_bytecodeOffset);
</span><span class="cx"> 
</span><ins>+        m_pcToCodeOriginMapBuilder.appendItem(label(), CodeOrigin(m_bytecodeOffset));
+
</ins><span class="cx"> #if ENABLE(OPCODE_SAMPLING)
</span><span class="cx">         if (m_bytecodeOffset &gt; 0) // Avoid the overhead of sampling op_enter twice.
</span><span class="cx">             sampleInstruction(currentInstruction);
</span><span class="lines">@@ -365,6 +369,8 @@
</span><span class="cx">     for (Vector&lt;SlowCaseEntry&gt;::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
</span><span class="cx">         m_bytecodeOffset = iter-&gt;to;
</span><span class="cx"> 
</span><ins>+        m_pcToCodeOriginMapBuilder.appendItem(label(), CodeOrigin(m_bytecodeOffset));
+
</ins><span class="cx">         unsigned firstTo = m_bytecodeOffset;
</span><span class="cx"> 
</span><span class="cx">         Instruction* currentInstruction = instructionsBegin + m_bytecodeOffset;
</span><span class="lines">@@ -519,6 +525,8 @@
</span><span class="cx">         m_compilation-&gt;addProfiledBytecodes(*m_vm-&gt;m_perBytecodeProfiler, m_codeBlock);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    m_pcToCodeOriginMapBuilder.appendItem(label(), CodeOrigin(0, nullptr));
+
</ins><span class="cx">     if (m_disassembler)
</span><span class="cx">         m_disassembler-&gt;setStartOfCode(label());
</span><span class="cx"> 
</span><span class="lines">@@ -571,6 +579,7 @@
</span><span class="cx">     
</span><span class="cx">     if (m_disassembler)
</span><span class="cx">         m_disassembler-&gt;setEndOfSlowPath(label());
</span><ins>+    m_pcToCodeOriginMapBuilder.appendItem(label(), PCToCodeOriginMapBuilder::defaultCodeOrigin());
</ins><span class="cx"> 
</span><span class="cx">     stackOverflow.link(this);
</span><span class="cx">     m_bytecodeOffset = 0;
</span><span class="lines">@@ -612,7 +621,9 @@
</span><span class="cx">     
</span><span class="cx">     if (m_disassembler)
</span><span class="cx">         m_disassembler-&gt;setEndOfCode(label());
</span><ins>+    m_pcToCodeOriginMapBuilder.appendItem(label(), PCToCodeOriginMapBuilder::defaultCodeOrigin());
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock, effort);
</span><span class="cx">     if (patchBuffer.didFailToAllocate())
</span><span class="cx">         return CompilationFailed;
</span><span class="lines">@@ -708,6 +719,9 @@
</span><span class="cx">         m_disassembler-&gt;reportToProfiler(m_compilation.get(), patchBuffer);
</span><span class="cx">         m_vm-&gt;m_perBytecodeProfiler-&gt;addCompilation(m_compilation);
</span><span class="cx">     }
</span><ins>+
+    if (m_pcToCodeOriginMapBuilder.didBuildMapping())
+        m_codeBlock-&gt;setPCToCodeOriginMap(std::make_unique&lt;PCToCodeOriginMap&gt;(WTFMove(m_pcToCodeOriginMapBuilder), patchBuffer));
</ins><span class="cx">     
</span><span class="cx">     CodeRef result = FINALIZE_CODE(
</span><span class="cx">         patchBuffer,
</span><span class="lines">@@ -716,7 +730,7 @@
</span><span class="cx">     m_vm-&gt;machineCodeBytesPerBytecodeWordForBaselineJIT.add(
</span><span class="cx">         static_cast&lt;double&gt;(result.size()) /
</span><span class="cx">         static_cast&lt;double&gt;(m_codeBlock-&gt;instructions().size()));
</span><del>-    
</del><ins>+
</ins><span class="cx">     m_codeBlock-&gt;shrinkToFit(CodeBlock::LateShrink);
</span><span class="cx">     m_codeBlock-&gt;setJITCode(
</span><span class="cx">         adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;JITInlineCacheGenerator.h&quot;
</span><span class="cx"> #include &quot;JSInterfaceJIT.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><ins>+#include &quot;PCToCodeOriginMap.h&quot;
</ins><span class="cx"> #include &quot;ResultType.h&quot;
</span><span class="cx"> #include &quot;SamplingTool.h&quot;
</span><span class="cx"> #include &quot;UnusedPointer.h&quot;
</span><span class="lines">@@ -913,6 +914,8 @@
</span><span class="cx">         WeakRandom m_randomGenerator;
</span><span class="cx">         static CodeRef stringGetByValStubGenerator(VM*);
</span><span class="cx"> 
</span><ins>+        PCToCodeOriginMapBuilder m_pcToCodeOriginMapBuilder;
+
</ins><span class="cx">         bool m_canBeOptimized;
</span><span class="cx">         bool m_canBeOptimizedOrInlined;
</span><span class="cx">         bool m_shouldEmitProfiling;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCode.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCode.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/jit/JITCode.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -28,10 +28,12 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ArityCheckMode.h&quot;
</span><span class="cx"> #include &quot;CallFrame.h&quot;
</span><ins>+#include &quot;CodeOrigin.h&quot;
</ins><span class="cx"> #include &quot;Disassembler.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><ins>+#include &lt;wtf/Optional.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -195,6 +197,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     virtual RegisterSet liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex);
</span><ins>+    virtual Optional&lt;CodeOrigin&gt; findPC(CodeBlock*, void* pc) { UNUSED_PARAM(pc); return Nullopt; }
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitPCToCodeOriginMapcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.cpp (0 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -0,0 +1,301 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;PCToCodeOriginMap.h&quot;
+
+#if ENABLE(JIT)
+
+#include &quot;B3PCToOriginMap.h&quot;
+#include &quot;DFGNode.h&quot;
+#include &quot;LinkBuffer.h&quot;
+
+namespace JSC {
+
+namespace {
+
+class DeltaCompressionBuilder {
+public:
+    DeltaCompressionBuilder(size_t maxSize)
+        : m_offset(0)
+        , m_maxSize(maxSize)
+    {
+        m_buffer = static_cast&lt;uint8_t*&gt;(fastMalloc(m_maxSize));
+    }
+
+    template &lt;typename T&gt;
+    void write(T item)
+    {
+        RELEASE_ASSERT(m_offset + sizeof(T) &lt;= m_maxSize);
+        static const uint8_t mask = std::numeric_limits&lt;uint8_t&gt;::max();
+        for (unsigned i = 0; i &lt; sizeof(T); i++) {
+            *(m_buffer + m_offset) = static_cast&lt;uint8_t&gt;(item &amp; mask);
+            item = item &gt;&gt; (sizeof(uint8_t) * 8);
+            m_offset += 1;
+        }
+    }
+
+    uint8_t* m_buffer; 
+    size_t m_offset;
+    size_t m_maxSize;
+};
+
+class DeltaCompresseionReader {
+public:
+    DeltaCompresseionReader(uint8_t* buffer, size_t size)
+        : m_buffer(buffer)
+        , m_size(size)
+        , m_offset(0)
+    { }
+
+    template &lt;typename T&gt;
+    T read()
+    {
+        RELEASE_ASSERT(m_offset + sizeof(T) &lt;= m_size);
+        T result = 0;
+        for (unsigned i = 0; i &lt; sizeof(T); i++) {
+            uint8_t bitsAsInt8 = *(m_buffer + m_offset);
+            T bits = static_cast&lt;T&gt;(bitsAsInt8);
+            bits = bits &lt;&lt; (sizeof(uint8_t) * 8 * i);
+            result |= bits;
+            m_offset += 1;
+        }
+        return result;
+    }
+
+private:
+    uint8_t* m_buffer;
+    size_t m_size;
+    size_t m_offset;
+};
+
+} // anonymous namespace
+
+PCToCodeOriginMapBuilder::PCToCodeOriginMapBuilder(VM&amp; vm)
+    : m_vm(vm)
+    , m_shouldBuildMapping(vm.shouldBuilderPCToCodeOriginMapping())
+{ }
+
+PCToCodeOriginMapBuilder::PCToCodeOriginMapBuilder(PCToCodeOriginMapBuilder&amp;&amp; other)
+    : m_vm(other.m_vm)
+    , m_codeRanges(WTFMove(other.m_codeRanges))
+    , m_shouldBuildMapping(other.m_shouldBuildMapping)
+{ }
+
+#if FTL_USES_B3
+PCToCodeOriginMapBuilder::PCToCodeOriginMapBuilder(VM&amp; vm, B3::PCToOriginMap&amp;&amp; b3PCToOriginMap)
+    : m_vm(vm)
+    , m_shouldBuildMapping(vm.shouldBuilderPCToCodeOriginMapping())
+{
+    if (!m_shouldBuildMapping)
+        return;
+
+    for (const B3::PCToOriginMap::OriginRange&amp; originRange : b3PCToOriginMap.ranges()) {
+        DFG::Node* node = bitwise_cast&lt;DFG::Node*&gt;(originRange.origin.data());
+        if (node)
+            appendItem(originRange.label, node-&gt;origin.semantic);
+        else
+            appendItem(originRange.label, PCToCodeOriginMapBuilder::defaultCodeOrigin());
+    }
+}
+#endif
+
+void PCToCodeOriginMapBuilder::appendItem(MacroAssembler::Label label, const CodeOrigin&amp; codeOrigin)
+{
+    if (!m_shouldBuildMapping)
+        return;
+
+    if (m_codeRanges.size()) {
+        if (m_codeRanges.last().end == label)
+            return;
+        m_codeRanges.last().end = label;
+        if (m_codeRanges.last().codeOrigin == codeOrigin || !codeOrigin)
+            return;
+    }
+
+    m_codeRanges.append(CodeRange{label, label, codeOrigin});
+}
+
+
+static const uint8_t sentinelPCDelta = 0;
+static const int8_t sentinelBytecodeDelta = 0;
+
+PCToCodeOriginMap::PCToCodeOriginMap(PCToCodeOriginMapBuilder&amp;&amp; builder, LinkBuffer&amp; linkBuffer)
+{
+    RELEASE_ASSERT(builder.didBuildMapping());
+
+    if (!builder.m_codeRanges.size()) {
+        m_pcRangeStart = std::numeric_limits&lt;uintptr_t&gt;::max();
+        m_pcRangeEnd = std::numeric_limits&lt;uintptr_t&gt;::max();
+
+        m_compressedPCBufferSize = 0;
+        m_compressedPCs = nullptr;
+
+        m_compressedCodeOriginsSize = 0;
+        m_compressedCodeOrigins = nullptr;
+
+        return;
+    }
+
+    // We do a final touch-up on the last range here because of how we generate the table.
+    // The final range (if non empty) would be ignored if we didn't append any (arbitrary)
+    // range as the last item of the vector.
+    PCToCodeOriginMapBuilder::CodeRange&amp; last = builder.m_codeRanges.last();
+    if (!(last.start == last.end))
+        builder.m_codeRanges.append(PCToCodeOriginMapBuilder::CodeRange{ last.end, last.end, last.codeOrigin }); // This range will never actually be found, but it ensures the real last range is found.
+
+    DeltaCompressionBuilder pcCompressor((sizeof(uintptr_t) + sizeof(uint8_t)) * builder.m_codeRanges.size());
+    void* lastPCValue = nullptr;
+    auto buildPCTable = [&amp;] (void* pcValue) {
+        RELEASE_ASSERT(pcValue &gt; lastPCValue);
+        uintptr_t delta = bitwise_cast&lt;uintptr_t&gt;(pcValue) - bitwise_cast&lt;uintptr_t&gt;(lastPCValue);
+        RELEASE_ASSERT(delta != sentinelPCDelta);
+        lastPCValue = pcValue;
+        if (delta &gt; std::numeric_limits&lt;uint8_t&gt;::max()) {
+            pcCompressor.write&lt;uint8_t&gt;(sentinelPCDelta);
+            pcCompressor.write&lt;uintptr_t&gt;(delta);
+            return;
+        }
+
+        pcCompressor.write&lt;uint8_t&gt;(static_cast&lt;uint8_t&gt;(delta));
+    };
+
+    DeltaCompressionBuilder codeOriginCompressor((sizeof(intptr_t) + sizeof(int8_t) + sizeof(int8_t) + sizeof(InlineCallFrame*)) * builder.m_codeRanges.size());
+    CodeOrigin lastCodeOrigin(0, nullptr);
+    auto buildCodeOriginTable = [&amp;] (const CodeOrigin&amp; codeOrigin) {
+        intptr_t delta = static_cast&lt;intptr_t&gt;(codeOrigin.bytecodeIndex) - static_cast&lt;intptr_t&gt;(lastCodeOrigin.bytecodeIndex);
+        lastCodeOrigin = codeOrigin;
+        if (delta &gt; std::numeric_limits&lt;int8_t&gt;::max() || delta &lt; std::numeric_limits&lt;int8_t&gt;::min() || delta == sentinelBytecodeDelta) {
+            codeOriginCompressor.write&lt;int8_t&gt;(sentinelBytecodeDelta);
+            codeOriginCompressor.write&lt;intptr_t&gt;(delta);
+        } else
+            codeOriginCompressor.write&lt;int8_t&gt;(static_cast&lt;int8_t&gt;(delta));
+
+        int8_t hasInlineCallFrameByte = codeOrigin.inlineCallFrame ? 1 : 0;
+        codeOriginCompressor.write&lt;int8_t&gt;(hasInlineCallFrameByte);
+        if (hasInlineCallFrameByte)
+            codeOriginCompressor.write&lt;uintptr_t&gt;(bitwise_cast&lt;uintptr_t&gt;(codeOrigin.inlineCallFrame));
+    };
+
+    m_pcRangeStart = bitwise_cast&lt;uintptr_t&gt;(linkBuffer.locationOf(builder.m_codeRanges.first().start).dataLocation());
+    m_pcRangeEnd = bitwise_cast&lt;uintptr_t&gt;(linkBuffer.locationOf(builder.m_codeRanges.last().end).dataLocation());
+    m_pcRangeEnd -= 1;
+
+    for (unsigned i = 0; i &lt; builder.m_codeRanges.size(); i++) {
+        PCToCodeOriginMapBuilder::CodeRange&amp; codeRange = builder.m_codeRanges[i];
+        void* start = linkBuffer.locationOf(codeRange.start).dataLocation();
+        void* end = linkBuffer.locationOf(codeRange.end).dataLocation();
+        ASSERT(m_pcRangeStart &lt;= bitwise_cast&lt;uintptr_t&gt;(start));
+        ASSERT(m_pcRangeEnd &gt;= bitwise_cast&lt;uintptr_t&gt;(end) - 1);
+        if (start == end)
+            ASSERT(i == builder.m_codeRanges.size() - 1);
+        if (i &gt; 0)
+            ASSERT(linkBuffer.locationOf(builder.m_codeRanges[i - 1].end).dataLocation() == start);
+
+        buildPCTable(start);
+        buildCodeOriginTable(codeRange.codeOrigin);
+    }
+
+    m_compressedPCBufferSize = pcCompressor.m_offset;
+    m_compressedPCs = static_cast&lt;uint8_t*&gt;(fastRealloc(pcCompressor.m_buffer, m_compressedPCBufferSize));
+
+    m_compressedCodeOriginsSize = codeOriginCompressor.m_offset;
+    m_compressedCodeOrigins = static_cast&lt;uint8_t*&gt;(fastRealloc(codeOriginCompressor.m_buffer, m_compressedCodeOriginsSize));
+}
+
+PCToCodeOriginMap::~PCToCodeOriginMap()
+{
+    if (m_compressedPCs)
+        fastFree(m_compressedPCs);
+    if (m_compressedCodeOrigins)
+        fastFree(m_compressedCodeOrigins);
+}
+
+double PCToCodeOriginMap::memorySize()
+{
+    double size = 0;
+    size += m_compressedPCBufferSize;
+    size += m_compressedCodeOriginsSize;
+    return size;
+}
+
+Optional&lt;CodeOrigin&gt; PCToCodeOriginMap::findPC(void* pc) const
+{
+    uintptr_t pcAsInt = bitwise_cast&lt;uintptr_t&gt;(pc);
+    if (!(m_pcRangeStart &lt;= pcAsInt &amp;&amp; pcAsInt &lt;= m_pcRangeEnd))
+        return Nullopt;
+
+    uintptr_t currentPC = 0;
+    CodeOrigin currentCodeOrigin(0, nullptr);
+
+    DeltaCompresseionReader pcReader(m_compressedPCs, m_compressedPCBufferSize);
+    DeltaCompresseionReader codeOriginReader(m_compressedCodeOrigins, m_compressedCodeOriginsSize);
+    while (true) {
+        uintptr_t previousPC = currentPC;
+        {
+            uint8_t value = pcReader.read&lt;uint8_t&gt;();
+            uintptr_t delta;
+            if (value == sentinelPCDelta)
+                delta = pcReader.read&lt;uintptr_t&gt;();
+            else
+                delta = value;
+            currentPC += delta;
+        }
+
+        CodeOrigin previousOrigin = currentCodeOrigin;
+        {
+            int8_t value = codeOriginReader.read&lt;int8_t&gt;();
+            intptr_t delta;
+            if (value == sentinelBytecodeDelta)
+                delta = codeOriginReader.read&lt;intptr_t&gt;();
+            else
+                delta = static_cast&lt;intptr_t&gt;(value);
+
+            currentCodeOrigin.bytecodeIndex = static_cast&lt;unsigned&gt;(static_cast&lt;intptr_t&gt;(currentCodeOrigin.bytecodeIndex) + delta);
+
+            int8_t hasInlineFrame = codeOriginReader.read&lt;int8_t&gt;();
+            ASSERT(hasInlineFrame == 0 || hasInlineFrame == 1);
+            if (hasInlineFrame)
+                currentCodeOrigin.inlineCallFrame = bitwise_cast&lt;InlineCallFrame*&gt;(codeOriginReader.read&lt;uintptr_t&gt;());
+            else
+                currentCodeOrigin.inlineCallFrame = nullptr;
+        }
+
+        if (previousPC) {
+            uintptr_t startOfRange = previousPC;
+            // We subtract 1 because we generate end points inclusively in this table, even though we are interested in ranges of the form: [previousPC, currentPC)
+            uintptr_t endOfRange = currentPC - 1;
+            if (startOfRange &lt;= pcAsInt &amp;&amp; pcAsInt &lt;= endOfRange)
+                return Optional&lt;CodeOrigin&gt;(previousOrigin); // We return previousOrigin here because CodeOrigin's are mapped to the startValue of the range.
+        }
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+    return Nullopt;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitPCToCodeOriginMaph"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.h (0 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/PCToCodeOriginMap.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -0,0 +1,104 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PCToCodeOriginMap_h
+#define PCToCodeOriginMap_h
+
+#if ENABLE(JIT)
+
+#include &quot;CodeOrigin.h&quot;
+#include &quot;DFGCommon.h&quot;
+#include &quot;MacroAssembler.h&quot;
+#include &quot;VM.h&quot;
+#include &lt;wtf/Bag.h&gt;
+#include &lt;wtf/Optional.h&gt;
+#include &lt;wtf/RedBlackTree.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC {
+
+#if FTL_USES_B3
+namespace B3 {
+class PCToOriginMap;
+}
+#endif
+
+class LinkBuffer;
+class PCToCodeOriginMapBuilder;
+
+class PCToCodeOriginMapBuilder {
+    WTF_MAKE_NONCOPYABLE(PCToCodeOriginMapBuilder);
+    friend class PCToCodeOriginMap;
+
+public:
+    PCToCodeOriginMapBuilder(VM&amp;);
+    PCToCodeOriginMapBuilder(PCToCodeOriginMapBuilder&amp;&amp; other);
+
+#if FTL_USES_B3
+    PCToCodeOriginMapBuilder(VM&amp;, B3::PCToOriginMap&amp;&amp;);
+#endif
+
+    void appendItem(MacroAssembler::Label, const CodeOrigin&amp;);
+    static CodeOrigin defaultCodeOrigin() { return CodeOrigin(0, nullptr); }
+
+    bool didBuildMapping() const { return m_shouldBuildMapping; }
+
+private:
+
+    struct CodeRange {
+        MacroAssembler::Label start;
+        MacroAssembler::Label end;
+        CodeOrigin codeOrigin;
+    };
+
+    VM&amp; m_vm;
+    Vector&lt;CodeRange&gt; m_codeRanges;
+    bool m_shouldBuildMapping;
+};
+
+class PCToCodeOriginMap {
+    WTF_MAKE_NONCOPYABLE(PCToCodeOriginMap);
+public:
+    PCToCodeOriginMap(PCToCodeOriginMapBuilder&amp;&amp;, LinkBuffer&amp;);
+    ~PCToCodeOriginMap();
+
+    Optional&lt;CodeOrigin&gt; findPC(void* pc) const;
+
+    double memorySize();
+
+private:
+    size_t m_compressedPCBufferSize;
+    size_t m_compressedCodeOriginsSize;
+    uint8_t* m_compressedPCs;
+    uint8_t* m_compressedCodeOrigins;
+    uintptr_t m_pcRangeStart;
+    uintptr_t m_pcRangeEnd;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // PCToCodeOriginMap_h 
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -1643,7 +1643,6 @@
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(exec-&gt;vm().samplingProfiler());
</span><span class="cx">     String jsonString = exec-&gt;vm().samplingProfiler()-&gt;stackTracesAsJSON();
</span><del>-    exec-&gt;vm().samplingProfiler()-&gt;clearData();
</del><span class="cx">     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
</span><span class="cx">     RELEASE_ASSERT(!exec-&gt;hadException());
</span><span class="cx">     return result;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntPCRangesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntPCRanges.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntPCRanges.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/llint/LLIntPCRanges.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -45,6 +45,10 @@
</span><span class="cx">     return llintStart &lt;= pcAsInt &amp;&amp; pcAsInt &lt;= llintEnd;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(JIT)
+static const GPRReg LLIntPC = GPRInfo::regT4;
+#endif
+
</ins><span class="cx"> } } // namespace JSC::LLInt
</span><span class="cx"> 
</span><span class="cx"> #endif // LLIntPCRanges_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -258,7 +258,7 @@
</span><span class="cx">     # - The PC base (or PB for short) must be stored in a callee-save register.
</span><span class="cx">     # - C calls are still given the Instruction* rather than the PC index.
</span><span class="cx">     #   This requires an add before the call, and a sub after.
</span><del>-    const PC = t4
</del><ins>+    const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
</ins><span class="cx">     if ARM64
</span><span class="cx">         const PB = csr7
</span><span class="cx">         const tagTypeNumber = csr8
</span><span class="lines">@@ -290,7 +290,7 @@
</span><span class="cx">     end
</span><span class="cx"> 
</span><span class="cx"> else
</span><del>-    const PC = t4
</del><ins>+    const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
</ins><span class="cx">     macro loadisFromInstruction(offset, dest)
</span><span class="cx">         loadis offset * 4[PC], dest
</span><span class="cx">     end
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -323,6 +323,7 @@
</span><span class="cx">     v(bool, useTypeProfiler, false, nullptr) \
</span><span class="cx">     v(bool, useControlFlowProfiler, false, nullptr) \
</span><span class="cx">     v(bool, useSamplingProfiler, false, nullptr) \
</span><ins>+    v(bool, alwaysGeneratePCToCodeOriginMap, false, &quot;This will make sure we always generate a PCToCodeOriginMap for JITed code.&quot;) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, verifyHeap, false, nullptr) \
</span><span class="cx">     v(unsigned, numberOfGCCyclesToRecordForVerification, 3, nullptr) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSamplingProfilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include &quot;LLIntPCRanges.h&quot;
</span><span class="cx"> #include &quot;MarkedBlock.h&quot;
</span><span class="cx"> #include &quot;MarkedBlockSet.h&quot;
</span><ins>+#include &quot;PCToCodeOriginMap.h&quot;
</ins><span class="cx"> #include &quot;SlotVisitor.h&quot;
</span><span class="cx"> #include &quot;SlotVisitorInlines.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="lines">@@ -49,7 +50,6 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> static double sNumTotalStackTraces = 0;
</span><del>-static double sNumUnverifiedStackTraces = 0;
</del><span class="cx"> static double sNumTotalWalks = 0;
</span><span class="cx"> static double sNumFailedWalks = 0;
</span><span class="cx"> static const uint32_t sNumWalkReportingFrequency = 50;
</span><span class="lines">@@ -58,6 +58,8 @@
</span><span class="cx"> static const bool sReportStats = false;
</span><span class="cx"> 
</span><span class="cx"> using FrameType = SamplingProfiler::FrameType;
</span><ins>+using UnprocessedFrameType = SamplingProfiler::UnprocessedFrameType;
+using UnprocessedStackFrame = SamplingProfiler::UnprocessedStackFrame;
</ins><span class="cx"> 
</span><span class="cx"> ALWAYS_INLINE static void reportStats()
</span><span class="cx"> {
</span><span class="lines">@@ -65,8 +67,6 @@
</span><span class="cx">         if (!sReportStatsOnlyWhenTheyreAboveThreshold || (sNumFailedWalks / sNumTotalWalks &gt; sWalkErrorPercentage)) {
</span><span class="cx">             dataLogF(&quot;Num total walks: %llu. Failed walks percent: %lf\n&quot;,
</span><span class="cx">                 static_cast&lt;uint64_t&gt;(sNumTotalWalks), sNumFailedWalks / sNumTotalWalks);
</span><del>-            dataLogF(&quot;Total stack traces: %llu. Needs verification percent: %lf\n&quot;,
-                static_cast&lt;uint64_t&gt;(sNumTotalStackTraces), sNumUnverifiedStackTraces / sNumTotalStackTraces);
</del><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -82,33 +82,20 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    size_t walk(Vector&lt;SamplingProfiler::StackFrame&gt;&amp; stackTrace, bool&amp; didRunOutOfSpace, bool&amp; stacktraceNeedsVerification)
</del><ins>+    size_t walk(Vector&lt;UnprocessedStackFrame&gt;&amp; stackTrace, bool&amp; didRunOutOfSpace)
</ins><span class="cx">     {
</span><del>-        stacktraceNeedsVerification = false;
</del><span class="cx">         if (sReportStats)
</span><span class="cx">             sNumTotalWalks++;
</span><span class="cx">         resetAtMachineFrame();
</span><span class="cx">         size_t maxStackTraceSize = stackTrace.size();
</span><span class="cx">         while (!isAtTop() &amp;&amp; !m_bailingOut &amp;&amp; m_depth &lt; maxStackTraceSize) {
</span><del>-            while (m_inlineCallFrame &amp;&amp; m_depth &lt; maxStackTraceSize) {
-                CodeBlock* codeBlock = m_inlineCallFrame-&gt;baselineCodeBlock.get();
-                RELEASE_ASSERT(isValidCodeBlock(codeBlock));
-                stackTrace[m_depth] = SamplingProfiler::StackFrame(SamplingProfiler::FrameType::VerifiedExecutable, codeBlock-&gt;ownerExecutable());
-                m_depth++;
-                m_inlineCallFrame = m_inlineCallFrame-&gt;directCaller.inlineCallFrame;
-            }
-
-            if (m_depth &gt;= maxStackTraceSize)
-                break;
-
-            CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
-            if (isValidCodeBlock(codeBlock)) {
-                ExecutableBase* executable = codeBlock-&gt;ownerExecutable();
-                stackTrace[m_depth] = SamplingProfiler::StackFrame(FrameType::VerifiedExecutable,executable);
</del><ins>+            if (CodeBlock* codeBlock = m_callFrame-&gt;codeBlock()) {
+                ASSERT(isValidCodeBlock(codeBlock));
+                stackTrace[m_depth] = UnprocessedStackFrame(codeBlock, m_callFrame-&gt;callSiteIndex());
</ins><span class="cx">             } else {
</span><del>-                stacktraceNeedsVerification = true;
</del><ins>+                RELEASE_ASSERT(codeBlock == nullptr);
</ins><span class="cx">                 JSValue unsafeCallee = m_callFrame-&gt;unsafeCallee();
</span><del>-                stackTrace[m_depth] = SamplingProfiler::StackFrame(FrameType::UnverifiedCallee, JSValue::encode(unsafeCallee));
</del><ins>+                stackTrace[m_depth] = UnprocessedStackFrame(JSValue::encode(unsafeCallee));
</ins><span class="cx">             }
</span><span class="cx">             m_depth++;
</span><span class="cx">             advanceToParentFrame();
</span><span class="lines">@@ -138,8 +125,6 @@
</span><span class="cx"> 
</span><span class="cx">     void resetAtMachineFrame()
</span><span class="cx">     {
</span><del>-        m_inlineCallFrame = nullptr;
-
</del><span class="cx">         if (isAtTop())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="lines">@@ -151,9 +136,6 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-#if ENABLE(DFG_JIT)
-        // If the frame doesn't have a code block, then it's not a 
-        // DFG/FTL frame which means we're not an inlined frame.
</del><span class="cx">         CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
</span><span class="cx">         if (!codeBlock)
</span><span class="cx">             return;
</span><span class="lines">@@ -164,25 +146,6 @@
</span><span class="cx">                 sNumFailedWalks++;
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-
-        // If the code block does not have any code origins, then there's no
-        // inlining. Hence, we're not at an inlined frame.
-        if (!codeBlock-&gt;hasCodeOrigins())
-            return;
-
-        CallSiteIndex index = m_callFrame-&gt;callSiteIndex();
-        if (!codeBlock-&gt;canGetCodeOrigin(index)) {
-            // FIXME:
-            // For the most part, we only fail here when we're looking
-            // at the top most call frame. All other parent call frames
-            // should have set the CallSiteIndex when making a call.
-            //
-            // We should resort to getting information from the PC=&gt;CodeOrigin mapping
-            // once we implement it: https://bugs.webkit.org/show_bug.cgi?id=152629
-            return;
-        }
-        m_inlineCallFrame = codeBlock-&gt;codeOrigin(index).inlineCallFrame;
-#endif // !ENABLE(DFG_JIT)
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool isValidFramePointer(ExecState* exec)
</span><span class="lines">@@ -213,14 +176,12 @@
</span><span class="cx">     const LockHolder&amp; m_codeBlockSetLocker;
</span><span class="cx">     const LockHolder&amp; m_machineThreadsLocker;
</span><span class="cx">     bool m_bailingOut { false };
</span><del>-    InlineCallFrame* m_inlineCallFrame;
</del><span class="cx">     size_t m_depth { 0 };
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> SamplingProfiler::SamplingProfiler(VM&amp; vm, RefPtr&lt;Stopwatch&gt;&amp;&amp; stopwatch)
</span><span class="cx">     : m_vm(vm)
</span><span class="cx">     , m_stopwatch(WTFMove(stopwatch))
</span><del>-    , m_indexOfNextStackTraceToVerify(0)
</del><span class="cx">     , m_timingInterval(std::chrono::microseconds(1000))
</span><span class="cx">     , m_totalTime(0)
</span><span class="cx">     , m_timerQueue(WorkQueue::create(&quot;jsc.sampling-profiler.queue&quot;, WorkQueue::Type::Serial, WorkQueue::QOS::UserInteractive))
</span><span class="lines">@@ -256,23 +217,27 @@
</span><span class="cx">                 // While the JSC thread is suspended, we can't do things like malloc because the JSC thread
</span><span class="cx">                 // may be holding the malloc lock.
</span><span class="cx">                 ExecState* callFrame;
</span><del>-                void* pc;
</del><ins>+                void* machinePC;
+                bool topFrameIsLLInt = false;
+                void* llintPC;
</ins><span class="cx">                 {
</span><span class="cx">                     MachineThreads::Thread::Registers registers;
</span><span class="cx">                     m_jscExecutionThread-&gt;getRegisters(registers);
</span><span class="cx">                     callFrame = static_cast&lt;ExecState*&gt;(registers.framePointer());
</span><del>-                    pc = registers.instructionPointer();
</del><ins>+                    machinePC = registers.instructionPointer();
+                    llintPC = registers.llintPC();
</ins><span class="cx">                     m_jscExecutionThread-&gt;freeRegisters(registers);
</span><span class="cx">                 }
</span><span class="cx">                 // FIXME: Lets have a way of detecting when we're parsing code.
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=152761
</span><del>-                if (m_vm.executableAllocator.isValidExecutableMemory(executableAllocatorLocker, pc)) {
</del><ins>+                if (m_vm.executableAllocator.isValidExecutableMemory(executableAllocatorLocker, machinePC)) {
</ins><span class="cx">                     if (m_vm.isExecutingInRegExpJIT) {
</span><span class="cx">                         // FIXME: We're executing a regexp. Lets gather more intersting data.
</span><span class="cx">                         // https://bugs.webkit.org/show_bug.cgi?id=152729
</span><span class="cx">                         callFrame = m_vm.topCallFrame; // We need to do this or else we'd fail our backtrace validation b/c this isn't a JS frame.
</span><span class="cx">                     }
</span><del>-                } else if (LLInt::isLLIntPC(pc)) {
</del><ins>+                } else if (LLInt::isLLIntPC(machinePC)) {
+                    topFrameIsLLInt = true;
</ins><span class="cx">                     // We're okay to take a normal stack trace when the PC
</span><span class="cx">                     // is in LLInt code.
</span><span class="cx">                 } else {
</span><span class="lines">@@ -284,10 +249,9 @@
</span><span class="cx">                 size_t walkSize;
</span><span class="cx">                 bool wasValidWalk;
</span><span class="cx">                 bool didRunOutOfVectorSpace;
</span><del>-                bool stacktraceNeedsVerification;
</del><span class="cx">                 {
</span><span class="cx">                     FrameWalker walker(callFrame, m_vm, codeBlockSetLocker, machineThreadsLocker);
</span><del>-                    walkSize = walker.walk(m_currentFrames, didRunOutOfVectorSpace, stacktraceNeedsVerification);
</del><ins>+                    walkSize = walker.walk(m_currentFrames, didRunOutOfVectorSpace);
</ins><span class="cx">                     wasValidWalk = walker.wasValidWalk();
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -298,21 +262,16 @@
</span><span class="cx">                 // FIXME: It'd be interesting to take data about the program's state when
</span><span class="cx">                 // we fail to take a stack trace: https://bugs.webkit.org/show_bug.cgi?id=152758
</span><span class="cx">                 if (wasValidWalk &amp;&amp; walkSize) {
</span><del>-                    if (sReportStats) {
</del><ins>+                    if (sReportStats)
</ins><span class="cx">                         sNumTotalStackTraces++;
</span><del>-                        if (stacktraceNeedsVerification)
-                            sNumUnverifiedStackTraces++;
-                    }
-                    Vector&lt;StackFrame&gt; stackTrace;
</del><ins>+                    Vector&lt;UnprocessedStackFrame&gt; stackTrace;
</ins><span class="cx">                     stackTrace.reserveInitialCapacity(walkSize);
</span><span class="cx">                     for (size_t i = 0; i &lt; walkSize; i++) {
</span><del>-                        StackFrame frame = m_currentFrames[i];
-                        stackTrace.uncheckedAppend(frame); 
-                        if (frame.frameType == FrameType::VerifiedExecutable)
-                            m_seenExecutables.add(frame.u.verifiedExecutable);
</del><ins>+                        UnprocessedStackFrame frame = m_currentFrames[i];
+                        stackTrace.uncheckedAppend(frame);
</ins><span class="cx">                     }
</span><span class="cx"> 
</span><del>-                    m_stackTraces.append(StackTrace{ stacktraceNeedsVerification, nowTime, WTFMove(stackTrace) });
</del><ins>+                    m_unprocessedStackTraces.append(UnprocessedStackTrace { nowTime, machinePC, topFrameIsLLInt, llintPC, WTFMove(stackTrace) });
</ins><span class="cx"> 
</span><span class="cx">                     if (didRunOutOfVectorSpace)
</span><span class="cx">                         m_currentFrames.grow(m_currentFrames.size() * 1.25);
</span><span class="lines">@@ -332,6 +291,30 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static ALWAYS_INLINE unsigned tryGetBytecodeIndex(unsigned llintPC, CodeBlock* codeBlock, bool&amp; isValid)
+{
+    RELEASE_ASSERT(!codeBlock-&gt;hasCodeOrigins());
+
+#if USE(JSVALUE64)
+    unsigned bytecodeIndex = llintPC;
+    if (bytecodeIndex &lt; codeBlock-&gt;instructionCount()) {
+        isValid = true;
+        return bytecodeIndex;
+    }
+    isValid = false;
+    return 0;
+#else
+    Instruction* instruction = bitwise_cast&lt;Instruction*&gt;(llintPC);
+    if (instruction &gt;= codeBlock-&gt;instructions().begin() &amp;&amp; instruction &lt; codeBlock-&gt;instructions().begin() + codeBlock-&gt;instructionCount()) {
+        isValid = true;
+        unsigned bytecodeIndex = instruction - codeBlock-&gt;instructions().begin();
+        return bytecodeIndex;
+    }
+    isValid = false;
+    return 0;
+#endif
+}
+
</ins><span class="cx"> void SamplingProfiler::processUnverifiedStackTraces()
</span><span class="cx"> {
</span><span class="cx">     // This function needs to be called from the JSC execution thread.
</span><span class="lines">@@ -340,22 +323,30 @@
</span><span class="cx">     TinyBloomFilter filter = m_vm.heap.objectSpace().blocks().filter();
</span><span class="cx">     MarkedBlockSet&amp; markedBlockSet = m_vm.heap.objectSpace().blocks();
</span><span class="cx"> 
</span><del>-    for (unsigned i = m_indexOfNextStackTraceToVerify; i &lt; m_stackTraces.size(); i++) {
-        StackTrace&amp; stackTrace = m_stackTraces[i]; 
-        if (!stackTrace.needsVerification)
-            continue;
-        stackTrace.needsVerification = false;
</del><ins>+    for (UnprocessedStackTrace&amp; unprocessedStackTrace : m_unprocessedStackTraces) {
+        m_stackTraces.append(StackTrace());
+        StackTrace&amp; stackTrace = m_stackTraces.last();
+        stackTrace.timestamp = unprocessedStackTrace.timestamp;
</ins><span class="cx"> 
</span><del>-        for (StackFrame&amp; stackFrame : stackTrace.frames) {
-            if (stackFrame.frameType != FrameType::UnverifiedCallee) {
-                RELEASE_ASSERT(stackFrame.frameType == FrameType::VerifiedExecutable);
-                continue;
</del><ins>+        auto appendCodeBlock = [&amp;] (CodeBlock* codeBlock, unsigned bytecodeIndex) {
+            stackTrace.frames.append(StackFrame(codeBlock-&gt;ownerExecutable()));
+            m_seenExecutables.add(codeBlock-&gt;ownerExecutable());
+
+            if (bytecodeIndex &lt; codeBlock-&gt;instructionCount()) {
+                int divot;
+                int startOffset;
+                int endOffset;
+                codeBlock-&gt;expressionRangeForBytecodeOffset(bytecodeIndex, divot, startOffset, endOffset,
+                    stackTrace.frames.last().lineNumber, stackTrace.frames.last().columnNumber);
</ins><span class="cx">             }
</span><ins>+        };
</ins><span class="cx"> 
</span><del>-            JSValue callee = JSValue::decode(stackFrame.u.unverifiedCallee);
</del><ins>+        auto appendUnverifiedCallee = [&amp;] (JSValue callee) {
+            stackTrace.frames.append(StackFrame());
+            StackFrame&amp; stackFrame = stackTrace.frames.last();
</ins><span class="cx">             if (!Heap::isValueGCObject(filter, markedBlockSet, callee)) {
</span><span class="cx">                 stackFrame.frameType = FrameType::Unknown;
</span><del>-                continue;
</del><ins>+                return;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             JSCell* calleeCell = callee.asCell();
</span><span class="lines">@@ -372,22 +363,88 @@
</span><span class="cx"> 
</span><span class="cx">             if (calleeCell-&gt;type() != JSFunctionType) {
</span><span class="cx">                 stackFrame.frameType = frameTypeFromCallData();
</span><del>-                continue;
</del><ins>+                return;
</ins><span class="cx">             }
</span><span class="cx">             ExecutableBase* executable = static_cast&lt;JSFunction*&gt;(calleeCell)-&gt;executable();
</span><span class="cx">             if (!executable) {
</span><span class="cx">                 stackFrame.frameType = frameTypeFromCallData();
</span><del>-                continue;
</del><ins>+                return;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             RELEASE_ASSERT(Heap::isPointerGCObject(filter, markedBlockSet, executable));
</span><del>-            stackFrame.frameType = FrameType::VerifiedExecutable;
-            stackFrame.u.verifiedExecutable = executable;
</del><ins>+            stackFrame.frameType = FrameType::Executable;
+            stackFrame.executable = executable;
</ins><span class="cx">             m_seenExecutables.add(executable);
</span><ins>+        };
+
+        // Prepend the top-most inlined frame if needed and gather
+        // location information about where the top frame is executing.
+        size_t startIndex = 0;
+        if (unprocessedStackTrace.frames.size() &amp;&amp; unprocessedStackTrace.frames[0].frameType == UnprocessedFrameType::VerifiedCodeBlock) {
+            CodeBlock* topCodeBlock = unprocessedStackTrace.frames[0].u.verifiedCodeBlock;
+            if (unprocessedStackTrace.topFrameIsLLInt) {
+                // We reuse LLInt CodeBlocks for the baseline JIT, so we need to check for both jit types.
+                // This might also be false for various reasons (known and unknown), even though
+                // it's super unlikely. One reason that this can be false is when we throw from a DFG frame,
+                // and we end up having to unwind past a VMEntryFrame, we will end up executing
+                // inside the LLInt's handleUncaughtException. So we just protect against this
+                // by ignoring it.
+                unsigned bytecodeIndex = 0;
+                if (topCodeBlock-&gt;jitType() == JITCode::InterpreterThunk || topCodeBlock-&gt;jitType() == JITCode::BaselineJIT) {
+                    bool isValidPC;
+                    unsigned bits;
+#if USE(JSVALUE64)
+                    bits = static_cast&lt;unsigned&gt;(bitwise_cast&lt;uintptr_t&gt;(unprocessedStackTrace.llintPC));
+#else
+                    bits = bitwise_cast&lt;unsigned&gt;(unprocessedStackTrace.llintPC);
+#endif
+                    bytecodeIndex = tryGetBytecodeIndex(bits, topCodeBlock, isValidPC);
+
+                    UNUSED_PARAM(isValidPC); // FIXME: do something with this info for the web inspector: https://bugs.webkit.org/show_bug.cgi?id=153455
+
+                    appendCodeBlock(topCodeBlock, bytecodeIndex);
+                    startIndex = 1;
+                }
+            } else if (Optional&lt;CodeOrigin&gt; codeOrigin = topCodeBlock-&gt;findPC(unprocessedStackTrace.topPC)) {
+                codeOrigin-&gt;walkUpInlineStack([&amp;] (const CodeOrigin&amp; codeOrigin) {
+                    appendCodeBlock(codeOrigin.inlineCallFrame ? codeOrigin.inlineCallFrame-&gt;baselineCodeBlock.get() : topCodeBlock, codeOrigin.bytecodeIndex);
+                });
+                startIndex = 1;
+            }
</ins><span class="cx">         }
</span><ins>+
+        for (size_t i = startIndex; i &lt; unprocessedStackTrace.frames.size(); i++) {
+            UnprocessedStackFrame&amp; unprocessedStackFrame = unprocessedStackTrace.frames[i];
+            if (unprocessedStackFrame.frameType == UnprocessedFrameType::VerifiedCodeBlock) {
+                CodeBlock* codeBlock = unprocessedStackFrame.u.verifiedCodeBlock;
+                CallSiteIndex callSiteIndex = unprocessedStackFrame.callSiteIndex;
+
+                auto appendCodeBlockNoInlining = [&amp;] {
+                    bool isValidPC;
+                    appendCodeBlock(codeBlock, tryGetBytecodeIndex(callSiteIndex.bits(), codeBlock, isValidPC));
+                };
+
+#if ENABLE(DFG_JIT)
+                if (codeBlock-&gt;hasCodeOrigins()) {
+                    if (codeBlock-&gt;canGetCodeOrigin(callSiteIndex)) {
+                        codeBlock-&gt;codeOrigin(callSiteIndex).walkUpInlineStack([&amp;] (const CodeOrigin&amp; codeOrigin) {
+                            appendCodeBlock(codeOrigin.inlineCallFrame ? codeOrigin.inlineCallFrame-&gt;baselineCodeBlock.get() : codeBlock, codeOrigin.bytecodeIndex);
+                        });
+                    } else
+                        appendCodeBlock(codeBlock, std::numeric_limits&lt;unsigned&gt;::max());
+                } else
+                    appendCodeBlockNoInlining();
+#else
+                appendCodeBlockNoInlining();
+#endif
+            } else {
+                ASSERT(unprocessedStackFrame.frameType == UnprocessedFrameType::UnverifiedCallee);
+                appendUnverifiedCallee(JSValue::decode(unprocessedStackFrame.u.unverifiedCallee));
+            }
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_indexOfNextStackTraceToVerify = m_stackTraces.size();
</del><ins>+    m_unprocessedStackTraces.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SamplingProfiler::visit(SlotVisitor&amp; slotVisitor)
</span><span class="lines">@@ -478,18 +535,12 @@
</span><span class="cx">     dispatchIfNecessary(locker);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SamplingProfiler::clearData()
-{
-    LockHolder locker(m_lock);
-    clearData(locker);
-}
-
</del><span class="cx"> void SamplingProfiler::clearData(const LockHolder&amp;)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_lock.isLocked());
</span><span class="cx">     m_stackTraces.clear();
</span><span class="cx">     m_seenExecutables.clear();
</span><del>-    m_indexOfNextStackTraceToVerify = 0;
</del><ins>+    m_unprocessedStackTraces.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String SamplingProfiler::StackFrame::displayName()
</span><span class="lines">@@ -498,9 +549,7 @@
</span><span class="cx">         return ASCIILiteral(&quot;(unknown)&quot;);
</span><span class="cx">     if (frameType == FrameType::Host)
</span><span class="cx">         return ASCIILiteral(&quot;(host)&quot;);
</span><del>-    RELEASE_ASSERT(frameType != FrameType::UnverifiedCallee);
</del><span class="cx"> 
</span><del>-    ExecutableBase* executable = u.verifiedExecutable;
</del><span class="cx">     if (executable-&gt;isHostFunction())
</span><span class="cx">         return static_cast&lt;NativeExecutable*&gt;(executable)-&gt;name();
</span><span class="cx"> 
</span><span class="lines">@@ -521,9 +570,7 @@
</span><span class="cx">         return ASCIILiteral(&quot;(unknown)&quot;);
</span><span class="cx">     if (frameType == FrameType::Host)
</span><span class="cx">         return ASCIILiteral(&quot;(host)&quot;);
</span><del>-    RELEASE_ASSERT(frameType != FrameType::UnverifiedCallee);
</del><span class="cx"> 
</span><del>-    ExecutableBase* executable = u.verifiedExecutable;
</del><span class="cx">     if (executable-&gt;isHostFunction())
</span><span class="cx">         return static_cast&lt;NativeExecutable*&gt;(executable)-&gt;name();
</span><span class="cx"> 
</span><span class="lines">@@ -544,25 +591,21 @@
</span><span class="cx">     return String();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-int SamplingProfiler::StackFrame::startLine()
</del><ins>+int SamplingProfiler::StackFrame::functionStartLine()
</ins><span class="cx"> {
</span><span class="cx">     if (frameType == FrameType::Unknown || frameType == FrameType::Host)
</span><span class="cx">         return -1;
</span><del>-    RELEASE_ASSERT(frameType != FrameType::UnverifiedCallee);
</del><span class="cx"> 
</span><del>-    ExecutableBase* executable = u.verifiedExecutable;
</del><span class="cx">     if (executable-&gt;isHostFunction())
</span><span class="cx">         return -1;
</span><span class="cx">     return static_cast&lt;ScriptExecutable*&gt;(executable)-&gt;firstLine();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned SamplingProfiler::StackFrame::startColumn()
</del><ins>+unsigned SamplingProfiler::StackFrame::functionStartColumn()
</ins><span class="cx"> {
</span><span class="cx">     if (frameType == FrameType::Unknown || frameType == FrameType::Host)
</span><span class="cx">         return -1;
</span><del>-    RELEASE_ASSERT(frameType != FrameType::UnverifiedCallee);
</del><span class="cx"> 
</span><del>-    ExecutableBase* executable = u.verifiedExecutable;
</del><span class="cx">     if (executable-&gt;isHostFunction())
</span><span class="cx">         return -1;
</span><span class="cx"> 
</span><span class="lines">@@ -573,9 +616,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (frameType == FrameType::Unknown || frameType == FrameType::Host)
</span><span class="cx">         return -1;
</span><del>-    RELEASE_ASSERT(frameType != FrameType::UnverifiedCallee);
</del><span class="cx"> 
</span><del>-    ExecutableBase* executable = u.verifiedExecutable;
</del><span class="cx">     if (executable-&gt;isHostFunction())
</span><span class="cx">         return -1;
</span><span class="cx"> 
</span><span class="lines">@@ -586,9 +627,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (frameType == FrameType::Unknown || frameType == FrameType::Host)
</span><span class="cx">         return emptyString();
</span><del>-    RELEASE_ASSERT(frameType != FrameType::UnverifiedCallee);
</del><span class="cx"> 
</span><del>-    ExecutableBase* executable = u.verifiedExecutable;
</del><span class="cx">     if (executable-&gt;isHostFunction())
</span><span class="cx">         return emptyString();
</span><span class="cx"> 
</span><span class="lines">@@ -598,7 +637,7 @@
</span><span class="cx">     return url;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Vector&lt;SamplingProfiler::StackTrace&gt;&amp; SamplingProfiler::stackTraces(const LockHolder&amp;)
</del><ins>+Vector&lt;SamplingProfiler::StackTrace&gt; SamplingProfiler::releaseStackTraces(const LockHolder&amp; locker)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_lock.isLocked());
</span><span class="cx">     {
</span><span class="lines">@@ -606,7 +645,9 @@
</span><span class="cx">         processUnverifiedStackTraces();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return m_stackTraces;
</del><ins>+    Vector&lt;StackTrace&gt; result(WTFMove(m_stackTraces));
+    clearData(locker);
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String SamplingProfiler::stackTracesAsJSON()
</span><span class="lines">@@ -643,6 +684,8 @@
</span><span class="cx"> 
</span><span class="cx">     json.appendLiteral(&quot;]&quot;);
</span><span class="cx"> 
</span><ins>+    clearData(locker);
+
</ins><span class="cx">     return json.toString();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -655,12 +698,9 @@
</span><span class="cx"> void printInternal(PrintStream&amp; out, SamplingProfiler::FrameType frameType)
</span><span class="cx"> {
</span><span class="cx">     switch (frameType) {
</span><del>-    case SamplingProfiler::FrameType::VerifiedExecutable:
-        out.print(&quot;VerifiedExecutable&quot;);
</del><ins>+    case SamplingProfiler::FrameType::Executable:
+        out.print(&quot;Executable&quot;);
</ins><span class="cx">         break;
</span><del>-    case SamplingProfiler::FrameType::UnverifiedCallee:
-        out.print(&quot;UnverifiedCallee&quot;);
-        break;
</del><span class="cx">     case SamplingProfiler::FrameType::Host:
</span><span class="cx">         out.print(&quot;Host&quot;);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSamplingProfilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SamplingProfiler.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SamplingProfiler.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/runtime/SamplingProfiler.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -44,48 +44,88 @@
</span><span class="cx"> class SamplingProfiler : public ThreadSafeRefCounted&lt;SamplingProfiler&gt; {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    enum class FrameType { 
-        VerifiedExecutable, 
</del><ins>+
+    enum class UnprocessedFrameType { 
</ins><span class="cx">         UnverifiedCallee,
</span><del>-        Host, 
-        Unknown 
</del><ins>+        VerifiedCodeBlock
</ins><span class="cx">     };
</span><span class="cx"> 
</span><del>-    struct StackFrame {
-        StackFrame(FrameType frameType, EncodedJSValue callee)
-            : frameType(frameType)
</del><ins>+    struct UnprocessedStackFrame {
+        UnprocessedStackFrame(EncodedJSValue callee)
+            : frameType(UnprocessedFrameType::UnverifiedCallee)
</ins><span class="cx">         {
</span><span class="cx">             u.unverifiedCallee = callee;
</span><span class="cx">         }
</span><del>-        StackFrame(FrameType frameType, ExecutableBase* executable)
-            : frameType(frameType)
</del><ins>+        UnprocessedStackFrame(CodeBlock* codeBlock, CallSiteIndex callSiteIndex)
+            : frameType(UnprocessedFrameType::VerifiedCodeBlock)
+            , callSiteIndex(callSiteIndex)
</ins><span class="cx">         {
</span><del>-            u.verifiedExecutable = executable;
</del><ins>+            u.unverifiedCallee = JSValue::encode(JSValue());
+            u.verifiedCodeBlock = codeBlock;
</ins><span class="cx">         }
</span><del>-        StackFrame()
-            : frameType(FrameType::Unknown)
</del><ins>+        UnprocessedStackFrame()
+            : frameType(UnprocessedFrameType::UnverifiedCallee)
</ins><span class="cx">         {
</span><del>-            u.verifiedExecutable = nullptr;
</del><ins>+            u.unverifiedCallee = JSValue::encode(JSValue());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        FrameType frameType;
</del><ins>+        UnprocessedFrameType frameType;
</ins><span class="cx">         union {
</span><span class="cx">             EncodedJSValue unverifiedCallee;
</span><del>-            ExecutableBase* verifiedExecutable;
</del><ins>+            CodeBlock* verifiedCodeBlock;
</ins><span class="cx">         } u;
</span><ins>+        CallSiteIndex callSiteIndex;
+    };
</ins><span class="cx"> 
</span><ins>+    enum class FrameType { 
+        Executable,
+        Host,
+        Unknown 
+    };
+
+    struct StackFrame {
+        StackFrame(ExecutableBase* executable)
+            : frameType(FrameType::Executable)
+            , executable(executable)
+        { }
+        StackFrame()
+            : frameType(FrameType::Unknown)
+            , executable(nullptr)
+        { }
+
+        FrameType frameType;
+        ExecutableBase* executable;
+
+        // These attempt to be expression-level line and column number.
+        unsigned lineNumber { std::numeric_limits&lt;unsigned&gt;::max() };
+        unsigned columnNumber { std::numeric_limits&lt;unsigned&gt;::max() };
+
+        // These are function-level data.
</ins><span class="cx">         String displayName();
</span><span class="cx">         String displayNameForJSONTests(); // Used for JSC stress tests because they want the &quot;(anonymous function)&quot; string for anonymous functions and they want &quot;(eval)&quot; for eval'd code.
</span><del>-        int startLine();
-        unsigned startColumn();
</del><ins>+        int functionStartLine();
+        unsigned functionStartColumn();
</ins><span class="cx">         intptr_t sourceID();
</span><span class="cx">         String url();
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    struct UnprocessedStackTrace {
+        double timestamp;
+        void* topPC;
+        bool topFrameIsLLInt;
+        void* llintPC;
+        Vector&lt;UnprocessedStackFrame&gt; frames;
+    };
+
</ins><span class="cx">     struct StackTrace {
</span><del>-        bool needsVerification;
</del><span class="cx">         double timestamp;
</span><span class="cx">         Vector&lt;StackFrame&gt; frames;
</span><ins>+        StackTrace()
+        { }
+        StackTrace(StackTrace&amp;&amp; other)
+            : timestamp(other.timestamp)
+            , frames(WTFMove(other.frames))
+        { }
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     SamplingProfiler(VM&amp;, RefPtr&lt;Stopwatch&gt;&amp;&amp;);
</span><span class="lines">@@ -100,12 +140,10 @@
</span><span class="cx">     void start(const LockHolder&amp;);
</span><span class="cx">     void stop();
</span><span class="cx">     void stop(const LockHolder&amp;);
</span><del>-    Vector&lt;StackTrace&gt;&amp; stackTraces(const LockHolder&amp;);
</del><ins>+    Vector&lt;StackTrace&gt; releaseStackTraces(const LockHolder&amp;);
</ins><span class="cx">     JS_EXPORT_PRIVATE String stackTracesAsJSON();
</span><span class="cx">     JS_EXPORT_PRIVATE void noticeCurrentThreadAsJSCExecutionThread();
</span><span class="cx">     void noticeCurrentThreadAsJSCExecutionThread(const LockHolder&amp;);
</span><del>-    JS_EXPORT_PRIVATE void clearData();
-    void clearData(const LockHolder&amp;);
</del><span class="cx">     void processUnverifiedStackTraces(); // You should call this only after acquiring the lock.
</span><span class="cx">     double totalTime(const LockHolder&amp;) { return m_totalTime; }
</span><span class="cx">     void setStopWatch(const LockHolder&amp;, Ref&lt;Stopwatch&gt;&amp;&amp; stopwatch) { m_stopwatch = WTFMove(stopwatch); }
</span><span class="lines">@@ -114,11 +152,12 @@
</span><span class="cx">     void dispatchIfNecessary(const LockHolder&amp;);
</span><span class="cx">     void dispatchFunction(const LockHolder&amp;);
</span><span class="cx">     void pause();
</span><ins>+    void clearData(const LockHolder&amp;);
</ins><span class="cx"> 
</span><span class="cx">     VM&amp; m_vm;
</span><span class="cx">     RefPtr&lt;Stopwatch&gt; m_stopwatch;
</span><span class="cx">     Vector&lt;StackTrace&gt; m_stackTraces;
</span><del>-    size_t m_indexOfNextStackTraceToVerify;
</del><ins>+    Vector&lt;UnprocessedStackTrace&gt; m_unprocessedStackTraces;
</ins><span class="cx">     std::chrono::microseconds m_timingInterval;
</span><span class="cx">     double m_lastTime;
</span><span class="cx">     double m_totalTime;
</span><span class="lines">@@ -130,7 +169,7 @@
</span><span class="cx">     bool m_isPaused;
</span><span class="cx">     bool m_hasDispatchedFunction;
</span><span class="cx">     HashSet&lt;ExecutableBase*&gt; m_seenExecutables;
</span><del>-    Vector&lt;StackFrame&gt; m_currentFrames;
</del><ins>+    Vector&lt;UnprocessedStackFrame&gt; m_currentFrames;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -312,11 +312,15 @@
</span><span class="cx">         enableControlFlowProfiler();
</span><span class="cx"> #if ENABLE(SAMPLING_PROFILER)
</span><span class="cx">     if (Options::useSamplingProfiler()) {
</span><ins>+        setShouldBuildPCToCodeOriginMapping();
</ins><span class="cx">         m_samplingProfiler = adoptRef(new SamplingProfiler(*this, Stopwatch::create()));
</span><span class="cx">         m_samplingProfiler-&gt;start();
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(SAMPLING_PROFILER)
</span><span class="cx"> 
</span><ins>+    if (Options::alwaysGeneratePCToCodeOriginMap())
+        setShouldBuildPCToCodeOriginMapping();
+
</ins><span class="cx">     if (Options::watchdog()) {
</span><span class="cx">         std::chrono::milliseconds timeoutMillis(Options::watchdog());
</span><span class="cx">         Watchdog&amp; watchdog = ensureWatchdog();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -597,6 +597,9 @@
</span><span class="cx"> 
</span><span class="cx">     inline bool shouldTriggerTermination(ExecState*);
</span><span class="cx"> 
</span><ins>+    void setShouldBuildPCToCodeOriginMapping() { m_shouldBuildPCToCodeOriginMapping = true; }
+    bool shouldBuilderPCToCodeOriginMapping() const { return m_shouldBuildPCToCodeOriginMapping; }
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="cx">     friend class ClearExceptionScope;
</span><span class="lines">@@ -648,6 +651,7 @@
</span><span class="cx">     bool m_failNextNewCodeBlock { false };
</span><span class="cx">     bool m_inDefineOwnProperty;
</span><span class="cx">     bool m_shouldRewriteConstAsVar { false };
</span><ins>+    bool m_shouldBuildPCToCodeOriginMapping { false };
</ins><span class="cx">     std::unique_ptr&lt;CodeCache&gt; m_codeCache;
</span><span class="cx">     LegacyProfiler* m_enabledProfiler;
</span><span class="cx">     std::unique_ptr&lt;BuiltinExecutables&gt; m_builtinExecutables;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssamplingprofilerbasicjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/sampling-profiler-basic.js (195864 => 195865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sampling-profiler-basic.js        2016-01-30 00:34:47 UTC (rev 195864)
+++ trunk/Source/JavaScriptCore/tests/stress/sampling-profiler-basic.js        2016-01-30 01:11:05 UTC (rev 195865)
</span><span class="lines">@@ -26,11 +26,8 @@
</span><span class="cx">             x--;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    noInline(top);
-    // FIXME: We need to call top() to get the CallSiteIndex to update
-    // inside the call frame. We need to fix that by having a PC=&gt;CodeOrigin
-    // mapping: https://bugs.webkit.org/show_bug.cgi?id=152629
-    function jaz(x) { return x + top(); } // 
</del><ins>+
+    function jaz(x) { return x + top(); }
</ins><span class="cx">     function kaz(y) {
</span><span class="cx">         return jaz(y) + 5;
</span><span class="cx">     }
</span></span></pre>
</div>
</div>

</body>
</html>