Title: [245669] trunk/Source/_javascript_Core
Revision
245669
Author
ysuz...@apple.com
Date
2019-05-22 18:47:29 -0700 (Wed, 22 May 2019)

Log Message

[JSC] UnlinkedMetadataTable's offset table should be small
https://bugs.webkit.org/show_bug.cgi?id=197910

Reviewed by Saam Barati.

In Gmail, we found that massive # of UnlinkedMetadataTable (21979 - 24727) exists. Each UnlinkedMetadataTable takes at least 204 bytes
because of large (unsinged) offset table. This patch reduces the size of offset table by introducing 16bit version offset table.
Previously our code for looking up Metadata is like this.

    offset = offsetTable32[opcode]
    metadata = (SomeOp::Metadata*)table[offset] + id

Instead, we introduce uint16_t offset table. The lookup code becomes like this.

    offset = offsetTable16[opcode]
    if (!offset)
        offset = offsetTable32[opcode]
    metadata = (SomeOp::Metadata*)table[offset] + id

We use 0 offset as a marker to indicate that we have 32bit offset table. This is OK since 0 offset does not appear since all the offsets
included in this table is larger than s_offset16TableSize.

32bit offset table is allocated only when the offset exceeds 16bit range. It means that this will be used only when Metadata table is larger
than almost 64KB. Even in Gmail, such MetadataTable is rare, and additional 32bit offset table size does not matter much in this case since
MetadataTable is already so large.

Based on the # of UnlinkedMetadataTables, this optimization should improve Gmail steady state memory by 2MB.

* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* bytecode/MetadataTable.cpp:
(JSC::MetadataTable::~MetadataTable):
(JSC::MetadataTable::destroy):
* bytecode/MetadataTable.h:
(JSC::MetadataTable::ref):
(JSC::MetadataTable::deref):
(JSC::MetadataTable::buffer):
(JSC::MetadataTable::is32Bit const):
(JSC::MetadataTable::offsetTable16 const):
(JSC::MetadataTable::offsetTable32 const):
(JSC::MetadataTable::totalSize const):
(JSC::MetadataTable::getOffset const):
(JSC::MetadataTable::getImpl):
(JSC::MetadataTable::ref const): Deleted.
(JSC::MetadataTable::deref const): Deleted.
* bytecode/Opcode.cpp:
* bytecode/UnlinkedMetadataTable.cpp: Added.
(JSC::UnlinkedMetadataTable::finalize):
* bytecode/UnlinkedMetadataTable.h:
(JSC::UnlinkedMetadataTable::create):
(JSC::UnlinkedMetadataTable::totalSize const):
(JSC::UnlinkedMetadataTable::offsetTableSize const):
(JSC::UnlinkedMetadataTable::preprocessBuffer const):
(JSC::UnlinkedMetadataTable::buffer const):
(JSC::UnlinkedMetadataTable::offsetTable16 const):
(JSC::UnlinkedMetadataTable::offsetTable32 const):
* bytecode/UnlinkedMetadataTableInlines.h:
(JSC::UnlinkedMetadataTable::UnlinkedMetadataTable):
(JSC::UnlinkedMetadataTable::addEntry):
(JSC::UnlinkedMetadataTable::sizeInBytes):
(JSC::UnlinkedMetadataTable::link):
(JSC::UnlinkedMetadataTable::unlink):
(JSC::UnlinkedMetadataTable::finalize): Deleted.
* llint/LowLevelInterpreter.asm:
* runtime/CachedTypes.cpp:
(JSC::CachedMetadataTable::encode):
(JSC::CachedMetadataTable::decode const):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (245668 => 245669)


--- trunk/Source/_javascript_Core/ChangeLog	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-05-23 01:47:29 UTC (rev 245669)
@@ -1,5 +1,75 @@
 2019-05-22  Yusuke Suzuki  <ysuz...@apple.com>
 
