blob: e1730875bfa7f979f9a21aab2964cd0479d62313 [file] [log] [blame]
weinig@apple.com3412bb42008-09-01 21:22:54 +00001/*
fpizlo@apple.com604d38a2012-07-01 03:54:49 +00002 * Copyright (C) 2008, 2009, 2012 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"
weinig@apple.comc13fb9f2008-10-31 00:12:50 +000034#include "PropertyMapHashTable.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"
ggaren@apple.com5236be22009-10-17 05:52:20 +000037#include "Protect.h"
darin@apple.coma9778f92008-11-16 04:40:06 +000038#include "StructureTransitionTable.h"
hausmann@webkit.orgf580f322009-09-09 14:56:12 +000039#include "JSTypeInfo.h"
fpizlo@apple.com04e41152012-06-15 22:14:53 +000040#include "Watchpoint.h"
ggaren@apple.comf03cbce2011-04-10 02:32:07 +000041#include "Weak.h"
levin@chromium.orgca509e82011-04-25 21:48:58 +000042#include <wtf/PassOwnPtr.h>
weinig@apple.com3412bb42008-09-01 21:22:54 +000043#include <wtf/PassRefPtr.h>
44#include <wtf/RefCounted.h>
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000045#include <wtf/text/StringImpl.h>
weinig@apple.com3412bb42008-09-01 21:22:54 +000046
weinig@apple.comc13fb9f2008-10-31 00:12:50 +000047
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000048namespace JSC {
weinig@apple.com3412bb42008-09-01 21:22:54 +000049
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000050 class LLIntOffsetsExtractor;
weinig@apple.com503d9992008-09-15 07:27:14 +000051 class PropertyNameArray;
weinig@apple.com18b17a62008-09-20 04:35:33 +000052 class PropertyNameArrayData;
oliver@apple.com59144212011-04-04 18:41:15 +000053 class StructureChain;
ggaren@apple.com6e1f8c12011-06-16 22:01:43 +000054 class SlotVisitor;
msaboff@apple.com8bbd1b12012-04-25 00:58:17 +000055 class JSString;
weinig@apple.com3412bb42008-09-01 21:22:54 +000056
fpizlo@apple.com1ffdcff2012-07-19 00:30:34 +000057 // The out-of-line property storage capacity to use when first allocating out-of-line
58 // storage. Note that all objects start out without having any out-of-line storage;
59 // this comes into play only on the first property store that exhausts inline storage.
60 static const unsigned initialOutOfLineCapacity = 4;
61
62 // The factor by which to grow out-of-line storage when it is exhausted, after the
63 // initial allocation.
64 static const unsigned outOfLineGrowthFactor = 2;
65
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +000066 class Structure : public JSCell {
weinig@apple.com3412bb42008-09-01 21:22:54 +000067 public:
oliver@apple.comd32bf7a2009-09-10 20:01:57 +000068 friend class StructureTransitionTable;
commit-queue@webkit.org6c25c522011-08-09 20:46:17 +000069
70 typedef JSCell Base;
71
ggaren@apple.comc862eac2013-01-29 05:48:01 +000072 static Structure* create(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType = NonArray, unsigned inlineCapacity = 0);
weinig@apple.com22294302008-09-09 06:55:39 +000073
commit-queue@webkit.org403bfdf2011-08-26 22:32:53 +000074 protected:
75 void finishCreation(JSGlobalData& globalData)
76 {
77 Base::finishCreation(globalData);
78 ASSERT(m_prototype);
79 ASSERT(m_prototype.isObject() || m_prototype.isNull());
80 }
81
82 void finishCreation(JSGlobalData& globalData, CreatingEarlyCellTag)
83 {
84 Base::finishCreation(globalData, this, CreatingEarlyCell);
85 ASSERT(m_prototype);
86 ASSERT(m_prototype.isNull());
87 ASSERT(!globalData.structureStructure);
88 }
89
90 public:
weinig@apple.com7b219672008-10-16 05:31:41 +000091 static void dumpStatistics();
weinig@apple.com7b219672008-10-16 05:31:41 +000092
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +000093 JS_EXPORT_PRIVATE static Structure* addPropertyTransition(JSGlobalData&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
94 JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
95 static Structure* removePropertyTransition(JSGlobalData&, Structure*, PropertyName, PropertyOffset&);
morrita@google.comf0dd2d92012-01-13 07:23:44 +000096 JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
barraclough@apple.com38d3c752012-05-12 00:39:43 +000097 JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, PropertyName);
98 static Structure* attributeChangeTransition(JSGlobalData&, Structure*, PropertyName, unsigned attributes);
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +000099 static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
100 static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
101 static Structure* sealTransition(JSGlobalData&, Structure*);
102 static Structure* freezeTransition(JSGlobalData&, Structure*);
103 static Structure* preventExtensionsTransition(JSGlobalData&, Structure*);
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000104 static Structure* nonPropertyTransition(JSGlobalData&, Structure*, NonPropertyTransition);
barraclough@apple.comdd993102011-03-04 22:34:48 +0000105
oliver@apple.comaf134a72011-04-13 18:48:22 +0000106 bool isSealed(JSGlobalData&);
107 bool isFrozen(JSGlobalData&);
barraclough@apple.comdd993102011-03-04 22:34:48 +0000108 bool isExtensible() const { return !m_preventExtensions; }
ggaren@apple.com21daf642011-04-26 06:23:14 +0000109 bool didTransition() const { return m_didTransition; }
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000110 bool putWillGrowOutOfLineStorage()
fpizlo@apple.com604d38a2012-07-01 03:54:49 +0000111 {
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000112 ASSERT(outOfLineCapacity() >= outOfLineSize());
fpizlo@apple.com604d38a2012-07-01 03:54:49 +0000113
114 if (!m_propertyTable) {
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000115 unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
116 ASSERT(outOfLineCapacity() >= currentSize);
117 return currentSize == outOfLineCapacity();
fpizlo@apple.com604d38a2012-07-01 03:54:49 +0000118 }
119
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000120 ASSERT(totalStorageCapacity() >= m_propertyTable->propertyStorageSize());
fpizlo@apple.com604d38a2012-07-01 03:54:49 +0000121 if (m_propertyTable->hasDeletedOffset())
122 return false;
123
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000124 ASSERT(totalStorageCapacity() >= m_propertyTable->size());
125 return m_propertyTable->size() == totalStorageCapacity();
fpizlo@apple.com604d38a2012-07-01 03:54:49 +0000126 }
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000127 JS_EXPORT_PRIVATE size_t suggestedNewOutOfLineStorageCapacity();
oliver@apple.combd8e7702009-11-10 02:19:04 +0000128
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000129 Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
weinig@apple.com3412bb42008-09-01 21:22:54 +0000130
mhahnenberg@apple.com30738a72012-10-03 17:51:28 +0000131 static const bool needsDestruction = true;
132 static const bool hasImmortalStructure = true;
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000133 static void destroy(JSCell*);
weinig@apple.com3412bb42008-09-01 21:22:54 +0000134
weinig@apple.com5677e042008-10-20 21:27:44 +0000135 // These should be used with caution.
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000136 JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(JSGlobalData&, PropertyName, unsigned attributes, JSCell* specificValue);
137 PropertyOffset removePropertyWithoutTransition(JSGlobalData&, PropertyName);
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000138 void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); }
oliver@apple.comae865892009-09-21 15:45:13 +0000139
140 bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
141 bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
weinig@apple.com3412bb42008-09-01 21:22:54 +0000142
oliver@apple.comc909f5f2012-10-18 23:37:40 +0000143 bool propertyAccessesAreCacheable() { return m_dictionaryKind != UncachedDictionaryKind && !typeInfo().prohibitsPropertyCaching(); }
144
weinig@apple.com58576b22011-09-16 21:34:20 +0000145 // Type accessors.
jberlin@webkit.org3d6b4682011-05-03 15:41:28 +0000146 const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
weinig@apple.com58576b22011-09-16 21:34:20 +0000147 bool isObject() const { return typeInfo().isObject(); }
148
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000149 IndexingType indexingType() const { return m_indexingType & AllArrayTypes; }
150 IndexingType indexingTypeIncludingHistory() const { return m_indexingType; }
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +0000151
152 bool mayInterceptIndexedAccesses() const
153 {
154 return !!(indexingTypeIncludingHistory() & MayHaveIndexedAccessors);
155 }
156
157 bool anyObjectInChainMayInterceptIndexedAccesses() const;
158
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000159 bool needsSlowPutIndexing() const;
160 NonPropertyTransition suggestedArrayStorageTransition() const;
fpizlo@apple.com1c4a32c2012-09-17 20:56:39 +0000161
oliver@apple.com2346a3e2011-09-07 19:40:41 +0000162 JSGlobalObject* globalObject() const { return m_globalObject.get(); }
oliver@apple.comee1bdc82011-09-06 21:51:00 +0000163 void setGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject) { m_globalObject.set(globalData, this, globalObject); }
164
oliver@apple.com168e5062011-01-31 20:07:21 +0000165 JSValue storedPrototype() const { return m_prototype.get(); }
ggaren@apple.comdc067b62009-05-01 22:43:39 +0000166 JSValue prototypeForLookup(ExecState*) const;
fpizlo@apple.comfd598b92012-06-08 01:31:21 +0000167 JSValue prototypeForLookup(JSGlobalObject*) const;
168 JSValue prototypeForLookup(CodeBlock*) const;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000169 StructureChain* prototypeChain(JSGlobalData&, JSGlobalObject*) const;
ggaren@apple.comc8bc3c82009-02-25 23:44:07 +0000170 StructureChain* prototypeChain(ExecState*) const;
mhahnenberg@apple.com982c9ea2011-09-23 19:40:09 +0000171 static void visitChildren(JSCell*, SlotVisitor&);
fpizlo@apple.come77cbc82012-11-15 20:20:02 +0000172
173 // Will just the prototype chain intercept this property access?
174 bool prototypeChainMayInterceptStoreTo(JSGlobalData&, PropertyName);
175
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000176 bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }
177
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000178 Structure* previousID() const
179 {
180 ASSERT(structure()->classInfo() == &s_info);
181 return m_previous.get();
182 }
fpizlo@apple.com74d43ae2011-09-17 23:33:01 +0000183 bool transitivelyTransitionedFrom(Structure* structureToFind);
oliver@apple.come3c5d0e2008-09-14 08:18:49 +0000184
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000185 void growOutOfLineCapacity();
186 unsigned outOfLineCapacity() const
187 {
188 ASSERT(structure()->classInfo() == &s_info);
189 return m_outOfLineCapacity;
190 }
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000191 unsigned outOfLineSize() const
192 {
193 ASSERT(structure()->classInfo() == &s_info);
194 if (m_propertyTable) {
195 unsigned totalSize = m_propertyTable->propertyStorageSize();
196 unsigned inlineCapacity = this->inlineCapacity();
197 if (totalSize < inlineCapacity)
198 return 0;
199 return totalSize - inlineCapacity;
200 }
201 return numberOfOutOfLineSlotsForLastOffset(m_offset);
202 }
203 bool hasInlineStorage() const
204 {
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000205 return !!m_inlineCapacity;
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000206 }
207 unsigned inlineCapacity() const
208 {
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000209 return m_inlineCapacity;
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000210 }
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000211 unsigned inlineSize() const
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000212 {
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000213 unsigned result;
214 if (m_propertyTable)
215 result = m_propertyTable->propertyStorageSize();
216 else
217 result = m_offset + 1;
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000218 return std::min<unsigned>(result, m_inlineCapacity);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000219 }
220 unsigned totalStorageSize() const
221 {
222 if (m_propertyTable)
223 return m_propertyTable->propertyStorageSize();
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000224 return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000225 }
226 unsigned totalStorageCapacity() const
227 {
228 ASSERT(structure()->classInfo() == &s_info);
229 return m_outOfLineCapacity + inlineCapacity();
230 }
weinig@apple.coma3b7bbb2008-10-30 02:44:46 +0000231
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000232 PropertyOffset firstValidOffset() const
233 {
234 if (hasInlineStorage())
235 return 0;
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000236 return firstOutOfLineOffset;
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000237 }
238 PropertyOffset lastValidOffset() const
239 {
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000240 if (m_propertyTable)
ggaren@apple.comefd32fb22013-01-11 20:13:21 +0000241 return offsetForPropertyNumber(m_propertyTable->propertyStorageSize() - 1, m_inlineCapacity);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000242 return m_offset;
243 }
244 bool isValidOffset(PropertyOffset offset) const
245 {
246 return offset >= firstValidOffset()
247 && offset <= lastValidOffset();
248 }
249
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000250 bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject);
251
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000252 PropertyOffset get(JSGlobalData&, PropertyName);
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000253 PropertyOffset get(JSGlobalData&, const WTF::String& name);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000254 JS_EXPORT_PRIVATE PropertyOffset get(JSGlobalData&, PropertyName, unsigned& attributes, JSCell*& specificValue);
barraclough@apple.com07173242009-05-23 01:48:32 +0000255
weinig@apple.com35ba29b2008-10-07 23:49:59 +0000256 bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
barraclough@apple.com2668db92012-02-22 23:46:48 +0000257 bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
barraclough@apple.com4f5c0c02012-02-20 21:14:48 +0000258 void setHasGetterSetterProperties(bool is__proto__)
259 {
260 m_hasGetterSetterProperties = true;
261 if (!is__proto__)
barraclough@apple.com2668db92012-02-22 23:46:48 +0000262 m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
barraclough@apple.com7f154b82012-02-21 06:17:40 +0000263 }
264 void setContainsReadOnlyProperties()
265 {
barraclough@apple.com2668db92012-02-22 23:46:48 +0000266 m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
barraclough@apple.com4f5c0c02012-02-20 21:14:48 +0000267 }
weinig@apple.com35ba29b2008-10-07 23:49:59 +0000268
oliver@apple.com0a4803c2009-10-29 01:25:02 +0000269 bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
oliver@apple.com0a4803c2009-10-29 01:25:02 +0000270
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000271 bool isEmpty() const
272 {
273 if (m_propertyTable)
274 return m_propertyTable->isEmpty();
275 return !JSC::isValidOffset(m_offset);
276 }
weinig@apple.coma3b7bbb2008-10-30 02:44:46 +0000277
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000278 JS_EXPORT_PRIVATE void despecifyDictionaryFunction(JSGlobalData&, PropertyName);
ggaren@apple.comd0d58f42010-01-07 22:07:36 +0000279 void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
barraclough@apple.com07173242009-05-23 01:48:32 +0000280
oliver@apple.com8d857052011-02-15 23:54:06 +0000281 void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
ggaren@apple.com978e3e812010-02-12 02:51:35 +0000282 JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
mhahnenberg@apple.com2358ae12011-11-04 01:32:18 +0000283 void getPropertyNamesFromStructure(JSGlobalData&, PropertyNameArray&, EnumerationMode);
mrowe@apple.com30d5b452010-01-30 05:30:33 +0000284
msaboff@apple.com8bbd1b12012-04-25 00:58:17 +0000285 JSString* objectToStringValue() { return m_objectToStringValue.get(); }
286
287 void setObjectToStringValue(JSGlobalData& globalData, const JSCell* owner, JSString* value)
288 {
289 m_objectToStringValue.set(globalData, owner, value);
290 }
291
barraclough@apple.comdfe18a52011-10-15 01:25:53 +0000292 bool staticFunctionsReified()
293 {
294 return m_staticFunctionReified;
295 }
296
297 void setStaticFunctionsReified()
298 {
299 m_staticFunctionReified = true;
300 }
301
barraclough@apple.coma5540da2011-02-19 21:55:44 +0000302 const ClassInfo* classInfo() const { return m_classInfo; }
303
barraclough@apple.com66184e22011-03-13 21:16:29 +0000304 static ptrdiff_t prototypeOffset()
305 {
306 return OBJECT_OFFSETOF(Structure, m_prototype);
307 }
308
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000309 static ptrdiff_t globalObjectOffset()
310 {
311 return OBJECT_OFFSETOF(Structure, m_globalObject);
312 }
313
barraclough@apple.com66184e22011-03-13 21:16:29 +0000314 static ptrdiff_t typeInfoFlagsOffset()
315 {
316 return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset();
317 }
318
319 static ptrdiff_t typeInfoTypeOffset()
320 {
321 return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
322 }
fpizlo@apple.comf24804c2012-08-15 02:48:35 +0000323
324 static ptrdiff_t classInfoOffset()
325 {
326 return OBJECT_OFFSETOF(Structure, m_classInfo);
327 }
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000328
329 static ptrdiff_t indexingTypeOffset()
330 {
331 return OBJECT_OFFSETOF(Structure, m_indexingType);
332 }
barraclough@apple.com66184e22011-03-13 21:16:29 +0000333
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +0000334 static Structure* createStructure(JSGlobalData&);
oliver@apple.com41037162011-05-14 22:10:01 +0000335
fpizlo@apple.com04e41152012-06-15 22:14:53 +0000336 bool transitionWatchpointSetHasBeenInvalidated() const
337 {
338 return m_transitionWatchpointSet.hasBeenInvalidated();
339 }
340
341 bool transitionWatchpointSetIsStillValid() const
342 {
343 return m_transitionWatchpointSet.isStillValid();
344 }
345
346 void addTransitionWatchpoint(Watchpoint* watchpoint) const
347 {
348 ASSERT(transitionWatchpointSetIsStillValid());
349 m_transitionWatchpointSet.add(watchpoint);
350 }
351
352 void notifyTransitionFromThisStructure() const
353 {
354 m_transitionWatchpointSet.notifyWrite();
355 }
356
oliver@apple.com41037162011-05-14 22:10:01 +0000357 static JS_EXPORTDATA const ClassInfo s_info;
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000358
359 private:
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000360 friend class LLIntOffsetsExtractor;
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000361
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000362 JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType, unsigned inlineCapacity);
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000363 Structure(JSGlobalData&);
364 Structure(JSGlobalData&, const Structure*);
365
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +0000366 static Structure* create(JSGlobalData&, const Structure*);
oliver@apple.com23ce68f2011-04-25 21:21:28 +0000367
oliver@apple.comae865892009-09-21 15:45:13 +0000368 typedef enum {
369 NoneDictionaryKind = 0,
370 CachedDictionaryKind = 1,
371 UncachedDictionaryKind = 2
372 } DictionaryKind;
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000373 static Structure* toDictionaryTransition(JSGlobalData&, Structure*, DictionaryKind);
weinig@apple.coma3b7bbb2008-10-30 02:44:46 +0000374
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000375 PropertyOffset putSpecificValue(JSGlobalData&, PropertyName, unsigned attributes, JSCell* specificValue);
376 PropertyOffset remove(PropertyName);
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000377
barraclough@apple.com96cad9f2011-03-01 03:53:09 +0000378 void createPropertyMap(unsigned keyCount = 0);
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000379 void checkConsistency();
380
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000381 bool despecifyFunction(JSGlobalData&, PropertyName);
oliver@apple.comaf134a72011-04-13 18:48:22 +0000382 void despecifyAllFunctions(JSGlobalData&);
barraclough@apple.com07173242009-05-23 01:48:32 +0000383
levin@chromium.orgca509e82011-04-25 21:48:58 +0000384 PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
fpizlo@apple.com65c4b0d2011-10-27 22:19:14 +0000385 PassOwnPtr<PropertyTable> copyPropertyTableForPinning(JSGlobalData&, Structure* owner);
morrita@google.comf0dd2d92012-01-13 07:23:44 +0000386 JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&);
oliver@apple.comaf134a72011-04-13 18:48:22 +0000387 void materializePropertyMapIfNecessary(JSGlobalData& globalData)
weinig@apple.com8a866592008-11-14 23:36:06 +0000388 {
jberlin@webkit.org3d6b4682011-05-03 15:41:28 +0000389 ASSERT(structure()->classInfo() == &s_info);
barraclough@apple.com96cad9f2011-03-01 03:53:09 +0000390 if (!m_propertyTable && m_previous)
oliver@apple.comaf134a72011-04-13 18:48:22 +0000391 materializePropertyMap(globalData);
weinig@apple.com8a866592008-11-14 23:36:06 +0000392 }
fpizlo@apple.com65c4b0d2011-10-27 22:19:14 +0000393 void materializePropertyMapIfNecessaryForPinning(JSGlobalData& globalData)
394 {
395 ASSERT(structure()->classInfo() == &s_info);
396 if (!m_propertyTable)
397 materializePropertyMap(globalData);
398 }
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000399
zherczeg@webkit.org39150612011-10-03 06:49:50 +0000400 int transitionCount() const
alice.liu@apple.com04456af2009-01-05 00:18:53 +0000401 {
402 // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000403 return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
alice.liu@apple.com04456af2009-01-05 00:18:53 +0000404 }
barraclough@apple.com39724b82010-02-15 22:37:43 +0000405
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000406 bool isValid(JSGlobalObject*, StructureChain* cachedPrototypeChain) const;
ggaren@apple.comc8bc3c82009-02-25 23:44:07 +0000407 bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
fpizlo@apple.com4f0f1d02011-10-07 00:47:21 +0000408
409 void pin();
alice.liu@apple.com04456af2009-01-05 00:18:53 +0000410
fpizlo@apple.com01347912011-09-29 20:45:52 +0000411 static const int s_maxTransitionLength = 64;
alice.liu@apple.com04456af2009-01-05 00:18:53 +0000412
ggaren@apple.comd0d58f42010-01-07 22:07:36 +0000413 static const unsigned maxSpecificFunctionThrashCount = 3;
414
mjs@apple.com52b67602008-09-22 03:15:52 +0000415 TypeInfo m_typeInfo;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000416 IndexingType m_indexingType;
oliver@apple.comee1bdc82011-09-06 21:51:00 +0000417
418 WriteBarrier<JSGlobalObject> m_globalObject;
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000419 WriteBarrier<Unknown> m_prototype;
420 mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
weinig@apple.com3412bb42008-09-01 21:22:54 +0000421
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000422 WriteBarrier<Structure> m_previous;
barraclough@apple.comee2085b2010-08-11 00:16:38 +0000423 RefPtr<StringImpl> m_nameInPrevious;
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000424 WriteBarrier<JSCell> m_specificValueInPrevious;
weinig@apple.com3412bb42008-09-01 21:22:54 +0000425
barraclough@apple.coma5540da2011-02-19 21:55:44 +0000426 const ClassInfo* m_classInfo;
427
barraclough@apple.com07be2aa2011-02-22 21:49:59 +0000428 StructureTransitionTable m_transitionTable;
weinig@apple.com22294302008-09-09 06:55:39 +0000429
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000430 WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
weinig@apple.com503d9992008-09-15 07:27:14 +0000431
barraclough@apple.com96cad9f2011-03-01 03:53:09 +0000432 OwnPtr<PropertyTable> m_propertyTable;
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000433
msaboff@apple.com8bbd1b12012-04-25 00:58:17 +0000434 WriteBarrier<JSString> m_objectToStringValue;
fpizlo@apple.com04e41152012-06-15 22:14:53 +0000435
436 mutable InlineWatchpointSet m_transitionWatchpointSet;
437
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000438 uint32_t m_outOfLineCapacity;
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000439 uint8_t m_inlineCapacity;
440 COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
msaboff@apple.com8bbd1b12012-04-25 00:58:17 +0000441
oliver@apple.com6c9bdeb2010-02-03 01:13:47 +0000442 // m_offset does not account for anonymous slots
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000443 PropertyOffset m_offset;
weinig@apple.comed15b6d2008-10-29 22:27:31 +0000444
oliver@apple.comae865892009-09-21 15:45:13 +0000445 unsigned m_dictionaryKind : 2;
weinig@apple.com8a866592008-11-14 23:36:06 +0000446 bool m_isPinnedPropertyTable : 1;
weinig@apple.comed15b6d2008-10-29 22:27:31 +0000447 bool m_hasGetterSetterProperties : 1;
barraclough@apple.com2668db92012-02-22 23:46:48 +0000448 bool m_hasReadOnlyOrGetterSetterPropertiesExcludingProto : 1;
oliver@apple.com0a4803c2009-10-29 01:25:02 +0000449 bool m_hasNonEnumerableProperties : 1;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000450 unsigned m_attributesInPrevious : 22;
ggaren@apple.comd0d58f42010-01-07 22:07:36 +0000451 unsigned m_specificFunctionThrashCount : 2;
barraclough@apple.comdd993102011-03-04 22:34:48 +0000452 unsigned m_preventExtensions : 1;
ggaren@apple.com21daf642011-04-26 06:23:14 +0000453 unsigned m_didTransition : 1;
barraclough@apple.comdfe18a52011-10-15 01:25:53 +0000454 unsigned m_staticFunctionReified;
weinig@apple.com3412bb42008-09-01 21:22:54 +0000455 };
456
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000457 inline Structure* Structure::create(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +0000458 {
459 ASSERT(globalData.structureStructure);
460 ASSERT(classInfo);
ggaren@apple.com20b4bfc2012-10-04 04:03:14 +0000461 Structure* structure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData, globalObject, prototype, typeInfo, classInfo, indexingType, inlineCapacity);
mhahnenberg@apple.comb44a7f02012-07-26 23:27:53 +0000462 structure->finishCreation(globalData);
463 return structure;
464 }
465
466 inline Structure* Structure::createStructure(JSGlobalData& globalData)
467 {
468 ASSERT(!globalData.structureStructure);
469 Structure* structure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData);
470 structure->finishCreation(globalData, CreatingEarlyCell);
471 return structure;
472 }
473
474 inline Structure* Structure::create(JSGlobalData& globalData, const Structure* structure)
475 {
476 ASSERT(globalData.structureStructure);
477 Structure* newStructure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData, structure);
478 newStructure->finishCreation(globalData);
479 return newStructure;
480 }
481
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000482 inline PropertyOffset Structure::get(JSGlobalData& globalData, PropertyName propertyName)
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000483 {
jberlin@webkit.org3d6b4682011-05-03 15:41:28 +0000484 ASSERT(structure()->classInfo() == &s_info);
oliver@apple.comaf134a72011-04-13 18:48:22 +0000485 materializePropertyMapIfNecessary(globalData);
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000486 if (!m_propertyTable)
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000487 return invalidOffset;
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000488
barraclough@apple.com6c9b2642012-05-22 00:37:09 +0000489 PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000490 return entry ? entry->offset : invalidOffset;
weinig@apple.comc13fb9f2008-10-31 00:12:50 +0000491 }
oliver@apple.com1368a402009-08-20 23:05:03 +0000492
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000493 inline PropertyOffset Structure::get(JSGlobalData& globalData, const WTF::String& name)
barraclough@apple.com5d959c72011-08-07 03:44:45 +0000494 {
495 ASSERT(structure()->classInfo() == &s_info);
496 materializePropertyMapIfNecessary(globalData);
497 if (!m_propertyTable)
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000498 return invalidOffset;
barraclough@apple.com5d959c72011-08-07 03:44:45 +0000499
500 PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first;
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000501 return entry ? entry->offset : invalidOffset;
barraclough@apple.com5d959c72011-08-07 03:44:45 +0000502 }
mhahnenberg@apple.com6fb47cf2011-10-10 22:32:00 +0000503
mhahnenberg@apple.com3b9069c2012-08-23 23:00:31 +0000504 inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
505 {
506 return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
507 }
508
mhahnenberg@apple.coma57e6712012-09-10 18:41:05 +0000509 ALWAYS_INLINE void SlotVisitor::internalAppend(JSCell* cell)
oliver@apple.comed66e772011-04-05 01:33:58 +0000510 {
511 ASSERT(!m_isCheckingForDefaultMarkViolation);
oliver@apple.com297e1a52012-08-24 21:23:51 +0000512 if (!cell)
513 return;
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000514#if ENABLE(GC_VALIDATION)
515 validate(cell);
516#endif
oliver@apple.com77473382011-10-27 00:19:31 +0000517 if (Heap::testAndSetMarked(cell) || !cell->structure())
oliver@apple.comed66e772011-04-05 01:33:58 +0000518 return;
msaboff@apple.com9d9eab62012-06-06 23:11:09 +0000519
520 m_visitCount++;
fpizlo@apple.com511aa4b2011-12-06 22:12:56 +0000521
msaboff@apple.com9d9eab62012-06-06 23:11:09 +0000522 MARK_LOG_CHILD(*this, cell);
523
fpizlo@apple.com511aa4b2011-12-06 22:12:56 +0000524 // Should never attempt to mark something that is zapped.
525 ASSERT(!cell->isZapped());
526
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000527 m_stack.append(cell);
oliver@apple.comed66e772011-04-05 01:33:58 +0000528 }
529
fpizlo@apple.com74d43ae2011-09-17 23:33:01 +0000530 inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
531 {
532 for (Structure* current = this; current; current = current->previousID()) {
533 if (current == structureToFind)
534 return true;
535 }
536 return false;
537 }
538
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000539} // namespace JSC
weinig@apple.com3412bb42008-09-01 21:22:54 +0000540
darin@apple.coma9778f92008-11-16 04:40:06 +0000541#endif // Structure_h