Add option to dump JIT memory
authortzagallo@apple.com <tzagallo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Apr 2019 21:47:32 +0000 (21:47 +0000)
committertzagallo@apple.com <tzagallo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Apr 2019 21:47:32 +0000 (21:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197062
<rdar://problem/49744332>

Reviewed by Saam Barati.

Dump all writes into JIT memory to the specified file. The format is:
- 64-bit destination address for the write
- 64-bit size of the content written
- Copy of the data that was written to JIT memory

* assembler/LinkBuffer.cpp:
(JSC::LinkBuffer::copyCompactAndLinkCode):
* jit/ExecutableAllocator.cpp:
(JSC::dumpJITMemory):
* jit/ExecutableAllocator.h:
(JSC::performJITMemcpy):
* runtime/Options.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244470 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/LinkBuffer.cpp
Source/JavaScriptCore/jit/ExecutableAllocator.cpp
Source/JavaScriptCore/jit/ExecutableAllocator.h
Source/JavaScriptCore/runtime/Options.h

index a30b284..b986148 100644 (file)
@@ -1,3 +1,24 @@
+2019-04-19  Tadeu Zagallo  <tzagallo@apple.com>
+
+        Add option to dump JIT memory
+        https://bugs.webkit.org/show_bug.cgi?id=197062
+        <rdar://problem/49744332>
+
+        Reviewed by Saam Barati.
+
+        Dump all writes into JIT memory to the specified file. The format is:
+        - 64-bit destination address for the write
+        - 64-bit size of the content written
+        - Copy of the data that was written to JIT memory
+
+        * assembler/LinkBuffer.cpp:
+        (JSC::LinkBuffer::copyCompactAndLinkCode):
+        * jit/ExecutableAllocator.cpp:
+        (JSC::dumpJITMemory):
+        * jit/ExecutableAllocator.h:
+        (JSC::performJITMemcpy):
+        * runtime/Options.h:
+
 2019-04-19  Keith Rollin  <krollin@apple.com>
 
         Add postprocess-header-rule scripts
index 7e10d48..dc80bff 100644 (file)
@@ -260,6 +260,8 @@ void LinkBuffer::copyCompactAndLinkCode(MacroAssembler& macroAssembler, void* ow
     performJITMemcpy(codeOutData, outData, m_size);
 #else
     ASSERT(codeOutData == outData);
+    if (UNLIKELY(Options::dumpJITMemoryPath()))
+        dumpJITMemory(outData, outData, m_size);
 #endif
 
     jumpsToLink.clear();
index 7e637f6..dcb5ba5 100644 (file)
@@ -550,6 +550,53 @@ bool isJITPC(void* pc)
     return allocator && allocator->isJITPC(pc);
 }
 
+void dumpJITMemory(const void* dst, const void* src, size_t size)
+{
+    ASSERT(Options::dumpJITMemoryPath());
+
+#if OS(DARWIN)
+    static int fd = -1;
+    static uint8_t* buffer;
+    static constexpr size_t bufferSize = fixedExecutableMemoryPoolSize;
+    static size_t offset = 0;
+    static auto flush = [] {
+        if (fd == -1) {
+            fd = open(Options::dumpJITMemoryPath(), O_CREAT | O_TRUNC | O_APPEND | O_WRONLY | O_EXLOCK | O_NONBLOCK, 0666);
+            RELEASE_ASSERT(fd != -1);
+        }
+        write(fd, buffer, offset);
+        offset = 0;
+    };
+
+    static Lock dumpJITMemoryLock;
+    static std::once_flag once;
+    std::call_once(once, [] {
+        buffer = bitwise_cast<uint8_t*>(malloc(bufferSize));
+        std::atexit([] {
+            LockHolder locker(dumpJITMemoryLock);
+            flush();
+            close(fd);
+        });
+    });
+
+    static auto write = [](const void* src, size_t size) {
+        if (UNLIKELY(offset + size > bufferSize))
+            flush();
+        memcpy(buffer + offset, src, size);
+        offset += size;
+    };
+
+    LockHolder locker(dumpJITMemoryLock);
+    uint64_t dst64 = bitwise_cast<uintptr_t>(dst);
+    write(&dst64, sizeof(dst64));
+    uint64_t size64 = size;
+    write(&size64, sizeof(size64));
+    write(src, size);
+#else
+    RELEASE_ASSERT_NOT_REACHED();
+#endif
+}
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index 85b67c6..283fb46 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "JITCompilationEffort.h"
 #include "JSCPtrTag.h"
+#include "Options.h"
 #include <stddef.h> // for ptrdiff_t
 #include <limits>
 #include <wtf/Assertions.h>
@@ -111,6 +112,8 @@ T endOfFixedExecutableMemoryPool()
 
 JS_EXPORT_PRIVATE bool isJITPC(void* pc);
 
+JS_EXPORT_PRIVATE void dumpJITMemory(const void*, const void*, size_t);
+
 #if ENABLE(SEPARATED_WX_HEAP)
 
 typedef void (*JITWriteSeparateHeapsFunction)(off_t, const void*, size_t);
@@ -128,6 +131,9 @@ static inline void* performJITMemcpy(void *dst, const void *src, size_t n)
 #endif
     if (isJITPC(dst)) {
         RELEASE_ASSERT(reinterpret_cast<uint8_t*>(dst) + n <= endOfFixedExecutableMemoryPool());
+
+        if (UNLIKELY(Options::dumpJITMemoryPath()))
+            dumpJITMemory(dst, src, n);
 #if ENABLE(FAST_JIT_PERMISSIONS)
 #if ENABLE(SEPARATED_WX_HEAP)
         if (useFastPermisionsJITCopy)
index 5c8d0cf..b509adf 100644 (file)
@@ -517,6 +517,7 @@ constexpr bool enableWebAssemblyStreamingApi = false;
     v(bool, forceDiskCache, false, Restricted, nullptr) \
     v(bool, validateAbstractInterpreterState, false, Restricted, nullptr) \
     v(double, validateAbstractInterpreterStateProbability, 0.5, Normal, nullptr) \
+    v(optionString, dumpJITMemoryPath, nullptr, Restricted, nullptr) \
 
 
 enum OptionEquivalence {