<!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>[213753] trunk/Source</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/213753">213753</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2017-03-10 23:17:48 -0800 (Fri, 10 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>The JITs should be able to emit fast TLS loads
https://bugs.webkit.org/show_bug.cgi?id=169483

Reviewed by Keith Miller.
        
Source/JavaScriptCore:

Added loadFromTLS32/64/Ptr to the MacroAssembler and added a B3 test for this.

* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::mrs_TPIDRRO_EL0):
* assembler/MacroAssembler.h:
(JSC::MacroAssembler::loadFromTLSPtr):
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::loadFromTLS32):
(JSC::MacroAssemblerARM64::loadFromTLS64):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::loadFromTLS32):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::loadFromTLS64):
* assembler/X86Assembler.h:
(JSC::X86Assembler::adcl_im):
(JSC::X86Assembler::addl_mr):
(JSC::X86Assembler::addl_im):
(JSC::X86Assembler::andl_im):
(JSC::X86Assembler::orl_im):
(JSC::X86Assembler::orl_rm):
(JSC::X86Assembler::subl_im):
(JSC::X86Assembler::cmpb_im):
(JSC::X86Assembler::cmpl_rm):
(JSC::X86Assembler::cmpl_im):
(JSC::X86Assembler::testb_im):
(JSC::X86Assembler::movb_i8m):
(JSC::X86Assembler::movb_rm):
(JSC::X86Assembler::movl_mr):
(JSC::X86Assembler::movq_mr):
(JSC::X86Assembler::movsxd_rr):
(JSC::X86Assembler::gs):
(JSC::X86Assembler::X86InstructionFormatter::SingleInstructionBufferWriter::memoryModRM):
* b3/testb3.cpp:
(JSC::B3::testFastTLS):
(JSC::B3::run):

Source/WTF:

Consolidated what we know about fast TLS in FastTLS.h.

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/FastTLS.h: Added.
(WTF::loadFastTLS):
(WTF::fastTLSOffsetForKey):
* wtf/Platform.h:
* wtf/WTFThreadData.cpp:
(WTF::WTFThreadData::createAndRegisterForGetspecificDirect):
* wtf/WTFThreadData.h:
(WTF::wtfThreadData):</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="#trunkSourceJavaScriptCoreassemblerMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/MacroAssembler.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="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerX86Assemblerh">trunk/Source/JavaScriptCore/assembler/X86Assembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFWTFxcodeprojprojectpbxproj">trunk/Source/WTF/WTF.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWTFwtfCMakeListstxt">trunk/Source/WTF/wtf/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWTFwtfPlatformh">trunk/Source/WTF/wtf/Platform.h</a></li>
<li><a href="#trunkSourceWTFwtfWTFThreadDatacpp">trunk/Source/WTF/wtf/WTFThreadData.cpp</a></li>
<li><a href="#trunkSourceWTFwtfWTFThreadDatah">trunk/Source/WTF/wtf/WTFThreadData.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWTFwtfFastTLSh">trunk/Source/WTF/wtf/FastTLS.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -1,3 +1,46 @@
</span><ins>+2017-03-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        The JITs should be able to emit fast TLS loads
+        https://bugs.webkit.org/show_bug.cgi?id=169483
+
+        Reviewed by Keith Miller.
+        
+        Added loadFromTLS32/64/Ptr to the MacroAssembler and added a B3 test for this.
+
+        * assembler/ARM64Assembler.h:
+        (JSC::ARM64Assembler::mrs_TPIDRRO_EL0):
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::loadFromTLSPtr):
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::loadFromTLS32):
+        (JSC::MacroAssemblerARM64::loadFromTLS64):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::loadFromTLS32):
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::loadFromTLS64):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::adcl_im):
+        (JSC::X86Assembler::addl_mr):
+        (JSC::X86Assembler::addl_im):
+        (JSC::X86Assembler::andl_im):
+        (JSC::X86Assembler::orl_im):
+        (JSC::X86Assembler::orl_rm):
+        (JSC::X86Assembler::subl_im):
+        (JSC::X86Assembler::cmpb_im):
+        (JSC::X86Assembler::cmpl_rm):
+        (JSC::X86Assembler::cmpl_im):
+        (JSC::X86Assembler::testb_im):
+        (JSC::X86Assembler::movb_i8m):
+        (JSC::X86Assembler::movb_rm):
+        (JSC::X86Assembler::movl_mr):
+        (JSC::X86Assembler::movq_mr):
+        (JSC::X86Assembler::movsxd_rr):
+        (JSC::X86Assembler::gs):
+        (JSC::X86Assembler::X86InstructionFormatter::SingleInstructionBufferWriter::memoryModRM):
+        * b3/testb3.cpp:
+        (JSC::B3::testFastTLS):
+        (JSC::B3::run):
+
</ins><span class="cx"> 2017-03-10  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix watch and tv builds after r213294
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerARM64Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -1588,6 +1588,13 @@
</span><span class="cx">         CHECK_DATASIZE();
</span><span class="cx">         insn(exoticStore(MEMOPSIZE, ExoticStoreFence_Release, result, src, dst));
</span><span class="cx">     }
</span><ins>+    
+#if ENABLE(FAST_TLS_JIT)
+    void mrs_TPIDRRO_EL0(RegisterID dst)
+    {
+        insn(0xd53bd060 | dst); // Thanks, otool -t!
+    }
+#endif
</ins><span class="cx"> 
</span><span class="cx">     template&lt;int datasize&gt;
</span><span class="cx">     ALWAYS_INLINE void orn(RegisterID rd, RegisterID rn, RegisterID rm)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssembler.h (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -627,6 +627,13 @@
</span><span class="cx">         load32(address, dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if ENABLE(FAST_TLS_JIT)
+    void loadFromTLSPtr(uint32_t offset, RegisterID dst)
+    {
+        loadFromTLS32(offset, dst);
+    }
+#endif
+
</ins><span class="cx">     DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         return load32WithAddressOffsetPatch(address, dest);
</span><span class="lines">@@ -934,6 +941,13 @@
</span><span class="cx">         load64(address, dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if ENABLE(FAST_TLS_JIT)
+    void loadFromTLSPtr(uint32_t offset, RegisterID dst)
+    {
+        loadFromTLS64(offset, dst);
+    }
+#endif
+
</ins><span class="cx">     DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         return load64WithAddressOffsetPatch(address, dest);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -3598,6 +3598,24 @@
</span><span class="cx">         m_assembler.eor&lt;64&gt;(dest, src, src);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+#if ENABLE(FAST_TLS_JIT)
+    // This will use scratch registers if the offset is not legal.
+    
+    void loadFromTLS32(uint32_t offset, RegisterID dst)
+    {
+        m_assembler.mrs_TPIDRRO_EL0(dst);
+        and64(TrustedImm32(~7), dst);
+        load32(Address(dst, offset), dst);
+    }
+    
+    void loadFromTLS64(uint32_t offset, RegisterID dst)
+    {
+        m_assembler.mrs_TPIDRRO_EL0(dst);
+        and64(TrustedImm32(~7), dst);
+        load64(Address(dst, offset), dst);
+    }
+#endif // ENABLE(FAST_TLS_JIT)
+    
</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 (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -3857,6 +3857,14 @@
</span><span class="cx">     void loadFence()
</span><span class="cx">     {
</span><span class="cx">     }
</span><ins>+    
+#if ENABLE(FAST_TLS_JIT)
+    void loadFromTLS32(uint32_t offset, RegisterID dst)
+    {
+        m_assembler.gs();
+        m_assembler.movl_mr(offset, dst);
+    }
+#endif
</ins><span class="cx"> 
</span><span class="cx">     static void replaceWithBreakpoint(CodeLocationLabel instructionStart)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -1701,6 +1701,14 @@
</span><span class="cx">         store64(imm, dest);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+#if ENABLE(FAST_TLS_JIT)
+    void loadFromTLS64(uint32_t offset, RegisterID dst)
+    {
+        m_assembler.gs();
+        m_assembler.movl_mr(offset, dst);
+    }
+#endif
+
</ins><span class="cx">     void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         m_assembler.cvttsd2siq_rr(src, dest);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerX86Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/X86Assembler.h (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -218,6 +218,7 @@
</span><span class="cx"> #if CPU(X86_64)
</span><span class="cx">         OP_MOVSXD_GvEv                  = 0x63,
</span><span class="cx"> #endif
</span><ins>+        PRE_GS                          = 0x65,
</ins><span class="cx">         PRE_OPERAND_SIZE                = 0x66,
</span><span class="cx">         PRE_SSE_66                      = 0x66,
</span><span class="cx">         OP_PUSH_Iz                      = 0x68,
</span><span class="lines">@@ -431,10 +432,10 @@
</span><span class="cx">     void adcl_im(int imm, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         if (CAN_SIGN_EXTEND_8_32(imm)) {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_ADC, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate8(imm);
</span><span class="cx">         } else {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADC, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_ADC, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate32(imm);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -458,7 +459,7 @@
</span><span class="cx"> #if !CPU(X86_64)
</span><span class="cx">     void addl_mr(const void* addr, RegisterID dst)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_ADD_GvEv, dst, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_ADD_GvEv, dst, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -631,10 +632,10 @@
</span><span class="cx">     void addl_im(int imm, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         if (CAN_SIGN_EXTEND_8_32(imm)) {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_ADD, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate8(imm);
</span><span class="cx">         } else {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_ADD, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate32(imm);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -818,10 +819,10 @@
</span><span class="cx">     void andl_im(int imm, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         if (CAN_SIGN_EXTEND_8_32(imm)) {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_AND, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate8(imm);
</span><span class="cx">         } else {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_AND, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate32(imm);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -1159,10 +1160,10 @@
</span><span class="cx">     void orl_im(int imm, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         if (CAN_SIGN_EXTEND_8_32(imm)) {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_OR, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate8(imm);
</span><span class="cx">         } else {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_OR, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate32(imm);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -1169,7 +1170,7 @@
</span><span class="cx"> 
</span><span class="cx">     void orl_rm(RegisterID src, const void* addr)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_OR_EvGv, src, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_OR_EvGv, src, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -1357,10 +1358,10 @@
</span><span class="cx">     void subl_im(int imm, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         if (CAN_SIGN_EXTEND_8_32(imm)) {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_SUB, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate8(imm);
</span><span class="cx">         } else {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_SUB, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate32(imm);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -1857,7 +1858,7 @@
</span><span class="cx"> #if CPU(X86)
</span><span class="cx">     void cmpb_im(int imm, const void* addr)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_GROUP1_EbIb, GROUP1_OP_CMP, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">         m_formatter.immediate8(imm);
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="lines">@@ -1938,16 +1939,16 @@
</span><span class="cx"> #else
</span><span class="cx">     void cmpl_rm(RegisterID reg, const void* addr)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_CMP_EvGv, reg, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void cmpl_im(int imm, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         if (CAN_SIGN_EXTEND_8_32(imm)) {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIb, GROUP1_OP_CMP, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate8(imm);
</span><span class="cx">         } else {
</span><del>-            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_GROUP1_EvIz, GROUP1_OP_CMP, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">             m_formatter.immediate32(imm);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -2025,7 +2026,7 @@
</span><span class="cx"> #if CPU(X86)
</span><span class="cx">     void testb_im(int imm, const void* addr)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_GROUP3_EbIb, GROUP3_OP_TEST, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">         m_formatter.immediate8(imm);
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="lines">@@ -2279,7 +2280,7 @@
</span><span class="cx">     void movb_i8m(int imm, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(-128 &lt;= imm &amp;&amp; imm &lt; 128);
</span><del>-        m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_GROUP11_EvIb, GROUP11_MOV, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">         m_formatter.immediate8(imm);
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="lines">@@ -2301,7 +2302,7 @@
</span><span class="cx"> #if !CPU(X86_64)
</span><span class="cx">     void movb_rm(RegisterID src, const void* addr)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_MOV_EbGb, src, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_MOV_EbGb, src, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="lines">@@ -2354,6 +2355,11 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void movl_mr(uint32_t addr, RegisterID dst)
+    {
+        m_formatter.oneByteOpAddr(OP_MOV_GvEv, dst, addr);
+    }
+
</ins><span class="cx"> #if CPU(X86_64)
</span><span class="cx">     void movq_rr(RegisterID src, RegisterID dst)
</span><span class="cx">     {
</span><span class="lines">@@ -2407,6 +2413,11 @@
</span><span class="cx">         m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void movq_mr(uint32_t addr, RegisterID dst)
+    {
+        m_formatter.oneByteOp64Addr(OP_MOV_GvEv, dst, addr);
+    }
+
</ins><span class="cx">     void movq_i32m(int imm, int offset, RegisterID base)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
</span><span class="lines">@@ -2435,28 +2446,26 @@
</span><span class="cx">     {
</span><span class="cx">         m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src);
</span><span class="cx">     }
</span><del>-    
-    
</del><span class="cx"> #else
</span><ins>+    void movl_mr(const void* addr, RegisterID dst)
+    {
+        if (dst == X86Registers::eax)
+            movl_mEAX(addr);
+        else
+            m_formatter.oneByteOpAddr(OP_MOV_GvEv, dst, bitwise_cast&lt;uint32_t&gt;(addr));
+    }
+
</ins><span class="cx">     void movl_rm(RegisterID src, const void* addr)
</span><span class="cx">     {
</span><span class="cx">         if (src == X86Registers::eax)
</span><span class="cx">             movl_EAXm(addr);
</span><span class="cx">         else 
</span><del>-            m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
</del><ins>+            m_formatter.oneByteOpAddr(OP_MOV_EvGv, src, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    void movl_mr(const void* addr, RegisterID dst)
-    {
-        if (dst == X86Registers::eax)
-            movl_mEAX(addr);
-        else
-            m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
-    }
-
</del><span class="cx">     void movl_i32m(int imm, const void* addr)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
</del><ins>+        m_formatter.oneByteOpAddr(OP_GROUP11_EvIz, GROUP11_MOV, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">         m_formatter.immediate32(imm);
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="lines">@@ -2494,7 +2503,7 @@
</span><span class="cx"> #if !CPU(X86_64)
</span><span class="cx">     void movzbl_mr(const void* address, RegisterID dst)
</span><span class="cx">     {
</span><del>-        m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, address);
</del><ins>+        m_formatter.twoByteOpAddr(OP2_MOVZX_GvEb, dst, bitwise_cast&lt;uint32_t&gt;(address));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -2604,7 +2613,7 @@
</span><span class="cx"> #else
</span><span class="cx">     void cmovl_mr(Condition cond, const void* addr, RegisterID dst)
</span><span class="cx">     {
</span><del>-        m_formatter.twoByteOp(cmovcc(cond), dst, addr);
</del><ins>+        m_formatter.twoByteOpAddr(cmovcc(cond), dst, bitwise_cast&lt;uint32_t&gt;(addr));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -2677,7 +2686,7 @@
</span><span class="cx"> #if !CPU(X86_64)
</span><span class="cx">     void jmp_m(const void* address)
</span><span class="cx">     {
</span><del>-        m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, address);
</del><ins>+        m_formatter.oneByteOpAddr(OP_GROUP5_Ev, GROUP5_OP_JMPN, bitwise_cast&lt;uint32_t&gt;(address));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -2853,7 +2862,7 @@
</span><span class="cx">     void addsd_mr(const void* address, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F2);
</span><del>-        m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, address);
</del><ins>+        m_formatter.twoByteOpAddr(OP2_ADDSD_VsdWsd, (RegisterID)dst, bitwise_cast&lt;uint32_t&gt;(address));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -2911,7 +2920,7 @@
</span><span class="cx">     void cvtsi2sd_mr(const void* address, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F2);
</span><del>-        m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address);
</del><ins>+        m_formatter.twoByteOpAddr(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, bitwise_cast&lt;uint32_t&gt;(address));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -3068,12 +3077,12 @@
</span><span class="cx">     void movsd_mr(const void* address, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F2);
</span><del>-        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
</del><ins>+        m_formatter.twoByteOpAddr(OP2_MOVSD_VsdWsd, (RegisterID)dst, bitwise_cast&lt;uint32_t&gt;(address));
</ins><span class="cx">     }
</span><span class="cx">     void movsd_rm(XMMRegisterID src, const void* address)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F2);
</span><del>-        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, address);
</del><ins>+        m_formatter.twoByteOpAddr(OP2_MOVSD_WsdVsd, (RegisterID)src, bitwise_cast&lt;uint32_t&gt;(address));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -3400,6 +3409,15 @@
</span><span class="cx">         m_formatter.prefix(PRE_LOCK);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // Causes the memory access in the next instruction to be offset by %gs. Usually you use
+    // this with a 32-bit absolute address load. That &quot;address&quot; ends up being the offset to
+    // %gs. This prefix is ignored by lea. Getting the value of %gs is hard - you can pretty
+    // much just use it as a secret offset.
+    void gs()
+    {
+        m_formatter.prefix(PRE_GS);
+    }
+    
</ins><span class="cx">     void cmpxchgb_rm(RegisterID src, int offset, RegisterID base)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.twoByteOp8(OP2_CMPXCHGb, src, base, offset);
</span><span class="lines">@@ -4053,14 +4071,17 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-#if !CPU(X86_64)
-            ALWAYS_INLINE void memoryModRM(int reg, const void* address)
</del><ins>+            ALWAYS_INLINE void memoryModRMAddr(int reg, uint32_t address)
</ins><span class="cx">             {
</span><ins>+#if CPU(X86_64)
+                putModRmSib(ModRmMemoryNoDisp, reg, noBase, noIndex, 0);
+#else
</ins><span class="cx">                 // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
</span><span class="cx">                 putModRm(ModRmMemoryNoDisp, reg, noBase);
</span><del>-                putIntUnchecked(reinterpret_cast&lt;int32_t&gt;(address));
</del><ins>+#endif
+                putIntUnchecked(address);
</ins><span class="cx">             }
</span><del>-#endif
</del><ins>+
</ins><span class="cx">             ALWAYS_INLINE void twoBytesVex(OneByteOpcodeID simdPrefix, RegisterID inOpReg, RegisterID r)
</span><span class="cx">             {
</span><span class="cx">                 putByteUnchecked(VexPrefix::TwoBytes);
</span><span class="lines">@@ -4185,14 +4206,12 @@
</span><span class="cx">             writer.memoryModRM(reg, base, index, scale, offset);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-#if !CPU(X86_64)
-        void oneByteOp(OneByteOpcodeID opcode, int reg, const void* address)
</del><ins>+        void oneByteOpAddr(OneByteOpcodeID opcode, int reg, uint32_t address)
</ins><span class="cx">         {
</span><span class="cx">             SingleInstructionBufferWriter writer(m_buffer);
</span><span class="cx">             writer.putByteUnchecked(opcode);
</span><del>-            writer.memoryModRM(reg, address);
</del><ins>+            writer.memoryModRMAddr(reg, address);
</ins><span class="cx">         }
</span><del>-#endif
</del><span class="cx"> 
</span><span class="cx">         void twoByteOp(TwoByteOpcodeID opcode)
</span><span class="cx">         {
</span><span class="lines">@@ -4228,15 +4247,14 @@
</span><span class="cx">             writer.memoryModRM(reg, base, index, scale, offset);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-#if !CPU(X86_64)
-        void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address)
</del><ins>+        void twoByteOpAddr(TwoByteOpcodeID opcode, int reg, uint32_t address)
</ins><span class="cx">         {
</span><span class="cx">             SingleInstructionBufferWriter writer(m_buffer);
</span><span class="cx">             writer.putByteUnchecked(OP_2BYTE_ESCAPE);
</span><span class="cx">             writer.putByteUnchecked(opcode);
</span><del>-            writer.memoryModRM(reg, address);
</del><ins>+            writer.memoryModRMAddr(reg, address);
</ins><span class="cx">         }
</span><del>-#endif
</del><ins>+
</ins><span class="cx">         void vexNdsLigWigTwoByteOp(OneByteOpcodeID simdPrefix, TwoByteOpcodeID opcode, RegisterID dest, RegisterID a, RegisterID b)
</span><span class="cx">         {
</span><span class="cx">             SingleInstructionBufferWriter writer(m_buffer);
</span><span class="lines">@@ -4367,6 +4385,14 @@
</span><span class="cx">             writer.memoryModRM(reg, base, index, scale, offset);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        void oneByteOp64Addr(OneByteOpcodeID opcode, int reg, uint32_t address)
+        {
+            SingleInstructionBufferWriter writer(m_buffer);
+            writer.emitRexW(reg, 0, 0);
+            writer.putByteUnchecked(opcode);
+            writer.memoryModRMAddr(reg, address);
+        }
+
</ins><span class="cx">         void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
</span><span class="cx">         {
</span><span class="cx">             SingleInstructionBufferWriter writer(m_buffer);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -69,6 +69,7 @@
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> #include &lt;cmath&gt;
</span><span class="cx"> #include &lt;string&gt;
</span><ins>+#include &lt;wtf/FastTLS.h&gt;
</ins><span class="cx"> #include &lt;wtf/ListDump.h&gt;
</span><span class="cx"> #include &lt;wtf/Lock.h&gt;
</span><span class="cx"> #include &lt;wtf/NumberOfCores.h&gt;
</span><span class="lines">@@ -15210,6 +15211,28 @@
</span><span class="cx">         CHECK_EQ(numToStore, value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testFastTLS()
+{
+#if ENABLE(FAST_TLS_JIT)
+    _pthread_setspecific_direct(WTF_TESTING_KEY, bitwise_cast&lt;void*&gt;(static_cast&lt;uintptr_t&gt;(0xbeef)));
+    
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    
+    PatchpointValue* patchpoint = root-&gt;appendNew&lt;PatchpointValue&gt;(proc, pointerType(), Origin());
+    patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
+    patchpoint-&gt;setGenerator(
+        [&amp;] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp; params) {
+            AllowMacroScratchRegisterUsage allowScratch(jit);
+            jit.loadFromTLSPtr(fastTLSOffsetForKey(WTF_TESTING_KEY), params[0].gpr());
+        });
+    
+    root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin(), patchpoint);
+    
+    CHECK_EQ(compileAndRun&lt;uintptr_t&gt;(proc), static_cast&lt;uintptr_t&gt;(0xbeef));
+#endif
+}
+
</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">@@ -16736,6 +16759,8 @@
</span><span class="cx">     RUN(testWasmBoundsCheck(10000));
</span><span class="cx">     RUN(testWasmBoundsCheck(std::numeric_limits&lt;unsigned&gt;::max() - 5));
</span><span class="cx">     RUN(testWasmAddress());
</span><ins>+    
+    RUN(testFastTLS());
</ins><span class="cx"> 
</span><span class="cx">     if (isX86()) {
</span><span class="cx">         RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp));
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/WTF/ChangeLog        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2017-03-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        The JITs should be able to emit fast TLS loads
+        https://bugs.webkit.org/show_bug.cgi?id=169483
+
+        Reviewed by Keith Miller.
+        
+        Consolidated what we know about fast TLS in FastTLS.h.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/FastTLS.h: Added.
+        (WTF::loadFastTLS):
+        (WTF::fastTLSOffsetForKey):
+        * wtf/Platform.h:
+        * wtf/WTFThreadData.cpp:
+        (WTF::WTFThreadData::createAndRegisterForGetspecificDirect):
+        * wtf/WTFThreadData.h:
+        (WTF::wtfThreadData):
+
</ins><span class="cx"> 2017-03-10  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Turn ENABLE(MASM_PROBE) on by default for OS(DARWIN) release builds.
</span></span></pre></div>
<a id="trunkSourceWTFWTFxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx">                 0F66B2921DC97BAB004A1D3F /* WallTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F66B2881DC97BAB004A1D3F /* WallTime.cpp */; };
</span><span class="cx">                 0F66B2931DC97BAB004A1D3F /* WallTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66B2891DC97BAB004A1D3F /* WallTime.h */; };
</span><span class="cx">                 0F725CAC1C50461600AD943A /* RangeSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CAB1C50461600AD943A /* RangeSet.h */; };
</span><ins>+                0F79C7C41E73511800EB34D1 /* FastTLS.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F79C7C31E73511800EB34D1 /* FastTLS.h */; };
</ins><span class="cx">                 0F7C5FB61D885CF20044F5E2 /* FastBitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7C5FB51D885CF20044F5E2 /* FastBitVector.cpp */; };
</span><span class="cx">                 0F824A681B7443A0002E345D /* ParkingLot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F824A641B7443A0002E345D /* ParkingLot.cpp */; };
</span><span class="cx">                 0F824A691B7443A0002E345D /* ParkingLot.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F824A651B7443A0002E345D /* ParkingLot.h */; };
</span><span class="lines">@@ -421,6 +422,7 @@
</span><span class="cx">                 0F66B2881DC97BAB004A1D3F /* WallTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WallTime.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F66B2891DC97BAB004A1D3F /* WallTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WallTime.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F725CAB1C50461600AD943A /* RangeSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RangeSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F79C7C31E73511800EB34D1 /* FastTLS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FastTLS.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F7C5FB51D885CF20044F5E2 /* FastBitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FastBitVector.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F824A641B7443A0002E345D /* ParkingLot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParkingLot.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F824A651B7443A0002E345D /* ParkingLot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParkingLot.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -974,6 +976,7 @@
</span><span class="cx">                                 0FD81AC4154FB22E00983E72 /* FastBitVector.h */,
</span><span class="cx">                                 A8A472A1151A825A004123FF /* FastMalloc.cpp */,
</span><span class="cx">                                 A8A472A2151A825A004123FF /* FastMalloc.h */,
</span><ins>+                                0F79C7C31E73511800EB34D1 /* FastTLS.h */,
</ins><span class="cx">                                 B38FD7BC168953E80065C969 /* FeatureDefines.h */,
</span><span class="cx">                                 0F9D335B165DBA73005AD387 /* FilePrintStream.cpp */,
</span><span class="cx">                                 0F9D335C165DBA73005AD387 /* FilePrintStream.h */,
</span><span class="lines">@@ -1486,6 +1489,7 @@
</span><span class="cx">                                 0F0D85B417234CC100338210 /* NoLock.h in Headers */,
</span><span class="cx">                                 A8A473EF151A825B004123FF /* Noncopyable.h in Headers */,
</span><span class="cx">                                 CE46516E19DB1FB4003ECA05 /* NSMapTableSPI.h in Headers */,
</span><ins>+                                0F79C7C41E73511800EB34D1 /* FastTLS.h in Headers */,
</ins><span class="cx">                                 A8A473F5151A825B004123FF /* NumberOfCores.h in Headers */,
</span><span class="cx">                                 7E29C33E15FFD79B00516D61 /* ObjcRuntimeExtras.h in Headers */,
</span><span class="cx">                                 1AFDE6531953B23D00C48FFA /* Optional.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWTFwtfCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CMakeLists.txt (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CMakeLists.txt        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/WTF/wtf/CMakeLists.txt        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx">     DisallowCType.h
</span><span class="cx">     DoublyLinkedList.h
</span><span class="cx">     FastMalloc.h
</span><ins>+    FastTLS.h
</ins><span class="cx">     FeatureDefines.h
</span><span class="cx">     FilePrintStream.h
</span><span class="cx">     FlipBytes.h
</span></span></pre></div>
<a id="trunkSourceWTFwtfFastTLSh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/FastTLS.h (0 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/FastTLS.h                                (rev 0)
+++ trunk/Source/WTF/wtf/FastTLS.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if HAVE(FAST_TLS)
+
+#include &lt;pthread.h&gt;
+#include &lt;System/pthread_machdep.h&gt;
+
+namespace WTF {
+
+// __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0 is taken by bmalloc, so WTF's KEY0 maps to the
+// system's KEY1.
+#define WTF_FAST_TLS_KEY0 __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1
+#define WTF_FAST_TLS_KEY1 __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY2
+#define WTF_FAST_TLS_KEY2 __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY3
+#define WTF_FAST_TLS_KEY3 __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4
+
+// NOTE: We should manage our use of these keys here. If you want to use a key for something,
+// put a #define in here to give your key a symbolic name. This ensures that we don't
+// accidentally use the same key for more than one thing.
+
+#define WTF_THREAD_DATA_KEY WTF_FAST_TLS_KEY0
+#define WTF_TESTING_KEY WTF_FAST_TLS_KEY3
+
+#if ENABLE(FAST_TLS_JIT)
+// Below is the code that the JIT will emit.
+
+#if CPU(X86_64)
+inline uintptr_t loadFastTLS(unsigned offset)
+{
+    uintptr_t result;
+    asm volatile(
+        &quot;movq %%gs:%1, %0&quot;
+        : &quot;=r&quot;(result)
+        : &quot;r&quot;(offset)
+        : &quot;memory&quot;);
+    return result;
+}
+#elif CPU(ARM64)
+inline uintptr_t loadFastTLS(unsigned passedOffset)
+{
+    uintptr_t result;
+    uintptr_t offset = passedOffset;
+    asm volatile(
+        &quot;mrs %0, TPIDRRO_EL0\n\t&quot;
+        &quot;and %0, %0, #0xfffffffffffffff8\n\t&quot;
+        &quot;ldr %0, [%0, %1]&quot;
+        : &quot;=r&quot;(result)
+        : &quot;r&quot;(offset)
+        : &quot;memory&quot;);
+    return result;
+}
+#else
+#error &quot;Bad architecture&quot;
+#endif
+#endif // ENABLE(FAST_TLS_JIT)
+
+inline unsigned fastTLSOffsetForKey(unsigned long slot)
+{
+    return slot * sizeof(void*);
+}
+
+} // namespace WTF
+
+using WTF::fastTLSOffsetForKey;
+
+#if ENABLE(FAST_TLS_JIT)
+using WTF::loadFastTLS;
+#endif
+
+#endif // HAVE(FAST_TLS)
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfPlatformh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Platform.h (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Platform.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/WTF/wtf/Platform.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -761,6 +761,14 @@
</span><span class="cx"> #define HAVE_LL_SC 1
</span><span class="cx"> #endif // CPU(ARM64)
</span><span class="cx"> 
</span><ins>+#if __has_include(&lt;System/pthread_machdep.h&gt;)
+#define HAVE_FAST_TLS 1
+#endif
+
+#if (CPU(X86_64) || CPU(ARM64)) &amp;&amp; HAVE(FAST_TLS)
+#define ENABLE_FAST_TLS_JIT 1
+#endif
+
</ins><span class="cx"> /* This controls whether B3 is built. B3 is needed for FTL JIT and WebAssembly */
</span><span class="cx"> #if ENABLE(FTL_JIT) || ENABLE(WEBASSEMBLY)
</span><span class="cx"> #define ENABLE_B3_JIT 1
</span></span></pre></div>
<a id="trunkSourceWTFwtfWTFThreadDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/WTFThreadData.cpp (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/WTFThreadData.cpp        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/WTF/wtf/WTFThreadData.cpp        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><del>-#if !USE(PTHREAD_GETSPECIFIC_DIRECT)
</del><ins>+#if !HAVE(FAST_TLS)
</ins><span class="cx"> ThreadSpecific&lt;WTFThreadData&gt;* WTFThreadData::staticData;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -61,12 +61,12 @@
</span><span class="cx">         m_atomicStringTableDestructor(m_defaultAtomicStringTable);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if USE(PTHREAD_GETSPECIFIC_DIRECT)
</del><ins>+#if HAVE(FAST_TLS)
</ins><span class="cx"> WTFThreadData&amp; WTFThreadData::createAndRegisterForGetspecificDirect()
</span><span class="cx"> {
</span><span class="cx">     WTFThreadData* data = new WTFThreadData;
</span><del>-    _pthread_setspecific_direct(directKey, data);
-    pthread_key_init_np(directKey, [](void* data){
</del><ins>+    _pthread_setspecific_direct(WTF_THREAD_DATA_KEY, data);
+    pthread_key_init_np(WTF_THREAD_DATA_KEY, [](void* data){
</ins><span class="cx">         delete static_cast&lt;WTFThreadData*&gt;(data);
</span><span class="cx">     });
</span><span class="cx">     return *data;
</span></span></pre></div>
<a id="trunkSourceWTFwtfWTFThreadDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/WTFThreadData.h (213752 => 213753)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/WTFThreadData.h        2017-03-11 06:56:12 UTC (rev 213752)
+++ trunk/Source/WTF/wtf/WTFThreadData.h        2017-03-11 07:17:48 UTC (rev 213753)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008-2017 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">@@ -27,25 +27,15 @@
</span><span class="cx"> #ifndef WTFThreadData_h
</span><span class="cx"> #define WTFThreadData_h
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/FastTLS.h&gt;
</ins><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/StackBounds.h&gt;
</span><span class="cx"> #include &lt;wtf/StackStats.h&gt;
</span><del>-#include &lt;wtf/text/StringHash.h&gt;
-
-#if USE(APPLE_INTERNAL_SDK)
-#include &lt;System/pthread_machdep.h&gt;
-#endif
-
-#if defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1)
-#define USE_PTHREAD_GETSPECIFIC_DIRECT 1
-#endif
-
-#if !USE(PTHREAD_GETSPECIFIC_DIRECT)
</del><span class="cx"> #include &lt;wtf/ThreadSpecific.h&gt;
</span><span class="cx"> #include &lt;wtf/Threading.h&gt;
</span><del>-#endif
</del><ins>+#include &lt;wtf/text/StringHash.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><span class="lines">@@ -122,8 +112,7 @@
</span><span class="cx">     void* m_savedStackPointerAtVMEntry;
</span><span class="cx">     void* m_savedLastStackTop;
</span><span class="cx"> 
</span><del>-#if USE(PTHREAD_GETSPECIFIC_DIRECT)
-    static const pthread_key_t directKey = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1;
</del><ins>+#if HAVE(FAST_TLS)
</ins><span class="cx">     WTF_EXPORT_PRIVATE static WTFThreadData&amp; createAndRegisterForGetspecificDirect();
</span><span class="cx"> #else
</span><span class="cx">     static WTF_EXPORTDATA ThreadSpecific&lt;WTFThreadData&gt;* staticData;
</span><span class="lines">@@ -141,12 +130,12 @@
</span><span class="cx">     // WRT JavaScriptCore:
</span><span class="cx">     //    wtfThreadData() is initially called from initializeThreading(), ensuring
</span><span class="cx">     //    this is initially called in a pthread_once locked context.
</span><del>-#if !USE(PTHREAD_GETSPECIFIC_DIRECT)
</del><ins>+#if !HAVE(FAST_TLS)
</ins><span class="cx">     if (!WTFThreadData::staticData)
</span><span class="cx">         WTFThreadData::staticData = new ThreadSpecific&lt;WTFThreadData&gt;;
</span><span class="cx">     return **WTFThreadData::staticData;
</span><span class="cx"> #else
</span><del>-    if (WTFThreadData* data = static_cast&lt;WTFThreadData*&gt;(_pthread_getspecific_direct(WTFThreadData::directKey)))
</del><ins>+    if (WTFThreadData* data = static_cast&lt;WTFThreadData*&gt;(_pthread_getspecific_direct(WTF_THREAD_DATA_KEY)))
</ins><span class="cx">         return *data;
</span><span class="cx">     return WTFThreadData::createAndRegisterForGetspecificDirect();
</span><span class="cx"> #endif
</span></span></pre>
</div>
</div>

</body>
</html>