+        [JSC] UnlinkedMetadataTable's offset table should be small
+        https://bugs.webkit.org/show_bug.cgi?id=197910
+
+        Reviewed by Saam Barati.
+
+        In Gmail, we found that massive # of UnlinkedMetadataTable (21979 - 24727) exists. Each UnlinkedMetadataTable takes at least 204 bytes
+        because of large (unsinged) offset table. This patch reduces the size of offset table by introducing 16bit version offset table.
+        Previously our code for looking up Metadata is like this.
+
+            offset = offsetTable32[opcode]
+            metadata = (SomeOp::Metadata*)table[offset] + id
+
+        Instead, we introduce uint16_t offset table. The lookup code becomes like this.
+
+            offset = offsetTable16[opcode]
+            if (!offset)
+                offset = offsetTable32[opcode]
+            metadata = (SomeOp::Metadata*)table[offset] + id
+
+        We use 0 offset as a marker to indicate that we have 32bit offset table. This is OK since 0 offset does not appear since all the offsets
+        included in this table is larger than s_offset16TableSize.
+
+        32bit offset table is allocated only when the offset exceeds 16bit range. It means that this will be used only when Metadata table is larger
+        than almost 64KB. Even in Gmail, such MetadataTable is rare, and additional 32bit offset table size does not matter much in this case since
+        MetadataTable is already so large.
+
+        Based on the # of UnlinkedMetadataTables, this optimization should improve Gmail steady state memory by 2MB.
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * bytecode/MetadataTable.cpp:
+        (JSC::MetadataTable::~MetadataTable):
+        (JSC::MetadataTable::destroy):
+        * bytecode/MetadataTable.h:
+        (JSC::MetadataTable::ref):
+        (JSC::MetadataTable::deref):
+        (JSC::MetadataTable::buffer):
+        (JSC::MetadataTable::is32Bit const):
+        (JSC::MetadataTable::offsetTable16 const):
+        (JSC::MetadataTable::offsetTable32 const):
+        (JSC::MetadataTable::totalSize const):
+        (JSC::MetadataTable::getOffset const):
+        (JSC::MetadataTable::getImpl):
+        (JSC::MetadataTable::ref const): Deleted.
+        (JSC::MetadataTable::deref const): Deleted.
+        * bytecode/Opcode.cpp:
+        * bytecode/UnlinkedMetadataTable.cpp: Added.
+        (JSC::UnlinkedMetadataTable::finalize):
+        * bytecode/UnlinkedMetadataTable.h:
+        (JSC::UnlinkedMetadataTable::create):
+        (JSC::UnlinkedMetadataTable::totalSize const):
+        (JSC::UnlinkedMetadataTable::offsetTableSize const):
+        (JSC::UnlinkedMetadataTable::preprocessBuffer const):
+        (JSC::UnlinkedMetadataTable::buffer const):
+        (JSC::UnlinkedMetadataTable::offsetTable16 const):
+        (JSC::UnlinkedMetadataTable::offsetTable32 const):
+        * bytecode/UnlinkedMetadataTableInlines.h:
+        (JSC::UnlinkedMetadataTable::UnlinkedMetadataTable):
+        (JSC::UnlinkedMetadataTable::addEntry):
+        (JSC::UnlinkedMetadataTable::sizeInBytes):
+        (JSC::UnlinkedMetadataTable::link):
+        (JSC::UnlinkedMetadataTable::unlink):
+        (JSC::UnlinkedMetadataTable::finalize): Deleted.
+        * llint/LowLevelInterpreter.asm:
+        * runtime/CachedTypes.cpp:
+        (JSC::CachedMetadataTable::encode):
+        (JSC::CachedMetadataTable::decode const):
+
+2019-05-22  Yusuke Suzuki  <ysuz...@apple.com>
+
         [JSC] ArrayAllocationProfile should not access to butterfly in concurrent compiler
         https://bugs.webkit.org/show_bug.cgi?id=197809
 

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (245668 => 245669)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-05-23 01:47:29 UTC (rev 245669)
@@ -4724,6 +4724,7 @@
 		E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeThreading.cpp; sourceTree = "<group>"; };
 		E18E3A560DF9278C00D90B34 /* VM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = VM.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		E18E3A570DF9278C00D90B34 /* VM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = VM.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
+		E3060128228F978100FAABDF /* UnlinkedMetadataTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedMetadataTable.cpp; sourceTree = "<group>"; };
 		E30677971B8BC6F5003F87F0 /* ModuleLoader.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = ModuleLoader.js; sourceTree = "<group>"; };
 		E31179A92288385D00514B2C /* SymbolTableOrScopeDepth.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymbolTableOrScopeDepth.h; sourceTree = "<group>"; };
 		E31618101EC5FE080006A218 /* DOMAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMAnnotation.h; sourceTree = "<group>"; };
@@ -8067,6 +8068,7 @@
 				14142E541B7973C000F4BF4B /* UnlinkedFunctionExecutable.cpp */,
 				14142E501B796ECE00F4BF4B /* UnlinkedFunctionExecutable.h */,
 				14AD911C1DCA9FA40014F9FE /* UnlinkedGlobalCodeBlock.h */,
