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