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):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@120786 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 47e8794..24e67b9 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -36,6 +36,8 @@
     API/JSValueRef.cpp
     API/JSWeakObjectMapRefPrivate.cpp
     API/OpaqueJSString.cpp
+    
+    assembler/LinkBuffer.cpp
 
     bytecode/CallLinkInfo.cpp
     bytecode/CallLinkStatus.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 8338c86..aafc84d 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,108 @@
+2012-06-19  Filip Pizlo  <fpizlo@apple.com>
+
+        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):
+
 2012-06-19  Mark Hahnenberg  <mhahnenberg@apple.com>
 
         [Qt][Mac] REGRESSION(r120742): It broke the build
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index 63a6c6f..77409fe 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -65,6 +65,7 @@
 	Source/JavaScriptCore/assembler/AssemblerBuffer.h \
 	Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \
 	Source/JavaScriptCore/assembler/CodeLocation.h \
+	Source/JavaScriptCore/assembler/LinkBuffer.cpp \
 	Source/JavaScriptCore/assembler/LinkBuffer.h \
 	Source/JavaScriptCore/assembler/MacroAssembler.h \
 	Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp \
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
index 2ffb2b5..78ca7dd 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
@@ -1738,6 +1738,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\assembler\LinkBuffer.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\assembler\LinkBuffer.h"
 				>
 			</File>
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index cd9733f..2ffc9e2 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -208,6 +208,7 @@
 		0FF4274A158EBE91004CB9FF /* udis86.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4273E158EBD94004CB9FF /* udis86.c */; };
 		0FF4274B158EBE91004CB9FF /* udis86.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4273F158EBD94004CB9FF /* udis86.h */; };
 		0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */; };
+		0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */; };
 		0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
 		0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; };
 		0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -927,6 +928,7 @@
 		0FF4273E158EBD94004CB9FF /* udis86.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86.c; path = disassembler/udis86/udis86.c; sourceTree = "<group>"; };
 		0FF4273F158EBD94004CB9FF /* udis86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86.h; path = disassembler/udis86/udis86.h; sourceTree = "<group>"; };
 		0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_itab_holder.c; path = disassembler/udis86/udis86_itab_holder.c; sourceTree = "<group>"; };
+		0FF4275615914A20004CB9FF /* LinkBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkBuffer.cpp; sourceTree = "<group>"; };
 		0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
 		0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; };
 		0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
@@ -2295,6 +2297,7 @@
 				9688CB130ED12B4E001D649F /* AssemblerBuffer.h */,
 				86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */,
 				86E116B00FE75AC800B512BC /* CodeLocation.h */,
+				0FF4275615914A20004CB9FF /* LinkBuffer.cpp */,
 				86D3B3C110159D7F002865E7 /* LinkBuffer.h */,
 				86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */,
 				86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */,
@@ -3340,6 +3343,7 @@
 				0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
 				0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */,
 				C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */,
+				0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */,
 				C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri
index d16cf99..e3488c7 100644
--- a/Source/JavaScriptCore/Target.pri
+++ b/Source/JavaScriptCore/Target.pri
@@ -47,6 +47,7 @@
     API/OpaqueJSString.cpp \
     assembler/ARMAssembler.cpp \
     assembler/ARMv7Assembler.cpp \
+    assembler/LinkBuffer.cpp \
     assembler/MacroAssemblerARM.cpp \
     assembler/MacroAssemblerSH4.cpp \
     bytecode/CallLinkInfo.cpp \
diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.cpp b/Source/JavaScriptCore/assembler/LinkBuffer.cpp
new file mode 100644
index 0000000..58030ba
--- /dev/null
+++ b/Source/JavaScriptCore/assembler/LinkBuffer.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "LinkBuffer.h"
+
+#if ENABLE(ASSEMBLER)
+
+#include "Options.h"
+
+namespace JSC {
+
+LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithoutDisassembly()
+{
+    performFinalization();
+    
+    return CodeRef(m_executableMemory);
+}
+
+LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, ...)
+{
+    ASSERT(Options::showDisassembly);
+    
+    CodeRef result = finalizeCodeWithoutDisassembly();
+    
+    dataLog("Generated JIT code for ");
+    va_list argList;
+    va_start(argList, format);
+    WTF::dataLogV(format, argList);
+    va_end(argList);
+    dataLog(":\n");
+    
+    dataLog("    Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size());
+    if (!tryToDisassemble(result.code(), m_size, "    ", WTF::dataFile()))
+        dataLog("        <no disassembly available>");
+    
+    return result;
+}
+
+void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort)
+{
+    ASSERT(!m_code);
+#if !ENABLE(BRANCH_COMPACTION)
+    m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
+    if (!m_executableMemory)
+        return;
+    m_code = m_executableMemory->start();
+    m_size = m_assembler->m_assembler.codeSize();
+    ASSERT(m_code);
+#else
+    m_initialSize = m_assembler->m_assembler.codeSize();
+    m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
+    if (!m_executableMemory)
+        return;
+    m_code = (uint8_t*)m_executableMemory->start();
+    ASSERT(m_code);
+    ExecutableAllocator::makeWritable(m_code, m_initialSize);
+    uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
+    uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
+    int readPtr = 0;
+    int writePtr = 0;
+    Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
+    unsigned jumpCount = jumpsToLink.size();
+    for (unsigned i = 0; i < jumpCount; ++i) {
+        int offset = readPtr - writePtr;
+        ASSERT(!(offset & 1));
+            
+        // Copy the instructions from the last jump to the current one.
+        size_t regionSize = jumpsToLink[i].from() - readPtr;
+        uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr);
+        uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize);
+        uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr);
+        ASSERT(!(regionSize % 2));
+        ASSERT(!(readPtr % 2));
+        ASSERT(!(writePtr % 2));
+        while (copySource != copyEnd)
+            *copyDst++ = *copySource++;
+        m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
+        readPtr += regionSize;
+        writePtr += regionSize;
+            
+        // Calculate absolute address of the jump target, in the case of backwards
+        // branches we need to be precise, forward branches we are pessimistic
+        const uint8_t* target;
+        if (jumpsToLink[i].to() >= jumpsToLink[i].from())
+            target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
+        else
+            target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
+            
+        JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target);
+        // Compact branch if we can...
+        if (m_assembler->canCompact(jumpsToLink[i].type())) {
+            // Step back in the write stream
+            int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
+            if (delta) {
+                writePtr -= delta;
+                m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
+            }
+        }
+        jumpsToLink[i].setFrom(writePtr);
+    }
+    // Copy everything after the last jump
+    memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr);
+    m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr);
+        
+    for (unsigned i = 0; i < jumpCount; ++i) {
+        uint8_t* location = outData + jumpsToLink[i].from();
+        uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
+        m_assembler->link(jumpsToLink[i], location, target);
+    }
+
+    jumpsToLink.clear();
+    m_size = writePtr + m_initialSize - readPtr;
+    m_executableMemory->shrink(m_size);
+
+#if DUMP_LINK_STATISTICS
+    dumpLinkStatistics(m_code, m_initialSize, m_size);
+#endif
+#if DUMP_CODE
+    dumpCode(m_code, m_size);
+#endif
+#endif
+}
+
+void LinkBuffer::performFinalization()
+{
+#ifndef NDEBUG
+    ASSERT(!m_completed);
+    ASSERT(isValid());
+    m_completed = true;
+#endif
+    
+#if ENABLE(BRANCH_COMPACTION)
+    ExecutableAllocator::makeExecutable(code(), m_initialSize);
+#else
+    ExecutableAllocator::makeExecutable(code(), m_size);
+#endif
+    MacroAssembler::cacheFlush(code(), m_size);
+}
+
+#if DUMP_LINK_STATISTICS
+void LinkBuffer::dumpLinkStatistics(void* code, size_t initializeSize, size_t finalSize)
+{
+    static unsigned linkCount = 0;
+    static unsigned totalInitialSize = 0;
+    static unsigned totalFinalSize = 0;
+    linkCount++;
+    totalInitialSize += initialSize;
+    totalFinalSize += finalSize;
+    dataLog("link %p: orig %u, compact %u (delta %u, %.2f%%)\n", 
+            code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize),
+            static_cast<unsigned>(initialSize - finalSize),
+            100.0 * (initialSize - finalSize) / initialSize);
+    dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", 
+            linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize,
+            100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize);
+}
+#endif
+
+#if DUMP_CODE
+void LinkBuffer::dumpCode(void* code, size_t size)
+{
+#if CPU(ARM_THUMB2)
+    // Dump the generated code in an asm file format that can be assembled and then disassembled
+    // for debugging purposes. For example, save this output as jit.s:
+    //   gcc -arch armv7 -c jit.s
+    //   otool -tv jit.o
+    static unsigned codeCount = 0;
+    unsigned short* tcode = static_cast<unsigned short*>(code);
+    size_t tsize = size / sizeof(short);
+    char nameBuf[128];
+    snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
+    dataLog("\t.syntax unified\n"
+            "\t.section\t__TEXT,__text,regular,pure_instructions\n"
+            "\t.globl\t%s\n"
+            "\t.align 2\n"
+            "\t.code 16\n"
+            "\t.thumb_func\t%s\n"
+            "# %p\n"
+            "%s:\n", nameBuf, nameBuf, code, nameBuf);
+        
+    for (unsigned i = 0; i < tsize; i++)
+        dataLog("\t.short\t0x%x\n", tcode[i]);
+#elif CPU(ARM_TRADITIONAL)
+    //   gcc -c jit.s
+    //   objdump -D jit.o
+    static unsigned codeCount = 0;
+    unsigned int* tcode = static_cast<unsigned int*>(code);
+    size_t tsize = size / sizeof(unsigned int);
+    char nameBuf[128];
+    snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
+    dataLog("\t.globl\t%s\n"
+            "\t.align 4\n"
+            "\t.code 32\n"
+            "\t.text\n"
+            "# %p\n"
+            "%s:\n", nameBuf, code, nameBuf);
+
+    for (unsigned i = 0; i < tsize; i++)
+        dataLog("\t.long\t0x%x\n", tcode[i]);
+#endif
+}
+#endif
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+
diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h
index eff320d..c6e0031 100644
--- a/Source/JavaScriptCore/assembler/LinkBuffer.h
+++ b/Source/JavaScriptCore/assembler/LinkBuffer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -193,13 +193,13 @@
         return applyOffset(label.m_label).m_offset;
     }
 
