]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/JSCell.h
JavaScriptCore-1097.13.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
14957cd0
A
26#include "CallData.h"
27#include "CallFrame.h"
28#include "ConstructData.h"
29#include "Heap.h"
30#include "JSLock.h"
31#include "JSValueInlineMethods.h"
6fe7ccc8 32#include "SlotVisitor.h"
14957cd0 33#include "WriteBarrier.h"
f9bf01c6 34#include <wtf/Noncopyable.h>
9dae56ea
A
35
36namespace JSC {
37
14957cd0 38 class JSGlobalObject;
6fe7ccc8
A
39 class LLIntOffsetsExtractor;
40 class PropertyDescriptor;
41 class PropertyNameArray;
14957cd0
A
42 class Structure;
43
6fe7ccc8
A
44 enum EnumerationMode {
45 ExcludeDontEnumProperties,
46 IncludeDontEnumProperties
47 };
14957cd0 48
6fe7ccc8
A
49 enum TypedArrayType {
50 TypedArrayNone,
51 TypedArrayInt8,
52 TypedArrayInt16,
53 TypedArrayInt32,
54 TypedArrayUint8,
55 TypedArrayUint8Clamped,
56 TypedArrayUint16,
57 TypedArrayUint32,
58 TypedArrayFloat32,
59 TypedArrayFloat64
14957cd0
A
60 };
61
14957cd0 62 class JSCell {
ba379fdc 63 friend class JSValue;
14957cd0 64 friend class MarkedBlock;
6fe7ccc8
A
65 template<typename T> friend void* allocateCell(Heap&);
66
67 public:
14957cd0 68 enum CreatingEarlyCellTag { CreatingEarlyCell };
6fe7ccc8 69 JSCell(CreatingEarlyCellTag);
14957cd0
A
70
71 protected:
14957cd0 72 JSCell(JSGlobalData&, Structure*);
6fe7ccc8 73 JS_EXPORT_PRIVATE static void destroy(JSCell*);
9dae56ea
A
74
75 public:
76 // Querying the type.
9dae56ea
A
77 bool isString() const;
78 bool isObject() const;
6fe7ccc8 79 bool isGetterSetter() const;
f9bf01c6 80 bool inherits(const ClassInfo*) const;
6fe7ccc8 81 bool isAPIValueWrapper() const;
9dae56ea
A
82
83 Structure* structure() const;
6fe7ccc8
A
84 void setStructure(JSGlobalData&, Structure*);
85 void clearStructure() { m_structure.clear(); }
9dae56ea
A
86
87 // Extracting the value.
6fe7ccc8
A
88 JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const;
89 JS_EXPORT_PRIVATE UString getString(ExecState* exec) const; // null string if not a string
90 JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
9dae56ea
A
91 const JSObject* getObject() const; // NULL if not an object
92
6fe7ccc8
A
93 JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
94 JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
9dae56ea
A
95
96 // Basic conversions.
6fe7ccc8
A
97 JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
98 bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
99 bool toBoolean(ExecState*) const;
100 JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
101 JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
102
103 static void visitChildren(JSCell*, SlotVisitor&);
9dae56ea
A
104
105 // Object operations, with the toObject operation included.
14957cd0 106 const ClassInfo* classInfo() const;
6fe7ccc8
A
107 const ClassInfo* validatedClassInfo() const;
108 const MethodTable* methodTable() const;
109 static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
110 static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
111
112 static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
113 static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
114
115 static JSObject* toThisObject(JSCell*, ExecState*);
9dae56ea 116
6fe7ccc8
A
117 void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
118 bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
f9bf01c6 119
4e4e5a6f
A
120 // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and
121 // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always
122 // call this function, not its slower virtual counterpart. (For integer
123 // property names, we want a similar interface with appropriate optimizations.)
124 bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
6fe7ccc8 125 JSValue fastGetOwnProperty(ExecState*, const UString&);
4e4e5a6f 126
14957cd0
A
127 static ptrdiff_t structureOffset()
128 {
129 return OBJECT_OFFSETOF(JSCell, m_structure);
130 }
131
6fe7ccc8
A
132 static ptrdiff_t classInfoOffset()
133 {
134 return OBJECT_OFFSETOF(JSCell, m_classInfo);
135 }
136
137 void* structureAddress()
138 {
139 return &m_structure;
140 }
141
14957cd0
A
142#if ENABLE(GC_VALIDATION)
143 Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
144#endif
145
6fe7ccc8 146 static const TypedArrayType TypedArrayStorageType = TypedArrayNone;
f9bf01c6 147 protected:
9dae56ea 148
6fe7ccc8
A
149 void finishCreation(JSGlobalData&);
150 void finishCreation(JSGlobalData&, Structure*, CreatingEarlyCellTag);
151
9dae56ea 152 // Base implementation; for non-object classes implements getPropertySlot.
6fe7ccc8
A
153 static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
154 static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
155
156 // Dummy implementations of override-able static functions for classes to put in their MethodTable
157 static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
158 static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
159 static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
160 static UString className(const JSObject*);
161 static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
162 static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
163 static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
164 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
165
166 private:
167 friend class LLIntOffsetsExtractor;
9dae56ea 168
6fe7ccc8 169 const ClassInfo* m_classInfo;
14957cd0 170 WriteBarrier<Structure> m_structure;
9dae56ea
A
171 };
172
6fe7ccc8 173 inline JSCell::JSCell(CreatingEarlyCellTag)
9dae56ea
A
174 {
175 }
176
6fe7ccc8 177 inline void JSCell::finishCreation(JSGlobalData& globalData)
9dae56ea 178 {
14957cd0 179#if ENABLE(GC_VALIDATION)
6fe7ccc8
A
180 ASSERT(globalData.isInitializingObject());
181 globalData.setInitializingObjectClass(0);
182#else
183 UNUSED_PARAM(globalData);
ba379fdc 184#endif
6fe7ccc8 185 ASSERT(m_structure);
9dae56ea
A
186 }
187
6fe7ccc8 188 inline Structure* JSCell::structure() const
9dae56ea 189 {
6fe7ccc8 190 return m_structure.get();
9dae56ea
A
191 }
192
6fe7ccc8 193 inline const ClassInfo* JSCell::classInfo() const
9dae56ea 194 {
6fe7ccc8 195 return m_classInfo;
9dae56ea
A
196 }
197
6fe7ccc8 198 inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
9dae56ea 199 {
6fe7ccc8 200 visitor.append(&cell->m_structure);
9dae56ea
A
201 }
202
203 // --- JSValue inlines ----------------------------
204
ba379fdc 205 inline bool JSValue::isString() const
9dae56ea 206 {
ba379fdc 207 return isCell() && asCell()->isString();
9dae56ea
A
208 }
209
6fe7ccc8
A
210 inline bool JSValue::isPrimitive() const
211 {
212 return !isCell() || asCell()->isString();
213 }
214
ba379fdc 215 inline bool JSValue::isGetterSetter() const
9dae56ea 216 {
ba379fdc 217 return isCell() && asCell()->isGetterSetter();
9dae56ea
A
218 }
219
ba379fdc 220 inline bool JSValue::isObject() const
9dae56ea 221 {
ba379fdc 222 return isCell() && asCell()->isObject();
9dae56ea
A
223 }
224
f9bf01c6 225 inline bool JSValue::getString(ExecState* exec, UString& s) const
9dae56ea 226 {
f9bf01c6 227 return isCell() && asCell()->getString(exec, s);
9dae56ea
A
228 }
229
f9bf01c6 230 inline UString JSValue::getString(ExecState* exec) const
9dae56ea 231 {
f9bf01c6 232 return isCell() ? asCell()->getString(exec) : UString();
9dae56ea
A
233 }
234
14957cd0
A
235 template <typename Base> UString HandleConverter<Base, Unknown>::getString(ExecState* exec) const
236 {
237 return jsValue().getString(exec);
238 }
239
ba379fdc 240 inline JSObject* JSValue::getObject() const
9dae56ea 241 {
ba379fdc 242 return isCell() ? asCell()->getObject() : 0;
9dae56ea
A
243 }
244
ba379fdc 245 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
9dae56ea 246 {
ba379fdc
A
247 if (isInt32()) {
248 int32_t i = asInt32();
249 v = static_cast<uint32_t>(i);
250 return i >= 0;
251 }
252 if (isDouble()) {
253 double d = asDouble();
254 v = static_cast<uint32_t>(d);
255 return v == d;
256 }
257 return false;
9dae56ea
A
258 }
259
ba379fdc 260 inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
9dae56ea 261 {
ba379fdc 262 return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
9dae56ea
A
263 }
264
ba379fdc 265 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
9dae56ea 266 {
ba379fdc
A
267 if (isInt32()) {
268 number = asInt32();
269 value = *this;
270 return true;
271 }
272 if (isDouble()) {
273 number = asDouble();
274 value = *this;
275 return true;
276 }
277 if (isCell())
278 return asCell()->getPrimitiveNumber(exec, number, value);
279 if (isTrue()) {
280 number = 1.0;
281 value = *this;
282 return true;
283 }
284 if (isFalse() || isNull()) {
285 number = 0.0;
286 value = *this;
9dae56ea
A
287 return true;
288 }
ba379fdc 289 ASSERT(isUndefined());
6fe7ccc8 290 number = std::numeric_limits<double>::quiet_NaN();
ba379fdc
A
291 value = *this;
292 return true;
9dae56ea
A
293 }
294
ba379fdc 295 ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
9dae56ea 296 {
ba379fdc
A
297 if (isInt32())
298 return asInt32();
299 if (isDouble())
300 return asDouble();
6fe7ccc8 301 return toNumberSlowCase(exec);
9dae56ea
A
302 }
303
ba379fdc 304 inline JSObject* JSValue::toObject(ExecState* exec) const
9dae56ea 305 {
14957cd0 306 return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
9dae56ea
A
307 }
308
14957cd0 309 inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
9dae56ea 310 {
14957cd0 311 return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
9dae56ea
A
312 }
313
6fe7ccc8
A
314#if COMPILER(CLANG)
315 template<class T>
316 struct NeedsDestructor {
317 static const bool value = !__has_trivial_destructor(T);
318 };
319#else
320 // Write manual specializations for this struct template if you care about non-clang compilers.
321 template<class T>
322 struct NeedsDestructor {
323 static const bool value = true;
324 };
f9bf01c6 325#endif
14957cd0 326
6fe7ccc8
A
327 template<typename T>
328 void* allocateCell(Heap& heap)
14957cd0 329 {
6fe7ccc8
A
330#if ENABLE(GC_VALIDATION)
331 ASSERT(!heap.globalData()->isInitializingObject());
332 heap.globalData()->setInitializingObjectClass(&T::s_info);
333#endif
334 JSCell* result = 0;
335 if (NeedsDestructor<T>::value)
336 result = static_cast<JSCell*>(heap.allocateWithDestructor(sizeof(T)));
337 else {
338 ASSERT(T::s_info.methodTable.destroy == JSCell::destroy);
339 result = static_cast<JSCell*>(heap.allocateWithoutDestructor(sizeof(T)));
14957cd0 340 }
6fe7ccc8
A
341 result->clearStructure();
342 return result;
14957cd0
A
343 }
344
6fe7ccc8 345 inline bool isZapped(const JSCell* cell)
14957cd0 346 {
6fe7ccc8 347 return cell->isZapped();
14957cd0
A
348 }
349
6fe7ccc8
A
350 template<typename To, typename From>
351 inline To jsCast(From* from)
14957cd0 352 {
6fe7ccc8
A
353 ASSERT(!from || from->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
354 return static_cast<To>(from);
14957cd0 355 }
6fe7ccc8
A
356
357 template<typename To>
358 inline To jsCast(JSValue from)
14957cd0 359 {
6fe7ccc8
A
360 ASSERT(from.isCell() && from.asCell()->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
361 return static_cast<To>(from.asCell());
14957cd0
A
362 }
363
6fe7ccc8
A
364 template<typename To, typename From>
365 inline To jsDynamicCast(From* from)
14957cd0 366 {
6fe7ccc8 367 return from->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from) : 0;
14957cd0
A
368 }
369
6fe7ccc8
A
370 template<typename To>
371 inline To jsDynamicCast(JSValue from)
14957cd0 372 {
6fe7ccc8 373 return from.isCell() && from.asCell()->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from.asCell()) : 0;
14957cd0
A
374 }
375
9dae56ea
A
376} // namespace JSC
377
378#endif // JSCell_h