• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef StructureTransitionTable_h
27 #define StructureTransitionTable_h
28 
29 #include "UString.h"
30 #include "WeakGCMap.h"
31 #include <wtf/HashFunctions.h>
32 #include <wtf/HashTraits.h>
33 #include <wtf/OwnPtr.h>
34 #include <wtf/RefPtr.h>
35 
36 namespace JSC {
37 
38 class Structure;
39 
40 class StructureTransitionTable {
41     static const intptr_t UsingSingleSlotFlag = 1;
42 
43     struct Hash {
44         typedef std::pair<RefPtr<StringImpl>, unsigned> Key;
hashHash45         static unsigned hash(const Key& p)
46         {
47             return p.first->existingHash();
48         }
49 
equalHash50         static bool equal(const Key& a, const Key& b)
51         {
52             return a == b;
53         }
54 
55         static const bool safeToCompareToEmptyOrDeleted = true;
56     };
57 
58     struct HashTraits {
59         typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits;
60         typedef WTF::GenericHashTraits<unsigned> SecondTraits;
61         typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
62 
63         static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
emptyValueHashTraits64         static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
65 
66         static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
67 
constructDeletedValueHashTraits68         static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
isDeletedValueHashTraits69         static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
70     };
71 
72     struct WeakGCMapFinalizerCallback {
finalizerContextForWeakGCMapFinalizerCallback73         static void* finalizerContextFor(Hash::Key)
74         {
75             return 0;
76         }
77 
keyForFinalizerWeakGCMapFinalizerCallback78         static inline Hash::Key keyForFinalizer(void* context, Structure* structure)
79         {
80             return keyForWeakGCMapFinalizer(context, structure);
81         }
82     };
83 
84     typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap;
85 
86     static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
87 
88 public:
StructureTransitionTable()89     StructureTransitionTable()
90         : m_data(UsingSingleSlotFlag)
91     {
92     }
93 
~StructureTransitionTable()94     ~StructureTransitionTable()
95     {
96         if (!isUsingSingleSlot())
97             delete map();
98         else
99             clearSingleTransition();
100     }
101 
102     inline void add(JSGlobalData&, Structure*);
103     inline void remove(Structure*);
104     inline bool contains(StringImpl* rep, unsigned attributes) const;
105     inline Structure* get(StringImpl* rep, unsigned attributes) const;
106 
107 private:
isUsingSingleSlot()108     bool isUsingSingleSlot() const
109     {
110         return m_data & UsingSingleSlotFlag;
111     }
112 
map()113     TransitionMap* map() const
114     {
115         ASSERT(!isUsingSingleSlot());
116         return reinterpret_cast<TransitionMap*>(m_data);
117     }
118 
slot()119     HandleSlot slot() const
120     {
121         ASSERT(isUsingSingleSlot());
122         return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag);
123     }
124 
setMap(TransitionMap * map)125     void setMap(TransitionMap* map)
126     {
127         ASSERT(isUsingSingleSlot());
128 
129         if (HandleSlot slot = this->slot())
130             HandleHeap::heapFor(slot)->deallocate(slot);
131 
132         // This implicitly clears the flag that indicates we're using a single transition
133         m_data = reinterpret_cast<intptr_t>(map);
134 
135         ASSERT(!isUsingSingleSlot());
136     }
137 
singleTransition()138     Structure* singleTransition() const
139     {
140         ASSERT(isUsingSingleSlot());
141         if (HandleSlot slot = this->slot()) {
142             if (*slot)
143                 return reinterpret_cast<Structure*>(slot->asCell());
144         }
145         return 0;
146     }
147 
clearSingleTransition()148     void clearSingleTransition()
149     {
150         ASSERT(isUsingSingleSlot());
151         if (HandleSlot slot = this->slot())
152             HandleHeap::heapFor(slot)->deallocate(slot);
153     }
154 
setSingleTransition(JSGlobalData & globalData,Structure * structure)155     void setSingleTransition(JSGlobalData& globalData, Structure* structure)
156     {
157         ASSERT(isUsingSingleSlot());
158         HandleSlot slot = this->slot();
159         if (!slot) {
160             slot = globalData.allocateGlobalHandle();
161             HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0);
162             m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag;
163         }
164         HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure));
165         *slot = reinterpret_cast<JSCell*>(structure);
166     }
167 
168     intptr_t m_data;
169 };
170 
171 } // namespace JSC
172 
173 #endif // StructureTransitionTable_h
174