+				E3060128228F978100FAABDF /* UnlinkedMetadataTable.cpp */,
 				142D52BE21762958002DB086 /* UnlinkedMetadataTable.h */,
 				142D52BD21762957002DB086 /* UnlinkedMetadataTableInlines.h */,
 				14AD912A1DCAAAB00014F9FE /* UnlinkedModuleProgramCodeBlock.cpp */,

Modified: trunk/Source/_javascript_Core/Sources.txt (245668 => 245669)


--- trunk/Source/_javascript_Core/Sources.txt	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/Sources.txt	2019-05-23 01:47:29 UTC (rev 245669)
@@ -273,6 +273,7 @@
 bytecode/UnlinkedEvalCodeBlock.cpp
 bytecode/UnlinkedFunctionCodeBlock.cpp
 bytecode/UnlinkedFunctionExecutable.cpp
+bytecode/UnlinkedMetadataTable.cpp
 bytecode/UnlinkedModuleProgramCodeBlock.cpp
 bytecode/UnlinkedProgramCodeBlock.cpp
 bytecode/ValueRecovery.cpp

Modified: trunk/Source/_javascript_Core/bytecode/MetadataTable.cpp (245668 => 245669)


--- trunk/Source/_javascript_Core/bytecode/MetadataTable.cpp	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/bytecode/MetadataTable.cpp	2019-05-23 01:47:29 UTC (rev 245669)
@@ -56,11 +56,16 @@
 {
     for (unsigned i = 0; i < NUMBER_OF_BYTECODE_WITH_METADATA; i++)
         getOpcodeType<DeallocTable>(static_cast<OpcodeID>(i), this);
-    Ref<UnlinkedMetadataTable> unlinkedMetadata = WTFMove(linkingData().unlinkedMetadata);
     linkingData().~LinkingData();
+}
+
+void MetadataTable::destroy(MetadataTable* table)
+{
+    Ref<UnlinkedMetadataTable> unlinkedMetadata = WTFMove(table->linkingData().unlinkedMetadata);
+    table->~MetadataTable();
     // Since UnlinkedMetadata::unlink frees the underlying memory of MetadataTable.
     // We need to destroy LinkingData before calling it.
-    unlinkedMetadata->unlink(*this);
+    unlinkedMetadata->unlink(*table);
 }
 
 size_t MetadataTable::sizeInBytes()

Modified: trunk/Source/_javascript_Core/bytecode/MetadataTable.h (245668 => 245669)


--- trunk/Source/_javascript_Core/bytecode/MetadataTable.h	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/bytecode/MetadataTable.h	2019-05-23 01:47:29 UTC (rev 245669)
@@ -63,16 +63,16 @@
 
     size_t sizeInBytes();
 
-    void ref() const
+    void ref()
     {
         ++linkingData().refCount;
     }
 
