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, 2015 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 "CellState.h"
28#include "ConstructData.h"
29#include "EnumerationMode.h"
30#include "Heap.h"
31#include "IndexingType.h"
32#include "JSLock.h"
33#include "JSTypeInfo.h"
34#include "SlotVisitor.h"
35#include "TypedArrayType.h"
36#include "WriteBarrier.h"
37#include <wtf/Noncopyable.h>
38
39namespace JSC {
40
41class CopyVisitor;
42class ExecState;
43class Identifier;
44class JSArrayBufferView;
45class JSDestructibleObject;
46class JSGlobalObject;
47class LLIntOffsetsExtractor;
48class PropertyDescriptor;
49class PropertyNameArray;
50class Structure;
51
52template<typename T> void* allocateCell(Heap&);
53template<typename T> void* allocateCell(Heap&, size_t);
54
55#define DECLARE_EXPORT_INFO \
56 protected: \
57 static JS_EXPORTDATA const ::JSC::ClassInfo s_info; \
58 public: \
59 static const ::JSC::ClassInfo* info() { return &s_info; }
60
61#define DECLARE_INFO \
62 protected: \
63 static const ::JSC::ClassInfo s_info; \
64 public: \
65 static const ::JSC::ClassInfo* info() { return &s_info; }
66
67class JSCell {
68 friend class JSValue;
69 friend class MarkedBlock;
70 template<typename T> friend void* allocateCell(Heap&);
71 template<typename T> friend void* allocateCell(Heap&, size_t);
72
73public:
74 static const unsigned StructureFlags = 0;
75
76 static const bool needsDestruction = false;
77
78 static JSCell* seenMultipleCalleeObjects() { return bitwise_cast<JSCell*>(static_cast<uintptr_t>(1)); }
79
80 enum CreatingEarlyCellTag { CreatingEarlyCell };
81 JSCell(CreatingEarlyCellTag);
82
83protected:
84 JSCell(VM&, Structure*);
85 JS_EXPORT_PRIVATE static void destroy(JSCell*);
86
87public:
88 // Querying the type.
89 bool isString() const;
90 bool isSymbol() 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 VM* vm() const;
111
112 // Extracting the value.
113 JS_EXPORT_PRIVATE bool getString(ExecState*, String&) const;
114 JS_EXPORT_PRIVATE String getString(ExecState*) const; // null string if not a string
115 JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
116 const JSObject* getObject() const; // NULL if not an object
117
118 // Returns information about how to call/construct this cell as a function/constructor. May tell
119 // you that the cell is not callable or constructor (default is that it's not either). If it
120 // says that the function is callable, and the TypeOfShouldCallGetCallData type flag is set, and
121 // this is an object, then typeof will return "function" instead of "object". These methods
122 // cannot change their minds and must be thread-safe. They are sometimes called from compiler
123 // threads.
124 JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
125 JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
126
127 // Basic conversions.
128 JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
129 bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
130 bool toBoolean(ExecState*) const;
131 TriState pureToBoolean() const;
132 JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
133 JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
134
135 void dump(PrintStream&) const;
136 JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&);
137
138 size_t estimatedSizeInBytes() const;
139 JS_EXPORT_PRIVATE static size_t estimatedSize(JSCell*);
140
141 static void visitChildren(JSCell*, SlotVisitor&);
142 JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);
143
144 // Object operations, with the toObject operation included.
145 const ClassInfo* classInfo() const;
146 const MethodTable* methodTable() const;
147 const MethodTable* methodTable(VM&) const;
148 static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
149 static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
150
151 static bool deleteProperty(JSCell*, ExecState*, PropertyName);
152 static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
153
154 static JSValue toThis(JSCell*, ExecState*, ECMAMode);
155
156 void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
157 bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
158
159 static bool canUseFastGetOwnProperty(const Structure&);
160 JSValue fastGetOwnProperty(VM&, Structure&, PropertyName);
161
162 // The recommended idiom for using cellState() is to switch on it or perform an == comparison on it
163 // directly. We deliberately avoid helpers for this, because we want transparency about how the various
164 // CellState values influences our various algorithms.
165 CellState cellState() const { return m_cellState; }
166
167 void setCellState(CellState data) const { const_cast<JSCell*>(this)->m_cellState = data; }
168
169 static ptrdiff_t structureIDOffset()
170 {
171 return OBJECT_OFFSETOF(JSCell, m_structureID);
172 }
173
174 static ptrdiff_t typeInfoFlagsOffset()
175 {
176 return OBJECT_OFFSETOF(JSCell, m_flags);
177 }
178
179 static ptrdiff_t typeInfoTypeOffset()
180 {
181 return OBJECT_OFFSETOF(JSCell, m_type);
182 }
183
184 static ptrdiff_t indexingTypeOffset()
185 {
186 return OBJECT_OFFSETOF(JSCell, m_indexingType);
187 }
188
189 static ptrdiff_t cellStateOffset()
190 {
191 return OBJECT_OFFSETOF(JSCell, m_cellState);
192 }
193
194 static const TypedArrayType TypedArrayStorageType = NotTypedArray;
195protected:
196
197 void finishCreation(VM&);
198 void finishCreation(VM&, Structure*, CreatingEarlyCellTag);
199
200 // Dummy implementations of override-able static functions for classes to put in their MethodTable
201 static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
202 static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
203 static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
204 static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
205
206 static uint32_t getEnumerableLength(ExecState*, JSObject*);
207 static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
208 static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
209
210 static String className(const JSObject*);
211 JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
212 static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
213 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
214 static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
215 JS_EXPORT_PRIVATE static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*);
216 JS_EXPORT_PRIVATE static PassRefPtr<ArrayBufferView> getTypedArrayImpl(JSArrayBufferView*);
217
218private:
219 friend class LLIntOffsetsExtractor;
220
221 StructureID m_structureID;
222 IndexingType m_indexingType;
223 JSType m_type;
224 TypeInfo::InlineTypeFlags m_flags;
225 CellState m_cellState;
226};
227
228template<typename To, typename From>
229inline To jsCast(From* from)
230{
231 ASSERT_WITH_SECURITY_IMPLICATION(!from || from->JSCell::inherits(std::remove_pointer<To>::type::info()));
232 return static_cast<To>(from);
233}
234
235template<typename To>
236inline To jsCast(JSValue from)
237{
238 ASSERT_WITH_SECURITY_IMPLICATION(from.isCell() && from.asCell()->JSCell::inherits(std::remove_pointer<To>::type::info()));
239 return static_cast<To>(from.asCell());
240}
241
242template<typename To, typename From>
243inline To jsDynamicCast(From* from)
244{
245 if (LIKELY(from->inherits(std::remove_pointer<To>::type::info())))
246 return static_cast<To>(from);
247 return nullptr;
248}
249
250template<typename To>
251inline To jsDynamicCast(JSValue from)
252{
253 if (LIKELY(from.isCell() && from.asCell()->inherits(std::remove_pointer<To>::type::info())))
254 return static_cast<To>(from.asCell());
255 return nullptr;
256}
257
258} // namespace JSC
259
260#endif // JSCell_h
261