X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..2656c66b5b30d5597e842a751c7f19ad6c2fe31a:/runtime/StructureTransitionTable.h diff --git a/runtime/StructureTransitionTable.h b/runtime/StructureTransitionTable.h index d1dc2d9..27c0a79 100644 --- a/runtime/StructureTransitionTable.h +++ b/runtime/StructureTransitionTable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * 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 COMPUTER, INC. ``AS IS'' AND ANY + * 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 COMPUTER, INC. OR + * 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 @@ -26,22 +26,79 @@ #ifndef StructureTransitionTable_h #define StructureTransitionTable_h -#include "UString.h" +#include "IndexingType.h" +#include "WeakGCMap.h" #include -#include -#include #include -#include +#include namespace JSC { - class Structure; +class JSCell; +class Structure; - struct StructureTransitionTableHash { - typedef std::pair, unsigned> Key; +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(hasArrayStorage(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; + + + struct Hash { + typedef std::pair Key; + static unsigned hash(const Key& p) { - return p.first->existingHash(); + return PtrHash::hash(p.first) + p.second; } static bool equal(const Key& a, const Key& b) @@ -52,19 +109,83 @@ namespace JSC { static const bool safeToCompareToEmptyOrDeleted = true; }; - struct StructureTransitionTableHashTraits { - typedef WTF::HashTraits > FirstTraits; - typedef WTF::GenericHashTraits SecondTraits; - typedef std::pair TraitType; + typedef WeakGCMap TransitionMap; - static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; - static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } +public: + StructureTransitionTable() + : m_data(UsingSingleSlotFlag) + { + } - static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; + ~StructureTransitionTable() + { + if (!isUsingSingleSlot()) { + delete map(); + return; + } - static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } - static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } - }; + WeakImpl* impl = this->weakImpl(); + if (!impl) + return; + WeakSet::deallocate(impl); + } + + inline void add(VM&, 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); + } + + WeakImpl* weakImpl() const + { + ASSERT(isUsingSingleSlot()); + return reinterpret_cast(m_data & ~UsingSingleSlotFlag); + } + + void setMap(TransitionMap* map) + { + ASSERT(isUsingSingleSlot()); + + 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); + + ASSERT(!isUsingSingleSlot()); + } + + Structure* singleTransition() const + { + ASSERT(isUsingSingleSlot()); + if (WeakImpl* impl = this->weakImpl()) { + if (impl->state() == WeakImpl::Live) + return reinterpret_cast(impl->jsValue().asCell()); + } + return 0; + } + + void setSingleTransition(VM&, Structure* structure) + { + ASSERT(isUsingSingleSlot()); + 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; +}; } // namespace JSC