KJS
JSImmediate.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef KJS_JS_IMMEDIATE_H
00024 #define KJS_JS_IMMEDIATE_H
00025
00026 #include <kjs/global.h>
00027 #include "JSType.h"
00028 #include <wtf/Assertions.h>
00029 #include <wtf/AlwaysInline.h>
00030 #include <wtf/MathExtras.h>
00031 #ifdef HAVE_STDINT_H
00032 #include <stdint.h>
00033 #endif
00034 #include <stdlib.h>
00035 #include <math.h>
00036
00037 namespace KJS {
00038
00039 class ExecState;
00040 class JSObject;
00041 class JSValue;
00042 class UString;
00043
00044 KJS_EXPORT extern const double NaN;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 class KJS_EXPORT JSImmediate {
00068 public:
00069 static ALWAYS_INLINE bool isImmediate(const JSValue* v)
00070 {
00071 return getTag(v) != 0;
00072 }
00073
00074 static ALWAYS_INLINE bool isNumber(const JSValue* v)
00075 {
00076 return (getTag(v) == NumberType);
00077 }
00078
00079 static ALWAYS_INLINE bool isBoolean(const JSValue* v)
00080 {
00081 return (getTag(v) == BooleanType);
00082 }
00083
00084
00085 static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v)
00086 {
00087 return (getTag(v) == UndefinedType);
00088 }
00089
00090 static JSValue* from(char);
00091 static JSValue* from(signed char);
00092 static JSValue* from(unsigned char);
00093 static JSValue* from(short);
00094 static JSValue* from(unsigned short);
00095 static JSValue* from(int);
00096 static JSValue* from(unsigned);
00097 static JSValue* from(long);
00098 static JSValue* from(unsigned long);
00099 static JSValue* from(long long);
00100 static JSValue* from(unsigned long long);
00101 static JSValue* from(double);
00102
00103 static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
00104 {
00105 return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType;
00106 }
00107
00108 static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2)
00109 {
00110 ASSERT(areBothImmediateNumbers(v1, v2));
00111 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2));
00112 }
00113
00114 static double toDouble(const JSValue*);
00115 static bool toBoolean(const JSValue*);
00116 static JSObject* toObject(const JSValue*, ExecState*);
00117 static UString toString(const JSValue*);
00118 static JSType type(const JSValue*);
00119
00120 static bool getUInt32(const JSValue*, uint32_t&);
00121 static bool getTruncatedInt32(const JSValue*, int32_t&);
00122 static bool getTruncatedUInt32(const JSValue*, uint32_t&);
00123
00124 static int32_t getTruncatedInt32(const JSValue*);
00125
00126 static JSValue* trueImmediate();
00127 static JSValue* falseImmediate();
00128 static JSValue* undefinedImmediate();
00129 static JSValue* nullImmediate();
00130
00131 private:
00132 static const uintptr_t TagMask = 3;
00133
00134
00135 static const int minImmediateInt = -(1 << 29);
00136 static const int maxImmediateInt = (1 << 29) - 1;
00137 static const unsigned maxImmediateUInt = maxImmediateInt;
00138
00139 static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag)
00140 {
00141 return reinterpret_cast<JSValue*>(bits | tag);
00142 }
00143
00144 static ALWAYS_INLINE uintptr_t unTag(const JSValue* v)
00145 {
00146 return reinterpret_cast<uintptr_t>(v) & ~TagMask;
00147 }
00148
00149 static ALWAYS_INLINE uintptr_t getTag(const JSValue* v)
00150 {
00151 return reinterpret_cast<uintptr_t>(v) & TagMask;
00152 }
00153 };
00154
00155 ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); }
00156 ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); }
00157 ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
00158 ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
00159
00160 ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
00161 {
00162 ASSERT(isImmediate(v));
00163 uintptr_t bits = unTag(v);
00164 return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType);
00165 }
00166
00167 ALWAYS_INLINE JSValue* JSImmediate::from(char i)
00168 {
00169 return tag(i << 2, NumberType);
00170 }
00171
00172 ALWAYS_INLINE JSValue* JSImmediate::from(signed char i)
00173 {
00174 return tag(i << 2, NumberType);
00175 }
00176
00177 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i)
00178 {
00179 return tag(i << 2, NumberType);
00180 }
00181
00182 ALWAYS_INLINE JSValue* JSImmediate::from(short i)
00183 {
00184 return tag(i << 2, NumberType);
00185 }
00186
00187 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i)
00188 {
00189 return tag(i << 2, NumberType);
00190 }
00191
00192 ALWAYS_INLINE JSValue* JSImmediate::from(int i)
00193 {
00194 if ((i < minImmediateInt) || (i > maxImmediateInt))
00195 return 0;
00196 return tag(i << 2, NumberType);
00197 }
00198
00199 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i)
00200 {
00201 if (i > maxImmediateUInt)
00202 return 0;
00203 return tag(i << 2, NumberType);
00204 }
00205
00206 ALWAYS_INLINE JSValue* JSImmediate::from(long i)
00207 {
00208 if ((i < minImmediateInt) || (i > maxImmediateInt))
00209 return 0;
00210 return tag(i << 2, NumberType);
00211 }
00212
00213 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i)
00214 {
00215 if (i > maxImmediateUInt)
00216 return 0;
00217 return tag(i << 2, NumberType);
00218 }
00219
00220 ALWAYS_INLINE JSValue* JSImmediate::from(long long i)
00221 {
00222 if ((i < minImmediateInt) || (i > maxImmediateInt))
00223 return 0;
00224 return tag(static_cast<uintptr_t>(i) << 2, NumberType);
00225 }
00226
00227 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i)
00228 {
00229 if (i > maxImmediateUInt)
00230 return 0;
00231 return tag(static_cast<uintptr_t>(i) << 2, NumberType);
00232 }
00233
00234 ALWAYS_INLINE JSValue* JSImmediate::from(double d)
00235 {
00236 const int intVal = static_cast<int>(d);
00237
00238 if ((intVal < minImmediateInt) || (intVal > maxImmediateInt))
00239 return 0;
00240
00241
00242 if ((intVal != d) || (!intVal && signbit(d)))
00243 return 0;
00244
00245 return tag(intVal << 2, NumberType);
00246 }
00247
00248 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue* v)
00249 {
00250 ASSERT(isNumber(v));
00251 return static_cast<int32_t>(unTag(v)) >> 2;
00252 }
00253
00254 ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v)
00255 {
00256 ASSERT(isImmediate(v));
00257 const int32_t i = static_cast<int32_t>(unTag(v)) >> 2;
00258 if (JSImmediate::getTag(v) == UndefinedType && i)
00259 return NaN;
00260 return i;
00261 }
00262
00263 ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i)
00264 {
00265 const int32_t si = static_cast<int32_t>(unTag(v)) >> 2;
00266 i = si;
00267 return isNumber(v) & (si >= 0);
00268 }
00269
00270 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i)
00271 {
00272 i = static_cast<int32_t>(unTag(v)) >> 2;
00273 return isNumber(v);
00274 }
00275
00276 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i)
00277 {
00278 return getUInt32(v, i);
00279 }
00280
00281 }
00282
00283 #endif