1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich (at) 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 #if ENABLE(OPCODE_STATS) 34 #include <stdio.h> 35 #include <wtf/FixedArray.h> 36 #endif 37 38 using namespace std; 39 40 namespace JSC { 41 42 #if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS) 43 44 const char* const opcodeNames[] = { 45 #define OPCODE_NAME_ENTRY(opcode, size) #opcode, 46 FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY) 47 #undef OPCODE_NAME_ENTRY 48 }; 49 50 #endif 51 52 #if ENABLE(OPCODE_STATS) 53 54 long long OpcodeStats::opcodeCounts[numOpcodeIDs]; 55 long long OpcodeStats::opcodePairCounts[numOpcodeIDs][numOpcodeIDs]; 56 int OpcodeStats::lastOpcode = -1; 57 58 static OpcodeStats logger; 59 60 OpcodeStats::OpcodeStats() 61 { 62 for (int i = 0; i < numOpcodeIDs; ++i) 63 opcodeCounts[i] = 0; 64 65 for (int i = 0; i < numOpcodeIDs; ++i) 66 for (int j = 0; j < numOpcodeIDs; ++j) 67 opcodePairCounts[i][j] = 0; 68 } 69 70 static int compareOpcodeIndices(const void* left, const void* right) 71 { 72 long long leftValue = OpcodeStats::opcodeCounts[*(int*) left]; 73 long long rightValue = OpcodeStats::opcodeCounts[*(int*) right]; 74 75 if (leftValue < rightValue) 76 return 1; 77 else if (leftValue > rightValue) 78 return -1; 79 else 80 return 0; 81 } 82 83 static int compareOpcodePairIndices(const void* left, const void* right) 84 { 85 pair<int, int> leftPair = *(pair<int, int>*) left; 86 long long leftValue = OpcodeStats::opcodePairCounts[leftPair.first][leftPair.second]; 87 pair<int, int> rightPair = *(pair<int, int>*) right; 88 long long rightValue = OpcodeStats::opcodePairCounts[rightPair.first][rightPair.second]; 89 90 if (leftValue < rightValue) 91 return 1; 92 else if (leftValue > rightValue) 93 return -1; 94 else 95 return 0; 96 } 97 98 OpcodeStats::~OpcodeStats() 99 { 100 long long totalInstructions = 0; 101 for (int i = 0; i < numOpcodeIDs; ++i) 102 totalInstructions += opcodeCounts[i]; 103 104 long long totalInstructionPairs = 0; 105 for (int i = 0; i < numOpcodeIDs; ++i) 106 for (int j = 0; j < numOpcodeIDs; ++j) 107 totalInstructionPairs += opcodePairCounts[i][j]; 108 109 FixedArray<int, numOpcodeIDs> sortedIndices; 110 for (int i = 0; i < numOpcodeIDs; ++i) 111 sortedIndices[i] = i; 112 qsort(sortedIndices.data(), numOpcodeIDs, sizeof(int), compareOpcodeIndices); 113 114 pair<int, int> sortedPairIndices[numOpcodeIDs * numOpcodeIDs]; 115 pair<int, int>* currentPairIndex = sortedPairIndices; 116 for (int i = 0; i < numOpcodeIDs; ++i) 117 for (int j = 0; j < numOpcodeIDs; ++j) 118 *(currentPairIndex++) = make_pair(i, j); 119 qsort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices); 120 121 printf("\nExecuted opcode statistics\n"); 122 123 printf("Total instructions executed: %lld\n\n", totalInstructions); 124 125 printf("All opcodes by frequency:\n\n"); 126 127 for (int i = 0; i < numOpcodeIDs; ++i) { 128 int index = sortedIndices[i]; 129 printf("%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0); 130 } 131 132 printf("\n"); 133 printf("2-opcode sequences by frequency: %lld\n\n", totalInstructions); 134 135 for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) { 136 pair<int, int> indexPair = sortedPairIndices[i]; 137 long long count = opcodePairCounts[indexPair.first][indexPair.second]; 138 139 if (!count) 140 break; 141 142 printf("%s%s %s:%s %lld %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), count, ((double) count) / ((double) totalInstructionPairs) * 100.0); 143 } 144 145 printf("\n"); 146 printf("Most common opcodes and sequences:\n"); 147 148 for (int i = 0; i < numOpcodeIDs; ++i) { 149 int index = sortedIndices[i]; 150 long long opcodeCount = opcodeCounts[index]; 151 double opcodeProportion = ((double) opcodeCount) / ((double) totalInstructions); 152 if (opcodeProportion < 0.0001) 153 break; 154 printf("\n%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCount, opcodeProportion * 100.0); 155 156 for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) { 157 pair<int, int> indexPair = sortedPairIndices[j]; 158 long long pairCount = opcodePairCounts[indexPair.first][indexPair.second]; 159 double pairProportion = ((double) pairCount) / ((double) totalInstructionPairs); 160 161 if (!pairCount || pairProportion < 0.0001 || pairProportion < opcodeProportion / 100) 162 break; 163 164 if (indexPair.first != index && indexPair.second != index) 165 continue; 166 167 printf(" %s%s %s:%s %lld - %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), pairCount, pairProportion * 100.0); 168 } 169 170 } 171 printf("\n"); 172 } 173 174 void OpcodeStats::recordInstruction(int opcode) 175 { 176 opcodeCounts[opcode]++; 177 178 if (lastOpcode != -1) 179 opcodePairCounts[lastOpcode][opcode]++; 180 181 lastOpcode = opcode; 182 } 183 184 void OpcodeStats::resetLastInstruction() 185 { 186 lastOpcode = -1; 187 } 188 189 #endif 190 191 } // namespace JSC 192