Optimize own property GetByVals with rope string subscripts.
[WebKit-https.git] / Source / JavaScriptCore / runtime / Structure.h
1 /*
2  * Copyright (C) 2008, 2009, 2012, 2013, 2014 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 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 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 Structure_h
27 #define Structure_h
28
29 #include "ClassInfo.h"
30 #include "ConcurrentJITLock.h"
31 #include "IndexingType.h"
32 #include "JSCJSValue.h"
33 #include "JSCell.h"
34 #include "JSType.h"
35 #include "PropertyName.h"
36 #include "PropertyNameArray.h"
37 #include "PropertyOffset.h"
38 #include "Protect.h"
39 #include "PutPropertySlot.h"
40 #include "StructureIDBlob.h"
41 #include "StructureRareData.h"
42 #include "StructureTransitionTable.h"
43 #include "JSTypeInfo.h"
44 #include "Watchpoint.h"
45 #include "Weak.h"
46 #include "WriteBarrierInlines.h"
47 #include <wtf/CompilationThread.h>
48 #include <wtf/PassRefPtr.h>
49 #include <wtf/PrintStream.h>
50 #include <wtf/RefCounted.h>
51 #include <wtf/text/StringImpl.h>
52
53
54 namespace JSC {
55
56 class DeferGC;
57 class LLIntOffsetsExtractor;
58 class PropertyNameArray;
59 class PropertyNameArrayData;
60 class PropertyTable;
61 class StructureChain;
62 class StructureShape;
63 class SlotVisitor;
64 class JSString;
65 struct DumpContext;
66
67 // The out-of-line property storage capacity to use when first allocating out-of-line
68 // storage. Note that all objects start out without having any out-of-line storage;
69 // this comes into play only on the first property store that exhausts inline storage.
70 static const unsigned initialOutOfLineCapacity = 4;
71
72 // The factor by which to grow out-of-line storage when it is exhausted, after the
73 // initial allocation.
74 static const unsigned outOfLineGrowthFactor = 2;
75
76 class Structure : public JSCell {
77 public:
78     friend class StructureTransitionTable;
79
80     typedef JSCell Base;
81     
82     static Structure* create(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType = NonArray, unsigned inlineCapacity = 0);
83
84     ~Structure();
85
86 protected:
87     void finishCreation(VM& vm)
88     {
89         Base::finishCreation(vm);
90         ASSERT(m_prototype);
91         ASSERT(m_prototype.isObject() || m_prototype.isNull());
92     }
93
94     void finishCreation(VM& vm, CreatingEarlyCellTag)
95     {
96         Base::finishCreation(vm, this, CreatingEarlyCell);
97         ASSERT(m_prototype);
98         ASSERT(m_prototype.isNull());
99         ASSERT(!vm.structureStructure);
100     }
101
102 public:
103     StructureID id() const { return m_blob.structureID(); }
104     int32_t objectInitializationBlob() const { return m_blob.blobExcludingStructureID(); }
105     int64_t idBlob() const { return m_blob.blob(); }
106
107     bool isProxy() const
108     {
109         JSType type = m_blob.type();
110         return type == ImpureProxyType || type == PureForwardingProxyType;
111     }
112
113     static void dumpStatistics();
114
115     JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext);
116     static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, StringImpl* uid, unsigned attributes, PropertyOffset&);
117     JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, PropertyOffset&);
118     static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&);
119     JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(VM&, Structure*, JSValue prototype);
120     static Structure* attributeChangeTransition(VM&, Structure*, PropertyName, unsigned attributes);
121     JS_EXPORT_PRIVATE static Structure* toCacheableDictionaryTransition(VM&, Structure*);
122     static Structure* toUncacheableDictionaryTransition(VM&, Structure*);
123     JS_EXPORT_PRIVATE static Structure* sealTransition(VM&, Structure*);
124     JS_EXPORT_PRIVATE static Structure* freezeTransition(VM&, Structure*);
125     static Structure* preventExtensionsTransition(VM&, Structure*);
126     JS_EXPORT_PRIVATE static Structure* nonPropertyTransition(VM&, Structure*, NonPropertyTransition);
127
128     JS_EXPORT_PRIVATE bool isSealed(VM&);
129     JS_EXPORT_PRIVATE bool isFrozen(VM&);
130     bool isExtensible() const { return !preventExtensions(); }
131     bool putWillGrowOutOfLineStorage();
132     size_t suggestedNewOutOfLineStorageCapacity(); 
133
134     JS_EXPORT_PRIVATE Structure* flattenDictionaryStructure(VM&, JSObject*);
135
136     static const bool needsDestruction = true;
137     static const bool hasImmortalStructure = true;
138     static void destroy(JSCell*);
139
140     // These should be used with caution.  
141     JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes);
142     PropertyOffset removePropertyWithoutTransition(VM&, PropertyName);
143     void setPrototypeWithoutTransition(VM& vm, JSValue prototype) { m_prototype.set(vm, this, prototype); }
144         
145     bool isDictionary() const { return dictionaryKind() != NoneDictionaryKind; }
146     bool isUncacheableDictionary() const { return dictionaryKind() == UncachedDictionaryKind; }
147   
148     bool propertyAccessesAreCacheable() { return dictionaryKind() != UncachedDictionaryKind && !typeInfo().prohibitsPropertyCaching(); }
149
150     // We use SlowPath in GetByIdStatus for structures that may get new impure properties later to prevent
151     // DFG from inlining property accesses since structures don't transition when a new impure property appears.
152     bool takesSlowPathInDFGForImpureProperty()
153     {
154         return typeInfo().hasImpureGetOwnPropertySlot();
155     }
156
157     // Type accessors.
158     TypeInfo typeInfo() const { ASSERT(structure()->classInfo() == info()); return m_blob.typeInfo(m_outOfLineTypeFlags); }
159     bool isObject() const { return typeInfo().isObject(); }
160
161     IndexingType indexingType() const { return m_blob.indexingType() & AllArrayTypes; }
162     IndexingType indexingTypeIncludingHistory() const { return m_blob.indexingType(); }
163         
164     bool mayInterceptIndexedAccesses() const
165     {
166         return !!(indexingTypeIncludingHistory() & MayHaveIndexedAccessors);
167     }
168         
169     bool anyObjectInChainMayInterceptIndexedAccesses() const;
170     bool holesMustForwardToPrototype(VM&) const;
171         
172     bool needsSlowPutIndexing() const;
173     NonPropertyTransition suggestedArrayStorageTransition() const;
174         
175     JSGlobalObject* globalObject() const { return m_globalObject.get(); }
176     void setGlobalObject(VM& vm, JSGlobalObject* globalObject) { m_globalObject.set(vm, this, globalObject); }
177         
178     JSValue storedPrototype() const { return m_prototype.get(); }
179     JSObject* storedPrototypeObject() const;
180     Structure* storedPrototypeStructure() const;
181     JSValue prototypeForLookup(ExecState*) const;
182     JSValue prototypeForLookup(JSGlobalObject*) const;
183     JSValue prototypeForLookup(CodeBlock*) const;
184     StructureChain* prototypeChain(VM&, JSGlobalObject*) const;
185     StructureChain* prototypeChain(ExecState*) const;
186     static void visitChildren(JSCell*, SlotVisitor&);
187         
188     // Will just the prototype chain intercept this property access?
189     bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
190         
191     Structure* previousID() const
192     {
193         ASSERT(structure()->classInfo() == info());
194         if (hasRareData())
195             return rareData()->previousID();
196         return previous();
197     }
198     bool transitivelyTransitionedFrom(Structure* structureToFind);
199
200     unsigned outOfLineCapacity() const
201     {
202         ASSERT(checkOffsetConsistency());
203             
204         unsigned outOfLineSize = this->outOfLineSize();
205
206         if (!outOfLineSize)
207             return 0;
208
209         if (outOfLineSize <= initialOutOfLineCapacity)
210             return initialOutOfLineCapacity;
211
212         ASSERT(outOfLineSize > initialOutOfLineCapacity);
213         COMPILE_ASSERT(outOfLineGrowthFactor == 2, outOfLineGrowthFactor_is_two);
214         return WTF::roundUpToPowerOfTwo(outOfLineSize);
215     }
216     unsigned outOfLineSize() const
217     {
218         ASSERT(checkOffsetConsistency());
219         ASSERT(structure()->classInfo() == info());
220             
221         return numberOfOutOfLineSlotsForLastOffset(m_offset);
222     }
223     bool hasInlineStorage() const
224     {
225         return !!m_inlineCapacity;
226     }
227     unsigned inlineCapacity() const
228     {
229         return m_inlineCapacity;
230     }
231     unsigned inlineSize() const
232     {
233         return std::min<unsigned>(m_offset + 1, m_inlineCapacity);
234     }
235     unsigned totalStorageSize() const
236     {
237         return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
238     }
239     unsigned totalStorageCapacity() const
240     {
241         ASSERT(structure()->classInfo() == info());
242         return outOfLineCapacity() + inlineCapacity();
243     }
244
245     bool isValidOffset(PropertyOffset offset) const
246     {
247         return JSC::isValidOffset(offset)
248             && offset <= m_offset
249             && (offset < m_inlineCapacity || offset >= firstOutOfLineOffset);
250     }
251     
252     bool couldHaveIndexingHeader() const
253     {
254         return hasIndexedProperties(indexingType())
255             || isTypedView(m_classInfo->typedArrayStorageType);
256     }
257     
258     bool hasIndexingHeader(const JSCell*) const;
259     
260     bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject);
261
262     PropertyOffset get(VM&, PropertyName);
263     PropertyOffset get(VM&, PropertyName, unsigned& attributes);
264
265     PropertyOffset getConcurrently(VM&, StringImpl* uid);
266     PropertyOffset getConcurrently(VM&, StringImpl* uid, unsigned& attributes);
267     
268     void setHasGetterSetterPropertiesWithProtoCheck(bool is__proto__)
269     {
270         setHasGetterSetterProperties(true);
271         if (!is__proto__)
272             setHasReadOnlyOrGetterSetterPropertiesExcludingProto(true);
273     }
274     
275     void setContainsReadOnlyProperties() { setHasReadOnlyOrGetterSetterPropertiesExcludingProto(true); }
276     
277     void setHasCustomGetterSetterPropertiesWithProtoCheck(bool is__proto__)
278     {
279         setHasCustomGetterSetterProperties(true);
280         if (!is__proto__)
281             setHasReadOnlyOrGetterSetterPropertiesExcludingProto(true);
282     }
283     
284     bool isEmpty() const
285     {
286         ASSERT(checkOffsetConsistency());
287         return !JSC::isValidOffset(m_offset);
288     }
289
290     void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
291     void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
292     JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
293     JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
294     bool canCacheStructurePropertyNameEnumerator() const;
295     bool canCacheGenericPropertyNameEnumerator() const;
296     bool canAccessPropertiesQuickly() const;
297
298     void getPropertyNamesFromStructure(VM&, PropertyNameArray&, EnumerationMode);
299
300     JSString* objectToStringValue()
301     {
302         if (!hasRareData())
303             return 0;
304         return rareData()->objectToStringValue();
305     }
306
307     void setObjectToStringValue(VM& vm, JSString* value)
308     {
309         if (!hasRareData())
310             allocateRareData(vm);
311         rareData()->setObjectToStringValue(vm, value);
312     }
313
314     const ClassInfo* classInfo() const { return m_classInfo; }
315
316     static ptrdiff_t structureIDOffset()
317     {
318         return OBJECT_OFFSETOF(Structure, m_blob) + StructureIDBlob::structureIDOffset();
319     }
320
321     static ptrdiff_t prototypeOffset()
322     {
323         return OBJECT_OFFSETOF(Structure, m_prototype);
324     }
325
326     static ptrdiff_t globalObjectOffset()
327     {
328         return OBJECT_OFFSETOF(Structure, m_globalObject);
329     }
330
331     static ptrdiff_t classInfoOffset()
332     {
333         return OBJECT_OFFSETOF(Structure, m_classInfo);
334     }
335         
336     static ptrdiff_t indexingTypeOffset()
337     {
338         return OBJECT_OFFSETOF(Structure, m_blob) + StructureIDBlob::indexingTypeOffset();
339     }
340
341     static Structure* createStructure(VM&);
342         
343     bool transitionWatchpointSetHasBeenInvalidated() const
344     {
345         return m_transitionWatchpointSet.hasBeenInvalidated();
346     }
347         
348     bool transitionWatchpointSetIsStillValid() const
349     {
350         return m_transitionWatchpointSet.isStillValid();
351     }
352     
353     bool dfgShouldWatchIfPossible() const
354     {
355         // FIXME: We would like to not watch things that are unprofitable to watch, like
356         // dictionaries. Unfortunately, we can't do such things: a dictionary could get flattened,
357         // in which case it will start to appear watchable and so the DFG will think that it is
358         // watching it. We should come up with a comprehensive story for not watching things that
359         // aren't profitable to watch.
360         // https://bugs.webkit.org/show_bug.cgi?id=133625
361         return true;
362     }
363     
364     bool dfgShouldWatch() const
365     {
366         return dfgShouldWatchIfPossible() && transitionWatchpointSetIsStillValid();
367     }
368         
369     void addTransitionWatchpoint(Watchpoint* watchpoint) const
370     {
371         ASSERT(transitionWatchpointSetIsStillValid());
372         m_transitionWatchpointSet.add(watchpoint);
373     }
374     
375     void didTransitionFromThisStructure() const;
376     
377     InlineWatchpointSet& transitionWatchpointSet() const
378     {
379         return m_transitionWatchpointSet;
380     }
381     
382     WatchpointSet* ensurePropertyReplacementWatchpointSet(VM&, PropertyOffset);
383     void startWatchingPropertyForReplacements(VM& vm, PropertyOffset offset)
384     {
385         ensurePropertyReplacementWatchpointSet(vm, offset);
386     }
387     void startWatchingPropertyForReplacements(VM&, PropertyName);
388     WatchpointSet* propertyReplacementWatchpointSet(PropertyOffset);
389     void didReplaceProperty(PropertyOffset);
390     void didCachePropertyReplacement(VM&, PropertyOffset);
391     
392     void startWatchingInternalPropertiesIfNecessary(VM& vm)
393     {
394         if (LIKELY(didWatchInternalProperties()))
395             return;
396         startWatchingInternalProperties(vm);
397     }
398     
399     void startWatchingInternalPropertiesIfNecessaryForEntireChain(VM& vm)
400     {
401         for (Structure* structure = this; structure; structure = structure->storedPrototypeStructure())
402             structure->startWatchingInternalPropertiesIfNecessary(vm);
403     }
404
405     PassRefPtr<StructureShape> toStructureShape(JSValue);
406     
407     void dump(PrintStream&) const;
408     void dumpInContext(PrintStream&, DumpContext*) const;
409     void dumpBrief(PrintStream&, const CString&) const;
410     
411     static void dumpContextHeader(PrintStream&);
412     
413     DECLARE_EXPORT_INFO;
414
415 private:
416     typedef enum { 
417         NoneDictionaryKind = 0,
418         CachedDictionaryKind = 1,
419         UncachedDictionaryKind = 2
420     } DictionaryKind;
421
422 public:
423 #define DEFINE_BITFIELD(type, lowerName, upperName, width, offset) \
424     static const uint32_t s_##lowerName##Shift = offset;\
425     static const uint32_t s_##lowerName##Mask = ((1 << (width - 1)) | ((1 << (width - 1)) - 1));\
426     type lowerName() const { return static_cast<type>((m_bitField >> offset) & s_##lowerName##Mask); }\
427     void set##upperName(type newValue) \
428     {\
429         m_bitField &= ~(s_##lowerName##Mask << offset);\
430         m_bitField |= (newValue & s_##lowerName##Mask) << offset;\
431     }
432
433     DEFINE_BITFIELD(DictionaryKind, dictionaryKind, DictionaryKind, 2, 0);
434     DEFINE_BITFIELD(bool, isPinnedPropertyTable, IsPinnedPropertyTable, 1, 2);
435     DEFINE_BITFIELD(bool, hasGetterSetterProperties, HasGetterSetterProperties, 1, 3);
436     DEFINE_BITFIELD(bool, hasReadOnlyOrGetterSetterPropertiesExcludingProto, HasReadOnlyOrGetterSetterPropertiesExcludingProto, 1, 4);
437     DEFINE_BITFIELD(bool, hasNonEnumerableProperties, HasNonEnumerableProperties, 1, 5);
438     DEFINE_BITFIELD(unsigned, attributesInPrevious, AttributesInPrevious, 14, 6);
439     DEFINE_BITFIELD(bool, preventExtensions, PreventExtensions, 1, 20);
440     DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 21);
441     DEFINE_BITFIELD(bool, staticFunctionsReified, StaticFunctionsReified, 1, 22);
442     DEFINE_BITFIELD(bool, hasRareData, HasRareData, 1, 23);
443     DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 24);
444     DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 25);
445     DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 26);
446
447 private:
448     friend class LLIntOffsetsExtractor;
449
450     JS_EXPORT_PRIVATE Structure(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType, unsigned inlineCapacity);
451     Structure(VM&);
452     Structure(VM&, Structure*);
453
454     static Structure* create(VM&, Structure*);
455     
456     static Structure* addPropertyTransitionToExistingStructureImpl(Structure*, StringImpl* uid, unsigned attributes, PropertyOffset&);
457
458     // This will return the structure that has a usable property table, that property table,
459     // and the list of structures that we visited before we got to it. If it returns a
460     // non-null structure, it will also lock the structure that it returns; it is your job
461     // to unlock it.
462     void findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, Structure*&, PropertyTable*&);
463     
464     static Structure* toDictionaryTransition(VM&, Structure*, DictionaryKind);
465
466     PropertyOffset add(VM&, PropertyName, unsigned attributes);
467     PropertyOffset remove(PropertyName);
468
469     void createPropertyMap(const GCSafeConcurrentJITLocker&, VM&, unsigned keyCount = 0);
470     void checkConsistency();
471
472     WriteBarrier<PropertyTable>& propertyTable();
473     PropertyTable* takePropertyTableOrCloneIfPinned(VM&);
474     PropertyTable* copyPropertyTable(VM&);
475     PropertyTable* copyPropertyTableForPinning(VM&);
476     JS_EXPORT_PRIVATE void materializePropertyMap(VM&);
477     ALWAYS_INLINE void materializePropertyMapIfNecessary(VM& vm, DeferGC&)
478     {
479         ASSERT(!isCompilationThread());
480         ASSERT(structure()->classInfo() == info());
481         ASSERT(checkOffsetConsistency());
482         if (!propertyTable() && previousID())
483             materializePropertyMap(vm);
484     }
485     ALWAYS_INLINE void materializePropertyMapIfNecessary(VM& vm, PropertyTable*& table)
486     {
487         ASSERT(!isCompilationThread());
488         ASSERT(structure()->classInfo() == info());
489         ASSERT(checkOffsetConsistency());
490         table = propertyTable().get();
491         if (!table && previousID()) {
492             DeferGC deferGC(vm.heap);
493             materializePropertyMap(vm);
494             table = propertyTable().get();
495         }
496     }
497     void materializePropertyMapIfNecessaryForPinning(VM& vm, DeferGC&)
498     {
499         ASSERT(structure()->classInfo() == info());
500         checkOffsetConsistency();
501         if (!propertyTable())
502             materializePropertyMap(vm);
503     }
504
505     void setPreviousID(VM& vm, Structure* structure)
506     {
507         if (hasRareData())
508             rareData()->setPreviousID(vm, structure);
509         else
510             m_previousOrRareData.set(vm, this, structure);
511     }
512
513     void clearPreviousID()
514     {
515         if (hasRareData())
516             rareData()->clearPreviousID();
517         else
518             m_previousOrRareData.clear();
519     }
520
521     int transitionCount() const
522     {
523         // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
524         return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
525     }
526
527     bool isValid(JSGlobalObject*, StructureChain* cachedPrototypeChain) const;
528     bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
529         
530     void pin();
531
532     Structure* previous() const
533     {
534         ASSERT(!hasRareData());
535         return static_cast<Structure*>(m_previousOrRareData.get());
536     }
537
538     StructureRareData* rareData() const
539     {
540         ASSERT(hasRareData());
541         return static_cast<StructureRareData*>(m_previousOrRareData.get());
542     }
543         
544     bool checkOffsetConsistency() const;
545
546     JS_EXPORT_PRIVATE void allocateRareData(VM&);
547     
548     void startWatchingInternalProperties(VM&);
549
550     static const int s_maxTransitionLength = 64;
551     static const int s_maxTransitionLengthForNonEvalPutById = 512;
552
553     // These need to be properly aligned at the beginning of the 'Structure'
554     // part of the object.
555     StructureIDBlob m_blob;
556     TypeInfo::OutOfLineTypeFlags m_outOfLineTypeFlags;
557
558     WriteBarrier<JSGlobalObject> m_globalObject;
559     WriteBarrier<Unknown> m_prototype;
560     mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
561
562     WriteBarrier<JSCell> m_previousOrRareData;
563
564     RefPtr<StringImpl> m_nameInPrevious;
565
566     const ClassInfo* m_classInfo;
567
568     StructureTransitionTable m_transitionTable;
569
570     // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
571     WriteBarrier<PropertyTable> m_propertyTableUnsafe;
572
573     mutable InlineWatchpointSet m_transitionWatchpointSet;
574
575     COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
576
577     // m_offset does not account for anonymous slots
578     PropertyOffset m_offset;
579
580     uint8_t m_inlineCapacity;
581     
582     ConcurrentJITLock m_lock;
583     
584     uint32_t m_bitField;
585 };
586
587 } // namespace JSC
588
589 #endif // Structure_h