-    // Upon completion of all patching 'finalizeCode()' should be called once to complete generation of the code.
-    CodeRef finalizeCode()
-    {
-        performFinalization();
-
-        return CodeRef(m_executableMemory);
-    }
+    // Upon completion of all patching 'FINALIZE_CODE()' should be called once to
+    // complete generation of the code. Alternatively, call
+    // finalizeCodeWithoutDisassembly() directly if you have your own way of
+    // displaying disassembly.
+    
+    CodeRef finalizeCodeWithoutDisassembly();
+    CodeRef finalizeCodeWithDisassembly(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
 
     CodePtr trampolineAt(Label label)
     {
@@ -231,169 +231,16 @@
         return m_code;
     }
 
-    void linkCode(void* ownerUID, JITCompilationEffort effort)
-    {
-        ASSERT(!m_code);
-#if !ENABLE(BRANCH_COMPACTION)
-        m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
-        if (!m_executableMemory)
-            return;
-        m_code = m_executableMemory->start();
-        m_size = m_assembler->m_assembler.codeSize();
-        ASSERT(m_code);
-#else
-        m_initialSize = m_assembler->m_assembler.codeSize();
-        m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
-        if (!m_executableMemory)
-            return;
-        m_code = (uint8_t*)m_executableMemory->start();
-        ASSERT(m_code);
-        ExecutableAllocator::makeWritable(m_code, m_initialSize);
-        uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
-        uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
-        int readPtr = 0;
-        int writePtr = 0;
-        Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
-        unsigned jumpCount = jumpsToLink.size();
-        for (unsigned i = 0; i < jumpCount; ++i) {
-            int offset = readPtr - writePtr;
-            ASSERT(!(offset & 1));
-            
-            // Copy the instructions from the last jump to the current one.
-            size_t regionSize = jumpsToLink[i].from() - readPtr;
-            uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr);
-            uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize);
-            uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr);
-            ASSERT(!(regionSize % 2));
-            ASSERT(!(readPtr % 2));
-            ASSERT(!(writePtr % 2));
-            while (copySource != copyEnd)
-                *copyDst++ = *copySource++;
-            m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
-            readPtr += regionSize;
-            writePtr += regionSize;
-            
-            // Calculate absolute address of the jump target, in the case of backwards
-            // branches we need to be precise, forward branches we are pessimistic
-            const uint8_t* target;
-            if (jumpsToLink[i].to() >= jumpsToLink[i].from())
-                target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
-            else
-                target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
-            
-            JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target);
-            // Compact branch if we can...
-            if (m_assembler->canCompact(jumpsToLink[i].type())) {
-                // Step back in the write stream
-                int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
-                if (delta) {
-                    writePtr -= delta;
-                    m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
-                }
-            }
-            jumpsToLink[i].setFrom(writePtr);
-        }
-        // Copy everything after the last jump
-        memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr);
-        m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr);
-        
-        for (unsigned i = 0; i < jumpCount; ++i) {
-            uint8_t* location = outData + jumpsToLink[i].from();
-            uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
-            m_assembler->link(jumpsToLink[i], location, target);
-        }
+    void linkCode(void* ownerUID, JITCompilationEffort);
 
-        jumpsToLink.clear();
-        m_size = writePtr + m_initialSize - readPtr;
-        m_executableMemory->shrink(m_size);
+    void performFinalization();
 
 #if DUMP_LINK_STATISTICS
