<!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>[196658] 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/196658">196658</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-02-16 14:01:37 -0800 (Tue, 16 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>SamplingProfiler still fails with ASan enabled
https://bugs.webkit.org/show_bug.cgi?id=154301
&lt;rdar://problem/24679502&gt;

Reviewed by Filip Pizlo.

To fix this issue, I've come up with unsafe versions
of all operations that load memory from the thread's call
frame. All these new unsafe methods are marked with SUPPRESS_ASAN.

* interpreter/CallFrame.cpp:
(JSC::CallFrame::callSiteAsRawBits):
(JSC::CallFrame::unsafeCallSiteAsRawBits):
(JSC::CallFrame::callSiteIndex):
(JSC::CallFrame::unsafeCallSiteIndex):
(JSC::CallFrame::stack):
(JSC::CallFrame::callerFrame):
(JSC::CallFrame::unsafeCallerFrame):
(JSC::CallFrame::friendlyFunctionName):
* interpreter/CallFrame.h:
(JSC::ExecState::calleeAsValue):
(JSC::ExecState::callee):
(JSC::ExecState::unsafeCallee):
(JSC::ExecState::codeBlock):
(JSC::ExecState::unsafeCodeBlock):
(JSC::ExecState::scope):
(JSC::ExecState::callerFrame):
(JSC::ExecState::callerFrameOrVMEntryFrame):
(JSC::ExecState::unsafeCallerFrameOrVMEntryFrame):
(JSC::ExecState::callerFrameOffset):
(JSC::ExecState::callerFrameAndPC):
(JSC::ExecState::unsafeCallerFrameAndPC):
* interpreter/Register.h:
(JSC::Register::codeBlock):
(JSC::Register::asanUnsafeCodeBlock):
(JSC::Register::unboxedInt32):
(JSC::Register::tag):
(JSC::Register::unsafeTag):
(JSC::Register::payload):
* interpreter/VMEntryRecord.h:
(JSC::VMEntryRecord::prevTopCallFrame):
(JSC::VMEntryRecord::unsafePrevTopCallFrame):
(JSC::VMEntryRecord::prevTopVMEntryFrame):
(JSC::VMEntryRecord::unsafePrevTopVMEntryFrame):
* runtime/SamplingProfiler.cpp:
(JSC::FrameWalker::walk):
(JSC::FrameWalker::advanceToParentFrame):
(JSC::FrameWalker::isAtTop):
(JSC::FrameWalker::resetAtMachineFrame):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterCallFramecpp">trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterCallFrameh">trunk/Source/JavaScriptCore/interpreter/CallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterRegisterh">trunk/Source/JavaScriptCore/interpreter/Register.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterVMEntryRecordh">trunk/Source/JavaScriptCore/interpreter/VMEntryRecord.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSamplingProfilercpp">trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (196657 => 196658)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-02-16 21:42:26 UTC (rev 196657)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-02-16 22:01:37 UTC (rev 196658)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2016-02-16  Saam barati  &lt;sbarati@apple.com&gt;
+
+        SamplingProfiler still fails with ASan enabled
+        https://bugs.webkit.org/show_bug.cgi?id=154301
+        &lt;rdar://problem/24679502&gt;
+
+        Reviewed by Filip Pizlo.
+
+        To fix this issue, I've come up with unsafe versions
+        of all operations that load memory from the thread's call
+        frame. All these new unsafe methods are marked with SUPPRESS_ASAN.
+
+        * interpreter/CallFrame.cpp:
+        (JSC::CallFrame::callSiteAsRawBits):
+        (JSC::CallFrame::unsafeCallSiteAsRawBits):
+        (JSC::CallFrame::callSiteIndex):
+        (JSC::CallFrame::unsafeCallSiteIndex):
+        (JSC::CallFrame::stack):
+        (JSC::CallFrame::callerFrame):
+        (JSC::CallFrame::unsafeCallerFrame):
+        (JSC::CallFrame::friendlyFunctionName):
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::calleeAsValue):
+        (JSC::ExecState::callee):
+        (JSC::ExecState::unsafeCallee):
+        (JSC::ExecState::codeBlock):
+        (JSC::ExecState::unsafeCodeBlock):
+        (JSC::ExecState::scope):
+        (JSC::ExecState::callerFrame):
+        (JSC::ExecState::callerFrameOrVMEntryFrame):
+        (JSC::ExecState::unsafeCallerFrameOrVMEntryFrame):
+        (JSC::ExecState::callerFrameOffset):
+        (JSC::ExecState::callerFrameAndPC):
+        (JSC::ExecState::unsafeCallerFrameAndPC):
+        * interpreter/Register.h:
+        (JSC::Register::codeBlock):
+        (JSC::Register::asanUnsafeCodeBlock):
+        (JSC::Register::unboxedInt32):
+        (JSC::Register::tag):
+        (JSC::Register::unsafeTag):
+        (JSC::Register::payload):
+        * interpreter/VMEntryRecord.h:
+        (JSC::VMEntryRecord::prevTopCallFrame):
+        (JSC::VMEntryRecord::unsafePrevTopCallFrame):
+        (JSC::VMEntryRecord::prevTopVMEntryFrame):
+        (JSC::VMEntryRecord::unsafePrevTopVMEntryFrame):
+        * runtime/SamplingProfiler.cpp:
+        (JSC::FrameWalker::walk):
+        (JSC::FrameWalker::advanceToParentFrame):
+        (JSC::FrameWalker::isAtTop):
+        (JSC::FrameWalker::resetAtMachineFrame):
+
</ins><span class="cx"> 2016-02-16  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         FTL should support NewTypedArray
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp (196657 => 196658)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp        2016-02-16 21:42:26 UTC (rev 196657)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp        2016-02-16 22:01:37 UTC (rev 196658)
</span><span class="lines">@@ -79,11 +79,21 @@
</span><span class="cx">     return this[JSStack::ArgumentCount].tag();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SUPPRESS_ASAN unsigned CallFrame::unsafeCallSiteAsRawBits() const
+{
+    return this[JSStack::ArgumentCount].unsafeTag();
+}
+
</ins><span class="cx"> CallSiteIndex CallFrame::callSiteIndex() const
</span><span class="cx"> {
</span><span class="cx">     return CallSiteIndex(callSiteAsRawBits());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SUPPRESS_ASAN CallSiteIndex CallFrame::unsafeCallSiteIndex() const
+{
+    return CallSiteIndex(unsafeCallSiteAsRawBits());
+}
+
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> JSStack* CallFrame::stack()
</span><span class="cx"> {
</span><span class="lines">@@ -194,6 +204,16 @@
</span><span class="cx">     return static_cast&lt;CallFrame*&gt;(callerFrameOrVMEntryFrame());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SUPPRESS_ASAN CallFrame* CallFrame::unsafeCallerFrame(VMEntryFrame*&amp; currVMEntryFrame)
+{
+    if (unsafeCallerFrameOrVMEntryFrame() == currVMEntryFrame) {
+        VMEntryRecord* currVMEntryRecord = vmEntryRecord(currVMEntryFrame);
+        currVMEntryFrame = currVMEntryRecord-&gt;unsafePrevTopVMEntryFrame();
+        return currVMEntryRecord-&gt;unsafePrevTopCallFrame();
+    }
+    return static_cast&lt;CallFrame*&gt;(unsafeCallerFrameOrVMEntryFrame());
+}
+
</ins><span class="cx"> String CallFrame::friendlyFunctionName()
</span><span class="cx"> {
</span><span class="cx">     CodeBlock* codeBlock = this-&gt;codeBlock();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.h (196657 => 196658)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-02-16 21:42:26 UTC (rev 196657)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-02-16 22:01:37 UTC (rev 196658)
</span><span class="lines">@@ -66,8 +66,9 @@
</span><span class="cx">     public:
</span><span class="cx">         JSValue calleeAsValue() const { return this[JSStack::Callee].jsValue(); }
</span><span class="cx">         JSObject* callee() const { return this[JSStack::Callee].object(); }
</span><del>-        JSValue unsafeCallee() const { return this[JSStack::Callee].asanUnsafeJSValue(); }
</del><ins>+        SUPPRESS_ASAN JSValue unsafeCallee() const { return this[JSStack::Callee].asanUnsafeJSValue(); }
</ins><span class="cx">         CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); }
</span><ins>+        SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const { return this[JSStack::CodeBlock].Register::asanUnsafeCodeBlock(); }
</ins><span class="cx">         JSScope* scope(int scopeRegisterOffset) const
</span><span class="cx">         {
</span><span class="cx">             ASSERT(this[scopeRegisterOffset].Register::scope());
</span><span class="lines">@@ -115,7 +116,9 @@
</span><span class="cx"> 
</span><span class="cx">         CallFrame* callerFrame() const { return static_cast&lt;CallFrame*&gt;(callerFrameOrVMEntryFrame()); }
</span><span class="cx">         void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; }
</span><ins>+        SUPPRESS_ASAN void* unsafeCallerFrameOrVMEntryFrame() const { return unsafeCallerFrameAndPC().callerFrame; }
</ins><span class="cx"> 
</span><ins>+        CallFrame* unsafeCallerFrame(VMEntryFrame*&amp;);
</ins><span class="cx">         JS_EXPORT_PRIVATE CallFrame* callerFrame(VMEntryFrame*&amp;);
</span><span class="cx"> 
</span><span class="cx">         static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); }
</span><span class="lines">@@ -130,7 +133,9 @@
</span><span class="cx">         bool callSiteBitsAreCodeOriginIndex() const;
</span><span class="cx"> 
</span><span class="cx">         unsigned callSiteAsRawBits() const;
</span><ins>+        unsigned unsafeCallSiteAsRawBits() const;
</ins><span class="cx">         CallSiteIndex callSiteIndex() const;
</span><ins>+        CallSiteIndex unsafeCallSiteIndex() const;
</ins><span class="cx">     private:
</span><span class="cx">         unsigned callSiteBitsAsBytecodeOffset() const;
</span><span class="cx">     public:
</span><span class="lines">@@ -282,6 +287,7 @@
</span><span class="cx"> 
</span><span class="cx">         CallerFrameAndPC&amp; callerFrameAndPC() { return *reinterpret_cast&lt;CallerFrameAndPC*&gt;(this); }
</span><span class="cx">         const CallerFrameAndPC&amp; callerFrameAndPC() const { return *reinterpret_cast&lt;const CallerFrameAndPC*&gt;(this); }
</span><ins>+        SUPPRESS_ASAN const CallerFrameAndPC&amp; unsafeCallerFrameAndPC() const { return *reinterpret_cast&lt;const CallerFrameAndPC*&gt;(this); }
</ins><span class="cx"> 
</span><span class="cx">         friend class JSStack;
</span><span class="cx">     };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterRegisterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Register.h (196657 => 196658)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Register.h        2016-02-16 21:42:26 UTC (rev 196657)
+++ trunk/Source/JavaScriptCore/interpreter/Register.h        2016-02-16 22:01:37 UTC (rev 196658)
</span><span class="lines">@@ -62,6 +62,7 @@
</span><span class="cx">         int32_t i() const;
</span><span class="cx">         CallFrame* callFrame() const;
</span><span class="cx">         CodeBlock* codeBlock() const;
</span><ins>+        CodeBlock* asanUnsafeCodeBlock() const;
</ins><span class="cx">         JSObject* object() const;
</span><span class="cx">         JSScope* scope() const;
</span><span class="cx">         int32_t unboxedInt32() const;
</span><span class="lines">@@ -72,6 +73,7 @@
</span><span class="cx">         JSCell* unboxedCell() const;
</span><span class="cx">         int32_t payload() const;
</span><span class="cx">         int32_t tag() const;
</span><ins>+        int32_t unsafeTag() const;
</ins><span class="cx">         int32_t&amp; payload();
</span><span class="cx">         int32_t&amp; tag();
</span><span class="cx"> 
</span><span class="lines">@@ -155,6 +157,11 @@
</span><span class="cx">         return u.codeBlock;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    SUPPRESS_ASAN ALWAYS_INLINE CodeBlock* Register::asanUnsafeCodeBlock() const
+    {
+        return u.codeBlock;
+    }
+
</ins><span class="cx">     ALWAYS_INLINE int32_t Register::unboxedInt32() const
</span><span class="cx">     {
</span><span class="cx">         return payload();
</span><span class="lines">@@ -199,6 +206,11 @@
</span><span class="cx">         return u.encodedValue.asBits.tag;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    SUPPRESS_ASAN ALWAYS_INLINE int32_t Register::unsafeTag() const
+    {
+        return u.encodedValue.asBits.tag;
+    }
+
</ins><span class="cx">     ALWAYS_INLINE int32_t&amp; Register::payload()
</span><span class="cx">     {
</span><span class="cx">         return u.encodedValue.asBits.payload;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterVMEntryRecordh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/VMEntryRecord.h (196657 => 196658)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/VMEntryRecord.h        2016-02-16 21:42:26 UTC (rev 196657)
+++ trunk/Source/JavaScriptCore/interpreter/VMEntryRecord.h        2016-02-16 22:01:37 UTC (rev 196658)
</span><span class="lines">@@ -43,8 +43,10 @@
</span><span class="cx">     VMEntryFrame* m_prevTopVMEntryFrame;
</span><span class="cx"> 
</span><span class="cx">     ExecState* prevTopCallFrame() { return m_prevTopCallFrame; }
</span><ins>+    SUPPRESS_ASAN ExecState* unsafePrevTopCallFrame() { return m_prevTopCallFrame; }
</ins><span class="cx"> 
</span><span class="cx">     VMEntryFrame* prevTopVMEntryFrame() { return m_prevTopVMEntryFrame; }
</span><ins>+    SUPPRESS_ASAN VMEntryFrame* unsafePrevTopVMEntryFrame() { return m_prevTopVMEntryFrame; }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; VMEntryRecord* vmEntryRecord(VMEntryFrame*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSamplingProfilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp (196657 => 196658)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp        2016-02-16 21:42:26 UTC (rev 196657)
+++ trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp        2016-02-16 22:01:37 UTC (rev 196658)
</span><span class="lines">@@ -92,10 +92,10 @@
</span><span class="cx">         while (!isAtTop() &amp;&amp; !m_bailingOut &amp;&amp; m_depth &lt; maxStackTraceSize) {
</span><span class="cx">             CallSiteIndex callSiteIndex;
</span><span class="cx">             JSValue unsafeCallee = m_callFrame-&gt;unsafeCallee();
</span><del>-            CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
</del><ins>+            CodeBlock* codeBlock = m_callFrame-&gt;unsafeCodeBlock();
</ins><span class="cx">             if (codeBlock) {
</span><span class="cx">                 ASSERT(isValidCodeBlock(codeBlock));
</span><del>-                callSiteIndex = m_callFrame-&gt;callSiteIndex();
</del><ins>+                callSiteIndex = m_callFrame-&gt;unsafeCallSiteIndex();
</ins><span class="cx">             }
</span><span class="cx">             stackTrace[m_depth] = UnprocessedStackFrame(codeBlock, JSValue::encode(unsafeCallee), callSiteIndex);
</span><span class="cx">             m_depth++;
</span><span class="lines">@@ -117,7 +117,7 @@
</span><span class="cx">     SUPPRESS_ASAN
</span><span class="cx">     void advanceToParentFrame()
</span><span class="cx">     {
</span><del>-        m_callFrame = m_callFrame-&gt;callerFrame(m_vmEntryFrame);
</del><ins>+        m_callFrame = m_callFrame-&gt;unsafeCallerFrame(m_vmEntryFrame);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool isAtTop() const
</span><span class="lines">@@ -139,7 +139,7 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
</del><ins>+        CodeBlock* codeBlock = m_callFrame-&gt;unsafeCodeBlock();
</ins><span class="cx">         if (!codeBlock)
</span><span class="cx">             return;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>