Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org)
      3  *  Copyright (C) 2001 Peter Kelly (pmk (at) 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 
     33 namespace 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