X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..refs/heads/master:/runtime/JSCell.h diff --git a/runtime/JSCell.h b/runtime/JSCell.h index 43d81a5..6d648ad 100644 --- a/runtime/JSCell.h +++ b/runtime/JSCell.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, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 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 @@ -23,277 +23,256 @@ #ifndef JSCell_h #define JSCell_h +#include "CallData.h" +#include "ConstructData.h" +#include "EnumerationMode.h" +#include "Heap.h" +#include "IndexingType.h" +#include "JSLock.h" +#include "JSTypeInfo.h" +#include "SlotVisitor.h" +#include "TypedArrayType.h" +#include "WriteBarrier.h" #include -#include "Structure.h" -#include "JSValue.h" -#include "JSImmediate.h" -#include "Collector.h" namespace JSC { - class JSCell : Noncopyable { - friend class JIT; - friend class GetterSetter; - friend class Heap; - friend class JSNumberCell; - friend class JSObject; - friend class JSPropertyNameIterator; - friend class JSString; - friend class JSValuePtr; - friend class Interpreter; - - private: - explicit JSCell(Structure*); - virtual ~JSCell(); - - public: - // Querying the type. - bool isNumber() const; - bool isString() const; - bool isObject() const; - virtual bool isGetterSetter() const; - virtual bool isObject(const ClassInfo*) const; - - Structure* structure() const; - - // Extracting the value. - bool getString(UString&) const; - UString getString() const; // null string if not a string - JSObject* getObject(); // NULL if not an object - const JSObject* getObject() const; // NULL if not an object +class CopyVisitor; +class ExecState; +class Identifier; +class JSArrayBufferView; +class JSDestructibleObject; +class JSGlobalObject; +class LLIntOffsetsExtractor; +class PropertyDescriptor; +class PropertyNameArray; +class Structure; + +template void* allocateCell(Heap&); +template void* allocateCell(Heap&, size_t); + +#define DECLARE_EXPORT_INFO \ + protected: \ + static JS_EXPORTDATA const ::JSC::ClassInfo s_info; \ + public: \ + static const ::JSC::ClassInfo* info() { return &s_info; } + +#define DECLARE_INFO \ + protected: \ + static const ::JSC::ClassInfo s_info; \ + public: \ + static const ::JSC::ClassInfo* info() { return &s_info; } + +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 JSCell* seenMultipleCalleeObjects() { return bitwise_cast(static_cast(1)); } + + enum CreatingEarlyCellTag { CreatingEarlyCell }; + JSCell(CreatingEarlyCellTag); + +protected: + JSCell(VM&, Structure*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); + +public: + // Querying the type. + bool isString() const; + bool isSymbol() const; + bool isObject() const; + bool isGetterSetter() const; + bool isCustomGetterSetter() const; + bool isProxy() const; + bool inherits(const ClassInfo*) const; + bool isAPIValueWrapper() const; + + JSType type() const; + IndexingType indexingType() const; + StructureID structureID() const { return m_structureID; } + Structure* structure() const; + Structure* structure(VM&) const; + void setStructure(VM&, Structure*); + void clearStructure() { m_structureID = 0; } + + TypeInfo::InlineTypeFlags inlineTypeFlags() const { return m_flags; } + + const char* className() const; + + VM* vm() const; + + // 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 - virtual CallType getCallData(CallData&); - virtual ConstructType getConstructData(ConstructData&); - - // Extracting integer values. - // FIXME: remove these methods, can check isNumberCell in JSValuePtr && then call asNumberCell::*. - virtual bool getUInt32(uint32_t&) const; - virtual bool getTruncatedInt32(int32_t&) const; - virtual bool getTruncatedUInt32(uint32_t&) const; - - // Basic conversions. - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const = 0; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&) = 0; - virtual bool toBoolean(ExecState*) const = 0; - virtual double toNumber(ExecState*) const = 0; - virtual UString toString(ExecState*) const = 0; - virtual JSObject* toObject(ExecState*) const = 0; - - // Garbage collection. - void* operator new(size_t, ExecState*); - void* operator new(size_t, JSGlobalData*); - void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; } - virtual void mark(); - bool marked() const; - - // Object operations, with the toObject operation included. - virtual const ClassInfo* classInfo() const; - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValuePtr); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual bool deleteProperty(ExecState*, unsigned propertyName); - - virtual JSObject* toThisObject(ExecState*) const; - virtual UString toThisString(ExecState*) const; - virtual JSString* toThisJSString(ExecState*); - virtual JSValuePtr getJSNumber(); - void* vptr() { return *reinterpret_cast(this); } - - private: - // Base implementation; for non-object classes implements getPropertySlot. - bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); - virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); - virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + // Returns information about how to call/construct this cell as a function/constructor. May tell + // you that the cell is not callable or constructor (default is that it's not either). If it + // says that the function is callable, and the TypeOfShouldCallGetCallData type flag is set, and + // this is an object, then typeof will return "function" instead of "object". These methods + // cannot change their minds and must be thread-safe. They are sometimes called from compiler + // threads. + 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; + + void dump(PrintStream&) const; + JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&); + static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken); + + // Object operations, with the toObject operation included. + const ClassInfo* classInfo() const; + const MethodTable* methodTable() const; + const MethodTable* methodTable(VM&) const; + static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); - Structure* m_structure; - }; - - JSCell* asCell(JSValuePtr); - - inline JSCell* asCell(JSValuePtr value) - { - return value.asCell(); - } - - inline JSCell::JSCell(Structure* structure) - : m_structure(structure) - { - } - - inline JSCell::~JSCell() - { - } - - inline bool JSCell::isNumber() const - { - return Heap::isNumber(const_cast(this)); - } - - inline bool JSCell::isObject() const - { - return m_structure->typeInfo().type() == ObjectType; - } - - inline bool JSCell::isString() const - { - return m_structure->typeInfo().type() == StringType; - } - - inline Structure* JSCell::structure() const - { - return m_structure; - } - - inline bool JSCell::marked() const - { - return Heap::isCellMarked(this); - } - - inline void JSCell::mark() - { - return Heap::markCell(this); - } - - ALWAYS_INLINE JSCell* JSValuePtr::asCell() const - { - ASSERT(isCell()); - return m_ptr; - } - - inline void* JSCell::operator new(size_t size, JSGlobalData* globalData) - { -#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - return globalData->heap.inlineAllocate(size); -#else - return globalData->heap.allocate(size); -#endif - } - - // --- JSValue inlines ---------------------------- - - inline bool JSValuePtr::isString() const - { - return !JSImmediate::isImmediate(asValue()) && asCell()->isString(); - } + static bool deleteProperty(JSCell*, ExecState*, PropertyName); + static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - inline bool JSValuePtr::isGetterSetter() const - { - return !JSImmediate::isImmediate(asValue()) && asCell()->isGetterSetter(); - } + static JSValue toThis(JSCell*, ExecState*, ECMAMode); - inline bool JSValuePtr::isObject() const - { - return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(); - } + void zap() { *reinterpret_cast(this) = 0; } + bool isZapped() const { return !*reinterpret_cast(this); } - inline bool JSValuePtr::getString(UString& s) const - { - return !JSImmediate::isImmediate(asValue()) && asCell()->getString(s); - } + static bool canUseFastGetOwnProperty(const Structure&); + JSValue fastGetOwnProperty(VM&, Structure&, PropertyName); - inline UString JSValuePtr::getString() const - { - return JSImmediate::isImmediate(asValue()) ? UString() : asCell()->getString(); - } + enum GCData : uint8_t { + Marked = 0, // The object has survived a GC and is in the old gen. + NotMarked = 1, // The object is new and in the eden gen. + MarkedAndRemembered = 2, // The object is in the GC's remembered set. - inline JSObject* JSValuePtr::getObject() const - { - return JSImmediate::isImmediate(asValue()) ? 0 : asCell()->getObject(); - } + // The object being in the GC's remembered set implies that it is also + // Marked. This is because objects are only added to the remembered sets + // by write barriers, and write barriers are only interested in old gen + // objects that point to potential eden gen objects. + }; - inline CallType JSValuePtr::getCallData(CallData& callData) + void setMarked() { m_gcData = Marked; } + void setRemembered(bool remembered) { - return JSImmediate::isImmediate(asValue()) ? CallTypeNone : asCell()->getCallData(callData); + ASSERT(m_gcData == (remembered ? Marked : MarkedAndRemembered)); + m_gcData = remembered ? MarkedAndRemembered : Marked; } - - inline ConstructType JSValuePtr::getConstructData(ConstructData& constructData) + bool isMarked() const { - return JSImmediate::isImmediate(asValue()) ? ConstructTypeNone : asCell()->getConstructData(constructData); + switch (m_gcData) { + case Marked: + case MarkedAndRemembered: + return true; + case NotMarked: + return false; + } + RELEASE_ASSERT_NOT_REACHED(); + return false; } + bool isRemembered() const { return m_gcData == MarkedAndRemembered; } - ALWAYS_INLINE bool JSValuePtr::getUInt32(uint32_t& v) const + static ptrdiff_t structureIDOffset() { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::getUInt32(asValue(), v) : asCell()->getUInt32(v); + return OBJECT_OFFSETOF(JSCell, m_structureID); } - ALWAYS_INLINE bool JSValuePtr::getTruncatedInt32(int32_t& v) const + static ptrdiff_t typeInfoFlagsOffset() { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedInt32(asValue(), v) : asCell()->getTruncatedInt32(v); + return OBJECT_OFFSETOF(JSCell, m_flags); } - inline bool JSValuePtr::getTruncatedUInt32(uint32_t& v) const + static ptrdiff_t typeInfoTypeOffset() { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedUInt32(asValue(), v) : asCell()->getTruncatedUInt32(v); + return OBJECT_OFFSETOF(JSCell, m_type); } - inline void JSValuePtr::mark() + static ptrdiff_t indexingTypeOffset() { - asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells + return OBJECT_OFFSETOF(JSCell, m_indexingType); } - inline bool JSValuePtr::marked() const + static ptrdiff_t gcDataOffset() { - return JSImmediate::isImmediate(asValue()) || asCell()->marked(); + return OBJECT_OFFSETOF(JSCell, m_gcData); } - inline JSValuePtr JSValuePtr::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const - { - return JSImmediate::isImmediate(asValue()) ? asValue() : asCell()->toPrimitive(exec, preferredType); - } + static const TypedArrayType TypedArrayStorageType = NotTypedArray; +protected: - inline bool JSValuePtr::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& value) - { - if (JSImmediate::isImmediate(asValue())) { - number = JSImmediate::toDouble(asValue()); - value = asValue(); - return true; - } - return asCell()->getPrimitiveNumber(exec, number, value); - } + void finishCreation(VM&); + void finishCreation(VM&, Structure*, CreatingEarlyCellTag); - inline bool JSValuePtr::toBoolean(ExecState* exec) const - { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toBoolean(asValue()) : asCell()->toBoolean(exec); - } + // 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); - ALWAYS_INLINE double JSValuePtr::toNumber(ExecState* exec) const - { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->toNumber(exec); - } + static uint32_t getEnumerableLength(ExecState*, JSObject*); + static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - inline UString JSValuePtr::toString(ExecState* exec) const - { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toString(exec); - } + static String className(const JSObject*); + JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue); + static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); + JS_EXPORT_PRIVATE static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*); + JS_EXPORT_PRIVATE static PassRefPtr getTypedArrayImpl(JSArrayBufferView*); - inline JSObject* JSValuePtr::toObject(ExecState* exec) const - { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toObject(asValue(), exec) : asCell()->toObject(exec); - } +private: + friend class LLIntOffsetsExtractor; - inline JSObject* JSValuePtr::toThisObject(ExecState* exec) const - { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) - return JSImmediate::toThisObject(asValue(), exec); - return asCell()->toThisObject(exec); - } + StructureID m_structureID; + IndexingType m_indexingType; + JSType m_type; + TypeInfo::InlineTypeFlags m_flags; + uint8_t m_gcData; +}; - inline bool JSValuePtr::needsThisConversion() const - { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) - return true; - return asCell()->structure()->typeInfo().needsThisConversion(); - } +template +inline To jsCast(From* from) +{ + ASSERT_WITH_SECURITY_IMPLICATION(!from || from->JSCell::inherits(std::remove_pointer::type::info())); + return static_cast(from); +} + +template +inline To jsCast(JSValue from) +{ + ASSERT_WITH_SECURITY_IMPLICATION(from.isCell() && from.asCell()->JSCell::inherits(std::remove_pointer::type::info())); + return static_cast(from.asCell()); +} - inline UString JSValuePtr::toThisString(ExecState* exec) const - { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toThisString(exec); - } +template +inline To jsDynamicCast(From* from) +{ + if (LIKELY(from->inherits(std::remove_pointer::type::info()))) + return static_cast(from); + return nullptr; +} - inline JSValuePtr JSValuePtr::getJSNumber() - { - return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? noValue() : asCell()->getJSNumber(); - } +template +inline To jsDynamicCast(JSValue from) +{ + if (LIKELY(from.isCell() && from.asCell()->inherits(std::remove_pointer::type::info()))) + return static_cast(from.asCell()); + return nullptr; +} } // namespace JSC