2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 
   3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com) 
   4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 
   6  *  This library is free software; you can redistribute it and/or 
   7  *  modify it under the terms of the GNU Library General Public 
   8  *  License as published by the Free Software Foundation; either 
   9  *  version 2 of the License, or (at your option) any later version. 
  11  *  This library is distributed in the hope that it will be useful, 
  12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  14  *  Library General Public License for more details. 
  16  *  You should have received a copy of the GNU Library General Public License 
  17  *  along with this library; see the file COPYING.LIB.  If not, write to 
  18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  19  *  Boston, MA 02110-1301, USA. 
  27 #include "ClassInfo.h" 
  28 #include "CommonIdentifiers.h" 
  29 #include "Completion.h" 
  30 #include "CallFrame.h" 
  32 #include "JSNumberCell.h" 
  33 #include "MarkStack.h" 
  34 #include "PropertySlot.h" 
  35 #include "PutPropertySlot.h" 
  36 #include "ScopeChain.h" 
  37 #include "Structure.h" 
  38 #include "JSGlobalData.h" 
  40 #include <wtf/StdLibExtras.h> 
  44     inline JSCell
* getJSFunction(JSGlobalData
& globalData
, JSValue value
) 
  46         if (value
.isCell() && (value
.asCell()->vptr() == globalData
.jsFunctionVPtr
)) 
  47             return value
.asCell(); 
  52     class InternalFunction
; 
  53     class PropertyDescriptor
; 
  54     class PropertyNameArray
; 
  59     // Property attributes 
  62         ReadOnly     
= 1 << 1,  // property can be only read, not written 
  63         DontEnum     
= 1 << 2,  // property doesn't appear in (for .. in ..) 
  64         DontDelete   
= 1 << 3,  // property can't be deleted 
  65         Function     
= 1 << 4,  // property is a function - only used by static hashtables 
  66         Getter       
= 1 << 5,  // property is a getter 
  67         Setter       
= 1 << 6   // property is a setter 
  70     typedef EncodedJSValue
* PropertyStorage
; 
  71     typedef const EncodedJSValue
* ConstPropertyStorage
; 
  73     class JSObject 
: public JSCell 
{ 
  74         friend class BatchedTransitionOptimizer
; 
  79         explicit JSObject(NonNullPassRefPtr
<Structure
>); 
  81         virtual void markChildren(MarkStack
&); 
  82         ALWAYS_INLINE 
void markChildrenDirect(MarkStack
& markStack
); 
  84         // The inline virtual destructor cannot be the first virtual function declared 
  85         // in the class as it results in the vtable being generated as a weak symbol 
  88         JSValue 
prototype() const; 
  89         void setPrototype(JSValue prototype
); 
  91         void setStructure(NonNullPassRefPtr
<Structure
>); 
  92         Structure
* inheritorID(); 
  94         virtual UString 
className() const; 
  96         JSValue 
get(ExecState
*, const Identifier
& propertyName
) const; 
  97         JSValue 
get(ExecState
*, unsigned propertyName
) const; 
  99         bool getPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&); 
 100         bool getPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&); 
 101         bool getPropertyDescriptor(ExecState
*, const Identifier
& propertyName
, PropertyDescriptor
&); 
 103         virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&); 
 104         virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&); 
 105         virtual bool getOwnPropertyDescriptor(ExecState
*, const Identifier
&, PropertyDescriptor
&); 
 107         virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
&); 
 108         virtual void put(ExecState
*, unsigned propertyName
, JSValue value
); 
 110         virtual void putWithAttributes(ExecState
*, const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
); 
 111         virtual void putWithAttributes(ExecState
*, const Identifier
& propertyName
, JSValue value
, unsigned attributes
); 
 112         virtual void putWithAttributes(ExecState
*, unsigned propertyName
, JSValue value
, unsigned attributes
); 
 114         bool propertyIsEnumerable(ExecState
*, const Identifier
& propertyName
) const; 
 116         bool hasProperty(ExecState
*, const Identifier
& propertyName
) const; 
 117         bool hasProperty(ExecState
*, unsigned propertyName
) const; 
 118         bool hasOwnProperty(ExecState
*, const Identifier
& propertyName
) const; 
 120         virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
); 
 121         virtual bool deleteProperty(ExecState
*, unsigned propertyName
); 
 123         virtual JSValue 