-    void deref() const
+    void deref()
     {
         unsigned tempRefCount = linkingData().refCount - 1;
         if (!tempRefCount) {
-            this->~MetadataTable();
+            MetadataTable::destroy(this);
             return;
         }
         linkingData().refCount = tempRefCount;
@@ -91,20 +91,37 @@
 private:
     MetadataTable(UnlinkedMetadataTable&);
 
+    UnlinkedMetadataTable::Offset16* offsetTable16() const { return bitwise_cast<UnlinkedMetadataTable::Offset16*>(this); }
+    UnlinkedMetadataTable::Offset32* offsetTable32() const { return bitwise_cast<UnlinkedMetadataTable::Offset32*>(bitwise_cast<uint8_t*>(this) + UnlinkedMetadataTable::s_offset16TableSize); }
+
+    size_t totalSize() const
+    {
+        return getOffset(UnlinkedMetadataTable::s_offsetTableEntries - 1);
+    }
+
     UnlinkedMetadataTable::LinkingData& linkingData() const
     {
         return *bitwise_cast<UnlinkedMetadataTable::LinkingData*>((bitwise_cast<uint8_t*>(this) - sizeof(UnlinkedMetadataTable::LinkingData)));
     }
 
-    UnlinkedMetadataTable::Offset* buffer()
+    void* buffer() { return this; }
+
+    bool is32Bit() const { return !offsetTable16()[0]; }
+
+    ALWAYS_INLINE unsigned getOffset(unsigned i) const
     {
-        return bitwise_cast<UnlinkedMetadataTable::Offset*>(this);
+        unsigned offset = offsetTable16()[i];
+        if (offset)
+            return offset;
+        return offsetTable32()[i];
     }
 
     ALWAYS_INLINE uint8_t* getImpl(unsigned i)
     {
-        return bitwise_cast<uint8_t*>(this) + buffer()[i];
+        return bitwise_cast<uint8_t*>(this) + getOffset(i);
     }
+
+    static void destroy(MetadataTable*);
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/Opcode.cpp (245668 => 245669)


--- trunk/Source/_javascript_Core/bytecode/Opcode.cpp	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.cpp	2019-05-23 01:47:29 UTC (rev 245669)
@@ -203,7 +203,7 @@
 
 #endif
 
-static unsigned metadataSizes[] = {
+static const unsigned metadataSizes[] = {
 
 #define METADATA_SIZE(size) size,
     FOR_EACH_BYTECODE_METADATA_SIZE(METADATA_SIZE)
@@ -211,7 +211,7 @@
 
 };
 
-static unsigned metadataAlignments[] = {
+static const unsigned metadataAlignments[] = {
 
 #define METADATA_ALIGNMENT(size) size,
     FOR_EACH_BYTECODE_METADATA_ALIGNMENT(METADATA_ALIGNMENT)

Added: trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.cpp (0 => 245669)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.cpp	2019-05-23 01:47:29 UTC (rev 245669)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 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 "UnlinkedMetadataTable.h"
+
+#include "BytecodeStructs.h"
+#include "CodeBlock.h"
+#include "JSCInlines.h"
+#include "OpcodeInlines.h"
+#include "UnlinkedMetadataTableInlines.h"
+#include <wtf/FastMalloc.h>
+
+namespace JSC {
+
+#define JSC_ALIGNMENT_CHECK(size) static_assert(size <= UnlinkedMetadataTable::s_maxMetadataAlignment);
+FOR_EACH_BYTECODE_METADATA_ALIGNMENT(JSC_ALIGNMENT_CHECK)
+#undef JSC_ALIGNMENT_CHECK
+
+void UnlinkedMetadataTable::finalize()
+{
+    ASSERT(!m_isFinalized);
+    m_isFinalized = true;
+    if (!m_hasMetadata) {
+        fastFree(m_rawBuffer);
+        m_rawBuffer = nullptr;
+        return;
+    }
+
+    unsigned offset = s_offset16TableSize;
+    {
+        Offset32* buffer = preprocessBuffer();
+        for (unsigned i = 0; i < s_offsetTableEntries - 1; i++) {
+            unsigned numberOfEntries = buffer[i];
+            if (!numberOfEntries) {
+                buffer[i] = offset;
+                continue;
+            }
+            unsigned alignment = metadataAlignment(static_cast<OpcodeID>(i));
+            offset = roundUpToMultipleOf(alignment, offset);
+            ASSERT(alignment <= s_maxMetadataAlignment);
+            buffer[i] = offset;
+            offset += numberOfEntries * metadataSize(static_cast<OpcodeID>(i));
+        }
+        buffer[s_offsetTableEntries - 1] = offset;
+        m_is32Bit = offset > UINT16_MAX;
+    }
+
+    if (m_is32Bit) {
+        m_rawBuffer = reinterpret_cast<uint8_t*>(fastRealloc(m_rawBuffer, s_offset16TableSize + s_offset32TableSize + sizeof(LinkingData)));
+        memmove(m_rawBuffer + sizeof(LinkingData) + s_offset16TableSize, m_rawBuffer + sizeof(LinkingData), s_offset32TableSize);
+        memset(m_rawBuffer + sizeof(LinkingData), 0, s_offset16TableSize);
+        Offset32* buffer = bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData) + s_offset16TableSize);
+        // This adjustment does not break the alignment calculated for metadata in the above loop so long as s_offset32TableSize is rounded with 8.
+        for (unsigned i = 0; i < s_offsetTableEntries; i++)
+            buffer[i] += s_offset32TableSize;
+    } else {
+        Offset32* oldBuffer = bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData));
+        Offset16* buffer = bitwise_cast<Offset16*>(m_rawBuffer + sizeof(LinkingData));
+        for (unsigned i = 0; i < s_offsetTableEntries; i++)
+            buffer[i] = oldBuffer[i];
+        m_rawBuffer = static_cast<uint8_t*>(fastRealloc(m_rawBuffer, s_offset16TableSize + sizeof(LinkingData)));
+    }
+}
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.h (245668 => 245669)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.h	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.h	2019-05-23 01:47:29 UTC (rev 245669)
@@ -37,8 +37,9 @@
     friend class LLIntOffsetsExtractor;
     friend class MetadataTable;
     friend class CachedMetadataTable;
+public:
+    static constexpr unsigned s_maxMetadataAlignment = 8;
 
-public:
     struct LinkingData {
         Ref<UnlinkedMetadataTable> unlinkedMetadata;
         unsigned refCount;
@@ -61,22 +62,63 @@
 
 private:
     UnlinkedMetadataTable();
+    UnlinkedMetadataTable(bool is32Bit);
 
+    static Ref<UnlinkedMetadataTable> create(bool is32Bit)
+    {
+        return adoptRef(*new UnlinkedMetadataTable(is32Bit));
+    }
+
     void unlink(MetadataTable&);
 
     size_t sizeInBytes(MetadataTable&);
 
-    using Offset = unsigned;
+    unsigned totalSize() const
+    {
+        ASSERT(m_isFinalized);
+        if (m_is32Bit)
+            return offsetTable32()[s_offsetTableEntries - 1];
+        return offsetTable16()[s_offsetTableEntries - 1];
+    }
 
+    unsigned offsetTableSize() const
+    {
+        ASSERT(m_isFinalized);
+        if (m_is32Bit)
+            return s_offset16TableSize + s_offset32TableSize;
+        return s_offset16TableSize;
+    }
+
+    using Offset32 = uint32_t;
+    using Offset16 = uint16_t;
+
     static constexpr unsigned s_offsetTableEntries = NUMBER_OF_BYTECODE_WITH_METADATA + 1; // one extra entry for the "end" offset;
-    static constexpr unsigned s_offsetTableSize = s_offsetTableEntries * sizeof(UnlinkedMetadataTable::Offset);
 
-    Offset* buffer() const { return bitwise_cast<Offset*>(bitwise_cast<uint8_t*>(m_rawBuffer) + sizeof(LinkingData)); }
+    // Not to break alignment of 32bit offset table, we round up size with sizeof(Offset32).
+    static constexpr unsigned s_offset16TableSize = roundUpToMultipleOf<sizeof(Offset32)>(s_offsetTableEntries * sizeof(Offset16));
+    // Not to break alignment of the metadata calculated based on the alignment of s_offset16TableSize, s_offset32TableSize must be rounded by 8.
+    // Then, s_offset16TableSize and s_offset16TableSize + s_offset32TableSize offer the same alignment characteristics for subsequent Metadata.
+    static constexpr unsigned s_offset32TableSize = roundUpToMultipleOf<s_maxMetadataAlignment>(s_offsetTableEntries * sizeof(Offset32));
 
+    Offset32* preprocessBuffer() const { return bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData)); }
+    void* buffer() const { return m_rawBuffer + sizeof(LinkingData); }
+
+    Offset16* offsetTable16() const
+    {
+        ASSERT(!m_is32Bit);
+        return bitwise_cast<Offset16*>(m_rawBuffer + sizeof(LinkingData));
+    }
+    Offset32* offsetTable32() const
+    {
+        ASSERT(m_is32Bit);
+        return bitwise_cast<Offset32*>(m_rawBuffer + sizeof(LinkingData) + s_offset16TableSize);
+    }
+
     bool m_hasMetadata : 1;
     bool m_isFinalized : 1;
     bool m_isLinked : 1;
