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