blob: 12a411bb4cd6f0fc84334bc31bf193bd31868def [file] [log] [blame]
weinig@apple.com3412bb42008-09-01 21:22:54 +00001/*
fpizlo@apple.com31be38f2013-02-16 05:31:00 +00002 * Copyright (C) 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
weinig@apple.com3412bb42008-09-01 21:22:54 +00003 *
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
darin@apple.coma9778f92008-11-16 04:40:06 +000026#ifndef Structure_h
27#define Structure_h
weinig@apple.com3412bb42008-09-01 21:22:54 +000028
barraclough@apple.comdfe18a52011-10-15 01:25:53 +000029#include "ClassInfo.h"
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +000030#include "IndexingType.h"
mhahnenberg@apple.comc1bc9d32013-01-24 21:39:55 +000031#include "JSCJSValue.h"
oliver@apple.comed66e772011-04-05 01:33:58 +000032#include "JSCell.h"
mjs@apple.com4fab8112008-09-10 08:42:43 +000033#include "JSType.h"
barraclough@apple.com38d3c752012-05-12 00:39:43 +000034#include "PropertyName.h"
ggaren@apple.coma850b062009-10-09 18:14:08 +000035#include "PropertyNameArray.h"
akling@apple.com85b26822013-03-06 12:52:16 +000036#include "PropertyOffset.h"
ggaren@apple.com5236be22009-10-17 05:52:20 +000037#include "Protect.h"
mhahnenberg@apple.comdc3d1482013-02-01 23:10:49 +000038#include "StructureRareData.h"
darin@apple.coma9778f92008-11-16 04:40:06 +000039#include "StructureTransitionTable.h"
hausmann@webkit.orgf580f322009-09-09 14:56:12 +000040#include "JSTypeInfo.h"
fpizlo@apple.com04e41152012-06-15 22:14:53 +000041#include "Watchpoint.h"
oliver@apple.com22fdb102013-07-25 03:58:56 +000042#include "Weak.h"
43#include <wtf/ByteSpinLock.h>
oliver@apple.com634a76a2013-07-25 03:59:09 +000044#include <wtf/CompilationThread.h>
weinig@apple.com3412bb42008-09-01 21:22:54 +000045#include <wtf/PassRefPtr.h>
46#include <wtf/RefCounted.h>
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000047#include <wtf/text/StringImpl.h>
weinig@apple.com3412bb42008-09-01 21:22:54 +000048
weinig@apple.comc13fb9f2008-10-31 00:12:50 +000049
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000050namespace JSC {
weinig@apple.com3412bb42008-09-01 21:22:54 +000051
fpizlo@apple.com34cee202013-02-16 20:07:05 +000052class LLIntOffsetsExtractor;
53class PropertyNameArray;
54class PropertyNameArrayData;
akling@apple.com85b26822013-03-06 12:52:16 +000055class PropertyTable;
fpizlo@apple.com34cee202013-02-16 20:07:05 +000056class StructureChain;
57class SlotVisitor;
58class JSString;
weinig@apple.com3412bb42008-09-01 21:22:54 +000059
fpizlo@apple.com34cee202013-02-16 20:07:05 +000060// The out-of-line property storage capacity to use when first allocating out-of-line
61// storage. Note that all objects start out without having any out-of-line storage;
62// this comes into play only on the first property store that exhausts inline storage.
63static const unsigned initialOutOfLineCapacity = 4;
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +000064
fpizlo@apple.com34cee202013-02-16 20:07:05 +000065// The factor by which to grow out-of-line storage when it is exhausted, after the
66// initial allocation.
67static const unsigned outOfLineGrowthFactor = 2;
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +000068
fpizlo@apple.com34cee202013-02-16 20:07:05 +000069class Structure : public JSCell {
70public:
71 friend class StructureTransitionTable;
commit-queue@webkit.org6c25c522011-08-09 20:46:17 +000072
fpizlo@apple.com34cee202013-02-16 20:07:05 +000073 typedef JSCell Base;
oliver@apple.com22fdb102013-07-25 03:58:56 +000074
75 typedef ByteSpinLock Lock;
76 typedef ByteSpinLocker Locker;
commit-queue@webkit.org6c25c522011-08-09 20:46:17 +000077
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000078 static Structure* create(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType = NonArray, unsigned inlineCapacity = 0);
weinig@apple.com22294302008-09-09 06:55:39 +000079
fpizlo@apple.com34cee202013-02-16 20:07:05 +000080protected:
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000081 void finishCreation(VM& vm)
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +000082 {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000083 Base::finishCreation(vm);
fpizlo@apple.com34cee202013-02-16 20:07:05 +000084 ASSERT(m_prototype);
85 ASSERT(m_prototype.isObject() || m_prototype.isNull());
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +000086 }
fpizlo@apple.com34cee202013-02-16 20:07:05 +000087
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000088 void finishCreation(VM& vm, CreatingEarlyCellTag)
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +000089 {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000090 Base::finishCreation(vm, this, CreatingEarlyCell);
fpizlo@apple.com34cee202013-02-16 20:07:05 +000091 ASSERT(m_prototype);
92 ASSERT(m_prototype.isNull());
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000093 ASSERT(!vm.structureStructure);
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +000094 }
95
fpizlo@apple.com34cee202013-02-16 20:07:05 +000096public:
97 static void dumpStatistics();
98
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000099 JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
oliver@apple.com02039462013-07-25 03:59:29 +0000100 static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset&);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000101 JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000102 static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&);
103 JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(VM&, Structure*, JSValue prototype);
104 JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(VM&, Structure*, PropertyName);
105 static Structure* attributeChangeTransition(VM&, Structure*, PropertyName, unsigned attributes);
106 static Structure* toCacheableDictionaryTransition(VM&, Structure*);
107 static Structure* toUncacheableDictionaryTransition(VM&, Structure*);
108 static Structure* sealTransition(VM&, Structure*);
109 static Structure* freezeTransition(VM&, Structure*);
110 static Structure* preventExtensionsTransition(VM&, Structure*);
111 static Structure* nonPropertyTransition(VM&, Structure*, NonPropertyTransition);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000112
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000113 bool isSealed(VM&);
114 bool isFrozen(VM&);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000115 bool isExtensible() const { return !m_preventExtensions; }
116 bool didTransition() const { return m_didTransition; }
akling@apple.com85b26822013-03-06 12:52:16 +0000117 bool putWillGrowOutOfLineStorage();
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000118 JS_EXPORT_PRIVATE size_t suggestedNewOutOfLineStorageCapacity();
fpizlo@apple.com74d43ae2011-09-17 23:33:01 +0000119
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000120 Structure* flattenDictionaryStructure(VM&, JSObject*);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000121
122 static const bool needsDestruction = true;
123 static const bool hasImmortalStructure = true;
124 static void destroy(JSCell*);
125
126 // These should be used with caution.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000127 JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
128 PropertyOffset removePropertyWithoutTransition(VM&, PropertyName);
129 void setPrototypeWithoutTransition(VM& vm, JSValue prototype) { m_prototype.set(vm, this, prototype); }
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000130
131 bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
132 bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
133
134 bool propertyAccessesAreCacheable() { return m_dictionaryKind != UncachedDictionaryKind && !typeInfo().prohibitsPropertyCaching(); }
135
136 // Type accessors.
137 const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
138 bool isObject() const { return typeInfo().isObject(); }
139
140 IndexingType indexingType() const { return m_indexingType & AllArrayTypes; }
141 IndexingType indexingTypeIncludingHistory() const { return m_indexingType; }
142
143 bool mayInterceptIndexedAccesses() const
mhahnenberg@apple.com9f04ed42013-02-02 03:57:42 +0000144 {
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000145 return !!(indexingTypeIncludingHistory() & MayHaveIndexedAccessors);
146 }
147
148 bool anyObjectInChainMayInterceptIndexedAccesses() const;
149
150 bool needsSlowPutIndexing() const;
151 NonPropertyTransition suggestedArrayStorageTransition() const;
152
153 JSGlobalObject* globalObject() const { return m_globalObject.get(); }
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000154 void setGlobalObject(VM& vm, JSGlobalObject* globalObject) { m_globalObject.set(vm, this, globalObject); }
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000155
156 JSValue storedPrototype() const { return m_prototype.get(); }
157 JSValue prototypeForLookup(ExecState*) const;
158 JSValue prototypeForLookup(JSGlobalObject*) const;
159 JSValue prototypeForLookup(CodeBlock*) const;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000160 StructureChain* prototypeChain(VM&, JSGlobalObject*) const;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000161 StructureChain* prototypeChain(ExecState*) const;
162 static void visitChildren(JSCell*, SlotVisitor&);
163
164 // Will just the prototype chain intercept this property access?
oliver@apple.com02039462013-07-25 03:59:29 +0000165 bool prototypeChainMayInterceptStoreTo(VM&, StringImpl* uid);
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000166 bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000167
168 bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }
169
170 Structure* previousID() const
171 {
172 ASSERT(structure()->classInfo() == &s_info);
173 if (typeInfo().structureHasRareData())
174 return rareData()->previousID();
175 return previous();
176 }
177 bool transitivelyTransitionedFrom(Structure* structureToFind);
178
179 unsigned outOfLineCapacity() const
180 {
181 ASSERT(checkOffsetConsistency());
182
183 unsigned outOfLineSize = this->outOfLineSize();
184
185 if (!outOfLineSize)
186 return 0;
187
188 if (outOfLineSize <= initialOutOfLineCapacity)
189 return initialOutOfLineCapacity;
190
191 ASSERT(outOfLineSize > initialOutOfLineCapacity);
192 COMPILE_ASSERT(outOfLineGrowthFactor == 2, outOfLineGrowthFactor_is_two);
193 return WTF::roundUpToPowerOfTwo(outOfLineSize);
194 }
195 unsigned outOfLineSize() const
196 {
197 ASSERT(checkOffsetConsistency());
198 ASSERT(structure()->classInfo() == &s_info);
199
200 return numberOfOutOfLineSlotsForLastOffset(m_offset);
201 }
202 bool hasInlineStorage() const
203 {
204 return !!m_inlineCapacity;
205 }
206 unsigned inlineCapacity() const
207 {
208 return m_inlineCapacity;
209 }
210 unsigned inlineSize() const
211 {
212 return std::min<unsigned>(m_offset + 1, m_inlineCapacity);
213 }
214 unsigned totalStorageSize() const
215 {
216 return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
217 }
218 unsigned totalStorageCapacity() const
219 {
220 ASSERT(structure()->classInfo() == &s_info);
221 return outOfLineCapacity() + inlineCapacity();
mhahnenberg@apple.com9f04ed42013-02-02 03:57:42 +0000222 }
223
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000224 PropertyOffset firstValidOffset() const
225 {
226 if (hasInlineStorage())
227 return 0;
228 return firstOutOfLineOffset;
229 }
230 PropertyOffset lastValidOffset() const
231 {
232 return m_offset;
233 }
234 bool isValidOffset(PropertyOffset offset) const
235 {
236 return offset >= firstValidOffset()
237 && offset <= lastValidOffset();
238 }
239
240 bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject);
241
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000242 PropertyOffset get(VM&, PropertyName);
243 PropertyOffset get(VM&, const WTF::String& name);
244 JS_EXPORT_PRIVATE PropertyOffset get(VM&, PropertyName, unsigned& attributes, JSCell*& specificValue);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000245
oliver@apple.com02039462013-07-25 03:59:29 +0000246 PropertyOffset getConcurrently(VM&, StringImpl* uid);
247 PropertyOffset getConcurrently(VM&, StringImpl* uid, unsigned& attributes, JSCell*& specificValue);
oliver@apple.comb3956442013-07-25 03:58:27 +0000248
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000249 bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
250 bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
251 void setHasGetterSetterProperties(bool is__proto__)
252 {
253 m_hasGetterSetterProperties = true;
254 if (!is__proto__)
255 m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
256 }
257 void setContainsReadOnlyProperties()
258 {
259 m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
260 }
261
262 bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
263
264 bool isEmpty() const
265 {
266 ASSERT(checkOffsetConsistency());
267 return !JSC::isValidOffset(m_offset);
268 }
269
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000270 JS_EXPORT_PRIVATE void despecifyDictionaryFunction(VM&, PropertyName);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000271 void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
272
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000273 void setEnumerationCache(VM&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000274 JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000275 void getPropertyNamesFromStructure(VM&, PropertyNameArray&, EnumerationMode);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000276
277 JSString* objectToStringValue()
mhahnenberg@apple.com9f04ed42013-02-02 03:57:42 +0000278 {
279 if (!typeInfo().structureHasRareData())
280 return 0;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000281 return rareData()->objectToStringValue();
mhahnenberg@apple.com9f04ed42013-02-02 03:57:42 +0000282 }
283
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000284 void setObjectToStringValue(VM& vm, const JSCell* owner, JSString* value)
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000285 {
286 if (!typeInfo().structureHasRareData())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000287 allocateRareData(vm);
288 rareData()->setObjectToStringValue(vm, owner, value);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000289 }
290
291 bool staticFunctionsReified()
292 {
293 return m_staticFunctionReified;
294 }
295
296 void setStaticFunctionsReified()
297 {
298 m_staticFunctionReified = true;
299 }
300
301 const ClassInfo* classInfo() const { return m_classInfo; }
302
303 static ptrdiff_t prototypeOffset()
304 {
305 return OBJECT_OFFSETOF(Structure, m_prototype);
306 }
307
308 static ptrdiff_t globalObjectOffset()
309 {
310 return OBJECT_OFFSETOF(Structure, m_globalObject);
311 }
312
313 static ptrdiff_t typeInfoFlagsOffset()
314 {
315 return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset();
316 }
317
318 static ptrdiff_t typeInfoTypeOffset()
319 {
320 return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
321 }
322
323 static ptrdiff_t classInfoOffset()
324 {
325 return OBJECT_OFFSETOF(Structure, m_classInfo);
326 }
327
328 static ptrdiff_t indexingTypeOffset()
329 {
330 return OBJECT_OFFSETOF(Structure, m_indexingType);
331 }
332
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000333 static Structure* createStructure(VM&);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000334
335 bool transitionWatchpointSetHasBeenInvalidated() const
336 {
337 return m_transitionWatchpointSet.hasBeenInvalidated();
338 }
339
340 bool transitionWatchpointSetIsStillValid() const
341 {
342 return m_transitionWatchpointSet.isStillValid();
343 }
344
345 void addTransitionWatchpoint(Watchpoint* watchpoint) const
346 {
347 ASSERT(transitionWatchpointSetIsStillValid());
348 m_transitionWatchpointSet.add(watchpoint);
349 }
350
351 void notifyTransitionFromThisStructure() const
352 {
353 m_transitionWatchpointSet.notifyWrite();
354 }
oliver@apple.com9397e002013-07-25 03:58:49 +0000355
356 InlineWatchpointSet& transitionWatchpointSet() const
357 {
358 return m_transitionWatchpointSet;
359 }
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000360
361 static JS_EXPORTDATA const ClassInfo s_info;
362
363private:
364 friend class LLIntOffsetsExtractor;
365
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000366 JS_EXPORT_PRIVATE Structure(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType, unsigned inlineCapacity);
367 Structure(VM&);
368 Structure(VM&, const Structure*);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000369
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000370 static Structure* create(VM&, const Structure*);
oliver@apple.com22fdb102013-07-25 03:58:56 +0000371
oliver@apple.com02039462013-07-25 03:59:29 +0000372 static Structure* addPropertyTransitionToExistingStructureImpl(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset&);
oliver@apple.comcece4b62013-07-25 03:59:22 +0000373
oliver@apple.com22fdb102013-07-25 03:58:56 +0000374 // This will return the structure that has a usable property table, that property table,
375 // and the list of structures that we visited before we got to it. If it returns a
376 // non-null structure, it will also lock the structure that it returns; it is your job
377 // to unlock it.
378 void findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, Structure*&, PropertyTable*&);
oliver@apple.comb3956442013-07-25 03:58:27 +0000379
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000380 typedef enum {
381 NoneDictionaryKind = 0,
382 CachedDictionaryKind = 1,
383 UncachedDictionaryKind = 2
384 } DictionaryKind;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000385 static Structure* toDictionaryTransition(VM&, Structure*, DictionaryKind);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000386
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000387 PropertyOffset putSpecificValue(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000388 PropertyOffset remove(PropertyName);
389
oliver@apple.com22fdb102013-07-25 03:58:56 +0000390 void createPropertyMap(const Locker&, VM&, unsigned keyCount = 0);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000391 void checkConsistency();
392
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000393 bool despecifyFunction(VM&, PropertyName);
394 void despecifyAllFunctions(VM&);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000395
akling@apple.com85b26822013-03-06 12:52:16 +0000396 WriteBarrier<PropertyTable>& propertyTable();
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000397 PropertyTable* takePropertyTableOrCloneIfPinned(VM&, Structure* owner);
398 PropertyTable* copyPropertyTable(VM&, Structure* owner);
399 PropertyTable* copyPropertyTableForPinning(VM&, Structure* owner);
400 JS_EXPORT_PRIVATE void materializePropertyMap(VM&);
401 void materializePropertyMapIfNecessary(VM& vm)
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000402 {
oliver@apple.com634a76a2013-07-25 03:59:09 +0000403 ASSERT(!isCompilationThread());
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000404 ASSERT(structure()->classInfo() == &s_info);
405 ASSERT(checkOffsetConsistency());
akling@apple.com85b26822013-03-06 12:52:16 +0000406 if (!propertyTable() && previousID())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000407 materializePropertyMap(vm);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000408 }
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000409 void materializePropertyMapIfNecessaryForPinning(VM& vm)
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000410 {
411 ASSERT(structure()->classInfo() == &s_info);
412 checkOffsetConsistency();
akling@apple.com85b26822013-03-06 12:52:16 +0000413 if (!propertyTable())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000414 materializePropertyMap(vm);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000415 }
416
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000417 void setPreviousID(VM& vm, Structure* transition, Structure* structure)
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000418 {
419 if (typeInfo().structureHasRareData())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000420 rareData()->setPreviousID(vm, transition, structure);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000421 else
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000422 m_previousOrRareData.set(vm, transition, structure);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000423 }
424
425 void clearPreviousID()
426 {
427 if (typeInfo().structureHasRareData())
428 rareData()->clearPreviousID();
429 else
430 m_previousOrRareData.clear();
431 }
432
433 int transitionCount() const
434 {
435 // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
436 return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
437 }
438
439 bool isValid(JSGlobalObject*, StructureChain* cachedPrototypeChain) const;
440 bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
441
442 void pin();
443
444 Structure* previous() const
445 {
446 ASSERT(!typeInfo().structureHasRareData());
447 return static_cast<Structure*>(m_previousOrRareData.get());
448 }
449
450 StructureRareData* rareData() const
451 {
452 ASSERT(typeInfo().structureHasRareData());
453 return static_cast<StructureRareData*>(m_previousOrRareData.get());
454 }
455
akling@apple.com85b26822013-03-06 12:52:16 +0000456 bool checkOffsetConsistency() const;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000457
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000458 void allocateRareData(VM&);
459 void cloneRareDataFrom(VM&, const Structure*);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000460
461 static const int s_maxTransitionLength = 64;
462
463 static const unsigned maxSpecificFunctionThrashCount = 3;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000464
465 WriteBarrier<JSGlobalObject> m_globalObject;
466 WriteBarrier<Unknown> m_prototype;
467 mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
468
469 WriteBarrier<JSCell> m_previousOrRareData;
470
471 RefPtr<StringImpl> m_nameInPrevious;
472 WriteBarrier<JSCell> m_specificValueInPrevious;
473
474 const ClassInfo* m_classInfo;
475
476 StructureTransitionTable m_transitionTable;
477
akling@apple.com85b26822013-03-06 12:52:16 +0000478 // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
479 WriteBarrier<PropertyTable> m_propertyTableUnsafe;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000480
481 mutable InlineWatchpointSet m_transitionWatchpointSet;
482
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000483 COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
484
485 // m_offset does not account for anonymous slots
486 PropertyOffset m_offset;
487
akling@apple.comb76b00b2013-03-06 19:43:24 +0000488 TypeInfo m_typeInfo;
489 IndexingType m_indexingType;
akling@apple.comb76b00b2013-03-06 19:43:24 +0000490 uint8_t m_inlineCapacity;
oliver@apple.com22fdb102013-07-25 03:58:56 +0000491
492 Lock m_lock;
493
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000494 unsigned m_dictionaryKind : 2;
495 bool m_isPinnedPropertyTable : 1;
496 bool m_hasGetterSetterProperties : 1;
497 bool m_hasReadOnlyOrGetterSetterPropertiesExcludingProto : 1;
498 bool m_hasNonEnumerableProperties : 1;
akling@apple.comb76b00b2013-03-06 19:43:24 +0000499 unsigned m_attributesInPrevious : 14;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000500 unsigned m_specificFunctionThrashCount : 2;
501 unsigned m_preventExtensions : 1;
502 unsigned m_didTransition : 1;
503 unsigned m_staticFunctionReified;
504};
505
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000506} // namespace JSC
weinig@apple.com3412bb42008-09-01 21:22:54 +0000507
darin@apple.coma9778f92008-11-16 04:40:06 +0000508#endif // Structure_h