X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..4be4e30906bcb8ee30b4d189205cb70bad6707ce:/runtime/StructureTransitionTable.h diff --git a/runtime/StructureTransitionTable.h b/runtime/StructureTransitionTable.h index adebad2..6012020 100644 --- a/runtime/StructureTransitionTable.h +++ b/runtime/StructureTransitionTable.h @@ -26,17 +26,70 @@ #ifndef StructureTransitionTable_h #define StructureTransitionTable_h -#include "UString.h" +#include "IndexingType.h" #include "WeakGCMap.h" #include -#include #include #include +#include namespace JSC { +class JSCell; class Structure; +static const unsigned FirstInternalAttribute = 1 << 6; // Use for transitions that don't have to do with property additions. + +// Support for attributes used to indicate transitions not related to properties. +// If any of these are used, the string portion of the key should be 0. +enum NonPropertyTransition { + AllocateUndecided, + AllocateInt32, + AllocateDouble, + AllocateContiguous, + AllocateArrayStorage, + AllocateSlowPutArrayStorage, + SwitchToSlowPutArrayStorage, + AddIndexedAccessors +}; + +inline unsigned toAttributes(NonPropertyTransition transition) +{ + return transition + FirstInternalAttribute; +} + +inline IndexingType newIndexingType(IndexingType oldType, NonPropertyTransition transition) +{ + switch (transition) { + case AllocateUndecided: + ASSERT(!hasIndexedProperties(oldType)); + return oldType | UndecidedShape; + case AllocateInt32: + ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType)); + return (oldType & ~IndexingShapeMask) | Int32Shape; + case AllocateDouble: + ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType)); + return (oldType & ~IndexingShapeMask) | DoubleShape; + case AllocateContiguous: + ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType)); + return (oldType & ~IndexingShapeMask) | ContiguousShape; + case AllocateArrayStorage: + ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType)); + return (oldType & ~IndexingShapeMask) | ArrayStorageShape; + case AllocateSlowPutArrayStorage: + ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType) || hasContiguous(oldType)); + return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape; + case SwitchToSlowPutArrayStorage: + ASSERT(hasFastArrayStorage(oldType)); + return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape; + case AddIndexedAccessors: + return oldType | MayHaveIndexedAccessors; + default: + RELEASE_ASSERT_NOT_REACHED(); + return oldType; + } +} + class StructureTransitionTable { static const intptr_t UsingSingleSlotFlag = 1; @@ -44,7 +97,10 @@ class StructureTransitionTable { typedef std::pair, unsigned> Key; static unsigned hash(const Key& p) { - return p.first->existingHash(); + unsigned result = p.second; + if (p.first) + result += p.first->existingHash(); + return result; } static bool equal(const Key& a, const Key& b) @@ -55,35 +111,7 @@ class StructureTransitionTable { static const bool safeToCompareToEmptyOrDeleted = true; }; - struct HashTraits { - typedef WTF::HashTraits > FirstTraits; - typedef WTF::GenericHashTraits SecondTraits; - typedef std::pair TraitType; - - static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; - static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } - - static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; - - static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } - 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*); + typedef WeakGCMap TransitionMap; public: StructureTransitionTable() @@ -93,14 +121,18 @@ public: ~StructureTransitionTable() { - if (!isUsingSingleSlot()) + if (!isUsingSingleSlot()) { delete map(); - else - clearSingleTransition(); + return; + } + + WeakImpl* impl = this->weakImpl(); + if (!impl) + return; + WeakSet::deallocate(impl); } - inline void add(JSGlobalData&, Structure*); - inline void remove(Structure*); + inline void add(VM&, Structure*); inline bool contains(StringImpl* rep, unsigned attributes) const; inline Structure* get(StringImpl* rep, unsigned attributes) const; @@ -116,18 +148,18 @@ private: return reinterpret_cast(m_data); } - HandleSlot slot() const + WeakImpl* weakImpl() const { ASSERT(isUsingSingleSlot()); - return reinterpret_cast(m_data & ~UsingSingleSlotFlag); + return reinterpret_cast(m_data & ~UsingSingleSlotFlag); } void setMap(TransitionMap* map) { ASSERT(isUsingSingleSlot()); - if (HandleSlot slot = this->slot()) - HandleHeap::heapFor(slot)->deallocate(slot); + if (WeakImpl* impl = this->weakImpl()) + WeakSet::deallocate(impl); // This implicitly clears the flag that indicates we're using a single transition m_data = reinterpret_cast(map); @@ -138,31 +170,20 @@ private: Structure* singleTransition() const { ASSERT(isUsingSingleSlot()); - if (HandleSlot slot = this->slot()) { - if (*slot) - return reinterpret_cast(slot->asCell()); + if (WeakImpl* impl = this->weakImpl()) { + if (impl->state() == WeakImpl::Live) + return reinterpret_cast(impl->jsValue().asCell()); } return 0; } - void clearSingleTransition() - { - ASSERT(isUsingSingleSlot()); - if (HandleSlot slot = this->slot()) - HandleHeap::heapFor(slot)->deallocate(slot); - } - - void setSingleTransition(JSGlobalData& globalData, Structure* structure) + void setSingleTransition(VM&, 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); + if (WeakImpl* impl = this->weakImpl()) + WeakSet::deallocate(impl); + WeakImpl* impl = WeakSet::allocate(reinterpret_cast(structure)); + m_data = reinterpret_cast(impl) | UsingSingleSlotFlag; } intptr_t m_data;