-        dumpLinkStatistics(m_code, m_initialSize, m_size);
-#endif
-#if DUMP_CODE
-        dumpCode(m_code, m_size);
-#endif
-#endif
-    }
-
-    void performFinalization()
-    {
-#ifndef NDEBUG
-        ASSERT(!m_completed);
-        ASSERT(isValid());
-        m_completed = true;
-#endif
-
-#if ENABLE(BRANCH_COMPACTION)
-        ExecutableAllocator::makeExecutable(code(), m_initialSize);
-#else
-        ExecutableAllocator::makeExecutable(code(), m_size);
-#endif
-        MacroAssembler::cacheFlush(code(), m_size);
-    }
-
-#if DUMP_LINK_STATISTICS
-    static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize)
-    {
-        static unsigned linkCount = 0;
-        static unsigned totalInitialSize = 0;
-        static unsigned totalFinalSize = 0;
-        linkCount++;
-        totalInitialSize += initialSize;
-        totalFinalSize += finalSize;
-        dataLog("link %p: orig %u, compact %u (delta %u, %.2f%%)\n", 
-                    code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize),
-                    static_cast<unsigned>(initialSize - finalSize),
-                    100.0 * (initialSize - finalSize) / initialSize);
-        dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", 
-                    linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize,
-                    100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize);
-    }
+    static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize);
 #endif
     
 #if DUMP_CODE
-    static void dumpCode(void* code, size_t size)
-    {
-#if CPU(ARM_THUMB2)
-        // Dump the generated code in an asm file format that can be assembled and then disassembled
-        // for debugging purposes. For example, save this output as jit.s:
-        //   gcc -arch armv7 -c jit.s
-        //   otool -tv jit.o
-        static unsigned codeCount = 0;
-        unsigned short* tcode = static_cast<unsigned short*>(code);
-        size_t tsize = size / sizeof(short);
-        char nameBuf[128];
-        snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
-        dataLog("\t.syntax unified\n"
-                    "\t.section\t__TEXT,__text,regular,pure_instructions\n"
-                    "\t.globl\t%s\n"
-                    "\t.align 2\n"
-                    "\t.code 16\n"
-                    "\t.thumb_func\t%s\n"
-                    "# %p\n"
-                    "%s:\n", nameBuf, nameBuf, code, nameBuf);
-        
-        for (unsigned i = 0; i < tsize; i++)
-            dataLog("\t.short\t0x%x\n", tcode[i]);
-#elif CPU(ARM_TRADITIONAL)
-        //   gcc -c jit.s
-        //   objdump -D jit.o
-        static unsigned codeCount = 0;
-        unsigned int* tcode = static_cast<unsigned int*>(code);
-        size_t tsize = size / sizeof(unsigned int);
-        char nameBuf[128];
-        snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
-        dataLog("\t.globl\t%s\n"
-                    "\t.align 4\n"
-                    "\t.code 32\n"
-                    "\t.text\n"
-                    "# %p\n"
-                    "%s:\n", nameBuf, code, nameBuf);
-
-        for (unsigned i = 0; i < tsize; i++)
-            dataLog("\t.long\t0x%x\n", tcode[i]);
-#endif
-    }
+    static void dumpCode(void* code, size_t);
 #endif
     
     RefPtr<ExecutableMemoryHandle> m_executableMemory;
@@ -410,6 +257,27 @@
 #endif
 };
 
+// Use this to finalize code, like so:
+//
+// CodeRef code = FINALIZE_CODE(linkBuffer, ("my super thingy number %d", number));
+//
+// Which, in disassembly mode, will print:
+//
+// Generated JIT code for my super thingy number 42:
+//     Code at [0x123456, 0x234567]:
+//         0x123456: mov $0, 0
+//         0x12345a: ret
+//
+// ... and so on.
+//
+// Note that the dataLogArgumentsForHeading are only evaluated when showDisassembly
+// is true, so you can hide expensive disassembly-only computations inside there.
+
+#define FINALIZE_CODE(linkBufferReference, dataLogArgumentsForHeading)  \
+    (UNLIKELY(Options::showDisassembly)                                 \
+     ? ((linkBufferReference).finalizeCodeWithDisassembly dataLogArgumentsForHeading) \
+     : (linkBufferReference).finalizeCodeWithoutDisassembly())
+
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
index ac62c42..a1b3a83 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,7 +26,9 @@
 #ifndef MacroAssemblerCodeRef_h
 #define MacroAssemblerCodeRef_h
 
+#include "Disassembler.h"
 #include "ExecutableAllocator.h"
+#include <wtf/DataLog.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefPtr.h>
 #include <wtf/UnusedParam.h>
@@ -367,6 +369,11 @@
         return m_executableMemory->sizeInBytes();
     }
     
+    bool tryToDisassemble(const char* prefix) const
+    {
+        return JSC::tryToDisassemble(m_codePtr, size(), prefix, WTF::dataFile());
+    }
+    
     bool operator!() const { return !m_codePtr; }
 
 private:
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index c0eeca8..561f516 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -220,10 +220,9 @@
     link(linkBuffer);
     speculative.linkOSREntries(linkBuffer);
 
-    entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
-#if DFG_ENABLE(DEBUG_VERBOSE)
-    entry.tryToDisassemble();
-#endif
+    entry = JITCode(
+        FINALIZE_CODE(linkBuffer, ("DFG program/eval CodeBlock %p", m_codeBlock)),
+        JITCode::DFGJIT);
     return true;
 }
 
