2008-06-04 Kevin McCullough <kmccullough@apple.com>
authorkmccullough@apple.com <kmccullough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Jun 2008 18:53:10 +0000 (18:53 +0000)
committerkmccullough@apple.com <kmccullough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Jun 2008 18:53:10 +0000 (18:53 +0000)
        Reviewed by Geoff.

        <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the
        profiler.
        - This patch removes the use of recursion for the sort functions.

        * JavaScriptCore.exp: Change the signatures of the functions being
        exported.
        * profiler/Profile.cpp:
        (KJS::Profile::sort): This generic function will accept any of the
        static sort functions and apply them to the whole tree.
        * profiler/Profile.h: All of the sorting functions now call the new
        sort() function.
        (KJS::Profile::sortTotalTimeDescending):
        (KJS::Profile::sortTotalTimeAscending):
        (KJS::Profile::sortSelfTimeDescending):
        (KJS::Profile::sortSelfTimeAscending):
        (KJS::Profile::sortCallsDescending):
        (KJS::Profile::sortCallsAscending):
        (KJS::Profile::sortFunctionNameDescending):
        (KJS::Profile::sortFunctionNameAscending):
        * profiler/ProfileNode.cpp:
        (KJS::ProfileNode::ProfileNode): m_head used to point to the head node
        if this was the head node.  It now points to null to make iteration easy
        (KJS::ProfileNode::willExecute): Now must check if m_head is null, this
        check used to happend in the constructor.
        (KJS::ProfileNode::stopProfiling): Again the check is slightly different
        to determine if this is the head.
        (KJS::ProfileNode::traverseNextNode): This function returns the next
        node in post order.
        (KJS::ProfileNode::sort): This generic function will sort according to
        the comparator passed in, then reset the children pointers to macth the
        new order.
        * profiler/ProfileNode.h: The sorting function were removed from the
        definition file and instead use the new generic sort() function
        (KJS::ProfileNode::totalPercent): because the head can now be empty we
        need to check here too for the head node.
        (KJS::ProfileNode::selfPercent): Ditto
        (KJS::ProfileNode::firstChild): This function is necessary for the
        iterative algorithm in Profile.cpp.
        (KJS::ProfileNode::sortTotalTimeDescending):
        (KJS::ProfileNode::sortTotalTimeAscending):
        (KJS::ProfileNode::sortSelfTimeDescending):
        (KJS::ProfileNode::sortSelfTimeAscending):
        (KJS::ProfileNode::sortCallsDescending):
        (KJS::ProfileNode::sortCallsAscending):
        (KJS::ProfileNode::sortFunctionNameDescending):
        (KJS::ProfileNode::sortFunctionNameAscending):
        (KJS::ProfileNode::childrenBegin):
        (KJS::ProfileNode::childrenEnd):
        (KJS::ProfileNode::totalTimeDescendingComparator):
        (KJS::ProfileNode::totalTimeAscendingComparator):
        (KJS::ProfileNode::selfTimeDescendingComparator):
        (KJS::ProfileNode::selfTimeAscendingComparator):
        (KJS::ProfileNode::callsDescendingComparator):
        (KJS::ProfileNode::callsAscendingComparator):
        (KJS::ProfileNode::functionNameDescendingComparator):
        (KJS::ProfileNode::functionNameAscendingComparator):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@34362 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/profiler/Profile.cpp
JavaScriptCore/profiler/Profile.h
JavaScriptCore/profiler/ProfileNode.cpp
JavaScriptCore/profiler/ProfileNode.h

