Changeset 10757 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Oct 5, 2005, 6:13:18 PM (20 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/internal.h
r10713 r10757 27 27 28 28 #include "ustring.h" 29 #include "value.h"30 29 #include "object.h" 31 30 #include "protect.h" … … 113 112 friend class ConstantValues; 114 113 friend class InterpreterImp; 115 friend ValueImp *jsNumber(int);116 friend ValueImp *jsNumber(unsigned);117 friend ValueImp *jsNumber(long);118 friend ValueImp *jsNumber(unsigned long);119 friend ValueImp *jsNumber(long long);120 friend ValueImp *jsNumber(unsigned long long);121 114 friend ValueImp *jsNumber(double); 122 friend ValueImp *jsNumber(double, bool);123 115 public: 124 116 double value() const { return val; } … … 139 131 double val; 140 132 }; 133 141 134 142 135 /** -
trunk/JavaScriptCore/kjs/math_object.cpp
r10701 r10757 233 233 case MathObjectImp::Pow: 234 234 // ECMA 15.8.2.1.13 (::pow takes care of most of the critera) 235 if ( KJS::isNaN(arg2))235 if (isNaN(arg2)) 236 236 result = NaN; 237 237 #if !APPLE_CHANGES … … 239 239 result = 1; 240 240 #endif 241 else if ( KJS::isNaN(arg) && arg2 != 0)241 else if (isNaN(arg) && arg2 != 0) 242 242 result = NaN; 243 243 #if !APPLE_CHANGES -
trunk/JavaScriptCore/kjs/nodes.cpp
r10744 r10757 663 663 ValueImp *v = slot.getValue(exec, m_ident); 664 664 665 bool knownToBeInteger; 666 double n = v->toNumber(exec, knownToBeInteger); 665 double n = v->toNumber(exec); 667 666 668 667 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 669 base->put(exec, m_ident, jsNumber(newValue , knownToBeInteger));668 base->put(exec, m_ident, jsNumber(newValue)); 670 669 671 return jsNumber(n , knownToBeInteger);670 return jsNumber(n); 672 671 } 673 672 … … 695 694 KJS_CHECKEXCEPTIONVALUE 696 695 697 bool knownToBeInteger; 698 double n = v->toNumber(exec, knownToBeInteger); 696 double n = v->toNumber(exec); 699 697 700 698 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 701 base->put(exec, propertyIndex, jsNumber(newValue , knownToBeInteger));699 base->put(exec, propertyIndex, jsNumber(newValue)); 702 700 703 return jsNumber(n , knownToBeInteger);701 return jsNumber(n); 704 702 } 705 703 … … 709 707 KJS_CHECKEXCEPTIONVALUE 710 708 711 bool knownToBeInteger; 712 double n = v->toNumber(exec, knownToBeInteger); 709 double n = v->toNumber(exec); 713 710 714 711 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 715 base->put(exec, propertyName, jsNumber(newValue , knownToBeInteger));712 base->put(exec, propertyName, jsNumber(newValue)); 716 713 717 return jsNumber(n , knownToBeInteger);714 return jsNumber(n); 718 715 } 719 716 … … 730 727 KJS_CHECKEXCEPTIONVALUE 731 728 732 bool knownToBeInteger; 733 double n = v->toNumber(exec, knownToBeInteger); 729 double n = v->toNumber(exec); 734 730 735 731 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 736 base->put(exec, m_ident, jsNumber(newValue , knownToBeInteger));732 base->put(exec, m_ident, jsNumber(newValue)); 737 733 738 return jsNumber(n , knownToBeInteger);734 return jsNumber(n); 739 735 } 740 736 … … 893 889 ValueImp *v = slot.getValue(exec, m_ident); 894 890 895 bool knownToBeInteger; 896 double n = v->toNumber(exec, knownToBeInteger); 891 double n = v->toNumber(exec); 897 892 898 893 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 899 ValueImp *n2 = jsNumber(newValue , knownToBeInteger);894 ValueImp *n2 = jsNumber(newValue); 900 895 base->put(exec, m_ident, n2); 901 896 … … 926 921 KJS_CHECKEXCEPTIONVALUE 927 922 928 bool knownToBeInteger; 929 double n = v->toNumber(exec, knownToBeInteger); 923 double n = v->toNumber(exec); 930 924 931 925 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 932 ValueImp *n2 = jsNumber(newValue , knownToBeInteger);926 ValueImp *n2 = jsNumber(newValue); 933 927 base->put(exec, propertyIndex, n2); 934 928 … … 941 935 KJS_CHECKEXCEPTIONVALUE 942 936 943 bool knownToBeInteger; 944 double n = v->toNumber(exec, knownToBeInteger); 937 double n = v->toNumber(exec); 945 938 946 939 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 947 ValueImp *n2 = jsNumber(newValue , knownToBeInteger);940 ValueImp *n2 = jsNumber(newValue); 948 941 base->put(exec, propertyName, n2); 949 942 … … 963 956 KJS_CHECKEXCEPTIONVALUE 964 957 965 bool knownToBeInteger; 966 double n = v->toNumber(exec, knownToBeInteger); 958 double n = v->toNumber(exec); 967 959 968 960 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1; 969 ValueImp *n2 = jsNumber(newValue , knownToBeInteger);961 ValueImp *n2 = jsNumber(newValue); 970 962 base->put(exec, m_ident, n2); 971 963 … … 992 984 KJS_CHECKEXCEPTIONVALUE 993 985 994 bool knownToBeInteger; 995 double n = v->toNumber(exec, knownToBeInteger); 996 return jsNumber(-n, knownToBeInteger && n != 0); 986 double n = v->toNumber(exec); 987 return jsNumber(-n); 997 988 } 998 989 … … 1258 1249 break; 1259 1250 case OpModEq: { 1260 bool d1KnownToBeInteger; 1261 double d1 = v1->toNumber(exec, d1KnownToBeInteger); 1262 bool d2KnownToBeInteger; 1263 double d2 = v2->toNumber(exec, d2KnownToBeInteger); 1264 v = jsNumber(fmod(d1, d2), d1KnownToBeInteger && d2KnownToBeInteger && d2 != 0); 1251 double d1 = v1->toNumber(exec); 1252 double d2 = v2->toNumber(exec); 1253 v = jsNumber(fmod(d1, d2)); 1265 1254 } 1266 1255 break; -
trunk/JavaScriptCore/kjs/number_object.cpp
r10701 r10757 357 357 358 358 const ClassInfo NumberObjectImp::info = {"Number", &InternalFunctionImp::info, &numberTable, 0}; 359 //const ClassInfo NumberObjectImp::info = {"Number", 0, &numberTable, 0};360 359 361 360 /* Source for number_object.lut.h -
trunk/JavaScriptCore/kjs/operations.cpp
r10724 r10757 143 143 double d1 = v1->toNumber(exec); 144 144 double d2 = v2->toNumber(exec); 145 // FIXME: Isn't this already how NaN behaves? 146 // Why the extra line of code? 147 if (isNaN(d1) || isNaN(d2)) 148 return false; 149 return d1 == d2; /* TODO: +0, -0 ? */ 145 return d1 == d2; 150 146 } 151 147 … … 172 168 double n1 = v1->toNumber(exec); 173 169 double n2 = v2->toNumber(exec); 174 // FIXME: Isn't this already how NaN behaves?175 // Why the extra line of code?176 if (isNaN(n1) || isNaN(n2))177 return false;178 170 if (n1 == n2) 179 return true; 180 /* TODO: +0 and -0 */ 171 return true; 181 172 return false; 182 173 } else if (t1 == StringType) { … … 231 222 } 232 223 233 bool n1KnownToBeInteger;234 double n1 = p1->toNumber(exec, n1KnownToBeInteger);235 bool n2KnownToBeInteger;236 double n2 = p2->toNumber(exec, n2KnownToBeInteger);237 238 bool resultKnownToBeInteger = n1KnownToBeInteger && n2KnownToBeInteger;239 240 224 if (oper == '+') 241 return jsNumber( n1 + n2, resultKnownToBeInteger);225 return jsNumber(p1->toNumber(exec) + p2->toNumber(exec)); 242 226 else 243 return jsNumber( n1 - n2, resultKnownToBeInteger);227 return jsNumber(p1->toNumber(exec) - p2->toNumber(exec)); 244 228 } 245 229 … … 247 231 ValueImp *mult(ExecState *exec, ValueImp *v1, ValueImp *v2, char oper) 248 232 { 249 bool n1KnownToBeInteger; 250 double n1 = v1->toNumber(exec, n1KnownToBeInteger); 251 bool n2KnownToBeInteger; 252 double n2 = v2->toNumber(exec, n2KnownToBeInteger); 233 double n1 = v1->toNumber(exec); 234 double n2 = v2->toNumber(exec); 253 235 254 236 double result; 255 bool resultKnownToBeInteger;256 237 257 238 if (oper == '*') { 258 239 result = n1 * n2; 259 resultKnownToBeInteger = n1KnownToBeInteger && n2KnownToBeInteger;260 240 } else if (oper == '/') { 261 241 result = n1 / n2; 262 resultKnownToBeInteger = false;263 242 } else { 264 243 result = fmod(n1, n2); 265 resultKnownToBeInteger = n1KnownToBeInteger && n2KnownToBeInteger && n2 != 0;266 244 } 267 245 268 return jsNumber(result , resultKnownToBeInteger);269 } 270 271 } 246 return jsNumber(result); 247 } 248 249 } -
trunk/JavaScriptCore/kjs/operations.h
r10084 r10757 24 24 #define _KJS_OPERATIONS_H_ 25 25 26 #include "value.h"27 28 26 namespace KJS { 29 27 30 28 class ExecState; 29 class ValueImp; 31 30 32 31 #if APPLE_CHANGES -
trunk/JavaScriptCore/kjs/simple_number.h
r10654 r10757 23 23 #define KJS_SIMPLE_NUMBER_H 24 24 25 // We include these headers here because simple_number.h is the most low-level header we have. 25 26 #include <float.h> 26 27 #include <math.h> … … 38 39 #endif 39 40 40 #define KJS_MIN_MACRO(a, b) ((a) < (b) ? (a) : (b)) 41 #if defined(__GNUC__) && (__GNUC__ > 3) 42 #define ALWAYS_INLINE __attribute__ ((always_inline)) 43 #else 44 #define ALWAYS_INLINE inline 45 #endif 41 46 42 47 namespace KJS { … … 44 49 class ValueImp; 45 50 46 static inline bool isNegativeZero(double num)47 {48 #if WIN3249 return _fpclass(num) == _FPCLASS_NZ;50 #else51 return num == -0.0 && signbit(num);52 #endif53 }54 55 51 class SimpleNumber { 56 52 public: 57 static const int tagBits = 2; // Pointer alignment guarantees that we have the low two bits to play with for type tagging 58 static const unsigned long tag = 1UL; // 01 is the full tag 59 static const unsigned long tagMask = (1UL << tagBits) - 1; 60 static const int valueBits = KJS_MIN_MACRO(sizeof(ValueImp *) * 8 - tagBits, sizeof(long) * 8); 61 static const unsigned long signMask = 1UL << sizeof(long) * 8 - 1; 62 static const long maxValue = (signMask >> tagBits) - 1; 63 static const unsigned long umaxValue = maxValue; 64 static const long minValue = -(maxValue + 1); 53 static const unsigned long tag = 1; // 01 is the full tag, since it's 2 bits long. 54 static const unsigned long tagMask = 3; // 11 is the tag mask, since it's 2 bits long. 55 56 ALWAYS_INLINE 57 static ValueImp *make(double d) 58 { 59 if (sizeof(float) == sizeof(unsigned long) && 60 sizeof(double) == sizeof(unsigned long long) && 61 sizeof(ValueImp*) >= sizeof(unsigned long)) { 62 // 32-bit 63 union { 64 unsigned long asBits; 65 float asFloat; 66 } floatunion; 67 floatunion.asFloat = d; 68 69 if ((floatunion.asBits & tagMask) != 0) 70 return 0; 71 72 // Check for loss in conversion to float 73 union { 74 unsigned long long asBits; 75 double asDouble; 76 } doubleunion1, doubleunion2; 77 doubleunion1.asDouble = floatunion.asFloat; 78 doubleunion2.asDouble = d; 79 if (doubleunion1.asBits != doubleunion2.asBits) 80 return 0; 81 82 return reinterpret_cast<ValueImp *>(floatunion.asBits | tag); 83 } else if (sizeof(double) == sizeof(unsigned long) && 84 sizeof(ValueImp*) >= sizeof(unsigned long)) { 85 // 64-bit 86 union { 87 unsigned long asBits; 88 double asDouble; 89 } doubleunion; 90 doubleunion.asDouble = d; 91 92 if ((doubleunion.asBits & tagMask) != 0) 93 return 0; 65 94 66 static unsigned long rightShiftSignExtended(uintptr_t l, int n) 95 return reinterpret_cast<ValueImp *>(doubleunion.asBits | tag); 96 } else { 97 // could just return 0 here, but nicer to be explicit about not supporting the platform well 98 abort(); 99 } 100 } 101 102 static bool is(const ValueImp *imp) 67 103 { 68 return ( l >> n) | ((l & signMask) ? (~0UL << valueBits) : 0);104 return (reinterpret_cast<unsigned long>(imp) & tagMask) == tag; 69 105 } 70 106 71 static ValueImp *make(long i) { return reinterpret_cast<ValueImp *>((i << tagBits) | tag); } 72 static bool is(const ValueImp *imp) { return (reinterpret_cast<uintptr_t>(imp) & tagMask) == tag; } 73 static long value(const ValueImp *imp) { return rightShiftSignExtended(reinterpret_cast<uintptr_t>(imp), tagBits); } 74 75 static bool fits(int i) { return !(i > maxValue || i < minValue); } 76 static bool fits(long i) { return !(i > maxValue || i < minValue); } 77 static bool fits(long long i) { return !(i > maxValue || i < minValue); } 78 static bool integerFits(double i) { return !(i > maxValue || i < minValue); } 79 80 static bool fits(double d) { return !(d > maxValue || d < minValue) && d == (double)(long)d && !isNegativeZero(d); } 81 82 static bool fits(unsigned i) { return !(i > umaxValue); } 83 static bool fits(unsigned long i) { return !(i > umaxValue); } 84 static bool fits(unsigned long long i) { return !(i > umaxValue); } 107 ALWAYS_INLINE 108 static double value(const ValueImp *imp) 109 { 110 assert(is(imp)); 111 112 if (sizeof(float) == sizeof(unsigned long)) { 113 // 32-bit 114 union { 115 unsigned long asBits; 116 float asFloat; 117 } floatunion; 118 floatunion.asBits = reinterpret_cast<unsigned long>(imp) & ~tagMask; 119 return floatunion.asFloat; 120 } else if (sizeof(double) == sizeof(unsigned long)) { 121 // 64-bit 122 union { 123 unsigned long asBits; 124 double asDouble; 125 } doubleunion; 126 doubleunion.asBits = reinterpret_cast<unsigned long>(imp) & ~tagMask; 127 return doubleunion.asDouble; 128 } else { 129 // could just return 0 here, but nicer to be explicit about not supporting the platform well 130 abort(); 131 } 132 } 133 85 134 }; 86 135 -
trunk/JavaScriptCore/kjs/string_object.cpp
r10701 r10757 621 621 double start = a0->toNumber(exec); 622 622 double end = a1->toNumber(exec); 623 if ( KJS::isNaN(start))623 if (isNaN(start)) 624 624 start = 0; 625 if ( KJS::isNaN(end))625 if (isNaN(end)) 626 626 end = 0; 627 627 if (start < 0) -
trunk/JavaScriptCore/kjs/ustring.cpp
r10634 r10757 968 968 bool b = true; 969 969 970 if ( isNaN(d) ||d != static_cast<uint32_t>(d)) {970 if (d != static_cast<uint32_t>(d)) { 971 971 b = false; 972 972 d = 0; … … 984 984 bool b = true; 985 985 986 if ( isNaN(d) ||d != static_cast<uint32_t>(d)) {986 if (d != static_cast<uint32_t>(d)) { 987 987 b = false; 988 988 d = 0; -
trunk/JavaScriptCore/kjs/value.cpp
r10701 r10757 45 45 AllocatedValueImp *ConstantValues::jsTrue = NULL; 46 46 AllocatedValueImp *ConstantValues::jsFalse = NULL; 47 AllocatedValueImp *ConstantValues::NaN = NULL;48 47 49 48 static const double D16 = 65536.0; … … 183 182 } 184 183 185 ValueImp *jsNumber(int i)186 {187 return SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i));188 }189 190 ValueImp *jsNumber(unsigned i)191 {192 return SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i));193 }194 195 ValueImp *jsNumber(long i)196 {197 return SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i));198 }199 200 ValueImp *jsNumber(unsigned long i)201 {202 return SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i));203 }204 205 ValueImp *jsNumber(long long i)206 {207 return SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i));208 }209 210 ValueImp *jsNumber(unsigned long long i)211 {212 return SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i));213 }214 215 184 ValueImp *jsNumber(double d) 216 185 { 217 return SimpleNumber::fits(d) 218 ? SimpleNumber::make(static_cast<long>(d)) 219 : (isNaN(d) ? jsNaN() : new NumberImp(d)); 220 } 221 222 ValueImp *jsNumber(double d, bool knownToBeInteger) 223 { 224 return (knownToBeInteger ? SimpleNumber::integerFits(d) : SimpleNumber::fits(d)) 225 ? SimpleNumber::make(static_cast<long>(d)) 226 : ((!knownToBeInteger && isNaN(d)) ? jsNaN() : new NumberImp(d)); 186 ValueImp *v = SimpleNumber::make(d); 187 return v ? v : new NumberImp(d); 227 188 } 228 189 … … 233 194 jsTrue = new BooleanImp(true); 234 195 jsFalse = new BooleanImp(false); 235 NaN = new NumberImp(::KJS::NaN);236 196 } 237 197 … … 242 202 jsTrue = NULL; 243 203 jsFalse = NULL; 244 NaN = NULL;245 204 } 246 205 … … 259 218 if (!v->marked()) 260 219 v->mark(); 261 if (AllocatedValueImp *v = NaN) 262 if (!v->marked()) 263 v->mark(); 264 } 265 266 } 220 } 221 222 } -
trunk/JavaScriptCore/kjs/value.h
r10556 r10757 102 102 bool toBoolean(ExecState *exec) const; 103 103 double toNumber(ExecState *exec) const; 104 double toNumber(ExecState *exec, bool& knownToBeInteger) const;105 104 UString toString(ExecState *exec) const; 106 105 ObjectImp *toObject(ExecState *exec) const; … … 162 161 virtual bool toBoolean(ExecState *exec) const = 0; 163 162 virtual double toNumber(ExecState *exec) const = 0; 164 double toNumber(ExecState *exec, bool& knownToBeInteger) const;165 163 virtual UString toString(ExecState *exec) const = 0; 166 164 virtual ObjectImp *toObject(ExecState *exec) const = 0; … … 181 179 182 180 ValueImp *jsNumber(double); 183 ValueImp *jsNumber(double, bool knownToBeInteger); 184 AllocatedValueImp *jsNaN(); 181 ValueImp *jsNaN(); 185 182 ValueImp *jsZero(); 186 183 ValueImp *jsOne(); 187 184 ValueImp *jsTwo(); 188 ValueImp *jsNumber(int);189 ValueImp *jsNumber(unsigned);190 ValueImp *jsNumber(long);191 ValueImp *jsNumber(unsigned long);192 ValueImp *jsNumber(long long);193 ValueImp *jsNumber(unsigned long long);194 185 195 186 AllocatedValueImp *jsString(const UString &); // returns empty string if passed null string … … 205 196 static AllocatedValueImp *jsFalse; 206 197 static AllocatedValueImp *jsTrue; 207 static AllocatedValueImp *NaN;208 198 209 199 static void init(); … … 227 217 } 228 218 229 inline AllocatedValueImp *jsNaN()230 { 231 return ConstantValues::NaN;219 inline ValueImp *jsNaN() 220 { 221 return SimpleNumber::make(NaN); 232 222 } 233 223 … … 373 363 { 374 364 if (SimpleNumber::is(this)) { 375 long i= SimpleNumber::value(this);376 if ( i < 0)365 double d = SimpleNumber::value(this); 366 if (!(d >= 0) || d > 0xFFFFFFFFUL) // true for NaN 377 367 return false; 378 v = i;368 v = static_cast<uint32_t>(d); 379 369 return true; 380 370 } … … 405 395 inline bool ValueImp::toBoolean(ExecState *exec) const 406 396 { 407 return SimpleNumber::is(this) ? SimpleNumber::value(this) : downcast()->toBoolean(exec); 397 if (SimpleNumber::is(this)) { 398 double d = SimpleNumber::value(this); 399 return d < 0 || d > 0; // false for NaN 400 } 401 402 return downcast()->toBoolean(exec); 408 403 } 409 404 … … 413 408 } 414 409 415 inline double ValueImp::toNumber(ExecState *exec, bool& knownToBeInteger) const410 inline UString ValueImp::toString(ExecState *exec) const 416 411 { 417 412 if (SimpleNumber::is(this)) { 418 knownToBeInteger = true; 419 return SimpleNumber::value(this); 413 double d = SimpleNumber::value(this); 414 if (d == 0.0) // +0.0 or -0.0 415 d = 0.0; 416 return UString::from(d); 420 417 } 421 knownToBeInteger = false; 422 return downcast()->toNumber(exec); 423 } 424 425 inline UString ValueImp::toString(ExecState *exec) const 426 { 427 return SimpleNumber::is(this) ? UString::from(SimpleNumber::value(this)) : downcast()->toString(exec); 418 419 return downcast()->toString(exec); 428 420 } 429 421 430 422 inline ValueImp *jsZero() 431 423 { 432 return SimpleNumber::make(0 );424 return SimpleNumber::make(0.0); 433 425 } 434 426 435 427 inline ValueImp *jsOne() 436 428 { 437 return SimpleNumber::make(1 );429 return SimpleNumber::make(1.0); 438 430 } 439 431 440 432 inline ValueImp *jsTwo() 441 433 { 442 return SimpleNumber::make(2 );434 return SimpleNumber::make(2.0); 443 435 } 444 436 … … 449 441 inline AllocatedValueImp *Boolean(bool b) { return jsBoolean(b); } 450 442 inline ValueImp *Number(double n) { return jsNumber(n); } 451 inline ValueImp *Number(int n) { return jsNumber(n); }452 inline ValueImp *Number(unsigned n) { return jsNumber(n); }453 inline ValueImp *Number(long n) { return jsNumber(n); }454 inline ValueImp *Number(unsigned long n) { return jsNumber(n); }455 443 inline AllocatedValueImp *String(const UString& s) { return jsString(s); } 456 444 inline AllocatedValueImp *String(const char *s) { return jsString(s); }
Note:
See TracChangeset
for help on using the changeset viewer.