2008-09-02 Csaba Osztrogonac <oszi@inf.u-szeged.hu>
[WebKit-https.git] / JavaScriptCore / VM / Opcode.cpp
index 0eb3f55..fcb6aa8 100644 (file)
 #include "config.h"
 #include "Opcode.h"
 
-#include <stdlib.h>
-
 using namespace std;
 
 namespace KJS {
 
+#if ENABLE(SAMPLING_TOOL) || DUMP_OPCODE_STATS
+
+const char* const opcodeNames[] = {
+#define OPCODE_NAME_ENTRY(opcode) #opcode,
+    FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY)
+#undef OPCODE_NAME_ENTRY
+};
+
+#endif
+
 #if DUMP_OPCODE_STATS
 
 long long OpcodeStats::opcodeCounts[numOpcodeIDs];
@@ -44,94 +52,6 @@ int OpcodeStats::lastOpcode = -1;
 
 static OpcodeStats logger;
 
-static const char* opcodeNames[] = {
-    "load",
-    "new_object",
-    "new_array",
-    "new_regexp",
-    "mov",
-    
-    "not",
-    "eq",
-    "neq",
-    "stricteq",
-    "nstricteq",
-    "less",
-    "lesseq",
-    
-    "pre_inc",
-    "pre_dec",
-    "post_inc",
-    "post_dec",
-    "to_jsnumber",
-    "negate",
-    "add",
-    "mul",
-    "div",
-    "mod",
-    "sub",
-    
-    "lshift",
-    "rshift",
-    "urshift",
-    "bitand",
-    "bitxor",
-    "bitor",
-    "bitnot",
-    
-    "instanceof",
-    "typeof",
-    "in",
-
-    "resolve",
-    "resolve_skip",
-    "get_scoped_var",
-    "put_scoped_var",
-    "resolve_base",
-    "resolve_with_base",
-    "resolve_func",
-    "get_by_id",
-    "put_by_id",
-    "del_by_id",
-    "get_by_val",
-    "put_by_val",
-    "del_by_val",
-    "put_by_index",
-    "put_getter",
-    "put_setter",
-
-    "jmp",
-    "jtrue",
-    "jfalse",
-    "jless",
-    "jmp_scopes",
-
-    "new_func",
-    "new_func_exp",
-    "call",
-    "call_eval",
-    "ret",
-
-    "construct",
-
-    "get_pnames",
-    "next_pname",
-
-    "push_scope",
-    "pop_scope",
-
-    "catch",
-    "throw",
-    "new_error",
-
-    "jsr",
-    "sret",
-
-    "debug",
-
-    "end"    
-};
-
 OpcodeStats::OpcodeStats()
 {
     for (int i = 0; i < numOpcodeIDs; ++i)
@@ -184,25 +104,28 @@ OpcodeStats::~OpcodeStats()
     int sortedIndices[numOpcodeIDs];    
     for (int i = 0; i < numOpcodeIDs; ++i)
         sortedIndices[i] = i;
-    mergesort(sortedIndices, numOpcodeIDs, sizeof(int), compareOpcodeIndices);
+    qsort(sortedIndices, numOpcodeIDs, sizeof(int), compareOpcodeIndices);
     
     pair<int, int> sortedPairIndices[numOpcodeIDs * numOpcodeIDs];
     pair<int, int>* currentPairIndex = sortedPairIndices;
     for (int i = 0; i < numOpcodeIDs; ++i)
         for (int j = 0; j < numOpcodeIDs; ++j)
             *(currentPairIndex++) = make_pair(i, j);
-    mergesort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices);
+    qsort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices);
     
-    printf("\nExecuted opcode statistics:\n\n"); 
+    printf("\nExecuted opcode statistics\n"); 
     
     printf("Total instructions executed: %lld\n\n", totalInstructions);
-    
+
+    printf("All opcodes by frequency:\n\n");
+
     for (int i = 0; i < numOpcodeIDs; ++i) {
         int index = sortedIndices[i];
-        printf("%s: %.2f%%\n", opcodeNames[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);    
+        printf("%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 24), opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);    
     }
     
     printf("\n");
+    printf("2-opcode sequences by frequency: %lld\n\n", totalInstructions);
     
     for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) {
         pair<int, int> indexPair = sortedPairIndices[i];
@@ -211,10 +134,36 @@ OpcodeStats::~OpcodeStats()
         if (!count)
             break;
         
-        printf("(%s, %s): %.2f%%\n", opcodeNames[indexPair.first], opcodeNames[indexPair.second], ((double) count) / ((double) totalInstructionPairs) * 100.0);
+        printf("%s%s %s:%s %lld %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 24), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 24), count, ((double) count) / ((double) totalInstructionPairs) * 100.0);
     }
     
     printf("\n");
+    printf("Most common opcodes and sequences:\n");
+
+    for (int i = 0; i < numOpcodeIDs; ++i) {
+        int index = sortedIndices[i];
+        long long opcodeCount = opcodeCounts[index];
+        double opcodeProportion = ((double) opcodeCount) / ((double) totalInstructions);
+        if (opcodeProportion < 0.0001)
+            break;
+        printf("\n%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 24), opcodeCount, opcodeProportion * 100.0);
+
+        for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) {
+            pair<int, int> indexPair = sortedPairIndices[j];
+            long long pairCount = opcodePairCounts[indexPair.first][indexPair.second];
+            double pairProportion = ((double) pairCount) / ((double) totalInstructionPairs);
+        
+            if (!pairCount || pairProportion < 0.0001 || pairProportion < opcodeProportion / 100)
+                break;
+
+            if (indexPair.first != index && indexPair.second != index)
+                continue;
+
+            printf("    %s%s %s:%s %lld - %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 24), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 24), pairCount, pairProportion * 100.0);
+        }
+        
+    }
+    printf("\n");
 }
 
 void OpcodeStats::recordInstruction(int opcode)
@@ -234,4 +183,4 @@ void OpcodeStats::resetLastInstruction()
 
 #endif
 
-} // namespace WTF
+} // namespace KJS