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