Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (237986 => 237987)
--- trunk/Source/_javascript_Core/ChangeLog 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-11-08 15:42:10 UTC (rev 237987)
@@ -1,3 +1,53 @@
+2018-11-07 Yusuke Suzuki <[email protected]>
+
+ Consider removing double load for accessing the MetadataTable from LLInt
+ https://bugs.webkit.org/show_bug.cgi?id=190933
+
+ Reviewed by Keith Miller.
+
+ This patch removes double load for accesses to MetadataTable from LLInt.
+ MetadataTable is now specially RefCounted class, which has interesting memory layout.
+ When refcount becomes 0, MetadataTable asks UnlinkedMetadataTable to destroy itself.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::finishCreation):
+ (JSC::CodeBlock::estimatedSize):
+ (JSC::CodeBlock::visitChildren):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::metadata):
+ * bytecode/CodeBlockInlines.h:
+ (JSC::CodeBlock::forEachValueProfile):
+ (JSC::CodeBlock::forEachArrayProfile):
+ (JSC::CodeBlock::forEachArrayAllocationProfile):
+ (JSC::CodeBlock::forEachObjectAllocationProfile):
+ (JSC::CodeBlock::forEachLLIntCallLinkInfo):
+ * bytecode/MetadataTable.cpp:
+ (JSC::MetadataTable::MetadataTable):
+ (JSC::MetadataTable::~MetadataTable):
+ (JSC::MetadataTable::sizeInBytes):
+ * bytecode/MetadataTable.h:
+ (JSC::MetadataTable::get):
+ (JSC::MetadataTable::forEach):
+ (JSC::MetadataTable::ref const):
+ (JSC::MetadataTable::deref const):
+ (JSC::MetadataTable::refCount const):
+ (JSC::MetadataTable::hasOneRef const):
+ (JSC::MetadataTable::buffer):
+ (JSC::MetadataTable::linkingData const):
+ (JSC::MetadataTable::getImpl):
+ * bytecode/UnlinkedMetadataTable.h:
+ (JSC::UnlinkedMetadataTable::buffer const):
+ * bytecode/UnlinkedMetadataTableInlines.h:
+ (JSC::UnlinkedMetadataTable::UnlinkedMetadataTable):
+ (JSC::UnlinkedMetadataTable::~UnlinkedMetadataTable):
+ (JSC::UnlinkedMetadataTable::addEntry):
+ (JSC::UnlinkedMetadataTable::sizeInBytes):
+ (JSC::UnlinkedMetadataTable::finalize):
+ (JSC::UnlinkedMetadataTable::link):
+ (JSC::UnlinkedMetadataTable::unlink):
+ * llint/LowLevelInterpreter.asm:
+ * llint/LowLevelInterpreter32_64.asm:
+
2018-11-07 Caio Lima <[email protected]>
[BigInt] Add support to BigInt into ValueAdd
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (237986 => 237987)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2018-11-08 15:42:10 UTC (rev 237987)
@@ -813,7 +813,8 @@
if (Options::dumpGeneratedBytecodes())
dumpBytecode();
- heap()->reportExtraMemoryAllocated(m_metadata->sizeInBytes());
+ if (m_metadata)
+ vm.heap.reportExtraMemoryAllocated(m_metadata->sizeInBytes());
return true;
}
@@ -954,7 +955,9 @@
size_t CodeBlock::estimatedSize(JSCell* cell, VM& vm)
{
CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
- size_t extraMemoryAllocated = thisObject->m_metadata->sizeInBytes();
+ size_t extraMemoryAllocated = 0;
+ if (thisObject->m_metadata)
+ extraMemoryAllocated += thisObject->m_metadata->sizeInBytes();
if (thisObject->m_jitCode)
extraMemoryAllocated += thisObject->m_jitCode->size();
return Base::estimatedSize(cell, vm) + extraMemoryAllocated;
@@ -975,9 +978,11 @@
if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
visitor.appendUnbarriered(otherBlock);
- size_t extraMemory = m_metadata->sizeInBytes();
+ size_t extraMemory = 0;
+ if (m_metadata)
+ extraMemory += m_metadata->sizeInBytes();
if (m_jitCode)
- extraMemory = m_jitCode->size();
+ extraMemory += m_jitCode->size();
visitor.reportExtraMemoryVisited(extraMemory);
stronglyVisitStrongReferences(locker, visitor);
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (237986 => 237987)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2018-11-08 15:42:10 UTC (rev 237987)
@@ -859,6 +859,7 @@
template<typename Metadata>
Metadata& metadata(OpcodeID opcodeID, unsigned metadataID)
{
+ ASSERT(m_metadata);
return reinterpret_cast<Metadata*>(m_metadata->get(opcodeID))[metadataID];
}
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlockInlines.h (237986 => 237987)
--- trunk/Source/_javascript_Core/bytecode/CodeBlockInlines.h 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlockInlines.h 2018-11-08 15:42:10 UTC (rev 237987)
@@ -37,12 +37,15 @@
for (unsigned i = 0; i < numberOfArgumentValueProfiles(); ++i)
func(valueProfileForArgument(i));
+ if (m_metadata) {
#define VISIT(__op) \
m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.profile); });
-FOR_EACH_OPCODE_WITH_VALUE_PROFILE(VISIT)
+ FOR_EACH_OPCODE_WITH_VALUE_PROFILE(VISIT)
#undef VISIT
+ }
+
}
template<typename Functor>
@@ -51,50 +54,58 @@
for (auto& arrayProfile : m_arrayProfiles)
func(arrayProfile);
- m_metadata->forEach<OpGetById>([&] (auto& metadata) {
- if (metadata.mode == GetByIdMode::ArrayLength)
- func(metadata.modeMetadata.arrayLengthMode.arrayProfile);
- });
+ if (m_metadata) {
+ m_metadata->forEach<OpGetById>([&] (auto& metadata) {
+ if (metadata.mode == GetByIdMode::ArrayLength)
+ func(metadata.modeMetadata.arrayLengthMode.arrayProfile);
+ });
#define VISIT(__op) \
m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.arrayProfile); });
-FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(VISIT)
+ FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(VISIT)
#undef VISIT
+ }
}
template<typename Functor>
void CodeBlock::forEachArrayAllocationProfile(const Functor& func)
{
+ if (m_metadata) {
#define VISIT(__op) \
m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.arrayAllocationProfile); });
-FOR_EACH_OPCODE_WITH_ARRAY_ALLOCATION_PROFILE(VISIT)
+ FOR_EACH_OPCODE_WITH_ARRAY_ALLOCATION_PROFILE(VISIT)
#undef VISIT
+ }
}
template<typename Functor>
void CodeBlock::forEachObjectAllocationProfile(const Functor& func)
{
+ if (m_metadata) {
#define VISIT(__op) \
m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.objectAllocationProfile); });
-FOR_EACH_OPCODE_WITH_OBJECT_ALLOCATION_PROFILE(VISIT)
+ FOR_EACH_OPCODE_WITH_OBJECT_ALLOCATION_PROFILE(VISIT)
#undef VISIT
+ }
}
template<typename Functor>
void CodeBlock::forEachLLIntCallLinkInfo(const Functor& func)
{
+ if (m_metadata) {
#define VISIT(__op) \
m_metadata->forEach<__op>([&] (auto& metadata) { func(metadata.callLinkInfo); });
-FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(VISIT)
+ FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(VISIT)
#undef VISIT
+ }
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/MetadataTable.cpp (237986 => 237987)
--- trunk/Source/_javascript_Core/bytecode/MetadataTable.cpp 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/bytecode/MetadataTable.cpp 2018-11-08 15:42:10 UTC (rev 237987)
@@ -33,10 +33,12 @@
namespace JSC {
-MetadataTable::MetadataTable(UnlinkedMetadataTable& unlinkedMetadata, UnlinkedMetadataTable::Offset* buffer)
- : m_buffer(buffer)
- , m_unlinkedMetadata(unlinkedMetadata)
+MetadataTable::MetadataTable(UnlinkedMetadataTable& unlinkedMetadata)
{
+ linkingData() = UnlinkedMetadataTable::LinkingData {
+ &unlinkedMetadata,
+ 1,
+ };
}
struct DeallocTable {
@@ -53,12 +55,12 @@
{
for (unsigned i = 0; i < NUMBER_OF_BYTECODE_WITH_METADATA; i++)
getOpcodeType<DeallocTable>(static_cast<OpcodeID>(i), this);
- m_unlinkedMetadata.unlink(*this);
+ linkingData().unlinkedMetadata->unlink(*this);
}
size_t MetadataTable::sizeInBytes()
{
- return m_unlinkedMetadata.sizeInBytes(*this);
+ return linkingData().unlinkedMetadata->sizeInBytes(*this);
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/MetadataTable.h (237986 => 237987)
--- trunk/Source/_javascript_Core/bytecode/MetadataTable.h 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/bytecode/MetadataTable.h 2018-11-08 15:42:10 UTC (rev 237987)
@@ -34,26 +34,27 @@
class CodeBlock;
-class MetadataTable : public RefCounted<MetadataTable> {
+// MetadataTable has a bit strange memory layout for LLInt optimization.
+// [UnlinkedMetadataTable::LinkingData][MetadataTable]
+// ^
+// The pointer of MetadataTable points at this address.
+class MetadataTable {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(MetadataTable);
friend class LLIntOffsetsExtractor;
friend class UnlinkedMetadataTable;
-
public:
~MetadataTable();
ALWAYS_INLINE Instruction::Metadata* get(OpcodeID opcodeID)
{
- ASSERT(m_buffer && opcodeID < NUMBER_OF_BYTECODE_WITH_METADATA);
+ ASSERT(opcodeID < NUMBER_OF_BYTECODE_WITH_METADATA);
return reinterpret_cast<Instruction::Metadata*>(getImpl(opcodeID));
}
-
template<typename Op, typename Functor>
ALWAYS_INLINE void forEach(const Functor& func)
{
- if (!m_buffer)
- return;
-
auto* metadata = reinterpret_cast<typename Op::Metadata*>(get(Op::opcodeID));
auto* end = reinterpret_cast<typename Op::Metadata*>(getImpl(Op::opcodeID + 1));
for (; metadata + 1 <= end; ++metadata)
@@ -62,16 +63,48 @@
size_t sizeInBytes();
+ void ref() const
+ {
+ ++linkingData().refCount;
+ }
+
+ void deref() const
+ {
+ unsigned tempRefCount = linkingData().refCount - 1;
+ if (!tempRefCount) {
+ this->~MetadataTable();
+ return;
+ }
+ linkingData().refCount = tempRefCount;
+ }
+
+ unsigned refCount() const
+ {
+ return linkingData().refCount;
+ }
+
+ unsigned hasOneRef() const
+ {
+ return refCount() == 1;
+ }
+
+ UnlinkedMetadataTable::Offset* buffer()
+ {
+ return bitwise_cast<UnlinkedMetadataTable::Offset*>(this);
+ }
+
private:
- MetadataTable(UnlinkedMetadataTable&, UnlinkedMetadataTable::Offset*);
+ MetadataTable(UnlinkedMetadataTable&);
+ UnlinkedMetadataTable::LinkingData& linkingData() const
+ {
+ return *bitwise_cast<UnlinkedMetadataTable::LinkingData*>((bitwise_cast<uint8_t*>(this) - sizeof(UnlinkedMetadataTable::LinkingData)));
+ }
+
ALWAYS_INLINE uint8_t* getImpl(unsigned i)
{
- return reinterpret_cast<uint8_t*>(m_buffer) + m_buffer[i];
+ return bitwise_cast<uint8_t*>(this) + buffer()[i];
}
-
- UnlinkedMetadataTable::Offset* m_buffer;
- UnlinkedMetadataTable& m_unlinkedMetadata;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.h (237986 => 237987)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.h 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTable.h 2018-11-08 15:42:10 UTC (rev 237987)
@@ -37,6 +37,11 @@
friend class MetadataTable;
public:
+ struct LinkingData {
+ UnlinkedMetadataTable* unlinkedMetadata;
+ unsigned refCount;
+ };
+
UnlinkedMetadataTable();
~UnlinkedMetadataTable();
@@ -46,7 +51,7 @@
void finalize();
- Ref<MetadataTable> link();
+ RefPtr<MetadataTable> link();
private:
void unlink(MetadataTable&);
@@ -58,10 +63,12 @@
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)); }
+
bool m_hasMetadata : 1;
bool m_isFinalized : 1;
bool m_isLinked : 1;
- Offset* m_buffer;
+ void* m_rawBuffer;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTableInlines.h (237986 => 237987)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTableInlines.h 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedMetadataTableInlines.h 2018-11-08 15:42:10 UTC (rev 237987)
@@ -36,7 +36,7 @@
m_hasMetadata = false;
m_isFinalized = false;
m_isLinked = false;
- m_buffer = reinterpret_cast<Offset*>(fastCalloc(s_offsetTableEntries, sizeof(UnlinkedMetadataTable::Offset)));
+ m_rawBuffer = fastZeroedMalloc(sizeof(LinkingData) + s_offsetTableSize);
}
ALWAYS_INLINE UnlinkedMetadataTable::~UnlinkedMetadataTable()
@@ -43,7 +43,7 @@
{
ASSERT(!m_isLinked);
if (m_hasMetadata || !m_isFinalized)
- fastFree(m_buffer);
+ fastFree(m_rawBuffer);
}
ALWAYS_INLINE unsigned UnlinkedMetadataTable::addEntry(OpcodeID opcodeID)
@@ -50,7 +50,7 @@
{
ASSERT(!m_isFinalized && opcodeID < s_offsetTableEntries - 1);
m_hasMetadata = true;
- return m_buffer[opcodeID]++;
+ return buffer()[opcodeID]++;
}
ALWAYS_INLINE size_t UnlinkedMetadataTable::sizeInBytes()
@@ -65,17 +65,14 @@
{
ASSERT(m_isFinalized);
- if (!metadataTable.m_buffer)
- return 0;
-
// In this case, we return the size of the table minus the offset table,
// which was already accounted for in the UnlinkedCodeBlock.
- if (metadataTable.m_buffer == m_buffer) {
+ if (metadataTable.buffer() == buffer()) {
ASSERT(m_isLinked);
- return m_buffer[s_offsetTableEntries - 1] - s_offsetTableSize;
+ return buffer()[s_offsetTableEntries - 1] - s_offsetTableSize;
}
- return metadataTable.m_buffer[s_offsetTableEntries - 1];
+ return metadataTable.buffer()[s_offsetTableEntries - 1];
}
ALWAYS_INLINE void UnlinkedMetadataTable::finalize()
@@ -83,45 +80,45 @@
ASSERT(!m_isFinalized);
m_isFinalized = true;
if (!m_hasMetadata) {
- fastFree(m_buffer);
- m_buffer = nullptr;
+ fastFree(m_rawBuffer);
+ m_rawBuffer = nullptr;
return;
}
unsigned offset = s_offsetTableSize;
for (unsigned i = 0; i < s_offsetTableEntries - 1; i++) {
- unsigned numberOfEntries = m_buffer[i];
+ unsigned numberOfEntries = buffer()[i];
if (numberOfEntries > 0) {
#if CPU(NEEDS_ALIGNED_ACCESS)
offset = roundUpToMultipleOf(metadataAlignment(static_cast<OpcodeID>(i)), offset);
#endif
- m_buffer[i] = offset;
+ buffer()[i] = offset;
offset += numberOfEntries * metadataSize(static_cast<OpcodeID>(i));
} else
- m_buffer[i] = offset;
+ buffer()[i] = offset;
}
- m_buffer[s_offsetTableEntries - 1] = offset;
+ buffer()[s_offsetTableEntries - 1] = offset;
}
-ALWAYS_INLINE Ref<MetadataTable> UnlinkedMetadataTable::link()
+ALWAYS_INLINE RefPtr<MetadataTable> UnlinkedMetadataTable::link()
{
ASSERT(m_isFinalized);
if (!m_hasMetadata)
- return adoptRef(*new MetadataTable(*this, nullptr));
+ return nullptr;
- unsigned totalSize = m_buffer[s_offsetTableEntries - 1];
- Offset* buffer;
+ unsigned totalSize = buffer()[s_offsetTableEntries - 1];
+ uint8_t* buffer;
if (!m_isLinked) {
m_isLinked = true;
- buffer = m_buffer = reinterpret_cast<Offset*>(fastRealloc(m_buffer, totalSize));
+ m_rawBuffer = buffer = reinterpret_cast<uint8_t*>(fastRealloc(m_rawBuffer, sizeof(LinkingData) + totalSize));
} else {
- buffer = reinterpret_cast<Offset*>(fastMalloc(totalSize));
- memcpy(buffer, m_buffer, s_offsetTableSize);
+ buffer = reinterpret_cast<uint8_t*>(fastMalloc(sizeof(LinkingData) + totalSize));
+ memcpy(buffer, m_rawBuffer, sizeof(LinkingData) + s_offsetTableSize);
}
- memset(reinterpret_cast<uint8_t*>(buffer) + s_offsetTableSize, 0, totalSize - s_offsetTableSize);
- return adoptRef(*new MetadataTable(*this, buffer));
+ memset(buffer + sizeof(LinkingData) + s_offsetTableSize, 0, totalSize - s_offsetTableSize);
+ return adoptRef(*new (buffer + sizeof(LinkingData)) MetadataTable(*this));
}
ALWAYS_INLINE void UnlinkedMetadataTable::unlink(MetadataTable& metadataTable)
@@ -130,12 +127,13 @@
if (!m_hasMetadata)
return;
- if (metadataTable.m_buffer == m_buffer) {
+ if (metadataTable.buffer() == buffer()) {
ASSERT(m_isLinked);
m_isLinked = false;
- m_buffer = reinterpret_cast<Offset*>(fastRealloc(m_buffer, s_offsetTableSize));
- } else if (metadataTable.m_buffer)
- fastFree(metadataTable.m_buffer);
+ m_rawBuffer = fastRealloc(m_rawBuffer, sizeof(LinkingData) + s_offsetTableSize);
+ return;
+ }
+ fastFree(&metadataTable.linkingData());
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (237986 => 237987)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2018-11-08 15:42:10 UTC (rev 237987)
@@ -1194,10 +1194,7 @@
move t0, sp
end
- # FIXME: cleanup double load
- # https://bugs.webkit.org/show_bug.cgi?id=190933
loadp CodeBlock::m_metadata[t1], metadataTable
- loadp MetadataTable::m_buffer[metadataTable], metadataTable
if JSVALUE64
move TagTypeNumber, tagTypeNumber
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (237986 => 237987)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2018-11-08 15:36:05 UTC (rev 237986)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2018-11-08 15:42:10 UTC (rev 237987)
@@ -1955,10 +1955,7 @@
# restore metadataTable since we don't restore callee saves for CLoop during unwinding
loadp CodeBlock[cfr], t1
- # FIXME: cleanup double load
- # https://bugs.webkit.org/show_bug.cgi?id=190933
loadp CodeBlock::m_metadata[t1], metadataTable
- loadp MetadataTable::m_buffer[metadataTable], metadataTable
loadi VM::targetInterpreterPCForThrow[t3], PC