]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/StructureInlines.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / StructureInlines.h
CommitLineData
93a37866 1/*
ed1e77d3 2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
93a37866
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
93a37866
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
93a37866
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 StructureInlines_h
27#define StructureInlines_h
28
81345200 29#include "JSArrayBufferView.h"
93a37866
A
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
81345200 52inline Structure* Structure::create(VM& vm, Structure* structure)
93a37866
A
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
81345200 60inline JSObject* Structure::storedPrototypeObject() const
93a37866 61{
81345200
A
62 JSValue value = m_prototype.get();
63 if (value.isNull())
ed1e77d3 64 return nullptr;
81345200
A
65 return asObject(value);
66}
67
68inline Structure* Structure::storedPrototypeStructure() const
69{
70 JSObject* object = storedPrototypeObject();
71 if (!object)
ed1e77d3 72 return nullptr;
81345200
A
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)
93a37866
A
83 return invalidOffset;
84
81345200 85 PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
93a37866
A
86 return entry ? entry->offset : invalidOffset;
87}
93a37866 88
ed1e77d3 89ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
93a37866 90{
81345200
A
91 ASSERT(!isCompilationThread());
92 ASSERT(structure()->classInfo() == info());
93
94 PropertyTable* propertyTable;
95 materializePropertyMapIfNecessary(vm, propertyTable);
96 if (!propertyTable)
97 return invalidOffset;
98
99 PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
100 if (!entry)
101 return invalidOffset;
102
103 attributes = entry->attributes;
81345200 104 return entry->offset;
93a37866
A
105}
106
ed1e77d3
A
107template<typename Functor>
108void Structure::forEachPropertyConcurrently(const Functor& functor)
109{
110 Vector<Structure*, 8> structures;
111 Structure* structure;
112 PropertyTable* table;
113
114 findStructuresAndMapForMaterialization(structures, structure, table);
115
116 if (table) {
117 for (auto& entry : *table) {
118 if (!functor(entry)) {
119 structure->m_lock.unlock();
120 return;
121 }
122 }
123 structure->m_lock.unlock();
124 }
125
126 for (unsigned i = structures.size(); i--;) {
127 structure = structures[i];
128 if (!structure->m_nameInPrevious)
129 continue;
130
131 if (!functor(PropertyMapEntry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious())))
132 return;
133 }
134}
135
136inline PropertyOffset Structure::getConcurrently(UniquedStringImpl* uid)
93a37866 137{
81345200 138 unsigned attributesIgnored;
ed1e77d3 139 return getConcurrently(uid, attributesIgnored);
81345200 140}
93a37866 141
81345200
A
142inline bool Structure::hasIndexingHeader(const JSCell* cell) const
143{
144 if (hasIndexedProperties(indexingType()))
145 return true;
146
147 if (!isTypedView(m_classInfo->typedArrayStorageType))
148 return false;
149
150 return jsCast<const JSArrayBufferView*>(cell)->mode() == WastefulTypedArray;
151}
93a37866 152
81345200
A
153inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
154{
155 return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
93a37866
A
156}
157
158inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
159{
160 for (Structure* current = this; current; current = current->previousID()) {
161 if (current == structureToFind)
162 return true;
163 }
164 return false;
165}
166
93a37866
A
167inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
168{
169 if (isObject())
170 return m_prototype.get();
ed1e77d3
A
171 if (typeInfo().type() == SymbolType)
172 return globalObject->symbolPrototype();
93a37866
A
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{
81345200 241 ASSERT(!globalObject() || !globalObject()->vm().heap.isCollecting());
93a37866
A
242 return m_propertyTableUnsafe;
243}
244
ed1e77d3
A
245inline void Structure::didReplaceProperty(PropertyOffset offset)
246{
247 if (LIKELY(!hasRareData()))
248 return;
249 StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get();
250 if (LIKELY(!map))
251 return;
252 WatchpointSet* set = map->get(offset);
253 if (LIKELY(!set))
254 return;
255 set->fireAll("Property did get replaced");
256}
257
258inline WatchpointSet* Structure::propertyReplacementWatchpointSet(PropertyOffset offset)
259{
260 ConcurrentJITLocker locker(m_lock);
261 if (!hasRareData())
262 return nullptr;
263 WTF::loadLoadFence();
264 StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get();
265 if (!map)
266 return nullptr;
267 return map->get(offset);
268}
269
93a37866
A
270ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
271{
272 PropertyTable* propertyTable = m_propertyTableUnsafe.get();
273
274 if (!propertyTable) {
ed1e77d3 275 ASSERT(!isPinnedPropertyTable());
93a37866
A
276 return true;
277 }
278
81345200
A
279 // We cannot reliably assert things about the property table in the concurrent
280 // compilation thread. It is possible for the table to be stolen and then have
281 // things added to it, which leads to the offsets being all messed up. We could
282 // get around this by grabbing a lock here, but I think that would be overkill.
283 if (isCompilationThread())
284 return true;
285
93a37866
A
286 RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());
287 unsigned totalSize = propertyTable->propertyStorageSize();
288 RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
289
290 return true;
291}
292
81345200
A
293inline size_t nextOutOfLineStorageCapacity(size_t currentCapacity)
294{
295 if (!currentCapacity)
296 return initialOutOfLineCapacity;
297 return currentCapacity * outOfLineGrowthFactor;
298}
299
300inline size_t Structure::suggestedNewOutOfLineStorageCapacity()
301{
302 return nextOutOfLineStorageCapacity(outOfLineCapacity());
303}
304
93a37866
A
305} // namespace JSC
306
307#endif // StructureInlines_h
308