<!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>[213295] 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/213295">213295</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2017-03-02 12:35:37 -0800 (Thu, 02 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add support for selective handling of VM traps.
https://bugs.webkit.org/show_bug.cgi?id=169087

Reviewed by Keith Miller.

This is needed because there are some places in the VM where it's appropriate to
handle some types of VM traps but not others.

We implement this selection by using a VMTraps::Mask that allows the user to
specify which traps should be serviced.

* interpreter/Interpreter.cpp:
(JSC::Interpreter::executeProgram):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::execute):
* runtime/VM.cpp:
(JSC::VM::handleTraps):
* runtime/VM.h:
* runtime/VMTraps.cpp:
(JSC::VMTraps::takeTrap): Deleted.
* runtime/VMTraps.h:
(JSC::VMTraps::Mask::Mask):
(JSC::VMTraps::Mask::allEventTypes):
(JSC::VMTraps::Mask::bits):
(JSC::VMTraps::Mask::init):
(JSC::VMTraps::needTrapHandling):
(JSC::VMTraps::hasTrapForEvent):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMTrapscpp">trunk/Source/JavaScriptCore/runtime/VMTraps.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMTrapsh">trunk/Source/JavaScriptCore/runtime/VMTraps.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (213294 => 213295)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-02 20:19:35 UTC (rev 213294)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-02 20:35:37 UTC (rev 213295)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2017-03-02  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Add support for selective handling of VM traps.
+        https://bugs.webkit.org/show_bug.cgi?id=169087
+
+        Reviewed by Keith Miller.
+
+        This is needed because there are some places in the VM where it's appropriate to
+        handle some types of VM traps but not others.
+
+        We implement this selection by using a VMTraps::Mask that allows the user to
+        specify which traps should be serviced.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::executeProgram):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::execute):
+        * runtime/VM.cpp:
+        (JSC::VM::handleTraps):
+        * runtime/VM.h:
+        * runtime/VMTraps.cpp:
+        (JSC::VMTraps::takeTrap): Deleted.
+        * runtime/VMTraps.h:
+        (JSC::VMTraps::Mask::Mask):
+        (JSC::VMTraps::Mask::allEventTypes):
+        (JSC::VMTraps::Mask::bits):
+        (JSC::VMTraps::Mask::init):
+        (JSC::VMTraps::needTrapHandling):
+        (JSC::VMTraps::hasTrapForEvent):
+
</ins><span class="cx"> 2017-03-02  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Continue enabling WebRTC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (213294 => 213295)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2017-03-02 20:19:35 UTC (rev 213294)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2017-03-02 20:35:37 UTC (rev 213295)
</span><span class="lines">@@ -861,7 +861,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(vm.needTrapHandling())) {
</span><del>-        vm.handleTraps(callFrame);
</del><ins>+        VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
+        vm.handleTraps(callFrame, mask);
</ins><span class="cx">         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -921,7 +922,8 @@
</span><span class="cx">         newCodeBlock = 0;
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(vm.needTrapHandling())) {
</span><del>-        vm.handleTraps(callFrame);
</del><ins>+        VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
+        vm.handleTraps(callFrame, mask);
</ins><span class="cx">         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -986,7 +988,8 @@
</span><span class="cx">         newCodeBlock = 0;
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(vm.needTrapHandling())) {
</span><del>-        vm.handleTraps(callFrame);
</del><ins>+        VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
+        vm.handleTraps(callFrame, mask);
</ins><span class="cx">         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1050,7 +1053,8 @@
</span><span class="cx">     StackStats::CheckPoint stackCheckPoint;
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(vm.needTrapHandling())) {
</span><del>-        vm.handleTraps(closure.oldCallFrame);
</del><ins>+        VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
+        vm.handleTraps(closure.oldCallFrame, mask);
</ins><span class="cx">         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1153,7 +1157,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(vm.needTrapHandling())) {
</span><del>-        vm.handleTraps(callFrame);
</del><ins>+        VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
+        vm.handleTraps(callFrame, mask);
</ins><span class="cx">         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1194,7 +1199,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(vm.needTrapHandling())) {
</span><del>-        vm.handleTraps(callFrame);
</del><ins>+        VMTraps::Mask mask(VMTraps::NeedTermination, VMTraps::NeedWatchdogCheck);
+        vm.handleTraps(callFrame, mask);
</ins><span class="cx">         RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (213294 => 213295)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-03-02 20:19:35 UTC (rev 213294)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-03-02 20:35:37 UTC (rev 213295)
</span><span class="lines">@@ -946,14 +946,17 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-void VM::handleTraps(ExecState* exec)
</del><ins>+void VM::handleTraps(ExecState* exec, VMTraps::Mask mask)
</ins><span class="cx"> {
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(*this);
</span><span class="cx"> 
</span><del>-    ASSERT(needTrapHandling());
-    while (needTrapHandling()) {
-        auto trapEventType = m_traps.takeTopPriorityTrap();
</del><ins>+    ASSERT(needTrapHandling(mask));
+    while (needTrapHandling(mask)) {
+        auto trapEventType = m_traps.takeTopPriorityTrap(mask);
</ins><span class="cx">         switch (trapEventType) {
</span><ins>+        case VMTraps::NeedDebuggerBreak:
+            RELEASE_ASSERT_NOT_REACHED();
+
</ins><span class="cx">         case VMTraps::NeedWatchdogCheck:
</span><span class="cx">             ASSERT(m_watchdog);
</span><span class="cx">             if (LIKELY(!m_watchdog-&gt;shouldTerminate(exec)))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (213294 => 213295)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2017-03-02 20:19:35 UTC (rev 213294)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2017-03-02 20:35:37 UTC (rev 213295)
</span><span class="lines">@@ -671,9 +671,9 @@
</span><span class="cx">     template&lt;typename Func&gt;
</span><span class="cx">     void logEvent(CodeBlock*, const char* summary, const Func&amp; func);
</span><span class="cx"> 
</span><del>-    void handleTraps(ExecState*);
</del><ins>+    void handleTraps(ExecState*, VMTraps::Mask = VMTraps::Mask::allEventTypes());
</ins><span class="cx"> 
</span><del>-    bool needTrapHandling() { return m_traps.needTrapHandling(); }
</del><ins>+    bool needTrapHandling(VMTraps::Mask mask = VMTraps::Mask::allEventTypes()) { return m_traps.needTrapHandling(mask); }
</ins><span class="cx">     void* needTrapHandlingAddress() { return m_traps.needTrapHandlingAddress(); }
</span><span class="cx"> 
</span><span class="cx">     void notifyNeedTermination() { m_traps.fireTrap(VMTraps::NeedTermination); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMTrapscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VMTraps.cpp (213294 => 213295)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VMTraps.cpp        2017-03-02 20:19:35 UTC (rev 213294)
+++ trunk/Source/JavaScriptCore/runtime/VMTraps.cpp        2017-03-02 20:35:37 UTC (rev 213295)
</span><span class="lines">@@ -34,22 +34,15 @@
</span><span class="cx">     setTrapForEvent(locker, eventType);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool VMTraps::takeTrap(VMTraps::EventType eventType)
</del><ins>+auto VMTraps::takeTopPriorityTrap(VMTraps::Mask mask) -&gt; EventType
</ins><span class="cx"> {
</span><span class="cx">     auto locker = holdLock(m_lock);
</span><del>-    if (hasTrapForEvent(locker, eventType)) {
-        clearTrapForEvent(locker, eventType);
-        return true;
-    }
-    return false;
-}
-
-auto VMTraps::takeTopPriorityTrap() -&gt; EventType
-{
</del><span class="cx">     for (int i = 0; i &lt; NumberOfEventTypes; ++i) {
</span><span class="cx">         EventType eventType = static_cast&lt;EventType&gt;(i);
</span><del>-        if (takeTrap(eventType))
</del><ins>+        if (hasTrapForEvent(locker, eventType, mask)) {
+            clearTrapForEvent(locker, eventType);
</ins><span class="cx">             return eventType;
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx">     return Invalid;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMTrapsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VMTraps.h (213294 => 213295)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VMTraps.h        2017-03-02 20:19:35 UTC (rev 213294)
+++ trunk/Source/JavaScriptCore/runtime/VMTraps.h        2017-03-02 20:35:37 UTC (rev 213295)
</span><span class="lines">@@ -33,9 +33,11 @@
</span><span class="cx"> class VM;
</span><span class="cx"> 
</span><span class="cx"> class VMTraps {
</span><ins>+    typedef uint8_t BitField;
</ins><span class="cx"> public:
</span><span class="cx">     enum EventType {
</span><span class="cx">         // Sorted in servicing priority order from highest to lowest.
</span><ins>+        NeedDebuggerBreak,
</ins><span class="cx">         NeedTermination,
</span><span class="cx">         NeedWatchdogCheck,
</span><span class="cx">         NumberOfEventTypes, // This entry must be last in this list.
</span><span class="lines">@@ -42,21 +44,51 @@
</span><span class="cx">         Invalid
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    bool needTrapHandling() { return m_needTrapHandling; }
</del><ins>+    class Mask {
+    public:
+        enum AllEventTypes { AllEventTypesTag };
+        Mask(AllEventTypes)
+            : m_mask(std::numeric_limits&lt;BitField&gt;::max())
+        { }
+        static Mask allEventTypes() { return Mask(AllEventTypesTag); }
+
+        template&lt;typename... Arguments&gt;
+        Mask(Arguments... args)
+            : m_mask(0)
+        {
+            init(args...);
+        }
+
+        BitField bits() const { return m_mask; }
+
+    private:
+        template&lt;typename... Arguments&gt;
+        void init(EventType eventType, Arguments... args)
+        {
+            ASSERT(eventType &lt; NumberOfEventTypes);
+            m_mask |= (1 &lt;&lt; eventType);
+            init(args...);
+        }
+
+        void init() { }
+
+        BitField m_mask;
+    };
+
+    bool needTrapHandling(Mask mask) { return m_needTrapHandling &amp; mask.bits(); }
</ins><span class="cx">     void* needTrapHandlingAddress() { return &amp;m_needTrapHandling; }
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void fireTrap(EventType);
</span><span class="cx"> 
</span><del>-    bool takeTrap(EventType);
-    EventType takeTopPriorityTrap();
</del><ins>+    EventType takeTopPriorityTrap(Mask);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     VM&amp; vm() const;
</span><span class="cx"> 
</span><del>-    bool hasTrapForEvent(Locker&lt;Lock&gt;&amp;, EventType eventType)
</del><ins>+    bool hasTrapForEvent(Locker&lt;Lock&gt;&amp;, EventType eventType, Mask mask)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(eventType &lt; NumberOfEventTypes);
</span><del>-        return (m_trapsBitField &amp; (1 &lt;&lt; eventType));
</del><ins>+        return (m_trapsBitField &amp; mask.bits() &amp; (1 &lt;&lt; eventType));
</ins><span class="cx">     }
</span><span class="cx">     void setTrapForEvent(Locker&lt;Lock&gt;&amp;, EventType eventType)
</span><span class="cx">     {
</span><span class="lines">@@ -71,8 +103,8 @@
</span><span class="cx"> 
</span><span class="cx">     Lock m_lock;
</span><span class="cx">     union {
</span><del>-        uint8_t m_needTrapHandling { false };
-        uint8_t m_trapsBitField;
</del><ins>+        BitField m_needTrapHandling { 0 };
+        BitField m_trapsBitField;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span></span></pre>
</div>
</div>

</body>
</html>