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

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

<h3>Log Message</h3>
<pre>Optimize B3-&gt;Air lowering of Fence on ARM
https://bugs.webkit.org/show_bug.cgi?id=162342

Reviewed by Geoffrey Garen.

This gives us comprehensive support for standalone fences on x86 and ARM. The changes are as
follows:

- Sets in stone the rule that the heaps of a B3::Fence tell you what the fence protects. If the
  fence reads, it protects motion of stores. If the fence writes, it protects motion of loads.
  This allows us to express for example load-load fences in a portable way: on x86 they will just
  block B3 optimizations and emit no code, while on ARM you will get some fence.

- Adds comprehensive support for WTF-style fences in the ARM assembler. I simplified it just a bit
  to match what B3, the main client, knows. There are three fences: MemoryFence, StoreFence, and
  LoadFence. On x86, MemoryFence is ortop while StoreFence and LoadFence emit no code. On ARM64,
  MemoryFence and LoadFence are dmb ish while StoreFence is dmb ishst.

- Tests! To test this, I needed to teach the disassembler how to disassemble dmb ish and dmb
  ishst. I think that the canonical way to do it would be to create a group for dmb and then teach
  that group how to decode the operands. But I don't actually know what are all of the ways of
  encoding dmb, so I'd rather that unrecognized encodings fall through to the &quot;.long blah&quot;
  bailout. So, this creates explicit matching rules for &quot;dmb ish&quot; and &quot;dmb ishst&quot;, which is the
  most conservative thing we can do.

* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::dmbISH):
(JSC::ARM64Assembler::dmbISHST):
(JSC::ARM64Assembler::dmbSY): Deleted.
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::memoryFence):
(JSC::MacroAssemblerARM64::storeFence):
(JSC::MacroAssemblerARM64::loadFence):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::storeFence):
(JSC::MacroAssemblerX86Common::loadFence):
* b3/B3FenceValue.h:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::testMemoryFence):
(JSC::B3::testStoreFence):
(JSC::B3::testLoadFence):
(JSC::B3::run):
(JSC::B3::testX86MFence): Deleted.
(JSC::B3::testX86CompilerFence): Deleted.
* disassembler/ARM64/A64DOpcode.cpp:
(JSC::ARM64Disassembler::A64DOpcodeDmbIsh::format):
(JSC::ARM64Disassembler::A64DOpcodeDmbIshSt::format):
* disassembler/ARM64/A64DOpcode.h:
(JSC::ARM64Disassembler::A64DOpcodeDmbIsh::opName):
(JSC::ARM64Disassembler::A64DOpcodeDmbIshSt::opName):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerARM64Assemblerh">trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3FenceValueh">trunk/Source/JavaScriptCore/b3/B3FenceValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerToAircpp">trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOpcodeopcodes">trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredisassemblerARM64A64DOpcodecpp">trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredisassemblerARM64A64DOpcodeh">trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2016-09-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Optimize B3-&gt;Air lowering of Fence on ARM
+        https://bugs.webkit.org/show_bug.cgi?id=162342
+
+        Reviewed by Geoffrey Garen.
+
+        This gives us comprehensive support for standalone fences on x86 and ARM. The changes are as
+        follows:
+
+        - Sets in stone the rule that the heaps of a B3::Fence tell you what the fence protects. If the
+          fence reads, it protects motion of stores. If the fence writes, it protects motion of loads.
+          This allows us to express for example load-load fences in a portable way: on x86 they will just
+          block B3 optimizations and emit no code, while on ARM you will get some fence.
+
+        - Adds comprehensive support for WTF-style fences in the ARM assembler. I simplified it just a bit
+          to match what B3, the main client, knows. There are three fences: MemoryFence, StoreFence, and
+          LoadFence. On x86, MemoryFence is ortop while StoreFence and LoadFence emit no code. On ARM64,
+          MemoryFence and LoadFence are dmb ish while StoreFence is dmb ishst.
+
+        - Tests! To test this, I needed to teach the disassembler how to disassemble dmb ish and dmb
+          ishst. I think that the canonical way to do it would be to create a group for dmb and then teach
+          that group how to decode the operands. But I don't actually know what are all of the ways of
+          encoding dmb, so I'd rather that unrecognized encodings fall through to the &quot;.long blah&quot;
+          bailout. So, this creates explicit matching rules for &quot;dmb ish&quot; and &quot;dmb ishst&quot;, which is the
+          most conservative thing we can do.
+
+        * assembler/ARM64Assembler.h:
+        (JSC::ARM64Assembler::dmbISH):
+        (JSC::ARM64Assembler::dmbISHST):
+        (JSC::ARM64Assembler::dmbSY): Deleted.
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::memoryFence):
+        (JSC::MacroAssemblerARM64::storeFence):
+        (JSC::MacroAssemblerARM64::loadFence):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::storeFence):
+        (JSC::MacroAssemblerX86Common::loadFence):
+        * b3/B3FenceValue.h:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::testMemoryFence):
+        (JSC::B3::testStoreFence):
+        (JSC::B3::testLoadFence):
+        (JSC::B3::run):
+        (JSC::B3::testX86MFence): Deleted.
+        (JSC::B3::testX86CompilerFence): Deleted.
+        * disassembler/ARM64/A64DOpcode.cpp:
+        (JSC::ARM64Disassembler::A64DOpcodeDmbIsh::format):
+        (JSC::ARM64Disassembler::A64DOpcodeDmbIshSt::format):
+        * disassembler/ARM64/A64DOpcode.h:
+        (JSC::ARM64Disassembler::A64DOpcodeDmbIsh::opName):
+        (JSC::ARM64Disassembler::A64DOpcodeDmbIshSt::opName):
+
</ins><span class="cx"> 2016-09-28  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Adopt #pragma once in some generated resources
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerARM64Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -1496,11 +1496,16 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    ALWAYS_INLINE void dmbSY()
</del><ins>+    ALWAYS_INLINE void dmbISH()
</ins><span class="cx">     {
</span><del>-        insn(0xd5033fbf);
</del><ins>+        insn(0xd5033bbf);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void dmbISHST()
+    {
+        insn(0xd5033abf);
+    }
+
</ins><span class="cx">     template&lt;int datasize&gt;
</span><span class="cx">     ALWAYS_INLINE void orn(RegisterID rd, RegisterID rn, RegisterID rm)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -3215,12 +3215,27 @@
</span><span class="cx">         m_assembler.nop();
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // We take memoryFence to mean acqrel. This has acqrel semantics on ARM64.
</ins><span class="cx">     void memoryFence()
</span><span class="cx">     {
</span><del>-        m_assembler.dmbSY();
</del><ins>+        m_assembler.dmbISH();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // We take this to mean that it prevents motion of normal stores. That's a store fence on ARM64 (hence the &quot;ST&quot;).
+    void storeFence()
+    {
+        m_assembler.dmbISHST();
+    }
</ins><span class="cx"> 
</span><ins>+    // We take this to mean that it prevents motion of normal loads. Ideally we'd have expressed this
+    // using dependencies or half fences, but there are cases where this is as good as it gets. The only
+    // way to get a standalone load fence instruction on ARM is to use the ISH fence, which is just like
+    // the memoryFence().
+    void loadFence()
+    {
+        m_assembler.dmbISH();
+    }
+
</ins><span class="cx">     // Misc helper functions.
</span><span class="cx"> 
</span><span class="cx">     // Invert a relational condition, e.g. == becomes !=, &lt; becomes &gt;=, etc.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -2636,6 +2636,16 @@
</span><span class="cx">         m_assembler.orl_im(0, 0, X86Registers::esp);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // We take this to mean that it prevents motion of normal stores. So, it's a no-op on x86.
+    void storeFence()
+    {
+    }
+
+    // We take this to mean that it prevents motion of normal loads. So, it's a no-op on x86.
+    void loadFence()
+    {
+    }
+
</ins><span class="cx">     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
</span><span class="cx">     {
</span><span class="cx">         X86Assembler::replaceWithJump(instructionStart.executableAddress(), destination.executableAddress());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3FenceValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3FenceValue.h (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3FenceValue.h        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/b3/B3FenceValue.h        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -41,7 +41,9 @@
</span><span class="cx">     // The read/write heaps are reflected in the effects() of this value. The compiler may change
</span><span class="cx">     // the lowering of a Fence based on the heaps. For example, if a fence does not write anything
</span><span class="cx">     // then it is understood to be a store-store fence. On x86, this may lead us to not emit any
</span><del>-    // code, while on ARM we may emit a cheaper fence (dmb ishst instead of dmb ish).
</del><ins>+    // code, while on ARM we may emit a cheaper fence (dmb ishst instead of dmb ish). We will do
+    // the same optimization for load-load fences, which are expressed as a Fence that writes but
+    // does not read.
</ins><span class="cx">     //
</span><span class="cx">     // This abstraction allows us to cover all of the fences on x86 and all of the standalone fences
</span><span class="cx">     // on ARM. X86 really just has one fence: mfence. This fence should be used to protect stores
</span><span class="lines">@@ -65,7 +67,6 @@
</span><span class="cx">     // On ARM there are many more fences. The Fence instruction is meant to model just two of them:
</span><span class="cx">     // dmb ish and dmb ishst. You can emit a dmb ishst by using a Fence with an empty write heap.
</span><span class="cx">     // Otherwise, you will get a dmb ish.
</span><del>-    // FIXME: Make this work right on ARM. https://bugs.webkit.org/show_bug.cgi?id=162342
</del><span class="cx">     // FIXME: Add fenced memory accesses. https://bugs.webkit.org/show_bug.cgi?id=162349
</span><span class="cx">     // FIXME: Add a Depend operation. https://bugs.webkit.org/show_bug.cgi?id=162350
</span><span class="cx">     HeapRange read { HeapRange::top() };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -2049,10 +2049,18 @@
</span><span class="cx">             
</span><span class="cx">         case Fence: {
</span><span class="cx">             FenceValue* fence = m_value-&gt;as&lt;FenceValue&gt;();
</span><del>-            if (isX86() &amp;&amp; !fence-&gt;write)
</del><ins>+            if (!fence-&gt;write &amp;&amp; !fence-&gt;read)
</ins><span class="cx">                 return;
</span><del>-            // FIXME: Optimize this on ARM.
-            // https://bugs.webkit.org/show_bug.cgi?id=162342
</del><ins>+            if (!fence-&gt;write) {
+                // A fence that reads but does not write is for protecting motion of stores.
+                append(StoreFence);
+                return;
+            }
+            if (!fence-&gt;read) {
+                // A fence that writes but does not read is for protecting motion of loads.
+                append(LoadFence);
+                return;
+            }
</ins><span class="cx">             append(MemoryFence);
</span><span class="cx">             return;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -844,6 +844,8 @@
</span><span class="cx">     DoubleCond, Tmp, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> MemoryFence /effects
</span><ins>+StoreFence /effects
+LoadFence /effects
</ins><span class="cx"> 
</span><span class="cx"> Jump /branch
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -13052,7 +13052,7 @@
</span><span class="cx">     CHECK_EQ(invoke&lt;int&gt;(*code, -1), 666);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void testX86MFence()
</del><ins>+void testMemoryFence()
</ins><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="cx">     
</span><span class="lines">@@ -13059,14 +13059,19 @@
</span><span class="cx">     BasicBlock* root = proc.addBlock();
</span><span class="cx">     
</span><span class="cx">     root-&gt;appendNew&lt;FenceValue&gt;(proc, Origin());
</span><del>-    root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin());
</del><ins>+    root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin(), root-&gt;appendIntConstant(proc, Origin(), Int32, 42));
</ins><span class="cx">     
</span><span class="cx">     auto code = compile(proc);
</span><del>-    checkUsesInstruction(*code, &quot;lock or $0x0, (%rsp)&quot;);
</del><ins>+    CHECK_EQ(invoke&lt;int&gt;(*code), 42);
+    if (isX86())
+        checkUsesInstruction(*code, &quot;lock or $0x0, (%rsp)&quot;);
+    if (isARM64())
+        checkUsesInstruction(*code, &quot;dmb    ish&quot;);
</ins><span class="cx">     checkDoesNotUseInstruction(*code, &quot;mfence&quot;);
</span><ins>+    checkDoesNotUseInstruction(*code, &quot;dmb    ishst&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void testX86CompilerFence()
</del><ins>+void testStoreFence()
</ins><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="cx">     
</span><span class="lines">@@ -13073,13 +13078,34 @@
</span><span class="cx">     BasicBlock* root = proc.addBlock();
</span><span class="cx">     
</span><span class="cx">     root-&gt;appendNew&lt;FenceValue&gt;(proc, Origin(), HeapRange::top(), HeapRange());
</span><del>-    root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin());
</del><ins>+    root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin(), root-&gt;appendIntConstant(proc, Origin(), Int32, 42));
</ins><span class="cx">     
</span><span class="cx">     auto code = compile(proc);
</span><ins>+    CHECK_EQ(invoke&lt;int&gt;(*code), 42);
</ins><span class="cx">     checkDoesNotUseInstruction(*code, &quot;lock&quot;);
</span><span class="cx">     checkDoesNotUseInstruction(*code, &quot;mfence&quot;);
</span><ins>+    if (isARM64())
+        checkUsesInstruction(*code, &quot;dmb    ishst&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testLoadFence()
+{
+    Procedure proc;
+    
+    BasicBlock* root = proc.addBlock();
+    
+    root-&gt;appendNew&lt;FenceValue&gt;(proc, Origin(), HeapRange(), HeapRange::top());
+    root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin(), root-&gt;appendIntConstant(proc, Origin(), Int32, 42));
+    
+    auto code = compile(proc);
+    CHECK_EQ(invoke&lt;int&gt;(*code), 42);
+    checkDoesNotUseInstruction(*code, &quot;lock&quot;);
+    checkDoesNotUseInstruction(*code, &quot;mfence&quot;);
+    if (isARM64())
+        checkUsesInstruction(*code, &quot;dmb    ish&quot;);
+    checkDoesNotUseInstruction(*code, &quot;dmb    ishst&quot;);
+}
+
</ins><span class="cx"> // Make sure the compiler does not try to optimize anything out.
</span><span class="cx"> NEVER_INLINE double zero()
</span><span class="cx"> {
</span><span class="lines">@@ -14510,8 +14536,6 @@
</span><span class="cx">         RUN(testBranchBitAndImmFusion(Load, Int32, 1, Air::BranchTest32, Air::Arg::Addr));
</span><span class="cx">         RUN(testBranchBitAndImmFusion(Load, Int64, 1, Air::BranchTest32, Air::Arg::Addr));
</span><span class="cx">         
</span><del>-        RUN(testX86MFence());
-        RUN(testX86CompilerFence());
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (isARM64()) {
</span><span class="lines">@@ -14519,6 +14543,10 @@
</span><span class="cx">         RUN(testTernarySubInstructionSelection(Trunc, Int32, Air::Sub32));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    RUN(testMemoryFence());
+    RUN(testStoreFence());
+    RUN(testLoadFence());
+    
</ins><span class="cx">     if (tasks.isEmpty())
</span><span class="cx">         usage();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredisassemblerARM64A64DOpcodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -84,6 +84,8 @@
</span><span class="cx">     OPCODE_GROUP_ENTRY(0x15, A64DOpcodeConditionalBranchImmediate),
</span><span class="cx">     OPCODE_GROUP_ENTRY(0x15, A64DOpcodeCompareAndBranchImmediate),
</span><span class="cx">     OPCODE_GROUP_ENTRY(0x15, A64DOpcodeHint),
</span><ins>+    OPCODE_GROUP_ENTRY(0x15, A64DOpcodeDmbIsh),
+    OPCODE_GROUP_ENTRY(0x15, A64DOpcodeDmbIshSt),
</ins><span class="cx">     OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchImmediate),
</span><span class="cx">     OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchRegister),
</span><span class="cx">     OPCODE_GROUP_ENTRY(0x16, A64DOpcodeTestAndBranchImmediate),
</span><span class="lines">@@ -823,6 +825,20 @@
</span><span class="cx">     return m_formatBuffer;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const char* A64DOpcodeDmbIsh::format()
+{
+    appendInstructionName(&quot;dmb&quot;);
+    appendString(&quot;ish&quot;);
+    return m_formatBuffer;
+}
+
+const char* A64DOpcodeDmbIshSt::format()
+{
+    appendInstructionName(&quot;dmb&quot;);
+    appendString(&quot;ishst&quot;);
+    return m_formatBuffer;
+}
+
</ins><span class="cx"> // A zero in an entry of the table means the instruction is Unallocated
</span><span class="cx"> const char* const A64DOpcodeLoadStore::s_opNames[32] = {
</span><span class="cx">     &quot;strb&quot;, &quot;ldrb&quot;, &quot;ldrsb&quot;, &quot;ldrsb&quot;, &quot;str&quot;, &quot;ldr&quot;, &quot;str&quot;, &quot;ldr&quot;,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredisassemblerARM64A64DOpcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h (206538 => 206539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h        2016-09-28 20:19:47 UTC (rev 206538)
+++ trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h        2016-09-28 20:30:44 UTC (rev 206539)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -509,6 +509,30 @@
</span><span class="cx">     unsigned immediate7() { return (m_opcode &gt;&gt; 5) &amp; 0x7f; }
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class A64DOpcodeDmbIsh : public A64DOpcode {
+public:
+    static const uint32_t mask = 0xffffffff;
+    static const uint32_t pattern = 0xd5033bbf;
+
+    DEFINE_STATIC_FORMAT(A64DOpcodeDmbIsh, thisObj);
+
+    const char* format();
+
+    const char* opName() { return &quot;dmb&quot;; }
+};
+
+class A64DOpcodeDmbIshSt : public A64DOpcode {
+public:
+    static const uint32_t mask = 0xffffffff;
+    static const uint32_t pattern = 0xd5033abf;
+
+    DEFINE_STATIC_FORMAT(A64DOpcodeDmbIshSt, thisObj);
+
+    const char* format();
+
+    const char* opName() { return &quot;dmb&quot;; }
+};
+
</ins><span class="cx"> class A64DOpcodeLoadStore : public A64DOpcode {
</span><span class="cx"> private:
</span><span class="cx">     static const char* const s_opNames[32];
</span></span></pre>
</div>
</div>

</body>
</html>