2008-09-15 Sam Weinig <sam@webkit.org>
[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         virtual bool masqueradeAsUndefined() const { return false; }
82
83         // Garbage collection.
84         void* operator new(size_t, ExecState*);
85         void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
86         virtual void mark();
87         bool marked() const;
88
89         // Object operations, with the toObject operation included.
90         virtual const ClassInfo* classInfo() const;
91         virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
92         virtual void put(ExecState*, unsigned propertyName, JSValue*);
93         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
94         virtual bool deleteProperty(ExecState*, unsigned propertyName);
95
96         virtual JSObject* toThisObject(ExecState*) const;
97         virtual UString toThisString(ExecState*) const;
98         virtual JSString* toThisJSString(ExecState*);
99         virtual JSValue* getJSNumber();
100         void* vptr() { return *reinterpret_cast<void**>(this); }
101
102     private:
103         // Base implementation, but for non-object classes implements getPropertySlot.
104         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
105         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
106         
107         StructureID* m_structureID;
108     };
109
110     inline JSCell::JSCell(StructureID* structureID)
111         : m_structureID(structureID)
112     {
113     }
114
115     inline JSCell::~JSCell()
116     {
117     }
118
119     inline bool JSCell::isNumber() const
120     {
121         return Heap::isNumber(const_cast<JSCell*>(this));
122     }
123
124     inline bool JSCell::isObject() const
125     {
126         return m_structureID->type() == ObjectType;
127     }
128
129     inline bool JSCell::isString() const
130     {
131         return m_structureID->type() == StringType;
132     }
133
134     inline StructureID* JSCell::structureID() const
135     {
136         return m_structureID;
137     }
138
139     inline bool JSCell::marked() const
140     {
141         return Heap::isCellMarked(this);
142     }
143
144     inline void JSCell::mark()
145     {
146         return Heap::markCell(this);
147     }
148
149     ALWAYS_INLINE JSCell* JSValue::asCell()
150     {
151         ASSERT(!JSImmediate::isImmediate(this));
152         return static_cast<JSCell*>(this);
153     }
154
155     ALWAYS_INLINE const JSCell* JSValue::asCell() const
156     {
157         ASSERT(!JSImmediate::isImmediate(this));
158         return static_cast<const JSCell*>(this);
159     }
160
161
162     // --- JSValue inlines ----------------------------
163
164     inline bool JSValue::isNumber() const
165     {
166         return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
167     }
168
169     inline bool JSValue::isString() const
170     {
171         return !JSImmediate::isImmediate(this) && asCell()->isString();
172     }
173
174     inline bool JSValue::isGetterSetter() const
175     {
176         return !JSImmediate::isImmediate(this) && asCell()->isGetterSetter();
177     }
178
179     inline bool JSValue::isObject() const
180     {
181         return !JSImmediate::isImmediate(this) && asCell()->isObject();
182     }
183
184     inline bool JSValue::getNumber(double& v) const
185     {
186         if (JSImmediate::isImmediate(this)) {
187             v = JSImmediate::toDouble(this);
188             return true;
189         }
190         return asCell()->getNumber(v);
191     }
192
193     inline double JSValue::getNumber() const
194     {
195         return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
196     }
197
198     inline bool JSValue::getString(UString& s) const
199     {
200         return !JSImmediate::isImmediate(this) && asCell()->getString(s);
201     }
202
203     inline UString JSValue::getString() const
204     {
205         return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
206     }
207
208     inline JSObject* JSValue::getObject()
209     {
210         return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
211     }
212
213     inline const JSObject* JSValue::getObject() const
214     {
215         return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
216     }
217
218     inline CallType JSValue::getCallData(CallData& callData)
219     {
220         return JSImmediate::isImmediate(this) ? CallTypeNone : asCell()->getCallData(callData);
221     }
222
223     inline ConstructType JSValue::getConstructData(ConstructData& constructData)
224     {
225         return JSImmediate::isImmediate(this) ? ConstructTypeNone : asCell()->getConstructData(constructData);
226     }
227
228     ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
229     {
230         return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
231     }
232
233     ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
234     {
235         return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
236     }
237
238     inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
239     {
240         return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
241     }
242
243     inline void JSValue::mark()
244     {
245         ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
246         asCell()->mark();
247     }
248
249     inline bool JSValue::marked() const
250     {
251         return JSImmediate::isImmediate(this) || asCell()->marked();
252     }
253
254     inline JSValue* JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
255     {
256         return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
257     }
258
259     inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
260     {
261         if (JSImmediate::isImmediate(this)) {
262             number = JSImmediate::toDouble(this);
263             value = this;
264             return true;
265         }
266         return asCell()->getPrimitiveNumber(exec, number, value);
267     }
268
269     inline bool JSValue::toBoolean(ExecState* exec) const
270     {
271         return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
272     }
273
274     ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
275     {
276         return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
277     }
278
279     inline UString JSValue::toString(ExecState* exec) const
280     {
281         return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
282     }
283
284     inline JSObject* JSValue::toObject(ExecState* exec) const
285     {
286         return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
287     }
288
289     inline JSObject* JSValue::toThisObject(ExecState* exec) const
290     {
291         if (UNLIKELY(JSImmediate::isImmediate(this)))
292             return JSImmediate::toObject(this, exec);
293         return asCell()->toThisObject(exec);
294     }
295
296     inline UString JSValue::toThisString(ExecState* exec) const
297     {
298         return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toThisString(exec);
299     }
300
301     inline JSValue* JSValue::getJSNumber()
302     {
303
304         return JSImmediate::isNumber(this) ? this : (JSImmediate::isImmediate(this) ? 0 : asCell()->getJSNumber());
305     }
306
307 } // namespace JSC
308
309 #endif // JSCell_h