defaultValue(ExecState
*, PreferredPrimitiveType
) const; 
 125         virtual bool hasInstance(ExecState
*, JSValue
, JSValue prototypeProperty
); 
 127         virtual void getPropertyNames(ExecState
*, PropertyNameArray
&, EnumerationMode mode 
= ExcludeDontEnumProperties
); 
 128         virtual void getOwnPropertyNames(ExecState
*, PropertyNameArray
&, EnumerationMode mode 
= ExcludeDontEnumProperties
); 
 130         virtual JSValue 
toPrimitive(ExecState
*, PreferredPrimitiveType 
= NoPreference
) const; 
 131         virtual bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
& value
); 
 132         virtual bool toBoolean(ExecState
*) const; 
 133         virtual double toNumber(ExecState
*) const; 
 134         virtual UString 
toString(ExecState
*) const; 
 135         virtual JSObject
* toObject(ExecState
*) const; 
 137         virtual JSObject
* toThisObject(ExecState
*) const; 
 138         virtual JSObject
* unwrappedObject(); 
 140         bool getPropertySpecificValue(ExecState
* exec
, const Identifier
& propertyName
, JSCell
*& specificFunction
) const; 
 142         // This get function only looks at the property map. 
 143         JSValue 
getDirect(const Identifier
& propertyName
) const 
 145             size_t offset 
= m_structure
->get(propertyName
); 
 146             return offset 
!= WTF::notFound 
? getDirectOffset(offset
) : JSValue(); 
 149         JSValue
* getDirectLocation(const Identifier
& propertyName
) 
 151             size_t offset 
= m_structure
->get(propertyName
); 
 152             return offset 
!= WTF::notFound 
? locationForOffset(offset
) : 0; 
 155         JSValue
* getDirectLocation(const Identifier
& propertyName
, unsigned& attributes
) 
 157             JSCell
* specificFunction
; 
 158             size_t offset 
= m_structure
->get(propertyName
, attributes
, specificFunction
); 
 159             return offset 
!= WTF::notFound 
? locationForOffset(offset
) : 0; 
 162         size_t offsetForLocation(JSValue
* location
) const 
 164             return location 
- reinterpret_cast<const JSValue
*>(propertyStorage()); 
 167         void transitionTo(Structure
*); 
 169         void removeDirect(const Identifier
& propertyName
); 
 170         bool hasCustomProperties() { return !m_structure
->isEmpty(); } 
 171         bool hasGetterSetterProperties() { return m_structure
->hasGetterSetterProperties(); } 
 173         void putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
); 
 174         void putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attr 
= 0); 
 175         void putDirect(const Identifier
& propertyName
, JSValue value
, PutPropertySlot
&); 
 177         void putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr 
= 0); 
 178         void putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
); 
 179         void putDirectFunction(ExecState
* exec
, InternalFunction
* function
, unsigned attr 
= 0); 
 181         void putDirectWithoutTransition(const Identifier
& propertyName
, JSValue value
, unsigned attr 
= 0); 
 182         void putDirectFunctionWithoutTransition(const Identifier
& propertyName
, JSCell
* value
, unsigned attr 
= 0); 
 183         void putDirectFunctionWithoutTransition(ExecState
* exec
, InternalFunction
* function
, unsigned attr 
= 0); 
 185         // Fast access to known property offsets. 
 186         JSValue 
getDirectOffset(size_t offset
) const { return JSValue::decode(propertyStorage()[offset
]); } 
 187         void putDirectOffset(size_t offset
, JSValue value
) { propertyStorage()[offset
] = JSValue::encode(value
); } 
 189         void fillGetterPropertySlot(PropertySlot
&, JSValue
* location
); 
 191         virtual void defineGetter(ExecState
*, const Identifier
& propertyName
, JSObject
* getterFunction
, unsigned attributes 
= 0); 
 192         virtual void defineSetter(ExecState
*, const Identifier
& propertyName
, JSObject
* setterFunction
, unsigned attributes 
= 0); 
 193         virtual JSValue 
lookupGetter(ExecState
*, const Identifier
& propertyName
); 
 194         virtual JSValue 
