source: webkit/trunk/JavaScriptCore/runtime/JSObject.h@ 44171

Last change on this file since 44171 was 44171, checked in by [email protected], 16 years ago

2009-05-26 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Fix for: <rdar://problem/6918095> REGRESSION: jQuery load() issue (25981),
and also an ASSERT failure on http://ihasahotdog.com/.

When overwriting a property on a dictionary with a cached specific value,
clear the cache if new value being written is different.

Export the new symbols.

  • jit/JITStubs.cpp: (JSC::JITStubs::cti_op_get_by_id_method_check_second):

Close dictionary prototypes upon caching a method access, as would happen when caching
a regular get_by_id.

  • runtime/JSObject.h: (JSC::JSObject::propertyStorage): (JSC::JSObject::locationForOffset):

Make these methods private.

(JSC::JSObject::putDirectInternal):

When overwriting a property on a dictionary with a cached specific value,
clear the cache if new value being written is different.

  • runtime/Structure.cpp: (JSC::Structure::despecifyDictionaryFunction):

Reset the specific value field for a given property in a dictionary.

(JSC::Structure::despecifyFunctionTransition):

Rename of 'changeFunctionTransition' (this was already internally refered to as a despecification).

  • runtime/Structure.h:

Declare new method.

  • Property svn:eol-style set to native
