Changeset 10757 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Oct 5, 2005, 6:13:18 PM (20 years ago)
Author:
ggaren
Message:
  • Darin and I rewrote our implementation of the SimpleNumber class to store number bit patterns in their floating point formats.

My tweaks reviewed by Darin.

~1% speedup on JS iBench.

  • kjs/internal.h: removed obsolete jsNumber declarations.
  • kjs/math_object.cpp: (MathFuncImp::callAsFunction): changed KJS::isNaN to isNaN
  • kjs/nodes.cpp: (PostfixResolveNode::evaluate): removed obsolete knownToBeInteger (PostfixBracketNode::evaluate): ditto (PostfixDotNode::evaluate): ditto (PrefixResolveNode::evaluate): ditto (PrefixBracketNode::evaluate): ditto (PrefixDotNode::evaluate): ditto (NegateNode::evaluate): ditto (valueForReadModifyAssignment): ditto
  • kjs/number_object.cpp: removed obsolete comment
  • kjs/operations.cpp: (KJS::equal): removed unnecessary isNaN checks (KJS::strictEqual): ditto (KJS::add): removed obsolete knownToBeInteger (KJS::mult): ditto
  • kjs/operations.h: removed include of "value.h" to prevent circular reference
  • kjs/simple_number.h: removed unnecessary #includes (KJS::SimpleNumber::make): see above (KJS::SimpleNumber::is): ditto (KJS::SimpleNumber::value): ditto
  • kjs/string_object.cpp: (StringProtoFuncImp::callAsFunction): changed KJS::isNaN to isNaN
  • kjs/ustring.cpp: removed unnecessary isNaN check (KJS::UString::toUInt32): ditto
  • kjs/value.cpp: (KJS::jsNumber): removed obsolete jsNumber definitions (KJS::ConstantValues::init): NaN is no longer a ConstantValue (KJS::ConstantValues::clear): ditto (KJS::ConstantValues::mark): ditto
  • kjs/value.h: removed obsolete knownToBeInteger (KJS::jsNaN): now returns a SimpleNumber (KJS::ValueImp::getUInt32): changed to account for NaN being a SimpleNumber (KJS::ValueImp::toBoolean): ditto (KJS::ValueImp::toString): changed to account for +/- 0.0 (KJS::jsZero): changed to reflect that SimpleNumber::make takes a double (KJS::jsOne): ditto (KJS::jsTwo): ditto (KJS::Number): removed obsolete non-double constructor declarations