lookupSetter(ExecState
*, const Identifier
& propertyName
); 
 195         virtual bool defineOwnProperty(ExecState
*, const Identifier
& propertyName
, PropertyDescriptor
&, bool shouldThrow
); 
 197         virtual bool isGlobalObject() const { return false; } 
 198         virtual bool isVariableObject() const { return false; } 
 199         virtual bool isActivationObject() const { return false; } 
 200         virtual bool isNotAnObjectErrorStub() const { return false; } 
 202         virtual ComplType 
exceptionType() const { return Throw
; } 
 204         void allocatePropertyStorage(size_t oldSize
, size_t newSize
); 
 205         void allocatePropertyStorageInline(size_t oldSize
, size_t newSize
); 
 206         bool isUsingInlineStorage() const { return m_structure
->isUsingInlineStorage(); } 
 208         static const unsigned inlineStorageCapacity 
= sizeof(EncodedJSValue
) == 2 * sizeof(void*) ? 4 : 3; 
 209         static const unsigned nonInlineBaseStorageCapacity 
= 16; 
 211         static PassRefPtr
<Structure
> createStructure(JSValue prototype
) 
 213             return Structure::create(prototype
, TypeInfo(ObjectType
, StructureFlags
), AnonymousSlotCount
); 
 216         void flattenDictionaryObject() 
 218             m_structure
->flattenDictionaryStructure(this); 
 222         static const unsigned StructureFlags 
= 0; 
 224         void putAnonymousValue(unsigned index
, JSValue value
) 
 226             ASSERT(index 
< m_structure
->anonymousSlotCount()); 
 227             *locationForOffset(index
) = value
; 
 229         JSValue 
getAnonymousValue(unsigned index
) const 
 231             ASSERT(index 
< m_structure
->anonymousSlotCount()); 
 232             return *locationForOffset(index
); 
 236         // Nobody should ever ask any of these questions on something already known to be a JSObject. 
 237         using JSCell::isAPIValueWrapper
; 
 238         using JSCell::isGetterSetter
; 
 239         using JSCell::toObject
; 
 241         void getString(ExecState
* exec
); 
 248         ConstPropertyStorage 
propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage 
: m_externalStorage
); } 
 249         PropertyStorage 
propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage 
: m_externalStorage
); } 
 251         const JSValue
* locationForOffset(size_t offset
) const 
 253             return reinterpret_cast<const JSValue
*>(&propertyStorage()[offset
]); 
 256         JSValue
* locationForOffset(size_t offset
) 
 258             return reinterpret_cast<JSValue
*>(&propertyStorage()[offset
]); 
 261         void putDirectInternal(const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
, JSCell
*); 
 262         void putDirectInternal(JSGlobalData
&, const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
); 
 263         void putDirectInternal(JSGlobalData
&, const Identifier
& propertyName
, JSValue value
, unsigned attr 
= 0); 
 265         bool inlineGetOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&); 
 267         const HashEntry
* findPropertyHashEntry(ExecState
*, const Identifier
& propertyName
) const; 
 268         Structure
* createInheritorID(); 
 271             PropertyStorage m_externalStorage
; 
 272             EncodedJSValue m_inlineStorage
[inlineStorageCapacity
]; 
 275         RefPtr
<Structure
> m_inheritorID
; 
 278 inline JSObject
* asObject(JSCell
* cell
) 
 280     ASSERT(cell
->isObject()); 
 281     return static_cast<JSObject
*>(cell
); 
 284 inline JSObject
* asObject(JSValue value
) 
 286     return asObject(value
.asCell()); 
 289 inline JSObject::JSObject(NonNullPassRefPtr
<Structure
> structure
) 
 290     : JSCell(structure
.releaseRef()) // ~JSObject balances this ref() 
 292     ASSERT(m_structure
->propertyStorageCapacity() == inlineStorageCapacity
); 
 293     ASSERT(m_structure
->isEmpty()); 
 294     ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); 
 295 #if USE(JSVALUE64) || USE(JSVALUE32_64) 
 296     ASSERT(OBJECT_OFFSETOF(JSObject
, m_inlineStorage
) % sizeof(double) == 0); 
 300 inline JSObject::~JSObject() 
 303     if (!isUsingInlineStorage()) 
 304         delete [] m_externalStorage
; 
 305     m_structure
->deref(); 
 308 inline JSValue 