File size: 25.5 KB
Line 
1/*
2 * Copyright (C) 1999-2001 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 *
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.
10 *
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.
15 *
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.
20 *
21 */
22
23#ifndef JSObject_h
24#define JSObject_h
25
26#include "ArgList.h"
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
37namespace JSC {
38
39 inline JSCell* getJSFunction(JSGlobalData& globalData, JSValue value)
40 {
41 if (value.isCell() && (value.asCell()->vptr() == globalData.jsFunctionVPtr))
42 return value.asCell();
43 return 0;
44 }
45
46 class InternalFunction;
47 class PropertyNameArray;
48 class Structure;
49 struct HashEntry;
50 struct HashTable;
51
52 // ECMA 262-3 8.6.1
53 // Property attributes
54 enum Attribute {
55 None = 0,
56 ReadOnly = 1 << 1, // property can be only read, not written
57 DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
58 DontDelete = 1 << 3, // property can't be deleted
59 Function = 1 << 4, // property is a function - only used by static hashtables
60 };
61
62 typedef EncodedJSValue* PropertyStorage;
63 typedef const EncodedJSValue* ConstPropertyStorage;
64
65 class JSObject : public JSCell {
66 friend class BatchedTransitionOptimizer;
67 friend class JIT;
68 friend class JSCell;
69
70 public:
71 explicit JSObject(PassRefPtr<Structure>);
72
73 virtual void mark();
74
75 // The inline virtual destructor cannot be the first virtual function declared
76 // in the class as it results in the vtable being generated as a weak symbol
77 virtual ~JSObject();
78
79 bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
80
81 JSValue prototype() const;
82 void setPrototype(JSValue prototype);
83
84 void setStructure(PassRefPtr<Structure>);
85 Structure* inheritorID();
86
87 virtual UString className() const;
88
89 JSValue get(ExecState*, const Identifier& propertyName) const;
90 JSValue get(ExecState*, unsigned propertyName) const;
91
92 bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
93 bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
94
95 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
96 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
97
98 virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
99 virtual void put(ExecState*, unsigned propertyName, JSValue value);
100
101 virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot);
102 virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
103 virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValue value, unsigned attributes);
104
105 bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
106
107 bool hasProperty(ExecState*, const Identifier& propertyName) const;
108 bool hasProperty(ExecState*, unsigned propertyName) const;
109 bool hasOwnProperty(ExecState*, const Identifier& propertyName) const;
110
111 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
112 virtual bool deleteProperty(ExecState*, unsigned propertyName);
113
114 virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
115
116 virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
117
118 virtual void getPropertyNames(ExecState*, PropertyNameArray&);
119
120 virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
121 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
122 virtual bool toBoolean(ExecState*) const;
123 virtual double toNumber(ExecState*) const;
124 virtual UString toString(ExecState*) const;
125 virtual JSObject* toObject(ExecState*) const;
126
127 virtual JSObject* toThisObject(ExecState*) const;
128 virtual JSObject* unwrappedObject();
129
130 virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
131 bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
132
133 // This get function only looks at the property map.
134 JSValue getDirect(const Identifier& propertyName) const
135 {
136 size_t offset = m_structure->get(propertyName);
137 return offset != WTF::notFound ? getDirectOffset(offset) : JSValue();
138 }
139
140 JSValue* getDirectLocation(const Identifier& propertyName)
141 {
142 size_t offset = m_structure->get(propertyName);
143 return offset != WTF::notFound ? locationForOffset(offset) : 0;
144 }
145
146 JSValue* getDirectLocation(const Identifier& propertyName, unsigned& attributes)
147 {
148 JSCell* specificFunction;
149 size_t offset = m_structure->get(propertyName, attributes, specificFunction);
150 return offset != WTF::notFound ? locationForOffset(offset) : 0;
151 }
152
153 size_t offsetForLocation(JSValue* location) const
154 {
155 return location - reinterpret_cast<const JSValue*>(propertyStorage());
156 }
157
158 void transitionTo(Structure*);
159
160 void removeDirect(const Identifier& propertyName);
161 bool hasCustomProperties() { return !m_structure->isEmpty(); }
162 bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
163
164 void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
165 void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0);
166
167 void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
168 void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
169 void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0);
170
171 void putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attr = 0);
172 void putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
173 void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0);
174
175 // Fast access to known property offsets.
176 JSValue getDirectOffset(size_t offset) const { return JSValue::decode(propertyStorage()[offset]); }
177 void putDirectOffset(size_t offset, JSValue value) { propertyStorage()[offset] = JSValue::encode(value); }
178
179 void fillGetterPropertySlot(PropertySlot&, JSValue* location);
180
181 virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
182 virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
183 virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
184 virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
185
186 virtual bool isGlobalObject() const { return false; }
187 virtual bool isVariableObject() const { return false; }
188 virtual bool isActivationObject() const { return false; }
189 virtual bool isWatchdogException() const { return false; }
190 virtual bool isNotAnObjectErrorStub() const { return false; }
191
192 void allocatePropertyStorage(size_t oldSize, size_t newSize);
193 void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
194 bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
195
196 static const size_t inlineStorageCapacity = 3;
197 static const size_t nonInlineBaseStorageCapacity = 16;
198
199 static PassRefPtr<Structure> createStructure(JSValue prototype)
200 {
201 return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
202 }
203
204 protected:
205 bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
206
207 private:
208 ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
209 PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
210
211 const JSValue* locationForOffset(size_t offset) const
212 {
213 return reinterpret_cast<const JSValue*>(&propertyStorage()[offset]);
214 }
215
216 JSValue* locationForOffset(size_t offset)
217 {
218 return reinterpret_cast<JSValue*>(&propertyStorage()[offset]);
219 }
220
221 void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*);
222 void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
223 void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0);
224
225 bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
226
227 const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
228 Structure* createInheritorID();
229
230 RefPtr<Structure> m_inheritorID;
231
232 union {
233 PropertyStorage m_externalStorage;
234 EncodedJSValue m_inlineStorage[inlineStorageCapacity];
235 };
236 };
237
238 JSObject* asObject(JSValue);
239
240 JSObject* constructEmptyObject(ExecState*);
241
242inline JSObject* asObject(JSValue value)
243{
244 ASSERT(asCell(value)->isObject());
245 return static_cast<JSObject*>(asCell(value));
246}
247
248inline JSObject::JSObject(PassRefPtr<Structure> structure)
249 : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
250{
251 ASSERT(m_structure);
252 ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity);
253 ASSERT(m_structure->isEmpty());
254 ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
255}
256
257inline JSObject::~JSObject()
258{
259 ASSERT(m_structure);
260 if (!isUsingInlineStorage())
261 delete [] m_externalStorage;
262 m_structure->deref();
263}
264
265inline JSValue JSObject::prototype() const
266{
267 return m_structure->storedPrototype();
268}
269
270inline void JSObject::setPrototype(JSValue prototype)
271{
272 ASSERT(prototype);
273 RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype);
274 setStructure(newStructure.release());
275}
276
277inline void JSObject::setStructure(PassRefPtr<Structure> structure)
278{
279 m_structure->deref();
280 m_structure = structure.releaseRef(); // ~JSObject balances this ref()
281}
282
283inline Structure* JSObject::inheritorID()
284{
285 if (m_inheritorID)
286 return m_inheritorID.get();
287 return createInheritorID();
288}
289
290inline bool Structure::isUsingInlineStorage() const
291{
292 return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
293}
294
295inline bool JSCell::isObject(const ClassInfo* info) const
296{
297 for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
298 if (ci == info)
299 return true;
300 }
301 return false;
302}
303
304// this method is here to be after the inline declaration of JSCell::isObject
305inline bool JSValue::isObject(const ClassInfo* classInfo) const
306{
307 return isCell() && asCell()->isObject(classInfo);
308}
309
310ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
311{
312 if (JSValue* location = getDirectLocation(propertyName)) {
313 if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter())
314 fillGetterPropertySlot(slot, location);
315 else
316 slot.setValueSlot(this, location, offsetForLocation(location));
317 return true;
318 }
319
320 // non-standard Netscape extension
321 if (propertyName == exec->propertyNames().underscoreProto) {
322 slot.setValue(prototype());
323 return true;
324 }
325
326 return false;
327}
328
329ALWAYS_INLINE bool JSObject::getOwnPropertySlotForWrite(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
330{
331 unsigned attributes;
332 if (JSValue* location = getDirectLocation(propertyName, attributes)) {
333 if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter()) {
334 slotIsWriteable = false;
335 fillGetterPropertySlot(slot, location);
336 } else {
337 slotIsWriteable = !(attributes & ReadOnly);
338 slot.setValueSlot(this, location, offsetForLocation(location));
339 }
340 return true;
341 }
342
343 // non-standard Netscape extension
344 if (propertyName == exec->propertyNames().underscoreProto) {
345 slot.setValue(prototype());
346 slotIsWriteable = false;
347 return true;
348 }
349
350 return false;
351}
352
353// It may seem crazy to inline a function this large, especially a virtual function,
354// but it makes a big difference to property lookup that derived classes can inline their
355// base class call to this.
356ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
357{
358 return inlineGetOwnPropertySlot(exec, propertyName, slot);
359}
360
361ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
362{
363 if (structure()->typeInfo().hasStandardGetOwnPropertySlot())
364 return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
365 return getOwnPropertySlot(exec, propertyName, slot);
366}
367
368// It may seem crazy to inline a function this large but it makes a big difference
369// since this is function very hot in variable lookup
370inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
371{
372 JSObject* object = this;
373 while (true) {
374 if (object->fastGetOwnPropertySlot(exec, propertyName, slot))
375 return true;
376 JSValue prototype = object->prototype();
377 if (!prototype.isObject())
378 return false;
379 object = asObject(prototype);
380 }
381}
382
383inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
384{
385 JSObject* object = this;
386 while (true) {
387 if (object->getOwnPropertySlot(exec, propertyName, slot))
388 return true;
389 JSValue prototype = object->prototype();
390 if (!prototype.isObject())
391 return false;
392 object = asObject(prototype);
393 }
394}
395
396inline JSValue JSObject::get(ExecState* exec, const Identifier& propertyName) const
397{
398 PropertySlot slot(this);
399 if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
400 return slot.getValue(exec, propertyName);
401
402 return jsUndefined();
403}
404
405inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
406{
407 PropertySlot slot(this);
408 if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
409 return slot.getValue(exec, propertyName);
410
411 return jsUndefined();
412}
413
414inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
415{
416 ASSERT(value);
417 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
418
419 if (m_structure->isDictionary()) {
420 unsigned currentAttributes;
421 JSCell* currentSpecificFunction;
422 size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
423 if (offset != WTF::notFound) {
424 if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
425 m_structure->despecifyDictionaryFunction(propertyName);
426 if (checkReadOnly && currentAttributes & ReadOnly)
427 return;
428 putDirectOffset(offset, value);
429 if (!specificFunction && !currentSpecificFunction)
430 slot.setExistingProperty(this, offset);
431 return;
432 }
433
434 size_t currentCapacity = m_structure->propertyStorageCapacity();
435 offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction);
436 if (currentCapacity != m_structure->propertyStorageCapacity())
437 allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
438
439 ASSERT(offset < m_structure->propertyStorageCapacity());
440 putDirectOffset(offset, value);
441 // See comment on setNewProperty call below.
442 if (!specificFunction)
443 slot.setNewProperty(this, offset);
444 return;
445 }
446
447 size_t offset;
448 size_t currentCapacity = m_structure->propertyStorageCapacity();
449 if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, specificFunction, offset)) {
450 if (currentCapacity != structure->propertyStorageCapacity())
451 allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
452
453 ASSERT(offset < structure->propertyStorageCapacity());
454 setStructure(structure.release());
455 putDirectOffset(offset, value);
456 // See comment on setNewProperty call below.
457 if (!specificFunction)
458 slot.setNewProperty(this, offset);
459 return;
460 }
461
462 unsigned currentAttributes;
463 JSCell* currentSpecificFunction;
464 offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
465 if (offset != WTF::notFound) {
466 if (checkReadOnly && currentAttributes & ReadOnly)
467 return;
468
469 if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) {
470 setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName));
471 putDirectOffset(offset, value);
472 // Function transitions are not currently cachable, so leave the slot in an uncachable state.
473 return;
474 }
475 putDirectOffset(offset, value);
476 slot.setExistingProperty(this, offset);
477 return;
478 }
479
480 RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset);
481 if (currentCapacity != structure->propertyStorageCapacity())
482 allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
483
484 ASSERT(offset < structure->propertyStorageCapacity());
485 setStructure(structure.release());
486 putDirectOffset(offset, value);
487 // Function transitions are not currently cachable, so leave the slot in an uncachable state.
488 if (!specificFunction)
489 slot.setNewProperty(this, offset);
490}
491
492inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
493{
494 ASSERT(value);
495 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
496
497 putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
498}
499
500inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
501{
502 PutPropertySlot slot;
503 putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value));
504}
505
506inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
507{
508 ASSERT(value);
509 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
510
511 putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0);
512}
513
514inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes)
515{
516 PutPropertySlot slot;
517 putDirectInternal(propertyName, value, attributes, false, slot, 0);
518}
519
520inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
521{
522 putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value);
523}
524
525inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr)
526{
527 PutPropertySlot slot;
528 putDirectInternal(propertyName, value, attr, false, slot, value);
529}
530
531inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attributes)
532{
533 size_t currentCapacity = m_structure->propertyStorageCapacity();
534 size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, 0);
535 if (currentCapacity != m_structure->propertyStorageCapacity())
536 allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
537 putDirectOffset(offset, value);
538}
539
540inline void JSObject::putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attributes)
541{
542 size_t currentCapacity = m_structure->propertyStorageCapacity();
543 size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, value);
544 if (currentCapacity != m_structure->propertyStorageCapacity())
545 allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
546 putDirectOffset(offset, value);
547}
548
549inline void JSObject::transitionTo(Structure* newStructure)
550{
551 if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
552 allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
553 setStructure(newStructure);
554}
555
556inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
557{
558 return defaultValue(exec, preferredType);
559}
560
561inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName) const
562{
563 PropertySlot slot(asValue());
564 return get(exec, propertyName, slot);
565}
566
567inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const
568{
569 if (UNLIKELY(!isCell())) {
570 JSObject* prototype = JSImmediate::prototype(asValue(), exec);
571 if (propertyName == exec->propertyNames().underscoreProto)
572 return prototype;
573 if (!prototype->getPropertySlot(exec, propertyName, slot))
574 return jsUndefined();
575 return slot.getValue(exec, propertyName);
576 }
577 JSCell* cell = asCell();
578 while (true) {
579 if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
580 return slot.getValue(exec, propertyName);
581 ASSERT(cell->isObject());
582 JSValue prototype = static_cast<JSObject*>(cell)->prototype();
583 if (!prototype.isObject())
584 return jsUndefined();
585 cell = asObject(prototype);
586 }
587}
588
589inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const
590{
591 PropertySlot slot(asValue());
592 return get(exec, propertyName, slot);
593}
594
595inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
596{
597 if (UNLIKELY(!isCell())) {
598 JSObject* prototype = JSImmediate::prototype(asValue(), exec);
599 if (!prototype->getPropertySlot(exec, propertyName, slot))
600 return jsUndefined();
601 return slot.getValue(exec, propertyName);
602 }
603 JSCell* cell = const_cast<JSCell*>(asCell());
604 while (true) {
605 if (cell->getOwnPropertySlot(exec, propertyName, slot))
606 return slot.getValue(exec, propertyName);
607 ASSERT(cell->isObject());
608 JSValue prototype = static_cast<JSObject*>(cell)->prototype();
609 if (!prototype.isObject())
610 return jsUndefined();
611 cell = prototype.asCell();
612 }
613}
614
615inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
616{
617 if (UNLIKELY(!isCell())) {
618 JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value, slot);
619 return;
620 }
621 asCell()->put(exec, propertyName, value, slot);
622}
623
624inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
625{
626 if (UNLIKELY(!isCell())) {
627 JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value);
628 return;
629 }
630 asCell()->put(exec, propertyName, value);
631}
632
633ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_t newSize)
634{
635 ASSERT(newSize > oldSize);
636
637 // It's important that this function not rely on m_structure, since
638 // we might be in the middle of a transition.
639 bool wasInline = (oldSize == JSObject::inlineStorageCapacity);
640
641 PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage);
642 PropertyStorage newPropertyStorage = new EncodedJSValue[newSize];
643
644 for (unsigned i = 0; i < oldSize; ++i)
645 newPropertyStorage[i] = oldPropertyStorage[i];
646
647 if (!wasInline)
648 delete [] oldPropertyStorage;
649
650 m_externalStorage = newPropertyStorage;
651}
652
653} // namespace JSC
654
655#endif // JSObject_h
Note: See TracBrowser for help on using the repository browser.