]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - runtime/StructureInlines.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / StructureInlines.h
... / ...
CommitLineData
1/*
2 * Copyright (C) 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 StructureInlines_h
27#define StructureInlines_h
28
29#include "JSArrayBufferView.h"
30#include "PropertyMapHashTable.h"
31#include "Structure.h"
32
33namespace JSC {
34
35inline Structure* Structure::create(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
36{
37 ASSERT(vm.structureStructure);
38 ASSERT(classInfo);
39 Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, globalObject, prototype, typeInfo, classInfo, indexingType, inlineCapacity);
40 structure->finishCreation(vm);
41 return structure;
42}
43
44inline Structure* Structure::createStructure(VM& vm)
45{
46 ASSERT(!vm.structureStructure);
47 Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm);
48 structure->finishCreation(vm, CreatingEarlyCell);
49 return structure;
50}
51
52inline Structure* Structure::create(VM& vm, Structure* structure)
53{
54 ASSERT(vm.structureStructure);
55 Structure* newStructure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, structure);
56 newStructure->finishCreation(vm);
57 return newStructure;
58}
59
60inline JSObject* Structure::storedPrototypeObject() const
61{
62 JSValue value = m_prototype.get();
63 if (value.isNull())
64 return 0;
65 return asObject(value);
66}
67
68inline Structure* Structure::storedPrototypeStructure() const
69{
70 JSObject* object = storedPrototypeObject();
71 if (!object)
72 return 0;
73 return object->structure();
74}
75
76ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
77{
78 ASSERT(!isCompilationThread());
79 ASSERT(structure()->classInfo() == info());
80 PropertyTable* propertyTable;
81 materializePropertyMapIfNecessary(vm, propertyTable);
82 if (!propertyTable)
83 return invalidOffset;
84
85 PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
86 return entry ? entry->offset : invalidOffset;
87}
88
89ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, const WTF::String& name)
90{
91 ASSERT(!isCompilationThread());
92 ASSERT(structure()->classInfo() == info());
93 PropertyTable* propertyTable;
94 materializePropertyMapIfNecessary(vm, propertyTable);
95 if (!propertyTable)
96 return invalidOffset;
97
98 PropertyMapEntry* entry = propertyTable->findWithString(name.impl()).first;
99 return entry ? entry->offset : invalidOffset;
100}
101
102ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, JSCell*& specificValue)
103{
104 ASSERT(!isCompilationThread());
105 ASSERT(structure()->classInfo() == info());
106
107 PropertyTable* propertyTable;
108 materializePropertyMapIfNecessary(vm, propertyTable);
109 if (!propertyTable)
110 return invalidOffset;
111
112 PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
113 if (!entry)
114 return invalidOffset;
115
116 attributes = entry->attributes;
117 specificValue = entry->specificValue.get();
118 return entry->offset;
119}
120
121inline PropertyOffset Structure::getConcurrently(VM& vm, StringImpl* uid)
122{
123 unsigned attributesIgnored;
124 JSCell* specificValueIgnored;
125 return getConcurrently(
126 vm, uid, attributesIgnored, specificValueIgnored);
127}
128
129inline bool Structure::hasIndexingHeader(const JSCell* cell) const
130{
131 if (hasIndexedProperties(indexingType()))
132 return true;
133
134 if (!isTypedView(m_classInfo->typedArrayStorageType))
135 return false;
136
137 return jsCast<const JSArrayBufferView*>(cell)->mode() == WastefulTypedArray;
138}
139
140inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
141{
142 return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
143}
144
145inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
146{
147 for (Structure* current = this; current; current = current->previousID()) {
148 if (current == structureToFind)
149 return true;
150 }
151 return false;
152}
153
154inline void Structure::setEnumerationCache(VM& vm, JSPropertyNameIterator* enumerationCache)
155{
156 ASSERT(!isDictionary());
157 if (!m_hasRareData)
158 allocateRareData(vm);
159 rareData()->setEnumerationCache(vm, enumerationCache);
160}
161
162inline JSPropertyNameIterator* Structure::enumerationCache()
163{
164 if (!m_hasRareData)
165 return 0;
166 return rareData()->enumerationCache();
167}
168
169inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
170{
171 if (isObject())
172 return m_prototype.get();
173
174 ASSERT(typeInfo().type() == StringType);
175 return globalObject->stringPrototype();
176}
177
178inline JSValue Structure::prototypeForLookup(ExecState* exec) const
179{
180 return prototypeForLookup(exec->lexicalGlobalObject());
181}
182
183inline StructureChain* Structure::prototypeChain(VM& vm, JSGlobalObject* globalObject) const
184{
185 // We cache our prototype chain so our clients can share it.
186 if (!isValid(globalObject, m_cachedPrototypeChain.get())) {
187 JSValue prototype = prototypeForLookup(globalObject);
188 m_cachedPrototypeChain.set(vm, this, StructureChain::create(vm, prototype.isNull() ? 0 : asObject(prototype)->structure()));
189 }
190 return m_cachedPrototypeChain.get();
191}
192
193inline StructureChain* Structure::prototypeChain(ExecState* exec) const
194{
195 return prototypeChain(exec->vm(), exec->lexicalGlobalObject());
196}
197
198inline bool Structure::isValid(JSGlobalObject* globalObject, StructureChain* cachedPrototypeChain) const
199{
200 if (!cachedPrototypeChain)
201 return false;
202
203 JSValue prototype = prototypeForLookup(globalObject);
204 WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
205 while (*cachedStructure && !prototype.isNull()) {
206 if (asObject(prototype)->structure() != cachedStructure->get())
207 return false;
208 ++cachedStructure;
209 prototype = asObject(prototype)->prototype();
210 }
211 return prototype.isNull() && !*cachedStructure;
212}
213
214inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
215{
216 return isValid(exec->lexicalGlobalObject(), cachedPrototypeChain);
217}
218
219inline bool Structure::putWillGrowOutOfLineStorage()
220{
221 checkOffsetConsistency();
222
223 ASSERT(outOfLineCapacity() >= outOfLineSize());
224
225 if (!propertyTable()) {
226 unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
227 ASSERT(outOfLineCapacity() >= currentSize);
228 return currentSize == outOfLineCapacity();
229 }
230
231 ASSERT(totalStorageCapacity() >= propertyTable()->propertyStorageSize());
232 if (propertyTable()->hasDeletedOffset())
233 return false;
234
235 ASSERT(totalStorageCapacity() >= propertyTable()->size());
236 return propertyTable()->size() == totalStorageCapacity();
237}
238
239ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable()
240{
241 ASSERT(!globalObject() || !globalObject()->vm().heap.isCollecting());
242 return m_propertyTableUnsafe;
243}
244
245ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
246{
247 PropertyTable* propertyTable = m_propertyTableUnsafe.get();
248
249 if (!propertyTable) {
250 ASSERT(!m_isPinnedPropertyTable);
251 return true;
252 }
253
254 // We cannot reliably assert things about the property table in the concurrent
255 // compilation thread. It is possible for the table to be stolen and then have
256 // things added to it, which leads to the offsets being all messed up. We could
257 // get around this by grabbing a lock here, but I think that would be overkill.
258 if (isCompilationThread())
259 return true;
260
261 RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());
262 unsigned totalSize = propertyTable->propertyStorageSize();
263 RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
264
265 return true;
266}
267
268inline size_t nextOutOfLineStorageCapacity(size_t currentCapacity)
269{
270 if (!currentCapacity)
271 return initialOutOfLineCapacity;
272 return currentCapacity * outOfLineGrowthFactor;
273}
274
275inline size_t Structure::suggestedNewOutOfLineStorageCapacity()
276{
277 return nextOutOfLineStorageCapacity(outOfLineCapacity());
278}
279
280} // namespace JSC
281
282#endif // StructureInlines_h
283