JSObject::prototype() const 
 310     return m_structure
->storedPrototype(); 
 313 inline void JSObject::setPrototype(JSValue prototype
) 
 316     RefPtr
<Structure
> newStructure 
= Structure::changePrototypeTransition(m_structure
, prototype
); 
 317     setStructure(newStructure
.release()); 
 320 inline void JSObject::setStructure(NonNullPassRefPtr
<Structure
> structure
) 
 322     m_structure
->deref(); 
 323     m_structure 
= structure
.releaseRef(); // ~JSObject balances this ref() 
 326 inline Structure
* JSObject::inheritorID() 
 329         return m_inheritorID
.get(); 
 330     return createInheritorID(); 
 333 inline bool Structure::isUsingInlineStorage() const 
 335     return (propertyStorageCapacity() == JSObject::inlineStorageCapacity
); 
 338 inline bool JSCell::inherits(const ClassInfo
* info
) const 
 340     for (const ClassInfo
* ci 
= classInfo(); ci
; ci 
= ci
->parentClass
) { 
 347 // this method is here to be after the inline declaration of JSCell::inherits 
 348 inline bool JSValue::inherits(const ClassInfo
* classInfo
) const 
 350     return isCell() && asCell()->inherits(classInfo
); 
 353 ALWAYS_INLINE 
bool JSObject::inlineGetOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) 
 355     if (JSValue
* location 
= getDirectLocation(propertyName
)) { 
 356         if (m_structure
->hasGetterSetterProperties() && location
[0].isGetterSetter()) 
 357             fillGetterPropertySlot(slot
, location
); 
 359             slot
.setValueSlot(this, location
, offsetForLocation(location
)); 
 363     // non-standard Netscape extension 
 364     if (propertyName 
== exec
->propertyNames().underscoreProto
) { 
 365         slot
.setValue(prototype()); 
 372 // It may seem crazy to inline a function this large, especially a virtual function, 
 373 // but it makes a big difference to property lookup that derived classes can inline their 
 374 // base class call to this. 
 375 ALWAYS_INLINE 
bool JSObject::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) 
 377     return inlineGetOwnPropertySlot(exec
, propertyName
, slot
); 
 380 ALWAYS_INLINE 
bool JSCell::fastGetOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) 
 382     if (!structure()->typeInfo().overridesGetOwnPropertySlot()) 
 383         return asObject(this)->inlineGetOwnPropertySlot(exec
, propertyName
, slot
); 
 384     return getOwnPropertySlot(exec
, propertyName
, slot
); 
 387 // It may seem crazy to inline a function this large but it makes a big difference 
 388 // since this is function very hot in variable lookup 
 389 ALWAYS_INLINE 
bool JSObject::getPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) 
 391     JSObject
* object 
= this; 
 393         if (object
->fastGetOwnPropertySlot(exec
, propertyName
, slot
)) 
 395         JSValue prototype 
= object
->prototype(); 
 396         if (!prototype
.isObject()) 
 398         object 
= asObject(prototype
); 
 402 ALWAYS_INLINE 
bool JSObject::getPropertySlot(ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
) 
 404     JSObject
* object 
= this; 
 406         if (object
->getOwnPropertySlot(exec
, propertyName
, slot
)) 
 408         JSValue prototype 
= object
->prototype(); 
 409         if (!prototype
.isObject()) 
 411         object 
= asObject(prototype
); 
 415 inline JSValue 
JSObject::get(ExecState
* exec
, const Identifier
& propertyName
) const 
 417     PropertySlot 
slot(this); 
 418     if (const_cast<JSObject
*>(this)->getPropertySlot(exec
, propertyName
, slot
)) 
 419         return slot
.getValue(exec
, propertyName
); 
 421     return jsUndefined(); 
 424 inline JSValue 
JSObject::get(ExecState
* exec
, unsigned propertyName
) const 
 426     PropertySlot 
slot(this); 
 427     if (const_cast<JSObject
*>(this)->getPropertySlot(exec
, propertyName
, slot
)) 
 428         return slot
