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