<!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>[181625] 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/181625">181625</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-03-17 01:41:19 -0700 (Tue, 17 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Show rendering frames (and FPS) in Layout and Rendering timeline
https://bugs.webkit.org/show_bug.cgi?id=142029

Patch by Matt Baker &lt;mattbaker@apple.com&gt; on 2015-03-17
Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

* inspector/protocol/Timeline.json:
Added new event type for runloop timeline records.

Source/WebCore:

Add new functionality to the Inspector timelines backend to add runloop data to timeline recordings.

* inspector/InspectorTimelineAgent.cpp:
(WebCore::currentRunLoop):
(WebCore::InspectorTimelineAgent::internalStart):
(WebCore::InspectorTimelineAgent::internalStop):
(WebCore::toProtocol):
(WebCore::InspectorTimelineAgent::InspectorTimelineAgent):
Install observers for the begining and end of the runloop when recording begins. All other
instrumented timeline events get added as children of the current runloop record, which is
sent to the frontend once the runloop completes.

* inspector/InspectorTimelineAgent.h:

* platform/cf/RunLoopObserver.cpp:
(WebCore::RunLoopObserver::schedule):
Wrapper changed to allow observing arbitrary runloop activities.

* platform/cf/RunLoopObserver.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolTimelinejson">trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorTimelineAgentcpp">trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorTimelineAgenth">trunk/Source/WebCore/inspector/InspectorTimelineAgent.h</a></li>
<li><a href="#trunkSourceWebCoreplatformcfRunLoopObservercpp">trunk/Source/WebCore/platform/cf/RunLoopObserver.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformcfRunLoopObserverh">trunk/Source/WebCore/platform/cf/RunLoopObserver.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (181624 => 181625)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-03-17 08:39:05 UTC (rev 181624)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-03-17 08:41:19 UTC (rev 181625)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-03-17  Matt Baker  &lt;mattbaker@apple.com&gt;
+
+        Web Inspector: Show rendering frames (and FPS) in Layout and Rendering timeline
+        https://bugs.webkit.org/show_bug.cgi?id=142029
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/protocol/Timeline.json:
+        Added new event type for runloop timeline records.
+
</ins><span class="cx"> 2015-03-16  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Enable ES6 classes by default
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolTimelinejson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json (181624 => 181625)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json        2015-03-17 08:39:05 UTC (rev 181624)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json        2015-03-17 08:41:19 UTC (rev 181625)
</span><span class="lines">@@ -13,6 +13,7 @@
</span><span class="cx">                 &quot;InvalidateLayout&quot;,
</span><span class="cx">                 &quot;Layout&quot;,
</span><span class="cx">                 &quot;Paint&quot;,
</span><ins>+                &quot;RunLoop&quot;,
</ins><span class="cx">                 &quot;ScrollLayer&quot;,
</span><span class="cx">                 &quot;ParseHTML&quot;,
</span><span class="cx">                 &quot;TimerInstall&quot;,
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (181624 => 181625)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-03-17 08:39:05 UTC (rev 181624)
+++ trunk/Source/WebCore/ChangeLog        2015-03-17 08:41:19 UTC (rev 181625)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-03-17  Matt Baker  &lt;mattbaker@apple.com&gt;
+
+        Web Inspector: Show rendering frames (and FPS) in Layout and Rendering timeline
+        https://bugs.webkit.org/show_bug.cgi?id=142029
+
+        Reviewed by Timothy Hatcher.
+
+        Add new functionality to the Inspector timelines backend to add runloop data to timeline recordings.
+
+        * inspector/InspectorTimelineAgent.cpp:
+        (WebCore::currentRunLoop):
+        (WebCore::InspectorTimelineAgent::internalStart):
+        (WebCore::InspectorTimelineAgent::internalStop):
+        (WebCore::toProtocol):
+        (WebCore::InspectorTimelineAgent::InspectorTimelineAgent):
+        Install observers for the begining and end of the runloop when recording begins. All other
+        instrumented timeline events get added as children of the current runloop record, which is
+        sent to the frontend once the runloop completes.
+
+        * inspector/InspectorTimelineAgent.h:
+
+        * platform/cf/RunLoopObserver.cpp:
+        (WebCore::RunLoopObserver::schedule):
+        Wrapper changed to allow observing arbitrary runloop activities.
+
+        * platform/cf/RunLoopObserver.h:
+
</ins><span class="cx"> 2015-03-17  Philippe Normand  &lt;pnormand@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] basic OpenWebRTC build support
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorTimelineAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp (181624 => 181625)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp        2015-03-17 08:39:05 UTC (rev 181624)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp        2015-03-17 08:41:19 UTC (rev 181625)
</span><span class="lines">@@ -54,10 +54,37 @@
</span><span class="cx"> #include &lt;profiler/LegacyProfiler.h&gt;
</span><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS)
+#include &quot;RuntimeApplicationChecksIOS.h&quot;
+#include &lt;WebCore/WebCoreThread.h&gt;
+#endif
+
+#if PLATFORM(COCOA)
+#include &lt;WebCore/RunLoopObserver.h&gt;
+#endif
+
</ins><span class="cx"> using namespace Inspector;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+#if PLATFORM(COCOA)
+static const CFIndex frameStopRunLoopOrder = (CFIndex)RunLoopObserver::WellKnownRunLoopOrders::CoreAnimationCommit + 1;
+
+static CFRunLoopRef currentRunLoop()
+{
+#if PLATFORM(IOS)
+    // A race condition during WebView deallocation can lead to a crash if the layer sync run loop
+    // observer is added to the main run loop &lt;rdar://problem/9798550&gt;. However, for responsiveness,
+    // we still allow this, see &lt;rdar://problem/7403328&gt;. Since the race condition and subsequent
+    // crash are especially troublesome for iBooks, we never allow the observer to be added to the
+    // main run loop in iBooks.
+    if (applicationIsIBooksOnIOS())
+        return WebThreadRunLoop();
+#endif
+    return CFRunLoopGetCurrent();
+}
+#endif
+
</ins><span class="cx"> InspectorTimelineAgent::~InspectorTimelineAgent()
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -122,6 +149,33 @@
</span><span class="cx"> 
</span><span class="cx">     m_enabled = true;
</span><span class="cx"> 
</span><ins>+    // FIXME: Abstract away platform-specific code once https://bugs.webkit.org/show_bug.cgi?id=142748 is fixed.
+
+#if PLATFORM(COCOA)
+    m_frameStartObserver = RunLoopObserver::create(0, [this]() {
+        if (!m_enabled || m_didStartRecordingRunLoop)
+            return;
+
+        pushCurrentRecord(InspectorObject::create(), TimelineRecordType::RunLoop, false, nullptr);
+        m_didStartRecordingRunLoop = true;
+    });
+
+    m_frameStopObserver = RunLoopObserver::create(frameStopRunLoopOrder, [this]() {
+        if (!m_enabled || !m_didStartRecordingRunLoop)
+            return;
+
+        didCompleteCurrentRecord(TimelineRecordType::RunLoop);
+        m_didStartRecordingRunLoop = false;
+    });
+
+    m_frameStartObserver-&gt;schedule(currentRunLoop(), kCFRunLoopAfterWaiting | kCFRunLoopBeforeTimers);
+    m_frameStopObserver-&gt;schedule(currentRunLoop(), kCFRunLoopBeforeWaiting | kCFRunLoopExit);
+
+    // Create a runloop record immediately in order to capture the rest of the current runloop.
+    pushCurrentRecord(InspectorObject::create(), TimelineRecordType::RunLoop, false, nullptr);
+    m_didStartRecordingRunLoop = true;
+#endif
+
</ins><span class="cx">     if (m_frontendDispatcher)
</span><span class="cx">         m_frontendDispatcher-&gt;recordingStarted();
</span><span class="cx"> }
</span><span class="lines">@@ -141,6 +195,11 @@
</span><span class="cx">     if (m_scriptDebugServer)
</span><span class="cx">         m_scriptDebugServer-&gt;removeListener(this, true);
</span><span class="cx"> 
</span><ins>+#if PLATFORM(COCOA)
+    m_frameStartObserver = nullptr;
+    m_frameStopObserver = nullptr;
+#endif
+
</ins><span class="cx">     clearRecordStack();
</span><span class="cx"> 
</span><span class="cx">     m_enabled = false;
</span><span class="lines">@@ -539,6 +598,8 @@
</span><span class="cx">         return Inspector::Protocol::Timeline::EventType::Layout;
</span><span class="cx">     case TimelineRecordType::Paint:
</span><span class="cx">         return Inspector::Protocol::Timeline::EventType::Paint;
</span><ins>+    case TimelineRecordType::RunLoop:
+        return Inspector::Protocol::Timeline::EventType::RunLoop;
</ins><span class="cx">     case TimelineRecordType::ScrollLayer:
</span><span class="cx">         return Inspector::Protocol::Timeline::EventType::ScrollLayer;
</span><span class="cx"> 
</span><span class="lines">@@ -654,6 +715,7 @@
</span><span class="cx">     , m_client(client)
</span><span class="cx">     , m_enabled(false)
</span><span class="cx">     , m_enabledFromFrontend(false)
</span><ins>+    , m_didStartRecordingRunLoop(false)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorTimelineAgenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.h (181624 => 181625)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.h        2015-03-17 08:39:05 UTC (rev 181624)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.h        2015-03-17 08:41:19 UTC (rev 181625)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx"> class RenderObject;
</span><span class="cx"> class ResourceRequest;
</span><span class="cx"> class ResourceResponse;
</span><ins>+class RunLoopObserver;
</ins><span class="cx"> 
</span><span class="cx"> typedef String ErrorString;
</span><span class="cx"> 
</span><span class="lines">@@ -71,6 +72,7 @@
</span><span class="cx">     InvalidateLayout,
</span><span class="cx">     Layout,
</span><span class="cx">     Paint,
</span><ins>+    RunLoop,
</ins><span class="cx">     ScrollLayer,
</span><span class="cx"> 
</span><span class="cx">     ParseHTML,
</span><span class="lines">@@ -244,6 +246,12 @@
</span><span class="cx"> 
</span><span class="cx">     bool m_enabled;
</span><span class="cx">     bool m_enabledFromFrontend;
</span><ins>+
+#if PLATFORM(COCOA)
+    std::unique_ptr&lt;WebCore::RunLoopObserver&gt; m_frameStartObserver;
+    std::unique_ptr&lt;WebCore::RunLoopObserver&gt; m_frameStopObserver;
+#endif
+    bool m_didStartRecordingRunLoop;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformcfRunLoopObservercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cf/RunLoopObserver.cpp (181624 => 181625)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cf/RunLoopObserver.cpp        2015-03-17 08:39:05 UTC (rev 181624)
+++ trunk/Source/WebCore/platform/cf/RunLoopObserver.cpp        2015-03-17 08:41:19 UTC (rev 181625)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx">     m_callback();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RunLoopObserver::schedule(CFRunLoopRef runLoop)
</del><ins>+void RunLoopObserver::schedule(CFRunLoopRef runLoop, CFRunLoopActivity activity)
</ins><span class="cx"> {
</span><span class="cx">     if (!runLoop)
</span><span class="cx">         runLoop = CFRunLoopGetCurrent();
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     CFRunLoopObserverContext context = { 0, this, 0, 0, 0 };
</span><del>-    m_runLoopObserver = adoptCF(CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting | kCFRunLoopExit, true, m_order, runLoopObserverFired, &amp;context));
</del><ins>+    m_runLoopObserver = adoptCF(CFRunLoopObserverCreate(0, activity, true, m_order, runLoopObserverFired, &amp;context));
</ins><span class="cx"> 
</span><span class="cx">     CFRunLoopAddObserver(runLoop, m_runLoopObserver.get(), kCFRunLoopCommonModes);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformcfRunLoopObserverh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cf/RunLoopObserver.h (181624 => 181625)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cf/RunLoopObserver.h        2015-03-17 08:39:05 UTC (rev 181624)
+++ trunk/Source/WebCore/platform/cf/RunLoopObserver.h        2015-03-17 08:41:19 UTC (rev 181625)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT ~RunLoopObserver();
</span><span class="cx"> 
</span><del>-    WEBCORE_EXPORT void schedule(CFRunLoopRef = nullptr);
</del><ins>+    WEBCORE_EXPORT void schedule(CFRunLoopRef = nullptr, CFRunLoopActivity = kCFRunLoopBeforeWaiting | kCFRunLoopExit);
</ins><span class="cx">     WEBCORE_EXPORT void invalidate();
</span><span class="cx"> 
</span><span class="cx">     bool isScheduled() const { return m_runLoopObserver; }
</span></span></pre>
</div>
</div>

</body>
</html>