18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 2231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef StructureTransitionTable_h 27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#define StructureTransitionTable_h 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "UString.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashFunctions.h> 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashMap.h> 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashTraits.h> 33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/PtrAndFlags.h> 34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/OwnPtr.h> 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/RefPtr.h> 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC { 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project class Structure; 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project struct StructureTransitionTableHash { 42231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block typedef std::pair<RefPtr<UString::Rep>, unsigned> Key; 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static unsigned hash(const Key& p) 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 45d0825bca7fe65beaee391d30da42e937db621564Steve Block return p.first->existingHash(); 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static bool equal(const Key& a, const Key& b) 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return a == b; 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static const bool safeToCompareToEmptyOrDeleted = true; 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project }; 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 56635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project struct StructureTransitionTableHashTraits { 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits; 58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block typedef WTF::GenericHashTraits<unsigned> SecondTraits; 59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType; 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; 62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project }; 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block class StructureTransitionTable { 71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block typedef std::pair<Structure*, Structure*> Transition; 72d0825bca7fe65beaee391d30da42e937db621564Steve Block typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable; 73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block public: 74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block StructureTransitionTable() { 75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_transitions.m_singleTransition.set(0); 76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_transitions.m_singleTransition.setFlag(usingSingleSlot); 77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 78231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ~StructureTransitionTable() { 80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!usingSingleTransitionSlot()) 81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block delete table(); 82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 84231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // The contains and get methods accept imprecise matches, so if an unspecialised transition exists 85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // for the given key they will consider that transition to be a match. If a specialised transition 86231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // exists and it matches the provided specificValue, get will return the specific transition. 87231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue); 88231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const; 89231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block inline bool hasTransition(const StructureTransitionTableHash::Key& key) const; 90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue) 91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block { 92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (usingSingleTransitionSlot()) { 93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(contains(key, specificValue)); 94231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block setSingleTransition(0); 95231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block TransitionTable::iterator find = table()->find(key); 98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!specificValue) 99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block find->second.first = 0; 100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block else 101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block find->second.second = 0; 102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!find->second.first && !find->second.second) 103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block table()->remove(find); 104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue) 106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block { 107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (usingSingleTransitionSlot()) { 108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!singleTransition()) { 109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block setSingleTransition(structure); 110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block reifySingleTransition(); 113231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!specificValue) { 115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block TransitionTable::iterator find = table()->find(key); 116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (find == table()->end()) 117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block table()->add(key, Transition(structure, 0)); 118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block else 119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block find->second.first = structure; 120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } else { 121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // If we're adding a transition to a specific value, then there cannot be 122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // an existing transition 123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(!table()->contains(key)); 124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block table()->add(key, Transition(0, structure)); 125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block private: 129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block TransitionTable* table() const { ASSERT(!usingSingleTransitionSlot()); return m_transitions.m_table; } 130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Structure* singleTransition() const { 131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(usingSingleTransitionSlot()); 132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return m_transitions.m_singleTransition.get(); 133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block bool usingSingleTransitionSlot() const { return m_transitions.m_singleTransition.isFlagSet(usingSingleSlot); } 135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block void setSingleTransition(Structure* structure) 136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block { 137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(usingSingleTransitionSlot()); 138231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_transitions.m_singleTransition.set(structure); 139231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block void setTransitionTable(TransitionTable* table) 142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block { 143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(usingSingleTransitionSlot()); 144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#ifndef NDEBUG 145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block setSingleTransition(0); 146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_transitions.m_table = table; 148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // This implicitly clears the flag that indicates we're using a single transition 149231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(!usingSingleTransitionSlot()); 150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block inline void reifySingleTransition(); 152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block enum UsingSingleSlot { 154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block usingSingleSlot 155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block }; 156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Last bit indicates whether we are using the single transition optimisation 157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block union { 158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block TransitionTable* m_table; 159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block PtrAndFlagsBase<Structure, UsingSingleSlot> m_singleTransition; 160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } m_transitions; 161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block }; 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace JSC 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif // StructureTransitionTable_h 166