Changeset 42808 in webkit


Ignore:
Timestamp:
Apr 23, 2009 8:47:50 PM (15 years ago)
Author:
timothy@apple.com
Message:

BUG 24604: WebKit profiler reports incorrect total times

JavaScriptCore:

2009-04-23 Francisco Tolmasky <francisco@280north.com>

BUG 24604: WebKit profiler reports incorrect total times
<https://bugs.webkit.org/show_bug.cgi?id=24604>

Reviewed by Timothy Hatcher and Kevin McCullough.

  • JavaScriptCore.exp:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • profiler/CallIdentifier.h: (JSC::CallIdentifier::Hash::hash): (JSC::CallIdentifier::Hash::equal): (JSC::CallIdentifier::hash): (WTF::):
  • profiler/HeavyProfile.cpp: Removed.
  • profiler/HeavyProfile.h: Removed.
  • profiler/Profile.cpp: No more need for TreeProfile/HeavyProfile (JSC::Profile::create):
  • profiler/Profile.h:
  • profiler/ProfileNode.cpp:
  • profiler/ProfileNode.h:
  • profiler/TreeProfile.cpp: Removed.
  • profiler/TreeProfile.h: Removed.

WebCore:

2009-04-23 Francisco Tolmasky <francisco@280north.com>

BUG 24604: WebKit profiler reports incorrect total times
<https://bugs.webkit.org/show_bug.cgi?id=24604>

Reviewed by Timothy Hatcher and Kevin McCullough.

Made it so that most of the profiler functions now match the behavior of Shark. Most notably, in the
heavy view, child nodes now represent the statistics of the root node. Each root node of heavy view
displays flattened statistics for a particular function that ran during the profile, and each child
of these root nodes represents a callpath that lead to it. Thus, the statistics for each of these child
nodes should show how much of the root nodes values came from it. For example, if you had the following to
stacks take place during the profile:

A ->calls 1 times-> B ->calls 2 times-> C
D ->calls 4 times-> C

The tree for the C root node would look like this:

C -> B -> A

-> D

The number of calls values would look like this:

C (6) -> B (2) -> A(2)

-> D (4)

What this means is that "2 of the total 6 C calls came from B", "2 of the total C calls came from A", and
"4 of the total C calls came from D". Notice that the "A ->calls 2 time->" is completely ignored. This becomes
particularly tricky during recursive calls, because each child note can represent multiple possible paths. This
is the reason that we would get things like 40000% previously with recursion.

This is also the way gprof works, and as close as we can get to Shark's behavior (Shark is not instrumented so it
can't know exactly how many calls came from where, etc).

  • English.lproj/localizedStrings.js: Added "Average" for average times in the profile.
  • inspector/JavaScriptProfile.cpp: (WebCore::ProfileClass):
  • inspector/JavaScriptProfileNode.cpp: (WebCore::getParent): (WebCore::getHead): (WebCore::getCallUID): (WebCore::ProfileNodeClass):
  • inspector/front-end/BottomUpProfileDataGridTree.js: Added. (WebInspector.BottomUpProfileDataGridTree): (WebInspector.BottomUpProfileDataGridTree.prototype.focus): (WebInspector.BottomUpProfileDataGridNode): (WebInspector.BottomUpProfileDataGridNode.prototype._takePropertiesFromProfileDataGridNode): (WebInspector.BottomUpProfileDataGridNode.prototype._keepOnlyChild): (WebInspector.BottomUpProfileDataGridNode.prototype._exclude): (WebInspector.BottomUpProfileDataGridNode.prototype._merge): (WebInspector.BottomUpProfileDataGridNode.prototype._populate):
  • inspector/front-end/DataGrid.js: (WebInspector.DataGrid.prototype.insertChild): (WebInspector.DataGrid.prototype.removeChild): (WebInspector.DataGrid.prototype.removeChildren): (WebInspector.DataGridNode.prototype.set hasChildren): (WebInspector.DataGridNode.prototype.get hasChildren):
  • inspector/front-end/ProfileDataGridTree.js: Added. (WebInspector.ProfileDataGridNode): (WebInspector.ProfileDataGridNode.prototype.get data.formatMilliseconds): (WebInspector.ProfileDataGridNode.prototype.get data): (WebInspector.ProfileDataGridNode.prototype.createCell): (WebInspector.ProfileDataGridNode.prototype.select): (WebInspector.ProfileDataGridNode.prototype.deselect): (WebInspector.ProfileDataGridNode.prototype.expand): (WebInspector.ProfileDataGridNode.prototype.insertChild): (WebInspector.ProfileDataGridNode.prototype.removeChild): (WebInspector.ProfileDataGridNode.prototype.removeChildren): (WebInspector.ProfileDataGridNode.prototype.findChild): (WebInspector.ProfileDataGridNode.prototype.get averageTime): (WebInspector.ProfileDataGridNode.prototype.get averagePercent): (WebInspector.ProfileDataGridNode.prototype.get selfPercent): (WebInspector.ProfileDataGridNode.prototype.get totalPercent): (WebInspector.ProfileDataGridNode.prototype._save): (WebInspector.ProfileDataGridNode.prototype._restore): (WebInspector.ProfileDataGridNode.prototype._merge): (WebInspector.ProfileDataGridTree): (WebInspector.ProfileDataGridTree.prototype.get expanded): (WebInspector.ProfileDataGridTree.prototype.appendChild): (WebInspector.ProfileDataGridTree.prototype.insertChild): (WebInspector.ProfileDataGridTree.prototype.removeChildren): (WebInspector.ProfileDataGridTree.prototype.findChild.WebInspector.ProfileDataGridNode.prototype.findChild.sort.WebInspector.ProfileDataGridNode.prototype.sort._save): (WebInspector.ProfileDataGridTree.propertyComparator.comparator): (WebInspector.ProfileDataGridTree.propertyComparator.else.comparator): (WebInspector.ProfileDataGridTree.propertyComparator):
  • inspector/front-end/ProfileView.js: (WebInspector.ProfileView): (WebInspector.ProfileView.prototype.set profile): (WebInspector.ProfileView.prototype.get bottomUpProfileDataGridTree): (WebInspector.ProfileView.prototype.get topDownProfileDataGridTree): (WebInspector.ProfileView.prototype.get currentTree): (WebInspector.ProfileView.prototype.set currentTree): (WebInspector.ProfileView.prototype.get topDownTree): (WebInspector.ProfileView.prototype.get bottomUpTree): (WebInspector.ProfileView.prototype.refresh): (WebInspector.ProfileView.prototype.refreshVisibleData): (WebInspector.ProfileView.prototype.refreshShowAsPercents): (WebInspector.ProfileView.prototype.performSearch.matchesQuery): (WebInspector.ProfileView.prototype.performSearch): (WebInspector.ProfileView.prototype._changeView): (WebInspector.ProfileView.prototype._focusClicked): (WebInspector.ProfileView.prototype._excludeClicked): (WebInspector.ProfileView.prototype._resetClicked): (WebInspector.ProfileView.prototype._sortProfile):
  • inspector/front-end/ProfilesPanel.js: (WebInspector.ProfilesPanel.prototype.showProfile): (WebInspector.ProfilesPanel.prototype.showView): (WebInspector.ProfilesPanel.prototype.searchMatchFound):
  • inspector/front-end/TopDownProfileDataGridTree.js: Added. (WebInspector.TopDownProfileDataGridNode): (WebInspector.TopDownProfileDataGridNode.prototype._populate): (WebInspector.TopDownProfileDataGridNode.prototype._exclude): (WebInspector.TopDownProfileDataGridTree): (WebInspector.TopDownProfileDataGridTree.prototype.focus): (WebInspector.TopDownProfileDataGridTree.prototype.exclude):
  • inspector/front-end/WebKit.qrc:
  • inspector/front-end/inspector.css:
  • inspector/front-end/inspector.html:

LayoutTests:

2009-04-23 Francisco Tolmasky <francisco@280north.com>

BUG 24604: WebKit profiler reports incorrect total times
<https://bugs.webkit.org/show_bug.cgi?id=24604>

Reviewed by Timothy Hatcher and Kevin McCullough.

Changed profile.treeProfile to just profile, since these aren't generated in C++ anymore.
Removed heavy-view test since heavy-view isn't an actual tree that is generated in C++ land anymore,
but rather just a different display of the normal treeProfile in the JS data grid.

  • fast/profiler/heavy-view-expected.txt: Removed.
  • fast/profiler/heavy-view.html: Removed.
  • fast/profiler/resources/profiler-test-JS-resources.js: profiles[i].treeProfile -> profiles[i].treeProfile (printProfilesDataWithoutTime):
