Ignore:
Timestamp:
Jul 24, 2013, 9:03:27 PM (12 years ago)
Author:
[email protected]
Message:

fourthTier: Re-indent JSString.h to aid mhe merging of the FTL branch

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSString.h

    r153225 r153239  
    3232namespace JSC {
    3333
    34 class JSString;
    35 class JSRopeString;
    36 class LLIntOffsetsExtractor;
    37 
    38 JSString* jsEmptyString(VM*);
    39 JSString* jsEmptyString(ExecState*);
    40 JSString* jsString(VM*, const String&); // returns empty string if passed null string
    41 JSString* jsString(ExecState*, const String&); // returns empty string if passed null string
    42 
    43 JSString* jsSingleCharacterString(VM*, UChar);
    44 JSString* jsSingleCharacterString(ExecState*, UChar);
    45 JSString* jsSingleCharacterSubstring(ExecState*, const String&, unsigned offset);
    46 JSString* jsSubstring(VM*, const String&, unsigned offset, unsigned length);
    47 JSString* jsSubstring(ExecState*, const String&, unsigned offset, unsigned length);
    48 
    49 // Non-trivial strings are two or more characters long.
    50 // These functions are faster than just calling jsString.
    51 JSString* jsNontrivialString(VM*, const String&);
    52 JSString* jsNontrivialString(ExecState*, const String&);
    53 
    54 // Should be used for strings that are owned by an object that will
    55 // likely outlive the JSValue this makes, such as the parse tree or a
    56 // DOM object that contains a String
    57 JSString* jsOwnedString(VM*, const String&);
    58 JSString* jsOwnedString(ExecState*, const String&);
    59 
    60 JSRopeString* jsStringBuilder(VM*);
    61 
    62 class JSString : public JSCell {
    63 public:
    64     friend class JIT;
    65     friend class VM;
    66     friend class SpecializedThunkJIT;
    67     friend class JSRopeString;
    68     friend class MarkStack;
    69     friend class SlotVisitor;
    70     friend struct ThunkHelpers;
    71 
    72     typedef JSCell Base;
    73 
    74     static const bool needsDestruction = true;
    75     static const bool hasImmortalStructure = true;
    76     static void destroy(JSCell*);
    77 
    78 private:
    79     JSString(VM& vm, PassRefPtr<StringImpl> value)
    80         : JSCell(vm, vm.stringStructure.get())
    81         , m_flags(0)
    82         , m_value(value)
    83     {
    84     }
    85 
    86     JSString(VM& vm)
    87         : JSCell(vm, vm.stringStructure.get())
    88         , m_flags(0)
    89     {
    90     }
    91 
    92     void finishCreation(VM& vm, size_t length)
    93     {
    94         ASSERT(!m_value.isNull());
    95         Base::finishCreation(vm);
    96         m_length = length;
    97         setIs8Bit(m_value.impl()->is8Bit());
    98         vm.m_newStringsSinceLastHashCons++;
    99     }
    100 
    101     void finishCreation(VM& vm, size_t length, size_t cost)
    102     {
    103         ASSERT(!m_value.isNull());
    104         Base::finishCreation(vm);
    105         m_length = length;
    106         setIs8Bit(m_value.impl()->is8Bit());
    107         Heap::heap(this)->reportExtraMemoryCost(cost);
    108         vm.m_newStringsSinceLastHashCons++;
    109     }
    110 
    111 protected:
    112     void finishCreation(VM& vm)
    113     {
    114         Base::finishCreation(vm);
    115         m_length = 0;
    116         setIs8Bit(true);
    117         vm.m_newStringsSinceLastHashCons++;
    118     }
    119        
    120 public:
    121     static JSString* create(VM& vm, PassRefPtr<StringImpl> value)
    122     {
    123         ASSERT(value);
    124         size_t length = value->length();
    125         size_t cost = value->cost();
    126         JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value);
    127         newString->finishCreation(vm, length, cost);
    128         return newString;
    129     }
    130     static JSString* createHasOtherOwner(VM& vm, PassRefPtr<StringImpl> value)
    131     {
    132         ASSERT(value);
    133         size_t length = value->length();
    134         JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value);
    135         newString->finishCreation(vm, length);
    136         return newString;
    137     }
    138 
    139     const String& value(ExecState*) const;
    140     const String& tryGetValue() const;
    141     const StringImpl* tryGetValueImpl() const;
    142     unsigned length() { return m_length; }
    143 
    144     JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
    145     JS_EXPORT_PRIVATE bool toBoolean() const;
    146     bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
    147     JSObject* toObject(ExecState*, JSGlobalObject*) const;
    148     double toNumber(ExecState*) const;
    149        
    150     bool getStringPropertySlot(ExecState*, PropertyName, PropertySlot&);
    151     bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
    152     bool getStringPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&);
    153 
    154     bool canGetIndex(unsigned i) { return i < m_length; }
    155     JSString* getIndex(ExecState*, unsigned);
    156 
    157     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
    158     {
    159         return Structure::create(vm, globalObject, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero), &s_info);
    160     }
    161 
    162     static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); }
    163     static size_t offsetOfFlags() { return OBJECT_OFFSETOF(JSString, m_flags); }
    164     static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); }
    165 
    166     static JS_EXPORTDATA const ClassInfo s_info;
    167 
    168     static void visitChildren(JSCell*, SlotVisitor&);
    169 
    170     enum {
    171         HashConsLock = 1u << 2,
    172         IsHashConsSingleton = 1u << 1,
    173         Is8Bit = 1u
     34    class JSString;
     35    class JSRopeString;
     36    class LLIntOffsetsExtractor;
     37
     38    JSString* jsEmptyString(VM*);
     39    JSString* jsEmptyString(ExecState*);
     40    JSString* jsString(VM*, const String&); // returns empty string if passed null string
     41    JSString* jsString(ExecState*, const String&); // returns empty string if passed null string
     42
     43    JSString* jsSingleCharacterString(VM*, UChar);
     44    JSString* jsSingleCharacterString(ExecState*, UChar);
     45    JSString* jsSingleCharacterSubstring(ExecState*, const String&, unsigned offset);
     46    JSString* jsSubstring(VM*, const String&, unsigned offset, unsigned length);
     47    JSString* jsSubstring(ExecState*, const String&, unsigned offset, unsigned length);
     48
     49    // Non-trivial strings are two or more characters long.
     50    // These functions are faster than just calling jsString.
     51    JSString* jsNontrivialString(VM*, const String&);
     52    JSString* jsNontrivialString(ExecState*, const String&);
     53
     54    // Should be used for strings that are owned by an object that will
     55    // likely outlive the JSValue this makes, such as the parse tree or a
     56    // DOM object that contains a String
     57    JSString* jsOwnedString(VM*, const String&);
     58    JSString* jsOwnedString(ExecState*, const String&);
     59
     60    JSRopeString* jsStringBuilder(VM*);
     61
     62    class JSString : public JSCell {
     63    public:
     64        friend class JIT;
     65        friend class VM;
     66        friend class SpecializedThunkJIT;
     67        friend class JSRopeString;
     68        friend class MarkStack;
     69        friend class SlotVisitor;
     70        friend struct ThunkHelpers;
     71
     72        typedef JSCell Base;
     73
     74        static const bool needsDestruction = true;
     75        static const bool hasImmortalStructure = true;
     76        static void destroy(JSCell*);
     77
     78    private:
     79        JSString(VM& vm, PassRefPtr<StringImpl> value)
     80            : JSCell(vm, vm.stringStructure.get())
     81            , m_flags(0)
     82            , m_value(value)
     83        {
     84        }
     85
     86        JSString(VM& vm)
     87            : JSCell(vm, vm.stringStructure.get())
     88            , m_flags(0)
     89        {
     90        }
     91
     92        void finishCreation(VM& vm, size_t length)
     93        {
     94            ASSERT(!m_value.isNull());
     95            Base::finishCreation(vm);
     96            m_length = length;
     97            setIs8Bit(m_value.impl()->is8Bit());
     98            vm.m_newStringsSinceLastHashCons++;
     99        }
     100
     101        void finishCreation(VM& vm, size_t length, size_t cost)
     102        {
     103            ASSERT(!m_value.isNull());
     104            Base::finishCreation(vm);
     105            m_length = length;
     106            setIs8Bit(m_value.impl()->is8Bit());
     107            Heap::heap(this)->reportExtraMemoryCost(cost);
     108            vm.m_newStringsSinceLastHashCons++;
     109        }
     110
     111    protected:
     112        void finishCreation(VM& vm)
     113        {
     114            Base::finishCreation(vm);
     115            m_length = 0;
     116            setIs8Bit(true);
     117            vm.m_newStringsSinceLastHashCons++;
     118        }
     119           
     120    public:
     121        static JSString* create(VM& vm, PassRefPtr<StringImpl> value)
     122        {
     123            ASSERT(value);
     124            size_t length = value->length();
     125            size_t cost = value->cost();
     126            JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value);
     127            newString->finishCreation(vm, length, cost);
     128            return newString;
     129        }
     130        static JSString* createHasOtherOwner(VM& vm, PassRefPtr<StringImpl> value)
     131        {
     132            ASSERT(value);
     133            size_t length = value->length();
     134            JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value);
     135            newString->finishCreation(vm, length);
     136            return newString;
     137        }
     138
     139        const String& value(ExecState*) const;
     140        const String& tryGetValue() const;
     141        const StringImpl* tryGetValueImpl() const;
     142        unsigned length() { return m_length; }
     143
     144        JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
     145        JS_EXPORT_PRIVATE bool toBoolean() const;
     146        bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
     147        JSObject* toObject(ExecState*, JSGlobalObject*) const;
     148        double toNumber(ExecState*) const;
     149           
     150        bool getStringPropertySlot(ExecState*, PropertyName, PropertySlot&);
     151        bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     152        bool getStringPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&);
     153
     154        bool canGetIndex(unsigned i) { return i < m_length; }
     155        JSString* getIndex(ExecState*, unsigned);
     156
     157        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
     158        {
     159            return Structure::create(vm, globalObject, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero), &s_info);
     160        }
     161
     162        static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); }
     163        static size_t offsetOfFlags() { return OBJECT_OFFSETOF(JSString, m_flags); }
     164        static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); }
     165
     166        static JS_EXPORTDATA const ClassInfo s_info;
     167
     168        static void visitChildren(JSCell*, SlotVisitor&);
     169
     170        enum {
     171            HashConsLock = 1u << 2,
     172            IsHashConsSingleton = 1u << 1,
     173            Is8Bit = 1u
     174        };
     175
     176    protected:
     177        friend class JSValue;
     178           
     179        bool isRope() const { return m_value.isNull(); }
     180        bool is8Bit() const { return m_flags & Is8Bit; }
     181        void setIs8Bit(bool flag)
     182        {
     183            if (flag)
     184                m_flags |= Is8Bit;
     185            else
     186                m_flags &= ~Is8Bit;
     187        }
     188        bool shouldTryHashCons();
     189        bool isHashConsSingleton() const { return m_flags & IsHashConsSingleton; }
     190        void clearHashConsSingleton() { m_flags &= ~IsHashConsSingleton; }
     191        void setHashConsSingleton() { m_flags |= IsHashConsSingleton; }
     192        bool tryHashConsLock();
     193        void releaseHashConsLock();
     194
     195        unsigned m_flags;
     196           
     197        // A string is represented either by a String or a rope of fibers.
     198        unsigned m_length;
     199        mutable String m_value;
     200
     201    private:
     202        friend class LLIntOffsetsExtractor;
     203           
     204        static JSValue toThis(JSCell*, ExecState*, ECMAMode);
     205
     206        // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
     207        static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
     208        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
     209
     210        String& string() { ASSERT(!isRope()); return m_value; }
     211
     212        friend JSValue jsString(ExecState*, JSString*, JSString*);
     213        friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length);
    174214    };
    175215
    176 protected:
    177     friend class JSValue;
    178        
    179     bool isRope() const { return m_value.isNull(); }
    180     bool is8Bit() const { return m_flags & Is8Bit; }
    181     void setIs8Bit(bool flag)
    182     {
    183         if (flag)
    184             m_flags |= Is8Bit;
    185         else
    186             m_flags &= ~Is8Bit;
    187     }
    188     bool shouldTryHashCons();
    189     bool isHashConsSingleton() const { return m_flags & IsHashConsSingleton; }
    190     void clearHashConsSingleton() { m_flags &= ~IsHashConsSingleton; }
    191     void setHashConsSingleton() { m_flags |= IsHashConsSingleton; }
    192     bool tryHashConsLock();
    193     void releaseHashConsLock();
    194 
    195     unsigned m_flags;
    196        
    197     // A string is represented either by a String or a rope of fibers.
    198     unsigned m_length;
    199     mutable String m_value;
    200 
    201 private:
    202     friend class LLIntOffsetsExtractor;
    203        
    204     static JSValue toThis(JSCell*, ExecState*, ECMAMode);
    205 
    206     // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
    207     static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
    208     static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
    209 
    210     String& string() { ASSERT(!isRope()); return m_value; }
    211 
    212     friend JSValue jsString(ExecState*, JSString*, JSString*);
    213     friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length);
    214 };
    215 
    216 class JSRopeString : public JSString {
    217     friend class JSString;
    218 
    219     friend JSRopeString* jsStringBuilder(VM*);
    220 
    221     class RopeBuilder {
     216    class JSRopeString : public JSString {
     217        friend class JSString;
     218
     219        friend JSRopeString* jsStringBuilder(VM*);
     220
     221        class RopeBuilder {
     222        public:
     223            RopeBuilder(VM& vm)
     224                : m_vm(vm)
     225                , m_jsString(jsStringBuilder(&vm))
     226                , m_index(0)
     227            {
     228            }
     229
     230            void append(JSString* jsString)
     231            {
     232                if (m_index == JSRopeString::s_maxInternalRopeLength)
     233                    expand();
     234                m_jsString->append(m_vm, m_index++, jsString);
     235            }
     236
     237            JSRopeString* release()
     238            {
     239                JSRopeString* tmp = m_jsString;
     240                m_jsString = 0;
     241                return tmp;
     242            }
     243
     244            unsigned length() { return m_jsString->m_length; }
     245
     246        private:
     247            void expand();
     248               
     249            VM& m_vm;
     250            JSRopeString* m_jsString;
     251            size_t m_index;
     252        };
     253           
     254    private:
     255        JSRopeString(VM& vm)
     256            : JSString(vm)
     257        {
     258        }
     259
     260        void finishCreation(VM& vm, JSString* s1, JSString* s2)
     261        {
     262            Base::finishCreation(vm);
     263            m_length = s1->length() + s2->length();
     264            setIs8Bit(s1->is8Bit() && s2->is8Bit());
     265            m_fibers[0].set(vm, this, s1);
     266            m_fibers[1].set(vm, this, s2);
     267        }
     268           
     269        void finishCreation(VM& vm, JSString* s1, JSString* s2, JSString* s3)
     270        {
     271            Base::finishCreation(vm);
     272            m_length = s1->length() + s2->length() + s3->length();
     273            setIs8Bit(s1->is8Bit() && s2->is8Bit() &&  s3->is8Bit());
     274            m_fibers[0].set(vm, this, s1);
     275            m_fibers[1].set(vm, this, s2);
     276            m_fibers[2].set(vm, this, s3);
     277        }
     278
     279        void finishCreation(VM& vm)
     280        {
     281            JSString::finishCreation(vm);
     282        }
     283
     284        void append(VM& vm, size_t index, JSString* jsString)
     285        {
     286            m_fibers[index].set(vm, this, jsString);
     287            m_length += jsString->m_length;
     288            setIs8Bit(is8Bit() && jsString->is8Bit());
     289        }
     290
     291        static JSRopeString* createNull(VM& vm)
     292        {
     293            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
     294            newString->finishCreation(vm);
     295            return newString;
     296        }
     297
    222298    public:
    223         RopeBuilder(VM& vm)
    224             : m_vm(vm)
    225             , m_jsString(jsStringBuilder(&vm))
    226             , m_index(0)
    227         {
    228         }
    229 
    230         void append(JSString* jsString)
    231         {
    232             if (m_index == JSRopeString::s_maxInternalRopeLength)
    233                 expand();
    234             m_jsString->append(m_vm, m_index++, jsString);
    235         }
    236 
    237         JSRopeString* release()
    238         {
    239             JSRopeString* tmp = m_jsString;
    240             m_jsString = 0;
    241             return tmp;
    242         }
    243 
    244         unsigned length() { return m_jsString->m_length; }
    245 
     299        static JSString* create(VM& vm, JSString* s1, JSString* s2)
     300        {
     301            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
     302            newString->finishCreation(vm, s1, s2);
     303            return newString;
     304        }
     305        static JSString* create(VM& vm, JSString* s1, JSString* s2, JSString* s3)
     306        {
     307            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
     308            newString->finishCreation(vm, s1, s2, s3);
     309            return newString;
     310        }
     311
     312        void visitFibers(SlotVisitor&);
     313           
     314        static ptrdiff_t offsetOfFibers() { return OBJECT_OFFSETOF(JSRopeString, m_fibers); }
     315
     316        static const unsigned s_maxInternalRopeLength = 3;
     317           
    246318    private:
    247         void expand();
    248            
    249         VM& m_vm;
    250         JSRopeString* m_jsString;
    251         size_t m_index;
     319        friend JSValue jsString(ExecState*, Register*, unsigned);
     320        friend JSValue jsStringFromArguments(ExecState*, JSValue);
     321
     322        JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
     323        void resolveRopeSlowCase8(LChar*) const;
     324        void resolveRopeSlowCase(UChar*) const;
     325        void outOfMemory(ExecState*) const;
     326           
     327        JSString* getIndexSlowCase(ExecState*, unsigned);
     328
     329        mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
    252330    };
    253        
    254 private:
    255     JSRopeString(VM& vm)
    256         : JSString(vm)
    257     {
    258     }
    259 
    260     void finishCreation(VM& vm, JSString* s1, JSString* s2)
    261     {
    262         Base::finishCreation(vm);
    263         m_length = s1->length() + s2->length();
    264         setIs8Bit(s1->is8Bit() && s2->is8Bit());
    265         m_fibers[0].set(vm, this, s1);
    266         m_fibers[1].set(vm, this, s2);
    267     }
    268        
    269     void finishCreation(VM& vm, JSString* s1, JSString* s2, JSString* s3)
    270     {
    271         Base::finishCreation(vm);
    272         m_length = s1->length() + s2->length() + s3->length();
    273         setIs8Bit(s1->is8Bit() && s2->is8Bit() &&  s3->is8Bit());
    274         m_fibers[0].set(vm, this, s1);
    275         m_fibers[1].set(vm, this, s2);
    276         m_fibers[2].set(vm, this, s3);
    277     }
    278 
    279     void finishCreation(VM& vm)
    280     {
    281         JSString::finishCreation(vm);
    282     }
    283 
    284     void append(VM& vm, size_t index, JSString* jsString)
    285     {
    286         m_fibers[index].set(vm, this, jsString);
    287         m_length += jsString->m_length;
    288         setIs8Bit(is8Bit() && jsString->is8Bit());
    289     }
    290 
    291     static JSRopeString* createNull(VM& vm)
    292     {
    293         JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
    294         newString->finishCreation(vm);
    295         return newString;
    296     }
    297 
    298 public:
    299     static JSString* create(VM& vm, JSString* s1, JSString* s2)
    300     {
    301         JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
    302         newString->finishCreation(vm, s1, s2);
    303         return newString;
    304     }
    305     static JSString* create(VM& vm, JSString* s1, JSString* s2, JSString* s3)
    306     {
    307         JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
    308         newString->finishCreation(vm, s1, s2, s3);
    309         return newString;
    310     }
    311 
    312     void visitFibers(SlotVisitor&);
    313        
    314     static ptrdiff_t offsetOfFibers() { return OBJECT_OFFSETOF(JSRopeString, m_fibers); }
    315 
    316     static const unsigned s_maxInternalRopeLength = 3;
    317        
    318 private:
    319     friend JSValue jsString(ExecState*, Register*, unsigned);
    320     friend JSValue jsStringFromArguments(ExecState*, JSValue);
    321 
    322     JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
    323     void resolveRopeSlowCase8(LChar*) const;
    324     void resolveRopeSlowCase(UChar*) const;
    325     void outOfMemory(ExecState*) const;
    326        
    327     JSString* getIndexSlowCase(ExecState*, unsigned);
    328 
    329     mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
    330 };
    331 
    332 
    333 inline const StringImpl* JSString::tryGetValueImpl() const
    334 {
    335     return m_value.impl();
    336 }
    337 
    338 JSString* asString(JSValue);
    339 
    340 inline JSString* asString(JSValue value)
    341 {
    342     ASSERT(value.asCell()->isString());
    343     return jsCast<JSString*>(value.asCell());
    344 }
    345 
    346 inline JSString* jsEmptyString(VM* vm)
    347 {
    348     return vm->smallStrings.emptyString();
    349 }
    350 
    351 ALWAYS_INLINE JSString* jsSingleCharacterString(VM* vm, UChar c)
    352 {
    353     if (c <= maxSingleCharacterString)
    354         return vm->smallStrings.singleCharacterString(vm, c);
    355     return JSString::create(*vm, String(&c, 1).impl());
    356 }
    357 
    358 ALWAYS_INLINE JSString* jsSingleCharacterSubstring(ExecState* exec, const String& s, unsigned offset)
    359 {
    360     VM* vm = &exec->vm();
    361     ASSERT(offset < static_cast<unsigned>(s.length()));
    362     UChar c = s.characterAt(offset);
    363     if (c <= maxSingleCharacterString)
    364         return vm->smallStrings.singleCharacterString(vm, c);
    365     return JSString::create(*vm, StringImpl::create(s.impl(), offset, 1));
    366 }
    367 
    368 inline JSString* jsNontrivialString(VM* vm, const String& s)
    369 {
    370     ASSERT(s.length() > 1);
    371     return JSString::create(*vm, s.impl());
    372 }
    373 
    374 inline const String& JSString::value(ExecState* exec) const
    375 {
    376     if (isRope())
    377         static_cast<const JSRopeString*>(this)->resolveRope(exec);
    378     return m_value;
    379 }
    380 
    381 inline const String& JSString::tryGetValue() const
    382 {
    383     if (isRope())
    384         static_cast<const JSRopeString*>(this)->resolveRope(0);
    385     return m_value;
    386 }
    387 
    388 inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
    389 {
    390     ASSERT(canGetIndex(i));
    391     if (isRope())
    392         return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i);
    393     ASSERT(i < m_value.length());
    394     return jsSingleCharacterSubstring(exec, m_value, i);
    395 }
    396 
    397 inline JSString* jsString(VM* vm, const String& s)
    398 {
    399     int size = s.length();
    400     if (!size)
     331
     332
     333    inline const StringImpl* JSString::tryGetValueImpl() const
     334    {
     335        return m_value.impl();
     336    }
     337
     338    JSString* asString(JSValue);
     339
     340    inline JSString* asString(JSValue value)
     341    {
     342        ASSERT(value.asCell()->isString());
     343        return jsCast<JSString*>(value.asCell());
     344    }
     345
     346    inline JSString* jsEmptyString(VM* vm)
     347    {
    401348        return vm->smallStrings.emptyString();
    402     if (size == 1) {
    403         UChar c = s.characterAt(0);
     349    }
     350
     351    ALWAYS_INLINE JSString* jsSingleCharacterString(VM* vm, UChar c)
     352    {
    404353        if (c <= maxSingleCharacterString)
    405354            return vm->smallStrings.singleCharacterString(vm, c);
    406     }
    407     return JSString::create(*vm, s.impl());
    408 }
    409 
    410 inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
    411 {
    412     ASSERT(offset <= static_cast<unsigned>(s->length()));
    413     ASSERT(length <= static_cast<unsigned>(s->length()));
    414     ASSERT(offset + length <= static_cast<unsigned>(s->length()));
    415     VM* vm = &exec->vm();
    416     if (!length)
    417         return vm->smallStrings.emptyString();
    418     return jsSubstring(vm, s->value(exec), offset, length);
    419 }
    420 
    421 inline JSString* jsSubstring8(VM* vm, const String& s, unsigned offset, unsigned length)
    422 {
    423     ASSERT(offset <= static_cast<unsigned>(s.length()));
    424     ASSERT(length <= static_cast<unsigned>(s.length()));
    425     ASSERT(offset + length <= static_cast<unsigned>(s.length()));
    426     if (!length)
    427         return vm->smallStrings.emptyString();
    428     if (length == 1) {
     355        return JSString::create(*vm, String(&c, 1).impl());
     356    }
     357
     358    ALWAYS_INLINE JSString* jsSingleCharacterSubstring(ExecState* exec, const String& s, unsigned offset)
     359    {
     360        VM* vm = &exec->vm();
     361        ASSERT(offset < static_cast<unsigned>(s.length()));
    429362        UChar c = s.characterAt(offset);
    430363        if (c <= maxSingleCharacterString)
    431364            return vm->smallStrings.singleCharacterString(vm, c);
    432     }
    433     return JSString::createHasOtherOwner(*vm, StringImpl::create8(s.impl(), offset, length));
    434 }
    435 
    436 inline JSString* jsSubstring(VM* vm, const String& s, unsigned offset, unsigned length)
    437 {
    438     ASSERT(offset <= static_cast<unsigned>(s.length()));
    439     ASSERT(length <= static_cast<unsigned>(s.length()));
    440     ASSERT(offset + length <= static_cast<unsigned>(s.length()));
    441     if (!length)
    442         return vm->smallStrings.emptyString();
    443     if (length == 1) {
    444         UChar c = s.characterAt(offset);
    445         if (c <= maxSingleCharacterString)
    446             return vm->smallStrings.singleCharacterString(vm, c);
    447     }
    448     return JSString::createHasOtherOwner(*vm, StringImpl::create(s.impl(), offset, length));
    449 }
    450 
    451 inline JSString* jsOwnedString(VM* vm, const String& s)
    452 {
    453     int size = s.length();
    454     if (!size)
    455         return vm->smallStrings.emptyString();
    456     if (size == 1) {
    457         UChar c = s.characterAt(0);
    458         if (c <= maxSingleCharacterString)
    459             return vm->smallStrings.singleCharacterString(vm, c);
    460     }
    461     return JSString::createHasOtherOwner(*vm, s.impl());
    462 }
    463 
    464 inline JSRopeString* jsStringBuilder(VM* vm)
    465 {
    466     return JSRopeString::createNull(*vm);
    467 }
    468 
    469 inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->vm()); }
    470 inline JSString* jsString(ExecState* exec, const String& s) { return jsString(&exec->vm(), s); }
    471 inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->vm(), c); }
    472 inline JSString* jsSubstring8(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring8(&exec->vm(), s, offset, length); }
    473 inline JSString* jsSubstring(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring(&exec->vm(), s, offset, length); }
    474 inline JSString* jsNontrivialString(ExecState* exec, const String& s) { return jsNontrivialString(&exec->vm(), s); }
    475 inline JSString* jsOwnedString(ExecState* exec, const String& s) { return jsOwnedString(&exec->vm(), s); }
    476 
    477 ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
    478 {
    479     if (propertyName == exec->propertyNames().length) {
    480         slot.setValue(jsNumber(m_length));
    481         return true;
    482     }
    483 
    484     unsigned i = propertyName.asIndex();
    485     if (i < m_length) {
    486         ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
    487         slot.setValue(getIndex(exec, i));
    488         return true;
    489     }
    490 
    491     return false;
    492 }
     365        return JSString::create(*vm, StringImpl::create(s.impl(), offset, 1));
     366    }
     367
     368    inline JSString* jsNontrivialString(VM* vm, const String& s)
     369    {
     370        ASSERT(s.length() > 1);
     371        return JSString::create(*vm, s.impl());
     372    }
     373
     374    inline const String& JSString::value(ExecState* exec) const
     375    {
     376        if (isRope())
     377            static_cast<const JSRopeString*>(this)->resolveRope(exec);
     378        return m_value;
     379    }
     380
     381    inline const String& JSString::tryGetValue() const
     382    {
     383        if (isRope())
     384            static_cast<const JSRopeString*>(this)->resolveRope(0);
     385        return m_value;
     386    }
     387
     388    inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
     389    {
     390        ASSERT(canGetIndex(i));
     391        if (isRope())
     392            return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i);
     393        ASSERT(i < m_value.length());
     394        return jsSingleCharacterSubstring(exec, m_value, i);
     395    }
     396
     397    inline JSString* jsString(VM* vm, const String& s)
     398    {
     399        int size = s.length();
     400        if (!size)
     401            return vm->smallStrings.emptyString();
     402        if (size == 1) {
     403            UChar c = s.characterAt(0);
     404            if (c <= maxSingleCharacterString)
     405                return vm->smallStrings.singleCharacterString(vm, c);
     406        }
     407        return JSString::create(*vm, s.impl());
     408    }
     409
     410    inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
     411    {
     412        ASSERT(offset <= static_cast<unsigned>(s->length()));
     413        ASSERT(length <= static_cast<unsigned>(s->length()));
     414        ASSERT(offset + length <= static_cast<unsigned>(s->length()));
     415        VM* vm = &exec->vm();
     416        if (!length)
     417            return vm->smallStrings.emptyString();
     418        return jsSubstring(vm, s->value(exec), offset, length);
     419    }
     420
     421    inline JSString* jsSubstring8(VM* vm, const String& s, unsigned offset, unsigned length)
     422    {
     423        ASSERT(offset <= static_cast<unsigned>(s.length()));
     424        ASSERT(length <= static_cast<unsigned>(s.length()));
     425        ASSERT(offset + length <= static_cast<unsigned>(s.length()));
     426        if (!length)
     427            return vm->smallStrings.emptyString();
     428        if (length == 1) {
     429            UChar c = s.characterAt(offset);
     430            if (c <= maxSingleCharacterString)
     431                return vm->smallStrings.singleCharacterString(vm, c);
     432        }
     433        return JSString::createHasOtherOwner(*vm, StringImpl::create8(s.impl(), offset, length));
     434    }
     435
     436    inline JSString* jsSubstring(VM* vm, const String& s, unsigned offset, unsigned length)
     437    {
     438        ASSERT(offset <= static_cast<unsigned>(s.length()));
     439        ASSERT(length <= static_cast<unsigned>(s.length()));
     440        ASSERT(offset + length <= static_cast<unsigned>(s.length()));
     441        if (!length)
     442            return vm->smallStrings.emptyString();
     443        if (length == 1) {
     444            UChar c = s.characterAt(offset);
     445            if (c <= maxSingleCharacterString)
     446                return vm->smallStrings.singleCharacterString(vm, c);
     447        }
     448        return JSString::createHasOtherOwner(*vm, StringImpl::create(s.impl(), offset, length));
     449    }
     450
     451    inline JSString* jsOwnedString(VM* vm, const String& s)
     452    {
     453        int size = s.length();
     454        if (!size)
     455            return vm->smallStrings.emptyString();
     456        if (size == 1) {
     457            UChar c = s.characterAt(0);
     458            if (c <= maxSingleCharacterString)
     459                return vm->smallStrings.singleCharacterString(vm, c);
     460        }
     461        return JSString::createHasOtherOwner(*vm, s.impl());
     462    }
     463
     464    inline JSRopeString* jsStringBuilder(VM* vm)
     465    {
     466        return JSRopeString::createNull(*vm);
     467    }
     468
     469    inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->vm()); }
     470    inline JSString* jsString(ExecState* exec, const String& s) { return jsString(&exec->vm(), s); }
     471    inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->vm(), c); }
     472    inline JSString* jsSubstring8(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring8(&exec->vm(), s, offset, length); }
     473    inline JSString* jsSubstring(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring(&exec->vm(), s, offset, length); }
     474    inline JSString* jsNontrivialString(ExecState* exec, const String& s) { return jsNontrivialString(&exec->vm(), s); }
     475    inline JSString* jsOwnedString(ExecState* exec, const String& s) { return jsOwnedString(&exec->vm(), s); }
     476
     477    ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
     478    {
     479        if (propertyName == exec->propertyNames().length) {
     480            slot.setValue(jsNumber(m_length));
     481            return true;
     482        }
     483
     484        unsigned i = propertyName.asIndex();
     485        if (i < m_length) {
     486            ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
     487            slot.setValue(getIndex(exec, i));
     488            return true;
     489        }
     490
     491        return false;
     492    }
     493           
     494    ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
     495    {
     496        if (propertyName < m_length) {
     497            slot.setValue(getIndex(exec, propertyName));
     498            return true;
     499        }
     500
     501        return false;
     502    }
     503
     504    inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; }
     505
     506    // --- JSValue inlines ----------------------------
    493507       
    494 ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
    495 {
    496     if (propertyName < m_length) {
    497         slot.setValue(getIndex(exec, propertyName));
    498         return true;
    499     }
    500 
    501     return false;
    502 }
    503 
    504 inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; }
    505 
    506 // --- JSValue inlines ----------------------------
    507    
    508 inline bool JSValue::toBoolean(ExecState* exec) const
    509 {
    510     if (isInt32())
    511         return asInt32();
    512     if (isDouble())
    513         return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
    514     if (isCell())
    515         return asCell()->toBoolean(exec);
    516     return isTrue(); // false, null, and undefined all convert to false.
    517 }
    518 
    519 inline JSString* JSValue::toString(ExecState* exec) const
    520 {
    521     if (isString())
    522         return jsCast<JSString*>(asCell());
    523     return toStringSlowCase(exec);
    524 }
    525 
    526 inline String JSValue::toWTFString(ExecState* exec) const
    527 {
    528     if (isString())
    529         return static_cast<JSString*>(asCell())->value(exec);
    530     return toWTFStringSlowCase(exec);
    531 }
    532 
    533 ALWAYS_INLINE String inlineJSValueNotStringtoString(const JSValue& value, ExecState* exec)
    534 {
    535     VM& vm = exec->vm();
    536     if (value.isInt32())
    537         return vm.numericStrings.add(value.asInt32());
    538     if (value.isDouble())
    539         return vm.numericStrings.add(value.asDouble());
    540     if (value.isTrue())
    541         return vm.propertyNames->trueKeyword.string();
    542     if (value.isFalse())
    543         return vm.propertyNames->falseKeyword.string();
    544     if (value.isNull())
    545         return vm.propertyNames->nullKeyword.string();
    546     if (value.isUndefined())
    547         return vm.propertyNames->undefinedKeyword.string();
    548     return value.toString(exec)->value(exec);
    549 }
    550 
    551 ALWAYS_INLINE String JSValue::toWTFStringInline(ExecState* exec) const
    552 {
    553     if (isString())
    554         return static_cast<JSString*>(asCell())->value(exec);
    555 
    556     return inlineJSValueNotStringtoString(*this, exec);
    557 }
     508    inline bool JSValue::toBoolean(ExecState* exec) const
     509    {
     510        if (isInt32())
     511            return asInt32();
     512        if (isDouble())
     513            return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
     514        if (isCell())
     515            return asCell()->toBoolean(exec);
     516        return isTrue(); // false, null, and undefined all convert to false.
     517    }
     518
     519    inline JSString* JSValue::toString(ExecState* exec) const
     520    {
     521        if (isString())
     522            return jsCast<JSString*>(asCell());
     523        return toStringSlowCase(exec);
     524    }
     525
     526    inline String JSValue::toWTFString(ExecState* exec) const
     527    {
     528        if (isString())
     529            return static_cast<JSString*>(asCell())->value(exec);
     530        return toWTFStringSlowCase(exec);
     531    }
     532
     533    ALWAYS_INLINE String inlineJSValueNotStringtoString(const JSValue& value, ExecState* exec)
     534    {
     535        VM& vm = exec->vm();
     536        if (value.isInt32())
     537            return vm.numericStrings.add(value.asInt32());
     538        if (value.isDouble())
     539            return vm.numericStrings.add(value.asDouble());
     540        if (value.isTrue())
     541            return vm.propertyNames->trueKeyword.string();
     542        if (value.isFalse())
     543            return vm.propertyNames->falseKeyword.string();
     544        if (value.isNull())
     545            return vm.propertyNames->nullKeyword.string();
     546        if (value.isUndefined())
     547            return vm.propertyNames->undefinedKeyword.string();
     548        return value.toString(exec)->value(exec);
     549    }
     550
     551    ALWAYS_INLINE String JSValue::toWTFStringInline(ExecState* exec) const
     552    {
     553        if (isString())
     554            return static_cast<JSString*>(asCell())->value(exec);
     555
     556        return inlineJSValueNotStringtoString(*this, exec);
     557    }
    558558
    559559} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.