2  * Copyright (C) 2013 Apple Inc. All rights reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   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. 
  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.  
  26 #ifndef StructureInlines_h 
  27 #define StructureInlines_h 
  29 #include "JSArrayBufferView.h" 
  30 #include "PropertyMapHashTable.h" 
  31 #include "Structure.h" 
  35 inline Structure
* Structure::create(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
, const TypeInfo
& typeInfo
, const ClassInfo
* classInfo
, IndexingType indexingType
, unsigned inlineCapacity
) 
  37     ASSERT(vm
.structureStructure
); 
  39     Structure
* structure 
= new (NotNull
, allocateCell
<Structure
>(vm
.heap
)) Structure(vm
, globalObject
, prototype
, typeInfo
, classInfo
, indexingType
, inlineCapacity
); 
  40     structure
->finishCreation(vm
); 
  44 inline Structure
* Structure::createStructure(VM
& vm
) 
  46     ASSERT(!vm
.structureStructure
); 
  47     Structure
* structure 
= new (NotNull
, allocateCell
<Structure
>(vm
.heap
)) Structure(vm
); 
  48     structure
->finishCreation(vm
, CreatingEarlyCell
); 
  52 inline Structure
* Structure::create(VM
& vm
, Structure
* structure
) 
  54     ASSERT(vm
.structureStructure
); 
  55     Structure
* newStructure 
= new (NotNull
, allocateCell
<Structure
>(vm
.heap
)) Structure(vm
, structure
); 
  56     newStructure
->finishCreation(vm
); 
  60 inline JSObject
* Structure::storedPrototypeObject() const 
  62     JSValue value 
= m_prototype
.get(); 
  65     return asObject(value
); 
  68 inline Structure
* Structure::storedPrototypeStructure() const 
  70     JSObject
* object 
= storedPrototypeObject(); 
  73     return object
->structure(); 
  76 ALWAYS_INLINE PropertyOffset 
Structure::get(VM
& vm
, PropertyName propertyName
) 
  78     ASSERT(!isCompilationThread()); 
  79     ASSERT(structure()->classInfo() == info()); 
  80     PropertyTable
* propertyTable
; 
  81     materializePropertyMapIfNecessary(vm
, propertyTable
); 
  85     PropertyMapEntry
* entry 
= propertyTable
->get(propertyName
.uid()); 
  86     return entry 
? entry
->offset 
: invalidOffset
; 
  89 ALWAYS_INLINE PropertyOffset 
Structure::get(VM
& vm
, const WTF::String
& name
) 
  91     ASSERT(!isCompilationThread()); 
  92     ASSERT(structure()->classInfo() == info()); 
  93     PropertyTable
* propertyTable
; 
  94     materializePropertyMapIfNecessary(vm
, propertyTable
); 
  98     PropertyMapEntry
* entry 
= propertyTable
->findWithString(name
.impl()).first
; 
  99     return entry 
? entry
->offset 
: invalidOffset
; 
 102 ALWAYS_INLINE PropertyOffset 
Structure::get(VM
& vm
, PropertyName propertyName
, unsigned& attributes
, JSCell
*& specificValue
) 
 104     ASSERT(!isCompilationThread()); 
 105     ASSERT(structure()->classInfo() == info()); 
 107     PropertyTable
* propertyTable
; 
 108     materializePropertyMapIfNecessary(vm
, propertyTable
); 
 110         return invalidOffset
; 
 112     PropertyMapEntry
* entry 
= propertyTable
->get(propertyName
.uid()); 
 114         return invalidOffset
; 
 116     attributes 
= entry
->attributes
; 
 117     specificValue 
= entry
->specificValue
.get(); 
 118     return entry
->offset
; 
 121 inline PropertyOffset 
Structure::getConcurrently(VM
& vm
, StringImpl
* uid
) 
 123     unsigned attributesIgnored
; 
 124     JSCell
* specificValueIgnored
; 
 125     return getConcurrently( 
 126         vm
, uid
, attributesIgnored
, specificValueIgnored
); 
 129 inline bool Structure::hasIndexingHeader(const JSCell
* cell
) const 
 131     if (hasIndexedProperties(indexingType())) 
 134     if (!isTypedView(m_classInfo
->typedArrayStorageType
)) 
 137     return jsCast
<const JSArrayBufferView
*>(cell
)->mode() == WastefulTypedArray
; 
 140 inline bool Structure::masqueradesAsUndefined(JSGlobalObject
* lexicalGlobalObject
) 
 142     return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject
; 
 145 inline bool Structure::transitivelyTransitionedFrom(Structure
* structureToFind
) 
 147     for (Structure
* current 
= this; current
; current 
= current
->previousID()) { 
 148         if (current 
== structureToFind
) 
 154 inline void Structure::setEnumerationCache(VM
& vm
, JSPropertyNameIterator
* enumerationCache
) 
 156     ASSERT(!isDictionary()); 
 158         allocateRareData(vm
); 
 159     rareData()->setEnumerationCache(vm
, enumerationCache
); 
 162 inline JSPropertyNameIterator
* Structure::enumerationCache() 
 166     return rareData()->enumerationCache(); 
 169 inline JSValue 
Structure::prototypeForLookup(JSGlobalObject
* globalObject
) const 
 172         return m_prototype
.get(); 
 174     ASSERT(typeInfo().type() == StringType
); 
 175     return globalObject
->stringPrototype(); 
 178 inline JSValue 
Structure::prototypeForLookup(ExecState
* exec
) const 
 180     return prototypeForLookup(exec
->lexicalGlobalObject()); 
 183 inline StructureChain
* Structure::prototypeChain(VM
& vm
, JSGlobalObject
* globalObject
) const 
 185     // We cache our prototype chain so our clients can share it. 
 186     if (!isValid(globalObject
, m_cachedPrototypeChain
.get())) { 
 187         JSValue prototype 
= prototypeForLookup(globalObject
); 
 188         m_cachedPrototypeChain
.set(vm
, this, StructureChain::create(vm
, prototype
.isNull() ? 0 : asObject(prototype
)->structure())); 
 190     return m_cachedPrototypeChain
.get(); 
 193 inline StructureChain
* Structure::prototypeChain(ExecState
* exec
) const 
 195     return prototypeChain(exec
->vm(), exec
->lexicalGlobalObject()); 
 198 inline bool Structure::isValid(JSGlobalObject
* globalObject
, StructureChain
* cachedPrototypeChain
) const 
 200     if (!cachedPrototypeChain
) 
 203     JSValue prototype 
= prototypeForLookup(globalObject
); 
 204     WriteBarrier
<Structure
>* cachedStructure 
= cachedPrototypeChain
->head(); 
 205     while (*cachedStructure 
&& !prototype
.isNull()) { 
 206         if (asObject(prototype
)->structure() != cachedStructure
->get()) 
 209         prototype 
= asObject(prototype
)->prototype(); 
 211     return prototype
.isNull() && !*cachedStructure
; 
 214 inline bool Structure::isValid(ExecState
* exec
, StructureChain
* cachedPrototypeChain
) const 
 216     return isValid(exec
->lexicalGlobalObject(), cachedPrototypeChain
); 
 219 inline bool Structure::putWillGrowOutOfLineStorage() 
 221     checkOffsetConsistency(); 
 223     ASSERT(outOfLineCapacity() >= outOfLineSize()); 
 225     if (!propertyTable()) { 
 226         unsigned currentSize 
= numberOfOutOfLineSlotsForLastOffset(m_offset
); 
 227         ASSERT(outOfLineCapacity() >= currentSize
); 
 228         return currentSize 
== outOfLineCapacity(); 
 231     ASSERT(totalStorageCapacity() >= propertyTable()->propertyStorageSize()); 
 232     if (propertyTable()->hasDeletedOffset()) 
 235     ASSERT(totalStorageCapacity() >= propertyTable()->size()); 
 236     return propertyTable()->size() == totalStorageCapacity(); 
 239 ALWAYS_INLINE WriteBarrier
<PropertyTable
>& Structure::propertyTable() 
 241     ASSERT(!globalObject() || !globalObject()->vm().heap
.isCollecting()); 
 242     return m_propertyTableUnsafe
; 
 245 ALWAYS_INLINE 
bool Structure::checkOffsetConsistency() const 
 247     PropertyTable
* propertyTable 
= m_propertyTableUnsafe
.get(); 
 249     if (!propertyTable
) { 
 250         ASSERT(!m_isPinnedPropertyTable
); 
 254     // We cannot reliably assert things about the property table in the concurrent 
 255     // compilation thread. It is possible for the table to be stolen and then have 
 256     // things added to it, which leads to the offsets being all messed up. We could 
 257     // get around this by grabbing a lock here, but I think that would be overkill. 
 258     if (isCompilationThread()) 
 261     RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset
, m_inlineCapacity
) == propertyTable
->propertyStorageSize()); 
 262     unsigned totalSize 
= propertyTable
->propertyStorageSize(); 
 263     RELEASE_ASSERT((totalSize 
< inlineCapacity() ? 0 : totalSize 
- inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset
)); 
 268 inline size_t nextOutOfLineStorageCapacity(size_t currentCapacity
) 
 270     if (!currentCapacity
) 
 271         return initialOutOfLineCapacity
; 
 272     return currentCapacity 
* outOfLineGrowthFactor
; 
 275 inline size_t Structure::suggestedNewOutOfLineStorageCapacity() 
 277     return nextOutOfLineStorageCapacity(outOfLineCapacity()); 
 282 #endif // StructureInlines_h