Location:
trunk
Files:
3 added
2 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r42805 r42808  
     12009-04-23  Francisco Tolmasky  <francisco@280north.com>
     2
     3        BUG 24604: WebKit profiler reports incorrect total times
     4        <https://bugs.webkit.org/show_bug.cgi?id=24604>
     5
     6        Reviewed by Timothy Hatcher and Kevin McCullough.
     7
     8        * JavaScriptCore.exp:
     9        * JavaScriptCore.xcodeproj/project.pbxproj:
     10        * profiler/CallIdentifier.h:
     11        (JSC::CallIdentifier::Hash::hash):
     12        (JSC::CallIdentifier::Hash::equal):
     13        (JSC::CallIdentifier::hash):
     14        (WTF::):
     15        * profiler/HeavyProfile.cpp: Removed.
     16        * profiler/HeavyProfile.h: Removed.
     17        * profiler/Profile.cpp: No more need for TreeProfile/HeavyProfile
     18        (JSC::Profile::create):
     19        * profiler/Profile.h:
     20        * profiler/ProfileNode.cpp:
     21        * profiler/ProfileNode.h:
     22        * profiler/TreeProfile.cpp: Removed.
     23        * profiler/TreeProfile.h: Removed.
     24
    1252009-04-23  Gavin Barraclough  <barraclough@apple.com>
    226
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r41168 r42808  
    106106__ZN3JSC11JSImmediate8toStringENS_10JSValuePtrE
    107107__ZN3JSC11JSImmediate9prototypeENS_10JSValuePtrEPNS_9ExecStateE
    108 __ZN3JSC11ProfileNode4sortEPFbRKN3WTF6RefPtrIS0_EES5_E
    109108__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
    110109__ZN3JSC12DateInstance4infoE
     
    213212__ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
    214213__ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
     214__ZN3JSC7UString3Rep11computeHashEPKci
    215215__ZN3JSC7UString3Rep11computeHashEPKti
    216216__ZN3JSC7UString3Rep14nullBaseStringE
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r42705 r42808  
    155155                95AB83420DA4322500BC83F3 /* Profiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AB832E0DA42CAD00BC83F3 /* Profiler.cpp */; };
    156156                95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AB83540DA43B4400BC83F3 /* ProfileNode.cpp */; };
    157                 95CD41B30E1BF6560085358E /* TreeProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95CD41B10E1BF6560085358E /* TreeProfile.cpp */; };
    158                 95CD41B40E1BF6560085358E /* TreeProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 95CD41B20E1BF6560085358E /* TreeProfile.h */; };
    159157                95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95CD45740E1C4FDD0085358E /* ProfileGenerator.cpp */; };
    160158                95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 95CD45750E1C4FDD0085358E /* ProfileGenerator.h */; settings = {ATTRIBUTES = (); }; };
    161159                95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 95E3BC040E1AE68200B2D1C1 /* CallIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
    162160                95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95988BA90E477BEC00D28D4D /* JSProfilerPrivate.cpp */; };
    163                 95FDFA140E22998F0006FB00 /* HeavyProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95FDFA130E22998F0006FB00 /* HeavyProfile.cpp */; };
    164                 95FDFA160E2299980006FB00 /* HeavyProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 95FDFA150E2299980006FB00 /* HeavyProfile.h */; };
    165161                960097A60EBABB58007A7297 /* LabelScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 960097A50EBABB58007A7297 /* LabelScope.h */; };
    166162                9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; };
     
    673669                95AB83550DA43B4400BC83F3 /* ProfileNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfileNode.h; path = profiler/ProfileNode.h; sourceTree = "<group>"; };
    674670                95C18D3E0C90E7EF00E72F73 /* JSRetainPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRetainPtr.h; sourceTree = "<group>"; };
    675                 95CD41B10E1BF6560085358E /* TreeProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TreeProfile.cpp; path = profiler/TreeProfile.cpp; sourceTree = "<group>"; };
    676                 95CD41B20E1BF6560085358E /* TreeProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TreeProfile.h; path = profiler/TreeProfile.h; sourceTree = "<group>"; };
    677671                95CD45740E1C4FDD0085358E /* ProfileGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfileGenerator.cpp; path = profiler/ProfileGenerator.cpp; sourceTree = "<group>"; };
    678672                95CD45750E1C4FDD0085358E /* ProfileGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfileGenerator.h; path = profiler/ProfileGenerator.h; sourceTree = "<group>"; };
    679673                95E3BC040E1AE68200B2D1C1 /* CallIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallIdentifier.h; path = profiler/CallIdentifier.h; sourceTree = "<group>"; };
    680                 95FDFA130E22998F0006FB00 /* HeavyProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HeavyProfile.cpp; path = profiler/HeavyProfile.cpp; sourceTree = "<group>"; };
    681                 95FDFA150E2299980006FB00 /* HeavyProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HeavyProfile.h; path = profiler/HeavyProfile.h; sourceTree = "<group>"; };
    682674                960097A50EBABB58007A7297 /* LabelScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelScope.h; sourceTree = "<group>"; };
    683675                9688CB130ED12B4E001D649F /* AssemblerBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssemblerBuffer.h; sourceTree = "<group>"; };
     
    14821474                        children = (
    14831475                                95E3BC040E1AE68200B2D1C1 /* CallIdentifier.h */,
    1484                                 95FDFA130E22998F0006FB00 /* HeavyProfile.cpp */,
    1485                                 95FDFA150E2299980006FB00 /* HeavyProfile.h */,
    14861476                                95742F630DD11F5A000917FB /* Profile.cpp */,
    14871477                                95742F640DD11F5A000917FB /* Profile.h */,
     
    14941484                                1C61516B0EBAC7A00031376F /* ProfilerServer.h */,
    14951485                                1C61516A0EBAC7A00031376F /* ProfilerServer.mm */,
    1496                                 95CD41B10E1BF6560085358E /* TreeProfile.cpp */,
    1497                                 95CD41B20E1BF6560085358E /* TreeProfile.h */,
    14981486                        );
    14991487                        name = profiler;
     
    16341622                                BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */,
    16351623                                BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */,
    1636                                 95FDFA160E2299980006FB00 /* HeavyProfile.h in Headers */,
    16371624                                BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */,
    16381625                                BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */,
     
    17661753                                BC18C4700E16F5CD00B34460 /* Threading.h in Headers */,
    17671754                                5D53726F0E1C54880021E549 /* Tracing.h in Headers */,
    1768                                 95CD41B40E1BF6560085358E /* TreeProfile.h in Headers */,
    17691755                                6507D29E0E871E5E00D7D896 /* TypeInfo.h in Headers */,
    17701756                                0B4D7E630F319AC800AD7E58 /* TypeTraits.h in Headers */,
     
    21022088                                A782F1A50EEC9FA20036273F /* ExecutableAllocatorPosix.cpp in Sources */,
    21032089                                65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */,
    2104                                 95FDFA140E22998F0006FB00 /* HeavyProfile.cpp in Sources */,
    21052090                                E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */,
    21062091                                1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */,
     
    21452130                                5D6A566B0F05995500266145 /* Threading.cpp in Sources */,
    21462131                                E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */,
    2147                                 95CD41B30E1BF6560085358E /* TreeProfile.cpp in Sources */,
    21482132                                E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */,
    21492133                                869083150E6518D7000D36ED /* WREC.cpp in Sources */,
  • trunk/JavaScriptCore/profiler/CallIdentifier.h

    r38137 r42808  
    5252        inline bool operator!=(const CallIdentifier& ci) const { return !(*this == ci); }
    5353
     54        struct Hash {
     55            static unsigned hash(const CallIdentifier& key)
     56            {
     57                unsigned hashCodes[3] = {
     58                    key.m_name.rep()->hash(),
     59                    key.m_url.rep()->hash(),
     60                    key.m_lineNumber
     61                };
     62                return UString::Rep::computeHash(reinterpret_cast<char*>(hashCodes), sizeof(hashCodes));
     63            }
     64
     65            static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; }
     66            static const bool safeToCompareToEmptyOrDeleted = true;
     67        };
     68
     69        unsigned hash() const { return Hash::hash(*this); }
     70
    5471#ifndef NDEBUG
    5572        operator const char*() const { return c_str(); }
     
    5875    };
    5976
    60     struct CallIdentifierHash {
    61         static unsigned hash(const CallIdentifier& key)
    62         {
    63             unsigned hashCodes[3] = {
    64                 key.m_name.rep()->hash(),
    65                 key.m_url.rep()->hash(),
    66                 key.m_lineNumber
    67             };
    68             return UString::Rep::computeHash(reinterpret_cast<char*>(hashCodes), sizeof(hashCodes));
    69         }
    70 
    71         static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; }
    72         static const bool safeToCompareToEmptyOrDeleted = true;
    73     };
    74 
    7577} // namespace JSC
    7678
    7779namespace WTF {
    7880
    79     template<> struct DefaultHash<JSC::CallIdentifier> { typedef JSC::CallIdentifierHash Hash; };
     81    template<> struct DefaultHash<JSC::CallIdentifier> { typedef JSC::CallIdentifier::Hash Hash; };
    8082
    8183    template<> struct HashTraits<JSC::CallIdentifier> : GenericHashTraits<JSC::CallIdentifier> {
  • trunk/JavaScriptCore/profiler/HeavyProfile.cpp

    r36263 r42808  
    1 /*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
    10  *    notice, this list of conditions and the following disclaimer in the
    11  *    documentation and/or other materials provided with the distribution.
    12  *
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    24  */
    25 
    26 #include "config.h"
    27 #include "HeavyProfile.h"
    28 
    29 #include "TreeProfile.h"
    30 
    31 namespace JSC {
    32 
    33 HeavyProfile::HeavyProfile(TreeProfile* treeProfile)
    34     : Profile(treeProfile->title(), treeProfile->uid())
    35 {
    36     m_treeProfile = treeProfile;
    37     head()->setTotalTime(m_treeProfile->head()->actualTotalTime());
    38     head()->setSelfTime(m_treeProfile->head()->actualSelfTime());
    39     generateHeavyStructure();
    40 }
    41 
    42 void HeavyProfile::generateHeavyStructure()
    43 {
    44     ProfileNode* treeHead = m_treeProfile->head();
    45     ProfileNode* currentNode = treeHead->firstChild();
    46     for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild())
    47         currentNode = nextNode;
    48 
    49     // For each node
    50     HashMap<CallIdentifier, ProfileNode*> foundChildren;
    51     while (currentNode && currentNode != treeHead) {
    52         ProfileNode* child = foundChildren.get(currentNode->callIdentifier());
    53         if (child) // currentNode is in the set already
    54             mergeProfiles(child, currentNode);
    55         else { // currentNode is not in the set
    56             child = addNode(currentNode);
    57             foundChildren.set(currentNode->callIdentifier(), child);
    58         }
    59 
    60         currentNode = currentNode->traverseNextNodePostOrder();
    61     }
    62 }
    63 
    64 ProfileNode* HeavyProfile::addNode(ProfileNode* currentNode)
    65 {
    66     RefPtr<ProfileNode> node = ProfileNode::create(head(), currentNode);
    67     head()->addChild(node);
    68 
    69     addAncestorsAsChildren(currentNode->parent(), node.get());
    70     return node.get();
    71 }
    72 
    73 void HeavyProfile::mergeProfiles(ProfileNode* heavyProfileHead, ProfileNode* treeProfileHead)
    74 {
    75     ASSERT_ARG(heavyProfileHead, heavyProfileHead);
    76     ASSERT_ARG(treeProfileHead, treeProfileHead);
    77 
    78     ProfileNode* currentTreeNode = treeProfileHead;
    79     ProfileNode* currentHeavyNode = heavyProfileHead;
    80     ProfileNode* previousHeavyNode = 0;
    81    
    82     while (currentHeavyNode) {
    83         previousHeavyNode = currentHeavyNode;
    84 
    85         currentHeavyNode->setTotalTime(currentHeavyNode->actualTotalTime() + currentTreeNode->actualTotalTime());
    86         currentHeavyNode->setSelfTime(currentHeavyNode->actualSelfTime() + currentTreeNode->actualSelfTime());
    87         currentHeavyNode->setNumberOfCalls(currentHeavyNode->numberOfCalls() + currentTreeNode->numberOfCalls());
    88 
    89         currentTreeNode = currentTreeNode->parent();
    90         currentHeavyNode = currentHeavyNode->findChild(currentTreeNode);
    91     }
    92 
    93     // If currentTreeNode is null then we already have the whole tree we wanted to copy.
    94     // If not we need to copy the subset of the tree that remains different between the two.
    95     if (currentTreeNode)
    96         addAncestorsAsChildren(currentTreeNode, previousHeavyNode);
    97 }
    98 
    99 void HeavyProfile::addAncestorsAsChildren(ProfileNode* getFrom, ProfileNode* addTo)
    100 {
    101     ASSERT_ARG(getFrom, getFrom);
    102     ASSERT_ARG(addTo, addTo);
    103 
    104     if (!getFrom->head())
    105         return;
    106 
    107     RefPtr<ProfileNode> currentNode = addTo;
    108     for (ProfileNode* treeAncestor = getFrom; treeAncestor && treeAncestor != getFrom->head(); treeAncestor = treeAncestor->parent()) {
    109         RefPtr<ProfileNode> newChild = ProfileNode::create(currentNode->head(), treeAncestor);
    110         currentNode->addChild(newChild);
    111         currentNode = newChild.release();
    112     }
    113 }
    114 
    115 }   // namespace JSC
  • trunk/JavaScriptCore/profiler/HeavyProfile.h

    r37433 r42808  
    1 /*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
    10  *    notice, this list of conditions and the following disclaimer in the
    11  *    documentation and/or other materials provided with the distribution.
    12  *
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    24  */
    25  
    26 #ifndef HeavyProfile_h
    27 #define HeavyProfile_h
    28 
    29 #include "Profile.h"
    30 #include "ProfileNode.h"
    31 #include "TreeProfile.h"
    32 
    33 namespace JSC {
    34 
    35     class UString;
    36 
    37     class HeavyProfile : public Profile {
    38     public:
    39         static PassRefPtr<HeavyProfile> create(TreeProfile* treeProfile)
    40         {
    41             return adoptRef(new HeavyProfile(treeProfile));
    42         }
    43 
    44         virtual Profile* heavyProfile() { return this; }
    45         virtual Profile* treeProfile()
    46         {
    47             return m_treeProfile;
    48         }
    49 
    50 
    51     private:
    52         HeavyProfile(TreeProfile*);
    53         void generateHeavyStructure();
    54         ProfileNode* addNode(ProfileNode*);
    55         void mergeProfiles(ProfileNode* heavyProfileHead, ProfileNode* treeProfileHead);
    56         void addAncestorsAsChildren(ProfileNode* getFrom, ProfileNode* addTo);
    57 
    58         TreeProfile* m_treeProfile;
    59     };
    60 
    61 } // namespace JSC
    62 
    63 #endif // HeavyProfile_h
  • trunk/JavaScriptCore/profiler/Profile.cpp

    r36263 r42808  
    2828
    2929#include "ProfileNode.h"
    30 #include "TreeProfile.h"
    3130#include <stdio.h>
    3231
     
    3534PassRefPtr<Profile> Profile::create(const UString& title, unsigned uid)
    3635{
    37     return TreeProfile::create(title, uid);
     36    return adoptRef(new Profile(title, uid));
    3837}
    3938
  • trunk/JavaScriptCore/profiler/Profile.h

    r38137 r42808  
    4646
    4747        void forEach(void (ProfileNode::*)());
    48         void sortTotalTimeDescending() { forEach(&ProfileNode::sortTotalTimeDescending); }
    49         void sortTotalTimeAscending() { forEach(&ProfileNode::sortTotalTimeAscending); }
    50         void sortSelfTimeDescending() { forEach(&ProfileNode::sortSelfTimeDescending); }
    51         void sortSelfTimeAscending() { forEach(&ProfileNode::sortSelfTimeAscending); }
    52         void sortCallsDescending() { forEach(&ProfileNode::sortCallsDescending); }
    53         void sortCallsAscending() { forEach(&ProfileNode::sortCallsAscending); }
    54         void sortFunctionNameDescending() { forEach(&ProfileNode::sortFunctionNameDescending); }
    55         void sortFunctionNameAscending() { forEach(&ProfileNode::sortFunctionNameAscending); }
    5648
    5749        void focus(const ProfileNode*);
    5850        void exclude(const ProfileNode*);
    5951        void restoreAll();
    60 
    61         virtual Profile* heavyProfile() = 0;
    62         virtual Profile* treeProfile() = 0;
    6352
    6453#ifndef NDEBUG
  • trunk/JavaScriptCore/profiler/ProfileNode.cpp

    r36263 r42808  
    205205}
    206206
    207 void ProfileNode::sort(bool comparator(const RefPtr<ProfileNode>& , const RefPtr<ProfileNode>& ))
    208 {
    209     std::sort(childrenBegin(), childrenEnd(), comparator);   
    210     resetChildrensSiblings();
    211 }
    212 
    213207void ProfileNode::setTreeVisible(ProfileNode* node, bool visible)
    214208{
  • trunk/JavaScriptCore/profiler/ProfileNode.h

    r36263 r42808  
    113113        ProfileNode* traverseNextNodePreOrder(bool processChildren = true) const;
    114114
    115         void sort(bool (*)(const RefPtr<ProfileNode>&, const RefPtr<ProfileNode>&));
    116         void sortTotalTimeDescending() { sort(totalTimeDescendingComparator); }
    117         void sortTotalTimeAscending() { sort(totalTimeAscendingComparator); }
    118         void sortSelfTimeDescending() { sort(selfTimeDescendingComparator); }
    119         void sortSelfTimeAscending() { sort(selfTimeAscendingComparator); }
    120         void sortCallsDescending() { sort(callsDescendingComparator); }
    121         void sortCallsAscending() { sort(callsAscendingComparator); }
    122         void sortFunctionNameDescending() { sort(functionNameDescendingComparator); }
    123         void sortFunctionNameAscending() { sort(functionNameAscendingComparator); }
    124 
    125115        // Views
    126116        void calculateVisibleTotalTime();
  • trunk/JavaScriptCore/profiler/TreeProfile.cpp

    r36263 r42808  
    1 /*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
    10  *    notice, this list of conditions and the following disclaimer in the
    11  *    documentation and/or other materials provided with the distribution.
    12  *
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    24  */
    25 
    26 #include "config.h"
    27 #include "TreeProfile.h"
    28 
    29 #include "HeavyProfile.h"
    30 
    31 namespace JSC {
    32 
    33 PassRefPtr<TreeProfile> TreeProfile::create(const UString& title, unsigned uid)
    34 {
    35     return adoptRef(new TreeProfile(title, uid));
    36 }
    37 
    38 TreeProfile::TreeProfile(const UString& title, unsigned uid)
    39     : Profile(title, uid)
    40 {
    41 }
    42 
    43 Profile* TreeProfile::heavyProfile()
    44 {
    45     if (!m_heavyProfile)
    46         m_heavyProfile = HeavyProfile::create(this);
    47 
    48     return m_heavyProfile.get();
    49 }
    50 
    51 } // namespace JSC
  • trunk/JavaScriptCore/profiler/TreeProfile.h

    r36263 r42808  
    1 /*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
    10  *    notice, this list of conditions and the following disclaimer in the
    11  *    documentation and/or other materials provided with the distribution.
    12  *
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    24  */
    25  
    26 #ifndef TreeProfile_h
    27 #define TreeProfile_h
    28 
    29 #include "Profile.h"
    30 
    31 namespace JSC {
    32 
    33     class ExecState;
    34     class HeavyProfile;
    35     class UString;
    36 
    37     class TreeProfile : public Profile {
    38     public:
    39         static PassRefPtr<TreeProfile> create(const UString& title, unsigned uid);
    40 
    41         virtual Profile* heavyProfile();
    42         virtual Profile* treeProfile() { return this; }
    43 
    44     private:
    45         TreeProfile(const UString& title, unsigned uid);
    46         RefPtr<HeavyProfile> m_heavyProfile;
    47     };
    48 
    49 } // namespace JSC
    50 
    51 #endif // TreeProfiler_h
  • trunk/LayoutTests/ChangeLog

    r42806 r42808  
     12009-04-23  Francisco Tolmasky  <francisco@280north.com>
     2
     3        BUG 24604: WebKit profiler reports incorrect total times
     4        <https://bugs.webkit.org/show_bug.cgi?id=24604>
     5
     6        Reviewed by Timothy Hatcher and Kevin McCullough.
     7
     8        Changed profile.treeProfile to just profile, since these aren't generated in C++ anymore.
     9        Removed heavy-view test since heavy-view isn't an actual tree that is generated in C++ land anymore,
     10        but rather just a different display of the normal treeProfile in the JS data grid.
     11
     12        * fast/profiler/heavy-view-expected.txt: Removed.
     13        * fast/profiler/heavy-view.html: Removed.
     14        * fast/profiler/resources/profiler-test-JS-resources.js: profiles[i].treeProfile -> profiles[i].treeProfile
     15        (printProfilesDataWithoutTime):
     16
    1172009-04-23  Kevin McCullough  <kmccullough@apple.com>
    218
  • trunk/LayoutTests/fast/profiler/resources/profiler-test-JS-resources.js

    r41411 r42808  
    6868    for (var i = 0; i < profiles.length; ++i) {
    6969        preElement.appendChild(document.createTextNode("Profile title: " + profiles[i].title + "\n"));
    70         printProfileNodeWithoutTime(preElement, profiles[i].treeProfile.head, 0);
     70        printProfileNodeWithoutTime(preElement, profiles[i].head, 0);
    7171        preElement.appendChild(document.createTextNode("\n"));
    7272    }
  • trunk/WebCore/ChangeLog

    r42807 r42808  
     12009-04-23  Francisco Tolmasky  <francisco@280north.com>
     2
     3        BUG 24604: WebKit profiler reports incorrect total times
     4        <https://bugs.webkit.org/show_bug.cgi?id=24604>
     5
     6        Reviewed by Timothy Hatcher and Kevin McCullough.
     7
     8        Made it so that most of the profiler functions now match the behavior of Shark. Most notably, in the
     9        heavy view, child nodes now represent the statistics of the root node. Each root node of heavy view
     10        displays flattened statistics for a particular function that ran during the profile, and each child
     11        of these root nodes represents a callpath that lead to it. Thus, the statistics for each of these child
     12        nodes should show how much of the root nodes values came from it. For example, if you had the following to
     13        stacks take place during the profile:
     14
     15        A ->calls 1 times-> B ->calls 2 times-> C
     16        D ->calls 4 times-> C
     17
     18        The tree for the C root node would look like this:
     19
     20        C -> B -> A
     21          -> D
     22
     23        The number of calls values would look like this:
     24
     25        C (6) -> B (2) -> A(2)
     26              -> D (4)
     27
     28        What this means is that "2 of the total 6 C calls came from B", "2 of the total C calls came from A", and
     29        "4 of the total C calls came from D".  Notice that the "A ->calls 2 time->" is completely ignored. This becomes
     30        particularly tricky during recursive calls, because each child note can represent multiple possible paths. This
     31        is the reason that we would get things like 40000% previously with recursion.
     32
     33        This is also the way gprof works, and as close as we can get to Shark's behavior (Shark is not instrumented so it
     34        can't know exactly how many calls came from where, etc).
     35
     36        * English.lproj/localizedStrings.js: Added "Average" for average times in the profile.
     37        * inspector/JavaScriptProfile.cpp:
     38        (WebCore::ProfileClass):
     39        * inspector/JavaScriptProfileNode.cpp:
     40        (WebCore::getParent):
     41        (WebCore::getHead):
     42        (WebCore::getCallUID):
     43        (WebCore::ProfileNodeClass):
     44        * inspector/front-end/BottomUpProfileDataGridTree.js: Added.
     45        (WebInspector.BottomUpProfileDataGridTree):
     46        (WebInspector.BottomUpProfileDataGridTree.prototype.focus):
     47        (WebInspector.BottomUpProfileDataGridNode):
     48        (WebInspector.BottomUpProfileDataGridNode.prototype._takePropertiesFromProfileDataGridNode):
     49        (WebInspector.BottomUpProfileDataGridNode.prototype._keepOnlyChild):
     50        (WebInspector.BottomUpProfileDataGridNode.prototype._exclude):
     51        (WebInspector.BottomUpProfileDataGridNode.prototype._merge):
     52        (WebInspector.BottomUpProfileDataGridNode.prototype._populate):
     53        * inspector/front-end/DataGrid.js:
     54        (WebInspector.DataGrid.prototype.insertChild):
     55        (WebInspector.DataGrid.prototype.removeChild):
     56        (WebInspector.DataGrid.prototype.removeChildren):
     57        (WebInspector.DataGridNode.prototype.set hasChildren):
     58        (WebInspector.DataGridNode.prototype.get hasChildren):
     59        * inspector/front-end/ProfileDataGridTree.js: Added.
     60        (WebInspector.ProfileDataGridNode):
     61        (WebInspector.ProfileDataGridNode.prototype.get data.formatMilliseconds):
     62        (WebInspector.ProfileDataGridNode.prototype.get data):
     63        (WebInspector.ProfileDataGridNode.prototype.createCell):
     64        (WebInspector.ProfileDataGridNode.prototype.select):
     65        (WebInspector.ProfileDataGridNode.prototype.deselect):
     66        (WebInspector.ProfileDataGridNode.prototype.expand):
     67        (WebInspector.ProfileDataGridNode.prototype.insertChild):
     68        (WebInspector.ProfileDataGridNode.prototype.removeChild):
     69        (WebInspector.ProfileDataGridNode.prototype.removeChildren):
     70        (WebInspector.ProfileDataGridNode.prototype.findChild):
     71        (WebInspector.ProfileDataGridNode.prototype.get averageTime):
     72        (WebInspector.ProfileDataGridNode.prototype.get averagePercent):
     73        (WebInspector.ProfileDataGridNode.prototype.get selfPercent):
     74        (WebInspector.ProfileDataGridNode.prototype.get totalPercent):
     75        (WebInspector.ProfileDataGridNode.prototype._save):
     76        (WebInspector.ProfileDataGridNode.prototype._restore):
     77        (WebInspector.ProfileDataGridNode.prototype._merge):
     78        (WebInspector.ProfileDataGridTree):
     79        (WebInspector.ProfileDataGridTree.prototype.get expanded):
     80        (WebInspector.ProfileDataGridTree.prototype.appendChild):
     81        (WebInspector.ProfileDataGridTree.prototype.insertChild):
     82        (WebInspector.ProfileDataGridTree.prototype.removeChildren):
     83        (WebInspector.ProfileDataGridTree.prototype.findChild.WebInspector.ProfileDataGridNode.prototype.findChild.sort.WebInspector.ProfileDataGridNode.prototype.sort._save):
     84        (WebInspector.ProfileDataGridTree.propertyComparator.comparator):
     85        (WebInspector.ProfileDataGridTree.propertyComparator.else.comparator):
     86        (WebInspector.ProfileDataGridTree.propertyComparator):
     87        * inspector/front-end/ProfileView.js:
     88        (WebInspector.ProfileView):
     89        (WebInspector.ProfileView.prototype.set profile):
     90        (WebInspector.ProfileView.prototype.get bottomUpProfileDataGridTree):
     91        (WebInspector.ProfileView.prototype.get topDownProfileDataGridTree):
     92        (WebInspector.ProfileView.prototype.get currentTree):
     93        (WebInspector.ProfileView.prototype.set currentTree):
     94        (WebInspector.ProfileView.prototype.get topDownTree):
     95        (WebInspector.ProfileView.prototype.get bottomUpTree):
     96        (WebInspector.ProfileView.prototype.refresh):
     97        (WebInspector.ProfileView.prototype.refreshVisibleData):
     98        (WebInspector.ProfileView.prototype.refreshShowAsPercents):
     99        (WebInspector.ProfileView.prototype.performSearch.matchesQuery):
     100        (WebInspector.ProfileView.prototype.performSearch):
     101        (WebInspector.ProfileView.prototype._changeView):
     102        (WebInspector.ProfileView.prototype._focusClicked):
     103        (WebInspector.ProfileView.prototype._excludeClicked):
     104        (WebInspector.ProfileView.prototype._resetClicked):
     105        (WebInspector.ProfileView.prototype._sortProfile):
     106        * inspector/front-end/ProfilesPanel.js:
     107        (WebInspector.ProfilesPanel.prototype.showProfile):
     108        (WebInspector.ProfilesPanel.prototype.showView):
     109        (WebInspector.ProfilesPanel.prototype.searchMatchFound):
     110        * inspector/front-end/TopDownProfileDataGridTree.js: Added.
     111        (WebInspector.TopDownProfileDataGridNode):
     112        (WebInspector.TopDownProfileDataGridNode.prototype._populate):
     113        (WebInspector.TopDownProfileDataGridNode.prototype._exclude):
     114        (WebInspector.TopDownProfileDataGridTree):
     115        (WebInspector.TopDownProfileDataGridTree.prototype.focus):
     116        (WebInspector.TopDownProfileDataGridTree.prototype.exclude):
     117        * inspector/front-end/WebKit.qrc:
     118        * inspector/front-end/inspector.css:
     119        * inspector/front-end/inspector.html:
     120
    11212009-04-23  Eric Seidel  <eric@webkit.org>
    2122
  • trunk/WebCore/WebCore.vcproj/WebCore.vcproj

    r42738 r42808  
    1564815648                                >
    1564915649                                <File
     15650                                        RelativePath="..\inspector\front-end\BottomUpProfileDataGridTree.js"
     15651                                        >
     15652                                </File>
     15653                                <File
    1565015654                                        RelativePath="..\inspector\front-end\Breakpoint.js"
    1565115655                                        >
     
    1574415748                                </File>
    1574515749                                <File
     15750                                        RelativePath="..\inspector\front-end\ProfileDataGridTree.js"
     15751                                        >
     15752                                </File>
     15753                                <File
    1574615754                                        RelativePath="..\inspector\front-end\PropertiesSection.js"
    1574715755                                        >
     
    1579715805                                <File
    1579815806                                        RelativePath="..\inspector\front-end\StylesSidebarPane.js"
     15807                                        >
     15808                                </File>
     15809                                <File
     15810                                        RelativePath="..\inspector\front-end\TopDownProfileDataGridTree.js"
    1579915811                                        >
    1580015812                                </File>
  • trunk/WebCore/inspector/JavaScriptProfile.cpp

    r39670 r42808  
    7373}
    7474
    75 static JSValueRef getHeavyProfileCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
    76 {
    77     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    78         return JSValueMakeUndefined(ctx);
    79 
    80     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    81     return toRef(toJS(toJS(ctx), profile->heavyProfile()));
    82 }
    83 
    84 static JSValueRef getTreeProfileCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
    85 {
    86     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    87         return JSValueMakeUndefined(ctx);
    88 
    89     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    90     return toRef(toJS(toJS(ctx), profile->treeProfile()));
    91 }
    92 
    9375static JSValueRef getUniqueIdCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
    9476{
     
    147129}
    148130
    149 static JSValueRef sortTotalTimeDescending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    150 {
    151     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    152         return JSValueMakeUndefined(ctx);
    153 
    154     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    155     profile->sortTotalTimeDescending();
    156 
    157     return JSValueMakeUndefined(ctx);
    158 }
    159 
    160 static JSValueRef sortTotalTimeAscending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    161 {
    162     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    163         return JSValueMakeUndefined(ctx);
    164 
    165     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    166     profile->sortTotalTimeAscending();
    167 
    168     return JSValueMakeUndefined(ctx);
    169 }
    170 
    171 static JSValueRef sortSelfTimeDescending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    172 {
    173     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    174         return JSValueMakeUndefined(ctx);
    175 
    176     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    177     profile->sortSelfTimeDescending();
    178 
    179     return JSValueMakeUndefined(ctx);
    180 }
    181 
    182 static JSValueRef sortSelfTimeAscending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    183 {
    184     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    185         return JSValueMakeUndefined(ctx);
    186 
    187     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    188     profile->sortSelfTimeAscending();
    189 
    190     return JSValueMakeUndefined(ctx);
    191 }
    192 
    193 static JSValueRef sortCallsDescending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    194 {
    195     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    196         return JSValueMakeUndefined(ctx);
    197 
    198     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    199     profile->sortCallsDescending();
    200 
    201     return JSValueMakeUndefined(ctx);
    202 }
    203 
    204 static JSValueRef sortCallsAscending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    205 {
    206     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    207         return JSValueMakeUndefined(ctx);
    208 
    209     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    210     profile->sortCallsAscending();
    211 
    212     return JSValueMakeUndefined(ctx);
    213 }
    214 
    215 static JSValueRef sortFunctionNameDescending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    216 {
    217     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    218         return JSValueMakeUndefined(ctx);
    219 
    220     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    221     profile->sortFunctionNameDescending();
    222 
    223     return JSValueMakeUndefined(ctx);
    224 }
    225 
    226 static JSValueRef sortFunctionNameAscending(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
    227 {
    228     if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass()))
    229         return JSValueMakeUndefined(ctx);
    230 
    231     Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject));
    232     profile->sortFunctionNameAscending();
    233 
    234     return JSValueMakeUndefined(ctx);
    235 }
    236 
    237131static void finalize(JSObjectRef object)
    238132{
     
    247141        { "title", getTitleCallback, 0, kJSPropertyAttributeNone },
    248142        { "head", getHeadCallback, 0, kJSPropertyAttributeNone },
    249         { "heavyProfile", getHeavyProfileCallback, 0, kJSPropertyAttributeNone },
    250         { "treeProfile", getTreeProfileCallback, 0, kJSPropertyAttributeNone },
    251143        { "uid", getUniqueIdCallback, 0, kJSPropertyAttributeNone },
    252144        { 0, 0, 0, 0 }
     
    257149        { "exclude", exclude, kJSPropertyAttributeNone },
    258150        { "restoreAll", restoreAll, kJSPropertyAttributeNone },
    259         { "sortTotalTimeDescending", sortTotalTimeDescending, kJSPropertyAttributeNone },
    260         { "sortTotalTimeAscending", sortTotalTimeAscending, kJSPropertyAttributeNone },
    261         { "sortSelfTimeDescending", sortSelfTimeDescending, kJSPropertyAttributeNone },
    262         { "sortSelfTimeAscending", sortSelfTimeAscending, kJSPropertyAttributeNone },
    263         { "sortCallsDescending", sortCallsDescending, kJSPropertyAttributeNone },
    264         { "sortCallsAscending", sortCallsAscending, kJSPropertyAttributeNone },
    265         { "sortFunctionNameDescending", sortFunctionNameDescending, kJSPropertyAttributeNone },
    266         { "sortFunctionNameAscending", sortFunctionNameAscending, kJSPropertyAttributeNone },
    267151        { 0, 0, 0 }
    268152    };
  • trunk/WebCore/inspector/JavaScriptProfileNode.cpp

    r39670 r42808  
    4747
    4848static ProfileNodeMap& profileNodeCache()
    49 { 
     49{
    5050    DEFINE_STATIC_LOCAL(ProfileNodeMap, staticProfileNodes, ());
    5151    return staticProfileNodes;
     
    163163
    164164    JSRetainPtr<JSStringRef> pushString(Adopt, JSStringCreateWithUTF8CString("push"));
    165    
     165
    166166    JSValueRef pushProperty = JSObjectGetProperty(ctx, result, pushString.get(), exception);
    167167    if (exception && *exception)
     
    182182}
    183183
     184static JSValueRef getParent(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
     185{
     186    JSC::JSLock lock(false);
     187
     188    if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
     189        return JSValueMakeUndefined(ctx);
     190
     191    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
     192    return toRef(toJS(toJS(ctx), profileNode->parent())
     193    );
     194}
     195
     196static JSValueRef getHead(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
     197{
     198    JSC::JSLock lock(false);
     199
     200    if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
     201        return JSValueMakeUndefined(ctx);
     202
     203    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
     204    return toRef(toJS(toJS(ctx), profileNode->head()));
     205}
     206
    184207static JSValueRef getVisible(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
    185208{
     
    191214    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
    192215    return JSValueMakeBoolean(ctx, profileNode->visible());
     216}
     217
     218static JSValueRef getCallUID(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
     219{
     220    JSC::JSLock lock(false);
     221
     222    if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
     223        return JSValueMakeUndefined(ctx);
     224
     225    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
     226    return JSValueMakeNumber(ctx, profileNode->callIdentifier().hash());
    193227}
    194228
     
    212246        { "numberOfCalls", getNumberOfCalls, 0, kJSPropertyAttributeNone },
    213247        { "children", getChildren, 0, kJSPropertyAttributeNone },
     248        { "parent", getParent, 0, kJSPropertyAttributeNone },
     249        { "head", getHead, 0, kJSClassAttributeNone },
    214250        { "visible", getVisible, 0, kJSPropertyAttributeNone },
     251        { "callUID", getCallUID, 0, kJSPropertyAttributeNone },
    215252        { 0, 0, 0, 0 }
    216253    };
  • trunk/WebCore/inspector/front-end/DataGrid.js

    r37289 r42808  
    170170    {
    171171        if (!child)
    172             throw("Node can't be undefined or null.");
     172            throw("insertChild: Node can't be undefined or null.");
    173173        if (child.parent === this)
    174             throw("Node is already a child of this node.");
     174            throw("insertChild: Node is already a child of this node.");
    175175
    176176        if (child.parent)
    177177            child.parent.removeChild(child);
    178178
    179         var previousChild = (index > 0 ? this.children[index - 1] : null);
    180         if (previousChild) {
    181             previousChild.nextSibling = child;
    182             child.previousSibling = previousChild;
    183         } else
    184             child.previousSibling = null;
    185 
    186         var nextChild = this.children[index];
    187         if (nextChild) {
    188             nextChild.previousSibling = child;
    189             child.nextSibling = nextChild;
    190         } else
    191             child.nextSibling = null;
    192 
    193179        this.children.splice(index, 0, child);
    194180        this.hasChildren = true;
     
    196182        child.parent = this;
    197183        child.dataGrid = this.dataGrid;
     184        child._recalculateSiblings(index);
    198185
    199186        delete child._depth;
     
    217204    {
    218205        if (!child)
    219             throw("Node can't be undefined or null.");
     206            throw("removeChild: Node can't be undefined or null.");
    220207        if (child.parent !== this)
    221             throw("Node is not a child of this node.");
     208            throw("removeChild: Node is not a child of this node.");
    222209
    223210        child.deselect();
     
    234221        child.nextSibling = null;
    235222        child.previousSibling = null;
     223
     224        if (this.children.length <= 0)
     225            this.hasChildren = false;
    236226    },
    237227
     
    250240
    251241        this.children = [];
     242        this.hasChildren = false;
    252243    },
    253244
     
    406397        if (!gridNode || !gridNode.selectable)
    407398            return;
    408    
     399
    409400        if (gridNode.isEventWithinDisclosureTriangle(event))
    410401            return;
     
    520511    },
    521512
     513    set hasChildren(x)
     514    {
     515        if (this._hasChildren === x)
     516            return;
     517
     518        this._hasChildren = x;
     519
     520        if (!this._element)
     521            return;
     522
     523        if (this._hasChildren)
     524        {
     525            this._element.addStyleClass("parent");
     526            if (this.expanded)
     527                this._element.addStyleClass("expanded");
     528        }
     529        else
     530        {
     531            this._element.removeStyleClass("parent");
     532            this._element.removeStyleClass("expanded");
     533        }
     534    },
     535
     536    get hasChildren()
     537    {
     538        return this._hasChildren;
     539    },
     540
    522541    set revealed(x)
    523542    {
     
    624643    removeChildren: WebInspector.DataGrid.prototype.removeChildren,
    625644    removeChildrenRecursive: WebInspector.DataGrid.prototype.removeChildrenRecursive,
     645
     646    _recalculateSiblings: function(myIndex)
     647    {
     648        if (!this.parent)
     649            return;
     650
     651        var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);
     652
     653        if (previousChild) {
     654            previousChild.nextSibling = this;
     655            this.previousSibling = previousChild;
     656        } else
     657            this.previousSibling = null;
     658
     659        var nextChild = this.parent.children[myIndex + 1];
     660
     661        if (nextChild) {
     662            nextChild.previousSibling = this;
     663            this.nextSibling = nextChild;
     664        } else
     665            this.nextSibling = null;
     666    },
    626667
    627668    collapse: function()
  • trunk/WebCore/inspector/front-end/ProfileView.js

    r37289 r42808  
    3232    this.showSelfTimeAsPercent = true;
    3333    this.showTotalTimeAsPercent = true;
     34    this.showAverageTimeAsPercent = true;
    3435
    3536    var columns = { "self": { title: WebInspector.UIString("Self"), width: "72px", sort: "descending", sortable: true },
    3637                    "total": { title: WebInspector.UIString("Total"), width: "72px", sortable: true },
     38                    "average": { title: WebInspector.UIString("Average"), width: "72px", sortable: true },
    3739                    "calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true },
    3840                    "function": { title: WebInspector.UIString("Function"), disclosure: true, sortable: true } };
     
    7678    this.resetButton.addEventListener("click", this._resetClicked.bind(this), false);
    7779
    78     // Default to the heavy profile.
    79     profile = profile.heavyProfile;
    80 
    81     // By default the profile isn't sorted, so sort based on our default sort
    82     // column and direction added to the DataGrid columns above.
    83     profile.sortSelfTimeDescending();
     80    this.profile = profile;
     81
     82    this.profileDataGridTree = this.bottomUpProfileDataGridTree;
     83    this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator("selfTime", false));
     84
     85    this.refresh();
    8486
    8587    this._updatePercentButton();
    86 
    87     this.profile = profile;
    8888}
    8989
     
    102102    {
    103103        this._profile = profile;
     104    },
     105
     106    get bottomUpProfileDataGridTree()
     107    {
     108        if (!this._bottomUpProfileDataGridTree)
     109            this._bottomUpProfileDataGridTree = new WebInspector.BottomUpProfileDataGridTree(this, this.profile.head);
     110        return this._bottomUpProfileDataGridTree;
     111    },
     112
     113    get topDownProfileDataGridTree()
     114    {
     115        if (!this._topDownProfileDataGridTree)
     116            this._topDownProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.head);
     117        return this._topDownProfileDataGridTree;
     118    },
     119
     120    get currentTree()
     121    {
     122        return this._currentTree;
     123    },
     124
     125    set currentTree(tree)
     126    {
     127        this._currentTree = tree;
    104128        this.refresh();
     129    },
     130
     131    get topDownTree()
     132    {
     133        if (!this._topDownTree) {
     134            this._topDownTree = WebInspector.TopDownTreeFactory.create(this.profile.head);
     135            this._sortProfile(this._topDownTree);
     136        }
     137
     138        return this._topDownTree;
     139    },
     140
     141    get bottomUpTree()
     142    {
     143        if (!this._bottomUpTree) {
     144            this._bottomUpTree = WebInspector.BottomUpTreeFactory.create(this.profile.head);
     145            this._sortProfile(this._bottomUpTree);
     146        }
     147
     148        return this._bottomUpTree;
    105149    },
    106150
     
    117161        this.dataGrid.removeChildren();
    118162
    119         var children = this.profile.head.children;
    120         var childrenLength = children.length;
    121         for (var i = 0; i < childrenLength; ++i)
    122             if (children[i].visible)
    123                 this.dataGrid.appendChild(new WebInspector.ProfileDataGridNode(this, children[i]));
     163        var children = this.profileDataGridTree.children;
     164        var count = children.length;
     165
     166        for (var index = 0; index < count; ++index)
     167            this.dataGrid.appendChild(children[index]);
    124168
    125169        if (selectedProfileNode && selectedProfileNode._dataGridNode)
     
    127171    },
    128172
    129     refreshShowAsPercents: function()
    130     {
    131         this._updatePercentButton();
    132 
     173    refreshVisibleData: function()
     174    {
    133175        var child = this.dataGrid.children[0];
    134176        while (child) {
     
    136178            child = child.traverseNextNode(false, null, true);
    137179        }
     180    },
     181
     182    refreshShowAsPercents: function()
     183    {
     184        this._updatePercentButton();
     185        this.refreshVisibleData();
    138186    },
    139187
     
    192240            equalTo = true;
    193241
    194         function matchesQuery(profileNode)
     242        function matchesQuery(/*ProfileDataGridNode*/ profileDataGridNode)
    195243        {
    196             delete profileNode._searchMatchedSelfColumn;
    197             delete profileNode._searchMatchedTotalColumn;
    198             delete profileNode._searchMatchedCallsColumn;
    199             delete profileNode._searchMatchedFunctionColumn;
     244            delete profileDataGridNode._searchMatchedSelfColumn;
     245            delete profileDataGridNode._searchMatchedTotalColumn;
     246            delete profileDataGridNode._searchMatchedAverageColumn;
     247            delete profileDataGridNode._searchMatchedCallsColumn;
     248            delete profileDataGridNode._searchMatchedFunctionColumn;
    200249
    201250            if (percentUnits) {
    202251                if (lessThan) {
    203                     if (profileNode.selfPercent < queryNumber)
    204                         profileNode._searchMatchedSelfColumn = true;
    205                     if (profileNode.totalPercent < queryNumber)
    206                         profileNode._searchMatchedTotalColumn = true;
     252                    if (profileDataGridNode.selfPercent < queryNumber)
     253                        profileDataGridNode._searchMatchedSelfColumn = true;
     254                    if (profileDataGridNode.totalPercent < queryNumber)
     255                        profileDataGridNode._searchMatchedTotalColumn = true;
     256                    if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
     257                        profileDataGridNode._searchMatchedAverageColumn = true;
    207258                } else if (greaterThan) {
    208                     if (profileNode.selfPercent > queryNumber)
    209                         profileNode._searchMatchedSelfColumn = true;
    210                     if (profileNode.totalPercent > queryNumber)
    211                         profileNode._searchMatchedTotalColumn = true;
     259                    if (profileDataGridNode.selfPercent > queryNumber)
     260                        profileDataGridNode._searchMatchedSelfColumn = true;
     261                    if (profileDataGridNode.totalPercent > queryNumber)
     262                        profileDataGridNode._searchMatchedTotalColumn = true;
     263                    if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
     264                        profileDataGridNode._searchMatchedAverageColumn = true;
    212265                }
    213266
    214267                if (equalTo) {
    215                     if (profileNode.selfPercent == queryNumber)
    216                         profileNode._searchMatchedSelfColumn = true;
    217                     if (profileNode.totalPercent == queryNumber)
    218                         profileNode._searchMatchedTotalColumn = true;
     268                    if (profileDataGridNode.selfPercent == queryNumber)
     269                        profileDataGridNode._searchMatchedSelfColumn = true;
     270                    if (profileDataGridNode.totalPercent == queryNumber)
     271                        profileDataGridNode._searchMatchedTotalColumn = true;
     272                    if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
     273                        profileDataGridNode._searchMatchedAverageColumn = true;
    219274                }
    220275            } else if (millisecondsUnits || secondsUnits) {
    221276                if (lessThan) {
    222                     if (profileNode.selfTime < queryNumberMilliseconds)
    223                         profileNode._searchMatchedSelfColumn = true;
    224                     if (profileNode.totalTime < queryNumberMilliseconds)
    225                         profileNode._searchMatchedTotalColumn = true;
     277                    if (profileDataGridNode.selfTime < queryNumberMilliseconds)
     278                        profileDataGridNode._searchMatchedSelfColumn = true;
     279                    if (profileDataGridNode.totalTime < queryNumberMilliseconds)
     280                        profileDataGridNode._searchMatchedTotalColumn = true;
     281                    if (profileDataGridNode.averageTime < queryNumberMilliseconds)
     282                        profileDataGridNode._searchMatchedAverageColumn = true;
    226283                } else if (greaterThan) {
    227                     if (profileNode.selfTime > queryNumberMilliseconds)
    228                         profileNode._searchMatchedSelfColumn = true;
    229                     if (profileNode.totalTime > queryNumberMilliseconds)
    230                         profileNode._searchMatchedTotalColumn = true;
     284                    if (profileDataGridNode.selfTime > queryNumberMilliseconds)
     285                        profileDataGridNode._searchMatchedSelfColumn = true;
     286                    if (profileDataGridNode.totalTime > queryNumberMilliseconds)
     287                        profileDataGridNode._searchMatchedTotalColumn = true;
     288                    if (profileDataGridNode.averageTime > queryNumberMilliseconds)
     289                        profileDataGridNode._searchMatchedAverageColumn = true;
    231290                }
    232291
    233292                if (equalTo) {
    234                     if (profileNode.selfTime == queryNumberMilliseconds)
    235                         profileNode._searchMatchedSelfColumn = true;
    236                     if (profileNode.totalTime == queryNumberMilliseconds)
    237                         profileNode._searchMatchedTotalColumn = true;
     293                    if (profileDataGridNode.selfTime == queryNumberMilliseconds)
     294                        profileDataGridNode._searchMatchedSelfColumn = true;
     295                    if (profileDataGridNode.totalTime == queryNumberMilliseconds)
     296                        profileDataGridNode._searchMatchedTotalColumn = true;
     297                    if (profileDataGridNode.averageTime == queryNumberMilliseconds)
     298                        profileDataGridNode._searchMatchedAverageColumn = true;
    238299                }
    239300            } else {
    240                 if (equalTo && profileNode.numberOfCalls == queryNumber)
    241                     profileNode._searchMatchedCallsColumn = true;
    242                 if (greaterThan && profileNode.numberOfCalls > queryNumber)
    243                     profileNode._searchMatchedCallsColumn = true;
    244                 if (lessThan && profileNode.numberOfCalls < queryNumber)
    245                     profileNode._searchMatchedCallsColumn = true;
     301                if (equalTo && profileDataGridNode.numberOfCalls == queryNumber)
     302                    profileDataGridNode._searchMatchedCallsColumn = true;
     303                if (greaterThan && profileDataGridNode.numberOfCalls > queryNumber)
     304                    profileDataGridNode._searchMatchedCallsColumn = true;
     305                if (lessThan && profileDataGridNode.numberOfCalls < queryNumber)
     306                    profileDataGridNode._searchMatchedCallsColumn = true;
    246307            }
    247308
    248             if (profileNode.functionName.hasSubstring(query, true) || profileNode.url.hasSubstring(query, true))
    249                 profileNode._searchMatchedFunctionColumn = true;
    250 
    251             var matched = (profileNode._searchMatchedSelfColumn || profileNode._searchMatchedTotalColumn || profileNode._searchMatchedCallsColumn || profileNode._searchMatchedFunctionColumn);
    252             if (matched && profileNode._dataGridNode)
    253                 profileNode._dataGridNode.refresh();
    254 
    255             return matched;
    256         }
    257 
    258         var current = this.profile.head;
     309            if (profileDataGridNode.functionName.hasSubstring(query, true) || profileDataGridNode.url.hasSubstring(query, true))
     310                profileDataGridNode._searchMatchedFunctionColumn = true;
     311
     312            if (profileDataGridNode._searchMatchedSelfColumn ||
     313                profileDataGridNode._searchMatchedTotalColumn ||
     314                profileDataGridNode._searchMatchedAverageColumn ||
     315                profileDataGridNode._searchMatchedCallsColumn ||
     316                profileDataGridNode._searchMatchedFunctionColumn);
     317            {
     318                profileDataGridNode.refresh();
     319                return true;
     320            }
     321
     322            return false;
     323        }
     324
     325        var current = this.dataGrid;
    259326        var ancestors = [];
    260327        var nextIndexes = [];
     
    381448
    382449        if (event.target.selectedIndex == 1 && this.view == "Heavy") {
    383             this._sortProfile(this.profile.treeProfile);
    384             this.profile = this.profile.treeProfile;
     450            this.profileDataGridTree = this.topDownProfileDataGridTree;
     451            this._sortProfile();
    385452            this.view = "Tree";
    386453        } else if (event.target.selectedIndex == 0 && this.view == "Tree") {
    387             this._sortProfile(this.profile.heavyProfile);
    388             this.profile = this.profile.heavyProfile;
     454            this.profileDataGridTree = this.bottomUpProfileDataGridTree;
     455            this._sortProfile();
    389456            this.view = "Heavy";
    390457        }
     
    402469    _percentClicked: function(event)
    403470    {
    404         var currentState = this.showSelfTimeAsPercent && this.showTotalTimeAsPercent;
     471        var currentState = this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent;
    405472        this.showSelfTimeAsPercent = !currentState;
    406473        this.showTotalTimeAsPercent = !currentState;
     474        this.showAverageTimeAsPercent = !currentState;
    407475        this.refreshShowAsPercents();
    408476    },
     
    410478    _updatePercentButton: function()
    411479    {
    412         if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent) {
     480        if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) {
    413481            this.percentButton.title = WebInspector.UIString("Show absolute total and self times.");
    414482            this.percentButton.addStyleClass("toggled-on");
     
    421489    _focusClicked: function(event)
    422490    {
    423         if (!this.dataGrid.selectedNode || !this.dataGrid.selectedNode.profileNode)
    424             return;
     491        if (!this.dataGrid.selectedNode)
     492            return;
     493
    425494        this.resetButton.removeStyleClass("hidden");
    426         this.profile.focus(this.dataGrid.selectedNode.profileNode);
     495        this.profileDataGridTree.focus(this.dataGrid.selectedNode);
    427496        this.refresh();
     497        this.refreshVisibleData();
    428498    },
    429499
    430500    _excludeClicked: function(event)
    431501    {
    432         if (!this.dataGrid.selectedNode || !this.dataGrid.selectedNode.profileNode)
    433             return;
     502        var selectedNode = this.dataGrid.selectedNode
     503
     504        if (!selectedNode)
     505            return;
     506
     507        selectedNode.deselect();
     508
    434509        this.resetButton.removeStyleClass("hidden");
    435         this.profile.exclude(this.dataGrid.selectedNode.profileNode);
    436         this.dataGrid.selectedNode.deselect();
     510        this.profileDataGridTree.exclude(selectedNode);
    437511        this.refresh();
     512        this.refreshVisibleData();
    438513    },
    439514
     
    441516    {
    442517        this.resetButton.addStyleClass("hidden");
    443         this.profile.restoreAll();
     518        this.profileDataGridTree.restore();
    444519        this.refresh();
     520        this.refreshVisibleData();
    445521    },
    446522
     
    462538    },
    463539
    464     _sortProfile: function(profile)
    465     {
    466         if (!profile)
    467             return;
    468 
    469         var sortOrder = this.dataGrid.sortOrder;
     540    _sortProfile: function()
     541    {
     542        var sortAscending = this.dataGrid.sortOrder === "ascending";
    470543        var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
    471 
    472         var sortingFunctionName = "sort";
    473 
    474         if (sortColumnIdentifier === "self")
    475             sortingFunctionName += "SelfTime";
    476         else if (sortColumnIdentifier === "total")
    477             sortingFunctionName += "TotalTime";
    478         else if (sortColumnIdentifier === "calls")
    479             sortingFunctionName += "Calls";
    480         else if (sortColumnIdentifier === "function")
    481             sortingFunctionName += "FunctionName";
    482 
    483         if (sortOrder === "ascending")
    484             sortingFunctionName += "Ascending";
    485         else
    486             sortingFunctionName += "Descending";
    487 
    488         if (!(sortingFunctionName in this.profile))
    489             return;
    490 
    491         profile[sortingFunctionName]();
    492 
    493         if (profile === this.profile)
    494             this.refresh();
     544        var sortProperty = {
     545                "average": "averageTime",
     546                "self": "selfTime",
     547                "total": "totalTime",
     548                "calls": "numberOfCalls",
     549                "function": "functionName"
     550            }[sortColumnIdentifier];
     551
     552        this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator(sortProperty, sortAscending));
     553
     554        this.refresh();
    495555    },
    496556
     
    501561
    502562        var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
    503         if (!cell || (!cell.hasStyleClass("total-column") && !cell.hasStyleClass("self-column")))
     563        if (!cell || (!cell.hasStyleClass("total-column") && !cell.hasStyleClass("self-column") && !cell.hasStyleClass("average-column")))
    504564            return;
    505565
     
    508568        else if (cell.hasStyleClass("self-column"))
    509569            this.showSelfTimeAsPercent = !this.showSelfTimeAsPercent;
     570        else if (cell.hasStyleClass("average-column"))
     571            this.showAverageTimeAsPercent = !this.showAverageTimeAsPercent;
    510572
    511573        this.refreshShowAsPercents();
     
    517579
    518580WebInspector.ProfileView.prototype.__proto__ = WebInspector.View.prototype;
    519 
    520 WebInspector.ProfileDataGridNode = function(profileView, profileNode)
    521 {
    522     this.profileView = profileView;
    523 
    524     this.profileNode = profileNode;
    525     profileNode._dataGridNode = this;
    526 
    527     // Find the first child that is visible. Since we don't want to claim
    528     // we have children if all the children are invisible.
    529     var hasChildren = false;
    530     var children = this.profileNode.children;
    531     var childrenLength = children.length;
    532     for (var i = 0; i < childrenLength; ++i) {
    533         if (children[i].visible) {
    534             hasChildren = true;
    535             break;
    536         }
    537     }
    538 
    539     WebInspector.DataGridNode.call(this, null, hasChildren);
    540 
    541     this.addEventListener("populate", this._populate, this);
    542 
    543     this.expanded = profileNode._expanded;
    544 }
    545 
    546 WebInspector.ProfileDataGridNode.prototype = {
    547     get data()
    548     {
    549         function formatMilliseconds(time)
    550         {
    551             return Number.secondsToString(time / 1000, WebInspector.UIString.bind(WebInspector), true);
    552         }
    553 
    554         var data = {};
    555         data["function"] = this.profileNode.functionName;
    556         data["calls"] = this.profileNode.numberOfCalls;
    557 
    558         if (this.profileView.showSelfTimeAsPercent)
    559             data["self"] = WebInspector.UIString("%.2f%%", this.profileNode.selfPercent);
    560         else
    561             data["self"] = formatMilliseconds(this.profileNode.selfTime);
    562 
    563         if (this.profileView.showTotalTimeAsPercent)
    564             data["total"] = WebInspector.UIString("%.2f%%", this.profileNode.totalPercent);
    565         else
    566             data["total"] = formatMilliseconds(this.profileNode.totalTime);
    567 
    568         return data;
    569     },
    570 
    571     createCell: function(columnIdentifier)
    572     {
    573         var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
    574 
    575         if (columnIdentifier === "self" && this.profileNode._searchMatchedSelfColumn)
    576             cell.addStyleClass("highlight");
    577         else if (columnIdentifier === "total" && this.profileNode._searchMatchedTotalColumn)
    578             cell.addStyleClass("highlight");
    579         else if (columnIdentifier === "calls" && this.profileNode._searchMatchedCallsColumn)
    580             cell.addStyleClass("highlight");
    581 
    582         if (columnIdentifier !== "function")
    583             return cell;
    584 
    585         if (this.profileNode._searchMatchedFunctionColumn)
    586             cell.addStyleClass("highlight");
    587 
    588         if (this.profileNode.url) {
    589             var fileName = WebInspector.displayNameForURL(this.profileNode.url);
    590 
    591             var urlElement = document.createElement("a");
    592             urlElement.className = "profile-node-file webkit-html-resource-link";
    593             urlElement.href = this.profileNode.url;
    594             urlElement.lineNumber = this.profileNode.lineNumber;
    595 
    596             if (this.profileNode.lineNumber > 0)
    597                 urlElement.textContent = fileName + ":" + this.profileNode.lineNumber;
    598             else
    599                 urlElement.textContent = fileName;
    600 
    601             cell.insertBefore(urlElement, cell.firstChild);
    602         }
    603 
    604         return cell;
    605     },
    606 
    607     select: function(supressSelectedEvent)
    608     {
    609         WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent);
    610         this.profileView._dataGridNodeSelected(this);
    611     },
    612 
    613     deselect: function(supressDeselectedEvent)
    614     {
    615         WebInspector.DataGridNode.prototype.deselect.call(this, supressDeselectedEvent);
    616         this.profileView._dataGridNodeDeselected(this);
    617     },
    618 
    619     expand: function()
    620     {
    621         WebInspector.DataGridNode.prototype.expand.call(this);
    622         this.profileNode._expanded = true;
    623     },
    624 
    625     collapse: function()
    626     {
    627         WebInspector.DataGridNode.prototype.collapse.call(this);
    628         this.profileNode._expanded = false;
    629     },
    630 
    631     _populate: function(event)
    632     {
    633         var children = this.profileNode.children;
    634         var childrenLength = children.length;
    635         for (var i = 0; i < childrenLength; ++i)
    636             if (children[i].visible)
    637                 this.appendChild(new WebInspector.ProfileDataGridNode(this.profileView, children[i]));
    638         this.removeEventListener("populate", this._populate, this);
    639     }
    640 }
    641 
    642 WebInspector.ProfileDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
  • trunk/WebCore/inspector/front-end/ProfilesPanel.js

    r37933 r42808  
    219219
    220220        profile._profilesTreeElement.select(true);
    221         profile._profilesTreeElement.reveal()
     221        profile._profilesTreeElement.reveal();
    222222
    223223        this.visibleView = view;
     
    232232    showView: function(view)
    233233    {
    234         // Always use the treeProfile, since the heavy profile might be showing.
    235         this.showProfile(view.profile.treeProfile);
     234        this.showProfile(view.profile);
    236235    },
    237236
     
    296295    searchMatchFound: function(view, matches)
    297296    {
    298         // Always use the treeProfile, since the heavy profile might be showing.
    299         view.profile.treeProfile._profilesTreeElement.searchMatches = matches;
     297        view.profile._profilesTreeElement.searchMatches = matches;
    300298    },
    301299
  • trunk/WebCore/inspector/front-end/WebKit.qrc

    r41288 r42808  
    44    <file>Breakpoint.js</file>
    55    <file>BreakpointsSidebarPane.js</file>
     6    <file>BottomUpProfileDataGridTree.js</file>
    67    <file>CallStackSidebarPane.js</file>
    78    <file>Console.js</file>
     
    2627    <file>Placard.js</file>
    2728    <file>ProfilesPanel.js</file>
     29    <file>ProfileDataGridTree.js</file>
    2830    <file>ProfileView.js</file>
    2931    <file>PropertiesSection.js</file>
     
    4345    <file>StylesSidebarPane.js</file>
    4446    <file>TextPrompt.js</file>
     47    <file>TopDownProfileDataGridTree.js</file>
    4548    <file>treeoutline.js</file>
    4649    <file>utilities.js</file>
  • trunk/WebCore/inspector/front-end/inspector.css

    r41423 r42808  
    29312931}
    29322932
     2933.profile-view .data-grid th.average-column {
     2934    text-align: center;
     2935}
     2936
     2937.profile-view .data-grid td.average-column {
     2938    text-align: right;
     2939}
     2940
    29332941.profile-view .data-grid th.self-column {
    29342942    text-align: center;
  • trunk/WebCore/inspector/front-end/inspector.html

    r41288 r42808  
    7474    <script type="text/javascript" src="DatabaseQueryView.js"></script>
    7575    <script type="text/javascript" src="ScriptView.js"></script>
     76    <script type="text/javascript" src="ProfileDataGridTree.js"></script>
     77    <script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
     78    <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
    7679    <script type="text/javascript" src="ProfileView.js"></script>
    7780</head>
Note: See TracChangeset for help on using the changeset viewer.