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 JSNumberCell_h
24#define JSNumberCell_h
25
26#include "CallFrame.h"
27#include "JSCell.h"
28#include "JSImmediate.h"
29#include "Collector.h"
30#include "UString.h"
31#include <stddef.h> // for size_t
32
33namespace JSC {
34
35    extern const double NaN;
36    extern const double Inf;
37
38#if USE(JSVALUE32)
39    JSValue jsNumberCell(ExecState*, double);
40
41    class Identifier;
42    class JSCell;
43    class JSObject;
44    class JSString;
45    class PropertySlot;
46
47    struct ClassInfo;
48    struct Instruction;
49
50    class JSNumberCell : public JSCell {
51        friend class JIT;
52        friend JSValue jsNumberCell(JSGlobalData*, double);
53        friend JSValue jsNumberCell(ExecState*, double);
54
55    public:
56        double value() const { return m_value; }
57
58        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
59        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
60        virtual bool toBoolean(ExecState*) const;
61        virtual double toNumber(ExecState*) const;
62        virtual UString toString(ExecState*) const;
63        virtual JSObject* toObject(ExecState*) const;
64
65        virtual UString toThisString(ExecState*) const;
66        virtual JSObject* toThisObject(ExecState*) const;
67        virtual JSValue getJSNumber();
68
69        void* operator new(size_t size, ExecState* exec)
70        {
71            return exec->heap()->allocateNumber(size);
72        }
73
74        void* operator new(size_t size, JSGlobalData* globalData)
75        {
76            return globalData->heap.allocateNumber(size);
77        }
78
79        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); }
80
81    private:
82        JSNumberCell(JSGlobalData* globalData, double value)
83            : JSCell(globalData->numberStructure.get())
84            , m_value(value)
85        {
86        }
87
88        JSNumberCell(ExecState* exec, double value)
89            : JSCell(exec->globalData().numberStructure.get())
90            , m_value(value)
91        {
92        }
93
94        virtual bool getUInt32(uint32_t&) const;
95
96        double m_value;
97    };
98
99    JSValue jsNumberCell(JSGlobalData*, double);
100
101    inline bool isNumberCell(JSValue v)
102    {
103        return v.isCell() && v.asCell()->isNumber();
104    }
105
106    inline JSNumberCell* asNumberCell(JSValue v)
107    {
108        ASSERT(isNumberCell(v));
109        return static_cast<JSNumberCell*>(v.asCell());
110    }
111
112    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState* exec, double d)
113    {
114        *this = jsNumberCell(exec, d);
115    }
116
117    inline JSValue::JSValue(ExecState* exec, double d)
118    {
119        JSValue v = JSImmediate::from(d);
120        *this = v ? v : jsNumberCell(exec, d);
121    }
122
123    inline JSValue::JSValue(ExecState* exec, int i)
124    {
125        JSValue v = JSImmediate::from(i);
126        *this = v ? v : jsNumberCell(exec, i);
127    }
128
129    inline JSValue::JSValue(ExecState* exec, unsigned i)
130    {
131        JSValue v = JSImmediate::from(i);
132        *this = v ? v : jsNumberCell(exec, i);
133    }
134
135    inline JSValue::JSValue(ExecState* exec, long i)
136    {
137        JSValue v = JSImmediate::from(i);
138        *this = v ? v : jsNumberCell(exec, i);
139    }
140
141    inline JSValue::JSValue(ExecState* exec, unsigned long i)
142    {
143        JSValue v = JSImmediate::from(i);
144        *this = v ? v : jsNumberCell(exec, i);
145    }
146
147    inline JSValue::JSValue(ExecState* exec, long long i)
148    {
149        JSValue v = JSImmediate::from(i);
150        *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
151    }
152
153    inline JSValue::JSValue(ExecState* exec, unsigned long long i)
154    {
155        JSValue v = JSImmediate::from(i);
156        *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
157    }
158
159    inline JSValue::JSValue(JSGlobalData* globalData, double d)
160    {
161        JSValue v = JSImmediate::from(d);
162        *this = v ? v : jsNumberCell(globalData, d);
163    }
164
165    inline JSValue::JSValue(JSGlobalData* globalData, int i)
166    {
167        JSValue v = JSImmediate::from(i);
168        *this = v ? v : jsNumberCell(globalData, i);
169    }
170
171    inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
172    {
173        JSValue v = JSImmediate::from(i);
174        *this = v ? v : jsNumberCell(globalData, i);
175    }
176
177    inline bool JSValue::isDouble() const
178    {
179        return isNumberCell(asValue());
180    }
181
182    inline double JSValue::asDouble() const
183    {
184        return asNumberCell(asValue())->value();
185    }
186
187    inline bool JSValue::isNumber() const
188    {
189        return JSImmediate::isNumber(asValue()) || isDouble();
190    }
191
192    inline double JSValue::uncheckedGetNumber() const
193    {
194        ASSERT(isNumber());
195        return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asDouble();
196    }
197
198#endif // USE(JSVALUE32)
199
200#if USE(JSVALUE64)
201    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
202    {
203        *this = JSImmediate::fromNumberOutsideIntegerRange(d);
204    }
205
206    inline JSValue::JSValue(ExecState*, double d)
207    {
208        JSValue v = JSImmediate::from(d);
209        ASSERT(v);
210        *this = v;
211    }
212
213    inline JSValue::JSValue(ExecState*, int i)
214    {
215        JSValue v = JSImmediate::from(i);
216        ASSERT(v);
217        *this = v;
218    }
219
220    inline JSValue::JSValue(ExecState*, unsigned i)
221    {
222        JSValue v = JSImmediate::from(i);
223        ASSERT(v);
224        *this = v;
225    }
226
227    inline JSValue::JSValue(ExecState*, long i)
228    {
229        JSValue v = JSImmediate::from(i);
230        ASSERT(v);
231        *this = v;
232    }
233
234    inline JSValue::JSValue(ExecState*, unsigned long i)
235    {
236        JSValue v = JSImmediate::from(i);
237        ASSERT(v);
238        *this = v;
239    }
240
241    inline JSValue::JSValue(ExecState*, long long i)
242    {
243        JSValue v = JSImmediate::from(static_cast<double>(i));
244        ASSERT(v);
245        *this = v;
246    }
247
248    inline JSValue::JSValue(ExecState*, unsigned long long i)
249    {
250        JSValue v = JSImmediate::from(static_cast<double>(i));
251        ASSERT(v);
252        *this = v;
253    }
254
255    inline JSValue::JSValue(JSGlobalData*, double d)
256    {
257        JSValue v = JSImmediate::from(d);
258        ASSERT(v);
259        *this = v;
260    }
261
262    inline JSValue::JSValue(JSGlobalData*, int i)
263    {
264        JSValue v = JSImmediate::from(i);
265        ASSERT(v);
266        *this = v;
267    }
268
269    inline JSValue::JSValue(JSGlobalData*, unsigned i)
270    {
271        JSValue v = JSImmediate::from(i);
272        ASSERT(v);
273        *this = v;
274    }
275
276    inline bool JSValue::isDouble() const
277    {
278        return JSImmediate::isDouble(asValue());
279    }
280
281    inline double JSValue::asDouble() const
282    {
283        return JSImmediate::doubleValue(asValue());
284    }
285
286    inline bool JSValue::isNumber() const
287    {
288        return JSImmediate::isNumber(asValue());
289    }
290
291    inline double JSValue::uncheckedGetNumber() const
292    {
293        ASSERT(isNumber());
294        return JSImmediate::toDouble(asValue());
295    }
296
297#endif // USE(JSVALUE64)
298
299#if USE(JSVALUE32) || USE(JSVALUE64)
300
301    inline JSValue::JSValue(ExecState*, char i)
302    {
303        ASSERT(JSImmediate::from(i));
304        *this = JSImmediate::from(i);
305    }
306
307    inline JSValue::JSValue(ExecState*, unsigned char i)
308    {
309        ASSERT(JSImmediate::from(i));
310        *this = JSImmediate::from(i);
311    }
312
313    inline JSValue::JSValue(ExecState*, short i)
314    {
315        ASSERT(JSImmediate::from(i));
316        *this = JSImmediate::from(i);
317    }
318
319    inline JSValue::JSValue(ExecState*, unsigned short i)
320    {
321        ASSERT(JSImmediate::from(i));
322        *this = JSImmediate::from(i);
323    }
324
325    inline JSValue jsNaN(ExecState* exec)
326    {
327        return jsNumber(exec, NaN);
328    }
329
330    inline JSValue jsNaN(JSGlobalData* globalData)
331    {
332        return jsNumber(globalData, NaN);
333    }
334
335    // --- JSValue inlines ----------------------------
336
337    ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
338    {
339        return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
340    }
341
342    inline bool JSValue::getNumber(double &result) const
343    {
344        if (isInt32())
345            result = asInt32();
346        else if (LIKELY(isDouble()))
347            result = asDouble();
348        else {
349            ASSERT(!isNumber());
350            return false;
351        }
352        return true;
353    }
354
355#endif // USE(JSVALUE32) || USE(JSVALUE64)
356
357} // namespace JSC
358
359#endif // JSNumberCell_h
360