<!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>[173199] trunk</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/173199">173199</a></dd>
<dt>Author</dt> <dd>burg@cs.washington.edu</dd>
<dt>Date</dt> <dd>2014-09-02 21:58:55 -0700 (Tue, 02 Sep 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>LegacyProfiler: remove redundant ProfileNode members and other cleanup
https://bugs.webkit.org/show_bug.cgi?id=136380

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

ProfileNode's selfTime and totalTime members are redundant and only used
for dumping profile data from debug-only code. Remove the members and compute
the same data on-demand when necessary using a postorder traversal functor.

Remove ProfileNode.head since it is only used to calculate percentages for
dumped profile data. This can be explicitly passed around when needed.

Rename Profile.head to Profile.rootNode, and other various renamings.

Rearrange some header includes so that touching LegacyProfiler-related headers
will no longer cause a full rebuild.

* inspector/JSConsoleClient.cpp: Add header include.
* inspector/agents/InspectorProfilerAgent.cpp:
(Inspector::InspectorProfilerAgent::buildProfileInspectorObject):
* inspector/protocol/Profiler.json: Remove unused Profile.idleTime member.
* jit/JIT.h: Remove header include.
* jit/JITCode.h: Remove header include.
* jit/JITOperations.cpp: Sort and add header include.
* llint/LLIntSlowPaths.cpp: Sort and add header include.
* profiler/Profile.cpp: Rename the debug dumping functions. Move the node
postorder traversal code to ProfileNode so we can traverse any subtree.
(JSC::Profile::Profile):
(JSC::Profile::debugPrint):
(JSC::Profile::debugPrintSampleStyle):
(JSC::Profile::forEach): Deleted.
(JSC::Profile::debugPrintData): Deleted.
(JSC::Profile::debugPrintDataSampleStyle): Deleted.
* profiler/Profile.h:
* profiler/ProfileGenerator.cpp:
(JSC::ProfileGenerator::ProfileGenerator):
(JSC::AddParentForConsoleStartFunctor::AddParentForConsoleStartFunctor):
(JSC::AddParentForConsoleStartFunctor::operator()):
(JSC::ProfileGenerator::addParentForConsoleStart):
(JSC::ProfileGenerator::didExecute):
(JSC::StopProfilingFunctor::operator()):
(JSC::ProfileGenerator::stopProfiling):
(JSC::ProfileGenerator::removeProfileStart):
(JSC::ProfileGenerator::removeProfileEnd):
* profiler/ProfileGenerator.h:
* profiler/ProfileNode.cpp:
(JSC::ProfileNode::ProfileNode):
(JSC::ProfileNode::willExecute):
(JSC::ProfileNode::removeChild):
(JSC::ProfileNode::stopProfiling):
(JSC::ProfileNode::endAndRecordCall):
(JSC::ProfileNode::debugPrint):
(JSC::ProfileNode::debugPrintSampleStyle):
(JSC::ProfileNode::debugPrintRecursively):
(JSC::ProfileNode::debugPrintSampleStyleRecursively):
(JSC::ProfileNode::debugPrintData): Deleted.
(JSC::ProfileNode::debugPrintDataSampleStyle): Deleted.
* profiler/ProfileNode.h: Calculate per-node self and total times using a postorder traversal.
The forEachNodePostorder functor traverses the subtree rooted at |this|.
(JSC::ProfileNode::create):
(JSC::ProfileNode::calls):
(JSC::ProfileNode::forEachNodePostorder):
(JSC::CalculateProfileSubtreeDataFunctor::returnValue):
(JSC::CalculateProfileSubtreeDataFunctor::operator()):
(JSC::ProfileNode::head): Deleted.
(JSC::ProfileNode::setHead): Deleted.
(JSC::ProfileNode::totalTime): Deleted.
(JSC::ProfileNode::setTotalTime): Deleted.
(JSC::ProfileNode::selfTime): Deleted.
(JSC::ProfileNode::setSelfTime): Deleted.
(JSC::ProfileNode::totalPercent): Deleted.
(JSC::ProfileNode::selfPercent): Deleted.
* runtime/ConsoleClient.h: Remove header include.

Source/WebCore:

Remove Profile.idleTime, rename head to rootNode, and remove ProfileNode members.

Covered by existing tests.

* inspector/ScriptProfile.idl:
* inspector/ScriptProfileNode.idl:
* inspector/TimelineRecordFactory.cpp:

Source/WebInspectorUI:

Remove unused Profile.idleTime member.

* UserInterface/Models/Profile.js:
(WebInspector.Profile.prototype.get idleTime): Deleted.
* UserInterface/Models/ScriptTimelineRecord.js:
(WebInspector.ScriptTimelineRecord.prototype._initializeProfileFromPayload):

LayoutTests:

Renamed Profile.head to Profile.rootNode.

* fast/profiler/resources/profiler-test-JS-resources.js:
(printHeavyProfilesDataWithoutTime):
(printProfilesDataWithoutTime):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastprofilerresourcesprofilertestJSresourcesjs">trunk/LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCodeh">trunk/Source/JavaScriptCore/jit/JITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfilecpp">trunk/Source/JavaScriptCore/profiler/Profile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreprofilerProfileh">trunk/Source/JavaScriptCore/profiler/Profile.h</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="#trunkSourceJavaScriptCoreruntimeConsoleClienth">trunk/Source/JavaScriptCore/runtime/ConsoleClient.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectorScriptProfileidl">trunk/Source/WebCore/inspector/ScriptProfile.idl</a></li>
<li><a href="#trunkSourceWebCoreinspectorScriptProfileNodeidl">trunk/Source/WebCore/inspector/ScriptProfileNode.idl</a></li>
<li><a href="#trunkSourceWebCoreinspectorTimelineRecordFactorycpp">trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsProfilejs">trunk/Source/WebInspectorUI/UserInterface/Models/Profile.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsScriptTimelineRecordjs">trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/LayoutTests/ChangeLog        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
+
+        LegacyProfiler: remove redundant ProfileNode members and other cleanup
+        https://bugs.webkit.org/show_bug.cgi?id=136380
+
+        Reviewed by Timothy Hatcher.
+
+        Renamed Profile.head to Profile.rootNode.
+
+        * fast/profiler/resources/profiler-test-JS-resources.js:
+        (printHeavyProfilesDataWithoutTime):
+        (printProfilesDataWithoutTime):
+
</ins><span class="cx"> 2014-09-02  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Avoid backing store allocation with some combinations of replaced elements, masking and visibility:hidden
</span></span></pre></div>
<a id="trunkLayoutTestsfastprofilerresourcesprofilertestJSresourcesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">     var profiles = internals.consoleProfiles;
</span><span class="cx">     for (var i = 0; i &lt; profiles.length; ++i) {
</span><span class="cx">         preElement.appendChild(document.createTextNode(&quot;Profile title: &quot; + profiles[i].title + &quot;\n&quot;));
</span><del>-        printProfileNodeWithoutTime(preElement, profiles[i].heavyProfile.head, 0);
</del><ins>+        printProfileNodeWithoutTime(preElement, profiles[i].heavyProfile.rootNode, 0);
</ins><span class="cx">         preElement.appendChild(document.createTextNode(&quot;\n&quot;));
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx">     var profiles = internals.consoleProfiles;
</span><span class="cx">     for (var i = 0; i &lt; profiles.length; ++i) {
</span><span class="cx">         preElement.appendChild(document.createTextNode(&quot;Profile title: &quot; + profiles[i].title + &quot;\n&quot;));
</span><del>-        printProfileNodeWithoutTime(preElement, profiles[i].head, 0);
</del><ins>+        printProfileNodeWithoutTime(preElement, profiles[i].rootNode, 0);
</ins><span class="cx">         preElement.appendChild(document.createTextNode(&quot;\n&quot;));
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -1,5 +1,81 @@
</span><span class="cx"> 2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
</span><span class="cx"> 
</span><ins>+        LegacyProfiler: remove redundant ProfileNode members and other cleanup
+        https://bugs.webkit.org/show_bug.cgi?id=136380
+
+        Reviewed by Timothy Hatcher.
+
+        ProfileNode's selfTime and totalTime members are redundant and only used
+        for dumping profile data from debug-only code. Remove the members and compute
+        the same data on-demand when necessary using a postorder traversal functor.
+
+        Remove ProfileNode.head since it is only used to calculate percentages for
+        dumped profile data. This can be explicitly passed around when needed.
+
+        Rename Profile.head to Profile.rootNode, and other various renamings.
+
+        Rearrange some header includes so that touching LegacyProfiler-related headers
+        will no longer cause a full rebuild.
+
+        * inspector/JSConsoleClient.cpp: Add header include.
+        * inspector/agents/InspectorProfilerAgent.cpp:
+        (Inspector::InspectorProfilerAgent::buildProfileInspectorObject):
+        * inspector/protocol/Profiler.json: Remove unused Profile.idleTime member.
+        * jit/JIT.h: Remove header include.
+        * jit/JITCode.h: Remove header include.
+        * jit/JITOperations.cpp: Sort and add header include.
+        * llint/LLIntSlowPaths.cpp: Sort and add header include.
+        * profiler/Profile.cpp: Rename the debug dumping functions. Move the node
+        postorder traversal code to ProfileNode so we can traverse any subtree.
+        (JSC::Profile::Profile):
+        (JSC::Profile::debugPrint):
+        (JSC::Profile::debugPrintSampleStyle):
+        (JSC::Profile::forEach): Deleted.
+        (JSC::Profile::debugPrintData): Deleted.
+        (JSC::Profile::debugPrintDataSampleStyle): Deleted.
+        * profiler/Profile.h:
+        * profiler/ProfileGenerator.cpp:
+        (JSC::ProfileGenerator::ProfileGenerator):
+        (JSC::AddParentForConsoleStartFunctor::AddParentForConsoleStartFunctor):
+        (JSC::AddParentForConsoleStartFunctor::operator()):
+        (JSC::ProfileGenerator::addParentForConsoleStart):
+        (JSC::ProfileGenerator::didExecute):
+        (JSC::StopProfilingFunctor::operator()):
+        (JSC::ProfileGenerator::stopProfiling):
+        (JSC::ProfileGenerator::removeProfileStart):
+        (JSC::ProfileGenerator::removeProfileEnd):
+        * profiler/ProfileGenerator.h:
+        * profiler/ProfileNode.cpp:
+        (JSC::ProfileNode::ProfileNode):
+        (JSC::ProfileNode::willExecute):
+        (JSC::ProfileNode::removeChild):
+        (JSC::ProfileNode::stopProfiling):
+        (JSC::ProfileNode::endAndRecordCall):
+        (JSC::ProfileNode::debugPrint):
+        (JSC::ProfileNode::debugPrintSampleStyle):
+        (JSC::ProfileNode::debugPrintRecursively):
+        (JSC::ProfileNode::debugPrintSampleStyleRecursively):
+        (JSC::ProfileNode::debugPrintData): Deleted.
+        (JSC::ProfileNode::debugPrintDataSampleStyle): Deleted.
+        * profiler/ProfileNode.h: Calculate per-node self and total times using a postorder traversal.
+        The forEachNodePostorder functor traverses the subtree rooted at |this|.
+        (JSC::ProfileNode::create):
+        (JSC::ProfileNode::calls):
+        (JSC::ProfileNode::forEachNodePostorder):
+        (JSC::CalculateProfileSubtreeDataFunctor::returnValue):
+        (JSC::CalculateProfileSubtreeDataFunctor::operator()):
+        (JSC::ProfileNode::head): Deleted.
+        (JSC::ProfileNode::setHead): Deleted.
+        (JSC::ProfileNode::totalTime): Deleted.
+        (JSC::ProfileNode::setTotalTime): Deleted.
+        (JSC::ProfileNode::selfTime): Deleted.
+        (JSC::ProfileNode::setSelfTime): Deleted.
+        (JSC::ProfileNode::totalPercent): Deleted.
+        (JSC::ProfileNode::selfPercent): Deleted.
+        * runtime/ConsoleClient.h: Remove header include.
+
+2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
+
</ins><span class="cx">         Web Inspector: remove ProfilerAgent and legacy profiler files in the frontend
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=136462
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -44,7 +44,6 @@
</span><span class="cx"> #include &quot;JITDisassembler.h&quot;
</span><span class="cx"> #include &quot;JITInlineCacheGenerator.h&quot;
</span><span class="cx"> #include &quot;JSInterfaceJIT.h&quot;
</span><del>-#include &quot;LegacyProfiler.h&quot;
</del><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;ResultType.h&quot;
</span><span class="cx"> #include &quot;SamplingTool.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCode.h (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCode.h        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/jit/JITCode.h        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -31,7 +31,6 @@
</span><span class="cx"> #include &quot;Disassembler.h&quot;
</span><span class="cx"> #include &quot;JITStubs.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><del>-#include &quot;LegacyProfiler.h&quot;
</del><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;RegisterPreservationMode.h&quot;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -43,13 +43,14 @@
</span><span class="cx"> #include &quot;HostCallReturnValue.h&quot;
</span><span class="cx"> #include &quot;JIT.h&quot;
</span><span class="cx"> #include &quot;JITToDFGDeferredCompilationCallback.h&quot;
</span><ins>+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;JSGlobalObjectFunctions.h&quot;
</span><span class="cx"> #include &quot;JSNameScope.h&quot;
</span><span class="cx"> #include &quot;JSPropertyNameEnumerator.h&quot;
</span><span class="cx"> #include &quot;JSStackInlines.h&quot;
</span><span class="cx"> #include &quot;JSWithScope.h&quot;
</span><ins>+#include &quot;LegacyProfiler.h&quot;
</ins><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</span><del>-#include &quot;JSCInlines.h&quot;
</del><span class="cx"> #include &quot;Repatch.h&quot;
</span><span class="cx"> #include &quot;RepatchBuffer.h&quot;
</span><span class="cx"> #include &quot;TestRunnerUtils.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;LLIntSlowPaths.h&quot;
</span><ins>+
</ins><span class="cx"> #include &quot;Arguments.h&quot;
</span><span class="cx"> #include &quot;ArrayConstructor.h&quot;
</span><span class="cx"> #include &quot;CallFrame.h&quot;
</span><span class="lines">@@ -38,6 +39,7 @@
</span><span class="cx"> #include &quot;JIT.h&quot;
</span><span class="cx"> #include &quot;JITExceptions.h&quot;
</span><span class="cx"> #include &quot;JSActivation.h&quot;
</span><ins>+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;JSGlobalObjectFunctions.h&quot;
</span><span class="cx"> #include &quot;JSNameScope.h&quot;
</span><span class="lines">@@ -46,9 +48,9 @@
</span><span class="cx"> #include &quot;JSWithScope.h&quot;
</span><span class="cx"> #include &quot;LLIntCommon.h&quot;
</span><span class="cx"> #include &quot;LLIntExceptions.h&quot;
</span><ins>+#include &quot;LegacyProfiler.h&quot;
</ins><span class="cx"> #include &quot;LowLevelInterpreter.h&quot;
</span><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</span><del>-#include &quot;JSCInlines.h&quot;
</del><span class="cx"> #include &quot;ProtoCallFrame.h&quot;
</span><span class="cx"> #include &quot;StructureRareDataInlines.h&quot;
</span><span class="cx"> #include &lt;wtf/StringPrintStream.h&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/Profile.cpp (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/Profile.cpp        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/profiler/Profile.cpp        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -39,38 +39,25 @@
</span><span class="cx"> Profile::Profile(const String&amp; title, unsigned uid)
</span><span class="cx">     : m_title(title)
</span><span class="cx">     , m_uid(uid)
</span><del>-    , m_idleTime(0)
</del><span class="cx"> {
</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><del>-    m_head = ProfileNode::create(0, CallIdentifier(ASCIILiteral(&quot;Thread_1&quot;), String(), 0, 0), 0, 0);
</del><ins>+    m_rootNode = ProfileNode::create(nullptr, CallIdentifier(ASCIILiteral(&quot;Thread_1&quot;), String(), 0, 0), nullptr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Profile::~Profile()
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Profile::forEach(void (ProfileNode::*function)())
-{
-    ProfileNode* currentNode = m_head-&gt;firstChild();
-    for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode-&gt;firstChild())
-        currentNode = nextNode;
-
-    if (!currentNode)
-        currentNode = m_head.get();
-
-    ProfileNode* endNode = m_head-&gt;traverseNextNodePostOrder();
-    while (currentNode &amp;&amp; currentNode != endNode) {
-        (currentNode-&gt;*function)();
-        currentNode = currentNode-&gt;traverseNextNodePostOrder();
-    } 
-}
-
</del><span class="cx"> #ifndef NDEBUG
</span><del>-void Profile::debugPrintData() const
</del><ins>+void Profile::debugPrint()
</ins><span class="cx"> {
</span><ins>+    CalculateProfileSubtreeDataFunctor functor;
+    m_rootNode-&gt;forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
</ins><span class="cx">     dataLogF(&quot;Call graph:\n&quot;);
</span><del>-    m_head-&gt;debugPrintData(0);
</del><ins>+    m_rootNode-&gt;debugPrintRecursively(0, data);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> typedef WTF::KeyValuePair&lt;FunctionCallHashCount::ValueType, unsigned&gt; NameCountPair;
</span><span class="lines">@@ -80,13 +67,17 @@
</span><span class="cx">     return a.value &gt; b.value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Profile::debugPrintDataSampleStyle() const
</del><ins>+void Profile::debugPrintSampleStyle()
</ins><span class="cx"> {
</span><span class="cx">     typedef Vector&lt;NameCountPair&gt; NameCountPairVector;
</span><span class="cx"> 
</span><ins>+    CalculateProfileSubtreeDataFunctor functor;
+    m_rootNode-&gt;forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
</ins><span class="cx">     FunctionCallHashCount countedFunctions;
</span><span class="cx">     dataLogF(&quot;Call graph:\n&quot;);
</span><del>-    m_head-&gt;debugPrintDataSampleStyle(0, countedFunctions);
</del><ins>+    m_rootNode-&gt;debugPrintSampleStyleRecursively(0, countedFunctions, data);
</ins><span class="cx"> 
</span><span class="cx">     dataLogF(&quot;\nTotal number in stack:\n&quot;);
</span><span class="cx">     NameCountPairVector sortedFunctions(countedFunctions.size());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/Profile.h (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/Profile.h        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/profiler/Profile.h        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -41,19 +41,12 @@
</span><span class="cx">     const String&amp; title() const { return m_title; }
</span><span class="cx">     unsigned uid() const { return m_uid; }
</span><span class="cx"> 
</span><del>-    ProfileNode* head() const { return m_head.get(); }
-    void setHead(PassRefPtr&lt;ProfileNode&gt; head) { m_head = head; }
</del><ins>+    ProfileNode* rootNode() const { return m_rootNode.get(); }
+    void setRootNode(PassRefPtr&lt;ProfileNode&gt; rootNode) { m_rootNode = rootNode; }
</ins><span class="cx"> 
</span><del>-    double totalTime() const { return m_head-&gt;totalTime(); }
-
-    double idleTime() const { return m_idleTime; }
-    void setIdleTime(double idleTime) { m_idleTime = idleTime; }
-
-    void forEach(void (ProfileNode::*)());
-
</del><span class="cx"> #ifndef NDEBUG
</span><del>-    void debugPrintData() const;
-    void debugPrintDataSampleStyle() const;
</del><ins>+    void debugPrint();
+    void debugPrintSampleStyle();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="lines">@@ -64,9 +57,8 @@
</span><span class="cx">     void removeProfileEnd();
</span><span class="cx"> 
</span><span class="cx">     String m_title;
</span><del>-    RefPtr&lt;ProfileNode&gt; m_head;
</del><ins>+    RefPtr&lt;ProfileNode&gt; m_rootNode;
</ins><span class="cx">     unsigned m_uid;
</span><del>-    double m_idleTime;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -50,18 +50,18 @@
</span><span class="cx">     , m_foundConsoleStartParent(false)
</span><span class="cx"> {
</span><span class="cx">     m_profile = Profile::create(title, uid);
</span><del>-    m_currentNode = m_head = m_profile-&gt;head();
</del><ins>+    m_currentNode = m_rootNode = m_profile-&gt;rootNode();
</ins><span class="cx">     if (exec)
</span><span class="cx">         addParentForConsoleStart(exec);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> class AddParentForConsoleStartFunctor {
</span><span class="cx"> public:
</span><del>-    AddParentForConsoleStartFunctor(ExecState* exec, RefPtr&lt;ProfileNode&gt;&amp; head, RefPtr&lt;ProfileNode&gt;&amp; currentNode)
</del><ins>+    AddParentForConsoleStartFunctor(ExecState* exec, RefPtr&lt;ProfileNode&gt;&amp; rootNode, RefPtr&lt;ProfileNode&gt;&amp; currentNode)
</ins><span class="cx">         : m_exec(exec)
</span><span class="cx">         , m_hasSkippedFirstFrame(false)
</span><span class="cx">         , m_foundParent(false)
</span><del>-        , m_head(head)
</del><ins>+        , m_rootNode(rootNode)
</ins><span class="cx">         , m_currentNode(currentNode)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="lines">@@ -78,8 +78,8 @@
</span><span class="cx">         unsigned line = 0;
</span><span class="cx">         unsigned column = 0;
</span><span class="cx">         visitor-&gt;computeLineAndColumn(line, column);
</span><del>-        m_currentNode = ProfileNode::create(m_exec, LegacyProfiler::createCallIdentifier(m_exec, visitor-&gt;callee(), visitor-&gt;sourceURL(), line, column), m_head.get(), m_head.get());
-        m_head-&gt;insertNode(m_currentNode.get());
</del><ins>+        m_currentNode = ProfileNode::create(m_exec, LegacyProfiler::createCallIdentifier(m_exec, visitor-&gt;callee(), visitor-&gt;sourceURL(), line, column), m_rootNode.get());
+        m_rootNode-&gt;insertNode(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">@@ -88,14 +88,14 @@
</span><span class="cx"> private:
</span><span class="cx">     ExecState* m_exec;
</span><span class="cx">     bool m_hasSkippedFirstFrame;
</span><del>-    bool m_foundParent; 
-    RefPtr&lt;ProfileNode&gt;&amp; m_head;
</del><ins>+    bool m_foundParent;
+    RefPtr&lt;ProfileNode&gt;&amp; m_rootNode;
</ins><span class="cx">     RefPtr&lt;ProfileNode&gt;&amp; m_currentNode;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
</span><span class="cx"> {
</span><del>-    AddParentForConsoleStartFunctor functor(exec, m_head, m_currentNode);
</del><ins>+    AddParentForConsoleStartFunctor functor(exec, m_rootNode, m_currentNode);
</ins><span class="cx">     exec-&gt;iterate(functor);
</span><span class="cx"> 
</span><span class="cx">     m_foundConsoleStartParent = functor.foundParent();
</span><span class="lines">@@ -134,7 +134,7 @@
</span><span class="cx"> 
</span><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_head.get(), m_currentNode.get());
</del><ins>+        RefPtr&lt;ProfileNode&gt; returningNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
</ins><span class="cx">         returningNode-&gt;lastCall().setStartTime(m_currentNode-&gt;lastCall().startTime());
</span><span class="cx">         returningNode-&gt;didExecute();
</span><span class="cx">         m_currentNode-&gt;insertNode(returningNode.release());
</span><span class="lines">@@ -155,9 +155,16 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+struct StopProfilingFunctor {
+    void operator()(ProfileNode* node) { node-&gt;stopProfiling(); }
+};
+
</ins><span class="cx"> void ProfileGenerator::stopProfiling()
</span><span class="cx"> {
</span><del>-    m_profile-&gt;forEach(&amp;ProfileNode::stopProfiling);
</del><ins>+    // 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);
</ins><span class="cx"> 
</span><span class="cx">     if (m_foundConsoleStartParent) {
</span><span class="cx">         removeProfileStart();
</span><span class="lines">@@ -169,25 +176,18 @@
</span><span class="cx">     // Set the current node to the parent, because we are in a call that
</span><span class="cx">     // will not get didExecute call.
</span><span class="cx">     m_currentNode = m_currentNode-&gt;parent();
</span><del>-
-    if (double headSelfTime = m_head-&gt;selfTime()) {
-        m_head-&gt;setSelfTime(0.0);
-        m_profile-&gt;setIdleTime(headSelfTime);
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</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><span class="cx">     ProfileNode* currentNode = 0;
</span><del>-    for (ProfileNode* next = m_head.get(); next; next = next-&gt;firstChild())
</del><ins>+    for (ProfileNode* next = m_rootNode.get(); next; next = next-&gt;firstChild())
</ins><span class="cx">         currentNode = next;
</span><span class="cx"> 
</span><span class="cx">     if (currentNode-&gt;callIdentifier().functionName() != &quot;profile&quot;)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    // Attribute the time of the node aobut to be removed to the self time of its parent
-    currentNode-&gt;parent()-&gt;setSelfTime(currentNode-&gt;parent()-&gt;selfTime() + currentNode-&gt;totalTime());
</del><span class="cx">     currentNode-&gt;parent()-&gt;removeChild(currentNode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -195,15 +195,12 @@
</span><span class="cx"> void ProfileGenerator::removeProfileEnd()
</span><span class="cx"> {
</span><span class="cx">     ProfileNode* currentNode = 0;
</span><del>-    for (ProfileNode* next = m_head.get(); next; next = next-&gt;lastChild())
</del><ins>+    for (ProfileNode* next = m_rootNode.get(); next; next = next-&gt;lastChild())
</ins><span class="cx">         currentNode = next;
</span><span class="cx"> 
</span><span class="cx">     if (currentNode-&gt;callIdentifier().functionName() != &quot;profileEnd&quot;)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    // Attribute the time of the node aobut to be removed to the self time of its parent
-    currentNode-&gt;parent()-&gt;setSelfTime(currentNode-&gt;parent()-&gt;selfTime() + currentNode-&gt;totalTime());
-
</del><span class="cx">     ASSERT(currentNode-&gt;callIdentifier() == (currentNode-&gt;parent()-&gt;children()[currentNode-&gt;parent()-&gt;children().size() - 1])-&gt;callIdentifier());
</span><span class="cx">     currentNode-&gt;parent()-&gt;removeChild(currentNode);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileGenerator.h (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileGenerator.h        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/profiler/ProfileGenerator.h        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx">  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><del>- 
</del><ins>+
</ins><span class="cx"> #ifndef ProfileGenerator_h
</span><span class="cx"> #define ProfileGenerator_h
</span><span class="cx"> 
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx">     class JSGlobalObject;
</span><span class="cx">     class Profile;
</span><span class="cx">     class ProfileNode;
</span><del>-    struct CallIdentifier;    
</del><ins>+    struct CallIdentifier;
</ins><span class="cx"> 
</span><span class="cx">     class ProfileGenerator : public RefCounted&lt;ProfileGenerator&gt;  {
</span><span class="cx">     public:
</span><span class="lines">@@ -70,7 +70,7 @@
</span><span class="cx">         RefPtr&lt;Profile&gt; m_profile;
</span><span class="cx">         JSGlobalObject* m_origin;
</span><span class="cx">         unsigned m_profileGroup;
</span><del>-        RefPtr&lt;ProfileNode&gt; m_head;
</del><ins>+        RefPtr&lt;ProfileNode&gt; m_rootNode;
</ins><span class="cx">         RefPtr&lt;ProfileNode&gt; m_currentNode;
</span><span class="cx">         bool m_foundConsoleStartParent;
</span><span class="cx">     };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileNode.cpp (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileNode.cpp        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/profiler/ProfileNode.cpp        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -38,26 +38,20 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier&amp; callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
</del><ins>+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier&amp; callIdentifier, ProfileNode* parentNode)
</ins><span class="cx">     : m_callerCallFrame(callerCallFrame)
</span><span class="cx">     , m_callIdentifier(callIdentifier)
</span><del>-    , m_head(headNode)
</del><span class="cx">     , m_parent(parentNode)
</span><span class="cx">     , m_nextSibling(nullptr)
</span><del>-    , m_totalTime(0)
-    , m_selfTime(0)
</del><span class="cx"> {
</span><span class="cx">     startTimer();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy)
</del><ins>+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
</ins><span class="cx">     : m_callerCallFrame(callerCallFrame)
</span><span class="cx">     , m_callIdentifier(nodeToCopy-&gt;callIdentifier())
</span><del>-    , m_head(headNode)
</del><span class="cx">     , m_parent(nodeToCopy-&gt;parent())
</span><del>-    , m_nextSibling(0)
-    , m_totalTime(nodeToCopy-&gt;totalTime())
-    , m_selfTime(nodeToCopy-&gt;selfTime())
</del><ins>+    , m_nextSibling(nullptr)
</ins><span class="cx">     , m_calls(nodeToCopy-&gt;calls())
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -71,7 +65,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    RefPtr&lt;ProfileNode&gt; newChild = ProfileNode::create(callerCallFrame, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
</del><ins>+    RefPtr&lt;ProfileNode&gt; newChild = ProfileNode::create(callerCallFrame, callIdentifier, this);
</ins><span class="cx">     if (m_children.size())
</span><span class="cx">         m_children.last()-&gt;setNextSibling(newChild.get());
</span><span class="cx">     m_children.append(newChild.release());
</span><span class="lines">@@ -104,7 +98,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     resetChildrensSiblings();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -125,13 +119,6 @@
</span><span class="cx"> 
</span><span class="cx">     if (isnan(m_calls.last().totalTime()))
</span><span class="cx">         endAndRecordCall();
</span><del>-
-    // Because we iterate in post order all of our children have been stopped before us.
-    for (unsigned i = 0; i &lt; m_children.size(); ++i)
-        m_selfTime += m_children[i]-&gt;totalTime();
-
-    ASSERT(m_selfTime &lt;= m_totalTime);
-    m_selfTime = m_totalTime - m_selfTime;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ProfileNode* ProfileNode::traverseNextNodePostOrder() const
</span><span class="lines">@@ -150,8 +137,6 @@
</span><span class="cx">     ASSERT(isnan(last.totalTime()));
</span><span class="cx"> 
</span><span class="cx">     last.setTotalTime(currentTime() - last.startTime());
</span><del>-
-    m_totalTime += last.totalTime();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ProfileNode::startTimer()
</span><span class="lines">@@ -167,32 +152,63 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><del>-void ProfileNode::debugPrintData(int indentLevel) const
</del><ins>+void ProfileNode::debugPrint()
</ins><span class="cx"> {
</span><ins>+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+    debugPrintRecursively(0, data);
+}
+
+void ProfileNode::debugPrintSampleStyle()
+{
+    FunctionCallHashCount countedFunctions;
+
+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+    debugPrintSampleStyleRecursively(0, countedFunctions, data);
+}
+
+void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData&amp; data)
+{
</ins><span class="cx">     // Print function names
</span><span class="cx">     for (int i = 0; i &lt; indentLevel; ++i)
</span><span class="cx">         dataLogF(&quot;  &quot;);
</span><span class="cx"> 
</span><ins>+    auto it = data.selfAndTotalTimes.find(this);
+    ASSERT(it != data.selfAndTotalTimes.end());
+
+    double nodeSelfTime = it-&gt;value.first;
+    double nodeTotalTime = it-&gt;value.second;
+    double rootTotalTime = data.rootTotalTime;
+
</ins><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(), m_selfTime, selfPercent(), m_totalTime, totalPercent(),
</del><ins>+        numberOfCalls(), 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 class="cx"> 
</span><span class="cx">     // Print children's names and information
</span><span class="cx">     for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
</span><del>-        (*currentChild)-&gt;debugPrintData(indentLevel);
</del><ins>+        (*currentChild)-&gt;debugPrintRecursively(indentLevel, data);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // print the profiled data in a format that matches the tool sample's output.
</span><del>-double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount&amp; countedFunctions) const
</del><ins>+double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount&amp; countedFunctions, const ProfileSubtreeData&amp; data)
</ins><span class="cx"> {
</span><span class="cx">     dataLogF(&quot;    &quot;);
</span><span class="cx"> 
</span><ins>+    auto it = data.selfAndTotalTimes.find(this);
+    ASSERT(it != data.selfAndTotalTimes.end());
+    double nodeTotalTime = it-&gt;value.second;
+
</ins><span class="cx">     // Print function names
</span><span class="cx">     const char* name = functionName().utf8().data();
</span><del>-    double sampleCount = m_totalTime * 1000;
</del><ins>+    double sampleCount = nodeTotalTime * 1000;
</ins><span class="cx">     if (indentLevel) {
</span><span class="cx">         for (int i = 0; i &lt; indentLevel; ++i)
</span><span class="cx">             dataLogF(&quot;  &quot;);
</span><span class="lines">@@ -208,7 +224,7 @@
</span><span class="cx">     // Print children's names and information
</span><span class="cx">     double sumOfChildrensCount = 0.0;
</span><span class="cx">     for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
</span><del>-        sumOfChildrensCount += (*currentChild)-&gt;debugPrintDataSampleStyle(indentLevel, countedFunctions);
</del><ins>+        sumOfChildrensCount += (*currentChild)-&gt;debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data);
</ins><span class="cx"> 
</span><span class="cx">     sumOfChildrensCount *= 1000;    //
</span><span class="cx">     // Print remainder of samples to match sample's output
</span><span class="lines">@@ -220,7 +236,7 @@
</span><span class="cx">         dataLogF(&quot;%.0f %s\n&quot;, sampleCount - sumOfChildrensCount, functionName().utf8().data());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return m_totalTime;
</del><ins>+    return nodeTotalTime;
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreprofilerProfileNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/profiler/ProfileNode.h (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/profiler/ProfileNode.h        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/profiler/ProfileNode.h        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -44,14 +44,14 @@
</span><span class="cx"> 
</span><span class="cx">     class ProfileNode : public RefCounted&lt;ProfileNode&gt; {
</span><span class="cx">     public:
</span><del>-        static PassRefPtr&lt;ProfileNode&gt; create(ExecState* callerCallFrame, const CallIdentifier&amp; callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
</del><ins>+        static PassRefPtr&lt;ProfileNode&gt; create(ExecState* callerCallFrame, const CallIdentifier&amp; callIdentifier, ProfileNode* parentNode)
</ins><span class="cx">         {
</span><del>-            return adoptRef(new ProfileNode(callerCallFrame, callIdentifier, headNode, parentNode));
</del><ins>+            return adoptRef(new ProfileNode(callerCallFrame, callIdentifier, parentNode));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        static PassRefPtr&lt;ProfileNode&gt; create(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* node)
</del><ins>+        static PassRefPtr&lt;ProfileNode&gt; create(ExecState* callerCallFrame, ProfileNode* node)
</ins><span class="cx">         {
</span><del>-            return adoptRef(new ProfileNode(callerCallFrame, headNode, node));
</del><ins>+            return adoptRef(new ProfileNode(callerCallFrame, node));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         struct Call {
</span><span class="lines">@@ -90,26 +90,13 @@
</span><span class="cx">         unsigned columnNumber() const { return m_callIdentifier.columnNumber(); }
</span><span class="cx"> 
</span><span class="cx">         // Relationships
</span><del>-        ProfileNode* head() const { return m_head; }
-        void setHead(ProfileNode* head) { m_head = head; }
-
</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><span class="cx">         ProfileNode* nextSibling() const { return m_nextSibling; }
</span><span class="cx">         void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
</span><span class="cx"> 
</span><del>-        // Time members
-        double totalTime() const { return m_totalTime; }
-        void setTotalTime(double time) { m_totalTime = time; }
-
-        double selfTime() const { return m_selfTime; }
-        void setSelfTime(double time) { m_selfTime = time; }
-
-        double totalPercent() const { return (m_totalTime / (m_head ? m_head-&gt;totalTime() : totalTime())) * 100.0; }
-        double selfPercent() const { return (m_selfTime / (m_head ? m_head-&gt;totalTime() : totalTime())) * 100.0; }
-
-        Vector&lt;Call&gt; calls() const { return m_calls; }
</del><ins>+        const Vector&lt;Call&gt;&amp; calls() const { return m_calls; }
</ins><span class="cx">         Call&amp; lastCall() { ASSERT(!m_calls.isEmpty()); return m_calls.last(); }
</span><span class="cx">         size_t numberOfCalls() const { return m_calls.size(); }
</span><span class="cx"> 
</span><span class="lines">@@ -121,37 +108,85 @@
</span><span class="cx">         void addChild(PassRefPtr&lt;ProfileNode&gt; prpChild);
</span><span class="cx">         void insertNode(PassRefPtr&lt;ProfileNode&gt; prpNode);
</span><span class="cx"> 
</span><del>-        ProfileNode* traverseNextNodePostOrder() const;
</del><ins>+        template &lt;typename Functor&gt; void forEachNodePostorder(Functor&amp;);
</ins><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><ins>+        struct ProfileSubtreeData {
+            HashMap&lt;ProfileNode*, std::pair&lt;double, double&gt;&gt; selfAndTotalTimes;
+            double rootTotalTime;
+        };
+
</ins><span class="cx">         const char* c_str() const { return m_callIdentifier; }
</span><del>-        void debugPrintData(int indentLevel) const;
-        double debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount&amp;) const;
</del><ins>+        // Use these functions to dump the subtree rooted at this node.
+        void debugPrint();
+        void debugPrintSampleStyle();
+
+        // These are used to recursively print entire subtrees using precomputed self and total times.
+        void debugPrintRecursively(int indentLevel, const ProfileSubtreeData&amp;);
+        double debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount&amp;, const ProfileSubtreeData&amp;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         typedef Vector&lt;RefPtr&lt;ProfileNode&gt;&gt;::const_iterator StackIterator;
</span><span class="cx"> 
</span><del>-        ProfileNode(ExecState* callerCallFrame, const CallIdentifier&amp;, ProfileNode* headNode, ProfileNode* parentNode);
-        ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy);
</del><ins>+        ProfileNode(ExecState* callerCallFrame, const CallIdentifier&amp;, ProfileNode* parentNode);
+        ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy);
</ins><span class="cx"> 
</span><span class="cx">         void startTimer();
</span><span class="cx">         void resetChildrensSiblings();
</span><span class="cx">         void endAndRecordCall();
</span><ins>+        ProfileNode* traverseNextNodePostOrder() const;
</ins><span class="cx"> 
</span><span class="cx">         ExecState* m_callerCallFrame;
</span><span class="cx">         CallIdentifier m_callIdentifier;
</span><del>-        ProfileNode* m_head;
</del><span class="cx">         ProfileNode* m_parent;
</span><span class="cx">         ProfileNode* m_nextSibling;
</span><span class="cx"> 
</span><del>-        double m_totalTime;
-        double m_selfTime;
-
-        Vector&lt;Call, 1&gt; m_calls;
</del><ins>+        Vector&lt;Call&gt; m_calls;
</ins><span class="cx">         Vector&lt;RefPtr&lt;ProfileNode&gt;&gt; m_children;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    template &lt;typename Functor&gt; inline void ProfileNode::forEachNodePostorder(Functor&amp; functor)
+    {
+        ProfileNode* currentNode = this;
+        // Go down to the first node of the traversal, and slowly walk back up.
+        for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode-&gt;firstChild())
+            currentNode = nextNode;
+
+        ProfileNode* endNode = this;
+        while (currentNode &amp;&amp; currentNode != endNode) {
+            functor(currentNode);
+            currentNode = currentNode-&gt;traverseNextNodePostOrder();
+        }
+
+        functor(endNode);
+    }
+
+#ifndef NDEBUG
+    struct CalculateProfileSubtreeDataFunctor {
+        void operator()(ProfileNode* node)
+        {
+            double selfTime = 0.0;
+            for (const ProfileNode::Call&amp; call : node-&gt;calls())
+                selfTime += call.totalTime();
+
+            double totalTime = selfTime;
+            for (RefPtr&lt;ProfileNode&gt; child : node-&gt;children()) {
+                auto it = m_data.selfAndTotalTimes.find(child.get());
+                if (it != m_data.selfAndTotalTimes.end())
+                    totalTime += it-&gt;value.second;
+            }
+
+            ASSERT(node);
+            m_data.selfAndTotalTimes.set(node, std::make_pair(selfTime, totalTime));
+        }
+
+        ProfileNode::ProfileSubtreeData returnValue() { return WTF::move(m_data); }
+
+        ProfileNode::ProfileSubtreeData m_data;
+    };
+#endif
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ProfileNode_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeConsoleClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ConsoleClient.h (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ConsoleClient.h        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/JavaScriptCore/runtime/ConsoleClient.h        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -27,7 +27,6 @@
</span><span class="cx"> #define ConsoleClient_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ConsoleTypes.h&quot;
</span><del>-#include &quot;Profile.h&quot;
</del><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace Inspector {
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/WebCore/ChangeLog        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -1,5 +1,20 @@
</span><span class="cx"> 2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
</span><span class="cx"> 
</span><ins>+        LegacyProfiler: remove redundant ProfileNode members and other cleanup
+        https://bugs.webkit.org/show_bug.cgi?id=136380
+
+        Reviewed by Timothy Hatcher.
+
+        Remove Profile.idleTime, rename head to rootNode, and remove ProfileNode members.
+
+        Covered by existing tests.
+
+        * inspector/ScriptProfile.idl:
+        * inspector/ScriptProfileNode.idl:
+        * inspector/TimelineRecordFactory.cpp:
+
+2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
+
</ins><span class="cx">         Web Inspector: remove ProfilerAgent and legacy profiler files in the frontend
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=136462
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorScriptProfileidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/ScriptProfile.idl (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/ScriptProfile.idl        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/WebCore/inspector/ScriptProfile.idl        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -30,7 +30,6 @@
</span><span class="cx"> ] interface ScriptProfile {
</span><span class="cx">     readonly attribute DOMString title;
</span><span class="cx">     readonly attribute unsigned long uid;
</span><del>-    readonly attribute ScriptProfileNode head;
-    readonly attribute unrestricted double idleTime;
</del><ins>+    readonly attribute ScriptProfileNode rootNode;
</ins><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorScriptProfileNodeidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/ScriptProfileNode.idl (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/ScriptProfileNode.idl        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/WebCore/inspector/ScriptProfileNode.idl        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -36,9 +36,6 @@
</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 unrestricted double totalTime;
-    readonly attribute unrestricted double selfTime;
-
</del><span class="cx">     readonly attribute unsigned long numberOfCalls;
</span><span class="cx"> 
</span><span class="cx">     sequence&lt;ScriptProfileNode&gt; children();
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorTimelineRecordFactorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -310,15 +310,12 @@
</span><span class="cx"> static PassRefPtr&lt;Protocol::Timeline::CPUProfile&gt; buildProfileInspectorObject(const JSC::Profile* profile)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;Protocol::Array&lt;Protocol::Timeline::CPUProfileNode&gt;&gt; rootNodes = Protocol::Array&lt;Protocol::Timeline::CPUProfileNode&gt;::create();
</span><del>-    for (RefPtr&lt;JSC::ProfileNode&gt; profileNode : profile-&gt;head()-&gt;children())
</del><ins>+    for (RefPtr&lt;JSC::ProfileNode&gt; profileNode : profile-&gt;rootNode()-&gt;children())
</ins><span class="cx">         rootNodes-&gt;addItem(buildInspectorObject(profileNode.get()));
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Protocol::Timeline::CPUProfile&gt; result = Protocol::Timeline::CPUProfile::create()
</span><span class="cx">         .setRootNodes(rootNodes);
</span><span class="cx"> 
</span><del>-    if (profile-&gt;idleTime())
-        result-&gt;setIdleTime(profile-&gt;idleTime());
-
</del><span class="cx">     return result.release();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/WebInspectorUI/ChangeLog        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -1,5 +1,19 @@
</span><span class="cx"> 2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
</span><span class="cx"> 
</span><ins>+        LegacyProfiler: remove redundant ProfileNode members and other cleanup
+        https://bugs.webkit.org/show_bug.cgi?id=136380
+
+        Reviewed by Timothy Hatcher.
+
+        Remove unused Profile.idleTime member.
+
+        * UserInterface/Models/Profile.js:
+        (WebInspector.Profile.prototype.get idleTime): Deleted.
+        * UserInterface/Models/ScriptTimelineRecord.js:
+        (WebInspector.ScriptTimelineRecord.prototype._initializeProfileFromPayload):
+
+2014-09-02  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
+
</ins><span class="cx">         Web Inspector: remove ProfilerAgent and legacy profiler files in the frontend
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=136462
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsProfilejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Profile.js (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/Profile.js        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Profile.js        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-WebInspector.Profile = function(topDownRootNodes, idleTime)
</del><ins>+WebInspector.Profile = function(topDownRootNodes)
</ins><span class="cx"> {
</span><span class="cx">     WebInspector.Object.call(this);
</span><span class="cx"> 
</span><span class="lines">@@ -33,7 +33,6 @@
</span><span class="cx">     console.assert(topDownRootNodes.reduce(function(previousValue, node) { return previousValue &amp;&amp; node instanceof WebInspector.ProfileNode; }, true));
</span><span class="cx"> 
</span><span class="cx">     this._topDownRootNodes = topDownRootNodes;
</span><del>-    this._idleTime = idleTime || 0;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.Profile.prototype = {
</span><span class="lines">@@ -42,11 +41,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get idleTime()
-    {
-        return this._idleTime;
-    },
-
</del><span class="cx">     get topDownRootNodes()
</span><span class="cx">     {
</span><span class="cx">         return this._topDownRootNodes;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsScriptTimelineRecordjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js (173198 => 173199)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js        2014-09-03 03:17:47 UTC (rev 173198)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js        2014-09-03 04:58:55 UTC (rev 173199)
</span><span class="lines">@@ -346,7 +346,7 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        this._profile = new WebInspector.Profile(rootNodes, payload.idleTime);
</del><ins>+        this._profile = new WebInspector.Profile(rootNodes);
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>