-    void* m_rawBuffer;
+    bool m_is32Bit : 1;
+    uint8_t* m_rawBuffer;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTableInlines.h (245668 => 245669)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTableInlines.h	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTableInlines.h	2019-05-23 01:47:29 UTC (rev 245669)
@@ -35,10 +35,20 @@
     : m_hasMetadata(false)
     , m_isFinalized(false)
     , m_isLinked(false)
-    , m_rawBuffer(fastZeroedMalloc(sizeof(LinkingData) + s_offsetTableSize))
+    , m_is32Bit(false)
+    , m_rawBuffer(static_cast<uint8_t*>(fastZeroedMalloc(sizeof(LinkingData) + s_offset32TableSize)))
 {
 }
 
+ALWAYS_INLINE UnlinkedMetadataTable::UnlinkedMetadataTable(bool is32Bit)
+    : m_hasMetadata(false)
+    , m_isFinalized(false)
+    , m_isLinked(false)
+    , m_is32Bit(is32Bit)
+    , m_rawBuffer(static_cast<uint8_t*>(fastZeroedMalloc(sizeof(LinkingData) + (is32Bit ? s_offset16TableSize + s_offset32TableSize : s_offset16TableSize))))
+{
+}
+
 ALWAYS_INLINE UnlinkedMetadataTable::~UnlinkedMetadataTable()
 {
     ASSERT(!m_isLinked);
@@ -50,7 +60,7 @@
 {
     ASSERT(!m_isFinalized && opcodeID < s_offsetTableEntries - 1);
     m_hasMetadata = true;
-    return buffer()[opcodeID]++;
+    return preprocessBuffer()[opcodeID]++;
 }
 
 ALWAYS_INLINE size_t UnlinkedMetadataTable::sizeInBytes()
@@ -58,7 +68,9 @@
     if (m_isFinalized && !m_hasMetadata)
         return 0;
 
-    return s_offsetTableSize;
+    if (m_is32Bit)
+        return s_offset16TableSize + s_offset32TableSize;
+    return s_offset16TableSize;
 }
 
 ALWAYS_INLINE size_t UnlinkedMetadataTable::sizeInBytes(MetadataTable& metadataTable)
