Show
Ignore:
Timestamp:
08/01/08 14:47:24 (5 months ago)
Author:
sroret
Message:

merge with webkit revision 35510

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/JavaScriptCore/VM/Opcode.cpp

    r418 r427  
    3131#include "Opcode.h" 
    3232 
    33 #include <stdlib.h> 
    34 #include "CodeBlock.h" 
    35 #include "Machine.h" 
    36  
    3733using namespace std; 
    3834 
    3935namespace KJS { 
    4036 
    41 #if SAMPLING_TOOL_ENABLED || DUMP_OPCODE_STATS 
     37#if ENABLE(SAMPLING_TOOL) || DUMP_OPCODE_STATS 
    4238 
    43 static const char* opcodeNames[] = { 
    44     "load             ", 
    45     "new_object       ", 
    46     "new_array        ", 
    47     "new_regexp       ", 
    48     "mov              ", 
    49      
    50     "not              ", 
    51     "eq               ", 
    52     "neq              ", 
    53     "stricteq         ", 
    54     "nstricteq        ", 
    55     "less             ", 
    56     "lesseq           ", 
    57      
    58     "pre_inc          ", 
    59     "pre_dec          ", 
    60     "post_inc         ", 
    61     "post_dec         ", 
    62     "to_jsnumber      ", 
    63     "negate           ", 
    64     "add              ", 
    65     "mul              ", 
    66     "div              ", 
    67     "mod              ", 
    68     "sub              ", 
    69      
    70     "lshift           ", 
    71     "rshift           ", 
    72     "urshift          ", 
    73     "bitand           ", 
    74     "bitxor           ", 
    75     "bitor            ", 
    76     "bitnot           ", 
    77      
    78     "instanceof       ", 
    79     "typeof           ", 
    80     "in               ", 
    81  
    82     "resolve          ", 
    83     "resolve_skip     ", 
    84     "get_scoped_var   ", 
    85     "put_scoped_var   ", 
    86     "resolve_base     ", 
    87     "resolve_with_base", 
    88     "resolve_func     ", 
    89     "get_by_id        ", 
    90     "put_by_id        ", 
    91     "del_by_id        ", 
    92     "get_by_val       ", 
    93     "put_by_val       ", 
    94     "del_by_val       ", 
    95     "put_by_index     ", 
    96     "put_getter       ", 
    97     "put_setter       ", 
    98  
    99     "jmp              ", 
    100     "jtrue            ", 
    101     "jfalse           ", 
    102     "jless            ", 
    103     "jnless           ", 
    104     "jmp_scopes       ", 
    105     "loop             ", 
    106     "loop_if_true     ", 
    107     "loop_if_less     ", 
    108     "switch_imm       ", 
    109     "switch_char      ", 
    110     "switch_string    ", 
    111  
    112     "new_func         ", 
    113     "new_func_exp     ", 
    114     "call             ", 
    115     "call_eval        ", 
    116     "ret              ", 
    117  
    118     "construct        ", 
    119  
    120     "get_pnames       ", 
    121     "next_pname       ", 
    122  
    123     "push_scope       ", 
    124     "pop_scope        ", 
    125  
    126     "catch            ", 
    127     "throw            ", 
    128     "new_error        ", 
    129  
    130     "jsr              ", 
    131     "sret             ", 
    132  
    133     "debug            ", 
    134  
    135     "end              " 
     39const char* const opcodeNames[] = { 
     40#define OPCODE_NAME_ENTRY(opcode) #opcode, 
     41    FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY) 
     42#undef OPCODE_NAME_ENTRY 
    13643}; 
    13744 
    13845#endif 
    139  
    140 #if SAMPLING_TOOL_ENABLED 
    141  
    142 void ScopeSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC) 
    143 { 
    144     m_totalCount++; 
    145  
    146     if (!m_vpcCounts) { 
    147         m_size = codeBlock->instructions.size(); 
    148         m_vpcCounts = static_cast<int*>(calloc(m_size, sizeof(int))); 
    149         m_codeBlock = codeBlock; 
    150     } 
    151  
    152     unsigned codeOffset = static_cast<unsigned>(reinterpret_cast<ptrdiff_t>(vPC) - reinterpret_cast<ptrdiff_t>(codeBlock->instructions.begin())) / sizeof(Instruction*); 
    153     // This could occur if codeBlock & vPC are not consistent - e.g. sample mid op_call/op_ret. 
    154     if (codeOffset < m_size) 
    155         m_vpcCounts[codeOffset]++; 
    156 } 
    157  
    158 static inline unsigned hertz2us(unsigned hertz) 
    159 { 
    160     return 1000000 / hertz; 
    161 } 
    162  
    163 void SamplingTool::run() 
    164 { 
    165     while (m_running) { 
    166         usleep(hertz2us(m_hertz)); 
    167  
    168         m_totalSamples++; 
    169  
    170         CodeBlock* codeBlock = m_recordedCodeBlock; 
    171         Instruction* vPC = m_recordedVPC; 
    172  
    173         if (codeBlock && vPC) { 
    174             ScopeSampleRecord* record = m_scopeSampleMap->get(codeBlock->ownerNode); 
    175             if (record) 
    176                 record->sample(codeBlock, vPC); 
    177         } 
    178     } 
    179 } 
    180  
    181 void* SamplingTool::threadStartFunc(void* samplingTool) 
    182 { 
    183     reinterpret_cast<SamplingTool*>(samplingTool)->run(); 
    184     return 0; 
    185 } 
    186  
    187 void SamplingTool::notifyOfScope(ScopeNode* scope) 
    188 { 
    189     m_scopeSampleMap->set(scope, new ScopeSampleRecord(scope)); 
    190 } 
    191  
    192 void SamplingTool::start(unsigned hertz) 
    193 { 
    194     ASSERT(!m_running); 
    195     m_running = true; 
    196     m_hertz = hertz; 
    197     pthread_create(&m_samplingThread, 0, threadStartFunc, this); 
    198 } 
    199  
    200 void SamplingTool::stop() 
    201 { 
    202     ASSERT(m_running); 
    203     m_running = false; 
    204     pthread_join(m_samplingThread, 0); 
    205 } 
    206  
    207 struct OpcodeSampleInfo 
    208 { 
    209     OpcodeID opcode; 
    210     long long count; 
    211 }; 
    212  
    213 struct LineCountInfo 
    214 { 
    215     unsigned line; 
    216     unsigned count; 
    217 }; 
    218  
    219 static int compareLineCountInfoSampling(const void* left, const void* right) 
    220 { 
    221     const LineCountInfo *leftLineCount = reinterpret_cast<const LineCountInfo *>(left); 
    222     const LineCountInfo *rightLineCount = reinterpret_cast<const LineCountInfo *>(right); 
    223  
    224     return (leftLineCount->line > rightLineCount->line) ? 1 : (leftLineCount->line < rightLineCount->line) ? -1 : 0; 
    225 } 
    226  
    227 static int compareOpcodeIndicesSampling(const void* left, const void* right) 
    228 { 
    229     const OpcodeSampleInfo *leftSampleInfo = reinterpret_cast<const OpcodeSampleInfo *>(left); 
    230     const OpcodeSampleInfo *rightSampleInfo = reinterpret_cast<const OpcodeSampleInfo *>(right); 
    231  
    232     return (leftSampleInfo->count < rightSampleInfo->count) ? 1 : (leftSampleInfo->count > rightSampleInfo->count) ? -1 : 0; 
    233 } 
    234  
    235 static int compareScopeSampleRecords(const void* left, const void* right) 
    236 { 
    237     const ScopeSampleRecord* const leftValue = *static_cast<const ScopeSampleRecord* const *>(left); 
    238     const ScopeSampleRecord* const rightValue = *static_cast<const ScopeSampleRecord* const *>(right); 
    239  
    240     return (leftValue->m_totalCount < rightValue->m_totalCount) ? 1 : (leftValue->m_totalCount > rightValue->m_totalCount) ? -1 : 0; 
    241 } 
    242  
    243 void SamplingTool::dump(ExecState* exec) 
    244 { 
    245     // Tidies up SunSpider output by removing short scripts - such a small number of samples would likely not be useful anyhow. 
    246     if (m_totalSamples < 10) 
    247         return; 
    248      
    249     // (1) Calculate 'totalCodeBlockSamples', build and sort 'codeBlockSamples' array. 
    250  
    251     int scopeCount = m_scopeSampleMap->size(); 
    252     long long totalCodeBlockSamples = 0; 
    253     ScopeSampleRecord* codeBlockSamples[scopeCount]; 
    254     ScopeSampleRecordMap::iterator iter = m_scopeSampleMap->begin(); 
    255     for (int i=0; i < scopeCount; ++i, ++iter) { 
    256         codeBlockSamples[i] = iter->second; 
    257         totalCodeBlockSamples += codeBlockSamples[i]->m_totalCount; 
    258     } 
    259     mergesort(codeBlockSamples, scopeCount, sizeof(ScopeSampleRecord*), compareScopeSampleRecords); 
    260  
    261     // (2) Print data from 'codeBlockSamples' array, calculate 'totalOpcodeSamples', populate 'opcodeSampleCounts' array. 
    262  
    263     long long totalOpcodeSamples = 0; 
    264     long long opcodeSampleCounts[numOpcodeIDs] = { 0 }; 
    265  
    266     fprintf(stdout, "\nBlock sampling results\n\n");  
    267     fprintf(stdout, "Total blocks sampled (total samples): %lld (%lld)\n\n", totalCodeBlockSamples, m_totalSamples); 
    268  
    269     for (int i=0; i < scopeCount; i++) { 
    270         ScopeSampleRecord *record = codeBlockSamples[i]; 
    271         CodeBlock* codeBlock = record->m_codeBlock; 
    272  
    273         double totalPercent = (record->m_totalCount * 100.0)/m_totalSamples; 
    274         double blockPercent = (record->m_totalCount * 100.0)/totalCodeBlockSamples; 
    275  
    276         if ((blockPercent >= 1) && codeBlock) { 
    277             Instruction* code = codeBlock->instructions.begin(); 
    278             fprintf(stdout, "#%d: %s:%d: sampled %d times - %.3f%% (%.3f%%)\n", i+1, record->m_scope->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForVPC(code), record->m_totalCount, blockPercent, totalPercent); 
    279             if (i < 10) { 
    280                 HashMap<unsigned,unsigned> lineCounts; 
    281                 codeBlock->dump(exec); 
    282                 for (unsigned op = 0; op < record->m_size; ++op) { 
    283                     int count = record->m_vpcCounts[op]; 
    284                     if (count) { 
    285                         printf("    [% 4d] has sample count: % 4d\n", op, count); 
    286                         unsigned line = codeBlock->lineNumberForVPC(code+op); 
    287                         lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count); 
    288                     } 
    289                 } 
    290                 printf("\n"); 
    291                 int linesCount = lineCounts.size(); 
    292                 LineCountInfo lineCountInfo[linesCount]; 
    293                 int lineno = 0; 
    294                 for (HashMap<unsigned,unsigned>::iterator iter = lineCounts.begin(); iter != lineCounts.end(); ++iter, ++lineno) { 
    295                     lineCountInfo[lineno].line = iter->first; 
    296                     lineCountInfo[lineno].count = iter->second; 
    297                 } 
    298                 mergesort(lineCountInfo, linesCount, sizeof(LineCountInfo), compareLineCountInfoSampling); 
    299                 for (lineno = 0; lineno < linesCount; ++lineno) { 
    300                     printf("    Line #%d has sample count %d.\n", lineCountInfo[lineno].line, lineCountInfo[lineno].count); 
    301                 } 
    302                 printf("\n"); 
    303             } 
    304         } 
    305          
    306         if (record->m_vpcCounts && codeBlock) { 
    307             Instruction* instructions = codeBlock->instructions.begin(); 
    308             for (unsigned op = 0; op < record->m_size; ++op) { 
    309                 Opcode opcode = instructions[op].u.opcode; 
    310                 if (exec->machine()->isOpcode(opcode)) { 
    311                     totalOpcodeSamples += record->m_vpcCounts[op]; 
    312                     opcodeSampleCounts[exec->machine()->getOpcodeID(opcode)] += record->m_vpcCounts[op]; 
    313                 } 
    314             } 
    315         } 
    316     } 
    317     printf("\n"); 
    318  
    319     // (3) Build and sort 'opcodeSampleInfo' array. 
    320  
    321     OpcodeSampleInfo opcodeSampleInfo[numOpcodeIDs]; 
    322     for (int i = 0; i < numOpcodeIDs; ++i) { 
    323         opcodeSampleInfo[i].opcode = (OpcodeID)i; 
    324         opcodeSampleInfo[i].count = opcodeSampleCounts[i]; 
    325     } 
    326     mergesort(opcodeSampleInfo, numOpcodeIDs, sizeof(OpcodeSampleInfo), compareOpcodeIndicesSampling); 
    327  
    328     // (4) Print Opcode sampling results. 
    329      
    330     fprintf(stdout, "\nOpcode sampling results\n\n");  
    331      
    332     fprintf(stdout, "Total opcodes sampled (total samples): %lld (%lld)\n\n", totalOpcodeSamples, m_totalSamples); 
    333     fprintf(stdout, "Opcodes in order:\n\n"); 
    334     for (int i = 0; i < numOpcodeIDs; ++i) { 
    335         long long count = opcodeSampleCounts[i]; 
    336         fprintf(stdout, "%s:\t%6lld\t%.3f%%\t(%.3f%%)\n", opcodeNames[i], count, ((double)count * 100)/totalOpcodeSamples, ((double)count * 100)/m_totalSamples);     
    337     } 
    338     fprintf(stdout, "\n"); 
    339     fprintf(stdout, "Opcodes by sample count:\n\n"); 
    340     for (int i = 0; i < numOpcodeIDs; ++i) { 
    341         OpcodeID opcode = opcodeSampleInfo[i].opcode; 
    342         long long count = opcodeSampleInfo[i].count; 
    343         fprintf(stdout, "%s:\t%6lld\t%.3f%%\t(%.3f%%)\n", opcodeNames[opcode], count, ((double)count * 100)/totalOpcodeSamples, ((double)count * 100)/m_totalSamples);     
    344     } 
    345     fprintf(stdout, "\n"); 
    346 } 
    347  
    348 #endif 
    349  
    35046 
    35147#if DUMP_OPCODE_STATS 
     
    426122    for (int i = 0; i < numOpcodeIDs; ++i) { 
    427123        int index = sortedIndices[i]; 
    428         printf("%s: %lld - %.2f%%\n", opcodeNames[index], opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);     
     124        printf("%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 24), opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);     
    429125    } 
    430126     
     
    439135            break; 
    440136         
    441         printf("%s %s: %lld %.2f%%\n", opcodeNames[indexPair.first], opcodeNames[indexPair.second], count, ((double) count) / ((double) totalInstructionPairs) * 100.0); 
     137        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); 
    442138    } 
    443139     
     
    451147        if (opcodeProportion < 0.0001) 
    452148            break; 
    453         printf("\n%s: %lld - %.2f%%\n", opcodeNames[index], opcodeCount, opcodeProportion * 100.0); 
     149        printf("\n%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 24), opcodeCount, opcodeProportion * 100.0); 
    454150 
    455151        for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) { 
     
    464160                continue; 
    465161 
    466             printf("    %s %s: %lld - %.2f%%\n", opcodeNames[indexPair.first], opcodeNames[indexPair.second], pairCount, pairProportion * 100.0); 
     162            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); 
    467163        } 
    468164         
     
    488184#endif 
    489185 
    490 } // namespace WTF 
     186} // namespace KJS