| 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 |  | 
| 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)); } | 
| 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(value: 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(d: 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(d: 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(v: asValue()); | 
| 279 |     } | 
| 280 |  | 
| 281 |     inline double JSValue::asDouble() const | 
| 282 |     { | 
| 283 |         return JSImmediate::doubleValue(v: asValue()); | 
| 284 |     } | 
| 285 |  | 
| 286 |     inline bool JSValue::isNumber() const | 
| 287 |     { | 
| 288 |         return JSImmediate::isNumber(v: asValue()); | 
| 289 |     } | 
| 290 |  | 
| 291 |     inline double JSValue::uncheckedGetNumber() const | 
| 292 |     { | 
| 293 |         ASSERT(isNumber()); | 
| 294 |         return JSImmediate::toDouble(v: 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, d: NaN); | 
| 328 |     } | 
| 329 |  | 
| 330 |     inline JSValue jsNaN(JSGlobalData* globalData) | 
| 331 |     { | 
| 332 |         return jsNumber(globalData, d: NaN); | 
| 333 |     } | 
| 334 |  | 
| 335 |     // --- JSValue inlines ---------------------------- | 
| 336 |  | 
| 337 |     ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const | 
| 338 |     { | 
| 339 |         return isNumber() ? asValue() : jsNumber(exec, d: 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 |  |