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

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

NotNullPassRefPtr: smart pointer optimized for passing references that are not null
https://bugs.webkit.org/show_bug.cgi?id=29822

Patch by Geoffrey Garen <[email protected]> on 2009-09-28
Reviewed by Darin Adler.

JavaScriptCore:

Added NotNullPassRefPtr, and deployed it in all places that initialize
JavaScript objects.

2.2% speedup on bench-allocate-nonretained.js.

  • API/JSCallbackConstructor.cpp:

(JSC::JSCallbackConstructor::JSCallbackConstructor):

  • API/JSCallbackConstructor.h:
  • API/JSCallbackObject.h:
  • API/JSCallbackObjectFunctions.h:

(JSC::JSCallbackObject::JSCallbackObject):

(JSC::CodeBlock::addFunctionDecl):
(JSC::CodeBlock::addFunctionExpr):

  • runtime/ArrayConstructor.cpp:

(JSC::ArrayConstructor::ArrayConstructor):

  • runtime/ArrayConstructor.h:
  • runtime/ArrayPrototype.cpp:

(JSC::ArrayPrototype::ArrayPrototype):

  • runtime/ArrayPrototype.h:
  • runtime/BooleanConstructor.cpp:

(JSC::BooleanConstructor::BooleanConstructor):

  • runtime/BooleanConstructor.h:
  • runtime/BooleanObject.cpp:

(JSC::BooleanObject::BooleanObject):

  • runtime/BooleanObject.h:
  • runtime/BooleanPrototype.cpp:

(JSC::BooleanPrototype::BooleanPrototype):

  • runtime/BooleanPrototype.h:
  • runtime/DateConstructor.cpp:

(JSC::DateConstructor::DateConstructor):

  • runtime/DateConstructor.h:
  • runtime/DateInstance.cpp:

(JSC::DateInstance::DateInstance):

  • runtime/DateInstance.h:
  • runtime/DatePrototype.cpp:

(JSC::DatePrototype::DatePrototype):

  • runtime/DatePrototype.h:
  • runtime/ErrorConstructor.cpp:

(JSC::ErrorConstructor::ErrorConstructor):

  • runtime/ErrorConstructor.h:
  • runtime/ErrorInstance.cpp:

(JSC::ErrorInstance::ErrorInstance):

  • runtime/ErrorInstance.h:
  • runtime/ErrorPrototype.cpp:

(JSC::ErrorPrototype::ErrorPrototype):

  • runtime/ErrorPrototype.h:
  • runtime/FunctionConstructor.cpp:

(JSC::FunctionConstructor::FunctionConstructor):

  • runtime/FunctionConstructor.h:
  • runtime/FunctionPrototype.cpp:

(JSC::FunctionPrototype::FunctionPrototype):

  • runtime/FunctionPrototype.h:
  • runtime/GlobalEvalFunction.cpp:

(JSC::GlobalEvalFunction::GlobalEvalFunction):

  • runtime/GlobalEvalFunction.h:
  • runtime/InternalFunction.cpp:

(JSC::InternalFunction::InternalFunction):

  • runtime/InternalFunction.h:

(JSC::InternalFunction::InternalFunction):

  • runtime/JSActivation.cpp:

(JSC::JSActivation::JSActivation):

  • runtime/JSActivation.h:

(JSC::JSActivation::JSActivationData::JSActivationData):

  • runtime/JSArray.cpp:

(JSC::JSArray::JSArray):

  • runtime/JSArray.h:
  • runtime/JSByteArray.cpp:

(JSC::JSByteArray::JSByteArray):

  • runtime/JSByteArray.h:
  • runtime/JSFunction.cpp:

(JSC::JSFunction::JSFunction):

  • runtime/JSFunction.h:
  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::JSGlobalObject):

  • runtime/JSONObject.h:

(JSC::JSONObject::JSONObject):

  • runtime/JSObject.h:

(JSC::JSObject::JSObject):
(JSC::JSObject::setStructure):

  • runtime/JSVariableObject.h:

(JSC::JSVariableObject::JSVariableObject):

  • runtime/JSWrapperObject.h:

(JSC::JSWrapperObject::JSWrapperObject):

  • runtime/MathObject.cpp:

(JSC::MathObject::MathObject):

  • runtime/MathObject.h:
  • runtime/NativeErrorConstructor.cpp:

(JSC::NativeErrorConstructor::NativeErrorConstructor):

  • runtime/NativeErrorConstructor.h:
  • runtime/NativeErrorPrototype.cpp:

(JSC::NativeErrorPrototype::NativeErrorPrototype):

  • runtime/NativeErrorPrototype.h:
  • runtime/NumberConstructor.cpp:

