2008-09-15 Gavin Barraclough <barraclough@apple.com>
[WebKit-https.git] / JavaScriptCore / kjs / 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 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 "StructureID.h"
27 #include "JSValue.h"
28 #include "collector.h"
29
30 namespace JSC {
31
32     class JSCell : public JSValue {
33         friend class Heap;
34         friend class GetterSetter;
35         friend class JSObject;
36         friend class JSPropertyNameIterator;
37         friend class JSValue;
38         friend class JSNumberCell;
39         friend class JSString;
40         friend class Machine;
41         friend class CTI;
42     private:
43         JSCell(StructureID*);
44         virtual ~JSCell();
45
46     public:
47         // Querying the type.
48         bool isNumber() const;
49         bool isString() const;
50         bool isObject() const;
51         virtual bool isGetterSetter() const;
52         virtual bool isObject(const ClassInfo*) const;
53
54         StructureID* structureID() const;
55
56         // Extracting the value.
57         bool getNumber(double&) const;
58         double getNumber() const; // NaN if not a number
59         bool getString(UString&) const;
60         UString getString() const; // null string if not a string
61         JSObject* getObject(); // NULL if not an object
62         const JSObject* getObject() const; // NULL if not an object
63         
64         virtual CallType getCallData(CallData&);
65         virtual ConstructType getConstructData(ConstructData&);
66
67         // Extracting integer values.
68         virtual bool getUInt32(uint32_t&) const;
69         virtual bool getTruncatedInt32(int32_t&) const;
70         virtual bool getTruncatedUInt32(uint32_t&) const;
71
72         // Basic conversions.
73         virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
74         virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
75         virtual bool toBoolean(ExecState*) const = 0;
76         virtual double toNumber(ExecState*) const = 0;
77         virtual UString toString(ExecState*) const = 0;
78         virtual JSObject* toObject(ExecState*) const = 0;
79
80         // WebCore uses this to make document.all and style.filter undetectable
81         //
82         // This in checked in CTI using a vptr check, so currently only StringObjectThatMasqueradesAsUndefined
83         // overloading ths is supported.  If this behaviour is required in other classes, then we will need
84         // update the code generated.
85         virtual bool masqueradeAsUndefined() const { return false; }
86
87         // Garbage collection.
88         void* operator new(size_t, ExecState*);
89         void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
90         virtual void mark();
91         bool marked() const;
92
93         // Object operations, with the toObject operation included.
94         virtual const ClassInfo* classInfo() const;
95         virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
96         virtual void put(ExecState*, unsigned propertyName, JSValue*);
97         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
98         virtual bool deleteProperty(ExecState*, unsigned propertyName);
99
100         virtual JSObject* toThisObject(ExecState*) const;
101         virtual UString toThisString(ExecState*) const;
102         virtual JSString* toThisJSString(ExecState*);
103         virtual JSValue* getJSNumber();
104         void* vptr() { return *reinterpret_cast<void**>(this); }
105
106     private:
107         // Base implementation, but for non-object classes implements getPropertySlot.
108         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
109         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
110         
111         StructureID* m_structureID;
112     };
113
114     inline JSCell::JSCell(StructureID* structureID)
115         : m_structureID(structureID)
116     {
117     }
118
119     inline JSCell::~JSCell()
120     {
121     }
122
123     inline bool JSCell::isNumber() const
124     {
125         return Heap::isNumber(const_cast<JSCell*>(this));
126     }
127
128     inline bool JSCell::isObject() const
129     {
130         return m_structureID->type() == ObjectType;
131     }
132
133     inline bool JSCell::isString() const
134     {
135         return m_structureID->type() == StringType;
136     }
137
138     inline StructureID* JSCell::structureID() const
139     {
140         return m_structureID;
141     }
142
143     inline bool JSCell::marked() const
144     {
145         return Heap::isCellMarked(this);
146     }
147
148     inline void JSCell::mark()
149     {
150         return Heap::markCell(this);
151     }
152
153     ALWAYS_INLINE JSCell* JSValue::asCell()
154     {
155         ASSERT(!JSImmediate::isImmediate(this));
156         return static_cast<JSCell*>(this);
157     }
158
159     ALWAYS_INLINE const JSCell* JSValue::asCell() const
160     {
161         ASSERT(!JSImmediate::isImmediate(this));
162         return static_cast<const JSCell*>(this);
163     }
164
165
166     // --- JSValue inlines ----------------------------
167
168     inline bool JSValue::isNumber() const
169     {
170         return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
171     }
172
173     inline bool JSValue::isString() const
174     {
175         return !JSImmediate::isImmediate(this) && asCell()->isString();
176     }
177
178     inline bool JSValue::isGetterSetter() const
179     {
180         return !JSImmediate::isImmediate(this) && asCell()->isGetterSetter();
181     }
182
183     inline bool JSValue::isObject() const
184     {
185         return !JSImmediate::isImmediate(this) && asCell()->isObject();
186     }
187
188     inline bool JSValue::getNumber(double& v) const
189     {
190         if (JSImmediate::isImmediate(this)) {
191             v = JSImmediate::toDouble(this);
192             return true;
193         }
194         return asCell()->getNumber(v);
195     }
196
197     inline double JSValue::getNumber() const
198     {
199         return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
200     }
201
202     inline bool JSValue::getString(UString& s) const
203     {
204         return !JSImmediate::isImmediate(this) && asCell()->getString(s);
205     }
206
207     inline UString JSValue::getString() const
208     {
209         return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
210     }
211
212     inline JSObject* JSValue::getObject()
213     {
214         return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
215     }
216
217     inline const JSObject* JSValue::getObject() const
218     {
219         return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
220     }
221
222     inline CallType JSValue::getCallData(CallData& callData)
223     {
224         return JSImmediate::isImmediate(this) ? CallTypeNone : asCell()->getCallData(callData);
225     }
226
227     inline ConstructType JSValue::getConstructData(ConstructData& constructData)
228     {
229         return JSImmediate::isImmediate(this) ? ConstructTypeNone : asCell()->getConstructData(constructData);
230     }
231
232     ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
233     {
234         return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
235     }
236
237     ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
238     {
239         return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
240     }
241
242     inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
243     {
244         return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
245     }
246
247     inline void JSValue::mark()
248     {
249         ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
250         asCell()->mark();
251     }
252
253     inline bool JSValue::marked() const
254     {
255         return JSImmediate::isImmediate(this) || asCell()->marked();
256     }
257
258     inline JSValue* JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
259     {
260         return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
261     }
262
263     inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
264     {
265         if (JSImmediate::isImmediate(this)) {
266             number = JSImmediate::toDouble(this);
267             value = this;
268             return true;
269         }
270         return asCell()->getPrimitiveNumber(exec, number, value);
271     }
272
273     inline bool JSValue::toBoolean(ExecState* exec) const
274     {
275         return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
276     }
277
278     ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
279     {
280         return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
281     }
282
283     inline UString JSValue::toString(ExecState* exec) const
284     {
285         return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
286     }
287
288     inline JSObject* JSValue::toObject(ExecState* exec) const
289     {
290         return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
291     }
292
293     inline JSObject* JSValue::toThisObject(ExecState* exec) const
294     {
295         if (UNLIKELY(JSImmediate::isImmediate(this)))
296             return JSImmediate::toObject(this, exec);
297         return asCell()->toThisObject(exec);
298     }
299
300     inline UString JSValue::toThisString(ExecState* exec) const
301     {
302         return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toThisString(exec);
303     }
304
305     inline JSValue* JSValue::getJSNumber()
306     {
307
308         return JSImmediate::isNumber(this) ? this : (JSImmediate::isImmediate(this) ? 0 : asCell()->getJSNumber());
309     }
310
311 } // namespace JSC
312
313 #endif // JSCell_h