| /* |
| * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) |
| * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
| * 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 |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #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 <wtf/Noncopyable.h> |
| |
| namespace JSC { |
| |
| class CopyVisitor; |
| class ExecState; |
| class Identifier; |
| class JSArrayBufferView; |
| class JSDestructibleObject; |
| class JSGlobalObject; |
| class LLIntOffsetsExtractor; |
| class PropertyDescriptor; |
| class PropertyNameArray; |
| class Structure; |
| |
| template<typename T> void* allocateCell(Heap&); |
| template<typename T> 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<typename T> friend void* allocateCell(Heap&); |
| template<typename T> friend void* allocateCell(Heap&, size_t); |
| |
| public: |
| static const unsigned StructureFlags = 0; |
| |
| static const bool needsDestruction = false; |
| |
| static JSCell* seenMultipleCalleeObjects() { return bitwise_cast<JSCell*>(static_cast<uintptr_t>(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 |
| |
| // 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); |
| |
| static bool deleteProperty(JSCell*, ExecState*, PropertyName); |
| static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); |
| |
| static JSValue toThis(JSCell*, ExecState*, ECMAMode); |
| |
| void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; } |
| bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); } |
| |
| static bool canUseFastGetOwnProperty(const Structure&); |
| JSValue fastGetOwnProperty(VM&, Structure&, PropertyName); |
| |
| 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. |
| |
| // 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. |
| }; |
| |
| void setMarked() { m_gcData = Marked; } |
| void setRemembered(bool remembered) |
| { |
| ASSERT(m_gcData == (remembered ? Marked : MarkedAndRemembered)); |
| m_gcData = remembered ? MarkedAndRemembered : Marked; |
| } |
| bool isMarked() const |
| { |
| 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; } |
| |
| static ptrdiff_t structureIDOffset() |
| { |
| return OBJECT_OFFSETOF(JSCell, m_structureID); |
| } |
| |
| static ptrdiff_t typeInfoFlagsOffset() |
| { |
| return OBJECT_OFFSETOF(JSCell, m_flags); |
| } |
| |
| static ptrdiff_t typeInfoTypeOffset() |
| { |
| return OBJECT_OFFSETOF(JSCell, m_type); |
| } |
| |
| static ptrdiff_t indexingTypeOffset() |
| { |
| return OBJECT_OFFSETOF(JSCell, m_indexingType); |
| } |
| |
| static ptrdiff_t gcDataOffset() |
| { |
| return OBJECT_OFFSETOF(JSCell, m_gcData); |
| } |
| |
| static const TypedArrayType TypedArrayStorageType = NotTypedArray; |
| protected: |
| |
| void finishCreation(VM&); |
| void finishCreation(VM&, Structure*, CreatingEarlyCellTag); |
| |
| // 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 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); |
| |
| 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<ArrayBufferView> getTypedArrayImpl(JSArrayBufferView*); |
| |
| private: |
| friend class LLIntOffsetsExtractor; |
| |
| StructureID m_structureID; |
| IndexingType m_indexingType; |
| JSType m_type; |
| TypeInfo::InlineTypeFlags m_flags; |
| uint8_t m_gcData; |
| }; |
| |
| template<typename To, typename From> |
| inline To& jsCast(From& from) |
| { |
| ASSERT_WITH_SECURITY_IMPLICATION(from.JSCell::inherits(std::remove_reference<To>::type::info())); |
| return static_cast<To&>(from); |
| } |
| |
| template<typename To, typename From> |
| inline To jsCast(From* from) |
| { |
| ASSERT_WITH_SECURITY_IMPLICATION(!from || from->JSCell::inherits(std::remove_pointer<To>::type::info())); |
| return static_cast<To>(from); |
| } |
| |
| template<typename To> |
| inline To jsCast(JSValue from) |
| { |
| ASSERT_WITH_SECURITY_IMPLICATION(from.isCell() && from.asCell()->JSCell::inherits(std::remove_pointer<To>::type::info())); |
| return static_cast<To>(from.asCell()); |
| } |
| |
| template<typename To, typename From> |
| inline To jsDynamicCast(From* from) |
| { |
| if (LIKELY(from->inherits(std::remove_pointer<To>::type::info()))) |
| return static_cast<To>(from); |
| return nullptr; |
| } |
| |
| template<typename To> |
| inline To jsDynamicCast(JSValue from) |
| { |
| if (LIKELY(from.isCell() && from.asCell()->inherits(std::remove_pointer<To>::type::info()))) |
| return static_cast<To>(from.asCell()); |
| return nullptr; |
| } |
| |
| } // namespace JSC |
| |
| #endif // JSCell_h |