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 "CallFrame.h"
31 #include "JSNumberCell.h"
32 #include "MarkStack.h"
33 #include "PropertySlot.h"
34 #include "PutPropertySlot.h"
35 #include "ScopeChain.h"
36 #include "Structure.h"
37 #include "JSGlobalData.h"
38 #include <wtf/StdLibExtras.h>
42 inline JSCell
* getJSFunction(JSGlobalData
& globalData
, JSValue value
)
44 if (value
.isCell() && (value
.asCell()->vptr() == globalData
.jsFunctionVPtr
))
45 return value
.asCell();
50 class InternalFunction
;
51 class PropertyDescriptor
;
52 class PropertyNameArray
;
57 // Property attributes
60 ReadOnly
= 1 << 1, // property can be only read, not written
61 DontEnum
= 1 << 2, // property doesn't appear in (for .. in ..)
62 DontDelete
= 1 << 3, // property can't be deleted
63 Function
= 1 << 4, // property is a function - only used by static hashtables
64 Getter
= 1 << 5, // property is a getter
65 Setter
= 1 << 6 // property is a setter
68 typedef EncodedJSValue
* PropertyStorage
;
69 typedef const EncodedJSValue
* ConstPropertyStorage
;
71 class JSObject
: public JSCell
{
72 friend class BatchedTransitionOptimizer
;
77 explicit JSObject(NonNullPassRefPtr
<Structure
>);
79 virtual void markChildren(MarkStack
&);
80 ALWAYS_INLINE
void markChildrenDirect(MarkStack
& markStack
);
82 // The inline virtual destructor cannot be the first virtual function declared
83 // in the class as it results in the vtable being generated as a weak symbol
86 JSValue
prototype() const;
87 void setPrototype(JSValue prototype
);
89 void setStructure(NonNullPassRefPtr
<Structure
>);
90 Structure
* inheritorID();
92 virtual UString
className() const;
94 JSValue
get(ExecState
*, const Identifier
& propertyName
) const;
95 JSValue
get(ExecState
*, unsigned propertyName
) const;
97 bool getPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
98 bool getPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
99 bool getPropertyDescriptor(ExecState
*, const Identifier
& propertyName
, PropertyDescriptor
&);
101 virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
102 virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
103 virtual bool getOwnPropertyDescriptor(ExecState
*, const Identifier
&, PropertyDescriptor
&);
105 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
&);
106 virtual void put(ExecState
*, unsigned propertyName
, JSValue value
);
108 virtual void putWithAttributes(ExecState
*, const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
);
109 virtual void putWithAttributes(ExecState
*, const Identifier
& propertyName
, JSValue value
, unsigned attributes
);
110 virtual void putWithAttributes(ExecState
*, unsigned propertyName
, JSValue value
, unsigned attributes
);
112 bool propertyIsEnumerable(ExecState
*, const Identifier
& propertyName
) const;
114 bool hasProperty(ExecState
*, const Identifier
& propertyName
) const;
115 bool hasProperty(ExecState
*, unsigned propertyName
) const;
116 bool hasOwnProperty(ExecState
*, const Identifier
& propertyName
) const;
118 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
119 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
121 virtual JSValue
defaultValue(ExecState
*, PreferredPrimitiveType
) const;
123 virtual bool hasInstance(ExecState
*, JSValue
, JSValue prototypeProperty
);
125 virtual void getPropertyNames(ExecState
*, PropertyNameArray
&, EnumerationMode mode
= ExcludeDontEnumProperties
);
126 virtual void getOwnPropertyNames(ExecState
*, PropertyNameArray
&, EnumerationMode mode
= ExcludeDontEnumProperties
);
128 virtual JSValue
toPrimitive(ExecState
*, PreferredPrimitiveType
= NoPreference
) const;
129 virtual bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
& value
);
130 virtual bool toBoolean(ExecState
*) const;
131 virtual double toNumber(ExecState
*) const;
132 virtual UString
toString(ExecState
*) const;
133 virtual JSObject
* toObject(ExecState
*) const;
135 virtual JSObject
* toThisObject(ExecState
*) const;
136 virtual JSObject
* unwrappedObject();
138 bool getPropertySpecificValue(ExecState
* exec
, const Identifier
& propertyName
, JSCell
*& specificFunction
) const;
140 // This get function only looks at the property map.
141 JSValue
getDirect(const Identifier
& propertyName
) const
143 size_t offset
= m_structure
->get(propertyName
);
144 return offset
!= WTF::notFound
? getDirectOffset(offset
) : JSValue();
147 JSValue
* getDirectLocation(const Identifier
& propertyName
)
149 size_t offset
= m_structure
->get(propertyName
);
150 return offset
!= WTF::notFound
? locationForOffset(offset
) : 0;
153 JSValue
* getDirectLocation(const Identifier
& propertyName
, unsigned& attributes
)
155 JSCell
* specificFunction
;
156 size_t offset
= m_structure
->get(propertyName
, attributes
, specificFunction
);
157 return offset
!= WTF::notFound
? locationForOffset(offset
) : 0;
160 size_t offsetForLocation(JSValue
* location
) const
162 return location
- reinterpret_cast<const JSValue
*>(propertyStorage());
165 void transitionTo(Structure
*);
167 void removeDirect(const Identifier
& propertyName
);
168 bool hasCustomProperties() { return !m_structure
->isEmpty(); }
169 bool hasGetterSetterProperties() { return m_structure
->hasGetterSetterProperties(); }
171 void putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
);
172 void putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attr
= 0);
174 void putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
= 0);
175 void putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
);
176 void putDirectFunction(ExecState
* exec
, InternalFunction
* function
, unsigned attr
= 0);
178 void putDirectWithoutTransition(const Identifier
& propertyName
, JSValue value
, unsigned attr
= 0);
179 void putDirectFunctionWithoutTransition(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
= 0);
180 void putDirectFunctionWithoutTransition(ExecState
* exec
, InternalFunction
* function
, unsigned attr
= 0);
182 // Fast access to known property offsets.
183 JSValue
getDirectOffset(size_t offset
) const { return JSValue::decode(propertyStorage()[offset
]); }
184 void putDirectOffset(size_t offset
, JSValue value
) { propertyStorage()[offset
] = JSValue::encode(value
); }
186 void fillGetterPropertySlot(PropertySlot
&, JSValue
* location
);
188 virtual void defineGetter(ExecState
*, const Identifier
& propertyName
, JSObject
* getterFunction
, unsigned attributes
= 0);
189 virtual void defineSetter(ExecState
*, const Identifier
& propertyName
, JSObject
* setterFunction
, unsigned attributes
= 0);
190 virtual JSValue
lookupGetter(ExecState
*, const Identifier
& propertyName
);
191 virtual JSValue
lookupSetter(ExecState
*, const Identifier
& propertyName
);
192 virtual bool defineOwnProperty(ExecState
*, const Identifier
& propertyName
, PropertyDescriptor
&, bool shouldThrow
);
194 virtual bool isGlobalObject() const { return false; }
195 virtual bool isVariableObject() const { return false; }
196 virtual bool isActivationObject() const { return false; }
197 virtual bool isWatchdogException() const { return false; }
198 virtual bool isNotAnObjectErrorStub() const { return false; }
200 void allocatePropertyStorage(size_t oldSize
, size_t newSize
);
201 void allocatePropertyStorageInline(size_t oldSize
, size_t newSize
);
202 bool isUsingInlineStorage() const { return m_structure
->isUsingInlineStorage(); }
204 static const unsigned inlineStorageCapacity
= sizeof(EncodedJSValue
) == 2 * sizeof(void*) ? 4 : 3;
205 static const unsigned nonInlineBaseStorageCapacity
= 16;
207 static PassRefPtr
<Structure
> createStructure(JSValue prototype
)
209 return Structure::create(prototype
, TypeInfo(ObjectType
, StructureFlags
), AnonymousSlotCount
);
212 void flattenDictionaryObject()
214 m_structure
->flattenDictionaryStructure(this);
218 static const unsigned StructureFlags
= 0;
220 void putAnonymousValue(unsigned index
, JSValue value
)
222 ASSERT(index
< m_structure
->anonymousSlotCount());
223 *locationForOffset(index
) = value
;
225 JSValue
getAnonymousValue(unsigned index
) const
227 ASSERT(index
< m_structure
->anonymousSlotCount());
228 return *locationForOffset(index
);
232 // Nobody should ever ask any of these questions on something already known to be a JSObject.
233 using JSCell::isAPIValueWrapper
;
234 using JSCell::isGetterSetter
;
235 using JSCell::toObject
;
237 void getString(ExecState
* exec
);
244 ConstPropertyStorage
propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage
: m_externalStorage
); }
245 PropertyStorage
propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage
: m_externalStorage
); }
247 const JSValue
* locationForOffset(size_t offset
) const
249 return reinterpret_cast<const JSValue
*>(&propertyStorage()[offset
]);
252 JSValue
* locationForOffset(size_t offset
)
254 return reinterpret_cast<JSValue
*>(&propertyStorage()[offset
]);
257 void putDirectInternal(const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
, JSCell
*);
258 void putDirectInternal(JSGlobalData
&, const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
);
259 void putDirectInternal(JSGlobalData
&, const Identifier
& propertyName
, JSValue value
, unsigned attr
= 0);
261 bool inlineGetOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
263 const HashEntry
* findPropertyHashEntry(ExecState
*, const Identifier
& propertyName
) const;
264 Structure
* createInheritorID();
267 PropertyStorage m_externalStorage
;
268 EncodedJSValue m_inlineStorage
[inlineStorageCapacity
];
271 RefPtr
<Structure
> m_inheritorID
;
274 inline JSObject
* asObject(JSCell
* cell
)
276 ASSERT(cell
->isObject());
277 return static_cast<JSObject
*>(cell
);
280 inline JSObject
* asObject(JSValue value
)
282 return asObject(value
.asCell());
285 inline JSObject::JSObject(NonNullPassRefPtr
<Structure
> structure
)
286 : JSCell(structure
.releaseRef()) // ~JSObject balances this ref()
288 ASSERT(m_structure
->propertyStorageCapacity() == inlineStorageCapacity
);
289 ASSERT(m_structure
->isEmpty());
290 ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
291 #if USE(JSVALUE64) || USE(JSVALUE32_64)
292 ASSERT(OBJECT_OFFSETOF(JSObject
, m_inlineStorage
) % sizeof(double) == 0);
296 inline JSObject::~JSObject()
299 if (!isUsingInlineStorage())
300 delete [] m_externalStorage
;
301 m_structure
->deref();
304 inline JSValue
JSObject::prototype() const
306 return m_structure
->storedPrototype();
309 inline void JSObject::setPrototype(JSValue prototype
)
312 RefPtr
<Structure
> newStructure
= Structure::changePrototypeTransition(m_structure
, prototype
);
313 setStructure(newStructure
.release());
316 inline void JSObject::setStructure(NonNullPassRefPtr
<Structure
> structure
)
318 m_structure
->deref();
319 m_structure
= structure
.releaseRef(); // ~JSObject balances this ref()
322 inline Structure
* JSObject::inheritorID()
325 return m_inheritorID
.get();
326 return createInheritorID();
329 inline bool Structure::isUsingInlineStorage() const
331 return (propertyStorageCapacity() == JSObject::inlineStorageCapacity
);
334 inline bool JSCell::inherits(const ClassInfo
* info
) const
336 for (const ClassInfo
* ci
= classInfo(); ci
; ci
= ci
->parentClass
) {
343 // this method is here to be after the inline declaration of JSCell::inherits
344 inline bool JSValue::inherits(const ClassInfo
* classInfo
) const
346 return isCell() && asCell()->inherits(classInfo
);
349 ALWAYS_INLINE
bool JSObject::inlineGetOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
351 if (JSValue
* location
= getDirectLocation(propertyName
)) {
352 if (m_structure
->hasGetterSetterProperties() && location
[0].isGetterSetter())
353 fillGetterPropertySlot(slot
, location
);
355 slot
.setValueSlot(this, location
, offsetForLocation(location
));
359 // non-standard Netscape extension
360 if (propertyName
== exec
->propertyNames().underscoreProto
) {
361 slot
.setValue(prototype());
368 // It may seem crazy to inline a function this large, especially a virtual function,
369 // but it makes a big difference to property lookup that derived classes can inline their
370 // base class call to this.
371 ALWAYS_INLINE
bool JSObject::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
373 return inlineGetOwnPropertySlot(exec
, propertyName
, slot
);
376 ALWAYS_INLINE
bool JSCell::fastGetOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
378 if (!structure()->typeInfo().overridesGetOwnPropertySlot())
379 return asObject(this)->inlineGetOwnPropertySlot(exec
, propertyName
, slot
);
380 return getOwnPropertySlot(exec
, propertyName
, slot
);
383 // It may seem crazy to inline a function this large but it makes a big difference
384 // since this is function very hot in variable lookup
385 ALWAYS_INLINE
bool JSObject::getPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
387 JSObject
* object
= this;
389 if (object
->fastGetOwnPropertySlot(exec
, propertyName
, slot
))
391 JSValue prototype
= object
->prototype();
392 if (!prototype
.isObject())
394 object
= asObject(prototype
);
398 ALWAYS_INLINE
bool JSObject::getPropertySlot(ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
)
400 JSObject
* object
= this;
402 if (object
->getOwnPropertySlot(exec
, propertyName
, slot
))
404 JSValue prototype
= object
->prototype();
405 if (!prototype
.isObject())
407 object
= asObject(prototype
);
411 inline JSValue
JSObject::get(ExecState
* exec
, const Identifier
& propertyName
) const
413 PropertySlot
slot(this);
414 if (const_cast<JSObject
*>(this)->getPropertySlot(exec
, propertyName
, slot
))
415 return slot
.getValue(exec
, propertyName
);
417 return jsUndefined();
420 inline JSValue
JSObject::get(ExecState
* exec
, unsigned propertyName
) const
422 PropertySlot
slot(this);
423 if (const_cast<JSObject
*>(this)->getPropertySlot(exec
, propertyName
, slot
))
424 return slot
.getValue(exec
, propertyName
);
426 return jsUndefined();
429 inline void JSObject::putDirectInternal(const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
, JSCell
* specificFunction
)
432 ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this));
434 if (m_structure
->isDictionary()) {
435 unsigned currentAttributes
;
436 JSCell
* currentSpecificFunction
;
437 size_t offset
= m_structure
->get(propertyName
, currentAttributes
, currentSpecificFunction
);
438 if (offset
!= WTF::notFound
) {
439 if (currentSpecificFunction
&& (specificFunction
!= currentSpecificFunction
))
440 m_structure
->despecifyDictionaryFunction(propertyName
);
441 if (checkReadOnly
&& currentAttributes
& ReadOnly
)
443 putDirectOffset(offset
, value
);
444 if (!specificFunction
&& !currentSpecificFunction
)
445 slot
.setExistingProperty(this, offset
);
449 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
450 offset
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, specificFunction
);
451 if (currentCapacity
!= m_structure
->propertyStorageCapacity())
452 allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity());
454 ASSERT(offset
< m_structure
->propertyStorageCapacity());
455 putDirectOffset(offset
, value
);
456 // See comment on setNewProperty call below.
457 if (!specificFunction
)
458 slot
.setNewProperty(this, offset
);
463 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
464 if (RefPtr
<Structure
> structure
= Structure::addPropertyTransitionToExistingStructure(m_structure
, propertyName
, attributes
, specificFunction
, offset
)) {
465 if (currentCapacity
!= structure
->propertyStorageCapacity())
466 allocatePropertyStorage(currentCapacity
, structure
->propertyStorageCapacity());
468 ASSERT(offset
< structure
->propertyStorageCapacity());
469 setStructure(structure
.release());
470 putDirectOffset(offset
, value
);
471 // See comment on setNewProperty call below.
472 if (!specificFunction
)
473 slot
.setNewProperty(this, offset
);
477 unsigned currentAttributes
;
478 JSCell
* currentSpecificFunction
;
479 offset
= m_structure
->get(propertyName
, currentAttributes
, currentSpecificFunction
);
480 if (offset
!= WTF::notFound
) {
481 if (checkReadOnly
&& currentAttributes
& ReadOnly
)
484 if (currentSpecificFunction
&& (specificFunction
!= currentSpecificFunction
)) {
485 setStructure(Structure::despecifyFunctionTransition(m_structure
, propertyName
));
486 putDirectOffset(offset
, value
);
487 // Function transitions are not currently cachable, so leave the slot in an uncachable state.
490 putDirectOffset(offset
, value
);
491 slot
.setExistingProperty(this, offset
);
495 // If we have a specific function, we may have got to this point if there is
496 // already a transition with the correct property name and attributes, but
497 // specialized to a different function. In this case we just want to give up
498 // and despecialize the transition.
499 // In this case we clear the value of specificFunction which will result
500 // in us adding a non-specific transition, and any subsequent lookup in
501 // Structure::addPropertyTransitionToExistingStructure will just use that.
502 if (specificFunction
&& m_structure
->hasTransition(propertyName
, attributes
))
503 specificFunction
= 0;
505 RefPtr
<Structure
> structure
= Structure::addPropertyTransition(m_structure
, propertyName
, attributes
, specificFunction
, offset
);
507 if (currentCapacity
!= structure
->propertyStorageCapacity())
508 allocatePropertyStorage(currentCapacity
, structure
->propertyStorageCapacity());
510 ASSERT(offset
< structure
->propertyStorageCapacity());
511 setStructure(structure
.release());
512 putDirectOffset(offset
, value
);
513 // Function transitions are not currently cachable, so leave the slot in an uncachable state.
514 if (!specificFunction
)
515 slot
.setNewProperty(this, offset
);
518 inline void JSObject::putDirectInternal(JSGlobalData
& globalData
, const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
)
521 ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this));
523 putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, getJSFunction(globalData
, value
));
526 inline void JSObject::putDirectInternal(JSGlobalData
& globalData
, const Identifier
& propertyName
, JSValue value
, unsigned attributes
)
528 PutPropertySlot slot
;
529 putDirectInternal(propertyName
, value
, attributes
, false, slot
, getJSFunction(globalData
, value
));
532 inline void JSObject::putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
)
535 ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this));
537 putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, 0);
540 inline void JSObject::putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attributes
)
542 PutPropertySlot slot
;
543 putDirectInternal(propertyName
, value
, attributes
, false, slot
, 0);
546 inline void JSObject::putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
)
548 putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, value
);
551 inline void JSObject::putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
)
553 PutPropertySlot slot
;
554 putDirectInternal(propertyName
, value
, attr
, false, slot
, value
);
557 inline void JSObject::putDirectWithoutTransition(const Identifier
& propertyName
, JSValue value
, unsigned attributes
)
559 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
560 size_t offset
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, 0);
561 if (currentCapacity
!= m_structure
->propertyStorageCapacity())
562 allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity());
563 putDirectOffset(offset
, value
);
566 inline void JSObject::putDirectFunctionWithoutTransition(const Identifier
& propertyName
, JSCell
* value
, unsigned attributes
)
568 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
569 size_t offset
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, value
);
570 if (currentCapacity
!= m_structure
->propertyStorageCapacity())
571 allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity());
572 putDirectOffset(offset
, value
);
575 inline void JSObject::transitionTo(Structure
* newStructure
)
577 if (m_structure
->propertyStorageCapacity() != newStructure
->propertyStorageCapacity())
578 allocatePropertyStorage(m_structure
->propertyStorageCapacity(), newStructure
->propertyStorageCapacity());
579 setStructure(newStructure
);
582 inline JSValue
JSObject::toPrimitive(ExecState
* exec
, PreferredPrimitiveType preferredType
) const
584 return defaultValue(exec
, preferredType
);
587 inline JSValue
JSValue::get(ExecState
* exec
, const Identifier
& propertyName
) const
589 PropertySlot
slot(asValue());
590 return get(exec
, propertyName
, slot
);
593 inline JSValue
JSValue::get(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) const
595 if (UNLIKELY(!isCell())) {
596 JSObject
* prototype
= synthesizePrototype(exec
);
597 if (propertyName
== exec
->propertyNames().underscoreProto
)
599 if (!prototype
->getPropertySlot(exec
, propertyName
, slot
))
600 return jsUndefined();
601 return slot
.getValue(exec
, propertyName
);
603 JSCell
* cell
= asCell();
605 if (cell
->fastGetOwnPropertySlot(exec
, propertyName
, slot
))
606 return slot
.getValue(exec
, propertyName
);
607 JSValue prototype
= asObject(cell
)->prototype();
608 if (!prototype
.isObject())
609 return jsUndefined();
610 cell
= asObject(prototype
);
614 inline JSValue
JSValue::get(ExecState
* exec
, unsigned propertyName
) const
616 PropertySlot
slot(asValue());
617 return get(exec
, propertyName
, slot
);
620 inline JSValue
JSValue::get(ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
) const
622 if (UNLIKELY(!isCell())) {
623 JSObject
* prototype
= synthesizePrototype(exec
);
624 if (!prototype
->getPropertySlot(exec
, propertyName
, slot
))
625 return jsUndefined();
626 return slot
.getValue(exec
, propertyName
);
628 JSCell
* cell
= const_cast<JSCell
*>(asCell());
630 if (cell
->getOwnPropertySlot(exec
, propertyName
, slot
))
631 return slot
.getValue(exec
, propertyName
);
632 JSValue prototype
= asObject(cell
)->prototype();
633 if (!prototype
.isObject())
634 return jsUndefined();
635 cell
= prototype
.asCell();
639 inline void JSValue::put(ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
)
641 if (UNLIKELY(!isCell())) {
642 synthesizeObject(exec
)->put(exec
, propertyName
, value
, slot
);
645 asCell()->put(exec
, propertyName
, value
, slot
);
648 inline void JSValue::put(ExecState
* exec
, unsigned propertyName
, JSValue value
)
650 if (UNLIKELY(!isCell())) {
651 synthesizeObject(exec
)->put(exec
, propertyName
, value
);
654 asCell()->put(exec
, propertyName
, value
);
657 ALWAYS_INLINE
void JSObject::allocatePropertyStorageInline(size_t oldSize
, size_t newSize
)
659 ASSERT(newSize
> oldSize
);
661 // It's important that this function not rely on m_structure, since
662 // we might be in the middle of a transition.
663 bool wasInline
= (oldSize
== JSObject::inlineStorageCapacity
);
665 PropertyStorage oldPropertyStorage
= (wasInline
? m_inlineStorage
: m_externalStorage
);
666 PropertyStorage newPropertyStorage
= new EncodedJSValue
[newSize
];
668 for (unsigned i
= 0; i
< oldSize
; ++i
)
669 newPropertyStorage
[i
] = oldPropertyStorage
[i
];
672 delete [] oldPropertyStorage
;
674 m_externalStorage
= newPropertyStorage
;
677 ALWAYS_INLINE
void JSObject::markChildrenDirect(MarkStack
& markStack
)
679 JSCell::markChildren(markStack
);
681 markStack
.append(prototype());
683 PropertyStorage storage
= propertyStorage();
684 size_t storageSize
= m_structure
->propertyStorageSize();
685 markStack
.appendValues(reinterpret_cast<JSValue
*>(storage
), storageSize
);