• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Collector.h"
27 #include "JSImmediate.h"
28 #include "JSValue.h"
29 #include "MarkStack.h"
30 #include "Structure.h"
31 #include <wtf/Noncopyable.h>
32 
33 namespace JSC {
34 
35     class JSCell : public NoncopyableCustomAllocated {
36         friend class GetterSetter;
37         friend class Heap;
38         friend class JIT;
39         friend class JSNumberCell;
40         friend class JSObject;
41         friend class JSPropertyNameIterator;
42         friend class JSString;
43         friend class JSValue;
44         friend class JSAPIValueWrapper;
45         friend class JSZombie;
46         friend class JSGlobalData;
47 
48     private:
49         explicit JSCell(Structure*);
50         virtual ~JSCell();
51 
52     public:
createDummyStructure()53         static PassRefPtr<Structure> createDummyStructure()
54         {
55             return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
56         }
57 
58         // Querying the type.
59 #if USE(JSVALUE32)
60         bool isNumber() const;
61 #endif
62         bool isString() const;
63         bool isObject() const;
64         virtual bool isGetterSetter() const;
65         bool inherits(const ClassInfo*) const;
isAPIValueWrapper()66         virtual bool isAPIValueWrapper() const { return false; }
isPropertyNameIterator()67         virtual bool isPropertyNameIterator() const { return false; }
68 
69         Structure* structure() const;
70 
71         // Extracting the value.
72         bool getString(ExecState* exec, UString&) const;
73         UString getString(ExecState* exec) const; // null string if not a string
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.
81         // FIXME: remove these methods, can check isNumberCell in JSValue && then call asNumberCell::*.
82         virtual bool getUInt32(uint32_t&) const;
83 
84         // Basic conversions.
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;
91 
92         // Garbage collection.
93         void* operator new(size_t, ExecState*);
94         void* operator new(size_t, JSGlobalData*);
new(size_t,void * placementNewDestination)95         void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
96 
97         virtual void markChildren(MarkStack&);
98 #if ENABLE(JSC_ZOMBIES)
isZombie()99         virtual bool isZombie() const { return false; }
100 #endif
101 
102         // Object operations, with the toObject operation included.
103         virtual const ClassInfo* classInfo() const;
104         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
105         virtual void put(ExecState*, unsigned propertyName, JSValue);
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*);
112         virtual JSValue getJSNumber();
vptr()113         void* vptr() { return *reinterpret_cast<void**>(this); }
setVPtr(void * vptr)114         void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; }
115 
116     protected:
117         static const unsigned AnonymousSlotCount = 0;
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 
JSCell(Structure * structure)128     inline JSCell::JSCell(Structure* structure)
129         : m_structure(structure)
130     {
131     }
132 
~JSCell()133     inline JSCell::~JSCell()
134     {
135     }
136 
137 #if USE(JSVALUE32)
isNumber()138     inline bool JSCell::isNumber() const
139     {
140         return m_structure->typeInfo().type() == NumberType;
141     }
142 #endif
143 
isObject()144     inline bool JSCell::isObject() const
145     {
146         return m_structure->typeInfo().type() == ObjectType;
147     }
148 
isString()149     inline bool JSCell::isString() const
150     {
151         return m_structure->typeInfo().type() == StringType;
152     }
153 
structure()154     inline Structure* JSCell::structure() const
155     {
156         return m_structure;
157     }
158 
markChildren(MarkStack &)159     inline void JSCell::markChildren(MarkStack&)
160     {
161     }
162 
new(size_t size,JSGlobalData * globalData)163     inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
164     {
165         return globalData->heap.allocate(size);
166     }
167 
new(size_t size,ExecState * exec)168     inline void* JSCell::operator new(size_t size, ExecState* exec)
169     {
170         return exec->heap()->allocate(size);
171     }
172 
173     // --- JSValue inlines ----------------------------
174 
isString()175     inline bool JSValue::isString() const
176     {
177         return isCell() && asCell()->isString();
178     }
179 
isGetterSetter()180     inline bool JSValue::isGetterSetter() const
181     {
182         return isCell() && asCell()->isGetterSetter();
183     }
184 
isObject()185     inline bool JSValue::isObject() const
186     {
187         return isCell() && asCell()->isObject();
188     }
189 
getString(ExecState * exec,UString & s)190     inline bool JSValue::getString(ExecState* exec, UString& s) const
191     {
192         return isCell() && asCell()->getString(exec, s);
193     }
194 
getString(ExecState * exec)195     inline UString JSValue::getString(ExecState* exec) const
196     {
197         return isCell() ? asCell()->getString(exec) : UString();
198     }
199 
getObject()200     inline JSObject* JSValue::getObject() const
201     {
202         return isCell() ? asCell()->getObject() : 0;
203     }
204 
getCallData(CallData & callData)205     inline CallType JSValue::getCallData(CallData& callData)
206     {
207         return isCell() ? asCell()->getCallData(callData) : CallTypeNone;
208     }
209 
getConstructData(ConstructData & constructData)210     inline ConstructType JSValue::getConstructData(ConstructData& constructData)
211     {
212         return isCell() ? asCell()->getConstructData(constructData) : ConstructTypeNone;
213     }
214 
getUInt32(uint32_t & v)215     ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
216     {
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;
228     }
229 
230 #if !USE(JSVALUE32_64)
asCell()231     ALWAYS_INLINE JSCell* JSValue::asCell() const
232     {
233         ASSERT(isCell());
234         return m_ptr;
235     }
236 #endif // !USE(JSVALUE32_64)
237 
toPrimitive(ExecState * exec,PreferredPrimitiveType preferredType)238     inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
239     {
240         return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
241     }
242 
getPrimitiveNumber(ExecState * exec,double & number,JSValue & value)243     inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
244     {
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;
265             return true;
266         }
267         ASSERT(isUndefined());
268         number = nonInlineNaN();
269         value = *this;
270         return true;
271     }
272 
toBoolean(ExecState * exec)273     inline bool JSValue::toBoolean(ExecState* exec) const
274     {
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.
282     }
283 
toNumber(ExecState * exec)284     ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
285     {
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.
295     }
296 
needsThisConversion()297     inline bool JSValue::needsThisConversion() const
298     {
299         if (UNLIKELY(!isCell()))
300             return true;
301         return asCell()->structure()->typeInfo().needsThisConversion();
302     }
303 
toThisString(ExecState * exec)304     inline UString JSValue::toThisString(ExecState* exec) const
305     {
306         return isCell() ? asCell()->toThisString(exec) : toString(exec);
307     }
308 
getJSNumber()309     inline JSValue JSValue::getJSNumber()
310     {
311         if (isInt32() || isDouble())
312             return *this;
313         if (isCell())
314             return asCell()->getJSNumber();
315         return JSValue();
316     }
317 
toObject(ExecState * exec)318     inline JSObject* JSValue::toObject(ExecState* exec) const
319     {
320         return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec);
321     }
322 
toThisObject(ExecState * exec)323     inline JSObject* JSValue::toThisObject(ExecState* exec) const
324     {
325         return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
326     }
327 
append(JSCell * cell)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 
append(JSValue value)339     ALWAYS_INLINE void MarkStack::append(JSValue value)
340     {
341         ASSERT(value);
342         if (value.isCell())
343             append(value.asCell());
344     }
345 
heap(JSValue v)346     inline Heap* Heap::heap(JSValue v)
347     {
348         if (!v.isCell())
349             return 0;
350         return heap(v.asCell());
351     }
352 
heap(JSCell * c)353     inline Heap* Heap::heap(JSCell* c)
354     {
355         return cellBlock(c)->heap;
356     }
357 
358 #if ENABLE(JSC_ZOMBIES)
isZombie()359     inline bool JSValue::isZombie() const
360     {
361         return isCell() && asCell() && asCell()->isZombie();
362     }
363 #endif
364 } // namespace JSC
365 
366 #endif // JSCell_h
367