Diff
Modified: branches/safari-609-branch/Source/_javascript_Core/ChangeLog (257032 => 257033)
--- branches/safari-609-branch/Source/_javascript_Core/ChangeLog 2020-02-20 02:59:58 UTC (rev 257032)
+++ branches/safari-609-branch/Source/_javascript_Core/ChangeLog 2020-02-20 03:00:03 UTC (rev 257033)
@@ -1,3 +1,33 @@
+2020-02-19 Alan Coon <alanc...@apple.com>
+
+ Apply patch. rdar://problem/59611919
+
+ 2020-02-19 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Compact StructureTransitionTable
+ https://bugs.webkit.org/show_bug.cgi?id=207616
+
+ Reviewed by Mark Lam.
+
+ Some of StructureTransitionTable are shown as very large HashMap and we can compact it by encoding key.
+ We leverage 48bit pointers and 8byte alignment of UniquedStringImpl* to encode other parameters into it.
+
+ * runtime/Structure.cpp:
+ (JSC::StructureTransitionTable::contains const):
+ (JSC::StructureTransitionTable::get const):
+ (JSC::StructureTransitionTable::add):
+ * runtime/Structure.h:
+ * runtime/StructureTransitionTable.h:
+ (JSC::StructureTransitionTable::Hash::Key::Key):
+ (JSC::StructureTransitionTable::Hash::Key::isHashTableDeletedValue const):
+ (JSC::StructureTransitionTable::Hash::Key::impl const):
+ (JSC::StructureTransitionTable::Hash::Key::isAddition const):
+ (JSC::StructureTransitionTable::Hash::Key::attributes const):
+ (JSC::StructureTransitionTable::Hash::Key::operator==):
+ (JSC::StructureTransitionTable::Hash::Key::operator!=):
+ (JSC::StructureTransitionTable::Hash::hash):
+ (JSC::StructureTransitionTable::Hash::equal):
+
2020-02-18 Simon Fraser <simon.fra...@apple.com>
Unreviewed build fix.
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/Structure.cpp (257032 => 257033)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/Structure.cpp 2020-02-20 02:59:58 UTC (rev 257032)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/Structure.cpp 2020-02-20 03:00:03 UTC (rev 257033)
@@ -93,7 +93,7 @@
Structure* transition = singleTransition();
return transition && transition->m_nameInPrevious == rep && transition->attributesInPrevious() == attributes;
}
- return map()->get(std::make_pair(rep, attributes));
+ return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, false));
}
inline Structure* StructureTransitionTable::get(UniquedStringImpl* rep, unsigned attributes) const
@@ -102,7 +102,7 @@
Structure* transition = singleTransition();
return (transition && transition->m_nameInPrevious == rep && transition->attributesInPrevious() == attributes) ? transition : 0;
}
- return map()->get(std::make_pair(rep, attributes));
+ return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, false));
}
void StructureTransitionTable::add(VM& vm, Structure* structure)
@@ -123,11 +123,7 @@
}
// Add the structure to the map.
-
- // Newer versions of the STL have an std::make_pair function that takes rvalue references.
- // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.
- // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details
- map()->set(std::make_pair(structure->m_nameInPrevious.get(), +structure->attributesInPrevious()), structure);
+ map()->set(StructureTransitionTable::Hash::Key(structure->m_nameInPrevious.get(), +structure->attributesInPrevious(), false), structure);
}
void Structure::dumpStatistics()
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/Structure.h (257032 => 257033)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/Structure.h 2020-02-20 02:59:58 UTC (rev 257032)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/Structure.h 2020-02-20 03:00:03 UTC (rev 257033)
@@ -638,6 +638,7 @@
#define DEFINE_BITFIELD(type, lowerName, upperName, width, offset) \
static constexpr uint32_t s_##lowerName##Shift = offset;\
static constexpr uint32_t s_##lowerName##Mask = ((1 << (width - 1)) | ((1 << (width - 1)) - 1));\
+ static constexpr uint32_t s_bitWidthOf##upperName = width;\
type lowerName() const { return static_cast<type>((m_bitField >> offset) & s_##lowerName##Mask); }\
void set##upperName(type newValue) \
{\
@@ -662,6 +663,8 @@
DEFINE_BITFIELD(bool, isAddingPropertyForTransition, IsAddingPropertyForTransition, 1, 28);
DEFINE_BITFIELD(bool, hasUnderscoreProtoPropertyExcludingOriginalProto, HasUnderscoreProtoPropertyExcludingOriginalProto, 1, 29);
+ static_assert(s_bitWidthOfAttributesInPrevious <= sizeof(TransitionPropertyAttributes) * 8);
+
private:
friend class LLIntOffsetsExtractor;
Modified: branches/safari-609-branch/Source/_javascript_Core/runtime/StructureTransitionTable.h (257032 => 257033)
--- branches/safari-609-branch/Source/_javascript_Core/runtime/StructureTransitionTable.h 2020-02-20 02:59:58 UTC (rev 257032)
+++ branches/safari-609-branch/Source/_javascript_Core/runtime/StructureTransitionTable.h 2020-02-20 03:00:03 UTC (rev 257033)
@@ -52,6 +52,7 @@
Seal,
Freeze
};
+using TransitionPropertyAttributes = uint16_t;
inline unsigned toAttributes(NonPropertyTransition transition)
{
@@ -143,8 +144,74 @@
static constexpr intptr_t UsingSingleSlotFlag = 1;
+#if CPU(ADDRESS64)
struct Hash {
- typedef std::pair<UniquedStringImpl*, unsigned> Key;
+ // Logically, Key is a tuple of (1) UniquedStringImpl*, (2) unsigned attributes, and (3) bool isAddition.
+ // We encode (2) and (3) into (1)'s empty bits since a pointer is 48bit and lower 3 bits are usable because of alignment.
+ struct Key {
+ friend struct Hash;
+ static_assert(WTF_CPU_EFFECTIVE_ADDRESS_WIDTH <= 48);
+ static constexpr uintptr_t isAdditionMask = 1ULL;
+ static constexpr uintptr_t stringMask = ((1ULL << 48) - 1) & (~isAdditionMask);
+ static constexpr unsigned attributesShift = 48;
+ static constexpr uintptr_t hashTableDeletedValue = 0x2;
+ static_assert(sizeof(TransitionPropertyAttributes) * 8 <= 16);
+ static_assert(hashTableDeletedValue < alignof(UniquedStringImpl));
+
+ // Highest 16 bits are for TransitionPropertyAttributes.
+ // Lowest 1 bit is for isAddition flag.
+ // Remaining bits are for UniquedStringImpl*.
+ Key(UniquedStringImpl* impl, unsigned attributes, bool isAddition)
+ : m_encodedData(bitwise_cast<uintptr_t>(impl) | (static_cast<uintptr_t>(attributes) << attributesShift) | (static_cast<uintptr_t>(isAddition) & isAdditionMask))
+ {
+ ASSERT(impl == this->impl());
+ ASSERT(isAddition == this->isAddition());
+ ASSERT(attributes == this->attributes());
+ }
+
+ Key() = default;
+
+ Key(WTF::HashTableDeletedValueType)
+ : m_encodedData(hashTableDeletedValue)
+ { }
+
+ bool isHashTableDeletedValue() const { return m_encodedData == hashTableDeletedValue; }
+
+ UniquedStringImpl* impl() const { return bitwise_cast<UniquedStringImpl*>(m_encodedData & stringMask); }
+ bool isAddition() const { return m_encodedData & isAdditionMask; }
+ unsigned attributes() const { return m_encodedData >> attributesShift; }
+
+ friend bool operator==(const Key& a, const Key& b)
+ {
+ return a.m_encodedData == b.m_encodedData;
+ }
+
+ friend bool operator!=(const Key& a, const Key& b)
+ {
+ return a.m_encodedData != b.m_encodedData;
+ }
+
+ private:
+ uintptr_t m_encodedData { 0 };
+ };
+ using KeyTraits = SimpleClassHashTraits<Key>;
+
+ static unsigned hash(const Key& p)
+ {
+ return IntHash<uintptr_t>::hash(p.m_encodedData);
+ }
+
+ static bool equal(const Key& a, const Key& b)
+ {
+ return a == b;
+ }
+
+ static constexpr bool safeToCompareToEmptyOrDeleted = true;
+ };
+#else
+ struct Hash {
+ using Key = std::tuple<UniquedStringImpl*, unsigned, bool>;
+ using KeyTraits = HashTraits<Key>;
static unsigned hash(const Key& p)
{
@@ -158,8 +225,9 @@
static constexpr bool safeToCompareToEmptyOrDeleted = true;
};
+#endif
- typedef WeakGCMap<Hash::Key, Structure, Hash> TransitionMap;
+ typedef WeakGCMap<Hash::Key, Structure, Hash, Hash::KeyTraits> TransitionMap;
public:
StructureTransitionTable()