We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSCell.h
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003-2017 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 #pragma once
24
25 #include "CallData.h"
26 #include "CellState.h"
27 #include "ConstructData.h"
28 #include "EnumerationMode.h"
29 #include "Heap.h"
30 #include "HeapCell.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
38 namespace JSC {
39
40 class CompleteSubspace;
41 class CopyVisitor;
42 class GCDeferralContext;
43 class ExecState;
44 class Identifier;
45 class JSArrayBufferView;
46 class JSDestructibleObject;
47 class JSGlobalObject;
48 class LLIntOffsetsExtractor;
49 class PropertyDescriptor;
50 class PropertyName;
51 class PropertyNameArray;
52 class Structure;
53 class JSCellLock;
54
55 enum class GCDeferralContextArgPresense {
56     HasArg,
57     DoesNotHaveArg
58 };
59
60 template<typename T> void* allocateCell(Heap&, size_t = sizeof(T));
61 template<typename T> void* tryAllocateCell(Heap&, size_t = sizeof(T));
62 template<typename T> void* allocateCell(Heap&, GCDeferralContext*, size_t = sizeof(T));
63 template<typename T> void* tryAllocateCell(Heap&, GCDeferralContext*, size_t = sizeof(T));
64
65 #define DECLARE_EXPORT_INFO                                                  \
66     protected:                                                               \
67         static JS_EXPORT_PRIVATE const ::JSC::ClassInfo s_info;              \
68     public:                                                                  \
69         static constexpr const ::JSC::ClassInfo* info() { return &s_info; }
70
71 #define DECLARE_INFO                                                         \
72     protected:                                                               \
73         static const ::JSC::ClassInfo s_info;                                \
74     public:                                                                  \
75         static constexpr const ::JSC::ClassInfo* info() { return &s_info; }
76
77 class JSCell : public HeapCell {
78     friend class JSValue;
79     friend class MarkedBlock;
80     template<typename T>
81     friend void* tryAllocateCellHelper(Heap&, size_t, GCDeferralContext*, AllocationFailureMode);
82
83 public:
84     static const unsigned StructureFlags = 0;
85
86     static const bool needsDestruction = false;
87
88     // Don't call this directly. Call JSC::subspaceFor<Type>(vm) instead.
89     // FIXME: Refer to Subspace by reference.
90     // https://bugs.webkit.org/show_bug.cgi?id=166988
91     template<typename CellType>
92     static CompleteSubspace* subspaceFor(VM&);
93
94     static JSCell* seenMultipleCalleeObjects() { return bitwise_cast<JSCell*>(static_cast<uintptr_t>(1)); }
95
96     enum CreatingEarlyCellTag { CreatingEarlyCell };
97     JSCell(CreatingEarlyCellTag);
98     
99 protected:
100     JSCell(VM&, Structure*);
101     JS_EXPORT_PRIVATE static void destroy(JSCell*);
102
103 public:
104     // Querying the type.
105     bool isString() const;
106     bool isBigInt() const;
107     bool isSymbol() const;
108     bool isObject() const;
109     bool isGetterSetter() const;
110     bool isCustomGetterSetter() const;
111     bool isProxy() const;
112     bool isFunction(VM&);
113     bool isCallable(VM&, CallType&, CallData&);
114     bool isConstructor(VM&);
115     bool isConstructor(VM&, ConstructType&, ConstructData&);
116     bool inherits(VM&, const ClassInfo*) const;
117     template<typename Target> bool inherits(VM&) const;
118     bool isAPIValueWrapper() const;
119     
120     // Each cell has a built-in lock. Currently it's simply available for use if you need it. It's
121     // a full-blown WTF::Lock. Note that this lock is currently used in JSArray and that lock's
122     // ordering with the Structure lock is that the Structure lock must be acquired first.
123
124     // We use this abstraction to make it easier to grep for places where we lock cells.
125     // to lock a cell you can just do:
126     // auto locker = holdLock(cell->cellLocker());
127     JSCellLock& cellLock() { return *reinterpret_cast<JSCellLock*>(this); }
128     
129     JSType type() const;
130     IndexingType indexingTypeAndMisc() const;
131     IndexingType indexingMode() const;
132     IndexingType indexingType() const;
133     StructureID structureID() const { return m_structureID; }
134     Structure* structure() const;
135     Structure* structure(VM&) const;
136     void setStructure(VM&, Structure*);
137     void setStructureIDDirectly(StructureID id) { m_structureID = id; }
138     void clearStructure() { m_structureID = 0; }
139
140     TypeInfo::InlineTypeFlags inlineTypeFlags() const { return m_flags; }
141     
142     bool mayBePrototype() const;
143     void didBecomePrototype();
144
145     const char* className(VM&) const;
146
147     // Extracting the value.
148     JS_EXPORT_PRIVATE bool getString(ExecState*, String&) const;
149     JS_EXPORT_PRIVATE String getString(ExecState*) const; // null string if not a string
150     JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
151     const JSObject* getObject() const; // NULL if not an object
152         
153     // Returns information about how to call/construct this cell as a function/constructor. May tell
154     // you that the cell is not callable or constructor (default is that it's not either). If it
155     // says that the function is callable, and the OverridesGetCallData type flag is set, and
156     // this is an object, then typeof will return "function" instead of "object". These methods
157     // cannot change their minds and must be thread-safe. They are sometimes called from compiler
158     // threads.
159     JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
160     JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
161
162     // Basic conversions.
163     JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
164     bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
165     bool toBoolean(ExecState*) const;
166     TriState pureToBoolean() const;
167     JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
168     JSObject* toObject(ExecState*, JSGlobalObject*) const;
169
170     void dump(PrintStream&) const;
171     JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&);
172
173     size_t estimatedSizeInBytes(VM&) const;
174     JS_EXPORT_PRIVATE static size_t estimatedSize(JSCell*, VM&);
175
176     static void visitChildren(JSCell*, SlotVisitor&);
177     static void visitOutputConstraints(JSCell*, SlotVisitor&);
178
179     JS_EXPORT_PRIVATE static void heapSnapshot(JSCell*, HeapSnapshotBuilder&);
180
181     // Object operations, with the toObject operation included.
182     const ClassInfo* classInfo(VM&) const;
183     const MethodTable* methodTable(VM&) const;
184     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
185     static bool putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
186     bool putInline(ExecState*, PropertyName, JSValue, PutPropertySlot&);
187         
188     static bool deleteProperty(JSCell*, ExecState*, PropertyName);
189     static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
190
191     static JSValue toThis(JSCell*, ExecState*, ECMAMode);
192
193     static bool canUseFastGetOwnProperty(const Structure&);
194     JSValue fastGetOwnProperty(VM&, Structure&, PropertyName);
195
196     // The recommended idiom for using cellState() is to switch on it or perform an == comparison on it
197     // directly. We deliberately avoid helpers for this, because we want transparency about how the various
198     // CellState values influences our various algorithms. 
199     CellState cellState() const { return m_cellState; }
200     
201     void setCellState(CellState data) const { const_cast<JSCell*>(this)->m_cellState = data; }
202     
203     bool atomicCompareExchangeCellStateWeakRelaxed(CellState oldState, CellState newState)
204     {
205         return WTF::atomicCompareExchangeWeakRelaxed(&m_cellState, oldState, newState);
206     }
207
208     CellState atomicCompareExchangeCellStateStrong(CellState oldState, CellState newState)
209     {
210         return WTF::atomicCompareExchangeStrong(&m_cellState, oldState, newState);
211     }
212
213     static ptrdiff_t structureIDOffset()
214     {
215         return OBJECT_OFFSETOF(JSCell, m_structureID);
216     }
217
218     static ptrdiff_t typeInfoFlagsOffset()
219     {
220         return OBJECT_OFFSETOF(JSCell, m_flags);
221     }
222
223     static ptrdiff_t typeInfoTypeOffset()
224     {
225         return OBJECT_OFFSETOF(JSCell, m_type);
226     }
227
228     // DO NOT store to this field. Always use a CAS loop, since some bits are flipped using CAS
229     // from other threads due to the internal lock. One exception: you don't need the CAS if the
230     // object has not escaped yet.
231     static ptrdiff_t indexingTypeAndMiscOffset()
232     {
233         return OBJECT_OFFSETOF(JSCell, m_indexingTypeAndMisc);
234     }
235
236     static ptrdiff_t cellStateOffset()
237     {
238         return OBJECT_OFFSETOF(JSCell, m_cellState);
239     }
240     
241     static const TypedArrayType TypedArrayStorageType = NotTypedArray;
242 protected:
243
244     void finishCreation(VM&);
245     void finishCreation(VM&, Structure*, CreatingEarlyCellTag);
246
247     // Dummy implementations of override-able static functions for classes to put in their MethodTable
248     static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
249     static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
250     static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
251     static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
252
253     static uint32_t getEnumerableLength(ExecState*, JSObject*);
254     static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
255     static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
256     static NO_RETURN_DUE_TO_CRASH bool preventExtensions(JSObject*, ExecState*);
257     static NO_RETURN_DUE_TO_CRASH bool isExtensible(JSObject*, ExecState*);
258     static NO_RETURN_DUE_TO_CRASH bool setPrototype(JSObject*, ExecState*, JSValue, bool);
259     static NO_RETURN_DUE_TO_CRASH JSValue getPrototype(JSObject*, ExecState*);
260
261     static String className(const JSObject*, VM&);
262     static String toStringName(const JSObject*, ExecState*);
263     JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
264     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
265     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
266     static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
267
268 private:
269     friend class LLIntOffsetsExtractor;
270     friend class JSCellLock;
271
272     JS_EXPORT_PRIVATE JSObject* toObjectSlow(ExecState*, JSGlobalObject*) const;
273
274     StructureID m_structureID;
275     IndexingType m_indexingTypeAndMisc; // DO NOT store to this field. Always CAS.
276     JSType m_type;
277     TypeInfo::InlineTypeFlags m_flags;
278     CellState m_cellState;
279 };
280
281 class JSCellLock : public JSCell {
282 public:
283     void lock();
284     bool tryLock();
285     void unlock();
286     bool isLocked() const;
287 private:
288     JS_EXPORT_PRIVATE void lockSlow();
289     JS_EXPORT_PRIVATE void unlockSlow();
290 };
291
292 // FIXME: Refer to Subspace by reference.
293 // https://bugs.webkit.org/show_bug.cgi?id=166988
294 template<typename Type>
295 inline auto subspaceFor(VM& vm)
296 {
297     return Type::template subspaceFor<Type>(vm);
298 }
299
300 } // namespace JSC