2008-05-13 Kevin McCullough <kmccullough@apple.com>
[WebKit-https.git] / JavaScriptCore / profiler / Profile.cpp
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 "Profile.h"
28
29 #include "FunctionCallProfile.h"
30 #include "JSGlobalObject.h"
31 #include "ExecState.h"
32 #include "function.h"
33
34 #include <stdio.h>
35
36 namespace KJS {
37
38 typedef Vector<UString>::const_iterator NameIterator;
39
40 Profile::Profile(const UString& title)
41     : m_title(title)
42 {
43     // FIXME: When multi-threading is supported this will be a vector and calls
44     // into the profiler will need to know which thread it is executing on.
45     m_callTree = FunctionCallProfile::create("Thread_1");
46 }
47
48 void Profile::willExecute(const Vector<UString>& callStackNames)
49 {
50     RefPtr<FunctionCallProfile> callTreeInsertionPoint;
51     RefPtr<FunctionCallProfile> foundNameInTree = m_callTree;
52     NameIterator callStackLocation = callStackNames.begin();
53
54     while (callStackLocation != callStackNames.end() && foundNameInTree) {
55         callTreeInsertionPoint = foundNameInTree;
56         foundNameInTree = callTreeInsertionPoint->findChild(*callStackLocation);
57         ++callStackLocation;
58     }
59
60     if (!foundNameInTree) {   // Insert remains of the stack into the call tree.
61         --callStackLocation;
62         for (RefPtr<FunctionCallProfile> next; callStackLocation != callStackNames.end(); ++callStackLocation) {
63             next = FunctionCallProfile::create(*callStackLocation);
64             callTreeInsertionPoint->addChild(next);
65             callTreeInsertionPoint = next;
66         }
67     } else    // We are calling a function that is already in the call tree.
68         foundNameInTree->willExecute();
69 }
70
71 void Profile::didExecute(const Vector<UString>& stackNames)
72 {
73     m_callTree->didExecute(stackNames, 0);    
74 }
75
76 void Profile::printDataInspectorStyle() const
77 {
78     printf("Call graph:\n");
79     m_callTree->printDataInspectorStyle(0);
80 }
81
82 typedef pair<UString::Rep*, unsigned> NameCountPair;
83
84 static inline bool functionNameCountPairComparator(const NameCountPair& a, const NameCountPair& b)
85 {
86     return a.second > b.second;
87 }
88
89 void Profile::printDataSampleStyle() const
90 {
91     typedef Vector<NameCountPair> NameCountPairVector;
92
93     FunctionCallHashCount countedFunctions;
94     printf("Call graph:\n");
95     m_callTree->printDataSampleStyle(0, countedFunctions);
96
97     printf("\nTotal number in stack:\n");
98     NameCountPairVector sortedFunctions(countedFunctions.size());
99     copyToVector(countedFunctions, sortedFunctions);
100
101     std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator);
102     for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it)
103         printf("        %-12d%s\n", (*it).second, UString((*it).first).UTF8String().c_str());
104
105     printf("\nSort by top of stack, same collapsed (when >= 5):\n");
106 }
107
108 }   // namespace KJS