]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/StructureInlines.h
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / runtime / StructureInlines.h
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 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 StructureInlines_h
27 #define StructureInlines_h
28
29 #include "PropertyMapHashTable.h"
30 #include "Structure.h"
31
32 namespace JSC {
33
34 inline Structure* Structure::create(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
35 {
36 ASSERT(vm.structureStructure);
37 ASSERT(classInfo);
38 Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, globalObject, prototype, typeInfo, classInfo, indexingType, inlineCapacity);
39 structure->finishCreation(vm);
40 return structure;
41 }
42
43 inline Structure* Structure::createStructure(VM& vm)
44 {
45 ASSERT(!vm.structureStructure);
46 Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm);
47 structure->finishCreation(vm, CreatingEarlyCell);
48 return structure;
49 }
50
51 inline Structure* Structure::create(VM& vm, const Structure* structure)
52 {
53 ASSERT(vm.structureStructure);
54 Structure* newStructure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, structure);
55 newStructure->finishCreation(vm);
56 return newStructure;
57 }
58
59 inline PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
60 {
61 ASSERT(structure()->classInfo() == &s_info);
62 materializePropertyMapIfNecessary(vm);
63 if (!propertyTable())
64 return invalidOffset;
65
66 PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
67 return entry ? entry->offset : invalidOffset;
68 }
69
70 inline PropertyOffset Structure::get(VM& vm, const WTF::String& name)
71 {
72 ASSERT(structure()->classInfo() == &s_info);
73 materializePropertyMapIfNecessary(vm);
74 if (!propertyTable())
75 return invalidOffset;
76
77 PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first;
78 return entry ? entry->offset : invalidOffset;
79 }
80
81 inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
82 {
83 return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
84 }
85
86 ALWAYS_INLINE void SlotVisitor::internalAppend(JSCell* cell)
87 {
88 ASSERT(!m_isCheckingForDefaultMarkViolation);
89 if (!cell)
90 return;
91 #if ENABLE(GC_VALIDATION)
92 validate(cell);
93 #endif
94 if (Heap::testAndSetMarked(cell) || !cell->structure())
95 return;
96
97 m_visitCount++;
98
99 MARK_LOG_CHILD(*this, cell);
100
101 // Should never attempt to mark something that is zapped.
102 ASSERT(!cell->isZapped());
103
104 m_stack.append(cell);
105 }
106
107 inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
108 {
109 for (Structure* current = this; current; current = current->previousID()) {
110 if (current == structureToFind)
111 return true;
112 }
113 return false;
114 }
115
116 inline void Structure::setEnumerationCache(VM& vm, JSPropertyNameIterator* enumerationCache)
117 {
118 ASSERT(!isDictionary());
119 if (!typeInfo().structureHasRareData())
120 allocateRareData(vm);
121 rareData()->setEnumerationCache(vm, this, enumerationCache);
122 }
123
124 inline JSPropertyNameIterator* Structure::enumerationCache()
125 {
126 if (!typeInfo().structureHasRareData())
127 return 0;
128 return rareData()->enumerationCache();
129 }
130
131 inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
132 {
133 if (isObject())
134 return m_prototype.get();
135
136 ASSERT(typeInfo().type() == StringType);
137 return globalObject->stringPrototype();
138 }
139
140 inline JSValue Structure::prototypeForLookup(ExecState* exec) const
141 {
142 return prototypeForLookup(exec->lexicalGlobalObject());
143 }
144
145 inline StructureChain* Structure::prototypeChain(VM& vm, JSGlobalObject* globalObject) const
146 {
147 // We cache our prototype chain so our clients can share it.
148 if (!isValid(globalObject, m_cachedPrototypeChain.get())) {
149 JSValue prototype = prototypeForLookup(globalObject);
150 m_cachedPrototypeChain.set(vm, this, StructureChain::create(vm, prototype.isNull() ? 0 : asObject(prototype)->structure()));
151 }
152 return m_cachedPrototypeChain.get();
153 }
154
155 inline StructureChain* Structure::prototypeChain(ExecState* exec) const
156 {
157 return prototypeChain(exec->vm(), exec->lexicalGlobalObject());
158 }
159
160 inline bool Structure::isValid(JSGlobalObject* globalObject, StructureChain* cachedPrototypeChain) const
161 {
162 if (!cachedPrototypeChain)
163 return false;
164
165 JSValue prototype = prototypeForLookup(globalObject);
166 WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
167 while (*cachedStructure && !prototype.isNull()) {
168 if (asObject(prototype)->structure() != cachedStructure->get())
169 return false;
170 ++cachedStructure;
171 prototype = asObject(prototype)->prototype();
172 }
173 return prototype.isNull() && !*cachedStructure;
174 }
175
176 inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
177 {
178 return isValid(exec->lexicalGlobalObject(), cachedPrototypeChain);
179 }
180
181 inline bool Structure::putWillGrowOutOfLineStorage()
182 {
183 checkOffsetConsistency();
184
185 ASSERT(outOfLineCapacity() >= outOfLineSize());
186
187 if (!propertyTable()) {
188 unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
189 ASSERT(outOfLineCapacity() >= currentSize);
190 return currentSize == outOfLineCapacity();
191 }
192
193 ASSERT(totalStorageCapacity() >= propertyTable()->propertyStorageSize());
194 if (propertyTable()->hasDeletedOffset())
195 return false;
196
197 ASSERT(totalStorageCapacity() >= propertyTable()->size());
198 return propertyTable()->size() == totalStorageCapacity();
199 }
200
201 ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable()
202 {
203 ASSERT(!globalObject() || !globalObject()->vm().heap.isBusy());
204 return m_propertyTableUnsafe;
205 }
206
207 ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
208 {
209 PropertyTable* propertyTable = m_propertyTableUnsafe.get();
210
211 if (!propertyTable) {
212 ASSERT(!m_isPinnedPropertyTable);
213 return true;
214 }
215
216 RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());
217 unsigned totalSize = propertyTable->propertyStorageSize();
218 RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
219
220 return true;
221 }
222
223 } // namespace JSC
224
225 #endif // StructureInlines_h
226