1/* 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2004, 2005, 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 JSCell_h 24#define JSCell_h 25 26#include "CallData.h" 27#include "ConstructData.h" 28#include "Heap.h" 29#include "IndexingType.h" 30#include "JSLock.h" 31#include "JSTypeInfo.h" 32#include "SlotVisitor.h" 33#include "TypedArrayType.h" 34#include "WriteBarrier.h" 35#include <wtf/Noncopyable.h> 36 37namespace JSC { 38 39class CopyVisitor; 40class ExecState; 41class JSArrayBufferView; 42class JSDestructibleObject; 43class JSGlobalObject; 44class LLIntOffsetsExtractor; 45class PropertyDescriptor; 46class PropertyNameArray; 47class Structure; 48 49enum EnumerationMode { 50 ExcludeDontEnumProperties, 51 IncludeDontEnumProperties 52}; 53 54template<typename T> void* allocateCell(Heap&); 55template<typename T> void* allocateCell(Heap&, size_t); 56 57#define DECLARE_EXPORT_INFO \ 58 protected: \ 59 static JS_EXPORTDATA const ::JSC::ClassInfo s_info; \ 60 public: \ 61 static const ::JSC::ClassInfo* info() { return &s_info; } 62 63#define DECLARE_INFO \ 64 protected: \ 65 static const ::JSC::ClassInfo s_info; \ 66 public: \ 67 static const ::JSC::ClassInfo* info() { return &s_info; } 68 69class JSCell { 70 friend class JSValue; 71 friend class MarkedBlock; 72 template<typename T> friend void* allocateCell(Heap&); 73 template<typename T> friend void* allocateCell(Heap&, size_t); 74 75public: 76 static const unsigned StructureFlags = 0; 77 78 static const bool needsDestruction = false; 79 static const bool hasImmortalStructure = false; 80 81 enum CreatingEarlyCellTag { CreatingEarlyCell }; 82 JSCell(CreatingEarlyCellTag); 83 84protected: 85 JSCell(VM&, Structure*); 86 JS_EXPORT_PRIVATE static void destroy(JSCell*); 87 88public: 89 // Querying the type. 90 bool isString() const; 91 bool isObject() const; 92 bool isGetterSetter() const; 93 bool isCustomGetterSetter() const; 94 bool isProxy() const; 95 bool inherits(const ClassInfo*) const; 96 bool isAPIValueWrapper() const; 97 98 JSType type() const; 99 IndexingType indexingType() const; 100 StructureID structureID() const { return m_structureID; } 101 Structure* structure() const; 102 Structure* structure(VM&) const; 103 void setStructure(VM&, Structure*); 104 void clearStructure() { m_structureID = 0; } 105 106 TypeInfo::InlineTypeFlags inlineTypeFlags() const { return m_flags; } 107 108 const char* className() const; 109 110 // Extracting the value. 111 JS_EXPORT_PRIVATE bool getString(ExecState*, String&) const; 112 JS_EXPORT_PRIVATE String getString(ExecState*) const; // null string if not a string 113 JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object 114 const JSObject* getObject() const; // NULL if not an object 115 116 JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&); 117 JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&); 118 119 // Basic conversions. 120 JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; 121 bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; 122 bool toBoolean(ExecState*) const; 123 TriState pureToBoolean() const; 124 JS_EXPORT_PRIVATE double toNumber(ExecState*) const; 125 JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const; 126 127 void dump(PrintStream&) const; 128 JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&); 129 static void visitChildren(JSCell*, SlotVisitor&); 130 JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken); 131 132 // Object operations, with the toObject operation included. 133 const ClassInfo* classInfo() const; 134 const MethodTable* methodTable() const; 135 const MethodTable* methodTable(VM&) const; 136 static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); 137 static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); 138 139 static bool deleteProperty(JSCell*, ExecState*, PropertyName); 140 static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); 141 142 static JSValue toThis(JSCell*, ExecState*, ECMAMode); 143 144 void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; } 145 bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); } 146 147 static bool canUseFastGetOwnProperty(const Structure&); 148 JSValue fastGetOwnProperty(VM&, Structure&, const String&); 149 150 enum GCData : uint8_t { 151 Marked = 0, 152 NotMarked = 1, 153 MarkedAndRemembered = 2, 154 }; 155 156 void setMarked() { m_gcData = Marked; } 157 void setRemembered(bool remembered) 158 { 159 ASSERT(m_gcData == (remembered ? Marked : MarkedAndRemembered)); 160 m_gcData = remembered ? MarkedAndRemembered : Marked; 161 } 162 bool isMarked() const 163 { 164 switch (m_gcData) { 165 case Marked: 166 case MarkedAndRemembered: 167 return true; 168 case NotMarked: 169 return false; 170 } 171 RELEASE_ASSERT_NOT_REACHED(); 172 return false; 173 } 174 bool isRemembered() const { return m_gcData == MarkedAndRemembered; } 175 176 static ptrdiff_t structureIDOffset() 177 { 178 return OBJECT_OFFSETOF(JSCell, m_structureID); 179 } 180 181 static ptrdiff_t typeInfoFlagsOffset() 182 { 183 return OBJECT_OFFSETOF(JSCell, m_flags); 184 } 185 186 static ptrdiff_t typeInfoTypeOffset() 187 { 188 return OBJECT_OFFSETOF(JSCell, m_type); 189 } 190 191 static ptrdiff_t indexingTypeOffset() 192 { 193 return OBJECT_OFFSETOF(JSCell, m_indexingType); 194 } 195 196 static ptrdiff_t gcDataOffset() 197 { 198 return OBJECT_OFFSETOF(JSCell, m_gcData); 199 } 200 201 static const TypedArrayType TypedArrayStorageType = NotTypedArray; 202protected: 203 204 void finishCreation(VM&); 205 void finishCreation(VM&, Structure*, CreatingEarlyCellTag); 206 207 // Dummy implementations of override-able static functions for classes to put in their MethodTable 208 static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); 209 static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 210 static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 211 static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 212 static String className(const JSObject*); 213 JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue); 214 static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); 215 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); 216 static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); 217 JS_EXPORT_PRIVATE static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*); 218 JS_EXPORT_PRIVATE static PassRefPtr<ArrayBufferView> getTypedArrayImpl(JSArrayBufferView*); 219 220private: 221 friend class LLIntOffsetsExtractor; 222 223 StructureID m_structureID; 224 IndexingType m_indexingType; 225 JSType m_type; 226 TypeInfo::InlineTypeFlags m_flags; 227 uint8_t m_gcData; 228}; 229 230template<typename To, typename From> 231inline To jsCast(From* from) 232{ 233 ASSERT(!from || from->JSCell::inherits(std::remove_pointer<To>::type::info())); 234 return static_cast<To>(from); 235} 236 237template<typename To> 238inline To jsCast(JSValue from) 239{ 240 ASSERT(from.isCell() && from.asCell()->JSCell::inherits(std::remove_pointer<To>::type::info())); 241 return static_cast<To>(from.asCell()); 242} 243 244template<typename To, typename From> 245inline To jsDynamicCast(From* from) 246{ 247 if (LIKELY(from->inherits(std::remove_pointer<To>::type::info()))) 248 return static_cast<To>(from); 249 return nullptr; 250} 251 252template<typename To> 253inline To jsDynamicCast(JSValue from) 254{ 255 if (LIKELY(from.isCell() && from.asCell()->inherits(std::remove_pointer<To>::type::info()))) 256 return static_cast<To>(from.asCell()); 257 return nullptr; 258} 259 260} // namespace JSC 261 262#endif // JSCell_h 263