@@ -67,38 +79,16 @@
 
     // In this case, we return the size of the table minus the offset table,
     // which was already accounted for in the UnlinkedCodeBlock.
+    size_t result = totalSize();
     if (metadataTable.buffer() == buffer()) {
         ASSERT(m_isLinked);
-        return buffer()[s_offsetTableEntries - 1] - s_offsetTableSize;
+        if (m_is32Bit)
+            return result - (s_offset16TableSize + s_offset32TableSize);
+        return result - s_offset16TableSize;
     }
-
-    return metadataTable.buffer()[s_offsetTableEntries - 1];
+    return result;
 }
 
-ALWAYS_INLINE void UnlinkedMetadataTable::finalize()
-{
-    ASSERT(!m_isFinalized);
-    m_isFinalized = true;
-    if (!m_hasMetadata) {
-        fastFree(m_rawBuffer);
-        m_rawBuffer = nullptr;
-        return;
-    }
-
-    unsigned offset = s_offsetTableSize;
-    for (unsigned i = 0; i < s_offsetTableEntries - 1; i++) {
-        unsigned numberOfEntries = buffer()[i];
-
-        if (numberOfEntries > 0) {
-            offset = roundUpToMultipleOf(metadataAlignment(static_cast<OpcodeID>(i)), offset);
-            buffer()[i] = offset;
-            offset += numberOfEntries * metadataSize(static_cast<OpcodeID>(i));
-        } else
-            buffer()[i] = offset;
-    }
-    buffer()[s_offsetTableEntries - 1] = offset;
-}
-
 ALWAYS_INLINE RefPtr<MetadataTable> UnlinkedMetadataTable::link()
 {
     ASSERT(m_isFinalized);
@@ -106,7 +96,8 @@
     if (!m_hasMetadata)
         return nullptr;
 
-    unsigned totalSize = buffer()[s_offsetTableEntries - 1];
+    unsigned totalSize = this->totalSize();
+    unsigned offsetTableSize = this->offsetTableSize();
     uint8_t* buffer;
     if (!m_isLinked) {
         m_isLinked = true;
@@ -113,9 +104,9 @@
         m_rawBuffer = buffer = reinterpret_cast<uint8_t*>(fastRealloc(m_rawBuffer, sizeof(LinkingData) + totalSize));
     } else {
         buffer = reinterpret_cast<uint8_t*>(fastMalloc(sizeof(LinkingData) + totalSize));
-        memcpy(buffer, m_rawBuffer, sizeof(LinkingData) + s_offsetTableSize);
+        memcpy(buffer, m_rawBuffer, sizeof(LinkingData) + offsetTableSize);
     }
-    memset(buffer + sizeof(LinkingData) + s_offsetTableSize, 0, totalSize - s_offsetTableSize);
+    memset(buffer + sizeof(LinkingData) + offsetTableSize, 0, totalSize - offsetTableSize);
     return adoptRef(*new (buffer + sizeof(LinkingData)) MetadataTable(*this));
 }
 
