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 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"
30 #include "JSNumberCell.h"
31 #include "PropertySlot.h"
32 #include "PutPropertySlot.h"
33 #include "ScopeChain.h"
34 #include "Structure.h"
35 #include "JSGlobalData.h"
36 #include <wtf/StdLibExtras.h>
40 inline JSCell
* getJSFunction(JSGlobalData
& globalData
, JSValue value
)
42 if (value
.isCell() && (value
.asCell()->vptr() == globalData
.jsFunctionVPtr
))
43 return value
.asCell();
47 class InternalFunction
;
48 class PropertyNameArray
;
54 // Property attributes
57 ReadOnly
= 1 << 1, // property can be only read, not written
58 DontEnum
= 1 << 2, // property doesn't appear in (for .. in ..)
59 DontDelete
= 1 << 3, // property can't be deleted
60 Function
= 1 << 4, // property is a function - only used by static hashtables
61 Getter
= 1 << 5, // property is a getter
62 Setter
= 1 << 6 // property is a setter
65 typedef EncodedJSValue
* PropertyStorage
;
66 typedef const EncodedJSValue
* ConstPropertyStorage
;
68 class JSObject
: public JSCell
{
69 friend class BatchedTransitionOptimizer
;
74 explicit JSObject(PassRefPtr
<Structure
>);
78 // The inline virtual destructor cannot be the first virtual function declared
79 // in the class as it results in the vtable being generated as a weak symbol
82 bool inherits(const ClassInfo
* classInfo
) const { return JSCell::isObject(classInfo
); }
84 JSValue
prototype() const;
85 void setPrototype(JSValue prototype
);
87 void setStructure(PassRefPtr
<Structure
>);
88 Structure
* inheritorID();
90 virtual UString
className() const;
92 JSValue
get(ExecState
*, const Identifier
& propertyName
) const;
93 JSValue
get(ExecState
*, unsigned propertyName
) const;
95 bool getPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
96 bool getPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
98 virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
99 virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
101 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
&);
102 virtual void put(ExecState
*, unsigned propertyName
, JSValue value
);
104 virtual void putWithAttributes(ExecState
*, const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
);
105 virtual void putWithAttributes(ExecState
*, const Identifier
& propertyName
, JSValue value
, unsigned attributes
);
106 virtual void putWithAttributes(ExecState
*, unsigned propertyName
, JSValue value
, unsigned attributes
);
108 bool propertyIsEnumerable(ExecState
*, const Identifier
& propertyName
) const;
110 bool hasProperty(ExecState
*, const Identifier
& propertyName
) const;
111 bool hasProperty(ExecState
*, unsigned propertyName
) const;
112 bool hasOwnProperty(ExecState
*, const Identifier
& propertyName
) const;
114 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
115 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
117 virtual JSValue
defaultValue(ExecState
*, PreferredPrimitiveType
) const;
119 virtual bool hasInstance(ExecState
*, JSValue
, JSValue prototypeProperty
);
121 virtual void getPropertyNames(ExecState
*, PropertyNameArray
&);
123 virtual JSValue
toPrimitive(ExecState
*, PreferredPrimitiveType
= NoPreference
) const;
124 virtual bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
& value
);
125 virtual bool toBoolean(ExecState
*) const;
126 virtual double toNumber(ExecState
*) const;
127 virtual UString
toString(ExecState
*) const;
128 virtual JSObject
* toObject(ExecState
*) const;
130 virtual JSObject
* toThisObject(ExecState
*) const;
131 virtual JSObject
* unwrappedObject();
133 virtual bool getPropertyAttributes(ExecState
*, const Identifier
& propertyName
, unsigned& attributes
) const;
134 bool getPropertySpecificValue(ExecState
* exec
, const Identifier
& propertyName
, JSCell
*& specificFunction
) const;
136 // This get function only looks at the property map.
137 JSValue
getDirect(const Identifier
& propertyName
) const
139 size_t offset
= m_structure
->get(propertyName
);
140 return offset
!= WTF::notFound
? getDirectOffset(offset
) : JSValue();
143 JSValue
* getDirectLocation(const Identifier
& propertyName
)
145 size_t offset
= m_structure
->get(propertyName
);
146 return offset
!= WTF::notFound
? locationForOffset(offset
) : 0;
149 JSValue
* getDirectLocation(const Identifier
& propertyName
, unsigned& attributes
)
151 JSCell
* specificFunction
;
152 size_t offset
= m_structure
->get(propertyName
, attributes
, specificFunction
);
153 return offset
!= WTF::notFound
? locationForOffset(offset
) : 0;
156 size_t offsetForLocation(JSValue
* location
) const
158 return location
- reinterpret_cast<const JSValue
*>(propertyStorage());
161 void transitionTo(Structure
*);
163 void removeDirect(const Identifier
& propertyName
);
164 bool hasCustomProperties() { return !m_structure
->isEmpty(); }
165 bool hasGetterSetterProperties() { return m_structure
->hasGetterSetterProperties(); }
167 void putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
);
168 void putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attr
= 0);
170 void putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
= 0);
171 void putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
);
172 void putDirectFunction(ExecState
* exec
, InternalFunction
* function
, unsigned attr
= 0);
174 void putDirectWithoutTransition(const Identifier
& propertyName
, JSValue value
, unsigned attr
= 0);
175 void putDirectFunctionWithoutTransition(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
= 0);
176 void putDirectFunctionWithoutTransition(ExecState
* exec
, InternalFunction
* function
, unsigned attr
= 0);
178 // Fast access to known property offsets.
179 JSValue
getDirectOffset(size_t offset
) const { return JSValue::decode(propertyStorage()[offset
]); }
180 void putDirectOffset(size_t offset
, JSValue value
) { propertyStorage()[offset
] = JSValue::encode(value
); }
182 void fillGetterPropertySlot(PropertySlot
&, JSValue
* location
);
184 virtual void defineGetter(ExecState
*, const Identifier
& propertyName
, JSObject
* getterFunction
);
185 virtual void defineSetter(ExecState
*, const Identifier
& propertyName
, JSObject
* setterFunction
);
186 virtual JSValue
lookupGetter(ExecState
*, const Identifier
& propertyName
);
187 virtual JSValue
lookupSetter(ExecState
*, const Identifier
& propertyName
);
189 virtual bool isGlobalObject() const { return false; }
190 virtual bool isVariableObject() const { return false; }
191 virtual bool isActivationObject() const { return false; }
192 virtual bool isWatchdogException() const { return false; }
193 virtual bool isNotAnObjectErrorStub() const { return false; }
195 void allocatePropertyStorage(size_t oldSize
, size_t newSize
);
196 void allocatePropertyStorageInline(size_t oldSize
, size_t newSize
);
197 bool isUsingInlineStorage() const { return m_structure
->isUsingInlineStorage(); }
199 static const size_t inlineStorageCapacity
= sizeof(EncodedJSValue
) == 2 * sizeof(void*) ? 4 : 3;
200 static const size_t nonInlineBaseStorageCapacity
= 16;
202 static PassRefPtr
<Structure
> createStructure(JSValue prototype
)
204 return Structure::create(prototype
, TypeInfo(ObjectType
, HasStandardGetOwnPropertySlot
));
207 void flattenDictionaryObject()
209 m_structure
->flattenDictionaryStructure(this);
213 ConstPropertyStorage
propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage
: m_externalStorage
); }
214 PropertyStorage
propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage
: m_externalStorage
); }
216 const JSValue
* locationForOffset(size_t offset
) const
218 return reinterpret_cast<const JSValue
*>(&propertyStorage()[offset
]);
221 JSValue
* locationForOffset(size_t offset
)
223 return reinterpret_cast<JSValue
*>(&propertyStorage()[offset
]);
226 void putDirectInternal(const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
, JSCell
*);
227 void putDirectInternal(JSGlobalData
&, const Identifier
& propertyName
, JSValue value
, unsigned attr
, bool checkReadOnly
, PutPropertySlot
& slot
);
228 void putDirectInternal(JSGlobalData
&, const Identifier
& propertyName
, JSValue value
, unsigned attr
= 0);
230 bool inlineGetOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
232 const HashEntry
* findPropertyHashEntry(ExecState
*, const Identifier
& propertyName
) const;
233 Structure
* createInheritorID();
236 PropertyStorage m_externalStorage
;
237 EncodedJSValue m_inlineStorage
[inlineStorageCapacity
];
240 RefPtr
<Structure
> m_inheritorID
;
243 JSObject
* constructEmptyObject(ExecState
*);
245 inline JSObject
* asObject(JSValue value
)
247 ASSERT(asCell(value
)->isObject());
248 return static_cast<JSObject
*>(asCell(value
));
251 inline JSObject::JSObject(PassRefPtr
<Structure
> structure
)
252 : JSCell(structure
.releaseRef()) // ~JSObject balances this ref()
255 ASSERT(m_structure
->propertyStorageCapacity() == inlineStorageCapacity
);
256 ASSERT(m_structure
->isEmpty());
257 ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
258 #if USE(JSVALUE64) || USE(JSVALUE32_64)
259 ASSERT(OBJECT_OFFSETOF(JSObject
, m_inlineStorage
) % sizeof(double) == 0);
263 inline JSObject::~JSObject()
266 if (!isUsingInlineStorage())
267 delete [] m_externalStorage
;
268 m_structure
->deref();
271 inline JSValue
JSObject::prototype() const
273 return m_structure
->storedPrototype();
276 inline void JSObject::setPrototype(JSValue prototype
)
279 RefPtr
<Structure
> newStructure
= Structure::changePrototypeTransition(m_structure
, prototype
);
280 setStructure(newStructure
.release());
283 inline void JSObject::setStructure(PassRefPtr
<Structure
> structure
)
285 m_structure
->deref();
286 m_structure
= structure
.releaseRef(); // ~JSObject balances this ref()
289 inline Structure
* JSObject::inheritorID()
292 return m_inheritorID
.get();
293 return createInheritorID();
296 inline bool Structure::isUsingInlineStorage() const
298 return (propertyStorageCapacity() == JSObject::inlineStorageCapacity
);
301 inline bool JSCell::isObject(const ClassInfo
* info
) const
303 for (const ClassInfo
* ci
= classInfo(); ci
; ci
= ci
->parentClass
) {
310 // this method is here to be after the inline declaration of JSCell::isObject
311 inline bool JSValue::isObject(const ClassInfo
* classInfo
) const
313 return isCell() && asCell()->isObject(classInfo
);
316 ALWAYS_INLINE
bool JSObject::inlineGetOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
318 if (JSValue
* location
= getDirectLocation(propertyName
)) {
319 if (m_structure
->hasGetterSetterProperties() && location
[0].isGetterSetter())
320 fillGetterPropertySlot(slot
, location
);
322 slot
.setValueSlot(this, location
, offsetForLocation(location
));
326 // non-standard Netscape extension
327 if (propertyName
== exec
->propertyNames().underscoreProto
) {
328 slot
.setValue(prototype());
335 // It may seem crazy to inline a function this large, especially a virtual function,
336 // but it makes a big difference to property lookup that derived classes can inline their
337 // base class call to this.
338 ALWAYS_INLINE
bool JSObject::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
340 return inlineGetOwnPropertySlot(exec
, propertyName
, slot
);
343 ALWAYS_INLINE
bool JSCell::fastGetOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
345 if (structure()->typeInfo().hasStandardGetOwnPropertySlot())
346 return asObject(this)->inlineGetOwnPropertySlot(exec
, propertyName
, slot
);
347 return getOwnPropertySlot(exec
, propertyName
, slot
);
350 // It may seem crazy to inline a function this large but it makes a big difference
351 // since this is function very hot in variable lookup
352 inline bool JSObject::getPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
354 JSObject
* object
= this;
356 if (object
->fastGetOwnPropertySlot(exec
, propertyName
, slot
))
358 JSValue prototype
= object
->prototype();
359 if (!prototype
.isObject())
361 object
= asObject(prototype
);
365 inline bool JSObject::getPropertySlot(ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
)
367 JSObject
* object
= this;
369 if (object
->getOwnPropertySlot(exec
, propertyName
, slot
))
371 JSValue prototype
= object
->prototype();
372 if (!prototype
.isObject())
374 object
= asObject(prototype
);
378 inline JSValue
JSObject::get(ExecState
* exec
, const Identifier
& propertyName
) const
380 PropertySlot
slot(this);
381 if (const_cast<JSObject
*>(this)->getPropertySlot(exec
, propertyName
, slot
))
382 return slot
.getValue(exec
, propertyName
);
384 return jsUndefined();
387 inline JSValue
JSObject::get(ExecState
* exec
, unsigned propertyName
) const
389 PropertySlot
slot(this);
390 if (const_cast<JSObject
*>(this)->getPropertySlot(exec
, propertyName
, slot
))
391 return slot
.getValue(exec
, propertyName
);
393 return jsUndefined();
396 inline void JSObject::putDirectInternal(const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
, JSCell
* specificFunction
)
399 ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this));
401 if (m_structure
->isDictionary()) {
402 unsigned currentAttributes
;
403 JSCell
* currentSpecificFunction
;
404 size_t offset
= m_structure
->get(propertyName
, currentAttributes
, currentSpecificFunction
);
405 if (offset
!= WTF::notFound
) {
406 if (currentSpecificFunction
&& (specificFunction
!= currentSpecificFunction
))
407 m_structure
->despecifyDictionaryFunction(propertyName
);
408 if (checkReadOnly
&& currentAttributes
& ReadOnly
)
410 putDirectOffset(offset
, value
);
411 if (!specificFunction
&& !currentSpecificFunction
)
412 slot
.setExistingProperty(this, offset
);
416 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
417 offset
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, specificFunction
);
418 if (currentCapacity
!= m_structure
->propertyStorageCapacity())
419 allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity());
421 ASSERT(offset
< m_structure
->propertyStorageCapacity());
422 putDirectOffset(offset
, value
);
423 // See comment on setNewProperty call below.
424 if (!specificFunction
)
425 slot
.setNewProperty(this, offset
);
430 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
431 if (RefPtr
<Structure
> structure
= Structure::addPropertyTransitionToExistingStructure(m_structure
, propertyName
, attributes
, specificFunction
, offset
)) {
432 if (currentCapacity
!= structure
->propertyStorageCapacity())
433 allocatePropertyStorage(currentCapacity
, structure
->propertyStorageCapacity());
435 ASSERT(offset
< structure
->propertyStorageCapacity());
436 setStructure(structure
.release());
437 putDirectOffset(offset
, value
);
438 // See comment on setNewProperty call below.
439 if (!specificFunction
)
440 slot
.setNewProperty(this, offset
);
444 unsigned currentAttributes
;
445 JSCell
* currentSpecificFunction
;
446 offset
= m_structure
->get(propertyName
, currentAttributes
, currentSpecificFunction
);
447 if (offset
!= WTF::notFound
) {
448 if (checkReadOnly
&& currentAttributes
& ReadOnly
)
451 if (currentSpecificFunction
&& (specificFunction
!= currentSpecificFunction
)) {
452 setStructure(Structure::despecifyFunctionTransition(m_structure
, propertyName
));
453 putDirectOffset(offset
, value
);
454 // Function transitions are not currently cachable, so leave the slot in an uncachable state.
457 putDirectOffset(offset
, value
);
458 slot
.setExistingProperty(this, offset
);
462 // If we have a specific function, we may have got to this point if there is
463 // already a transition with the correct property name and attributes, but
464 // specialized to a different function. In this case we just want to give up
465 // and despecialize the transition.
466 // In this case we clear the value of specificFunction which will result
467 // in us adding a non-specific transition, and any subsequent lookup in
468 // Structure::addPropertyTransitionToExistingStructure will just use that.
469 if (specificFunction
&& m_structure
->hasTransition(propertyName
, attributes
))
470 specificFunction
= 0;
472 RefPtr
<Structure
> structure
= Structure::addPropertyTransition(m_structure
, propertyName
, attributes
, specificFunction
, offset
);
474 if (currentCapacity
!= structure
->propertyStorageCapacity())
475 allocatePropertyStorage(currentCapacity
, structure
->propertyStorageCapacity());
477 ASSERT(offset
< structure
->propertyStorageCapacity());
478 setStructure(structure
.release());
479 putDirectOffset(offset
, value
);
480 // Function transitions are not currently cachable, so leave the slot in an uncachable state.
481 if (!specificFunction
)
482 slot
.setNewProperty(this, offset
);
485 inline void JSObject::putDirectInternal(JSGlobalData
& globalData
, const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
)
488 ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this));
490 putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, getJSFunction(globalData
, value
));
493 inline void JSObject::putDirectInternal(JSGlobalData
& globalData
, const Identifier
& propertyName
, JSValue value
, unsigned attributes
)
495 PutPropertySlot slot
;
496 putDirectInternal(propertyName
, value
, attributes
, false, slot
, getJSFunction(globalData
, value
));
499 inline void JSObject::putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
)
502 ASSERT(!Heap::heap(value
) || Heap::heap(value
) == Heap::heap(this));
504 putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, 0);
507 inline void JSObject::putDirect(const Identifier
& propertyName
, JSValue value
, unsigned attributes
)
509 PutPropertySlot slot
;
510 putDirectInternal(propertyName
, value
, attributes
, false, slot
, 0);
513 inline void JSObject::putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attributes
, bool checkReadOnly
, PutPropertySlot
& slot
)
515 putDirectInternal(propertyName
, value
, attributes
, checkReadOnly
, slot
, value
);
518 inline void JSObject::putDirectFunction(const Identifier
& propertyName
, JSCell
* value
, unsigned attr
)
520 PutPropertySlot slot
;
521 putDirectInternal(propertyName
, value
, attr
, false, slot
, value
);
524 inline void JSObject::putDirectWithoutTransition(const Identifier
& propertyName
, JSValue value
, unsigned attributes
)
526 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
527 size_t offset
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, 0);
528 if (currentCapacity
!= m_structure
->propertyStorageCapacity())
529 allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity());
530 putDirectOffset(offset
, value
);
533 inline void JSObject::putDirectFunctionWithoutTransition(const Identifier
& propertyName
, JSCell
* value
, unsigned attributes
)
535 size_t currentCapacity
= m_structure
->propertyStorageCapacity();
536 size_t offset
= m_structure
->addPropertyWithoutTransition(propertyName
, attributes
, value
);
537 if (currentCapacity
!= m_structure
->propertyStorageCapacity())
538 allocatePropertyStorage(currentCapacity
, m_structure
->propertyStorageCapacity());
539 putDirectOffset(offset
, value
);
542 inline void JSObject::transitionTo(Structure
* newStructure
)
544 if (m_structure
->propertyStorageCapacity() != newStructure
->propertyStorageCapacity())
545 allocatePropertyStorage(m_structure
->propertyStorageCapacity(), newStructure
->propertyStorageCapacity());
546 setStructure(newStructure
);
549 inline JSValue
JSObject::toPrimitive(ExecState
* exec
, PreferredPrimitiveType preferredType
) const
551 return defaultValue(exec
, preferredType
);
554 inline JSValue
JSValue::get(ExecState
* exec
, const Identifier
& propertyName
) const
556 PropertySlot
slot(asValue());
557 return get(exec
, propertyName
, slot
);
560 inline JSValue
JSValue::get(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) const
562 if (UNLIKELY(!isCell())) {
563 JSObject
* prototype
= synthesizePrototype(exec
);
564 if (propertyName
== exec
->propertyNames().underscoreProto
)
566 if (!prototype
->getPropertySlot(exec
, propertyName
, slot
))
567 return jsUndefined();
568 return slot
.getValue(exec
, propertyName
);
570 JSCell
* cell
= asCell();
572 if (cell
->fastGetOwnPropertySlot(exec
, propertyName
, slot
))
573 return slot
.getValue(exec
, propertyName
);
574 ASSERT(cell
->isObject());
575 JSValue prototype
= static_cast<JSObject
*>(cell
)->prototype();
576 if (!prototype
.isObject())
577 return jsUndefined();
578 cell
= asObject(prototype
);
582 inline JSValue
JSValue::get(ExecState
* exec
, unsigned propertyName
) const
584 PropertySlot
slot(asValue());
585 return get(exec
, propertyName
, slot
);
588 inline JSValue
JSValue::get(ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
) const
590 if (UNLIKELY(!isCell())) {
591 JSObject
* prototype
= synthesizePrototype(exec
);
592 if (!prototype
->getPropertySlot(exec
, propertyName
, slot
))
593 return jsUndefined();
594 return slot
.getValue(exec
, propertyName
);
596 JSCell
* cell
= const_cast<JSCell
*>(asCell());
598 if (cell
->getOwnPropertySlot(exec
, propertyName
, slot
))
599 return slot
.getValue(exec
, propertyName
);
600 ASSERT(cell
->isObject());
601 JSValue prototype
= static_cast<JSObject
*>(cell
)->prototype();
602 if (!prototype
.isObject())
603 return jsUndefined();
604 cell
= prototype
.asCell();
608 inline void JSValue::put(ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
)
610 if (UNLIKELY(!isCell())) {
611 synthesizeObject(exec
)->put(exec
, propertyName
, value
, slot
);
614 asCell()->put(exec
, propertyName
, value
, slot
);
617 inline void JSValue::put(ExecState
* exec
, unsigned propertyName
, JSValue value
)
619 if (UNLIKELY(!isCell())) {
620 synthesizeObject(exec
)->put(exec
, propertyName
, value
);
623 asCell()->put(exec
, propertyName
, value
);
626 ALWAYS_INLINE
void JSObject::allocatePropertyStorageInline(size_t oldSize
, size_t newSize
)
628 ASSERT(newSize
> oldSize
);
630 // It's important that this function not rely on m_structure, since
631 // we might be in the middle of a transition.
632 bool wasInline
= (oldSize
== JSObject::inlineStorageCapacity
);
634 PropertyStorage oldPropertyStorage
= (wasInline
? m_inlineStorage
: m_externalStorage
);
635 PropertyStorage newPropertyStorage
= new EncodedJSValue
[newSize
];
637 for (unsigned i
= 0; i
< oldSize
; ++i
)
638 newPropertyStorage
[i
] = oldPropertyStorage
[i
];
641 delete [] oldPropertyStorage
;
643 m_externalStorage
= newPropertyStorage
;