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