]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Structure.h
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / runtime / Structure.h
CommitLineData
9dae56ea 1/*
f9bf01c6 2 * Copyright (C) 2008, 2009 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 *
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 Structure_h
27#define Structure_h
28
29#include "Identifier.h"
14957cd0 30#include "JSCell.h"
9dae56ea
A
31#include "JSType.h"
32#include "JSValue.h"
33#include "PropertyMapHashTable.h"
f9bf01c6
A
34#include "PropertyNameArray.h"
35#include "Protect.h"
9dae56ea 36#include "StructureTransitionTable.h"
f9bf01c6 37#include "JSTypeInfo.h"
9dae56ea 38#include "UString.h"
14957cd0
A
39#include "Weak.h"
40#include <wtf/PassOwnPtr.h>
9dae56ea
A
41#include <wtf/PassRefPtr.h>
42#include <wtf/RefCounted.h>
43
9dae56ea
A
44
45namespace JSC {
46
f9bf01c6 47 class MarkStack;
9dae56ea
A
48 class PropertyNameArray;
49 class PropertyNameArrayData;
14957cd0
A
50 class StructureChain;
51 typedef MarkStack SlotVisitor;
52
53 struct ClassInfo;
9dae56ea 54
f9bf01c6
A
55 enum EnumerationMode {
56 ExcludeDontEnumProperties,
57 IncludeDontEnumProperties
58 };
59
14957cd0 60 class Structure : public JSCell {
9dae56ea 61 public:
f9bf01c6 62 friend class StructureTransitionTable;
14957cd0 63 static Structure* create(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
9dae56ea 64 {
14957cd0
A
65 ASSERT(globalData.structureStructure);
66 ASSERT(classInfo);
67 return new (&globalData) Structure(globalData, prototype, typeInfo, anonymousSlotCount, classInfo);
9dae56ea
A
68 }
69
9dae56ea
A
70 static void dumpStatistics();
71
14957cd0
A
72 static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
73 static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
74 static Structure* removePropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, size_t& offset);
75 static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
76 static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&);
77 static Structure* getterSetterTransition(JSGlobalData&, Structure*);
78 static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
79 static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
80 static Structure* sealTransition(JSGlobalData&, Structure*);
81 static Structure* freezeTransition(JSGlobalData&, Structure*);
82 static Structure* preventExtensionsTransition(JSGlobalData&, Structure*);
83
84 bool isSealed(JSGlobalData&);
85 bool isFrozen(JSGlobalData&);
86 bool isExtensible() const { return !m_preventExtensions; }
87 bool didTransition() const { return m_didTransition; }
88
89 Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
9dae56ea
A
90
91 ~Structure();
92
9dae56ea 93 // These should be used with caution.
14957cd0
A
94 size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
95 size_t removePropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName);
96 void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); }
ba379fdc
A
97
98 bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
99 bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
9dae56ea 100
14957cd0 101 const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
9dae56ea 102
14957cd0 103 JSValue storedPrototype() const { return m_prototype.get(); }
ba379fdc 104 JSValue prototypeForLookup(ExecState*) const;
9dae56ea 105 StructureChain* prototypeChain(ExecState*) const;
14957cd0 106 void visitChildren(SlotVisitor&);
9dae56ea 107
14957cd0 108 Structure* previousID() const { ASSERT(structure()->classInfo() == &s_info); return m_previous.get(); }
9dae56ea
A
109
110 void growPropertyStorageCapacity();
14957cd0
A
111 unsigned propertyStorageCapacity() const { ASSERT(structure()->classInfo() == &s_info); return m_propertyStorageCapacity; }
112 unsigned propertyStorageSize() const { ASSERT(structure()->classInfo() == &s_info); return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast<unsigned>(m_offset + 1)); }
ba379fdc 113 bool isUsingInlineStorage() const;
9dae56ea 114
14957cd0
A
115 size_t get(JSGlobalData&, const Identifier& propertyName);
116 size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
117 size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
ba379fdc
A
118 {
119 ASSERT(!propertyName.isNull());
14957cd0
A
120 ASSERT(structure()->classInfo() == &s_info);
121 return get(globalData, propertyName.impl(), attributes, specificValue);
ba379fdc
A
122 }
123
9dae56ea
A
124 bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
125 void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
126
f9bf01c6
A
127 bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
128
129 bool hasAnonymousSlots() const { return !!m_anonymousSlotCount; }
130 unsigned anonymousSlotCount() const { return m_anonymousSlotCount; }
131
14957cd0 132 bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; }
9dae56ea 133
14957cd0 134 void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName);
f9bf01c6 135 void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
9dae56ea 136
14957cd0 137 void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
f9bf01c6 138 JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
14957cd0
A
139 void getPropertyNames(JSGlobalData&, PropertyNameArray&, EnumerationMode mode);
140
141 const ClassInfo* classInfo() const { return m_classInfo; }
142
143 static ptrdiff_t prototypeOffset()
144 {
145 return OBJECT_OFFSETOF(Structure, m_prototype);
146 }
147
148 static ptrdiff_t typeInfoFlagsOffset()
149 {
150 return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset();
151 }
152
153 static ptrdiff_t typeInfoTypeOffset()
154 {
155 return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
156 }
157
158 static Structure* createStructure(JSGlobalData& globalData)
159 {
160 ASSERT(!globalData.structureStructure);
161 return new (&globalData) Structure(globalData);
162 }
f9bf01c6 163
14957cd0
A
164 static JS_EXPORTDATA const ClassInfo s_info;
165
ba379fdc 166 private:
14957cd0
A
167 Structure(JSGlobalData&, JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*);
168 Structure(JSGlobalData&);
169 Structure(JSGlobalData&, const Structure*);
f9bf01c6 170
14957cd0
A
171 static Structure* create(JSGlobalData& globalData, const Structure* structure)
172 {
173 ASSERT(globalData.structureStructure);
174 return new (&globalData) Structure(globalData, structure);
175 }
ba379fdc
A
176
177 typedef enum {
178 NoneDictionaryKind = 0,
179 CachedDictionaryKind = 1,
180 UncachedDictionaryKind = 2
181 } DictionaryKind;
14957cd0 182 static Structure* toDictionaryTransition(JSGlobalData&, Structure*, DictionaryKind);
ba379fdc 183
14957cd0 184 size_t putSpecificValue(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
9dae56ea 185 size_t remove(const Identifier& propertyName);
9dae56ea 186
14957cd0 187 void createPropertyMap(unsigned keyCount = 0);
9dae56ea
A
188 void checkConsistency();
189
14957cd0
A
190 bool despecifyFunction(JSGlobalData&, const Identifier&);
191 void despecifyAllFunctions(JSGlobalData&);
ba379fdc 192
14957cd0
A
193 PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
194 void materializePropertyMap(JSGlobalData&);
195 void materializePropertyMapIfNecessary(JSGlobalData& globalData)
9dae56ea 196 {
14957cd0
A
197 ASSERT(structure()->classInfo() == &s_info);
198 if (!m_propertyTable && m_previous)
199 materializePropertyMap(globalData);
9dae56ea
A
200 }
201
9dae56ea
A
202 signed char transitionCount() const
203 {
204 // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
205 return m_offset == noOffset ? 0 : m_offset + 1;
206 }
4e4e5a6f 207
9dae56ea
A
208 bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
209
9dae56ea
A
210 static const signed char s_maxTransitionLength = 64;
211
212 static const signed char noOffset = -1;
213
f9bf01c6
A
214 static const unsigned maxSpecificFunctionThrashCount = 3;
215
9dae56ea
A
216 TypeInfo m_typeInfo;
217
14957cd0
A
218 WriteBarrier<Unknown> m_prototype;
219 mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
9dae56ea 220
14957cd0
A
221 WriteBarrier<Structure> m_previous;
222 RefPtr<StringImpl> m_nameInPrevious;
223 WriteBarrier<JSCell> m_specificValueInPrevious;
9dae56ea 224
14957cd0 225 const ClassInfo* m_classInfo;
9dae56ea 226
14957cd0 227 StructureTransitionTable m_transitionTable;
9dae56ea 228
14957cd0
A
229 WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
230
231 OwnPtr<PropertyTable> m_propertyTable;
9dae56ea 232
f9bf01c6
A
233 uint32_t m_propertyStorageCapacity;
234
235 // m_offset does not account for anonymous slots
9dae56ea
A
236 signed char m_offset;
237
ba379fdc 238 unsigned m_dictionaryKind : 2;
9dae56ea
A
239 bool m_isPinnedPropertyTable : 1;
240 bool m_hasGetterSetterProperties : 1;
f9bf01c6
A
241 bool m_hasNonEnumerableProperties : 1;
242#if COMPILER(WINSCW)
243 // Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared
244 // bitfield, when used as argument in make_pair() function calls in structure.ccp.
245 // This bitfield optimization is insignificant for the Symbian emulator target.
246 unsigned m_attributesInPrevious;
247#else
ba379fdc 248 unsigned m_attributesInPrevious : 7;
f9bf01c6
A
249#endif
250 unsigned m_specificFunctionThrashCount : 2;
251 unsigned m_anonymousSlotCount : 5;
14957cd0
A
252 unsigned m_preventExtensions : 1;
253 unsigned m_didTransition : 1;
254 // 3 free bits
9dae56ea
A
255 };
256
14957cd0 257 inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName)
9dae56ea 258 {
14957cd0
A
259 ASSERT(structure()->classInfo() == &s_info);
260 materializePropertyMapIfNecessary(globalData);
9dae56ea 261 if (!m_propertyTable)
14957cd0 262 return notFound;
9dae56ea 263
14957cd0
A
264 PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
265 ASSERT(!entry || entry->offset >= m_anonymousSlotCount);
266 return entry ? entry->offset : notFound;
267 }
9dae56ea 268
14957cd0
A
269 inline bool JSCell::isObject() const
270 {
271 return m_structure->typeInfo().type() == ObjectType;
272 }
9dae56ea 273
14957cd0
A
274 inline bool JSCell::isString() const
275 {
276 return m_structure->typeInfo().type() == StringType;
277 }
9dae56ea 278
14957cd0
A
279 inline const ClassInfo* JSCell::classInfo() const
280 {
281#if ENABLE(GC_VALIDATION)
282 return m_structure.unvalidatedGet()->classInfo();
283#else
284 return m_structure->classInfo();
9dae56ea 285#endif
14957cd0 286 }
9dae56ea 287
14957cd0
A
288 inline Structure* JSCell::createDummyStructure(JSGlobalData& globalData)
289 {
290 return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, &s_dummyCellInfo);
291 }
9dae56ea 292
14957cd0
A
293 inline bool JSValue::needsThisConversion() const
294 {
295 if (UNLIKELY(!isCell()))
296 return true;
297 return asCell()->structure()->typeInfo().needsThisConversion();
298 }
9dae56ea 299
14957cd0
A
300 ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
301 {
302 ASSERT(!m_isCheckingForDefaultMarkViolation);
303 ASSERT(cell);
304 if (Heap::testAndSetMarked(cell))
305 return;
306 if (cell->structure() && cell->structure()->typeInfo().type() >= CompoundType)
307 m_values.append(cell);
308 }
9dae56ea 309
14957cd0
A
310 inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)
311 {
312 // Newer versions of the STL have an std::make_pair function that takes rvalue references.
313 // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.
314 // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details.
315 return Hash::Key(structure->m_nameInPrevious.get(), +structure->m_attributesInPrevious);
9dae56ea
A
316 }
317
318} // namespace JSC
319
320#endif // Structure_h