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" 302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "WeakGCMap.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashFunctions.h> 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashTraits.h> 33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/OwnPtr.h> 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/RefPtr.h> 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC { 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass Structure; 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass StructureTransitionTable { 4181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch static const intptr_t UsingSingleSlotFlag = 1; 4281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 4381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch struct Hash { 44f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick typedef std::pair<RefPtr<StringImpl>, unsigned> Key; 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static unsigned hash(const Key& p) 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 47d0825bca7fe65beaee391d30da42e937db621564Steve Block return p.first->existingHash(); 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static bool equal(const Key& a, const Key& b) 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return a == b; 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static const bool safeToCompareToEmptyOrDeleted = true; 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project }; 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch struct HashTraits { 59f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits; 60231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block typedef WTF::GenericHashTraits<unsigned> SecondTraits; 61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType; 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; 64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 66231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project }; 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch struct WeakGCMapFinalizerCallback { 732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static void* finalizerContextFor(Hash::Key) 742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch { 752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return 0; 762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static inline Hash::Key keyForFinalizer(void* context, Structure* structure) 792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch { 802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return keyForWeakGCMapFinalizer(context, structure); 812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch }; 832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap; 852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*); 8781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 8881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochpublic: 8981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch StructureTransitionTable() 9081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch : m_data(UsingSingleSlotFlag) 9181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch { 9281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 9381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 9481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ~StructureTransitionTable() 9581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch { 9681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!isUsingSingleSlot()) 9781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch delete map(); 982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch else 992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch clearSingleTransition(); 10081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 10181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch inline void add(JSGlobalData&, Structure*); 10381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch inline void remove(Structure*); 10481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch inline bool contains(StringImpl* rep, unsigned attributes) const; 10581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch inline Structure* get(StringImpl* rep, unsigned attributes) const; 10681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 10781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochprivate: 10881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch bool isUsingSingleSlot() const 10981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch { 11081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return m_data & UsingSingleSlotFlag; 11181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 11281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 11381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch TransitionMap* map() const 11481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch { 11581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(!isUsingSingleSlot()); 11681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return reinterpret_cast<TransitionMap*>(m_data); 11781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 11881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch HandleSlot slot() const 1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch { 1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ASSERT(isUsingSingleSlot()); 1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag); 1232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 1242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 12581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch void setMap(TransitionMap* map) 12681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch { 12781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(isUsingSingleSlot()); 1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (HandleSlot slot = this->slot()) 1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch HandleHeap::heapFor(slot)->deallocate(slot); 13181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 13281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // This implicitly clears the flag that indicates we're using a single transition 13381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_data = reinterpret_cast<intptr_t>(map); 13481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 13581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(!isUsingSingleSlot()); 13681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 13781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 13881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch Structure* singleTransition() const 13981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch { 14081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(isUsingSingleSlot()); 1412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (HandleSlot slot = this->slot()) { 1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (*slot) 1432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return reinterpret_cast<Structure*>(slot->asCell()); 1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return 0; 14681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 1472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch void clearSingleTransition() 14981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch { 15081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(isUsingSingleSlot()); 1512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (HandleSlot slot = this->slot()) 1522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch HandleHeap::heapFor(slot)->deallocate(slot); 1532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 1542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch void setSingleTransition(JSGlobalData& globalData, Structure* structure) 1562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch { 1572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ASSERT(isUsingSingleSlot()); 1582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch HandleSlot slot = this->slot(); 1592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!slot) { 1602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch slot = globalData.allocateGlobalHandle(); 1612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0); 1622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag; 1632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 1642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure)); 1652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *slot = reinterpret_cast<JSCell*>(structure); 16681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 16781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 16881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch intptr_t m_data; 16981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}; 17081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace JSC 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 173635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif // StructureTransitionTable_h 174