X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174..93a3786624b2768d89bfa27e46598dc64e2fb70a:/runtime/JSCell.h diff --git a/runtime/JSCell.h b/runtime/JSCell.h index 431e671..76acb1e 100644 --- a/runtime/JSCell.h +++ b/runtime/JSCell.h @@ -24,354 +24,173 @@ #define JSCell_h #include "CallData.h" -#include "CallFrame.h" #include "ConstructData.h" #include "Heap.h" #include "JSLock.h" -#include "JSValueInlineMethods.h" #include "SlotVisitor.h" +#include "TypedArrayDescriptor.h" #include "WriteBarrier.h" #include +#include namespace JSC { - class JSGlobalObject; - class LLIntOffsetsExtractor; - class PropertyDescriptor; - class PropertyNameArray; - class Structure; - - enum EnumerationMode { - ExcludeDontEnumProperties, - IncludeDontEnumProperties - }; - - enum TypedArrayType { - TypedArrayNone, - TypedArrayInt8, - TypedArrayInt16, - TypedArrayInt32, - TypedArrayUint8, - TypedArrayUint8Clamped, - TypedArrayUint16, - TypedArrayUint32, - TypedArrayFloat32, - TypedArrayFloat64 - }; - - class JSCell { - friend class JSValue; - friend class MarkedBlock; - template friend void* allocateCell(Heap&); - - public: - enum CreatingEarlyCellTag { CreatingEarlyCell }; - JSCell(CreatingEarlyCellTag); - - protected: - JSCell(JSGlobalData&, Structure*); - JS_EXPORT_PRIVATE static void destroy(JSCell*); - - public: - // Querying the type. - bool isString() const; - bool isObject() const; - bool isGetterSetter() const; - bool inherits(const ClassInfo*) const; - bool isAPIValueWrapper() const; - - Structure* structure() const; - void setStructure(JSGlobalData&, Structure*); - void clearStructure() { m_structure.clear(); } - - // Extracting the value. - JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const; - JS_EXPORT_PRIVATE UString getString(ExecState* exec) const; // null string if not a string - JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object - const JSObject* getObject() const; // NULL if not an object - - JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&); - JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&); - - // Basic conversions. - JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; - bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; - bool toBoolean(ExecState*) const; - JS_EXPORT_PRIVATE double toNumber(ExecState*) const; - JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const; - - static void visitChildren(JSCell*, SlotVisitor&); - - // Object operations, with the toObject operation included. - const ClassInfo* classInfo() const; - const ClassInfo* validatedClassInfo() const; - const MethodTable* methodTable() const; - static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); +class CopyVisitor; +class ExecState; +class JSDestructibleObject; +class JSGlobalObject; +class LLIntOffsetsExtractor; +class PropertyDescriptor; +class PropertyNameArray; +class Structure; + +enum EnumerationMode { + ExcludeDontEnumProperties, + IncludeDontEnumProperties +}; + +class JSCell { + friend class JSValue; + friend class MarkedBlock; + template friend void* allocateCell(Heap&); + template friend void* allocateCell(Heap&, size_t); + +public: + static const unsigned StructureFlags = 0; + + static const bool needsDestruction = false; + static const bool hasImmortalStructure = false; + + enum CreatingEarlyCellTag { CreatingEarlyCell }; + JSCell(CreatingEarlyCellTag); + +protected: + JSCell(VM&, Structure*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); + +public: + // Querying the type. + bool isString() const; + bool isObject() const; + bool isGetterSetter() const; + bool isProxy() const; + bool inherits(const ClassInfo*) const; + bool isAPIValueWrapper() const; + + Structure* structure() const; + void setStructure(VM&, Structure*); + void clearStructure() { m_structure.clear(); } + + const char* className(); + + // Extracting the value. + JS_EXPORT_PRIVATE bool getString(ExecState*, String&) const; + JS_EXPORT_PRIVATE String getString(ExecState*) const; // null string if not a string + JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object + const JSObject* getObject() const; // NULL if not an object - static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); - static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - - static JSObject* toThisObject(JSCell*, ExecState*); - - void zap() { *reinterpret_cast(this) = 0; } - bool isZapped() const { return !*reinterpret_cast(this); } - - // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and - // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always - // call this function, not its slower virtual counterpart. (For integer - // property names, we want a similar interface with appropriate optimizations.) - bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); - JSValue fastGetOwnProperty(ExecState*, const UString&); - - static ptrdiff_t structureOffset() - { - return OBJECT_OFFSETOF(JSCell, m_structure); - } - - static ptrdiff_t classInfoOffset() - { - return OBJECT_OFFSETOF(JSCell, m_classInfo); - } - - void* structureAddress() - { - return &m_structure; - } - -#if ENABLE(GC_VALIDATION) - Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); } -#endif - - static const TypedArrayType TypedArrayStorageType = TypedArrayNone; - protected: - - void finishCreation(JSGlobalData&); - void finishCreation(JSGlobalData&, Structure*, CreatingEarlyCellTag); - - // Base implementation; for non-object classes implements getPropertySlot. - static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - - // Dummy implementations of override-able static functions for classes to put in their MethodTable - static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); - static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - static UString className(const JSObject*); - static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); - static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); - - private: - friend class LLIntOffsetsExtractor; + JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&); + JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&); + + // Basic conversions. + JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; + bool toBoolean(ExecState*) const; + TriState pureToBoolean() const; + JS_EXPORT_PRIVATE double toNumber(ExecState*) const; + JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const; + + static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&); + + // Object operations, with the toObject operation included. + const ClassInfo* classInfo() const; + const MethodTable* methodTable() const; + const MethodTable* methodTableForDestruction() const; + static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); - const ClassInfo* m_classInfo; - WriteBarrier m_structure; - }; + static bool deleteProperty(JSCell*, ExecState*, PropertyName); + static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - inline JSCell::JSCell(CreatingEarlyCellTag) - { - } + static JSObject* toThisObject(JSCell*, ExecState*); - inline void JSCell::finishCreation(JSGlobalData& globalData) - { -#if ENABLE(GC_VALIDATION) - ASSERT(globalData.isInitializingObject()); - globalData.setInitializingObjectClass(0); -#else - UNUSED_PARAM(globalData); -#endif - ASSERT(m_structure); - } - - inline Structure* JSCell::structure() const - { - return m_structure.get(); - } - - inline const ClassInfo* JSCell::classInfo() const - { - return m_classInfo; - } + void zap() { *reinterpret_cast(this) = 0; } + bool isZapped() const { return !*reinterpret_cast(this); } - inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor) - { - visitor.append(&cell->m_structure); - } - - // --- JSValue inlines ---------------------------- - - inline bool JSValue::isString() const - { - return isCell() && asCell()->isString(); - } - - inline bool JSValue::isPrimitive() const - { - return !isCell() || asCell()->isString(); - } - - inline bool JSValue::isGetterSetter() const - { - return isCell() && asCell()->isGetterSetter(); - } + // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and + // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always + // call this function, not its slower virtual counterpart. (For integer + // property names, we want a similar interface with appropriate optimizations.) + bool fastGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&); + JSValue fastGetOwnProperty(ExecState*, const String&); - inline bool JSValue::isObject() const + static ptrdiff_t structureOffset() { - return isCell() && asCell()->isObject(); + return OBJECT_OFFSETOF(JSCell, m_structure); } - inline bool JSValue::getString(ExecState* exec, UString& s) const + void* structureAddress() { - return isCell() && asCell()->getString(exec, s); + return &m_structure; } - - inline UString JSValue::getString(ExecState* exec) const - { - return isCell() ? asCell()->getString(exec) : UString(); - } - - template UString HandleConverter::getString(ExecState* exec) const - { - return jsValue().getString(exec); - } - - inline JSObject* JSValue::getObject() const - { - return isCell() ? asCell()->getObject() : 0; - } - - ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const - { - if (isInt32()) { - int32_t i = asInt32(); - v = static_cast(i); - return i >= 0; - } - if (isDouble()) { - double d = asDouble(); - v = static_cast(d); - return v == d; - } - return false; - } - - inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const - { - return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue(); - } - - inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) - { - if (isInt32()) { - number = asInt32(); - value = *this; - return true; - } - if (isDouble()) { - number = asDouble(); - value = *this; - return true; - } - if (isCell()) - return asCell()->getPrimitiveNumber(exec, number, value); - if (isTrue()) { - number = 1.0; - value = *this; - return true; - } - if (isFalse() || isNull()) { - number = 0.0; - value = *this; - return true; - } - ASSERT(isUndefined()); - number = std::numeric_limits::quiet_NaN(); - value = *this; - return true; - } - - ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const - { - if (isInt32()) - return asInt32(); - if (isDouble()) - return asDouble(); - return toNumberSlowCase(exec); - } - - inline JSObject* JSValue::toObject(ExecState* exec) const - { - return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject()); - } - - inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const - { - return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject); - } - -#if COMPILER(CLANG) - template - struct NeedsDestructor { - static const bool value = !__has_trivial_destructor(T); - }; -#else - // Write manual specializations for this struct template if you care about non-clang compilers. - template - struct NeedsDestructor { - static const bool value = true; - }; -#endif - - template - void* allocateCell(Heap& heap) - { + #if ENABLE(GC_VALIDATION) - ASSERT(!heap.globalData()->isInitializingObject()); - heap.globalData()->setInitializingObjectClass(&T::s_info); + Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); } #endif - JSCell* result = 0; - if (NeedsDestructor::value) - result = static_cast(heap.allocateWithDestructor(sizeof(T))); - else { - ASSERT(T::s_info.methodTable.destroy == JSCell::destroy); - result = static_cast(heap.allocateWithoutDestructor(sizeof(T))); - } - result->clearStructure(); - return result; - } + + static const TypedArrayType TypedArrayStorageType = TypedArrayNone; +protected: + + void finishCreation(VM&); + void finishCreation(VM&, Structure*, CreatingEarlyCellTag); + + // Base implementation; for non-object classes implements getPropertySlot. + static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + + // Dummy implementations of override-able static functions for classes to put in their MethodTable + static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static String className(const JSObject*); + JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue); + static NO_RETURN_DUE_TO_CRASH void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes); + static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); + +private: + friend class LLIntOffsetsExtractor; + + WriteBarrier m_structure; +}; + +template +inline To jsCast(From* from) +{ + ASSERT(!from || from->JSCell::inherits(&WTF::RemovePointer::Type::s_info)); + return static_cast(from); +} - inline bool isZapped(const JSCell* cell) - { - return cell->isZapped(); - } - - template - inline To jsCast(From* from) - { - ASSERT(!from || from->JSCell::inherits(&WTF::RemovePointer::Type::s_info)); - return static_cast(from); - } - - template - inline To jsCast(JSValue from) - { - ASSERT(from.isCell() && from.asCell()->JSCell::inherits(&WTF::RemovePointer::Type::s_info)); - return static_cast(from.asCell()); - } - - template - inline To jsDynamicCast(From* from) - { - return from->inherits(&WTF::RemovePointer::Type::s_info) ? static_cast(from) : 0; - } - - template - inline To jsDynamicCast(JSValue from) - { - return from.isCell() && from.asCell()->inherits(&WTF::RemovePointer::Type::s_info) ? static_cast(from.asCell()) : 0; - } +template +inline To jsCast(JSValue from) +{ + ASSERT(from.isCell() && from.asCell()->JSCell::inherits(&WTF::RemovePointer::Type::s_info)); + return static_cast(from.asCell()); +} + +template +inline To jsDynamicCast(From* from) +{ + return from->inherits(&WTF::RemovePointer::Type::s_info) ? static_cast(from) : 0; +} + +template +inline To jsDynamicCast(JSValue from) +{ + return from.isCell() && from.asCell()->inherits(&WTF::RemovePointer::Type::s_info) ? static_cast(from.asCell()) : 0; +} } // namespace JSC