blob: fc9ec60ccbce09a6e464f8324b7b0b79bf059eb4 [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"
oliver@apple.com284cc3d2013-07-25 04:00:33 +000030#include "ConcurrentJITLock.h"
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +000031#include "IndexingType.h"
mhahnenberg@apple.comc1bc9d32013-01-24 21:39:55 +000032#include "JSCJSValue.h"
oliver@apple.comed66e772011-04-05 01:33:58 +000033#include "JSCell.h"
mjs@apple.com4fab8112008-09-10 08:42:43 +000034#include "JSType.h"
barraclough@apple.com38d3c752012-05-12 00:39:43 +000035#include "PropertyName.h"
ggaren@apple.coma850b062009-10-09 18:14:08 +000036#include "PropertyNameArray.h"
akling@apple.com85b26822013-03-06 12:52:16 +000037#include "PropertyOffset.h"
ggaren@apple.com5236be22009-10-17 05:52:20 +000038#include "Protect.h"
fpizlo@apple.com3d423142013-08-16 19:15:31 +000039#include "PutPropertySlot.h"
mhahnenberg@apple.comdc3d1482013-02-01 23:10:49 +000040#include "StructureRareData.h"
darin@apple.coma9778f92008-11-16 04:40:06 +000041#include "StructureTransitionTable.h"
hausmann@webkit.orgf580f322009-09-09 14:56:12 +000042#include "JSTypeInfo.h"
fpizlo@apple.com04e41152012-06-15 22:14:53 +000043#include "Watchpoint.h"
oliver@apple.com22fdb102013-07-25 03:58:56 +000044#include "Weak.h"
oliver@apple.com634a76a2013-07-25 03:59:09 +000045#include <wtf/CompilationThread.h>
weinig@apple.com3412bb42008-09-01 21:22:54 +000046#include <wtf/PassRefPtr.h>
oliver@apple.com880e6c32013-07-25 04:03:25 +000047#include <wtf/PrintStream.h>
weinig@apple.com3412bb42008-09-01 21:22:54 +000048#include <wtf/RefCounted.h>
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000049#include <wtf/text/StringImpl.h>
weinig@apple.com3412bb42008-09-01 21:22:54 +000050
weinig@apple.comc13fb9f2008-10-31 00:12:50 +000051
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000052namespace JSC {
weinig@apple.com3412bb42008-09-01 21:22:54 +000053
fpizlo@apple.com34cee202013-02-16 20:07:05 +000054class LLIntOffsetsExtractor;
55class PropertyNameArray;
56class PropertyNameArrayData;
akling@apple.com85b26822013-03-06 12:52:16 +000057class PropertyTable;
fpizlo@apple.com34cee202013-02-16 20:07:05 +000058class StructureChain;
59class SlotVisitor;
60class JSString;
oliver@apple.com237b1462013-07-25 04:05:36 +000061struct DumpContext;
weinig@apple.com3412bb42008-09-01 21:22:54 +000062
fpizlo@apple.com34cee202013-02-16 20:07:05 +000063// The out-of-line property storage capacity to use when first allocating out-of-line
64// storage. Note that all objects start out without having any out-of-line storage;
65// this comes into play only on the first property store that exhausts inline storage.
66static const unsigned initialOutOfLineCapacity = 4;
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +000067
fpizlo@apple.com34cee202013-02-16 20:07:05 +000068// The factor by which to grow out-of-line storage when it is exhausted, after the
69// initial allocation.
70static const unsigned outOfLineGrowthFactor = 2;
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +000071
fpizlo@apple.com34cee202013-02-16 20:07:05 +000072class Structure : public JSCell {
73public:
74 friend class StructureTransitionTable;
commit-queue@webkit.org6c25c522011-08-09 20:46:17 +000075
fpizlo@apple.com34cee202013-02-16 20:07:05 +000076 typedef JSCell Base;
oliver@apple.com22fdb102013-07-25 03:58:56 +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
fpizlo@apple.com3d423142013-08-16 19:15:31 +000099 JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext);
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.
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +0000137 const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == info()); return m_typeInfo; }
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000138 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(); }
oliver@apple.com98fb6bf2013-07-25 03:59:44 +0000157 JSObject* storedPrototypeObject() const;
158 Structure* storedPrototypeStructure() const;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000159 JSValue prototypeForLookup(ExecState*) const;
160 JSValue prototypeForLookup(JSGlobalObject*) const;
161 JSValue prototypeForLookup(CodeBlock*) const;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000162 StructureChain* prototypeChain(VM&, JSGlobalObject*) const;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000163 StructureChain* prototypeChain(ExecState*) const;
164 static void visitChildren(JSCell*, SlotVisitor&);
165
166 // Will just the prototype chain intercept this property access?
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000167 bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000168
169 bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }
170
171 Structure* previousID() const
172 {
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +0000173 ASSERT(structure()->classInfo() == info());
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000174 if (typeInfo().structureHasRareData())
175 return rareData()->previousID();
176 return previous();
177 }
178 bool transitivelyTransitionedFrom(Structure* structureToFind);
179
180 unsigned outOfLineCapacity() const
181 {
182 ASSERT(checkOffsetConsistency());
183
184 unsigned outOfLineSize = this->outOfLineSize();
185
186 if (!outOfLineSize)
187 return 0;
188
189 if (outOfLineSize <= initialOutOfLineCapacity)
190 return initialOutOfLineCapacity;
191
192 ASSERT(outOfLineSize > initialOutOfLineCapacity);
193 COMPILE_ASSERT(outOfLineGrowthFactor == 2, outOfLineGrowthFactor_is_two);
194 return WTF::roundUpToPowerOfTwo(outOfLineSize);
195 }
196 unsigned outOfLineSize() const
197 {
198 ASSERT(checkOffsetConsistency());
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +0000199 ASSERT(structure()->classInfo() == info());
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000200
201 return numberOfOutOfLineSlotsForLastOffset(m_offset);
202 }
203 bool hasInlineStorage() const
204 {
205 return !!m_inlineCapacity;
206 }
207 unsigned inlineCapacity() const
208 {
209 return m_inlineCapacity;
210 }
211 unsigned inlineSize() const
212 {
213 return std::min<unsigned>(m_offset + 1, m_inlineCapacity);
214 }
215 unsigned totalStorageSize() const
216 {
217 return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
218 }
219 unsigned totalStorageCapacity() const
220 {
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +0000221 ASSERT(structure()->classInfo() == info());
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000222 return outOfLineCapacity() + inlineCapacity();
mhahnenberg@apple.com9f04ed42013-02-02 03:57:42 +0000223 }
224
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000225 bool isValidOffset(PropertyOffset offset) const
226 {
oliver@apple.com0402d952013-07-25 04:05:07 +0000227 return JSC::isValidOffset(offset)
oliver@apple.combee4d272013-07-25 04:05:08 +0000228 && offset <= m_offset
229 && (offset < m_inlineCapacity || offset >= firstOutOfLineOffset);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000230 }
fpizlo@apple.com80deefc2013-08-02 18:27:51 +0000231
fpizlo@apple.com557c3d02013-08-04 00:12:21 +0000232 bool couldHaveIndexingHeader() const
fpizlo@apple.com80deefc2013-08-02 18:27:51 +0000233 {
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +0000234 return hasIndexedProperties(indexingType())
235 || isTypedView(m_classInfo->typedArrayStorageType);
fpizlo@apple.com80deefc2013-08-02 18:27:51 +0000236 }
fpizlo@apple.com557c3d02013-08-04 00:12:21 +0000237
fpizlo@apple.com0e0d9312013-08-15 20:43:06 +0000238 bool hasIndexingHeader(const JSCell*) const;
fpizlo@apple.com557c3d02013-08-04 00:12:21 +0000239
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000240 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 }
oliver@apple.com880e6c32013-07-25 04:03:25 +0000360
361 void dump(PrintStream&) const;
oliver@apple.com237b1462013-07-25 04:05:36 +0000362 void dumpInContext(PrintStream&, DumpContext*) const;
363 void dumpBrief(PrintStream&, const CString&) const;
364
365 static void dumpContextHeader(PrintStream&);
oliver@apple.com880e6c32013-07-25 04:03:25 +0000366
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +0000367 DECLARE_EXPORT_INFO;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000368
369private:
370 friend class LLIntOffsetsExtractor;
371
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000372 JS_EXPORT_PRIVATE Structure(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType, unsigned inlineCapacity);
373 Structure(VM&);
374 Structure(VM&, const Structure*);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000375
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000376 static Structure* create(VM&, const Structure*);
oliver@apple.com22fdb102013-07-25 03:58:56 +0000377
oliver@apple.com02039462013-07-25 03:59:29 +0000378 static Structure* addPropertyTransitionToExistingStructureImpl(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset&);
oliver@apple.comcece4b62013-07-25 03:59:22 +0000379
oliver@apple.com22fdb102013-07-25 03:58:56 +0000380 // This will return the structure that has a usable property table, that property table,
381 // and the list of structures that we visited before we got to it. If it returns a
382 // non-null structure, it will also lock the structure that it returns; it is your job
383 // to unlock it.
384 void findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, Structure*&, PropertyTable*&);
oliver@apple.comb3956442013-07-25 03:58:27 +0000385
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000386 typedef enum {
387 NoneDictionaryKind = 0,
388 CachedDictionaryKind = 1,
389 UncachedDictionaryKind = 2
390 } DictionaryKind;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000391 static Structure* toDictionaryTransition(VM&, Structure*, DictionaryKind);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000392
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000393 PropertyOffset putSpecificValue(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000394 PropertyOffset remove(PropertyName);
395
mhahnenberg@apple.come8cc67f2013-10-14 19:34:44 +0000396 void createPropertyMap(const GCSafeConcurrentJITLocker&, VM&, unsigned keyCount = 0);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000397 void checkConsistency();
398
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000399 bool despecifyFunction(VM&, PropertyName);
400 void despecifyAllFunctions(VM&);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000401
akling@apple.com85b26822013-03-06 12:52:16 +0000402 WriteBarrier<PropertyTable>& propertyTable();
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000403 PropertyTable* takePropertyTableOrCloneIfPinned(VM&, Structure* owner);
404 PropertyTable* copyPropertyTable(VM&, Structure* owner);
405 PropertyTable* copyPropertyTableForPinning(VM&, Structure* owner);
406 JS_EXPORT_PRIVATE void materializePropertyMap(VM&);
407 void materializePropertyMapIfNecessary(VM& vm)
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000408 {
oliver@apple.com634a76a2013-07-25 03:59:09 +0000409 ASSERT(!isCompilationThread());
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +0000410 ASSERT(structure()->classInfo() == info());
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000411 ASSERT(checkOffsetConsistency());
akling@apple.com85b26822013-03-06 12:52:16 +0000412 if (!propertyTable() && previousID())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000413 materializePropertyMap(vm);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000414 }
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000415 void materializePropertyMapIfNecessaryForPinning(VM& vm)
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000416 {
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +0000417 ASSERT(structure()->classInfo() == info());
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000418 checkOffsetConsistency();
akling@apple.com85b26822013-03-06 12:52:16 +0000419 if (!propertyTable())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000420 materializePropertyMap(vm);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000421 }
422
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000423 void setPreviousID(VM& vm, Structure* transition, Structure* structure)
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000424 {
425 if (typeInfo().structureHasRareData())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000426 rareData()->setPreviousID(vm, transition, structure);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000427 else
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000428 m_previousOrRareData.set(vm, transition, structure);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000429 }
430
431 void clearPreviousID()
432 {
433 if (typeInfo().structureHasRareData())
434 rareData()->clearPreviousID();
435 else
436 m_previousOrRareData.clear();
437 }
438
439 int transitionCount() const
440 {
441 // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
442 return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
443 }
444
445 bool isValid(JSGlobalObject*, StructureChain* cachedPrototypeChain) const;
446 bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
447
448 void pin();
449
450 Structure* previous() const
451 {
452 ASSERT(!typeInfo().structureHasRareData());
453 return static_cast<Structure*>(m_previousOrRareData.get());
454 }
455
456 StructureRareData* rareData() const
457 {
458 ASSERT(typeInfo().structureHasRareData());
459 return static_cast<StructureRareData*>(m_previousOrRareData.get());
460 }
461
akling@apple.com85b26822013-03-06 12:52:16 +0000462 bool checkOffsetConsistency() const;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000463
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000464 void allocateRareData(VM&);
465 void cloneRareDataFrom(VM&, const Structure*);
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000466
467 static const int s_maxTransitionLength = 64;
fpizlo@apple.com3d423142013-08-16 19:15:31 +0000468 static const int s_maxTransitionLengthForNonEvalPutById = 512;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000469
470 static const unsigned maxSpecificFunctionThrashCount = 3;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000471
472 WriteBarrier<JSGlobalObject> m_globalObject;
473 WriteBarrier<Unknown> m_prototype;
474 mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
475
476 WriteBarrier<JSCell> m_previousOrRareData;
477
478 RefPtr<StringImpl> m_nameInPrevious;
479 WriteBarrier<JSCell> m_specificValueInPrevious;
480
481 const ClassInfo* m_classInfo;
482
483 StructureTransitionTable m_transitionTable;
484
akling@apple.com85b26822013-03-06 12:52:16 +0000485 // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
486 WriteBarrier<PropertyTable> m_propertyTableUnsafe;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000487
488 mutable InlineWatchpointSet m_transitionWatchpointSet;
489
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000490 COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
491
492 // m_offset does not account for anonymous slots
493 PropertyOffset m_offset;
494
akling@apple.comb76b00b2013-03-06 19:43:24 +0000495 TypeInfo m_typeInfo;
496 IndexingType m_indexingType;
akling@apple.comb76b00b2013-03-06 19:43:24 +0000497 uint8_t m_inlineCapacity;
oliver@apple.com22fdb102013-07-25 03:58:56 +0000498
oliver@apple.comd2056662013-07-25 04:00:37 +0000499 ConcurrentJITLock m_lock;
oliver@apple.com22fdb102013-07-25 03:58:56 +0000500
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000501 unsigned m_dictionaryKind : 2;
502 bool m_isPinnedPropertyTable : 1;
503 bool m_hasGetterSetterProperties : 1;
504 bool m_hasReadOnlyOrGetterSetterPropertiesExcludingProto : 1;
505 bool m_hasNonEnumerableProperties : 1;
akling@apple.comb76b00b2013-03-06 19:43:24 +0000506 unsigned m_attributesInPrevious : 14;
fpizlo@apple.com34cee202013-02-16 20:07:05 +0000507 unsigned m_specificFunctionThrashCount : 2;
508 unsigned m_preventExtensions : 1;
509 unsigned m_didTransition : 1;
510 unsigned m_staticFunctionReified;
511};
512
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000513} // namespace JSC
weinig@apple.com3412bb42008-09-01 21:22:54 +0000514
darin@apple.coma9778f92008-11-16 04:40:06 +0000515#endif // Structure_h