X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..f9bf01c6616d5ddcf65b13b33cedf9e387ff7a63:/runtime/JSObject.h diff --git a/runtime/JSObject.h b/runtime/JSObject.h index ac4706f..2b31a65 100644 --- a/runtime/JSObject.h +++ b/runtime/JSObject.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,7 +27,9 @@ #include "ClassInfo.h" #include "CommonIdentifiers.h" #include "CallFrame.h" +#include "JSCell.h" #include "JSNumberCell.h" +#include "MarkStack.h" #include "PropertySlot.h" #include "PutPropertySlot.h" #include "ScopeChain.h" @@ -43,11 +45,12 @@ namespace JSC { return value.asCell(); return 0; } - + + class HashEntry; class InternalFunction; + class PropertyDescriptor; class PropertyNameArray; class Structure; - struct HashEntry; struct HashTable; // ECMA 262-3 8.6.1 @@ -71,20 +74,19 @@ namespace JSC { friend class JSCell; public: - explicit JSObject(PassRefPtr); + explicit JSObject(NonNullPassRefPtr); - virtual void mark(); + virtual void markChildren(MarkStack&); + ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack); // The inline virtual destructor cannot be the first virtual function declared // in the class as it results in the vtable being generated as a weak symbol virtual ~JSObject(); - bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); } - JSValue prototype() const; void setPrototype(JSValue prototype); - void setStructure(PassRefPtr); + void setStructure(NonNullPassRefPtr); Structure* inheritorID(); virtual UString className() const; @@ -94,9 +96,11 @@ namespace JSC { bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue value); @@ -118,7 +122,8 @@ namespace JSC { virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); @@ -130,7 +135,6 @@ namespace JSC { virtual JSObject* toThisObject(ExecState*) const; virtual JSObject* unwrappedObject(); - virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; // This get function only looks at the property map. @@ -181,10 +185,11 @@ namespace JSC { void fillGetterPropertySlot(PropertySlot&, JSValue* location); - virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction); - virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction); + virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); + virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName); virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName); + virtual bool defineOwnProperty(ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); virtual bool isGlobalObject() const { return false; } virtual bool isVariableObject() const { return false; } @@ -196,12 +201,12 @@ namespace JSC { void allocatePropertyStorageInline(size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } - static const size_t inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3; - static const size_t nonInlineBaseStorageCapacity = 16; + static const unsigned inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3; + static const unsigned nonInlineBaseStorageCapacity = 16; static PassRefPtr createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); } void flattenDictionaryObject() @@ -209,7 +214,33 @@ namespace JSC { m_structure->flattenDictionaryStructure(this); } + protected: + static const unsigned StructureFlags = 0; + + void putAnonymousValue(unsigned index, JSValue value) + { + ASSERT(index < m_structure->anonymousSlotCount()); + *locationForOffset(index) = value; + } + JSValue getAnonymousValue(unsigned index) const + { + ASSERT(index < m_structure->anonymousSlotCount()); + return *locationForOffset(index); + } + private: + // Nobody should ever ask any of these questions on something already known to be a JSObject. + using JSCell::isAPIValueWrapper; + using JSCell::isGetterSetter; + using JSCell::toObject; + void getObject(); + void getString(ExecState* exec); + void isObject(); + void isString(); +#if USE(JSVALUE32) + void isNumber(); +#endif + ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } @@ -240,18 +271,20 @@ namespace JSC { RefPtr m_inheritorID; }; -JSObject* constructEmptyObject(ExecState*); +inline JSObject* asObject(JSCell* cell) +{ + ASSERT(cell->isObject()); + return static_cast(cell); +} inline JSObject* asObject(JSValue value) { - ASSERT(asCell(value)->isObject()); - return static_cast(asCell(value)); + return asObject(value.asCell()); } -inline JSObject::JSObject(PassRefPtr structure) +inline JSObject::JSObject(NonNullPassRefPtr structure) : JSCell(structure.releaseRef()) // ~JSObject balances this ref() { - ASSERT(m_structure); ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); ASSERT(m_structure->isEmpty()); ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); @@ -280,7 +313,7 @@ inline void JSObject::setPrototype(JSValue prototype) setStructure(newStructure.release()); } -inline void JSObject::setStructure(PassRefPtr structure) +inline void JSObject::setStructure(NonNullPassRefPtr structure) { m_structure->deref(); m_structure = structure.releaseRef(); // ~JSObject balances this ref() @@ -298,7 +331,7 @@ inline bool Structure::isUsingInlineStorage() const return (propertyStorageCapacity() == JSObject::inlineStorageCapacity); } -inline bool JSCell::isObject(const ClassInfo* info) const +inline bool JSCell::inherits(const ClassInfo* info) const { for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) { if (ci == info) @@ -307,10 +340,10 @@ inline bool JSCell::isObject(const ClassInfo* info) const return false; } -// this method is here to be after the inline declaration of JSCell::isObject -inline bool JSValue::isObject(const ClassInfo* classInfo) const +// this method is here to be after the inline declaration of JSCell::inherits +inline bool JSValue::inherits(const ClassInfo* classInfo) const { - return isCell() && asCell()->isObject(classInfo); + return isCell() && asCell()->inherits(classInfo); } ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -342,14 +375,14 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifie ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (structure()->typeInfo().hasStandardGetOwnPropertySlot()) + if (!structure()->typeInfo().overridesGetOwnPropertySlot()) return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot); return getOwnPropertySlot(exec, propertyName, slot); } // It may seem crazy to inline a function this large but it makes a big difference // since this is function very hot in variable lookup -inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { JSObject* object = this; while (true) { @@ -362,7 +395,7 @@ inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propert } } -inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { JSObject* object = this; while (true) { @@ -571,8 +604,7 @@ inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, Pro while (true) { if (cell->fastGetOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); - ASSERT(cell->isObject()); - JSValue prototype = static_cast(cell)->prototype(); + JSValue prototype = asObject(cell)->prototype(); if (!prototype.isObject()) return jsUndefined(); cell = asObject(prototype); @@ -597,8 +629,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot while (true) { if (cell->getOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); - ASSERT(cell->isObject()); - JSValue prototype = static_cast(cell)->prototype(); + JSValue prototype = asObject(cell)->prototype(); if (!prototype.isObject()) return jsUndefined(); cell = prototype.asCell(); @@ -643,6 +674,17 @@ ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_ m_externalStorage = newPropertyStorage; } +ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) +{ + JSCell::markChildren(markStack); + + markStack.append(prototype()); + + PropertyStorage storage = propertyStorage(); + size_t storageSize = m_structure->propertyStorageSize(); + markStack.appendValues(reinterpret_cast(storage), storageSize); +} + } // namespace JSC #endif // JSObject_h