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;
};