index 67df4d641d8415bd95f1fa78953c036d2e6ae597..f31d6f9c08a5825784a4ed36a46c075bcc63675d 100644 (file)
@@ -1,3 +1,64 @@
+2008-06-04  Kevin McCullough  <kmccullough@apple.com>
+
+        Reviewed by Geoff.
+
+        <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the
+        profiler.
+        - This patch removes the use of recursion for the sort functions.
+
+        * JavaScriptCore.exp: Change the signatures of the functions being
+        exported.
+        * profiler/Profile.cpp:
+        (KJS::Profile::sort): This generic function will accept any of the
+        static sort functions and apply them to the whole tree.
+        * profiler/Profile.h: All of the sorting functions now call the new
+        sort() function.
+        (KJS::Profile::sortTotalTimeDescending):
+        (KJS::Profile::sortTotalTimeAscending):
+        (KJS::Profile::sortSelfTimeDescending):
+        (KJS::Profile::sortSelfTimeAscending):
+        (KJS::Profile::sortCallsDescending):
+        (KJS::Profile::sortCallsAscending):
+        (KJS::Profile::sortFunctionNameDescending):
+        (KJS::Profile::sortFunctionNameAscending):
+        * profiler/ProfileNode.cpp:
+        (KJS::ProfileNode::ProfileNode): m_head used to point to the head node
+        if this was the head node.  It now points to null to make iteration easy
+        (KJS::ProfileNode::willExecute): Now must check if m_head is null, this
+        check used to happend in the constructor.
+        (KJS::ProfileNode::stopProfiling): Again the check is slightly different
+        to determine if this is the head.
+        (KJS::ProfileNode::traverseNextNode): This function returns the next
+        node in post order.
+        (KJS::ProfileNode::sort): This generic function will sort according to
+        the comparator passed in, then reset the children pointers to macth the
+        new order.
+        * profiler/ProfileNode.h: The sorting function were removed from the
+        definition file and instead use the new generic sort() function
+        (KJS::ProfileNode::totalPercent): because the head can now be empty we
+        need to check here too for the head node.
+        (KJS::ProfileNode::selfPercent): Ditto
+        (KJS::ProfileNode::firstChild): This function is necessary for the 
+        iterative algorithm in Profile.cpp.
+        (KJS::ProfileNode::sortTotalTimeDescending):
+        (KJS::ProfileNode::sortTotalTimeAscending):
+        (KJS::ProfileNode::sortSelfTimeDescending):
+        (KJS::ProfileNode::sortSelfTimeAscending):
+        (KJS::ProfileNode::sortCallsDescending):
+        (KJS::ProfileNode::sortCallsAscending):
+        (KJS::ProfileNode::sortFunctionNameDescending):
+        (KJS::ProfileNode::sortFunctionNameAscending):
+        (KJS::ProfileNode::childrenBegin):
+        (KJS::ProfileNode::childrenEnd):
+        (KJS::ProfileNode::totalTimeDescendingComparator):
+        (KJS::ProfileNode::totalTimeAscendingComparator):
+        (KJS::ProfileNode::selfTimeDescendingComparator):
+        (KJS::ProfileNode::selfTimeAscendingComparator):
+        (KJS::ProfileNode::callsDescendingComparator):
+        (KJS::ProfileNode::callsAscendingComparator):
+        (KJS::ProfileNode::functionNameDescendingComparator):
+        (KJS::ProfileNode::functionNameAscendingComparator):
+
 2008-06-04  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Darin.
index 8875dec7b46ae4dc2cc8303f1a20731d69266251..1d2cec302bfc65e8035c6b6346668834f2658589 100644 (file)
@@ -15,17 +15,10 @@ __ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_7UStringEiN3
 __ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_7UStringEiS7_PNS_7JSValueE
 __ZN3KJS11JSImmediate8toObjectEPKNS_7JSValueEPNS_9ExecStateE
 __ZN3KJS11JSImmediate8toStringEPKNS_7JSValueE
-__ZN3KJS11ProfileNode10restoreAllEv
-__ZN3KJS11ProfileNode18sortCallsAscendingEv
-__ZN3KJS11ProfileNode19sortCallsDescendingEv
-__ZN3KJS11ProfileNode21sortSelfTimeAscendingEv
-__ZN3KJS11ProfileNode22sortSelfTimeDescendingEv
-__ZN3KJS11ProfileNode22sortTotalTimeAscendingEv
-__ZN3KJS11ProfileNode23sortTotalTimeDescendingEv
-__ZN3KJS11ProfileNode25sortFunctionNameAscendingEv
-__ZN3KJS11ProfileNode26sortFunctionNameDescendingEv
+__ZN3KJS11ProfileNode4sortEPFbRKN3WTF6RefPtrIS0_EES5_E
 __ZN3KJS11ProfileNode5focusERKNS_14CallIdentifierEb
 __ZN3KJS11ProfileNode7excludeERKNS_14CallIdentifierE
+__ZN3KJS11ProfileNode10restoreAllEv
 __ZN3KJS11ProgramNode6createEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_INS3_6RefPtrINS_12FuncDeclNodeEEELm16EEEbb
 __ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierE
 __ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierERb
@@ -95,6 +88,7 @@ __ZN3KJS6strtodEPKcPPc
 __ZN3KJS7CStringaSERKS0_
 __ZN3KJS7CStringD1Ev
 __ZN3KJS7Machine13dumpCallFrameEPKNS_9CodeBlockEPNS_14ScopeChainNodeEPNS_12RegisterFileEPKNS_8RegisterE
+__ZN3KJS7Profile4sortEPFvPNS_11ProfileNodeEE
 __ZN3KJS7UString3Rep11computeHashEPKti
 __ZN3KJS7UString3Rep4nullE
 __ZN3KJS7UString3Rep7destroyEv
@@ -149,6 +143,8 @@ __ZN3KJS9Collector7protectEPNS_7JSValueE
 __ZN3KJS9Collector9unprotectEPNS_7JSValueE
 __ZN3KJS9ExecStateC1EPNS_14JSGlobalObjectEPNS_8JSObjectEPNS_14ScopeChainNodeE
 __ZN3KJSeqERKNS_7UStringEPKc
+__ZN3KJSgtERKNS_7UStringES2_
+__ZN3KJSltERKNS_7UStringES2_
 __ZN3WTF10fastCallocEmm
 __ZN3WTF10fastMallocEm
 __ZN3WTF11fastReallocEPvm
index be88ec8718481d82cdccca00c8d4554b03d6a1ea..12dea44d6a20176733426a2eceaeb37326e2fe73 100644 (file)
@@ -86,6 +86,19 @@ void Profile::didExecute(const CallIdentifier& callIdentifier)
     --m_depth;
 }
 
+void Profile::sort(SortFunction function) {
+
+    ProfileNode* currentNode = m_headNode->firstChild();
+    for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild())
+        currentNode = nextNode;
+
+    ProfileNode* endNode = m_headNode->traverseNextNode();
+    while (currentNode && currentNode != endNode) {
+    function(currentNode);
+    currentNode = currentNode->traverseNextNode();
+    } 
+}
+
 #ifndef NDEBUG
 void Profile::debugPrintData() const
 {
index fb5f9e1c8dcff3f38d8d879c327f3b16995b0a85..ddd26456d69723b84c6bbe2aeb5e7f3568fa0bc8 100644 (file)
@@ -33,6 +33,7 @@
 namespace KJS {
 
     class ExecState;
+    typedef void (*SortFunction)(ProfileNode*);
 
     class Profile : public RefCounted<Profile> {
     public:
@@ -50,14 +51,15 @@ namespace KJS {
         ExecState* originatingGlobalExec() const { return m_originatingGlobalExec; }
         unsigned pageGroupIdentifier() const { return m_pageGroupIdentifier; }
 
-        void sortTotalTimeDescending() { m_headNode->sortTotalTimeDescending(); }
-        void sortTotalTimeAscending() { m_headNode->sortTotalTimeAscending(); }
-        void sortSelfTimeDescending() { m_headNode->sortSelfTimeDescending(); }
-        void sortSelfTimeAscending() { m_headNode->sortSelfTimeAscending(); }
-        void sortCallsDescending() { m_headNode->sortCallsDescending(); }
-        void sortCallsAscending() { m_headNode->sortCallsAscending(); }
-        void sortFunctionNameDescending() { m_headNode->sortFunctionNameDescending(); }
-        void sortFunctionNameAscending() { m_headNode->sortFunctionNameAscending(); }
+        void sort(SortFunction);
+        void sortTotalTimeDescending() { sort(ProfileNode::sortTotalTimeDescending); }
+        void sortTotalTimeAscending() { sort(ProfileNode::sortTotalTimeAscending); }
+        void sortSelfTimeDescending() { sort(ProfileNode::sortSelfTimeDescending); }
+        void sortSelfTimeAscending() { sort(ProfileNode::sortSelfTimeAscending); }
+        void sortCallsDescending() { sort(ProfileNode::sortCallsDescending); }
+        void sortCallsAscending() { sort(ProfileNode::sortCallsAscending); }
+        void sortFunctionNameDescending() { sort(ProfileNode::sortFunctionNameDescending); }
+        void sortFunctionNameAscending() { sort(ProfileNode::sortFunctionNameAscending); }
 
         void focus(const ProfileNode* profileNode) { if (!profileNode) return; m_headNode->focus(profileNode->callIdentifier()); }
         void exclude(const ProfileNode* profileNode) { if (!profileNode) return; m_headNode->exclude(profileNode->callIdentifier()); }
index f67aedc74d583e69120bfe6edbdfd3afde69fe4d..2e4a76613c68ddaed9227d3fe02e1e6df5587026 100644 (file)
@@ -69,9 +69,6 @@ ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* head
     , m_numberOfCalls(0)
     , m_visible(true)
 {
-    if (!m_head)
-        m_head = this;
-
     startTimer();
 }
 
@@ -84,7 +81,7 @@ ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
         }
     }
 
-    RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head, this);
+    RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head ? m_head : this, this);   // If this ProfileNode has no head it is the head.
     if (m_children.size())
         m_children.last()->setNextSibling(newChild.get());
     m_children.append(newChild.release());
