File indexing completed on 2024-05-12 15:43:24
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 0004 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 #ifndef KJS_JS_IMMEDIATE_H 0024 #define KJS_JS_IMMEDIATE_H 0025 0026 #include <kjs/global.h> 0027 #include "JSType.h" 0028 #include <wtf/Assertions.h> 0029 #include <wtf/AlwaysInline.h> 0030 #include <wtf/MathExtras.h> 0031 #if HAVE_STDINT_H 0032 #include <stdint.h> 0033 #endif 0034 #include <stdlib.h> 0035 0036 #if PLATFORM(SOLARIS_OS) 0037 static inline int signbit(double x) 0038 { 0039 return (x < 0.0) ? 1 : 0; 0040 } 0041 #endif 0042 0043 namespace KJS 0044 { 0045 0046 class ExecState; 0047 class JSObject; 0048 class JSValue; 0049 class UString; 0050 0051 KJS_EXPORT extern const double NaN; 0052 KJS_EXPORT extern const double Inf; 0053 0054 /* 0055 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 0056 * signed int masquerading as a pointer). The low two bits in a JSValue* are available 0057 * for type tagging because allocator alignment guarantees they will be 00 in cell pointers. 0058 * 0059 * For example, on a 32 bit system: 0060 * 0061 * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00 0062 * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ] 0063 * 0064 * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT 0065 * [ high 30 bits: signed int ] [ low 2 bits -- type tag ] 0066 * 0067 * The bit "payload" (the high 30 bits) is a 30 bit signed int for immediate numbers, a flag to distinguish true/false 0068 * and undefined/null. 0069 * 0070 * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits 0071 * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has 0072 * to sort them out. 0073 */ 0074 0075 class KJS_EXPORT JSImmediate 0076 { 0077 public: 0078 static ALWAYS_INLINE bool isImmediate(const JSValue *v) 0079 { 0080 return getTag(v) != 0; 0081 } 0082 0083 static ALWAYS_INLINE bool isNumber(const JSValue *v) 0084 { 0085 return (getTag(v) == NumberType); 0086 } 0087 0088 static ALWAYS_INLINE bool isBoolean(const JSValue *v) 0089 { 0090 return (getTag(v) == BooleanType); 0091 } 0092 0093 // Since we have room for only 3 unique tags, null and undefined have to share. 0094 static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue *v) 0095 { 0096 return (getTag(v) == UndefinedType); 0097 } 0098 0099 static JSValue *from(char); 0100 static JSValue *from(signed char); 0101 static JSValue *from(unsigned char); 0102 static JSValue *from(short); 0103 static JSValue *from(unsigned short); 0104 static JSValue *from(int); 0105 static JSValue *from(unsigned); 0106 static JSValue *from(long); 0107 static JSValue *from(unsigned long); 0108 static JSValue *from(long long); 0109 static JSValue *from(unsigned long long); 0110 static JSValue *from(double); 0111 0112 static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue *v1, const JSValue *v2) 0113 { 0114 return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType; 0115 } 0116 0117 static ALWAYS_INLINE JSValue *andImmediateNumbers(const JSValue *v1, const JSValue *v2) 0118 { 0119 ASSERT(areBothImmediateNumbers(v1, v2)); 0120 return reinterpret_cast<JSValue *>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2)); 0121 } 0122 0123 static double toDouble(const JSValue *); 0124 0125 // Non-converting getters for Number's 0126 static double getNumber(const JSValue *); // This returns NaN if the value is not a Number. 0127 static bool getNumber(const JSValue *, double &valOut); 0128 0129 static bool toBoolean(const JSValue *); 0130 static JSObject *toObject(const JSValue *, ExecState *); 0131 static UString toString(const JSValue *); 0132 static JSType type(const JSValue *); 0133 0134 static bool getUInt32(const JSValue *, uint32_t &); 0135 static bool getTruncatedInt32(const JSValue *, int32_t &); 0136 static bool getTruncatedUInt32(const JSValue *, uint32_t &); 0137 0138 static int32_t getTruncatedInt32(const JSValue *); 0139 0140 static JSValue *trueImmediate(); 0141 static JSValue *falseImmediate(); 0142 static JSValue *undefinedImmediate(); 0143 static JSValue *nullImmediate(); 0144 0145 private: 0146 static const uintptr_t TagMask = 3; // type tags are 2 bits long 0147 0148 // Immediate values are restricted to a 30 bit signed value. 0149 static const int minImmediateInt = -(1 << 29); 0150 static const int maxImmediateInt = (1 << 29) - 1; 0151 static const unsigned maxImmediateUInt = maxImmediateInt; 0152 0153 static ALWAYS_INLINE JSValue *tag(uintptr_t bits, uintptr_t tag) 0154 { 0155 return reinterpret_cast<JSValue *>(bits | tag); 0156 } 0157 0158 static ALWAYS_INLINE uintptr_t unTag(const JSValue *v) 0159 { 0160 return reinterpret_cast<uintptr_t>(v) & ~TagMask; 0161 } 0162 0163 static ALWAYS_INLINE uintptr_t getTag(const JSValue *v) 0164 { 0165 return reinterpret_cast<uintptr_t>(v) & TagMask; 0166 } 0167 }; 0168 0169 ALWAYS_INLINE JSValue *JSImmediate::trueImmediate() 0170 { 0171 return tag(1 << 2, BooleanType); 0172 } 0173 ALWAYS_INLINE JSValue *JSImmediate::falseImmediate() 0174 { 0175 return tag(0, BooleanType); 0176 } 0177 ALWAYS_INLINE JSValue *JSImmediate::undefinedImmediate() 0178 { 0179 return tag(1 << 2, UndefinedType); 0180 } 0181 ALWAYS_INLINE JSValue *JSImmediate::nullImmediate() 0182 { 0183 return tag(0, UndefinedType); 0184 } 0185 0186 ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue *v) 0187 { 0188 ASSERT(isImmediate(v)); 0189 uintptr_t bits = unTag(v); 0190 return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType); 0191 } 0192 0193 ALWAYS_INLINE JSValue *JSImmediate::from(char i) 0194 { 0195 return tag(i << 2, NumberType); 0196 } 0197 0198 ALWAYS_INLINE JSValue *JSImmediate::from(signed char i) 0199 { 0200 return tag(i << 2, NumberType); 0201 } 0202 0203 ALWAYS_INLINE JSValue *JSImmediate::from(unsigned char i) 0204 { 0205 return tag(i << 2, NumberType); 0206 } 0207 0208 ALWAYS_INLINE JSValue *JSImmediate::from(short i) 0209 { 0210 return tag(i << 2, NumberType); 0211 } 0212 0213 ALWAYS_INLINE JSValue *JSImmediate::from(unsigned short i) 0214 { 0215 return tag(i << 2, NumberType); 0216 } 0217 0218 ALWAYS_INLINE JSValue *JSImmediate::from(int i) 0219 { 0220 if ((i < minImmediateInt) || (i > maxImmediateInt)) { 0221 return nullptr; 0222 } 0223 return tag(i << 2, NumberType); 0224 } 0225 0226 ALWAYS_INLINE JSValue *JSImmediate::from(unsigned i) 0227 { 0228 if (i > maxImmediateUInt) { 0229 return nullptr; 0230 } 0231 return tag(i << 2, NumberType); 0232 } 0233 0234 ALWAYS_INLINE JSValue *JSImmediate::from(long i) 0235 { 0236 if ((i < minImmediateInt) || (i > maxImmediateInt)) { 0237 return nullptr; 0238 } 0239 return tag(i << 2, NumberType); 0240 } 0241 0242 ALWAYS_INLINE JSValue *JSImmediate::from(unsigned long i) 0243 { 0244 if (i > maxImmediateUInt) { 0245 return nullptr; 0246 } 0247 return tag(i << 2, NumberType); 0248 } 0249 0250 ALWAYS_INLINE JSValue *JSImmediate::from(long long i) 0251 { 0252 if ((i < minImmediateInt) || (i > maxImmediateInt)) { 0253 return nullptr; 0254 } 0255 return tag(static_cast<uintptr_t>(i) << 2, NumberType); 0256 } 0257 0258 ALWAYS_INLINE JSValue *JSImmediate::from(unsigned long long i) 0259 { 0260 if (i > maxImmediateUInt) { 0261 return nullptr; 0262 } 0263 return tag(static_cast<uintptr_t>(i) << 2, NumberType); 0264 } 0265 0266 ALWAYS_INLINE JSValue *JSImmediate::from(double d) 0267 { 0268 using namespace std; 0269 const int intVal = static_cast<int>(d); 0270 0271 if ((intVal < minImmediateInt) || (intVal > maxImmediateInt)) { 0272 return nullptr; 0273 } 0274 0275 // Check for data loss from conversion to int. 0276 if ((intVal != d) || (!intVal && signbit(d))) { 0277 return nullptr; 0278 } 0279 0280 return tag(intVal << 2, NumberType); 0281 } 0282 0283 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue *v) 0284 { 0285 ASSERT(isNumber(v)); 0286 return static_cast<int32_t>(unTag(v)) >> 2; 0287 } 0288 0289 ALWAYS_INLINE double JSImmediate::toDouble(const JSValue *v) 0290 { 0291 ASSERT(isImmediate(v)); 0292 const int32_t i = static_cast<int32_t>(unTag(v)) >> 2; 0293 if (JSImmediate::getTag(v) == UndefinedType && i) { 0294 return NaN; 0295 } 0296 return i; 0297 } 0298 0299 ALWAYS_INLINE double JSImmediate::getNumber(const JSValue *v) 0300 { 0301 ASSERT(isImmediate(v)); 0302 const int32_t i = static_cast<int32_t>(unTag(v)) >> 2; 0303 if (JSImmediate::getTag(v) != NumberType) { 0304 return NaN; 0305 } 0306 return i; 0307 } 0308 0309 ALWAYS_INLINE bool JSImmediate::getNumber(const JSValue *v, double &numberOut) 0310 { 0311 ASSERT(isImmediate(v)); 0312 numberOut = static_cast<int32_t>(unTag(v)) >> 2; 0313 return (JSImmediate::getTag(v) == NumberType); 0314 } 0315 0316 ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue *v, uint32_t &i) 0317 { 0318 const int32_t si = static_cast<int32_t>(unTag(v)) >> 2; 0319 i = si; 0320 return isNumber(v) & (si >= 0); 0321 } 0322 0323 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue *v, int32_t &i) 0324 { 0325 i = static_cast<int32_t>(unTag(v)) >> 2; 0326 return isNumber(v); 0327 } 0328 0329 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue *v, uint32_t &i) 0330 { 0331 return getUInt32(v, i); 0332 } 0333 0334 } // namespace KJS 0335 0336 #endif