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