.getValue(exec
, propertyName
); 
 430     return jsUndefined(); 
 433 inline void JSObject::putDirectInternal(const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
, JSCell
* specificFunction
) 
 436     ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this)); 
 438     if (m_structure
->isDictionary()) { 
 439         unsigned currentAttributes
; 
 440         JSCell
* currentSpecificFunction
; 
 441         size_t offset 
= m_structure
->get(propertyName
, currentAttributes
, currentSpecificFunction
); 
 442         if (offset 
!= WTF::notFound
) { 
 443             // If there is currently a specific function, and there now either isn't, 
 444             // or the new value is different, then despecify. 
 445             if (currentSpecificFunction 
&& (specificFunction 
!= currentSpecificFunction
)) 
 446                 m_structure
->despecifyDictionaryFunction(propertyName
); 
 447             if (checkReadOnly 
&& currentAttributes 
& ReadOnly
) 
 449             putDirectOffset(offset
, value
); 
 450             // At this point, the objects structure only has a specific value set if previously there 
 451             // had been one set, and if the new value being specified is the same (otherwise we would 
 452             // have despecified, above).  So, if currentSpecificFunction is not set, or if the new 
 453             // value is different (or there is no new value), then the slot now has no value - and 
 454             // as such it is cachable. 
 455             // If there was previously a value, and the new value is the same, then we cannot cache. 
 456             if (!currentSpecificFunction 
|| (specificFunction 
!= currentSpecificFunction
)) 
 457                 slot
.setExistingProperty(this, offset
); 
 461         size_t currentCapacity 
= m_structure
->propertyStorageCapacity(); 
 462         offset 
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, specificFunction
); 
 463         if (currentCapacity 
!= m_structure
->propertyStorageCapacity()) 
 464             allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity()); 
 466         ASSERT(offset 
< m_structure
->propertyStorageCapacity()); 
 467         putDirectOffset(offset
, value
); 
 468         // See comment on setNewProperty call below. 
 469         if (!specificFunction
) 
 470             slot
.setNewProperty(this, offset
); 
 475     size_t currentCapacity 
= m_structure
->propertyStorageCapacity(); 
 476     if (RefPtr
<Structure
> structure 
= Structure::addPropertyTransitionToExistingStructure(m_structure
, propertyName
, attributes
, specificFunction
, offset
)) {     
 477         if (currentCapacity 
!= structure
->propertyStorageCapacity()) 
 478             allocatePropertyStorage(currentCapacity
, structure
->propertyStorageCapacity()); 
 480         ASSERT(offset 
< structure
->propertyStorageCapacity()); 
 481         setStructure(structure
.release()); 
 482         putDirectOffset(offset
, value
); 
 483         // This is a new property; transitions with specific values are not currently cachable, 
 484         // so leave the slot in an uncachable state. 
 485         if (!specificFunction
) 
 486             slot
.setNewProperty(this, offset
); 
 490     unsigned currentAttributes
; 
 491     JSCell
* currentSpecificFunction
; 
 492     offset 
= m_structure
->get(propertyName
, currentAttributes
, currentSpecificFunction
); 
 493     if (offset 
!= WTF::notFound
) { 
 494         if (checkReadOnly 
&& currentAttributes 
& ReadOnly
) 
 497         // There are three possibilities here: 
 498         //  (1) There is an existing specific value set, and we're overwriting with *the same value*. 
 499         //       * Do nothing - no need to despecify, but that means we can't cache (a cached 
 500         //         put could write a different value). Leave the slot in an uncachable state. 
 501         //  (2) There is a specific value currently set, but we're writing a different value. 
 502         //       * First, we have to despecify.  Having done so, this is now a regular slot 
 503         //         with no specific value, so go ahead & cache like normal. 
 504         //  (3) Normal case, there is no specific value set. 
 505         //       * Go ahead & cache like normal. 
 506         if (currentSpecificFunction
) { 
 507             // case (1) Do the put, then return leaving the slot uncachable. 
 508             if (specificFunction 
== currentSpecificFunction
) { 
 509                 putDirectOffset(offset
, value
); 
 512             // case (2) Despecify, fall through to (3). 
 513             setStructure(Structure::despecifyFunctionTransition(m_structure
, propertyName
)); 
 516         // case (3) set the slot, do the put, return. 
 517         slot
.setExistingProperty(this, offset
); 
 518         putDirectOffset(offset
, value
); 
 522     // If we have a specific function, we may have got to this point if there is 
 523     // already a transition with the correct property name and attributes, but 
 524     // specialized to a different function.  In this case we just want to give up 
 525     // and despecialize the transition. 
 526     // In this case we clear the value of specificFunction which will result 
 527     // in us adding a non-specific transition, and any subsequent lookup in 
 528     // Structure::addPropertyTransitionToExistingStructure will just use that. 
 529     if (specificFunction 
&& m_structure
->hasTransition(propertyName
, attributes
)) 
 530         specificFunction 
= 0; 
 532     RefPtr
<Structure
> structure 
= Structure::addPropertyTransition(m_structure
, propertyName
, attributes
, specificFunction
, offset
); 
 534     if (currentCapacity 
!= structure
->propertyStorageCapacity()) 
 535         allocatePropertyStorage(currentCapacity
, structure
->propertyStorageCapacity()); 
 537     ASSERT(offset 
< structure
->propertyStorageCapacity()); 
 538     setStructure(structure
.release()); 
 539     putDirectOffset(offset
, value
); 
 540     // This is a new property; transitions with specific values are not currently cachable, 
 541     // so leave the slot in an uncachable state. 
 542     if (!specificFunction
) 
 543         slot
.setNewProperty(this, offset
); 
 546 inline void JSObject::putDirectInternal(JSGlobalData
& globalData
, const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
) 
 549     ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this)); 
 551     putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, getJSFunction(globalData
, value
)); 
 554 inline void JSObject::putDirectInternal(JSGlobalData
& globalData
, const Identifier
& propertyName
, JSValue value
, unsigned attributes
) 
 556     PutPropertySlot slot
; 
 557     putDirectInternal(propertyName
, value
, attributes
, false, slot
, getJSFunction(globalData
, value
)); 
 560 inline void JSObject::putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
) 
 563     ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this)); 
 565     putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, 0); 
 568 inline void JSObject::putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attributes
) 
 570     PutPropertySlot slot