Location:
trunk/JavaScriptCore/kjs
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/internal.h

    r10713 r10757  
    2727
    2828#include "ustring.h"
    29 #include "value.h"
    3029#include "object.h"
    3130#include "protect.h"
     
    113112    friend class ConstantValues;
    114113    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);
    121114    friend ValueImp *jsNumber(double);
    122     friend ValueImp *jsNumber(double, bool);
    123115  public:
    124116    double value() const { return val; }
     
    139131    double val;
    140132  };
     133 
    141134
    142135  /**
  • trunk/JavaScriptCore/kjs/math_object.cpp

    r10701 r10757  
    233233  case MathObjectImp::Pow:
    234234    // ECMA 15.8.2.1.13 (::pow takes care of most of the critera)
    235     if (KJS::isNaN(arg2))
     235    if (isNaN(arg2))
    236236      result = NaN;
    237237#if !APPLE_CHANGES
     
    239239      result = 1;
    240240#endif
    241     else if (KJS::isNaN(arg) && arg2 != 0)
     241    else if (isNaN(arg) && arg2 != 0)
    242242      result = NaN;
    243243#if !APPLE_CHANGES
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r10744 r10757  
    663663        ValueImp *v = slot.getValue(exec, m_ident);
    664664
    665         bool knownToBeInteger;
    666         double n = v->toNumber(exec, knownToBeInteger);
     665        double n = v->toNumber(exec);
    667666       
    668667        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));
    670669       
    671         return jsNumber(n, knownToBeInteger);
     670        return jsNumber(n);
    672671    }
    673672
     
    695694    KJS_CHECKEXCEPTIONVALUE
    696695
    697     bool knownToBeInteger;
    698     double n = v->toNumber(exec, knownToBeInteger);
     696    double n = v->toNumber(exec);
    699697
    700698    double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
    701     base->put(exec, propertyIndex, jsNumber(newValue, knownToBeInteger));
     699    base->put(exec, propertyIndex, jsNumber(newValue));
    702700       
    703     return jsNumber(n, knownToBeInteger);
     701    return jsNumber(n);
    704702  }
    705703
     
    709707  KJS_CHECKEXCEPTIONVALUE
    710708
    711   bool knownToBeInteger;
    712   double n = v->toNumber(exec, knownToBeInteger);
     709  double n = v->toNumber(exec);
    713710 
    714711  double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
    715   base->put(exec, propertyName, jsNumber(newValue, knownToBeInteger));
     712  base->put(exec, propertyName, jsNumber(newValue));
    716713       
    717   return jsNumber(n, knownToBeInteger);
     714  return jsNumber(n);
    718715}
    719716
     
    730727  KJS_CHECKEXCEPTIONVALUE
    731728
    732   bool knownToBeInteger;
    733   double n = v->toNumber(exec, knownToBeInteger);
     729  double n = v->toNumber(exec);
    734730 
    735731  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));
    737733       
    738   return jsNumber(n, knownToBeInteger);
     734  return jsNumber(n);
    739735}
    740736
     
    893889        ValueImp *v = slot.getValue(exec, m_ident);
    894890
    895         bool knownToBeInteger;
    896         double n = v->toNumber(exec, knownToBeInteger);
     891        double n = v->toNumber(exec);
    897892       
    898893        double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
    899         ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
     894        ValueImp *n2 = jsNumber(newValue);
    900895        base->put(exec, m_ident, n2);
    901896
     
    926921    KJS_CHECKEXCEPTIONVALUE
    927922
    928     bool knownToBeInteger;
    929     double n = v->toNumber(exec, knownToBeInteger);
     923    double n = v->toNumber(exec);
    930924
    931925    double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
    932     ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
     926    ValueImp *n2 = jsNumber(newValue);
    933927    base->put(exec, propertyIndex, n2);
    934928
     
    941935  KJS_CHECKEXCEPTIONVALUE
    942936
    943   bool knownToBeInteger;
    944   double n = v->toNumber(exec, knownToBeInteger);
     937  double n = v->toNumber(exec);
    945938 
    946939  double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
    947   ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
     940  ValueImp *n2 = jsNumber(newValue);
    948941  base->put(exec, propertyName, n2);
    949942
     
    963956  KJS_CHECKEXCEPTIONVALUE
    964957
    965   bool knownToBeInteger;
    966   double n = v->toNumber(exec, knownToBeInteger);
     958  double n = v->toNumber(exec);
    967959 
    968960  double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
    969   ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
     961  ValueImp *n2 = jsNumber(newValue);
    970962  base->put(exec, m_ident, n2);
    971963
     
    992984  KJS_CHECKEXCEPTIONVALUE
    993985
    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);
    997988}
    998989
     
    12581249    break;
    12591250  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));
    12651254  }
    12661255    break;
  • trunk/JavaScriptCore/kjs/number_object.cpp

    r10701 r10757  
    357357
    358358const ClassInfo NumberObjectImp::info = {"Number", &InternalFunctionImp::info, &numberTable, 0};
    359 //const ClassInfo NumberObjectImp::info = {"Number", 0, &numberTable, 0};
    360359
    361360/* Source for number_object.lut.h
  • trunk/JavaScriptCore/kjs/operations.cpp

    r10724 r10757  
    143143        double d1 = v1->toNumber(exec);
    144144        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;
    150146    }
    151147
     
    172168    double n1 = v1->toNumber(exec);
    173169    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;
    178170    if (n1 == n2)
    179       return true;
    180     /* TODO: +0 and -0 */
     171        return true;
    181172    return false;
    182173  } else if (t1 == StringType) {
     
    231222  }
    232223
    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 
    240224  if (oper == '+')
    241     return jsNumber(n1 + n2, resultKnownToBeInteger);
     225    return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
    242226  else
    243     return jsNumber(n1 - n2, resultKnownToBeInteger);
     227    return jsNumber(p1->toNumber(exec) - p2->toNumber(exec));
    244228}
    245229
     
    247231ValueImp *mult(ExecState *exec, ValueImp *v1, ValueImp *v2, char oper)
    248232{
    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);
    253235
    254236  double result;
    255   bool resultKnownToBeInteger;
    256237
    257238  if (oper == '*') {
    258239    result = n1 * n2;
    259     resultKnownToBeInteger = n1KnownToBeInteger && n2KnownToBeInteger;
    260240  } else if (oper == '/') {
    261241    result = n1 / n2;
    262     resultKnownToBeInteger = false;
    263242  } else {
    264243    result = fmod(n1, n2);
    265     resultKnownToBeInteger = n1KnownToBeInteger && n2KnownToBeInteger && n2 != 0;
    266244  }
    267245
    268   return jsNumber(result, resultKnownToBeInteger);
    269 }
    270 
    271 }
     246  return jsNumber(result);
     247}
     248
     249}
  • trunk/JavaScriptCore/kjs/operations.h

    r10084 r10757  
    2424#define _KJS_OPERATIONS_H_
    2525
    26 #include "value.h"
    27 
    2826namespace KJS {
    2927
    3028  class ExecState;
     29  class ValueImp;
    3130
    3231#if APPLE_CHANGES
  • trunk/JavaScriptCore/kjs/simple_number.h

    r10654 r10757  
    2323#define KJS_SIMPLE_NUMBER_H
    2424
     25// We include these headers here because simple_number.h is the most low-level header we have.
    2526#include <float.h>
    2627#include <math.h>
     
    3839#endif
    3940
    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
    4146
    4247namespace KJS {
     
    4449    class ValueImp;
    4550
    46     static inline bool isNegativeZero(double num)
    47     {
    48 #if WIN32
    49         return _fpclass(num) == _FPCLASS_NZ;
    50 #else
    51         return num == -0.0 && signbit(num);
    52 #endif
    53     }
    54    
    5551    class SimpleNumber {
    5652    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;
    6594
    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)
    67103        {
    68             return (l >> n) | ((l & signMask) ? (~0UL << valueBits) : 0);
     104            return (reinterpret_cast<unsigned long>(imp) & tagMask) == tag;
    69105        }
    70106       
    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       
    85134    };
    86135
  • trunk/JavaScriptCore/kjs/string_object.cpp

    r10701 r10757  
    621621    double start = a0->toNumber(exec);
    622622    double end = a1->toNumber(exec);
    623     if (KJS::isNaN(start))
     623    if (isNaN(start))
    624624      start = 0;
    625     if (KJS::isNaN(end))
     625    if (isNaN(end))
    626626      end = 0;
    627627    if (start < 0)
  • trunk/JavaScriptCore/kjs/ustring.cpp

    r10634 r10757  
    968968  bool b = true;
    969969
    970   if (isNaN(d) || d != static_cast<uint32_t>(d)) {
     970  if (d != static_cast<uint32_t>(d)) {
    971971    b = false;
    972972    d = 0;
     
    984984  bool b = true;
    985985
    986   if (isNaN(d) || d != static_cast<uint32_t>(d)) {
     986  if (d != static_cast<uint32_t>(d)) {
    987987    b = false;
    988988    d = 0;
  • trunk/JavaScriptCore/kjs/value.cpp

    r10701 r10757  
    4545AllocatedValueImp *ConstantValues::jsTrue = NULL;
    4646AllocatedValueImp *ConstantValues::jsFalse = NULL;
    47 AllocatedValueImp *ConstantValues::NaN = NULL;
    4847
    4948static const double D16 = 65536.0;
     
    183182}
    184183
    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 
    215184ValueImp *jsNumber(double d)
    216185{
    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);
    227188}
    228189
     
    233194    jsTrue = new BooleanImp(true);
    234195    jsFalse = new BooleanImp(false);
    235     NaN = new NumberImp(::KJS::NaN);
    236196}
    237197
     
    242202    jsTrue = NULL;
    243203    jsFalse = NULL;
    244     NaN = NULL;
    245204}
    246205
     
    259218        if (!v->marked())
    260219            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  
    102102    bool toBoolean(ExecState *exec) const;
    103103    double toNumber(ExecState *exec) const;
    104     double toNumber(ExecState *exec, bool& knownToBeInteger) const;
    105104    UString toString(ExecState *exec) const;
    106105    ObjectImp *toObject(ExecState *exec) const;
     
    162161    virtual bool toBoolean(ExecState *exec) const = 0;
    163162    virtual double toNumber(ExecState *exec) const = 0;
    164     double toNumber(ExecState *exec, bool& knownToBeInteger) const;
    165163    virtual UString toString(ExecState *exec) const = 0;
    166164    virtual ObjectImp *toObject(ExecState *exec) const = 0;
     
    181179
    182180ValueImp *jsNumber(double);
    183 ValueImp *jsNumber(double, bool knownToBeInteger);
    184 AllocatedValueImp *jsNaN();
     181ValueImp *jsNaN();
    185182ValueImp *jsZero();
    186183ValueImp *jsOne();
    187184ValueImp *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);
    194185
    195186AllocatedValueImp *jsString(const UString &); // returns empty string if passed null string
     
    205196    static AllocatedValueImp *jsFalse;
    206197    static AllocatedValueImp *jsTrue;
    207     static AllocatedValueImp *NaN;
    208198
    209199    static void init();
     
    227217}
    228218
    229 inline AllocatedValueImp *jsNaN()
    230 {
    231     return ConstantValues::NaN;
     219inline ValueImp *jsNaN()
     220{
     221    return SimpleNumber::make(NaN);
    232222}
    233223
     
    373363{
    374364    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
    377367            return false;
    378         v = i;
     368        v = static_cast<uint32_t>(d);
    379369        return true;
    380370    }
     
    405395inline bool ValueImp::toBoolean(ExecState *exec) const
    406396{
    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);
    408403}
    409404
     
    413408}
    414409
    415 inline double ValueImp::toNumber(ExecState *exec, bool& knownToBeInteger) const
     410inline UString ValueImp::toString(ExecState *exec) const
    416411{
    417412    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);
    420417    }
    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);
    428420}
    429421
    430422inline ValueImp *jsZero()
    431423{
    432     return SimpleNumber::make(0);
     424    return SimpleNumber::make(0.0);
    433425}
    434426
    435427inline ValueImp *jsOne()
    436428{
    437     return SimpleNumber::make(1);
     429    return SimpleNumber::make(1.0);
    438430}
    439431
    440432inline ValueImp *jsTwo()
    441433{
    442     return SimpleNumber::make(2);
     434    return SimpleNumber::make(2.0);
    443435}
    444436
     
    449441inline AllocatedValueImp *Boolean(bool b) { return jsBoolean(b); }
    450442inline 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); }
    455443inline AllocatedValueImp *String(const UString& s) { return jsString(s); }
    456444inline AllocatedValueImp *String(const char *s) { return jsString(s); }
Note: See TracChangeset for help on using the changeset viewer.