@@ -136,7 +133,7 @@ void ProfileNode::stopProfiling()
     ASSERT(m_actualSelfTime <= m_actualTotalTime);
     m_actualSelfTime = m_actualTotalTime - m_actualSelfTime;
 
-    if (m_head == this && m_actualSelfTime) {
+    if (!m_head && m_actualSelfTime) {
         ProfileNode* idleNode = willExecute(CallIdentifier(NonJSExecution, 0, 0));
 
         idleNode->setTotalTime(m_actualSelfTime);
@@ -149,133 +146,19 @@ void ProfileNode::stopProfiling()
     m_visibleSelfTime = m_actualSelfTime;
 }
 
-// Sorting methods
-
-static inline bool totalTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
-{
-    return a->totalTime() > b->totalTime();
-}
-
-void ProfileNode::sortTotalTimeDescending()
-{
-    std::sort(m_children.begin(), m_children.end(), totalTimeDescendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortTotalTimeDescending();
-    
-    resetChildrensSiblings();
-}
-
-static inline bool totalTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
-{
-    return a->totalTime() < b->totalTime();
-}
-
-void ProfileNode::sortTotalTimeAscending()
-{
-    std::sort(m_children.begin(), m_children.end(), totalTimeAscendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortTotalTimeAscending();
-
-    resetChildrensSiblings();
-}
-
-static inline bool selfTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
-{
-    return a->selfTime() > b->selfTime();
-}
-
-void ProfileNode::sortSelfTimeDescending()
-{
-    std::sort(m_children.begin(), m_children.end(), selfTimeDescendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortSelfTimeDescending();
-
-    resetChildrensSiblings();
-}
-
-static inline bool selfTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
-{
-    return a->selfTime() < b->selfTime();
-}
-
-void ProfileNode::sortSelfTimeAscending()
-{
-    std::sort(m_children.begin(), m_children.end(), selfTimeAscendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortSelfTimeAscending();
-
-    resetChildrensSiblings();
-}
-
-static inline bool callsDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
+ProfileNode* ProfileNode::traverseNextNode() const
 {
-    return a->numberOfCalls() > b->numberOfCalls();
+    ProfileNode* next = m_nextSibling;
+    if (!next)
+        return m_parent;
+    while (ProfileNode* firstChild = next->firstChild())
+        next = firstChild;
+    return next;
 }
 
-void ProfileNode::sortCallsDescending()
+void ProfileNode::sort(bool comparator(const RefPtr<ProfileNode>& , const RefPtr<ProfileNode>& ))
 {
-    std::sort(m_children.begin(), m_children.end(), callsDescendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortCallsDescending();
-
-    resetChildrensSiblings();
-}
-
-static inline bool callsAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
-{
-    return a->numberOfCalls() < b->numberOfCalls();
-}
-
-void ProfileNode::sortCallsAscending()
-{
-    std::sort(m_children.begin(), m_children.end(), callsAscendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortCallsAscending();
-
-    resetChildrensSiblings();
-}
-
-static inline bool functionNameDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
-{
-    return a->functionName() > b->functionName();
-}
-
-void ProfileNode::sortFunctionNameDescending()
-{
-    std::sort(m_children.begin(), m_children.end(), functionNameDescendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortFunctionNameDescending();
-
-    resetChildrensSiblings();
-}
-
-static inline bool functionNameAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b)
-{
-    return a->functionName() < b->functionName();
-}
-
-void ProfileNode::sortFunctionNameAscending()
-{
-    std::sort(m_children.begin(), m_children.end(), functionNameAscendingComparator);
-
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->sortFunctionNameAscending();
-
+    std::sort(childrenBegin(), childrenEnd(), comparator);    
     resetChildrensSiblings();
 }
 
index bc4ea02756a31cc3f503c743931cce39866461fa..293a7482912f123ba915f71640fa1e12c43d4362 100644 (file)
@@ -80,11 +80,12 @@ namespace KJS {
         void setTotalTime(double time) { m_actualTotalTime = time; m_visibleTotalTime = time; }
         double selfTime() const { return m_visibleSelfTime; }
         void setSelfTime(double time) { m_actualSelfTime = time; m_visibleSelfTime = time; }
-        double totalPercent() const { return (m_visibleTotalTime / m_head->totalTime()) * 100.0; }
-        double selfPercent() const { return (m_visibleSelfTime / m_head->totalTime()) * 100.0; }
+        double totalPercent() const { return (m_visibleTotalTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
+        double selfPercent() const { return (m_visibleSelfTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
         unsigned numberOfCalls() const { return m_numberOfCalls; }
         void setNumberOfCalls(unsigned number) { m_numberOfCalls = number; }
         const Vector<RefPtr<ProfileNode> >& children() const { return m_children; }
+        ProfileNode* firstChild() const { return m_children.size() ? m_children[0].get() : 0; }
         void addChild(PassRefPtr<ProfileNode> prpChild);
         void insertNode(PassRefPtr<ProfileNode> prpNode);
         bool visible() const { return m_visible; }
@@ -92,15 +93,16 @@ namespace KJS {
 
         void setTreeVisible(bool visible);
 
-        // Sorting functions
-        void sortTotalTimeDescending();
-        void sortTotalTimeAscending();
-        void sortSelfTimeDescending();
-        void sortSelfTimeAscending();
-        void sortCallsDescending();
-        void sortCallsAscending();
-        void sortFunctionNameDescending();
-        void sortFunctionNameAscending();
+        ProfileNode* traverseNextNode() const;
+        void sort(bool (*)(const RefPtr<ProfileNode>&, const RefPtr<ProfileNode>&));
+        static void sortTotalTimeDescending(ProfileNode* n) { n->sort(totalTimeDescendingComparator); }
+        static void sortTotalTimeAscending(ProfileNode* n) { n->sort(totalTimeAscendingComparator); }
+        static void sortSelfTimeDescending(ProfileNode* n) { n->sort(selfTimeDescendingComparator); }
+        static void sortSelfTimeAscending(ProfileNode* n) { n->sort(selfTimeAscendingComparator); }
+        static void sortCallsDescending(ProfileNode* n) { n->sort(callsDescendingComparator); }
+        static void sortCallsAscending(ProfileNode* n) { n->sort(callsAscendingComparator); }
+        static void sortFunctionNameDescending(ProfileNode* n) { n->sort(functionNameDescendingComparator); }
+        static void sortFunctionNameAscending(ProfileNode* n) { n->sort(functionNameAscendingComparator); }
 
         void focus(const CallIdentifier&, bool forceVisible = false);
         double exclude(const CallIdentifier&);
@@ -117,6 +119,18 @@ namespace KJS {
         ProfileNode(const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
         void startTimer();
         void resetChildrensSiblings();
+        RefPtr<ProfileNode>* childrenBegin() { return m_children.begin(); }
+        RefPtr<ProfileNode>* childrenEnd() { return m_children.end(); }
+
+        // Sorting comparators
+        static inline bool totalTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->totalTime() > b->totalTime(); }
+        static inline bool totalTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->totalTime() < b->totalTime(); }
+        static inline bool selfTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->selfTime() > b->selfTime(); }
+        static inline bool selfTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->selfTime() < b->selfTime(); }
+        static inline bool callsDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->numberOfCalls() > b->numberOfCalls(); }
+        static inline bool callsAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->numberOfCalls() < b->numberOfCalls(); }
+        static inline bool functionNameDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() > b->functionName(); }
+        static inline bool functionNameAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() < b->functionName(); }
 
         CallIdentifier m_callIdentifier;
         ProfileNode* m_head;