[JSC] Compact JITCodeMap by storing BytecodeIndex and CodeLocation separately
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Feb 2020 02:30:05 +0000 (02:30 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Feb 2020 02:30:05 +0000 (02:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=207673

Reviewed by Mark Lam.

Source/JavaScriptCore:

While BytecodeIndex is 4 bytes, CodeLocation is 8 bytes. So the tuple of them "JITCodeMap::Entry"
becomes 16 bytes because it adds 4 bytes padding. We should store BytecodeIndex and CodeLocation separately
to avoid this padding.

This patch introduces JITCodeMapBuilder. We use this to build JITCodeMap data structure as a immutable final result.

* jit/JIT.cpp:
(JSC::JIT::link):
* jit/JITCodeMap.h:
(JSC::JITCodeMap::JITCodeMap):
(JSC::JITCodeMap::find const):
(JSC::JITCodeMap::operator bool const):
(JSC::JITCodeMap::codeLocations const):
(JSC::JITCodeMap::indexes const):
(JSC::JITCodeMapBuilder::append):
(JSC::JITCodeMapBuilder::finalize):
(JSC::JITCodeMap::Entry::Entry): Deleted.
(JSC::JITCodeMap::Entry::bytecodeIndex const): Deleted.
(JSC::JITCodeMap::Entry::codeLocation): Deleted.
(JSC::JITCodeMap::append): Deleted.
(JSC::JITCodeMap::finish): Deleted.

Source/WTF:

* wtf/MallocPtr.h:

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JITCodeMap.h
Source/WTF/ChangeLog
Source/WTF/wtf/MallocPtr.h

index 33bca61..2d05047 100644 (file)
@@ -1,3 +1,32 @@
+2020-02-12  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Compact JITCodeMap by storing BytecodeIndex and CodeLocation separately
+        https://bugs.webkit.org/show_bug.cgi?id=207673
+
+        Reviewed by Mark Lam.
+
+        While BytecodeIndex is 4 bytes, CodeLocation is 8 bytes. So the tuple of them "JITCodeMap::Entry"
+        becomes 16 bytes because it adds 4 bytes padding. We should store BytecodeIndex and CodeLocation separately
+        to avoid this padding.
+
+        This patch introduces JITCodeMapBuilder. We use this to build JITCodeMap data structure as a immutable final result.
+
+        * jit/JIT.cpp:
+        (JSC::JIT::link):
+        * jit/JITCodeMap.h:
+        (JSC::JITCodeMap::JITCodeMap):
+        (JSC::JITCodeMap::find const):
+        (JSC::JITCodeMap::operator bool const):
+        (JSC::JITCodeMap::codeLocations const):
+        (JSC::JITCodeMap::indexes const):
+        (JSC::JITCodeMapBuilder::append):
+        (JSC::JITCodeMapBuilder::finalize):
+        (JSC::JITCodeMap::Entry::Entry): Deleted.
+        (JSC::JITCodeMap::Entry::bytecodeIndex const): Deleted.
+        (JSC::JITCodeMap::Entry::codeLocation): Deleted.
+        (JSC::JITCodeMap::append): Deleted.
+        (JSC::JITCodeMap::finish): Deleted.
+
 2020-02-12  Pavel Feldman  <pavel.feldman@gmail.com>
 
         Web Inspector: encode binary web socket frames using base64
index 68711ce..091c4f7 100644 (file)
@@ -912,13 +912,14 @@ CompilationResult JIT::link()
             patchBuffer.locationOfNearCall<JSInternalPtrTag>(compilationInfo.hotPathOther));
     }
 
-    JITCodeMap jitCodeMap;
-    for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) {
-        if (m_labels[bytecodeOffset].isSet())
-            jitCodeMap.append(BytecodeIndex(bytecodeOffset), patchBuffer.locationOf<JSEntryPtrTag>(m_labels[bytecodeOffset]));
+    {
+        JITCodeMapBuilder jitCodeMapBuilder;
+        for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) {
+            if (m_labels[bytecodeOffset].isSet())
+                jitCodeMapBuilder.append(BytecodeIndex(bytecodeOffset), patchBuffer.locationOf<JSEntryPtrTag>(m_labels[bytecodeOffset]));
+        }
+        m_codeBlock->setJITCodeMap(jitCodeMapBuilder.finalize());
     }
-    jitCodeMap.finish();
-    m_codeBlock->setJITCodeMap(WTFMove(jitCodeMap));
 
     MacroAssemblerCodePtr<JSEntryPtrTag> withArityCheck = patchBuffer.locationOf<JSEntryPtrTag>(m_arityCheck);
 
