X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..14957cd040308e3eeec43d26bae5d76da13fcd85:/runtime/StructureTransitionTable.h diff --git a/runtime/StructureTransitionTable.h b/runtime/StructureTransitionTable.h index d1dc2d9..adebad2 100644 --- a/runtime/StructureTransitionTable.h +++ b/runtime/StructureTransitionTable.h @@ -27,18 +27,21 @@ #define StructureTransitionTable_h #include "UString.h" +#include "WeakGCMap.h" #include -#include #include #include #include namespace JSC { - class Structure; +class Structure; - struct StructureTransitionTableHash { - typedef std::pair, unsigned> Key; +class StructureTransitionTable { + static const intptr_t UsingSingleSlotFlag = 1; + + struct Hash { + typedef std::pair, unsigned> Key; static unsigned hash(const Key& p) { return p.first->existingHash(); @@ -52,8 +55,8 @@ namespace JSC { static const bool safeToCompareToEmptyOrDeleted = true; }; - struct StructureTransitionTableHashTraits { - typedef WTF::HashTraits > FirstTraits; + struct HashTraits { + typedef WTF::HashTraits > FirstTraits; typedef WTF::GenericHashTraits SecondTraits; typedef std::pair TraitType; @@ -66,6 +69,105 @@ namespace JSC { static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } }; + struct WeakGCMapFinalizerCallback { + static void* finalizerContextFor(Hash::Key) + { + return 0; + } + + static inline Hash::Key keyForFinalizer(void* context, Structure* structure) + { + return keyForWeakGCMapFinalizer(context, structure); + } + }; + + typedef WeakGCMap TransitionMap; + + static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*); + +public: + StructureTransitionTable() + : m_data(UsingSingleSlotFlag) + { + } + + ~StructureTransitionTable() + { + if (!isUsingSingleSlot()) + delete map(); + else + clearSingleTransition(); + } + + inline void add(JSGlobalData&, Structure*); + inline void remove(Structure*); + inline bool contains(StringImpl* rep, unsigned attributes) const; + inline Structure* get(StringImpl* rep, unsigned attributes) const; + +private: + bool isUsingSingleSlot() const + { + return m_data & UsingSingleSlotFlag; + } + + TransitionMap* map() const + { + ASSERT(!isUsingSingleSlot()); + return reinterpret_cast(m_data); + } + + HandleSlot slot() const + { + ASSERT(isUsingSingleSlot()); + return reinterpret_cast(m_data & ~UsingSingleSlotFlag); + } + + void setMap(TransitionMap* map) + { + ASSERT(isUsingSingleSlot()); + + if (HandleSlot slot = this->slot()) + HandleHeap::heapFor(slot)->deallocate(slot); + + // This implicitly clears the flag that indicates we're using a single transition + m_data = reinterpret_cast(map); + + ASSERT(!isUsingSingleSlot()); + } + + Structure* singleTransition() const + { + ASSERT(isUsingSingleSlot()); + if (HandleSlot slot = this->slot()) { + if (*slot) + return reinterpret_cast(slot->asCell()); + } + return 0; + } + + void clearSingleTransition() + { + ASSERT(isUsingSingleSlot()); + if (HandleSlot slot = this->slot()) + HandleHeap::heapFor(slot)->deallocate(slot); + } + + void setSingleTransition(JSGlobalData& globalData, Structure* structure) + { + ASSERT(isUsingSingleSlot()); + HandleSlot slot = this->slot(); + if (!slot) { + slot = globalData.allocateGlobalHandle(); + HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0); + m_data = reinterpret_cast(slot) | UsingSingleSlotFlag; + } + HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast(structure)); + *slot = reinterpret_cast(structure); + } + + intptr_t m_data; +}; + } // namespace JSC #endif // StructureTransitionTable_h