WebKit/gtk:
[WebKit.git] / JavaScriptCore / VM / Opcode.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "Opcode.h"
32
33 #include <stdlib.h>
34
35 using namespace std;
36
37 namespace KJS {
38
39 #if DUMP_OPCODE_STATS
40
41 long long OpcodeStats::opcodeCounts[numOpcodeIDs];
42 long long OpcodeStats::opcodePairCounts[numOpcodeIDs][numOpcodeIDs];
43 int OpcodeStats::lastOpcode = -1;
44
45 static OpcodeStats logger;
46
47 static const char* opcodeNames[] = {
48     "load",
49     "new_object",
50     "new_array",
51     "new_regexp",
52     "mov",
53     
54     "not",
55     "eq",
56     "neq",
57     "stricteq",
58     "nstricteq",
59     "less",
60     "lesseq",
61     
62     "pre_inc",
63     "pre_dec",
64     "post_inc",
65     "post_dec",
66     "to_jsnumber",
67     "negate",
68     "add",
69     "mul",
70     "div",
71     "mod",
72     "sub",
73     
74     "lshift",
75     "rshift",
76     "urshift",
77     "bitand",
78     "bitxor",
79     "bitor",
80     "bitnot",
81     
82     "instanceof",
83     "typeof",
84     "in",
85
86     "resolve",
87     "resolve_skip",
88     "get_scoped_var",
89     "put_scoped_var",
90     "resolve_base",
91     "resolve_with_base",
92     "resolve_func",
93     "get_by_id",
94     "put_by_id",
95     "del_by_id",
96     "get_by_val",
97     "put_by_val",
98     "del_by_val",
99     "put_by_index",
100     "put_getter",
101     "put_setter",
102
103     "jmp",
104     "jtrue",
105     "jfalse",
106     "jless",
107     "jmp_scopes",
108
109     "new_func",
110     "new_func_exp",
111     "call",
112     "call_eval",
113     "ret",
114
115     "construct",
116
117     "get_pnames",
118     "next_pname",
119
120     "push_scope",
121     "pop_scope",
122
123     "catch",
124     "throw",
125     "new_error",
126
127     "jsr",
128     "sret",
129
130     "debug",
131
132     "end"    
133 };
134
135 OpcodeStats::OpcodeStats()
136 {
137     for (int i = 0; i < numOpcodeIDs; ++i)
138         opcodeCounts[i] = 0;
139     
140     for (int i = 0; i < numOpcodeIDs; ++i)
141         for (int j = 0; j < numOpcodeIDs; ++j)
142             opcodePairCounts[i][j] = 0;
143 }
144
145 static int compareOpcodeIndices(const void* left, const void* right)
146 {
147     long long leftValue = OpcodeStats::opcodeCounts[*(int*) left];
148     long long rightValue = OpcodeStats::opcodeCounts[*(int*) right];
149     
150     if (leftValue < rightValue)
151         return 1;
152     else if (leftValue > rightValue)
153         return -1;
154     else
155         return 0;
156 }
157
158 static int compareOpcodePairIndices(const void* left, const void* right)
159 {
160     pair<int, int> leftPair = *(pair<int, int>*) left;
161     long long leftValue = OpcodeStats::opcodePairCounts[leftPair.first][leftPair.second];
162     pair<int, int> rightPair = *(pair<int, int>*) right;
163     long long rightValue = OpcodeStats::opcodePairCounts[rightPair.first][rightPair.second];
164     
165     if (leftValue < rightValue)
166         return 1;
167     else if (leftValue > rightValue)
168         return -1;
169     else
170         return 0;
171 }
172
173 OpcodeStats::~OpcodeStats()
174 {
175     long long totalInstructions = 0;
176     for (int i = 0; i < numOpcodeIDs; ++i)
177         totalInstructions += opcodeCounts[i];
178     
179     long long totalInstructionPairs = 0;
180     for (int i = 0; i < numOpcodeIDs; ++i)
181         for (int j = 0; j < numOpcodeIDs; ++j)
182             totalInstructionPairs += opcodePairCounts[i][j];
183
184     int sortedIndices[numOpcodeIDs];    
185     for (int i = 0; i < numOpcodeIDs; ++i)
186         sortedIndices[i] = i;
187     mergesort(sortedIndices, numOpcodeIDs, sizeof(int), compareOpcodeIndices);
188     
189     pair<int, int> sortedPairIndices[numOpcodeIDs * numOpcodeIDs];
190     pair<int, int>* currentPairIndex = sortedPairIndices;
191     for (int i = 0; i < numOpcodeIDs; ++i)
192         for (int j = 0; j < numOpcodeIDs; ++j)
193             *(currentPairIndex++) = make_pair(i, j);
194     mergesort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices);
195     
196     printf("\nExecuted opcode statistics:\n\n"); 
197     
198     printf("Total instructions executed: %lld\n\n", totalInstructions);
199     
200     for (int i = 0; i < numOpcodeIDs; ++i) {
201         int index = sortedIndices[i];
202         printf("%s: %.2f%%\n", opcodeNames[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);    
203     }
204     
205     printf("\n");
206     
207     for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) {
208         pair<int, int> indexPair = sortedPairIndices[i];
209         long long count = opcodePairCounts[indexPair.first][indexPair.second];
210         
211         if (!count)
212             break;
213         
214         printf("(%s, %s): %.2f%%\n", opcodeNames[indexPair.first], opcodeNames[indexPair.second], ((double) count) / ((double) totalInstructionPairs) * 100.0);
215     }
216     
217     printf("\n");
218 }
219
220 void OpcodeStats::recordInstruction(int opcode)
221 {
222     opcodeCounts[opcode]++;
223     
224     if (lastOpcode != -1)
225         opcodePairCounts[lastOpcode][opcode]++;
226     
227     lastOpcode = opcode;
228 }
229
230 void OpcodeStats::resetLastInstruction()
231 {
232     lastOpcode = -1;
233 }
234
235 #endif
236
237 } // namespace WTF