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