@@ -305,10 +304,9 @@
     linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
 
     entryWithArityCheck = linkBuffer.locationOf(arityCheck);
-    entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
-#if DFG_ENABLE(DEBUG_VERBOSE)
-    entry.tryToDisassemble();
-#endif
+    entry = JITCode(
+        FINALIZE_CODE(linkBuffer, ("DFG function CodeBlock %p", m_codeBlock)),
+        JITCode::DFGJIT);
     return true;
 }
 
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
index 888a4a2..d46d596 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
@@ -79,11 +79,11 @@
         exitCompiler.compileExit(exit, recovery);
         
         LinkBuffer patchBuffer(*globalData, &jit, codeBlock);
-        exit.m_code = patchBuffer.finalizeCode();
-
-#if DFG_ENABLE(DEBUG_VERBOSE)
-        dataLog("OSR exit code at [%p, %p).\n", patchBuffer.debugAddress(), static_cast<char*>(patchBuffer.debugAddress()) + patchBuffer.debugSize());
-#endif
+        exit.m_code = FINALIZE_CODE(
+            patchBuffer,
+            ("DFG OSR exit #%u (bc#%u, @%u, %s) from CodeBlock %p",
+             exitIndex, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex,
+             exitKindToString(exit.m_kind), codeBlock));
     }
     
     {
diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
index 2c07ed5..9c3391b 100644
--- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp
+++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
@@ -155,7 +155,10 @@
     
     linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
     
-    stubRoutine = patchBuffer.finalizeCode();
+    stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("DFG prototype chain access stub for CodeBlock %p, return point %p",
+         exec->codeBlock(), successLabel.executableAddress()));
 }
 
 static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
@@ -206,7 +209,11 @@
         
         linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCases);
         
-        stubInfo.stubRoutine = patchBuffer.finalizeCode();
+        stubInfo.stubRoutine = FINALIZE_CODE(
+            patchBuffer,
+            ("DFG GetById array length stub for CodeBlock %p, return point %p",
+             exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+                 stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
         
         RepatchBuffer repatchBuffer(codeBlock);
         repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
@@ -405,7 +412,11 @@
             patchBuffer.link(handlerCall, lookupExceptionHandlerInStub);
         }
         
-        MacroAssemblerCodeRef stubRoutine = patchBuffer.finalizeCode();
+        MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+            patchBuffer,
+            ("DFG GetById polymorphic list access for CodeBlock %p, return point %p",
+             exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+                 stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
         
         polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
         
@@ -611,7 +622,11 @@
     patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
     patchBuffer.link(failure, failureLabel);
             
-    stubRoutine = patchBuffer.finalizeCode();
+    stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("DFG PutById replace stub for CodeBlock %p, return point %p",
+         exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+             stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
 }
 
 static void emitPutTransitionStub(
@@ -707,7 +722,11 @@
     else
         patchBuffer.link(failureCases, failureLabel);
             
-    stubRoutine = patchBuffer.finalizeCode();
+    stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("DFG PutById transition stub for CodeBlock %p, return point %p",
+         exec->codeBlock(), stubInfo.callReturnLocation.labelAtOffset(
+             stubInfo.patch.dfg.deltaCallToDone).executableAddress()));
 }
 
 static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier& ident, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
diff --git a/Source/JavaScriptCore/dfg/DFGThunks.cpp b/Source/JavaScriptCore/dfg/DFGThunks.cpp
index 1ed46c1..08ca6ea 100644
--- a/Source/JavaScriptCore/dfg/DFGThunks.cpp
+++ b/Source/JavaScriptCore/dfg/DFGThunks.cpp
@@ -79,7 +79,7 @@
     
     patchBuffer.link(functionCall, compileOSRExit);
     
-    return patchBuffer.finalizeCode();
+    return FINALIZE_CODE(patchBuffer, ("DFG OSR exit generation thunk"));
 }
 
 } } // namespace JSC::DFG
diff --git a/Source/JavaScriptCore/disassembler/Disassembler.h b/Source/JavaScriptCore/disassembler/Disassembler.h
index e49defd..7d7400a 100644
--- a/Source/JavaScriptCore/disassembler/Disassembler.h
+++ b/Source/JavaScriptCore/disassembler/Disassembler.h
@@ -26,16 +26,18 @@
 #ifndef Disassembler_h
 #define Disassembler_h
 
-#include "MacroAssemblerCodeRef.h"
+#include <stdio.h>
 #include <wtf/Platform.h>
 #include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
+class MacroAssemblerCodePtr;
+
 #if ENABLE(DISASSEMBLER)
-bool tryToDisassemble(MacroAssemblerCodePtr, size_t size, FILE* out);
+bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char* prefix, FILE* out);
 #else