; 
 571     putDirectInternal(propertyName
, value
, attributes
, false, slot
, 0); 
 574 inline void JSObject::putDirect(const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
) 
 576     putDirectInternal(propertyName
, value
, 0, false, slot
, 0); 
 579 inline void JSObject::putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
) 
 581     putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, value
); 
 584 inline void JSObject::putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
) 
 586     PutPropertySlot slot
; 
 587     putDirectInternal(propertyName
, value
, attr
, false, slot
, value
); 
 590 inline void JSObject::putDirectWithoutTransition(const Identifier
& propertyName
, JSValue value
, unsigned attributes
) 
 592     size_t currentCapacity 
= m_structure
->propertyStorageCapacity(); 
 593     size_t offset 
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, 0); 
 594     if (currentCapacity 
!= m_structure
->propertyStorageCapacity()) 
 595         allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity()); 
 596     putDirectOffset(offset
, value
); 
 599 inline void JSObject::putDirectFunctionWithoutTransition(const Identifier
& propertyName
, JSCell
* value
, unsigned attributes
) 
 601     size_t currentCapacity 
= m_structure
->propertyStorageCapacity(); 
 602     size_t offset 
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, value
); 
 603     if (currentCapacity 
!= m_structure
->propertyStorageCapacity()) 
 604         allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity()); 
 605     putDirectOffset(offset
, value
); 
 608 inline void JSObject::transitionTo(Structure
* newStructure
) 
 610     if (m_structure
->propertyStorageCapacity() != newStructure
->propertyStorageCapacity()) 
 611         allocatePropertyStorage(m_structure
->propertyStorageCapacity(), newStructure
->propertyStorageCapacity()); 
 612     setStructure(newStructure
); 
 615 inline JSValue 
JSObject::toPrimitive(ExecState
* exec
, PreferredPrimitiveType preferredType
) const 
 617     return defaultValue(exec
, preferredType
); 
 620 inline JSValue 
JSValue::get(ExecState
* exec
, const Identifier
& propertyName
) const 
 622     PropertySlot 
slot(asValue()); 
 623     return get(exec
, propertyName
, slot
); 
 626 inline JSValue 
