]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/StructureTransitionTable.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / StructureTransitionTable.h
CommitLineData
9dae56ea 1/*
81345200 2 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
9dae56ea
A
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 *
81345200 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
9dae56ea
A
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
81345200 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
9dae56ea
A
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
93a37866 29#include "IndexingType.h"
14957cd0 30#include "WeakGCMap.h"
9dae56ea 31#include <wtf/HashFunctions.h>
f9bf01c6 32#include <wtf/OwnPtr.h>
93a37866 33#include <wtf/text/StringImpl.h>
9dae56ea
A
34
35namespace JSC {
36
6fe7ccc8 37class JSCell;
14957cd0 38class Structure;
9dae56ea 39
93a37866
A
40static 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.
44enum NonPropertyTransition {
45 AllocateUndecided,
46 AllocateInt32,
47 AllocateDouble,
48 AllocateContiguous,
49 AllocateArrayStorage,
50 AllocateSlowPutArrayStorage,
51 SwitchToSlowPutArrayStorage,
52 AddIndexedAccessors
53};
54
55inline unsigned toAttributes(NonPropertyTransition transition)
56{
57 return transition + FirstInternalAttribute;
58}
59
60inline 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:
81345200 82 ASSERT(hasArrayStorage(oldType));
93a37866
A
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
14957cd0
A
92class StructureTransitionTable {
93 static const intptr_t UsingSingleSlotFlag = 1;
94
81345200 95
14957cd0 96 struct Hash {
81345200
A
97 typedef std::pair<StringImpl*, unsigned> Key;
98
9dae56ea
A
99 static unsigned hash(const Key& p)
100 {
81345200 101 return PtrHash<StringImpl*>::hash(p.first) + p.second;
9dae56ea
A
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
93a37866 112 typedef WeakGCMap<Hash::Key, Structure, Hash> TransitionMap;
14957cd0
A
113
114public:
115 StructureTransitionTable()
116 : m_data(UsingSingleSlotFlag)
117 {
118 }
119
120 ~StructureTransitionTable()
121 {
6fe7ccc8 122 if (!isUsingSingleSlot()) {
14957cd0 123 delete map();
6fe7ccc8
A
124 return;
125 }
126
127 WeakImpl* impl = this->weakImpl();
128 if (!impl)
129 return;
130 WeakSet::deallocate(impl);
14957cd0
A
131 }
132
93a37866 133 inline void add(VM&, Structure*);
14957cd0
A
134 inline bool contains(StringImpl* rep, unsigned attributes) const;
135 inline Structure* get(StringImpl* rep, unsigned attributes) const;
136
137private:
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
6fe7ccc8 149 WeakImpl* weakImpl() const
14957cd0
A
150 {
151 ASSERT(isUsingSingleSlot());
6fe7ccc8 152 return reinterpret_cast<WeakImpl*>(m_data & ~UsingSingleSlotFlag);
14957cd0
A
153 }
154
155 void setMap(TransitionMap* map)
156 {
157 ASSERT(isUsingSingleSlot());
158
6fe7ccc8
A
159 if (WeakImpl* impl = this->weakImpl())
160 WeakSet::deallocate(impl);
14957cd0
A
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());
6fe7ccc8
A
171 if (WeakImpl* impl = this->weakImpl()) {
172 if (impl->state() == WeakImpl::Live)
173 return reinterpret_cast<Structure*>(impl->jsValue().asCell());
14957cd0
A
174 }
175 return 0;
176 }
177
93a37866 178 void setSingleTransition(VM&, Structure* structure)
14957cd0
A
179 {
180 ASSERT(isUsingSingleSlot());
6fe7ccc8
A
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;
14957cd0
A
185 }
186
187 intptr_t m_data;
188};
189
9dae56ea
A
190} // namespace JSC
191
192#endif // StructureTransitionTable_h