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