@@ -128,7 +119,7 @@
     if (metadataTable.buffer() == buffer()) {
         ASSERT(m_isLinked);
         m_isLinked = false;
-        m_rawBuffer = fastRealloc(m_rawBuffer, sizeof(LinkingData) + s_offsetTableSize);
+        m_rawBuffer = static_cast<uint8_t*>(fastRealloc(m_rawBuffer, sizeof(LinkingData) + offsetTableSize()));
         return;
     }
     fastFree(&metadataTable.linkingData());

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (245668 => 245669)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2019-05-23 01:47:29 UTC (rev 245669)
@@ -181,6 +181,9 @@
 const FirstArgumentOffset = ThisArgumentOffset + SlotSize
 const CallFrameHeaderSize = ThisArgumentOffset
 
+const MetadataOffsetTable16Offset = 0
+const MetadataOffsetTable32Offset = constexpr UnlinkedMetadataTable::s_offset16TableSize
+
 # Some value representation constants.
 if JSVALUE64
     const TagBitTypeOther = constexpr TagBitTypeOther
@@ -336,7 +339,10 @@
 end
 
 macro metadata(size, opcode, dst, scratch)
-    loadi constexpr %opcode%::opcodeID * 4[metadataTable], dst # offset = metadataTable<unsigned*>[opcodeID]
+    loadh (constexpr %opcode%::opcodeID * 2 + MetadataOffsetTable16Offset)[metadataTable], dst # offset = metadataTable<uint16_t*>[opcodeID]
+    btinz dst, .setUpOffset
+    loadi (constexpr %opcode%::opcodeID * 4 + MetadataOffsetTable32Offset)[metadataTable], dst # offset = metadataTable<uint32_t*>[opcodeID]
+.setUpOffset:
     getu(size, opcode, m_metadataID, scratch) # scratch = bytecode.m_metadataID
     muli sizeof %opcode%::Metadata, scratch # scratch *= sizeof(Op::Metadata)
     addi scratch, dst # offset += scratch

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.cpp (245668 => 245669)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2019-05-23 01:39:47 UTC (rev 245668)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2019-05-23 01:47:29 UTC (rev 245669)
@@ -1348,23 +1348,35 @@
         m_hasMetadata = metadataTable.m_hasMetadata;
         if (!m_hasMetadata)
             return;
-        for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
-            m_metadata[i] = metadataTable.buffer()[i];
+        m_is32Bit = metadataTable.m_is32Bit;
+        if (m_is32Bit) {
+            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
+                m_metadata[i] = metadataTable.offsetTable32()[i];
+        } else {
+            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
+                m_metadata[i] = metadataTable.offsetTable16()[i];
+        }
     }
 
     Ref<UnlinkedMetadataTable> decode(Decoder&) const
     {
-        Ref<UnlinkedMetadataTable> metadataTable = UnlinkedMetadataTable::create();
+        Ref<UnlinkedMetadataTable> metadataTable = UnlinkedMetadataTable::create(m_is32Bit);
         metadataTable->m_isFinalized = true;
         metadataTable->m_isLinked = false;
         metadataTable->m_hasMetadata = m_hasMetadata;
-        for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
-            metadataTable->buffer()[i] = m_metadata[i];
+        if (m_is32Bit) {
+            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
+                metadataTable->offsetTable32()[i] = m_metadata[i];
+        } else {
+            for (unsigned i = UnlinkedMetadataTable::s_offsetTableEntries; i--;)
+                metadataTable->offsetTable16()[i] = m_metadata[i];
+        }
         return metadataTable;
     }
 
 private:
     bool m_hasMetadata;
+    bool m_is32Bit;
     std::array<unsigned, UnlinkedMetadataTable::s_offsetTableEntries> m_metadata;
 };
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to