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