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