Changeset 17723 in webkit for trunk/JavaScriptCore/kjs/JSImmediate.h
- Timestamp:
- Nov 11, 2006, 12:50:38 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/JSImmediate.h
r17587 r17723 2 2 * This file is part of the KDE libraries 3 3 * Copyright (C) 2003-2006 Apple Computer, Inc 4 * Copyright (C) 2006 Alexey Proskuryakov ([email protected]) 4 5 * 5 6 * This library is free software; you can redistribute it and/or … … 28 29 #include <stdlib.h> 29 30 30 #if COMPILER(MSVC)31 #pragma warning(push)32 #pragma warning(disable: 4127)33 #pragma warning(disable: 4244)34 #pragma warning(disable: 4305)35 #pragma warning(disable: 4307)36 #pragma warning(disable: 4309)37 #pragma warning(disable: 4341)38 #endif39 40 31 namespace KJS { 41 32 … … 45 36 class UString; 46 37 47 template<bool for32bit, bool for64bit> struct NanAsBitsValue {};48 template<> struct NanAsBitsValue<true, false> {49 enum { value = 0x7fc00000 };50 };51 template<> struct NanAsBitsValue<false, true> {52 enum { value = 0x7ff80000ULL << 32 };53 };54 55 template<bool for32bit, bool for64bit> struct oneAsBitsValue {};56 template<> struct oneAsBitsValue<true, false> {57 enum { value = 0x3f800000 };58 };59 template<> struct oneAsBitsValue<false, true> {60 enum { value = 0x3ff00000ULL << 32 };61 };62 63 38 /* 64 * A JSValue *is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged65 * IEEE floating point bit pattern masquerading as a pointer). The low two bits in a JSValue 39 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 40 * IEEE floating point bit pattern masquerading as a pointer). The low two bits in a JSValue* are available 66 41 * for type tagging because allocator alignment guarantees they will be 00 in cell pointers. 67 42 * 68 43 * For example, on a 32 bit system: 69 44 * 70 * JSCell *:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 0045 * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00 71 46 * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ] 72 47 * … … 85 60 class JSImmediate { 86 61 public: 87 static bool isImmediate(const JSValue *v)62 static bool isImmediate(const JSValue* v) 88 63 { 89 64 return getTag(v) != 0; 90 65 } 91 66 92 static bool isNumber(const JSValue *v)67 static bool isNumber(const JSValue* v) 93 68 { 94 69 return (getTag(v) == NumberType); 95 70 } 96 71 97 static bool isBoolean(const JSValue *v)72 static bool isBoolean(const JSValue* v) 98 73 { 99 74 return (getTag(v) == BooleanType); … … 101 76 102 77 // Since we have room for only 3 unique tags, null and undefined have to share. 103 static bool isUndefinedOrNull(const JSValue *v)78 static bool isUndefinedOrNull(const JSValue* v) 104 79 { 105 80 return (getTag(v) == UndefinedType); 106 81 } 107 82 108 static JSValue *fromDouble(double d) 109 { 110 if (is32bit) { 111 FloatUnion floatUnion; 112 floatUnion.asFloat = d; 113 114 // check for data loss from tagging 115 if ((floatUnion.asBits & TagMask) != 0) 116 return 0; 117 118 // check for data loss from conversion to float 119 DoubleUnion doubleUnion1, doubleUnion2; 120 doubleUnion1.asDouble = floatUnion.asFloat; 121 doubleUnion2.asDouble = d; 122 if (doubleUnion1.asBits != doubleUnion2.asBits) 123 return 0; 124 125 return tag(floatUnion.asBits, NumberType); 126 } else if (is64bit) { 127 DoubleUnion doubleUnion; 128 doubleUnion.asDouble = d; 129 130 // check for data loss from tagging 131 if ((doubleUnion.asBits & TagMask) != 0) 132 return 0; 133 134 return tag(doubleUnion.asBits, NumberType); 135 } else { 136 // could just return 0 without aborting, but nicer to be explicit about not supporting the platform well 137 abort(); 138 return 0; 139 } 140 } 141 142 static double toDouble(const JSValue *v) 143 { 144 ASSERT(isImmediate(v)); 145 146 if (is32bit) { 147 FloatUnion floatUnion; 148 floatUnion.asBits = unTag(v); 149 return floatUnion.asFloat; 150 } else if (is64bit) { 151 DoubleUnion doubleUnion; 152 doubleUnion.asBits = unTag(v); 153 return doubleUnion.asDouble; 154 } else { 155 abort(); 156 return 0; 157 } 158 } 159 160 static bool toBoolean(const JSValue *v) 161 { 162 ASSERT(isImmediate(v)); 163 164 uintptr_t bits = unTag(v); 165 if ((bits << 1) == 0) // -0.0 has the sign bit set 166 return false; 167 168 return bits != NanAsBits(); 169 } 170 171 static JSObject *toObject(const JSValue *, ExecState *); 172 static UString toString(const JSValue *); 173 static JSType type(const JSValue *); 83 static JSValue* fromDouble(double d); 84 static double toDouble(const JSValue* v); 85 static bool toBoolean(const JSValue* v); 86 static JSObject* toObject(const JSValue*, ExecState*); 87 static UString toString(const JSValue*); 88 static JSType type(const JSValue*); 174 89 175 90 // It would nice just to use fromDouble() to create these values, but that would prevent them from 176 91 // turning into compile-time constants. 177 static JSValue *trueImmediate() { return tag(oneAsBits(), BooleanType); }178 static JSValue *falseImmediate() { return tag(zeroAsBits(), BooleanType); }179 static JSValue *NaNImmediate() { return tag(NanAsBits(), NumberType); }180 static JSValue *undefinedImmediate() { return tag(NanAsBits(), UndefinedType); }181 static JSValue *nullImmediate() { return tag(zeroAsBits(), UndefinedType); }92 static JSValue* trueImmediate(); 93 static JSValue* falseImmediate(); 94 static JSValue* NaNImmediate(); 95 static JSValue* undefinedImmediate(); 96 static JSValue* nullImmediate(); 182 97 183 98 private: 184 99 static const uintptr_t TagMask = 3; // type tags are 2 bits long 185 100 186 static JSValue *tag(uintptr_t bits, uintptr_t tag)187 { 188 return reinterpret_cast<JSValue 189 } 190 191 static uintptr_t unTag(const JSValue *v)101 static JSValue* tag(uintptr_t bits, uintptr_t tag) 102 { 103 return reinterpret_cast<JSValue*>(bits | tag); 104 } 105 106 static uintptr_t unTag(const JSValue* v) 192 107 { 193 108 return reinterpret_cast<uintptr_t>(v) & ~TagMask; 194 109 } 195 110 196 static uintptr_t getTag(const JSValue *v)111 static uintptr_t getTag(const JSValue* v) 197 112 { 198 113 return reinterpret_cast<uintptr_t>(v) & TagMask; … … 219 134 sizeof(float) == sizeof(uint32_t) && sizeof(double) == sizeof(uint64_t) && sizeof(uintptr_t) == sizeof(uint64_t); 220 135 221 static uintptr_t NanAsBits() 222 { 223 return NanAsBitsValue<is32bit, is64bit>::value; 224 } 225 226 static uintptr_t zeroAsBits() 227 { 228 return 0x0; 229 } 230 231 static uintptr_t oneAsBits() 232 { 233 return oneAsBitsValue<is32bit, is64bit>::value; 234 } 136 template<bool for32bit, bool for64bit> struct FPBitValues {}; 235 137 }; 236 138 139 template<> struct JSImmediate::FPBitValues<true, false> { 140 static const uint32_t nanAsBits = 0x7fc00000; 141 static const uint32_t oneAsBits = 0x3f800000; 142 static const uint32_t zeroAsBits = 0x0; 143 144 static JSValue* fromDouble(double d) 145 { 146 FloatUnion floatUnion; 147 floatUnion.asFloat = static_cast<float>(d); 148 149 // check for data loss from tagging 150 if ((floatUnion.asBits & TagMask) != 0) 151 return 0; 152 153 // check for data loss from conversion to float 154 DoubleUnion doubleUnion1, doubleUnion2; 155 doubleUnion1.asDouble = floatUnion.asFloat; 156 doubleUnion2.asDouble = d; 157 if (doubleUnion1.asBits != doubleUnion2.asBits) 158 return 0; 159 160 return tag(floatUnion.asBits, NumberType); 161 } 162 163 static double toDouble(const JSValue* v) 164 { 165 ASSERT(isImmediate(v)); 166 167 FloatUnion floatUnion; 168 floatUnion.asBits = static_cast<uint32_t>(unTag(v)); 169 return floatUnion.asFloat; 170 } 171 }; 172 173 template<> struct JSImmediate::FPBitValues<false, true> { 174 static const uint64_t nanAsBits = 0x7ff80000ULL << 32; 175 static const uint64_t oneAsBits = 0x3ff00000ULL << 32; 176 static const uint64_t zeroAsBits = 0x0; 177 178 static JSValue* fromDouble(double d) 179 { 180 DoubleUnion doubleUnion; 181 doubleUnion.asDouble = d; 182 183 // check for data loss from tagging 184 if ((doubleUnion.asBits & TagMask) != 0) 185 return 0; 186 187 return tag(static_cast<uintptr_t>(doubleUnion.asBits), NumberType); 188 } 189 190 static double toDouble(const JSValue* v) 191 { 192 ASSERT(isImmediate(v)); 193 194 DoubleUnion doubleUnion; 195 doubleUnion.asBits = unTag(v); 196 return doubleUnion.asDouble; 197 } 198 }; 199 200 inline JSValue* JSImmediate::trueImmediate() { return tag(FPBitValues<is32bit, is64bit>::oneAsBits, BooleanType); } 201 inline JSValue* JSImmediate::falseImmediate() { return tag(FPBitValues<is32bit, is64bit>::zeroAsBits, BooleanType); } 202 inline JSValue* JSImmediate::NaNImmediate() { return tag(FPBitValues<is32bit, is64bit>::nanAsBits, NumberType); } 203 inline JSValue* JSImmediate::undefinedImmediate() { return tag(FPBitValues<is32bit, is64bit>::nanAsBits, UndefinedType); } 204 inline JSValue* JSImmediate::nullImmediate() { return tag(FPBitValues<is32bit, is64bit>::zeroAsBits, UndefinedType); } 205 206 inline bool JSImmediate::toBoolean(const JSValue* v) 207 { 208 ASSERT(isImmediate(v)); 209 210 uintptr_t bits = unTag(v); 211 if ((bits << 1) == 0) // -0.0 has the sign bit set 212 return false; 213 214 return bits != FPBitValues<is32bit, is64bit>::nanAsBits; 215 } 216 217 inline JSValue* JSImmediate::fromDouble(double d) 218 { 219 return FPBitValues<is32bit, is64bit>::fromDouble(d); 220 } 221 222 inline double JSImmediate::toDouble(const JSValue* v) 223 { 224 return FPBitValues<is32bit, is64bit>::toDouble(v); 225 } 226 237 227 } // namespace KJS 238 228 239 #if COMPILER(MSVC)240 #pragma warning(pop)241 229 #endif 242 243 #endif
Note:
See TracChangeset
for help on using the changeset viewer.