Ignore:
Timestamp:
Jun 19, 2012, 6:33:30 PM (13 years ago)
Author:
[email protected]
Message:

JSC should be able to show disassembly for all generated JIT code
https://bugs.webkit.org/show_bug.cgi?id=89536

Reviewed by Gavin Barraclough.

Now instead of doing linkBuffer.finalizeCode(), you do
FINALIZE_CODE(linkBuffer, (... explanation ...)). FINALIZE_CODE() then
prints your explanation and the disassembled code, if
Options::showDisassembly is set to true.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Target.pri:
  • assembler/LinkBuffer.cpp: Added.

(JSC):
(JSC::LinkBuffer::finalizeCodeWithoutDisassembly):
(JSC::LinkBuffer::finalizeCodeWithDisassembly):
(JSC::LinkBuffer::linkCode):
(JSC::LinkBuffer::performFinalization):
(JSC::LinkBuffer::dumpLinkStatistics):
(JSC::LinkBuffer::dumpCode):

  • assembler/LinkBuffer.h:

(LinkBuffer):
(JSC):

  • assembler/MacroAssemblerCodeRef.h:

(JSC::MacroAssemblerCodeRef::tryToDisassemble):
(MacroAssemblerCodeRef):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):

  • dfg/DFGOSRExitCompiler.cpp:
  • dfg/DFGRepatch.cpp:

(JSC::DFG::generateProtoChainAccessStub):
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDList):
(JSC::DFG::emitPutReplaceStub):
(JSC::DFG::emitPutTransitionStub):

  • dfg/DFGThunks.cpp:

(JSC::DFG::osrExitGenerationThunkGenerator):

  • disassembler/Disassembler.h:

(JSC):
(JSC::tryToDisassemble):

  • disassembler/UDis86Disassembler.cpp:

(JSC::tryToDisassemble):

  • jit/JIT.cpp:

(JSC::JIT::privateCompile):

  • jit/JITCode.h:

(JSC::JITCode::tryToDisassemble):

  • jit/JITOpcodes.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):
(JSC::JIT::privateCompileCTINativeCall):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::stringGetByValStubGenerator):
(JSC::JIT::privateCompilePutByIdTransition):
(JSC::JIT::privateCompilePatchGetArrayLength):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::stringGetByValStubGenerator):
(JSC::JIT::privateCompilePutByIdTransition):
(JSC::JIT::privateCompilePatchGetArrayLength):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):

  • jit/SpecializedThunkJIT.h:

(JSC::SpecializedThunkJIT::finalize):

  • jit/ThunkGenerators.cpp:

(JSC::charCodeAtThunkGenerator):
(JSC::charAtThunkGenerator):
(JSC::fromCharCodeThunkGenerator):
(JSC::sqrtThunkGenerator):
(JSC::floorThunkGenerator):
(JSC::ceilThunkGenerator):
(JSC::roundThunkGenerator):
(JSC::expThunkGenerator):
(JSC::logThunkGenerator):
(JSC::absThunkGenerator):
(JSC::powThunkGenerator):

  • llint/LLIntThunks.cpp:

(JSC::LLInt::generateThunkWithJumpTo):
(JSC::LLInt::functionForCallEntryThunkGenerator):
(JSC::LLInt::functionForConstructEntryThunkGenerator):
(JSC::LLInt::functionForCallArityCheckThunkGenerator):
(JSC::LLInt::functionForConstructArityCheckThunkGenerator):
(JSC::LLInt::evalEntryThunkGenerator):
(JSC::LLInt::programEntryThunkGenerator):

  • runtime/Options.cpp:

(Options):
(JSC::Options::initializeOptions):

  • runtime/Options.h:

(Options):

  • yarr/YarrJIT.cpp:

(JSC::Yarr::YarrGenerator::compile):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/assembler/LinkBuffer.h

    r118413 r120786  
    11/*
    2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    194194    }
    195195
    196     // Upon completion of all patching 'finalizeCode()' should be called once to complete generation of the code.
    197     CodeRef finalizeCode()
    198     {
    199         performFinalization();
    200 
    201         return CodeRef(m_executableMemory);
    202     }
     196    // Upon completion of all patching 'FINALIZE_CODE()' should be called once to
     197    // complete generation of the code. Alternatively, call
     198    // finalizeCodeWithoutDisassembly() directly if you have your own way of
     199    // displaying disassembly.
     200   
     201    CodeRef finalizeCodeWithoutDisassembly();
     202    CodeRef finalizeCodeWithDisassembly(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
    203203
    204204    CodePtr trampolineAt(Label label)
     
    232232    }
    233233
    234     void linkCode(void* ownerUID, JITCompilationEffort effort)
    235     {
    236         ASSERT(!m_code);
    237 #if !ENABLE(BRANCH_COMPACTION)
    238         m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
    239         if (!m_executableMemory)
    240             return;
    241         m_code = m_executableMemory->start();
    242         m_size = m_assembler->m_assembler.codeSize();
    243         ASSERT(m_code);
    244 #else
    245         m_initialSize = m_assembler->m_assembler.codeSize();
    246         m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
    247         if (!m_executableMemory)
    248             return;
    249         m_code = (uint8_t*)m_executableMemory->start();
    250         ASSERT(m_code);
    251         ExecutableAllocator::makeWritable(m_code, m_initialSize);
    252         uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
    253         uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
    254         int readPtr = 0;
    255         int writePtr = 0;
    256         Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
    257         unsigned jumpCount = jumpsToLink.size();
    258         for (unsigned i = 0; i < jumpCount; ++i) {
    259             int offset = readPtr - writePtr;
    260             ASSERT(!(offset & 1));
    261            
    262             // Copy the instructions from the last jump to the current one.
    263             size_t regionSize = jumpsToLink[i].from() - readPtr;
    264             uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr);
    265             uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize);
    266             uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr);
    267             ASSERT(!(regionSize % 2));
    268             ASSERT(!(readPtr % 2));
    269             ASSERT(!(writePtr % 2));
    270             while (copySource != copyEnd)
    271                 *copyDst++ = *copySource++;
    272             m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
    273             readPtr += regionSize;
    274             writePtr += regionSize;
    275            
    276             // Calculate absolute address of the jump target, in the case of backwards
    277             // branches we need to be precise, forward branches we are pessimistic
    278             const uint8_t* target;
    279             if (jumpsToLink[i].to() >= jumpsToLink[i].from())
    280                 target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
    281             else
    282                 target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
    283            
    284             JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target);
    285             // Compact branch if we can...
    286             if (m_assembler->canCompact(jumpsToLink[i].type())) {
    287                 // Step back in the write stream
    288                 int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
    289                 if (delta) {
    290                     writePtr -= delta;
    291                     m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
    292                 }
    293             }
    294             jumpsToLink[i].setFrom(writePtr);
    295         }
    296         // Copy everything after the last jump
    297         memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr);
    298         m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr);
    299        
    300         for (unsigned i = 0; i < jumpCount; ++i) {
    301             uint8_t* location = outData + jumpsToLink[i].from();
    302             uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
    303             m_assembler->link(jumpsToLink[i], location, target);
    304         }
    305 
    306         jumpsToLink.clear();
    307         m_size = writePtr + m_initialSize - readPtr;
    308         m_executableMemory->shrink(m_size);
     234    void linkCode(void* ownerUID, JITCompilationEffort);
     235
     236    void performFinalization();
    309237
    310238#if DUMP_LINK_STATISTICS
    311         dumpLinkStatistics(m_code, m_initialSize, m_size);
    312 #endif
     239    static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize);
     240#endif
     241   
    313242#if DUMP_CODE
    314         dumpCode(m_code, m_size);
    315 #endif
    316 #endif
    317     }
    318 
    319     void performFinalization()
    320     {
    321 #ifndef NDEBUG
    322         ASSERT(!m_completed);
    323         ASSERT(isValid());
    324         m_completed = true;
    325 #endif
    326 
    327 #if ENABLE(BRANCH_COMPACTION)
    328         ExecutableAllocator::makeExecutable(code(), m_initialSize);
    329 #else
    330         ExecutableAllocator::makeExecutable(code(), m_size);
    331 #endif
    332         MacroAssembler::cacheFlush(code(), m_size);
    333     }
    334 
    335 #if DUMP_LINK_STATISTICS
    336     static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize)
    337     {
    338         static unsigned linkCount = 0;
    339         static unsigned totalInitialSize = 0;
    340         static unsigned totalFinalSize = 0;
    341         linkCount++;
    342         totalInitialSize += initialSize;
    343         totalFinalSize += finalSize;
    344         dataLog("link %p: orig %u, compact %u (delta %u, %.2f%%)\n",
    345                     code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize),
    346                     static_cast<unsigned>(initialSize - finalSize),
    347                     100.0 * (initialSize - finalSize) / initialSize);
    348         dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n",
    349                     linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize,
    350                     100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize);
    351     }
    352 #endif
    353    
    354 #if DUMP_CODE
    355     static void dumpCode(void* code, size_t size)
    356     {
    357 #if CPU(ARM_THUMB2)
    358         // Dump the generated code in an asm file format that can be assembled and then disassembled
    359         // for debugging purposes. For example, save this output as jit.s:
    360         //   gcc -arch armv7 -c jit.s
    361         //   otool -tv jit.o
    362         static unsigned codeCount = 0;
    363         unsigned short* tcode = static_cast<unsigned short*>(code);
    364         size_t tsize = size / sizeof(short);
    365         char nameBuf[128];
    366         snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
    367         dataLog("\t.syntax unified\n"
    368                     "\t.section\t__TEXT,__text,regular,pure_instructions\n"
    369                     "\t.globl\t%s\n"
    370                     "\t.align 2\n"
    371                     "\t.code 16\n"
    372                     "\t.thumb_func\t%s\n"
    373                     "# %p\n"
    374                     "%s:\n", nameBuf, nameBuf, code, nameBuf);
    375        
    376         for (unsigned i = 0; i < tsize; i++)
    377             dataLog("\t.short\t0x%x\n", tcode[i]);
    378 #elif CPU(ARM_TRADITIONAL)
    379         //   gcc -c jit.s
    380         //   objdump -D jit.o
    381         static unsigned codeCount = 0;
    382         unsigned int* tcode = static_cast<unsigned int*>(code);
    383         size_t tsize = size / sizeof(unsigned int);
    384         char nameBuf[128];
    385         snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
    386         dataLog("\t.globl\t%s\n"
    387                     "\t.align 4\n"
    388                     "\t.code 32\n"
    389                     "\t.text\n"
    390                     "# %p\n"
    391                     "%s:\n", nameBuf, code, nameBuf);
    392 
    393         for (unsigned i = 0; i < tsize; i++)
    394             dataLog("\t.long\t0x%x\n", tcode[i]);
    395 #endif
    396     }
     243    static void dumpCode(void* code, size_t);
    397244#endif
    398245   
     
    411258};
    412259
     260// Use this to finalize code, like so:
     261//
     262// CodeRef code = FINALIZE_CODE(linkBuffer, ("my super thingy number %d", number));
     263//
     264// Which, in disassembly mode, will print:
     265//
     266// Generated JIT code for my super thingy number 42:
     267//     Code at [0x123456, 0x234567]:
     268//         0x123456: mov $0, 0
     269//         0x12345a: ret
     270//
     271// ... and so on.
     272//
     273// Note that the dataLogArgumentsForHeading are only evaluated when showDisassembly
     274// is true, so you can hide expensive disassembly-only computations inside there.
     275
     276#define FINALIZE_CODE(linkBufferReference, dataLogArgumentsForHeading)  \
     277    (UNLIKELY(Options::showDisassembly)                                 \
     278     ? ((linkBufferReference).finalizeCodeWithDisassembly dataLogArgumentsForHeading) \
     279     : (linkBufferReference).finalizeCodeWithoutDisassembly())
     280
    413281} // namespace JSC
    414282
Note: See TracChangeset for help on using the changeset viewer.