JSValue::get(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) const 
 628     if (UNLIKELY(!isCell())) { 
 629         JSObject
* prototype 
= synthesizePrototype(exec
); 
 630         if (propertyName 
== exec
->propertyNames().underscoreProto
) 
 632         if (!prototype
->getPropertySlot(exec
, propertyName
, slot
)) 
 633             return jsUndefined(); 
 634         return slot
.getValue(exec
, propertyName
); 
 636     JSCell
* cell 
= asCell(); 
 638         if (cell
->fastGetOwnPropertySlot(exec
, propertyName
, slot
)) 
 639             return slot
.getValue(exec
, propertyName
); 
 640         JSValue prototype 
= asObject(cell
)->prototype(); 
 641         if (!prototype
.isObject()) 
 642             return jsUndefined(); 
 643         cell 
= asObject(prototype
); 
 647 inline JSValue 
JSValue::get(ExecState
* exec
, unsigned propertyName
) const 
 649     PropertySlot 
slot(asValue()); 
 650     return get(exec
, propertyName
, slot
); 
 653 inline JSValue 
JSValue::get(ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
) const 
 655     if (UNLIKELY(!isCell())) { 
 656         JSObject
* prototype 
= synthesizePrototype(exec
); 
 657         if (!prototype
->getPropertySlot(exec
, propertyName
, slot
)) 
 658             return jsUndefined(); 
 659         return slot
.getValue(exec
, propertyName
); 
 661     JSCell
* cell 
= const_cast<JSCell
*>(asCell()); 
 663         if (cell
->getOwnPropertySlot(exec
, propertyName
, slot
)) 
 664             return slot
.getValue(exec
, propertyName
); 
 665         JSValue prototype 
= asObject(cell
)->prototype(); 
 666         if (!prototype
.isObject()) 
 667             return jsUndefined(); 
 668         cell 
= prototype
.asCell(); 
 672 inline void JSValue::put(ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
) 
 674     if (UNLIKELY(!isCell())) { 
 675         synthesizeObject(exec
)->put(exec
, propertyName
, value
, slot
); 
 678     asCell()->put(exec
, propertyName
, value
, slot
); 
 681 inline void JSValue::putDirect(ExecState
*, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
) 
 683     ASSERT(isCell() && isObject()); 
 684     asObject(asCell())->putDirect(propertyName
, value
, slot
); 
 687 inline void JSValue::put(ExecState
* exec
, unsigned propertyName
, JSValue value
) 
 689     if (UNLIKELY(!isCell())) { 
 690         synthesizeObject(exec
)->put(exec
, propertyName
, value
); 
 693     asCell()->put(exec
, propertyName
, value
); 
 696 ALWAYS_INLINE 
void JSObject::allocatePropertyStorageInline(size_t oldSize
, size_t newSize
) 
 698     ASSERT(newSize 
> oldSize
); 
 700     // It's important that this function not rely on m_structure, since 
 701     // we might be in the middle of a transition. 
 702     bool wasInline 
= (oldSize 
== JSObject::inlineStorageCapacity
); 
 704     PropertyStorage oldPropertyStorage 
= (wasInline 
? m_inlineStorage 
: m_externalStorage
); 
 705     PropertyStorage newPropertyStorage 
= new EncodedJSValue
[newSize
]; 
 707     for (unsigned i 
= 0; i 
< oldSize
; ++i
) 
 708        newPropertyStorage
[i
] = oldPropertyStorage
[i
]; 
 711         delete [] oldPropertyStorage
; 
 713     m_externalStorage 
= newPropertyStorage
; 
 716 ALWAYS_INLINE 
void JSObject::markChildrenDirect(MarkStack
& markStack
) 
 718     JSCell::markChildren(markStack
); 
 720     markStack
.append(prototype()); 
 722     PropertyStorage storage 
= propertyStorage(); 
 723     size_t storageSize 
= m_structure
->propertyStorageSize(); 
 724     markStack
.appendValues(reinterpret_cast<JSValue
*>(storage
), storageSize
); 
 727 // --- JSValue inlines ---------------------------- 
 729 ALWAYS_INLINE UString 
JSValue::toThisString(ExecState
* exec
) const 
 731     return isString() ? static_cast<JSString
*>(asCell())->value(exec
) : toThisObject(exec
)->toString(exec
); 
 734 inline JSString
* JSValue::toThisJSString(ExecState
* exec
) const 
 736     return isString() ? static_cast<JSString
*>(asCell()) : jsString(exec
, toThisObject(exec
)->toString(exec
));