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

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

JavaScriptCore:

2009-06-17 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

<rdar://problem/6974175> ASSERT in JITStubs.cpp at appsaccess.apple.com

Remove PropertySlot::putValue - PropertySlots should only be used for getting,
not putting. Rename JSGlobalObject::getOwnPropertySlot to hasOwnPropertyForWrite,
which is what it really was being used to ask, and remove some other getOwnPropertySlot
& getOwnPropertySlotForWrite methods, which were unused and likely to lead to confusion.

  • runtime/JSGlobalObject.h: (JSC::JSGlobalObject::hasOwnPropertyForWrite):
  • runtime/JSObject.h:
  • runtime/JSStaticScopeObject.cpp:
  • runtime/JSStaticScopeObject.h:
  • runtime/PropertySlot.h:

WebCore:

2009-06-17 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

<rdar://problem/6974175> ASSERT in JITStubs.cpp at appsaccess.apple.com

JSDOMWindowCustom was using PropertySlot::putValue, however this interface
appears to be fundaementally incorrect - PropertySlots are only used to get
values, all puts use PutPropertySlot. However PutPropertySlot cannot be
used in the fashion desired here - it only reports the caching type of a
write that has been performed.

(This caused a bug where the put should have triggered a transition, and
failed to do so.)

Removing the faulty case from the optimization leads to a ~0.5% progression
on in-browser SunSpider (presumably the very first case was not being hit
often, and the simplification here is beneficial).

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