-inline bool tryToDisassemble(MacroAssemblerCodePtr, size_t, FILE*)
+inline bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char*, FILE*)
 {
     return false;
 }
diff --git a/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp b/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp
index 26ec23b..b6baed4 100644
--- a/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp
+++ b/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp
@@ -28,11 +28,12 @@
 
 #if USE(UDIS86)
 
+#include "MacroAssemblerCodeRef.h"
 #include "udis86.h"
 
 namespace JSC {
 
-bool tryToDisassemble(MacroAssemblerCodePtr codePtr, size_t size, FILE* out)
+bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, FILE* out)
 {
     ud_t disassembler;
     ud_init(&disassembler);
@@ -45,10 +46,12 @@
     ud_set_pc(&disassembler, bitwise_cast<uintptr_t>(codePtr.executableAddress()));
     ud_set_syntax(&disassembler, UD_SYN_ATT);
     
+    uint64_t currentPC = disassembler.pc;
     while (ud_disassemble(&disassembler)) {
         char pcString[20];
-        snprintf(pcString, sizeof(pcString), "0x%lx", static_cast<unsigned long>(disassembler.pc));
-        fprintf(out, "%16s: %s\n", pcString, ud_insn_asm(&disassembler));
+        snprintf(pcString, sizeof(pcString), "0x%lx", static_cast<unsigned long>(currentPC));
+        fprintf(out, "%s%16s: %s\n", prefix, pcString, ud_insn_asm(&disassembler));
+        currentPC = disassembler.pc;
     }
     
     return true;
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index d3ba991..2aca351 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -761,7 +761,8 @@
     if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck)
         *functionEntryArityCheck = patchBuffer.locationOf(arityCheck);
     
-    CodeRef result = patchBuffer.finalizeCode();
+    CodeRef result = FINALIZE_CODE(
+        patchBuffer, ("Baseline JIT code for CodeBlock %p", m_codeBlock));
     
     m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.add(
         static_cast<double>(result.size()) /
diff --git a/Source/JavaScriptCore/jit/JITCode.h b/Source/JavaScriptCore/jit/JITCode.h
index 67df80a..478fcc7 100644
--- a/Source/JavaScriptCore/jit/JITCode.h
+++ b/Source/JavaScriptCore/jit/JITCode.h
@@ -145,9 +145,9 @@
             return m_ref.size();
         }
         
-        bool tryToDisassemble() const
+        bool tryToDisassemble(const char* prefix) const
         {
-            return JSC::tryToDisassemble(m_ref.code(), size(), WTF::dataFile());
+            return m_ref.tryToDisassemble(prefix);
         }
 
         ExecutableMemoryHandle* getExecutableMemory()
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index 2288a06..ad7a56e 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -211,7 +211,7 @@
     patchBuffer.link(callCallNotJSFunction, FunctionPtr(cti_op_call_NotJSFunction));
     patchBuffer.link(callConstructNotJSFunction, FunctionPtr(cti_op_construct_NotJSConstruct));
 
-    CodeRef finalCode = patchBuffer.finalizeCode();
+    CodeRef finalCode = FINALIZE_CODE(patchBuffer, ("JIT CTI machine trampolines"));
     RefPtr<ExecutableMemoryHandle> executableMemory = finalCode.executableMemory();
 
     trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 2a8abf4..57ef7ef 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -207,7 +207,7 @@
     patchBuffer.link(callCallNotJSFunction, FunctionPtr(cti_op_call_NotJSFunction));
     patchBuffer.link(callConstructNotJSFunction, FunctionPtr(cti_op_construct_NotJSConstruct));
 
-    CodeRef finalCode = patchBuffer.finalizeCode();
+    CodeRef finalCode = FINALIZE_CODE(patchBuffer, ("JIT CTI machine trampolines"));
     RefPtr<ExecutableMemoryHandle> executableMemory = finalCode.executableMemory();
 
     trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
@@ -497,7 +497,7 @@
     LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
 
     patchBuffer.link(nativeCall, FunctionPtr(func));
-    return patchBuffer.finalizeCode();
+    return FINALIZE_CODE(patchBuffer, ("JIT CTI native call"));
 }
 
 void JIT::emit_op_mov(Instruction* currentInstruction)
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
index 4fb40aa..7478f91 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
@@ -88,7 +88,7 @@
     jit.ret();
     
     LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
-    return patchBuffer.finalizeCode();
+    return FINALIZE_CODE(patchBuffer, ("String get_by_val stub"));
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -564,7 +564,10 @@
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
-    stubInfo->stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline put_by_id transition for CodeBlock %p, return point %p",
+         m_codeBlock, returnAddress.value()));
     RepatchBuffer repatchBuffer(m_codeBlock);
     repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
 }
