Show
Ignore:
Timestamp:
08/18/08 11:14:49 (5 months ago)
Author:
odole
Message:

merge with webkit revision 35814

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/JavaScriptCore/kjs/JSImmediate.h

    r418 r440  
    2828#include <wtf/MathExtras.h> 
    2929#include <limits> 
     30#include <limits.h> 
    3031#include <stdarg.h> 
    3132#include <stdint.h> 
     
    4142    /* 
    4243     * 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. 
     44     * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging 
     45     * because allocator alignment guarantees they will be 00 in cell pointers. 
    4546     * 
    4647     * For example, on a 32 bit system: 
    4748     * 
    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. 
     49     * JSCell*:             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     00 
     50     *                      [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ] 
     51     * JSImmediate:         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     TT 
     52     *                      [ high 30 bits: 'payload' ]             [ low 2 bits -- tag ] 
     53     * 
     54     * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed 
     55     * integer, or they mark the value as being an immediate of a type other than integer, with a secondary 
     56     * tag used to indicate the exact type. 
     57     * 
     58     * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value. 
     59     * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next 
     60     * two bits will form an extended tag. 
     61     * 
     62     * 31 bit signed int:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     X1 
     63     *                      [ high 30 bits of the value ]      [ high bit part of value ] 
     64     * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      ZZ               10 
     65     *                      [ extended 'payload' ]  [  extended tag  ]  [  tag 'other'  ] 
     66     * 
     67     * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following 
     68     * bit would flag the value as undefined.  If neither bits are set, the value is null. 
     69     * 
     70     * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      UB               10 
     71     *                      [ extended 'payload' ]  [ undefined | bool ]  [ tag 'other' ] 
     72     * 
     73     * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero. 
     74     * For undefined or null immediates the payload is zero. 
     75     * 
     76     * Boolean:             000000000000000000000000000V      01               10 
     77     *                      [ boolean value ]              [ bool ]       [ tag 'other' ] 
     78     * Undefined:           0000000000000000000000000000      10               10 
     79     *                      [ zero ]                    [ undefined ]     [ tag 'other' ] 
     80     * Null:                0000000000000000000000000000      00               10 
     81     *                      [ zero ]                       [ zero ]       [ tag 'other' ] 
    6082     */ 
    6183 
    6284    class JSImmediate { 
     85        static const uintptr_t TagMask           = 0x3u; // primary tag is 2 bits long 
     86        static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates int, this dominates the following bit 
     87        static const uintptr_t TagBitTypeOther   = 0x2u; // second bit set indicates immediate other than an integer 
     88 
     89        static const uintptr_t ExtendedTagMask         = 0xCu; // extended tag holds a further two bits 
     90        static const uintptr_t ExtendedTagBitBool      = 0x4u; 
     91        static const uintptr_t ExtendedTagBitUndefined = 0x8u; 
     92 
     93        static const uintptr_t FullTagTypeMask      = TagMask | ExtendedTagMask; 
     94        static const uintptr_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool; 
     95        static const uintptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined; 
     96        static const uintptr_t FullTagTypeNull      = TagBitTypeOther; 
     97 
     98        static const uint32_t IntegerPayloadShift  = 1u; 
     99        static const uint32_t ExtendedPayloadShift = 4u; 
     100 
     101        static const uintptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift; 
     102  
    63103    public: 
    64104        static ALWAYS_INLINE bool isImmediate(const JSValue* v) 
    65105        { 
    66             return getTag(v) != 0
     106            return (reinterpret_cast<uintptr_t>(v) & TagMask)
    67107        } 
    68108         
    69109        static ALWAYS_INLINE bool isNumber(const JSValue* v) 
    70110        { 
    71             return (getTag(v) == NumberType); 
     111            return (reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger); 
    72112        } 
    73113 
     
    75115        { 
    76116            // 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
     117            return (reinterpret_cast<uintptr_t>(v) & (0x80000000 | TagBitTypeInteger)) == TagBitTypeInteger
    78118        } 
    79119         
    80120        static ALWAYS_INLINE bool isBoolean(const JSValue* v) 
    81121        { 
    82             return (getTag(v) == BooleanType); 
    83         } 
    84          
    85         // Since we have room for only 3 unique tags, null and undefined have to share. 
     122            return ((reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool); 
     123        } 
     124         
    86125        static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v) 
    87126        { 
    88             return (getTag(v) == UndefinedType); 
     127            // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. 
     128            return ((reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull); 
    89129        } 
    90130 
     
    110150        static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2) 
    111151        { 
    112             return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType
     152            return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger)
    113153        } 
    114154 
     
    122162        { 
    123163            ASSERT(areBothImmediateNumbers(v1, v2)); 
    124             return tag(reinterpret_cast<uintptr_t>(v1) ^ reinterpret_cast<uintptr_t>(v2), NumberType); 
     164            return reinterpret_cast<JSValue*>((reinterpret_cast<uintptr_t>(v1) ^ reinterpret_cast<uintptr_t>(v2)) | TagBitTypeInteger); 
    125165        } 
    126166 
     
    134174        { 
    135175            ASSERT(areBothImmediateNumbers(val, shift)); 
    136             return reinterpret_cast<JSValue*>((reinterpret_cast<intptr_t>(val) >> ((reinterpret_cast<uintptr_t>(shift) >> 2) & 0x1f)) | NumberType); 
     176            return reinterpret_cast<JSValue*>((reinterpret_cast<intptr_t>(val) >> ((reinterpret_cast<uintptr_t>(shift) >> IntegerPayloadShift) & 0x1f)) | TagBitTypeInteger); 
    137177        } 
    138178 
     
    141181            // Number is non-negative and an operation involving two of these can't overflow. 
    142182            // 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
     183            return (reinterpret_cast<uintptr_t>(v) & (TagBitTypeInteger + (3u << 30))) == TagBitTypeInteger
    144184        } 
    145185 
     
    148188            ASSERT(canDoFastAdditiveOperations(v1)); 
    149189            ASSERT(canDoFastAdditiveOperations(v2)); 
    150             return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) + (reinterpret_cast<uintptr_t>(v2) & ~NumberType)); 
     190            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) + reinterpret_cast<uintptr_t>(v2) - TagBitTypeInteger); 
    151191        } 
    152192 
     
    155195            ASSERT(canDoFastAdditiveOperations(v1)); 
    156196            ASSERT(canDoFastAdditiveOperations(v2)); 
    157             return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) - (reinterpret_cast<uintptr_t>(v2) & ~NumberType)); 
     197            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) - reinterpret_cast<uintptr_t>(v2) + TagBitTypeInteger); 
    158198        } 
    159199 
     
    161201        { 
    162202            ASSERT(canDoFastAdditiveOperations(v)); 
    163             return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) + TagMask + 1); 
     203            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) + (1 << IntegerPayloadShift)); 
    164204        } 
    165205 
     
    167207        { 
    168208            ASSERT(canDoFastAdditiveOperations(v)); 
    169             return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) - (TagMask + 1)); 
     209            return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) - (1 << IntegerPayloadShift)); 
    170210        } 
    171211 
     
    193233 
    194234    private: 
    195         static const uintptr_t TagMask = 3; // type tags are 2 bits long 
    196  
    197235        // 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
     236        static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift
     237        static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift
    200238        static const unsigned maxImmediateUInt = maxImmediateInt; 
    201239         
    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; 
     240        static ALWAYS_INLINE JSValue* makeInt(int32_t value) 
     241        { 
     242            return reinterpret_cast<JSValue*>((value << IntegerPayloadShift) | TagBitTypeInteger); 
     243        } 
     244         
     245        static ALWAYS_INLINE JSValue* makeBool(bool b) 
     246        { 
     247            return reinterpret_cast<JSValue*>((static_cast<uintptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool); 
     248        } 
     249         
     250        static ALWAYS_INLINE JSValue* makeUndefined() 
     251        { 
     252            return reinterpret_cast<JSValue*>(FullTagTypeUndefined); 
     253        } 
     254         
     255        static ALWAYS_INLINE JSValue* makeNull() 
     256        { 
     257            return reinterpret_cast<JSValue*>(FullTagTypeNull); 
     258        } 
     259         
     260        static ALWAYS_INLINE int32_t intValue(const JSValue* v) 
     261        { 
     262            return static_cast<int32_t>(reinterpret_cast<intptr_t>(v) >> IntegerPayloadShift); 
     263        } 
     264         
     265        static ALWAYS_INLINE uint32_t uintValue(const JSValue* v) 
     266        { 
     267            return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift); 
     268        } 
     269         
     270        static ALWAYS_INLINE bool boolValue(const JSValue* v) 
     271        { 
     272            return (rawValue(v) & ExtendedPayloadBitBoolValue) != 0; 
     273        } 
     274         
     275        static ALWAYS_INLINE uintptr_t rawValue(const JSValue* v) 
     276        { 
     277            return reinterpret_cast<uintptr_t>(v); 
    215278        } 
    216279    }; 
    217280 
    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); } 
     281    ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return makeBool(true); } 
     282    ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return makeBool(false); } 
     283    ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return makeUndefined(); } 
     284    ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return makeNull(); } 
    222285 
    223286    // 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); } 
     287    ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return reinterpret_cast<JSValue*>(0x4); } 
    225288 
    226289    ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v) 
    227290    { 
    228291        ASSERT(isImmediate(v)); 
    229         uintptr_t bits = unTag(v); 
    230         return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType); 
     292        uintptr_t bits = rawValue(v); 
     293        return 
     294            (bits & TagBitTypeInteger) ? (bits != TagBitTypeInteger) : // !0 ints 
     295            (bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue)); // bool true 
    231296    } 
    232297 
    233298    ALWAYS_INLINE uint32_t JSImmediate::toTruncatedUInt32(const JSValue* v) 
    234299    { 
    235         ASSERT(isImmediate(v)); 
    236         return static_cast<uint32_t>(reinterpret_cast<intptr_t>(v) >> 2); 
     300        ASSERT(isNumber(v)); 
     301        return intValue(v); 
    237302    } 
    238303 
    239304    ALWAYS_INLINE JSValue* JSImmediate::from(char i) 
    240305    { 
    241         return tag(i << 2, NumberType); 
     306        return makeInt(i); 
    242307    } 
    243308 
    244309    ALWAYS_INLINE JSValue* JSImmediate::from(signed char i) 
    245310    { 
    246         return tag(i << 2, NumberType); 
     311        return makeInt(i); 
    247312    } 
    248313 
    249314    ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i) 
    250315    { 
    251         return tag(i << 2, NumberType); 
     316        return makeInt(i); 
    252317    } 
    253318 
    254319    ALWAYS_INLINE JSValue* JSImmediate::from(short i) 
    255320    { 
    256         return tag(i << 2, NumberType); 
     321        return makeInt(i); 
    257322    } 
    258323 
    259324    ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i) 
    260325    { 
    261         return tag(i << 2, NumberType); 
     326        return makeInt(i); 
    262327    } 
    263328 
     
    266331        if ((i < minImmediateInt) | (i > maxImmediateInt)) 
    267332            return 0; 
    268         return tag(i << 2, NumberType); 
     333        return makeInt(i); 
    269334    } 
    270335 
     
    273338        if (i > maxImmediateUInt) 
    274339            return 0; 
    275         return tag(i << 2, NumberType); 
     340        return makeInt(i); 
    276341    } 
    277342 
     
    280345        if ((i < minImmediateInt) | (i > maxImmediateInt)) 
    281346            return 0; 
    282         return tag(i << 2, NumberType); 
     347        return makeInt(i); 
    283348    } 
    284349 
     
    287352        if (i > maxImmediateUInt) 
    288353            return 0; 
    289         return tag(i << 2, NumberType); 
     354        return makeInt(i); 
    290355    } 
    291356 
     
    294359        if ((i < minImmediateInt) | (i > maxImmediateInt)) 
    295360            return 0; 
    296         return tag(static_cast<uintptr_t>(i) << 2, NumberType); 
     361        return makeInt(static_cast<uintptr_t>(i)); 
    297362    } 
    298363 
     
    301366        if (i > maxImmediateUInt) 
    302367            return 0; 
    303         return tag(static_cast<uintptr_t>(i) << 2, NumberType); 
     368        return makeInt(static_cast<uintptr_t>(i)); 
    304369    } 
    305370 
     
    315380            return 0; 
    316381 
    317         return tag(intVal << 2, NumberType); 
     382        return makeInt(intVal); 
    318383    } 
    319384 
     
    321386    { 
    322387        ASSERT(isNumber(v)); 
    323         return static_cast<int32_t>(unTag(v)) >> 2
     388        return intValue(v)
    324389    } 
    325390 
     
    327392    { 
    328393        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; 
     394        if (isNumber(v)) 
     395            return intValue(v); 
     396        if (rawValue(v) == (FullTagTypeBool | ExtendedPayloadBitBoolValue)) 
     397            return 1.0; 
     398        if (rawValue(v) != FullTagTypeUndefined) 
     399            return 0.0; 
     400        return std::numeric_limits<double>::quiet_NaN(); 
    333401    } 
    334402 
    335403    ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i) 
    336404    { 
    337         i = static_cast<uintptr_t>(unTag(v)) >> 2
     405        i = uintValue(v)
    338406        return isPositiveNumber(v); 
    339407    } 
     
    341409    ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i) 
    342410    { 
    343         i = static_cast<int32_t>(unTag(v)) >> 2
     411        i = intValue(v)
    344412        return isNumber(v); 
    345413    } 
     
    354422        ASSERT(isImmediate(v)); 
    355423         
    356         uintptr_t tag = getTag(v); 
    357         if (tag == UndefinedType) 
    358             return v == undefinedImmediate() ? UndefinedType : NullType; 
    359         return static_cast<JSType>(tag); 
     424        if (isNumber(v)) 
     425            return NumberType; 
     426        if (isBoolean(v)) 
     427            return BooleanType; 
     428        if (v != undefinedImmediate()) 
     429            return NullType; 
     430        return UndefinedType; 
    360431    } 
    361432