(JSC::NumberConstructor::NumberConstructor):

  • runtime/NumberConstructor.h:
  • runtime/NumberObject.cpp:

(JSC::NumberObject::NumberObject):

  • runtime/NumberObject.h:
  • runtime/NumberPrototype.cpp:

(JSC::NumberPrototype::NumberPrototype):

  • runtime/NumberPrototype.h:
  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::ObjectConstructor):

  • runtime/ObjectConstructor.h:
  • runtime/ObjectPrototype.cpp:

(JSC::ObjectPrototype::ObjectPrototype):

  • runtime/ObjectPrototype.h:
  • runtime/PropertyNameArray.h:

(JSC::PropertyNameArrayData::setCachedPrototypeChain):

  • runtime/PrototypeFunction.cpp:

(JSC::PrototypeFunction::PrototypeFunction):

  • runtime/PrototypeFunction.h:
  • runtime/RegExpConstructor.cpp:

(JSC::RegExpConstructor::RegExpConstructor):

  • runtime/RegExpConstructor.h:
  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::RegExpObject):

  • runtime/RegExpObject.h:

(JSC::RegExpObject::RegExpObjectData::RegExpObjectData):

  • runtime/RegExpPrototype.cpp:

(JSC::RegExpPrototype::RegExpPrototype):

  • runtime/RegExpPrototype.h:
  • runtime/StringConstructor.cpp:

(JSC::StringConstructor::StringConstructor):

  • runtime/StringConstructor.h:
  • runtime/StringObject.cpp:

(JSC::StringObject::StringObject):

  • runtime/StringObject.h:
  • runtime/StringObjectThatMasqueradesAsUndefined.h:

(JSC::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined):

  • runtime/StringPrototype.cpp:

(JSC::StringPrototype::StringPrototype):

  • runtime/StringPrototype.h:
  • wtf/PassRefPtr.h:

(WTF::NotNullPassRefPtr::NotNullPassRefPtr):
(WTF::NotNullPassRefPtr::~NotNullPassRefPtr):
(WTF::NotNullPassRefPtr::get):
(WTF::NotNullPassRefPtr::clear):
(WTF::NotNullPassRefPtr::releaseRef):
(WTF::NotNullPassRefPtr::operator*):
(WTF::NotNullPassRefPtr::operator->):
(WTF::NotNullPassRefPtr::operator!):
(WTF::NotNullPassRefPtr::operator UnspecifiedBoolType):

  • wtf/RefPtr.h:

(WTF::RefPtr::RefPtr):
(WTF::operator==):

WebCore:

Added NotNullPassRefPtr, and deployed it in all places that initialize
JavaScript objects.

  • bindings/js/DOMObjectWithSVGContext.h:

(WebCore::DOMObjectWithSVGContext::DOMObjectWithSVGContext):

  • bindings/js/JSDOMBinding.cpp:

(WebCore::cacheDOMStructure):

  • bindings/js/JSDOMBinding.h:

(WebCore::DOMObject::DOMObject):
(WebCore::DOMObjectWithGlobalPointer::DOMObjectWithGlobalPointer):
(WebCore::DOMConstructorObject::DOMConstructorObject):
(WebCore::DOMConstructorWithDocument::DOMConstructorWithDocument):

  • bindings/js/JSDOMGlobalObject.cpp:

(WebCore::JSDOMGlobalObject::JSDOMGlobalObject):

  • bindings/js/JSDOMGlobalObject.h:
  • bindings/js/JSDOMWindowBase.cpp:

(WebCore::JSDOMWindowBase::JSDOMWindowBase):

  • bindings/js/JSDOMWindowBase.h:
  • bindings/js/JSHTMLAllCollection.h:

(WebCore::JSHTMLAllCollection::JSHTMLAllCollection):

  • bindings/js/JSInspectedObjectWrapper.cpp:

(WebCore::JSInspectedObjectWrapper::JSInspectedObjectWrapper):

  • bindings/js/JSInspectedObjectWrapper.h:
  • bindings/js/JSInspectorCallbackWrapper.cpp:

(WebCore::JSInspectorCallbackWrapper::JSInspectorCallbackWrapper):

  • bindings/js/JSInspectorCallbackWrapper.h:
  • bindings/js/JSQuarantinedObjectWrapper.cpp:

(WebCore::JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper):

  • bindings/js/JSQuarantinedObjectWrapper.h:
  • bindings/js/JSWorkerContextBase.cpp:

(WebCore::JSWorkerContextBase::JSWorkerContextBase):

  • bindings/js/JSWorkerContextBase.h:
  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/runtime_object.cpp:

(JSC::RuntimeObjectImp::RuntimeObjectImp):

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