Ignore:
Timestamp:
Jul 6, 2008, 7:49:29 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2008-07-06 Sam Weinig <[email protected]>

Reviewed by Cameron Zwarich.

Second step in broad cleanup effort.

[ File list elided ]

WebCore:

2008-07-06 Sam Weinig <[email protected]>

Reviewed by Cameron Zwarich.

Add #include for kjs/protect.h.

  • xml/XMLHttpRequest.cpp: (WebCore::XMLHttpRequest::loadRequestAsynchronously):
File:
1 edited

Legend:

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

    r34943 r35027  
    3434namespace KJS {
    3535
    36 class ExecState;
    37 class JSObject;
    38 class JSValue;
    39 class UString;
    40 
    41 /*
    42  * A JSValue*  is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
    43  * signed int masquerading as a pointer). The low two bits in a JSValue* are available
    44  * for type tagging because allocator alignment guarantees they will be 00 in cell pointers.
    45  *
    46  * For example, on a 32 bit system:
    47  *
    48  * JSCell*:       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 00
    49  *               [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
    50  *
    51  * JSImmediate:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 TT
    52  *               [ high 30 bits: signed int ]       [ low 2 bits -- type tag ]
    53  *
    54  * The bit "payload" (the high 30 bits) is a 30 bit signed int for immediate numbers, a flag to distinguish true/false
    55  * and undefined/null.
    56  *
    57  * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits
    58  * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has
    59  * to sort them out.
    60  */
    61 
    62 class JSImmediate {
    63 public:
    64     static ALWAYS_INLINE bool isImmediate(const JSValue* v)
    65     {
    66         return getTag(v) != 0;
    67     }
    68    
    69     static ALWAYS_INLINE bool isNumber(const JSValue* v)
    70     {
    71         return (getTag(v) == NumberType);
    72     }
    73    
    74     static ALWAYS_INLINE bool isPositiveNumber(const JSValue* v)
    75     {
    76         // A single mask to check for the sign bit and the number tag all at once.
    77         return (reinterpret_cast<uintptr_t>(v) & (0x80000000 | NumberType)) == NumberType;
    78     }
    79    
    80     static ALWAYS_INLINE bool isBoolean(const JSValue* v)
    81     {
    82         return (getTag(v) == BooleanType);
    83     }
    84    
    85     // Since we have room for only 3 unique tags, null and undefined have to share.
    86     static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v)
    87     {
    88         return (getTag(v) == UndefinedType);
    89     }
    90 
    91     static bool isNegative(const JSValue* v)
     36    class ExecState;
     37    class JSObject;
     38    class JSValue;
     39    class UString;
     40
     41    /*
     42     * A JSValue*  is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
     43     * signed int masquerading as a pointer). The low two bits in a JSValue* are available
     44     * for type tagging because allocator alignment guarantees they will be 00 in cell pointers.
     45     *
     46     * For example, on a 32 bit system:
     47     *
     48     * JSCell*:       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 00
     49     *               [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
     50     *
     51     * JSImmediate:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 TT
     52     *               [ high 30 bits: signed int ]       [ low 2 bits -- type tag ]
     53     *
     54     * The bit "payload" (the high 30 bits) is a 30 bit signed int for immediate numbers, a flag to distinguish true/false
     55     * and undefined/null.
     56     *
     57     * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits
     58     * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has
     59     * to sort them out.
     60     */
     61
     62    class JSImmediate {
     63    public:
     64        static ALWAYS_INLINE bool isImmediate(const JSValue* v)
     65        {
     66            return getTag(v) != 0;
     67        }
     68       
     69        static ALWAYS_INLINE bool isNumber(const JSValue* v)
     70        {
     71            return (getTag(v) == NumberType);
     72        }
     73       
     74        static ALWAYS_INLINE bool isPositiveNumber(const JSValue* v)
     75        {
     76            // A single mask to check for the sign bit and the number tag all at once.
     77            return (reinterpret_cast<uintptr_t>(v) & (0x80000000 | NumberType)) == NumberType;
     78        }
     79       
     80        static ALWAYS_INLINE bool isBoolean(const JSValue* v)
     81        {
     82            return (getTag(v) == BooleanType);
     83        }
     84       
     85        // Since we have room for only 3 unique tags, null and undefined have to share.
     86        static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v)
     87        {
     88            return (getTag(v) == UndefinedType);
     89        }
     90
     91        static bool isNegative(const JSValue* v)
     92        {
     93            ASSERT(isNumber(v));
     94            return reinterpret_cast<uintptr_t>(v) & 0x80000000;
     95        }
     96
     97        static JSValue* from(char);
     98        static JSValue* from(signed char);
     99        static JSValue* from(unsigned char);
     100        static JSValue* from(short);
     101        static JSValue* from(unsigned short);
     102        static JSValue* from(int);
     103        static JSValue* from(unsigned);
     104        static JSValue* from(long);
     105        static JSValue* from(unsigned long);
     106        static JSValue* from(long long);
     107        static JSValue* from(unsigned long long);
     108        static JSValue* from(double);
     109
     110        static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
     111        {
     112            return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType;
     113        }
     114
     115        static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2)
     116        {
     117            ASSERT(areBothImmediateNumbers(v1, v2));
     118            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2));
     119        }
     120
     121        static ALWAYS_INLINE JSValue* xorImmediateNumbers(const JSValue* v1, const JSValue* v2)
     122        {
     123            ASSERT(areBothImmediateNumbers(v1, v2));
     124            return tag(reinterpret_cast<uintptr_t>(v1) ^ reinterpret_cast<uintptr_t>(v2), NumberType);
     125        }
     126
     127        static ALWAYS_INLINE JSValue* orImmediateNumbers(const JSValue* v1, const JSValue* v2)
     128        {
     129            ASSERT(areBothImmediateNumbers(v1, v2));
     130            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2));
     131        }
     132
     133        static ALWAYS_INLINE JSValue* rightShiftImmediateNumbers(const JSValue* val, const JSValue* shift)
     134        {
     135            ASSERT(areBothImmediateNumbers(val, shift));
     136            return reinterpret_cast<JSValue*>((reinterpret_cast<intptr_t>(val) >> ((reinterpret_cast<uintptr_t>(shift) >> 2) & 0x1f)) | NumberType);
     137        }
     138
     139        static ALWAYS_INLINE bool canDoFastAdditiveOperations(const JSValue* v)
     140        {
     141            // Number is non-negative and an operation involving two of these can't overflow.
     142            // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
     143            return (reinterpret_cast<uintptr_t>(v) & (NumberType + (3 << 30))) == NumberType;
     144        }
     145
     146        static ALWAYS_INLINE JSValue* addImmediateNumbers(const JSValue* v1, const JSValue* v2)
     147        {
     148            ASSERT(canDoFastAdditiveOperations(v1));
     149            ASSERT(canDoFastAdditiveOperations(v2));
     150            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) + (reinterpret_cast<uintptr_t>(v2) & ~NumberType));
     151        }
     152
     153        static ALWAYS_INLINE JSValue* subImmediateNumbers(const JSValue* v1, const JSValue* v2)
     154        {
     155            ASSERT(canDoFastAdditiveOperations(v1));
     156            ASSERT(canDoFastAdditiveOperations(v2));
     157            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) - (reinterpret_cast<uintptr_t>(v2) & ~NumberType));
     158        }
     159
     160        static ALWAYS_INLINE JSValue* incImmediateNumber(const JSValue* v)
     161        {
     162            ASSERT(canDoFastAdditiveOperations(v));
     163            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) + TagMask + 1);
     164        }
     165
     166        static ALWAYS_INLINE JSValue* decImmediateNumber(const JSValue* v)
     167        {
     168            ASSERT(canDoFastAdditiveOperations(v));
     169            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) - (TagMask + 1));
     170        }
     171
     172        static double toDouble(const JSValue*);
     173        static bool toBoolean(const JSValue*);
     174        static JSObject* toObject(const JSValue*, ExecState*);
     175        static UString toString(const JSValue*);
     176        static uint32_t toTruncatedUInt32(const JSValue*);
     177        static JSType type(const JSValue*);
     178
     179        static bool getUInt32(const JSValue*, uint32_t&);
     180        static bool getTruncatedInt32(const JSValue*, int32_t&);
     181        static bool getTruncatedUInt32(const JSValue*, uint32_t&);
     182
     183        static int32_t getTruncatedInt32(const JSValue*);
     184
     185        static JSValue* trueImmediate();
     186        static JSValue* falseImmediate();
     187        static JSValue* undefinedImmediate();
     188        static JSValue* nullImmediate();
     189
     190        static JSValue* impossibleValue();
     191       
     192        static JSObject* prototype(const JSValue*, ExecState*);
     193
     194    private:
     195        static const uintptr_t TagMask = 3; // type tags are 2 bits long
     196
     197        // Immediate values are restricted to a 30 bit signed value.
     198        static const int minImmediateInt = -(1 << 29);
     199        static const int maxImmediateInt = (1 << 29) - 1;
     200        static const unsigned maxImmediateUInt = maxImmediateInt;
     201       
     202        static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag)
     203        {
     204            return reinterpret_cast<JSValue*>(bits | tag);
     205        }
     206       
     207        static ALWAYS_INLINE uintptr_t unTag(const JSValue* v)
     208        {
     209            return reinterpret_cast<uintptr_t>(v) & ~TagMask;
     210        }
     211       
     212        static ALWAYS_INLINE uintptr_t getTag(const JSValue* v)
     213        {
     214            return reinterpret_cast<uintptr_t>(v) & TagMask;
     215        }
     216    };
     217
     218    ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); }
     219    ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); }
     220    ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
     221    ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
     222
     223    // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
     224    ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return tag(1 << 2, 0); }
     225
     226    ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
     227    {
     228        ASSERT(isImmediate(v));
     229        uintptr_t bits = unTag(v);
     230        return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType);
     231    }
     232
     233    ALWAYS_INLINE uint32_t JSImmediate::toTruncatedUInt32(const JSValue* v)
     234    {
     235        ASSERT(isImmediate(v));
     236        return static_cast<uint32_t>(reinterpret_cast<intptr_t>(v) >> 2);
     237    }
     238
     239    ALWAYS_INLINE JSValue* JSImmediate::from(char i)
     240    {
     241        return tag(i << 2, NumberType);
     242    }
     243
     244    ALWAYS_INLINE JSValue* JSImmediate::from(signed char i)
     245    {
     246        return tag(i << 2, NumberType);
     247    }
     248
     249    ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i)
     250    {
     251        return tag(i << 2, NumberType);
     252    }
     253
     254    ALWAYS_INLINE JSValue* JSImmediate::from(short i)
     255    {
     256        return tag(i << 2, NumberType);
     257    }
     258
     259    ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i)
     260    {
     261        return tag(i << 2, NumberType);
     262    }
     263
     264    ALWAYS_INLINE JSValue* JSImmediate::from(int i)
     265    {
     266        if ((i < minImmediateInt) | (i > maxImmediateInt))
     267            return 0;
     268        return tag(i << 2, NumberType);
     269    }
     270
     271    ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i)
     272    {
     273        if (i > maxImmediateUInt)
     274            return 0;
     275        return tag(i << 2, NumberType);
     276    }
     277
     278    ALWAYS_INLINE JSValue* JSImmediate::from(long i)
     279    {
     280        if ((i < minImmediateInt) | (i > maxImmediateInt))
     281            return 0;
     282        return tag(i << 2, NumberType);
     283    }
     284
     285    ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i)
     286    {
     287        if (i > maxImmediateUInt)
     288            return 0;
     289        return tag(i << 2, NumberType);
     290    }
     291
     292    ALWAYS_INLINE JSValue* JSImmediate::from(long long i)
     293    {
     294        if ((i < minImmediateInt) | (i > maxImmediateInt))
     295            return 0;
     296        return tag(static_cast<uintptr_t>(i) << 2, NumberType);
     297    }
     298
     299    ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i)
     300    {
     301        if (i > maxImmediateUInt)
     302            return 0;
     303        return tag(static_cast<uintptr_t>(i) << 2, NumberType);
     304    }
     305
     306    ALWAYS_INLINE JSValue* JSImmediate::from(double d)
     307    {
     308        const int intVal = static_cast<int>(d);
     309
     310        if ((intVal < minImmediateInt) | (intVal > maxImmediateInt))
     311            return 0;
     312
     313        // Check for data loss from conversion to int.
     314        if ((intVal != d) || (!intVal && signbit(d)))
     315            return 0;
     316
     317        return tag(intVal << 2, NumberType);
     318    }
     319
     320    ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue* v)
    92321    {
    93322        ASSERT(isNumber(v));
    94         return reinterpret_cast<uintptr_t>(v) & 0x80000000;
    95     }
    96 
    97     static JSValue* from(char);
    98     static JSValue* from(signed char);
    99     static JSValue* from(unsigned char);
    100     static JSValue* from(short);
    101     static JSValue* from(unsigned short);
    102     static JSValue* from(int);
    103     static JSValue* from(unsigned);
    104     static JSValue* from(long);
    105     static JSValue* from(unsigned long);
    106     static JSValue* from(long long);
    107     static JSValue* from(unsigned long long);
    108     static JSValue* from(double);
    109 
    110     static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
    111     {
    112         return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType;
    113     }
    114 
    115     static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2)
    116     {
    117         ASSERT(areBothImmediateNumbers(v1, v2));
    118         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2));
    119     }
    120 
    121     static ALWAYS_INLINE JSValue* xorImmediateNumbers(const JSValue* v1, const JSValue* v2)
    122     {
    123         ASSERT(areBothImmediateNumbers(v1, v2));
    124         return tag(reinterpret_cast<uintptr_t>(v1) ^ reinterpret_cast<uintptr_t>(v2), NumberType);
    125     }
    126 
    127     static ALWAYS_INLINE JSValue* orImmediateNumbers(const JSValue* v1, const JSValue* v2)
    128     {
    129         ASSERT(areBothImmediateNumbers(v1, v2));
    130         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2));
    131     }
    132 
    133     static ALWAYS_INLINE JSValue* rightShiftImmediateNumbers(const JSValue* val, const JSValue* shift)
    134     {
    135         ASSERT(areBothImmediateNumbers(val, shift));
    136         return reinterpret_cast<JSValue*>((reinterpret_cast<intptr_t>(val) >> ((reinterpret_cast<uintptr_t>(shift) >> 2) & 0x1f)) | NumberType);
    137     }
    138 
    139     static ALWAYS_INLINE bool canDoFastAdditiveOperations(const JSValue* v)
    140     {
    141         // Number is non-negative and an operation involving two of these can't overflow.
    142         // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
    143         return (reinterpret_cast<uintptr_t>(v) & (NumberType + (3 << 30))) == NumberType;
    144     }
    145 
    146     static ALWAYS_INLINE JSValue* addImmediateNumbers(const JSValue* v1, const JSValue* v2)
    147     {
    148         ASSERT(canDoFastAdditiveOperations(v1));
    149         ASSERT(canDoFastAdditiveOperations(v2));
    150         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) + (reinterpret_cast<uintptr_t>(v2) & ~NumberType));
    151     }
    152 
    153     static ALWAYS_INLINE JSValue* subImmediateNumbers(const JSValue* v1, const JSValue* v2)
    154     {
    155         ASSERT(canDoFastAdditiveOperations(v1));
    156         ASSERT(canDoFastAdditiveOperations(v2));
    157         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) - (reinterpret_cast<uintptr_t>(v2) & ~NumberType));
    158     }
    159 
    160     static ALWAYS_INLINE JSValue* incImmediateNumber(const JSValue* v)
    161     {
    162         ASSERT(canDoFastAdditiveOperations(v));
    163         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) + TagMask + 1);
    164     }
    165 
    166     static ALWAYS_INLINE JSValue* decImmediateNumber(const JSValue* v)
    167     {
    168         ASSERT(canDoFastAdditiveOperations(v));
    169         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) - (TagMask + 1));
    170     }
    171 
    172     static double toDouble(const JSValue*);
    173     static bool toBoolean(const JSValue*);
    174     static JSObject* toObject(const JSValue*, ExecState*);
    175     static UString toString(const JSValue*);
    176     static uint32_t toTruncatedUInt32(const JSValue*);
    177     static JSType type(const JSValue*);
    178 
    179     static bool getUInt32(const JSValue*, uint32_t&);
    180     static bool getTruncatedInt32(const JSValue*, int32_t&);
    181     static bool getTruncatedUInt32(const JSValue*, uint32_t&);
    182 
    183     static int32_t getTruncatedInt32(const JSValue*);
    184 
    185     static JSValue* trueImmediate();
    186     static JSValue* falseImmediate();
    187     static JSValue* undefinedImmediate();
    188     static JSValue* nullImmediate();
    189 
    190     static JSValue* impossibleValue();
    191    
    192     static JSObject* prototype(const JSValue*, ExecState*);
    193 
    194 private:
    195     static const uintptr_t TagMask = 3; // type tags are 2 bits long
    196 
    197     // Immediate values are restricted to a 30 bit signed value.
    198     static const int minImmediateInt = -(1 << 29);
    199     static const int maxImmediateInt = (1 << 29) - 1;
    200     static const unsigned maxImmediateUInt = maxImmediateInt;
    201    
    202     static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag)
    203     {
    204         return reinterpret_cast<JSValue*>(bits | tag);
    205     }
    206    
    207     static ALWAYS_INLINE uintptr_t unTag(const JSValue* v)
    208     {
    209         return reinterpret_cast<uintptr_t>(v) & ~TagMask;
    210     }
    211    
    212     static ALWAYS_INLINE uintptr_t getTag(const JSValue* v)
    213     {
    214         return reinterpret_cast<uintptr_t>(v) & TagMask;
    215     }
    216 };
    217 
    218 ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); }
    219 ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); }
    220 ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
    221 ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
    222 
    223 // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
    224 ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return tag(1 << 2, 0); }
    225 
    226 ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
    227 {
    228     ASSERT(isImmediate(v));
    229     uintptr_t bits = unTag(v);
    230     return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType);
    231 }
    232 
    233 ALWAYS_INLINE uint32_t JSImmediate::toTruncatedUInt32(const JSValue* v)
    234 {
    235     ASSERT(isImmediate(v));
    236     return static_cast<uint32_t>(reinterpret_cast<intptr_t>(v) >> 2);
    237 }
    238 
    239 ALWAYS_INLINE JSValue* JSImmediate::from(char i)
    240 {
    241     return tag(i << 2, NumberType);
    242 }
    243 
    244 ALWAYS_INLINE JSValue* JSImmediate::from(signed char i)
    245 {
    246     return tag(i << 2, NumberType);
    247 }
    248 
    249 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i)
    250 {
    251     return tag(i << 2, NumberType);
    252 }
    253 
    254 ALWAYS_INLINE JSValue* JSImmediate::from(short i)
    255 {
    256     return tag(i << 2, NumberType);
    257 }
    258 
    259 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i)
    260 {
    261     return tag(i << 2, NumberType);
    262 }
    263 
    264 ALWAYS_INLINE JSValue* JSImmediate::from(int i)
    265 {
    266     if ((i < minImmediateInt) | (i > maxImmediateInt))
    267         return 0;
    268     return tag(i << 2, NumberType);
    269 }
    270 
    271 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i)
    272 {
    273     if (i > maxImmediateUInt)
    274         return 0;
    275     return tag(i << 2, NumberType);
    276 }
    277 
    278 ALWAYS_INLINE JSValue* JSImmediate::from(long i)
    279 {
    280     if ((i < minImmediateInt) | (i > maxImmediateInt))
    281         return 0;
    282     return tag(i << 2, NumberType);
    283 }
    284 
    285 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i)
    286 {
    287     if (i > maxImmediateUInt)
    288         return 0;
    289     return tag(i << 2, NumberType);
    290 }
    291 
    292 ALWAYS_INLINE JSValue* JSImmediate::from(long long i)
    293 {
    294     if ((i < minImmediateInt) | (i > maxImmediateInt))
    295         return 0;
    296     return tag(static_cast<uintptr_t>(i) << 2, NumberType);
    297 }
    298 
    299 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i)
    300 {
    301     if (i > maxImmediateUInt)
    302         return 0;
    303     return tag(static_cast<uintptr_t>(i) << 2, NumberType);
    304 }
    305 
    306 ALWAYS_INLINE JSValue* JSImmediate::from(double d)
    307 {
    308     const int intVal = static_cast<int>(d);
    309 
    310     if ((intVal < minImmediateInt) | (intVal > maxImmediateInt))
    311         return 0;
    312 
    313     // Check for data loss from conversion to int.
    314     if ((intVal != d) || (!intVal && signbit(d)))
    315         return 0;
    316 
    317     return tag(intVal << 2, NumberType);
    318 }
    319 
    320 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue* v)
    321 {
    322     ASSERT(isNumber(v));
    323     return static_cast<int32_t>(unTag(v)) >> 2;
    324 }
    325 
    326 ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v)
    327 {
    328     ASSERT(isImmediate(v));
    329     const int32_t i = static_cast<int32_t>(unTag(v)) >> 2;
    330     if (JSImmediate::getTag(v) == UndefinedType && i)
    331         return std::numeric_limits<double>::quiet_NaN();
    332     return i;
    333 }
    334 
    335 ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i)
    336 {
    337     i = static_cast<uintptr_t>(unTag(v)) >> 2;
    338     return isPositiveNumber(v);
    339 }
    340 
    341 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i)
    342 {
    343     i = static_cast<int32_t>(unTag(v)) >> 2;
    344     return isNumber(v);
    345 }
    346 
    347 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i)
    348 {
    349     return getUInt32(v, i);
    350 }
    351 
    352 ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v)
    353 {
    354     ASSERT(isImmediate(v));
    355    
    356     uintptr_t tag = getTag(v);
    357     if (tag == UndefinedType)
    358         return v == undefinedImmediate() ? UndefinedType : NullType;
    359     return static_cast<JSType>(tag);
    360 }
    361 
    362 ALWAYS_INLINE JSValue* jsUndefined()
    363 {
    364     return JSImmediate::undefinedImmediate();
    365 }
    366 
    367 inline JSValue* jsNull()
    368 {
    369     return JSImmediate::nullImmediate();
    370 }
    371 
    372 inline JSValue* jsBoolean(bool b)
    373 {
    374     return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
    375 }
     323        return static_cast<int32_t>(unTag(v)) >> 2;
     324    }
     325
     326    ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v)
     327    {
     328        ASSERT(isImmediate(v));
     329        const int32_t i = static_cast<int32_t>(unTag(v)) >> 2;
     330        if (JSImmediate::getTag(v) == UndefinedType && i)
     331            return std::numeric_limits<double>::quiet_NaN();
     332        return i;
     333    }
     334
     335    ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i)
     336    {
     337        i = static_cast<uintptr_t>(unTag(v)) >> 2;
     338        return isPositiveNumber(v);
     339    }
     340
     341    ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i)
     342    {
     343        i = static_cast<int32_t>(unTag(v)) >> 2;
     344        return isNumber(v);
     345    }
     346
     347    ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i)
     348    {
     349        return getUInt32(v, i);
     350    }
     351
     352    ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v)
     353    {
     354        ASSERT(isImmediate(v));
     355       
     356        uintptr_t tag = getTag(v);
     357        if (tag == UndefinedType)
     358            return v == undefinedImmediate() ? UndefinedType : NullType;
     359        return static_cast<JSType>(tag);
     360    }
     361
     362    ALWAYS_INLINE JSValue* jsUndefined()
     363    {
     364        return JSImmediate::undefinedImmediate();
     365    }
     366
     367    inline JSValue* jsNull()
     368    {
     369        return JSImmediate::nullImmediate();
     370    }
     371
     372    inline JSValue* jsBoolean(bool b)
     373    {
     374        return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
     375    }
    376376
    377377} // namespace KJS
Note: See TracChangeset for help on using the changeset viewer.