@@ -625,7 +628,11 @@
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Basline JIT get_by_id array length stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -688,7 +695,11 @@
         }
     }
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline JIT get_by_id proto stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -745,7 +756,11 @@
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
+    MacroAssemblerCodeRef stubCode = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline JIT get_by_id list stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
 
     polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, isDirect);
 
@@ -811,7 +826,11 @@
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
+    MacroAssemblerCodeRef stubCode = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline JIT get_by_id proto list stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
     prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, prototypeStructure, isDirect);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
@@ -880,7 +899,11 @@
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    CodeRef stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline JIT get_by_id chain list stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
 
     // Track the stub we have created so that it will be deleted later.
     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
@@ -947,7 +970,11 @@
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     // Track the stub we have created so that it will be deleted later.
-    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    CodeRef stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline JIT get_by_id chain stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
     stubInfo->stubRoutine = stubRoutine;
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index 5bec19e..a44c576 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -194,7 +194,7 @@
     jit.ret();
     
     LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
-    return patchBuffer.finalizeCode();
+    return FINALIZE_CODE(patchBuffer, ("String get_by_val stub"));
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -545,7 +545,10 @@
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
-    stubInfo->stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline put_by_id transition stub for CodeBlock %p, return point %p",
+         m_codeBlock, returnAddress.value()));
     RepatchBuffer repatchBuffer(m_codeBlock);
     repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
 }
@@ -611,7 +614,11 @@
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline get_by_id array length stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -677,7 +684,11 @@
     }
 
     // Track the stub we have created so that it will be deleted later.
-    stubInfo->stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline get_by_id proto stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
@@ -735,7 +746,11 @@
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
-    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline get_by_id self list stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
 
     polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
     
@@ -800,7 +815,11 @@
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
-    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline get_by_id proto list stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
 
     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, prototypeStructure, isDirect);
     
@@ -870,7 +889,11 @@
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
-    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline get_by_id chain list stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
     
     // Track the stub we have created so that it will be deleted later.
     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
@@ -936,7 +959,11 @@
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     // Track the stub we have created so that it will be deleted later.
-    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    MacroAssemblerCodeRef stubRoutine = FINALIZE_CODE(
+        patchBuffer,
+        ("Baseline get_by_id chain stub for CodeBlock %p, return point %p",
+         m_codeBlock, stubInfo->hotPathBegin.labelAtOffset(
+             stubInfo->patch.baseline.u.get.putResult).executableAddress()));
     stubInfo->stubRoutine = stubRoutine;
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
diff --git a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
index 74e94ea..c98e57d1 100644
--- a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
+++ b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
@@ -132,13 +132,13 @@
             ret();
         }
         
-        MacroAssemblerCodeRef finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback)
+        MacroAssemblerCodeRef finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback, const char* thunkKind)
         {
             LinkBuffer patchBuffer(globalData, this, GLOBAL_THUNK_ID);
             patchBuffer.link(m_failures, CodeLocationLabel(fallback));
             for (unsigned i = 0; i < m_calls.size(); i++)
                 patchBuffer.link(m_calls[i].first, m_calls[i].second);
-            return patchBuffer.finalizeCode();
+            return FINALIZE_CODE(patchBuffer, ("Specialized thunk for %s", thunkKind));
         }
 
         // Assumes that the target function uses fpRegister0 as the first argument
diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
index de8c938..c440b51 100644
--- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp
+++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp
@@ -78,7 +78,7 @@
     SpecializedThunkJIT jit(1, globalData);
     stringCharLoad(jit);
     jit.returnInt32(SpecializedThunkJIT::regT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "charCodeAt");
 }
 
 MacroAssemblerCodeRef charAtThunkGenerator(JSGlobalData* globalData)
@@ -87,7 +87,7 @@
     stringCharLoad(jit);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
     jit.returnJSCell(SpecializedThunkJIT::regT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "charAt");
 }
 
 MacroAssemblerCodeRef fromCharCodeThunkGenerator(JSGlobalData* globalData)
@@ -97,7 +97,7 @@
     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
     jit.returnJSCell(SpecializedThunkJIT::regT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "fromCharCode");
 }
 
 MacroAssemblerCodeRef sqrtThunkGenerator(JSGlobalData* globalData)
@@ -109,7 +109,7 @@
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "sqrt");
 }
 
 
@@ -209,7 +209,7 @@
     jit.returnInt32(SpecializedThunkJIT::regT0);
     doubleResult.link(&jit);
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "floor");
 }
 
 MacroAssemblerCodeRef ceilThunkGenerator(JSGlobalData* globalData)
@@ -228,7 +228,7 @@
     jit.returnInt32(SpecializedThunkJIT::regT0);
     doubleResult.link(&jit);
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "ceil");
 }
 
 MacroAssemblerCodeRef roundThunkGenerator(JSGlobalData* globalData)
@@ -262,7 +262,7 @@
     jit.returnInt32(SpecializedThunkJIT::regT0);
     doubleResult.link(&jit);
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "round");
 }
 
 MacroAssemblerCodeRef expThunkGenerator(JSGlobalData* globalData)
