2008-06-13 Maciej Stachowiak <mjs@apple.com>
[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"); 
197     
198     printf("Total instructions executed: %lld\n\n", totalInstructions);
199
200     printf("All opcodes by frequency:\n\n");
201
202     for (int i = 0; i < numOpcodeIDs; ++i) {
203         int index = sortedIndices[i];
204         printf("%s: %lld - %.2f%%\n", opcodeNames[index], opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);    
205     }
206     
207     printf("\n");
208     printf("2-opcode sequences by frequency: %lld\n\n", totalInstructions);
209     
210     for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) {
211         pair<int, int> indexPair = sortedPairIndices[i];
212         long long count = opcodePairCounts[indexPair.first][indexPair.second];
213         
214         if (!count)
215             break;
216         
217         printf("%s %s: %lld %.2f%%\n", opcodeNames[indexPair.first], opcodeNames[indexPair.second], count, ((double) count) / ((double) totalInstructionPairs) * 100.0);
218     }
219     
220     printf("\n");
221     printf("Most common opcodes and sequences:\n");
222
223     for (int i = 0; i < numOpcodeIDs; ++i) {
224         int index = sortedIndices[i];
225         long long opcodeCount = opcodeCounts[index];
226         double opcodeProportion = ((double) opcodeCount) / ((double) totalInstructions);
227         if (opcodeProportion < 0.0001)
228             break;
229         printf("\n%s: %lld - %.2f%%\n", opcodeNames[index], opcodeCount, opcodeProportion * 100.0);
230
231         for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) {
232             pair<int, int> indexPair = sortedPairIndices[j];
233             long long pairCount = opcodePairCounts[indexPair.first][indexPair.second];
234             double pairProportion = ((double) pairCount) / ((double) totalInstructionPairs);
235         
236             if (!pairCount || pairProportion < 0.0001 || pairProportion < opcodeProportion / 100)
237                 break;
238
239             if (indexPair.first != index && indexPair.second != index)
240                 continue;
241
242             printf("    %s %s: %lld - %.2f%%\n", opcodeNames[indexPair.first], opcodeNames[indexPair.second], pairCount, pairProportion * 100.0);
243         }
244         
245     }
246     printf("\n");
247 }
248
249 void OpcodeStats::recordInstruction(int opcode)
250 {
251     opcodeCounts[opcode]++;
252     
253     if (lastOpcode != -1)
254         opcodePairCounts[lastOpcode][opcode]++;
255     
256     lastOpcode = opcode;
257 }
258
259 void OpcodeStats::resetLastInstruction()
260 {
261     lastOpcode = -1;
262 }
263
264 #endif
265
266 } // namespace WTF