index e075724..15c828a 100644 (file)
 namespace JSC {
 
 class JITCodeMap {
-private:
-    struct Entry {
-        Entry() { }
+public:
+    static_assert(std::is_trivially_destructible_v<BytecodeIndex>);
+    static_assert(std::is_trivially_destructible_v<CodeLocationLabel<JSEntryPtrTag>>);
+    static_assert(alignof(CodeLocationLabel<JSEntryPtrTag>) >= alignof(BytecodeIndex), "Putting CodeLocationLabel vector first since we can avoid alignment consideration of BytecodeIndex vector");
+    JITCodeMap() = default;
+    JITCodeMap(Vector<BytecodeIndex>&& indexes, Vector<CodeLocationLabel<JSEntryPtrTag>>&& codeLocations)
+        : m_size(indexes.size())
+    {
+        ASSERT(indexes.size() == codeLocations.size());
+        m_pointer = MallocPtr<uint8_t>::malloc(sizeof(CodeLocationLabel<JSEntryPtrTag>) * m_size + sizeof(BytecodeIndex) * m_size);
+        std::copy(codeLocations.begin(), codeLocations.end(), this->codeLocations());
+        std::copy(indexes.begin(), indexes.end(), this->indexes());
+    }
+
+    CodeLocationLabel<JSEntryPtrTag> find(BytecodeIndex bytecodeIndex) const
+    {
+        auto* index = binarySearch<BytecodeIndex, BytecodeIndex>(indexes(), m_size, bytecodeIndex, [] (BytecodeIndex* index) { return *index; });
+        if (!index)
+            return CodeLocationLabel<JSEntryPtrTag>();
+        return codeLocations()[index - indexes()];
+    }
+
+    explicit operator bool() const { return m_size; }
 
-        Entry(BytecodeIndex bytecodeIndex, CodeLocationLabel<JSEntryPtrTag> codeLocation)
-            : m_bytecodeIndex(bytecodeIndex)
-            , m_codeLocation(codeLocation)
-        { }
+private:
+    CodeLocationLabel<JSEntryPtrTag>* codeLocations() const
+    {
+        return bitwise_cast<CodeLocationLabel<JSEntryPtrTag>*>(m_pointer.get());
+    }
 
-        inline BytecodeIndex bytecodeIndex() const { return m_bytecodeIndex; }
-        inline CodeLocationLabel<JSEntryPtrTag> codeLocation() { return m_codeLocation; }
+    BytecodeIndex* indexes() const
+    {
+        return bitwise_cast<BytecodeIndex*>(m_pointer.get() + sizeof(CodeLocationLabel<JSEntryPtrTag>) * m_size);
+    }
 
-    private:
-        BytecodeIndex m_bytecodeIndex;
-        CodeLocationLabel<JSEntryPtrTag> m_codeLocation;
-    };
+    MallocPtr<uint8_t> m_pointer;
+    unsigned m_size { 0 };
+};
 
+class JITCodeMapBuilder {
+    WTF_MAKE_NONCOPYABLE(JITCodeMapBuilder);
 public:
+    JITCodeMapBuilder() = default;
     void append(BytecodeIndex bytecodeIndex, CodeLocationLabel<JSEntryPtrTag> codeLocation)
     {
-        m_entries.append({ bytecodeIndex, codeLocation });
+        m_indexes.append(bytecodeIndex);
+        m_codeLocations.append(codeLocation);
     }
 
-    void finish() { m_entries.shrinkToFit(); }
-
-    CodeLocationLabel<JSEntryPtrTag> find(BytecodeIndex bytecodeIndex) const
+    JITCodeMap finalize()
     {
-        auto* entry =
-            binarySearch<Entry, BytecodeIndex>(m_entries,
-                m_entries.size(), bytecodeIndex, [] (Entry* entry) {
-                    return entry->bytecodeIndex();
-                });
-        if (!entry)
-            return CodeLocationLabel<JSEntryPtrTag>();
-        return entry->codeLocation();
+        return JITCodeMap(WTFMove(m_indexes), WTFMove(m_codeLocations));
     }
 
-    explicit operator bool() const { return m_entries.size(); }
-
 private:
-    Vector<Entry> m_entries;
+    Vector<BytecodeIndex> m_indexes;
+    Vector<CodeLocationLabel<JSEntryPtrTag>> m_codeLocations;
 };
 
 } // namespace JSC
index fcf33b2..e5b9856 100644 (file)
@@ -1,3 +1,12 @@
+2020-02-12  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Compact JITCodeMap by storing BytecodeIndex and CodeLocation separately
+        https://bugs.webkit.org/show_bug.cgi?id=207673
+
+        Reviewed by Mark Lam.
+
+        * wtf/MallocPtr.h:
+
 2020-02-12  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r256010.
index f1bbe23..2cbd861 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
 
 // MallocPtr is a smart pointer class that calls fastFree in its destructor.
 // It is intended to be used for pointers where the C++ lifetime semantics
@@ -34,6 +35,7 @@
 namespace WTF {
 
 template<typename T, typename Malloc = FastMalloc> class MallocPtr {
+    WTF_MAKE_NONCOPYABLE(MallocPtr);
 public:
     MallocPtr() = default;