@@ -275,7 +275,7 @@
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     jit.callDoubleToDouble(UnaryDoubleOpWrapper(exp));
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "exp");
 }
 
 MacroAssemblerCodeRef logThunkGenerator(JSGlobalData* globalData)
@@ -288,7 +288,7 @@
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     jit.callDoubleToDouble(UnaryDoubleOpWrapper(log));
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "log");
 }
 
 MacroAssemblerCodeRef absThunkGenerator(JSGlobalData* globalData)
@@ -308,7 +308,7 @@
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     jit.absDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
     jit.returnDouble(SpecializedThunkJIT::fpRegT1);
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "abs");
 }
 
 MacroAssemblerCodeRef powThunkGenerator(JSGlobalData* globalData)
@@ -360,7 +360,7 @@
     } else
         jit.appendFailure(nonIntExponent);
 
-    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "pow");
 }
 
 }
diff --git a/Source/JavaScriptCore/llint/LLIntThunks.cpp b/Source/JavaScriptCore/llint/LLIntThunks.cpp
index b4d0264..6a6a579 100644
--- a/Source/JavaScriptCore/llint/LLIntThunks.cpp
+++ b/Source/JavaScriptCore/llint/LLIntThunks.cpp
@@ -36,7 +36,7 @@
 
 namespace JSC { namespace LLInt {
 
-static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)())
+static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)(), const char *thunkKind)
 {
     JSInterfaceJIT jit;
     
@@ -45,37 +45,37 @@
     jit.jump(JSInterfaceJIT::regT0);
     
     LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
-    return patchBuffer.finalizeCode();
+    return FINALIZE_CODE(patchBuffer, ("LLInt %s prologue thunk", thunkKind));
 }
 
 MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData* globalData)
 {
-    return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue);
+    return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue, "function for call");
 }
 
 MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData* globalData)
 {
-    return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue);
+    return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue, "function for construct");
 }
 
 MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData* globalData)
 {
-    return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check);
+    return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check, "function for call with arity check");
 }
 
 MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData* globalData)
 {
-    return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check);
+    return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check, "function for construct with arity check");
 }
 
 MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData* globalData)
 {
-    return generateThunkWithJumpTo(globalData, llint_eval_prologue);
+    return generateThunkWithJumpTo(globalData, llint_eval_prologue, "eval");
 }
 
 MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData* globalData)
 {
-    return generateThunkWithJumpTo(globalData, llint_program_prologue);
+    return generateThunkWithJumpTo(globalData, llint_program_prologue, "program");
 }
 
 } } // namespace JSC::LLInt
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index 9e05939..ec228f8 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -47,6 +47,8 @@
 
 bool useJIT;
 
+bool showDisassembly;
+
 unsigned maximumOptimizationCandidateInstructionCount;
 
 unsigned maximumFunctionForCallInlineCandidateInstructionCount;
@@ -162,6 +164,8 @@
 {
     SET(useJIT, true);
     
+    SET(showDisassembly, false);
+    
     SET(maximumOptimizationCandidateInstructionCount, 10000);
     
     SET(maximumFunctionForCallInlineCandidateInstructionCount, 180);
diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h
index ac49109..e5cc995 100644
--- a/Source/JavaScriptCore/runtime/Options.h
+++ b/Source/JavaScriptCore/runtime/Options.h
@@ -32,6 +32,8 @@
 
 extern bool useJIT;
 
+extern bool showDisassembly;
+
 extern unsigned maximumOptimizationCandidateInstructionCount;
 
 extern unsigned maximumFunctionForCallInlineCandidateInstructionCount;
diff --git a/Source/JavaScriptCore/yarr/YarrJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp
index 60519eb..eb9861f 100644
--- a/Source/JavaScriptCore/yarr/YarrJIT.cpp
+++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp
@@ -2611,14 +2611,14 @@
 
         if (compileMode == MatchOnly) {
             if (m_charSize == Char8)
-                jitObject.set8BitCodeMatchOnly(linkBuffer.finalizeCode());
+                jitObject.set8BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, ("Match-only 8-bit regular expression")));
             else
-                jitObject.set16BitCodeMatchOnly(linkBuffer.finalizeCode());
+                jitObject.set16BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, ("Match-only 16-bit regular expression")));
         } else {
             if (m_charSize == Char8)
-                jitObject.set8BitCode(linkBuffer.finalizeCode());
+                jitObject.set8BitCode(FINALIZE_CODE(linkBuffer, ("8-bit regular expression")));
             else
-                jitObject.set16BitCode(linkBuffer.finalizeCode());
+                jitObject.set16BitCode(FINALIZE_CODE(linkBuffer, ("16-bit regular expression")));
         }
         jitObject.setFallBack(m_shouldFallBack);
     }