<!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>[173262] 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/173262">173262</a></dd>
<dt>Author</dt> <dd>burg@cs.washington.edu</dd>
<dt>Date</dt> <dd>2014-09-04 10:00:22 -0700 (Thu, 04 Sep 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>LegacyProfiler: ProfileNodes should be used more like structs
https://bugs.webkit.org/show_bug.cgi?id=136381

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

Previously, both the profile generator and individual profile nodes
were collectively responsible for creating new Call entries and
maintaining data structure invariants. This complexity is unnecessary.

This patch centralizes profile data creation inside the profile generator.
The profile nodes manage nextSibling and parent pointers, but do not
collect the current time or create new Call entries themselves.

Since ProfileNode::nextSibling and its callers are only used within
debug printing code, it should be compiled out for release builds.

* profiler/ProfileGenerator.cpp:
(JSC::ProfileGenerator::ProfileGenerator):
(JSC::AddParentForConsoleStartFunctor::operator()):
(JSC::ProfileGenerator::beginCallEntry): create a new Call entry.
(JSC::ProfileGenerator::endCallEntry): finish the last Call entry.
(JSC::ProfileGenerator::willExecute): inline ProfileNode::willExecute()
(JSC::ProfileGenerator::didExecute): inline ProfileNode::didExecute()
(JSC::ProfileGenerator::stopProfiling): Only walk up the spine.
(JSC::ProfileGenerator::removeProfileStart):
(JSC::ProfileGenerator::removeProfileEnd):
* profiler/ProfileGenerator.h:
* profiler/ProfileNode.cpp:
(JSC::ProfileNode::ProfileNode):
(JSC::ProfileNode::addChild):
(JSC::ProfileNode::removeChild):
(JSC::ProfileNode::spliceNode): Renamed from insertNode.
(JSC::ProfileNode::debugPrintRecursively):
(JSC::ProfileNode::willExecute): Deleted.
(JSC::ProfileNode::insertNode): Deleted.
(JSC::ProfileNode::stopProfiling): Deleted.
(JSC::ProfileNode::traverseNextNodePostOrder):
(JSC::ProfileNode::endAndRecordCall): Deleted.
(JSC::ProfileNode::debugPrintDataSampleStyle):
* profiler/ProfileNode.h:
(JSC::ProfileNode::Call::setStartTime):
(JSC::ProfileNode::Call::setTotalTime):
(JSC::ProfileNode::appendCall):
(JSC::ProfileNode::firstChild):
(JSC::ProfileNode::lastChild):
(JSC::ProfileNode::nextSibling):
(JSC::ProfileNode::setNextSibling):

Source/WebCore:

* inspector/ScriptProfileNode.idl: Remove an unused property.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfilecpp">trunk/Source/JavaScriptCore/profiler/Profile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfileGeneratorcpp">trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfileGeneratorh">trunk/Source/JavaScriptCore/profiler/ProfileGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfileNodecpp">trunk/Source/JavaScriptCore/profiler/ProfileNode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfileNodeh">trunk/Source/JavaScriptCore/profiler/ProfileNode.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectorScriptProfileNodeidl">trunk/Source/WebCore/inspector/ScriptProfileNode.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -1,3 +1,53 @@
</span><ins>+2014-09-04  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
+
+        LegacyProfiler: ProfileNodes should be used more like structs
+        https://bugs.webkit.org/show_bug.cgi?id=136381
+
+        Reviewed by Timothy Hatcher.
+
+        Previously, both the profile generator and individual profile nodes
+        were collectively responsible for creating new Call entries and
+        maintaining data structure invariants. This complexity is unnecessary.
+
+        This patch centralizes profile data creation inside the profile generator.
+        The profile nodes manage nextSibling and parent pointers, but do not
+        collect the current time or create new Call entries themselves.
+
+        Since ProfileNode::nextSibling and its callers are only used within
+        debug printing code, it should be compiled out for release builds.
+
+        * profiler/ProfileGenerator.cpp:
+        (JSC::ProfileGenerator::ProfileGenerator):
+        (JSC::AddParentForConsoleStartFunctor::operator()):
+        (JSC::ProfileGenerator::beginCallEntry): create a new Call entry.
+        (JSC::ProfileGenerator::endCallEntry): finish the last Call entry.
+        (JSC::ProfileGenerator::willExecute): inline ProfileNode::willExecute()
+        (JSC::ProfileGenerator::didExecute): inline ProfileNode::didExecute()
+        (JSC::ProfileGenerator::stopProfiling): Only walk up the spine.
+        (JSC::ProfileGenerator::removeProfileStart):
+        (JSC::ProfileGenerator::removeProfileEnd):
+        * profiler/ProfileGenerator.h:
+        * profiler/ProfileNode.cpp:
+        (JSC::ProfileNode::ProfileNode):
+        (JSC::ProfileNode::addChild):
+        (JSC::ProfileNode::removeChild):
+        (JSC::ProfileNode::spliceNode): Renamed from insertNode.
+        (JSC::ProfileNode::debugPrintRecursively):
+        (JSC::ProfileNode::willExecute): Deleted.
+        (JSC::ProfileNode::insertNode): Deleted.
+        (JSC::ProfileNode::stopProfiling): Deleted.
+        (JSC::ProfileNode::traverseNextNodePostOrder):
+        (JSC::ProfileNode::endAndRecordCall): Deleted.
+        (JSC::ProfileNode::debugPrintDataSampleStyle):
+        * profiler/ProfileNode.h:
+        (JSC::ProfileNode::Call::setStartTime):
+        (JSC::ProfileNode::Call::setTotalTime):
+        (JSC::ProfileNode::appendCall):
+        (JSC::ProfileNode::firstChild):
+        (JSC::ProfileNode::lastChild):
+        (JSC::ProfileNode::nextSibling):
+        (JSC::ProfileNode::setNextSibling):
+
</ins><span class="cx"> 2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: fix prefixes for subclasses of JSC::ConsoleClient
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/Profile.cpp (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/Profile.cpp        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/JavaScriptCore/profiler/Profile.cpp        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;Profile.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ProfileNode.h&quot;
</span><ins>+#include &lt;wtf/CurrentTime.h&gt;
</ins><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -43,6 +44,7 @@
</span><span class="cx">     // FIXME: When multi-threading is supported this will be a vector and calls
</span><span class="cx">     // into the profiler will need to know which thread it is executing on.
</span><span class="cx">     m_rootNode = ProfileNode::create(nullptr, CallIdentifier(ASCIILiteral(&quot;Thread_1&quot;), String(), 0, 0), nullptr);
</span><ins>+    m_rootNode-&gt;appendCall(ProfileNode::Call(currentTime()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Profile::~Profile()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ProfileGenerator::ProfileGenerator(ExecState* exec, const String&amp; title, unsigned uid)
</span><del>-    : m_origin(exec ? exec-&gt;lexicalGlobalObject() : 0)
</del><ins>+    : m_origin(exec ? exec-&gt;lexicalGlobalObject() : nullptr)
</ins><span class="cx">     , m_profileGroup(exec ? exec-&gt;lexicalGlobalObject()-&gt;profileGroup() : 0)
</span><span class="cx">     , m_foundConsoleStartParent(false)
</span><span class="cx"> {
</span><span class="lines">@@ -79,7 +79,8 @@
</span><span class="cx">         unsigned column = 0;
</span><span class="cx">         visitor-&gt;computeLineAndColumn(line, column);
</span><span class="cx">         m_currentNode = ProfileNode::create(m_exec, LegacyProfiler::createCallIdentifier(m_exec, visitor-&gt;callee(), visitor-&gt;sourceURL(), line, column), m_rootNode.get());
</span><del>-        m_rootNode-&gt;insertNode(m_currentNode.get());
</del><ins>+        m_currentNode-&gt;appendCall(ProfileNode::Call(currentTime()));
+        m_rootNode-&gt;spliceNode(m_currentNode.get());
</ins><span class="cx"> 
</span><span class="cx">         m_foundParent = true;
</span><span class="cx">         return StackVisitor::Done;
</span><span class="lines">@@ -106,6 +107,25 @@
</span><span class="cx">     return m_profile-&gt;title();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ProfileGenerator::beginCallEntry(ProfileNode* node, double startTime)
+{
+    ASSERT_ARG(node, node);
+
+    if (isnan(startTime))
+        startTime = currentTime();
+    node-&gt;appendCall(ProfileNode::Call(startTime));
+}
+
+void ProfileGenerator::endCallEntry(ProfileNode* node)
+{
+    ASSERT_ARG(node, node);
+
+    ProfileNode::Call&amp; last = node-&gt;lastCall();
+    ASSERT(isnan(last.totalTime()));
+
+    last.setTotalTime(currentTime() - last.startTime());
+}
+
</ins><span class="cx"> void ProfileGenerator::willExecute(ExecState* callerCallFrame, const CallIdentifier&amp; callIdentifier)
</span><span class="cx"> {
</span><span class="cx">     if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) {
</span><span class="lines">@@ -117,8 +137,21 @@
</span><span class="cx">     if (!m_origin)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    ASSERT(m_currentNode);
-    m_currentNode = m_currentNode-&gt;willExecute(callerCallFrame, callIdentifier);
</del><ins>+    RefPtr&lt;ProfileNode&gt; calleeNode = nullptr;
+
+    // Find or create a node for the callee call frame.
+    for (const RefPtr&lt;ProfileNode&gt;&amp; child : m_currentNode-&gt;children()) {
+        if (child-&gt;callIdentifier() == callIdentifier)
+            calleeNode = child;
+    }
+
+    if (!calleeNode) {
+        calleeNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
+        m_currentNode-&gt;addChild(calleeNode);
+    }
+
+    m_currentNode = calleeNode;
+    beginCallEntry(calleeNode.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ProfileGenerator::didExecute(ExecState* callerCallFrame, const CallIdentifier&amp; callIdentifier)
</span><span class="lines">@@ -132,16 +165,19 @@
</span><span class="cx">     if (!m_origin)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    // Make a new node if the caller node has never seen this callee call frame before.
+    // This can happen if |console.profile()| is called several frames deep in the call stack.
</ins><span class="cx">     ASSERT(m_currentNode);
</span><span class="cx">     if (m_currentNode-&gt;callIdentifier() != callIdentifier) {
</span><del>-        RefPtr&lt;ProfileNode&gt; returningNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
-        returningNode-&gt;lastCall().setStartTime(m_currentNode-&gt;lastCall().startTime());
-        returningNode-&gt;didExecute();
-        m_currentNode-&gt;insertNode(returningNode.release());
</del><ins>+        RefPtr&lt;ProfileNode&gt; calleeNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
+        beginCallEntry(calleeNode.get(), m_currentNode-&gt;lastCall().startTime());
+        endCallEntry(calleeNode.get());
+        m_currentNode-&gt;spliceNode(calleeNode.release());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_currentNode = m_currentNode-&gt;didExecute();
</del><ins>+    endCallEntry(m_currentNode.get());
+    m_currentNode = m_currentNode-&gt;parent();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ProfileGenerator::exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&amp;)
</span><span class="lines">@@ -155,16 +191,10 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-struct StopProfilingFunctor {
-    void operator()(ProfileNode* node) { node-&gt;stopProfiling(); }
-};
-
</del><span class="cx"> void ProfileGenerator::stopProfiling()
</span><span class="cx"> {
</span><del>-    // FIXME: we shouldn't need a full traversal here, since only the spine from
-    // m_currentNode to m_rootNode should have any nodes currently accruing time.
-    StopProfilingFunctor functor;
-    m_profile-&gt;rootNode()-&gt;forEachNodePostorder(functor);
</del><ins>+    for (ProfileNode* node = m_currentNode.get(); node != m_profile-&gt;rootNode(); node = node-&gt;parent())
+        endCallEntry(node);
</ins><span class="cx"> 
</span><span class="cx">     if (m_foundConsoleStartParent) {
</span><span class="cx">         removeProfileStart();
</span><span class="lines">@@ -181,7 +211,7 @@
</span><span class="cx"> // The console.profile that started this ProfileGenerator will be the first child.
</span><span class="cx"> void ProfileGenerator::removeProfileStart()
</span><span class="cx"> {
</span><del>-    ProfileNode* currentNode = 0;
</del><ins>+    ProfileNode* currentNode = nullptr;
</ins><span class="cx">     for (ProfileNode* next = m_rootNode.get(); next; next = next-&gt;firstChild())
</span><span class="cx">         currentNode = next;
</span><span class="cx"> 
</span><span class="lines">@@ -194,7 +224,7 @@
</span><span class="cx"> // The console.profileEnd that stopped this ProfileGenerator will be the last child.
</span><span class="cx"> void ProfileGenerator::removeProfileEnd()
</span><span class="cx"> {
</span><del>-    ProfileNode* currentNode = 0;
</del><ins>+    ProfileNode* currentNode = nullptr;
</ins><span class="cx">     for (ProfileNode* next = m_rootNode.get(); next; next = next-&gt;lastChild())
</span><span class="cx">         currentNode = next;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileGenerator.h (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileGenerator.h        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/JavaScriptCore/profiler/ProfileGenerator.h        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -26,10 +26,10 @@
</span><span class="cx"> #ifndef ProfileGenerator_h
</span><span class="cx"> #define ProfileGenerator_h
</span><span class="cx"> 
</span><del>-#include &quot;Profile.h&quot;
</del><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><ins>+#include &lt;wtf/text/WTFString.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -49,13 +49,10 @@
</span><span class="cx">         JSGlobalObject* origin() const { return m_origin; }
</span><span class="cx">         unsigned profileGroup() const { return m_profileGroup; }
</span><span class="cx"> 
</span><del>-        // Collecting
</del><span class="cx">         void willExecute(ExecState* callerCallFrame, const CallIdentifier&amp;);
</span><span class="cx">         void didExecute(ExecState* callerCallFrame, const CallIdentifier&amp;);
</span><del>-
</del><span class="cx">         void exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&amp;);
</span><span class="cx"> 
</span><del>-        // Stopping Profiling
</del><span class="cx">         void stopProfiling();
</span><span class="cx"> 
</span><span class="cx">         typedef void (ProfileGenerator::*ProfileFunction)(ExecState* callerOrHandlerCallFrame, const CallIdentifier&amp; callIdentifier);
</span><span class="lines">@@ -67,6 +64,9 @@
</span><span class="cx">         void removeProfileStart();
</span><span class="cx">         void removeProfileEnd();
</span><span class="cx"> 
</span><ins>+        void beginCallEntry(ProfileNode*, double startTime = NAN);
+        void endCallEntry(ProfileNode*);
+
</ins><span class="cx">         RefPtr&lt;Profile&gt; m_profile;
</span><span class="cx">         JSGlobalObject* m_origin;
</span><span class="cx">         unsigned m_profileGroup;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileNode.cpp (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileNode.cpp        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/JavaScriptCore/profiler/ProfileNode.cpp        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -42,48 +42,31 @@
</span><span class="cx">     : m_callerCallFrame(callerCallFrame)
</span><span class="cx">     , m_callIdentifier(callIdentifier)
</span><span class="cx">     , m_parent(parentNode)
</span><ins>+#ifndef NDEBUG
</ins><span class="cx">     , m_nextSibling(nullptr)
</span><ins>+#endif
</ins><span class="cx"> {
</span><del>-    startTimer();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
</span><span class="cx">     : m_callerCallFrame(callerCallFrame)
</span><span class="cx">     , m_callIdentifier(nodeToCopy-&gt;callIdentifier())
</span><span class="cx">     , m_parent(nodeToCopy-&gt;parent())
</span><del>-    , m_nextSibling(nullptr)
</del><span class="cx">     , m_calls(nodeToCopy-&gt;calls())
</span><ins>+#ifndef NDEBUG
+    , m_nextSibling(nullptr)
+#endif
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier&amp; callIdentifier)
-{
-    for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
-        if ((*currentChild)-&gt;callIdentifier() == callIdentifier) {
-            (*currentChild)-&gt;startTimer();
-            return (*currentChild).get();
-        }
-    }
-
-    RefPtr&lt;ProfileNode&gt; newChild = ProfileNode::create(callerCallFrame, callIdentifier, this);
-    if (m_children.size())
-        m_children.last()-&gt;setNextSibling(newChild.get());
-    m_children.append(newChild.release());
-    return m_children.last().get();
-}
-
-ProfileNode* ProfileNode::didExecute()
-{
-    endAndRecordCall();
-    return m_parent;
-}
-
</del><span class="cx"> void ProfileNode::addChild(PassRefPtr&lt;ProfileNode&gt; prpChild)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;ProfileNode&gt; child = prpChild;
</span><span class="cx">     child-&gt;setParent(this);
</span><ins>+#ifndef NDEBUG
</ins><span class="cx">     if (m_children.size())
</span><span class="cx">         m_children.last()-&gt;setNextSibling(child.get());
</span><ins>+#endif
</ins><span class="cx">     m_children.append(child.release());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -99,10 +82,14 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    resetChildrensSiblings();
</del><ins>+#ifndef NDEBUG
+    size_t size = m_children.size();
+    for (size_t i = 0; i &lt; size; ++i)
+        m_children[i]-&gt;setNextSibling(i + 1 == size ? nullptr : m_children[i + 1].get());
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ProfileNode::insertNode(PassRefPtr&lt;ProfileNode&gt; prpNode)
</del><ins>+void ProfileNode::spliceNode(PassRefPtr&lt;ProfileNode&gt; prpNode)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr&lt;ProfileNode&gt; node = prpNode;
</span><span class="cx"> 
</span><span class="lines">@@ -113,14 +100,7 @@
</span><span class="cx">     m_children.append(node.release());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ProfileNode::stopProfiling()
-{
-    ASSERT(!m_calls.isEmpty());
-
-    if (isnan(m_calls.last().totalTime()))
-        endAndRecordCall();
-}
-
</del><ins>+#ifndef NDEBUG
</ins><span class="cx"> ProfileNode* ProfileNode::traverseNextNodePostOrder() const
</span><span class="cx"> {
</span><span class="cx">     ProfileNode* next = m_nextSibling;
</span><span class="lines">@@ -131,27 +111,6 @@
</span><span class="cx">     return next;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ProfileNode::endAndRecordCall()
-{
-    Call&amp; last = lastCall();
-    ASSERT(isnan(last.totalTime()));
-
-    last.setTotalTime(currentTime() - last.startTime());
-}
-
-void ProfileNode::startTimer()
-{
-    m_calls.append(Call(currentTime()));
-}
-
-void ProfileNode::resetChildrensSiblings()
-{
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i &lt; size; ++i)
-        m_children[i]-&gt;setNextSibling(i + 1 == size ? 0 : m_children[i + 1].get());
-}
-
-#ifndef NDEBUG
</del><span class="cx"> void ProfileNode::debugPrint()
</span><span class="cx"> {
</span><span class="cx">     CalculateProfileSubtreeDataFunctor functor;
</span><span class="lines">@@ -187,7 +146,7 @@
</span><span class="cx"> 
</span><span class="cx">     dataLogF(&quot;Function Name %s %zu SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n&quot;,
</span><span class="cx">         functionName().utf8().data(),
</span><del>-        numberOfCalls(), nodeSelfTime, nodeSelfTime / rootTotalTime * 100.0, nodeTotalTime, nodeTotalTime / rootTotalTime * 100.0,
</del><ins>+        m_calls.size(), nodeSelfTime, nodeSelfTime / rootTotalTime * 100.0, nodeTotalTime, nodeTotalTime / rootTotalTime * 100.0,
</ins><span class="cx">         m_nextSibling ? m_nextSibling-&gt;functionName().utf8().data() : &quot;&quot;);
</span><span class="cx"> 
</span><span class="cx">     ++indentLevel;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileNode.h (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileNode.h        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/JavaScriptCore/profiler/ProfileNode.h        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -63,10 +63,18 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             double startTime() const { return m_startTime; }
</span><del>-            void setStartTime(double time) { m_startTime = time; }
</del><ins>+            void setStartTime(double time)
+            {
+                ASSERT_ARG(time, time &gt;= 0.0);
+                m_startTime = time;
+            }
</ins><span class="cx"> 
</span><span class="cx">             double totalTime() const { return m_totalTime; }
</span><del>-            void setTotalTime(double time) { m_totalTime = time; }
</del><ins>+            void setTotalTime(double time)
+            {
+                ASSERT_ARG(time, time &gt;= 0.0);
+                m_totalTime = time;
+            }
</ins><span class="cx"> 
</span><span class="cx">         private:
</span><span class="cx">             double m_startTime;
</span><span class="lines">@@ -75,12 +83,6 @@
</span><span class="cx"> 
</span><span class="cx">         bool operator==(ProfileNode* node) { return m_callIdentifier == node-&gt;callIdentifier(); }
</span><span class="cx"> 
</span><del>-        ProfileNode* willExecute(ExecState* callerCallFrame, const CallIdentifier&amp;);
-        ProfileNode* didExecute();
-
-        void stopProfiling();
-
-        // CallIdentifier members
</del><span class="cx">         ExecState* callerCallFrame() const { return m_callerCallFrame; }
</span><span class="cx">         const CallIdentifier&amp; callIdentifier() const { return m_callIdentifier; }
</span><span class="cx">         unsigned id() const { return m_callIdentifier.hash(); }
</span><span class="lines">@@ -89,39 +91,35 @@
</span><span class="cx">         unsigned lineNumber() const { return m_callIdentifier.lineNumber(); }
</span><span class="cx">         unsigned columnNumber() const { return m_callIdentifier.columnNumber(); }
</span><span class="cx"> 
</span><del>-        // Relationships
</del><span class="cx">         ProfileNode* parent() const { return m_parent; }
</span><span class="cx">         void setParent(ProfileNode* parent) { m_parent = parent; }
</span><span class="cx"> 
</span><del>-        ProfileNode* nextSibling() const { return m_nextSibling; }
-        void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
-
</del><span class="cx">         const Vector&lt;Call&gt;&amp; calls() const { return m_calls; }
</span><span class="cx">         Call&amp; lastCall() { ASSERT(!m_calls.isEmpty()); return m_calls.last(); }
</span><del>-        size_t numberOfCalls() const { return m_calls.size(); }
</del><ins>+        void appendCall(Call call) { m_calls.append(call); }
</ins><span class="cx"> 
</span><del>-        // Children members
</del><span class="cx">         const Vector&lt;RefPtr&lt;ProfileNode&gt;&gt;&amp; children() const { return m_children; }
</span><del>-        ProfileNode* firstChild() const { return m_children.size() ? m_children.first().get() : 0; }
-        ProfileNode* lastChild() const { return m_children.size() ? m_children.last().get() : 0; }
</del><ins>+        ProfileNode* firstChild() const { return m_children.size() ? m_children.first().get() : nullptr; }
+        ProfileNode* lastChild() const { return m_children.size() ? m_children.last().get() : nullptr; }
+
</ins><span class="cx">         void removeChild(ProfileNode*);
</span><del>-        void addChild(PassRefPtr&lt;ProfileNode&gt; prpChild);
-        void insertNode(PassRefPtr&lt;ProfileNode&gt; prpNode);
</del><ins>+        void addChild(PassRefPtr&lt;ProfileNode&gt;);
+        // Reparent our child nodes to the passed node, and make it a child node of |this|.
+        void spliceNode(PassRefPtr&lt;ProfileNode&gt;);
</ins><span class="cx"> 
</span><del>-        template &lt;typename Functor&gt; void forEachNodePostorder(Functor&amp;);
-
</del><span class="cx"> #ifndef NDEBUG
</span><span class="cx">         struct ProfileSubtreeData {
</span><span class="cx">             HashMap&lt;ProfileNode*, std::pair&lt;double, double&gt;&gt; selfAndTotalTimes;
</span><span class="cx">             double rootTotalTime;
</span><span class="cx">         };
</span><span class="cx"> 
</span><del>-        const char* c_str() const { return m_callIdentifier; }
</del><span class="cx">         // Use these functions to dump the subtree rooted at this node.
</span><span class="cx">         void debugPrint();
</span><span class="cx">         void debugPrintSampleStyle();
</span><span class="cx"> 
</span><span class="cx">         // These are used to recursively print entire subtrees using precomputed self and total times.
</span><ins>+        template &lt;typename Functor&gt; void forEachNodePostorder(Functor&amp;);
+
</ins><span class="cx">         void debugPrintRecursively(int indentLevel, const ProfileSubtreeData&amp;);
</span><span class="cx">         double debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount&amp;, const ProfileSubtreeData&amp;);
</span><span class="cx"> #endif
</span><span class="lines">@@ -132,20 +130,25 @@
</span><span class="cx">         ProfileNode(ExecState* callerCallFrame, const CallIdentifier&amp;, ProfileNode* parentNode);
</span><span class="cx">         ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy);
</span><span class="cx"> 
</span><del>-        void startTimer();
-        void resetChildrensSiblings();
-        void endAndRecordCall();
</del><ins>+#ifndef NDEBUG
+        ProfileNode* nextSibling() const { return m_nextSibling; }
+        void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
+
</ins><span class="cx">         ProfileNode* traverseNextNodePostOrder() const;
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx">         ExecState* m_callerCallFrame;
</span><span class="cx">         CallIdentifier m_callIdentifier;
</span><span class="cx">         ProfileNode* m_parent;
</span><del>-        ProfileNode* m_nextSibling;
-
</del><span class="cx">         Vector&lt;Call&gt; m_calls;
</span><span class="cx">         Vector&lt;RefPtr&lt;ProfileNode&gt;&gt; m_children;
</span><ins>+
+#ifndef NDEBUG
+        ProfileNode* m_nextSibling;
+#endif
</ins><span class="cx">     };
</span><span class="cx"> 
</span><ins>+#ifndef NDEBUG
</ins><span class="cx">     template &lt;typename Functor&gt; inline void ProfileNode::forEachNodePostorder(Functor&amp; functor)
</span><span class="cx">     {
</span><span class="cx">         ProfileNode* currentNode = this;
</span><span class="lines">@@ -162,7 +165,6 @@
</span><span class="cx">         functor(endNode);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-#ifndef NDEBUG
</del><span class="cx">     struct CalculateProfileSubtreeDataFunctor {
</span><span class="cx">         void operator()(ProfileNode* node)
</span><span class="cx">         {
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/WebCore/ChangeLog        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2014-09-04  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
+
+        LegacyProfiler: ProfileNodes should be used more like structs
+        https://bugs.webkit.org/show_bug.cgi?id=136381
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/ScriptProfileNode.idl: Remove an unused property.
+
</ins><span class="cx"> 2014-09-04  Renato Nagy  &lt;rnagy@inf.u-szeged.hu&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove Qt cruft: MIMESniffing.cpp and MIMESniffing.h
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorScriptProfileNodeidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/ScriptProfileNode.idl (173261 => 173262)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/ScriptProfileNode.idl        2014-09-04 16:46:29 UTC (rev 173261)
+++ trunk/Source/WebCore/inspector/ScriptProfileNode.idl        2014-09-04 17:00:22 UTC (rev 173262)
</span><span class="lines">@@ -36,7 +36,5 @@
</span><span class="cx">     readonly attribute unsigned long lineNumber;
</span><span class="cx">     readonly attribute unsigned long columnNumber;
</span><span class="cx"> 
</span><del>-    readonly attribute unsigned long numberOfCalls;
-
</del><span class="cx">     sequence&lt;ScriptProfileNode&gt; children();
</span><span class="cx"> };
</span></span></pre>
</div>
</div>

</body>
</html>