]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/JSCell.h
JavaScriptCore-576.tar.gz
[apple/javascriptcore.git] / runtime / JSCell.h
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
f9bf01c6 4 * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
9dae56ea
A
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
9dae56ea 26#include "Collector.h"
f9bf01c6
A
27#include "JSImmediate.h"
28#include "JSValue.h"
29#include "MarkStack.h"
30#include "Structure.h"
31#include <wtf/Noncopyable.h>
9dae56ea
A
32
33namespace JSC {
34
f9bf01c6 35 class JSCell : public NoncopyableCustomAllocated {
9dae56ea
A
36 friend class GetterSetter;
37 friend class Heap;
ba379fdc 38 friend class JIT;
9dae56ea
A
39 friend class JSNumberCell;
40 friend class JSObject;
41 friend class JSPropertyNameIterator;
42 friend class JSString;
ba379fdc
A
43 friend class JSValue;
44 friend class JSAPIValueWrapper;
f9bf01c6
A
45 friend class JSZombie;
46 friend class JSGlobalData;
9dae56ea
A
47
48 private:
49 explicit JSCell(Structure*);
50 virtual ~JSCell();
51
52 public:
f9bf01c6
A
53 static PassRefPtr<Structure> createDummyStructure()
54 {
55 return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
56 }
57
9dae56ea 58 // Querying the type.
ba379fdc 59#if USE(JSVALUE32)
9dae56ea 60 bool isNumber() const;
ba379fdc 61#endif
9dae56ea
A
62 bool isString() const;
63 bool isObject() const;
64 virtual bool isGetterSetter() const;
f9bf01c6 65 bool inherits(const ClassInfo*) const;
ba379fdc 66 virtual bool isAPIValueWrapper() const { return false; }
f9bf01c6 67 virtual bool isPropertyNameIterator() const { return false; }
9dae56ea
A
68
69 Structure* structure() const;
70
71 // Extracting the value.
f9bf01c6
A
72 bool getString(ExecState* exec, UString&) const;
73 UString getString(ExecState* exec) const; // null string if not a string
9dae56ea
A
74 JSObject* getObject(); // NULL if not an object
75 const JSObject* getObject() const; // NULL if not an object
76
77 virtual CallType getCallData(CallData&);
78 virtual ConstructType getConstructData(ConstructData&);
79
80 // Extracting integer values.
ba379fdc 81 // FIXME: remove these methods, can check isNumberCell in JSValue && then call asNumberCell::*.
9dae56ea 82 virtual bool getUInt32(uint32_t&) const;
9dae56ea
A
83
84 // Basic conversions.
f9bf01c6
A
85 virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
86 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
87 virtual bool toBoolean(ExecState*) const;
88 virtual double toNumber(ExecState*) const;
89 virtual UString toString(ExecState*) const;
90 virtual JSObject* toObject(ExecState*) const;
9dae56ea
A
91
92 // Garbage collection.
93 void* operator new(size_t, ExecState*);
94 void* operator new(size_t, JSGlobalData*);
95 void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
f9bf01c6
A
96
97 virtual void markChildren(MarkStack&);
98#if ENABLE(JSC_ZOMBIES)
99 virtual bool isZombie() const { return false; }
100#endif
9dae56ea
A
101
102 // Object operations, with the toObject operation included.
103 virtual const ClassInfo* classInfo() const;
ba379fdc
A
104 virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
105 virtual void put(ExecState*, unsigned propertyName, JSValue);
9dae56ea
A
106 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
107 virtual bool deleteProperty(ExecState*, unsigned propertyName);
108
109 virtual JSObject* toThisObject(ExecState*) const;
110 virtual UString toThisString(ExecState*) const;
111 virtual JSString* toThisJSString(ExecState*);
ba379fdc 112 virtual JSValue getJSNumber();
9dae56ea 113 void* vptr() { return *reinterpret_cast<void**>(this); }
f9bf01c6
A
114 void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; }
115
116 protected:
117 static const unsigned AnonymousSlotCount = 0;
9dae56ea
A
118
119 private:
120 // Base implementation; for non-object classes implements getPropertySlot.
121 bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
122 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
123 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
124
125 Structure* m_structure;
126 };
127
9dae56ea
A
128 inline JSCell::JSCell(Structure* structure)
129 : m_structure(structure)
130 {
131 }
132
133 inline JSCell::~JSCell()
134 {
135 }
136
ba379fdc 137#if USE(JSVALUE32)
9dae56ea
A
138 inline bool JSCell::isNumber() const
139 {
f9bf01c6 140 return m_structure->typeInfo().type() == NumberType;
9dae56ea 141 }
ba379fdc 142#endif
9dae56ea
A
143
144 inline bool JSCell::isObject() const
145 {
146 return m_structure->typeInfo().type() == ObjectType;
147 }
148
149 inline bool JSCell::isString() const
150 {
151 return m_structure->typeInfo().type() == StringType;
152 }
153
154 inline Structure* JSCell::structure() const
155 {
156 return m_structure;
157 }
158
f9bf01c6 159 inline void JSCell::markChildren(MarkStack&)
9dae56ea 160 {
9dae56ea
A
161 }
162
f9bf01c6 163 inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
9dae56ea 164 {
f9bf01c6 165 return globalData->heap.allocate(size);
9dae56ea
A
166 }
167
f9bf01c6 168 inline void* JSCell::operator new(size_t size, ExecState* exec)
9dae56ea 169 {
f9bf01c6 170 return exec->heap()->allocate(size);
9dae56ea
A
171 }
172
173 // --- JSValue inlines ----------------------------
174
ba379fdc 175 inline bool JSValue::isString() const
9dae56ea 176 {
ba379fdc 177 return isCell() && asCell()->isString();
9dae56ea
A
178 }
179
ba379fdc 180 inline bool JSValue::isGetterSetter() const
9dae56ea 181 {
ba379fdc 182 return isCell() && asCell()->isGetterSetter();
9dae56ea
A
183 }
184
ba379fdc 185 inline bool JSValue::isObject() const
9dae56ea 186 {
ba379fdc 187 return isCell() && asCell()->isObject();
9dae56ea
A
188 }
189
f9bf01c6 190 inline bool JSValue::getString(ExecState* exec, UString& s) const
9dae56ea 191 {
f9bf01c6 192 return isCell() && asCell()->getString(exec, s);
9dae56ea
A
193 }
194
f9bf01c6 195 inline UString JSValue::getString(ExecState* exec) const
9dae56ea 196 {
f9bf01c6 197 return isCell() ? asCell()->getString(exec) : UString();
9dae56ea
A
198 }
199
ba379fdc 200 inline JSObject* JSValue::getObject() const
9dae56ea 201 {
ba379fdc 202 return isCell() ? asCell()->getObject() : 0;
9dae56ea
A
203 }
204
ba379fdc 205 inline CallType JSValue::getCallData(CallData& callData)
9dae56ea 206 {
ba379fdc 207 return isCell() ? asCell()->getCallData(callData) : CallTypeNone;
9dae56ea
A
208 }
209
ba379fdc 210 inline ConstructType JSValue::getConstructData(ConstructData& constructData)
9dae56ea 211 {
ba379fdc 212 return isCell() ? asCell()->getConstructData(constructData) : ConstructTypeNone;
9dae56ea
A
213 }
214
ba379fdc 215 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
9dae56ea 216 {
ba379fdc
A
217 if (isInt32()) {
218 int32_t i = asInt32();
219 v = static_cast<uint32_t>(i);
220 return i >= 0;
221 }
222 if (isDouble()) {
223 double d = asDouble();
224 v = static_cast<uint32_t>(d);
225 return v == d;
226 }
227 return false;
9dae56ea
A
228 }
229
ba379fdc
A
230#if !USE(JSVALUE32_64)
231 ALWAYS_INLINE JSCell* JSValue::asCell() const
9dae56ea 232 {
ba379fdc
A
233 ASSERT(isCell());
234 return m_ptr;
9dae56ea 235 }
ba379fdc 236#endif // !USE(JSVALUE32_64)
9dae56ea 237
ba379fdc 238 inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
9dae56ea 239 {
ba379fdc 240 return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
9dae56ea
A
241 }
242
ba379fdc 243 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
9dae56ea 244 {
ba379fdc
A
245 if (isInt32()) {
246 number = asInt32();
247 value = *this;
248 return true;
249 }
250 if (isDouble()) {
251 number = asDouble();
252 value = *this;
253 return true;
254 }
255 if (isCell())
256 return asCell()->getPrimitiveNumber(exec, number, value);
257 if (isTrue()) {
258 number = 1.0;
259 value = *this;
260 return true;
261 }
262 if (isFalse() || isNull()) {
263 number = 0.0;
264 value = *this;
9dae56ea
A
265 return true;
266 }
ba379fdc
A
267 ASSERT(isUndefined());
268 number = nonInlineNaN();
269 value = *this;
270 return true;
9dae56ea
A
271 }
272
ba379fdc 273 inline bool JSValue::toBoolean(ExecState* exec) const
9dae56ea 274 {
ba379fdc
A
275 if (isInt32())
276 return asInt32() != 0;
277 if (isDouble())
278 return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
279 if (isCell())
280 return asCell()->toBoolean(exec);
281 return isTrue(); // false, null, and undefined all convert to false.
9dae56ea
A
282 }
283
ba379fdc 284 ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
9dae56ea 285 {
ba379fdc
A
286 if (isInt32())
287 return asInt32();
288 if (isDouble())
289 return asDouble();
290 if (isCell())
291 return asCell()->toNumber(exec);
292 if (isTrue())
293 return 1.0;
294 return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
9dae56ea
A
295 }
296
ba379fdc 297 inline bool JSValue::needsThisConversion() const
9dae56ea 298 {
ba379fdc
A
299 if (UNLIKELY(!isCell()))
300 return true;
301 return asCell()->structure()->typeInfo().needsThisConversion();
9dae56ea
A
302 }
303
ba379fdc 304 inline UString JSValue::toThisString(ExecState* exec) const
9dae56ea 305 {
ba379fdc 306 return isCell() ? asCell()->toThisString(exec) : toString(exec);
9dae56ea
A
307 }
308
ba379fdc 309 inline JSValue JSValue::getJSNumber()
9dae56ea 310 {
ba379fdc
A
311 if (isInt32() || isDouble())
312 return *this;
313 if (isCell())
314 return asCell()->getJSNumber();
315 return JSValue();
9dae56ea
A
316 }
317
ba379fdc 318 inline JSObject* JSValue::toObject(ExecState* exec) const
9dae56ea 319 {
ba379fdc 320 return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec);
9dae56ea
A
321 }
322
ba379fdc 323 inline JSObject* JSValue::toThisObject(ExecState* exec) const
9dae56ea 324 {
ba379fdc 325 return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
9dae56ea
A
326 }
327
f9bf01c6
A
328 ALWAYS_INLINE void MarkStack::append(JSCell* cell)
329 {
330 ASSERT(!m_isCheckingForDefaultMarkViolation);
331 ASSERT(cell);
332 if (Heap::isCellMarked(cell))
333 return;
334 Heap::markCell(cell);
335 if (cell->structure()->typeInfo().type() >= CompoundType)
336 m_values.append(cell);
337 }
338
339 ALWAYS_INLINE void MarkStack::append(JSValue value)
340 {
341 ASSERT(value);
342 if (value.isCell())
343 append(value.asCell());
344 }
345
346 inline Heap* Heap::heap(JSValue v)
347 {
348 if (!v.isCell())
349 return 0;
350 return heap(v.asCell());
351 }
352
353 inline Heap* Heap::heap(JSCell* c)
354 {
355 return cellBlock(c)->heap;
356 }
357
358#if ENABLE(JSC_ZOMBIES)
359 inline bool JSValue::isZombie() const
360 {
361 return isCell() && asCell() && asCell()->isZombie();
362 }
363#endif
9dae56ea
A
364} // namespace JSC
365
366#endif // JSCell_h