]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/StructureTransitionTable.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / StructureTransitionTable.h
1 /*
2 * Copyright (C) 2008, 2009, 2013 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 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 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 "IndexingType.h"
30 #include "WeakGCMap.h"
31 #include <wtf/HashFunctions.h>
32 #include <wtf/OwnPtr.h>
33 #include <wtf/text/StringImpl.h>
34
35 namespace JSC {
36
37 class JSCell;
38 class Structure;
39
40 static const unsigned FirstInternalAttribute = 1 << 6; // Use for transitions that don't have to do with property additions.
41
42 // Support for attributes used to indicate transitions not related to properties.
43 // If any of these are used, the string portion of the key should be 0.
44 enum NonPropertyTransition {
45 AllocateUndecided,
46 AllocateInt32,
47 AllocateDouble,
48 AllocateContiguous,
49 AllocateArrayStorage,
50 AllocateSlowPutArrayStorage,
51 SwitchToSlowPutArrayStorage,
52 AddIndexedAccessors
53 };
54
55 inline unsigned toAttributes(NonPropertyTransition transition)
56 {
57 return transition + FirstInternalAttribute;
58 }
59
60 inline IndexingType newIndexingType(IndexingType oldType, NonPropertyTransition transition)
61 {
62 switch (transition) {
63 case AllocateUndecided:
64 ASSERT(!hasIndexedProperties(oldType));
65 return oldType | UndecidedShape;
66 case AllocateInt32:
67 ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType));
68 return (oldType & ~IndexingShapeMask) | Int32Shape;
69 case AllocateDouble:
70 ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType));
71 return (oldType & ~IndexingShapeMask) | DoubleShape;
72 case AllocateContiguous:
73 ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType));
74 return (oldType & ~IndexingShapeMask) | ContiguousShape;
75 case AllocateArrayStorage:
76 ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType));
77 return (oldType & ~IndexingShapeMask) | ArrayStorageShape;
78 case AllocateSlowPutArrayStorage:
79 ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType) || hasContiguous(oldType));
80 return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
81 case SwitchToSlowPutArrayStorage:
82 ASSERT(hasArrayStorage(oldType));
83 return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
84 case AddIndexedAccessors:
85 return oldType | MayHaveIndexedAccessors;
86 default:
87 RELEASE_ASSERT_NOT_REACHED();
88 return oldType;
89 }
90 }
91
92 class StructureTransitionTable {
93 static const intptr_t UsingSingleSlotFlag = 1;
94
95
96 struct Hash {
97 typedef std::pair<StringImpl*, unsigned> Key;
98
99 static unsigned hash(const Key& p)
100 {
101 return PtrHash<StringImpl*>::hash(p.first) + p.second;
102 }
103
104 static bool equal(const Key& a, const Key& b)
105 {
106 return a == b;
107 }
108
109 static const bool safeToCompareToEmptyOrDeleted = true;
110 };
111
112 typedef WeakGCMap<Hash::Key, Structure, Hash> TransitionMap;
113
114 public:
115 StructureTransitionTable()
116 : m_data(UsingSingleSlotFlag)
117 {
118 }
119
120 ~StructureTransitionTable()
121 {
122 if (!isUsingSingleSlot()) {
123 delete map();
124 return;
125 }
126
127 WeakImpl* impl = this->weakImpl();
128 if (!impl)
129 return;
130 WeakSet::deallocate(impl);
131 }
132
133 inline void add(VM&, Structure*);
134 inline bool contains(StringImpl* rep, unsigned attributes) const;
135 inline Structure* get(StringImpl* rep, unsigned attributes) const;
136
137 private:
138 bool isUsingSingleSlot() const
139 {
140 return m_data & UsingSingleSlotFlag;
141 }
142
143 TransitionMap* map() const
144 {
145 ASSERT(!isUsingSingleSlot());
146 return reinterpret_cast<TransitionMap*>(m_data);
147 }
148
149 WeakImpl* weakImpl() const
150 {
151 ASSERT(isUsingSingleSlot());
152 return reinterpret_cast<WeakImpl*>(m_data & ~UsingSingleSlotFlag);
153 }
154
155 void setMap(TransitionMap* map)
156 {
157 ASSERT(isUsingSingleSlot());
158
159 if (WeakImpl* impl = this->weakImpl())
160 WeakSet::deallocate(impl);
161
162 // This implicitly clears the flag that indicates we're using a single transition
163 m_data = reinterpret_cast<intptr_t>(map);
164
165 ASSERT(!isUsingSingleSlot());
166 }
167
168 Structure* singleTransition() const
169 {
170 ASSERT(isUsingSingleSlot());
171 if (WeakImpl* impl = this->weakImpl()) {
172 if (impl->state() == WeakImpl::Live)
173 return reinterpret_cast<Structure*>(impl->jsValue().asCell());
174 }
175 return 0;
176 }
177
178 void setSingleTransition(VM&, Structure* structure)
179 {
180 ASSERT(isUsingSingleSlot());
181 if (WeakImpl* impl = this->weakImpl())
182 WeakSet::deallocate(impl);
183 WeakImpl* impl = WeakSet::allocate(reinterpret_cast<JSCell*>(structure));
184 m_data = reinterpret_cast<intptr_t>(impl) | UsingSingleSlotFlag;
185 }
186
187 intptr_t m_data;
188 };
189
190 } // namespace JSC
191
192 #endif // StructureTransitionTable_h