diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/JavaScriptCore/runtime/JSString.h | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSString.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSString.h | 298 |
1 files changed, 182 insertions, 116 deletions
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index 32a32788a..10ec799e5 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -32,6 +32,7 @@ namespace JSC { class JSString; + class JSRopeString; class LLIntOffsetsExtractor; JSString* jsEmptyString(JSGlobalData*); @@ -58,55 +59,20 @@ namespace JSC { JSString* jsOwnedString(JSGlobalData*, const UString&); JSString* jsOwnedString(ExecState*, const UString&); - JSString* jsStringBuilder(JSGlobalData*); + JSRopeString* jsStringBuilder(JSGlobalData*); class JSString : public JSCell { public: friend class JIT; friend class JSGlobalData; friend class SpecializedThunkJIT; + friend class JSRopeString; friend struct ThunkHelpers; - friend JSString* jsStringBuilder(JSGlobalData*); typedef JSCell Base; static void destroy(JSCell*); - class RopeBuilder { - public: - RopeBuilder(JSGlobalData& globalData) - : m_globalData(globalData) - , m_jsString(jsStringBuilder(&globalData)) - , m_index(0) - { - } - - void append(JSString* jsString) - { - if (m_index == JSString::s_maxInternalRopeLength) - expand(); - m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString); - m_jsString->m_length += jsString->m_length; - m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit; - } - - JSString* release() - { - JSString* tmp = m_jsString; - m_jsString = 0; - return tmp; - } - - unsigned length() { return m_jsString->m_length; } - - private: - void expand(); - - JSGlobalData& m_globalData; - JSString* m_jsString; - size_t m_index; - }; - private: JSString(JSGlobalData& globalData, PassRefPtr<StringImpl> value) : JSCell(globalData, globalData.stringStructure.get()) @@ -119,13 +85,6 @@ namespace JSC { { } - void finishCreation(JSGlobalData& globalData) - { - Base::finishCreation(globalData); - m_length = 0; - m_is8Bit = true; - } - void finishCreation(JSGlobalData& globalData, size_t length) { ASSERT(!m_value.isNull()); @@ -143,32 +102,14 @@ namespace JSC { Heap::heap(this)->reportExtraMemoryCost(cost); } - void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2) - { - Base::finishCreation(globalData); - m_length = s1->length() + s2->length(); - m_is8Bit = (s1->is8Bit() && s2->is8Bit()); - m_fibers[0].set(globalData, this, s1); - m_fibers[1].set(globalData, this, s2); - } - - void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + protected: + void finishCreation(JSGlobalData& globalData) { Base::finishCreation(globalData); - m_length = s1->length() + s2->length() + s3->length(); - m_is8Bit = (s1->is8Bit() && s2->is8Bit() && s3->is8Bit()); - m_fibers[0].set(globalData, this, s1); - m_fibers[1].set(globalData, this, s2); - m_fibers[2].set(globalData, this, s3); - } - - static JSString* createNull(JSGlobalData& globalData) - { - JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData); - newString->finishCreation(globalData); - return newString; + m_length = 0; + m_is8Bit = true; } - + public: static JSString* create(JSGlobalData& globalData, PassRefPtr<StringImpl> value) { @@ -179,18 +120,6 @@ namespace JSC { newString->finishCreation(globalData, length, cost); return newString; } - static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2) - { - JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData); - newString->finishCreation(globalData, s1, s2); - return newString; - } - static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) - { - JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData); - newString->finishCreation(globalData, s1, s2, s3); - return newString; - } static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr<StringImpl> value) { ASSERT(value); @@ -200,18 +129,8 @@ namespace JSC { return newString; } - const UString& value(ExecState* exec) const - { - if (isRope()) - resolveRope(exec); - return m_value; - } - const UString& tryGetValue() const - { - if (isRope()) - resolveRope(0); - return m_value; - } + const UString& value(ExecState*) const; + const UString& tryGetValue() const; unsigned length() { return m_length; } JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; @@ -226,7 +145,6 @@ namespace JSC { bool canGetIndex(unsigned i) { return i < m_length; } JSString* getIndex(ExecState*, unsigned); - JSString* getIndexSlowCase(ExecState*, unsigned); static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { @@ -240,44 +158,145 @@ namespace JSC { static void visitChildren(JSCell*, SlotVisitor&); + protected: + bool isRope() const { return m_value.isNull(); } + bool is8Bit() const { return m_is8Bit; } + + // A string is represented either by a UString or a rope of fibers. + bool m_is8Bit : 1; + unsigned m_length; + mutable UString m_value; + private: friend class LLIntOffsetsExtractor; - JS_EXPORT_PRIVATE void resolveRope(ExecState*) const; - void resolveRopeSlowCase8(LChar*) const; - void resolveRopeSlowCase(UChar*) const; - void outOfMemory(ExecState*) const; - static JSObject* toThisObject(JSCell*, ExecState*); // Actually getPropertySlot, not getOwnPropertySlot (see JSCell). static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - static const unsigned s_maxInternalRopeLength = 3; - - // A string is represented either by a UString or a rope of fibers. - bool m_is8Bit : 1; - unsigned m_length; - mutable UString m_value; - mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers; - - bool isRope() const { return m_value.isNull(); } - bool is8Bit() const { return m_is8Bit; } UString& string() { ASSERT(!isRope()); return m_value; } friend JSValue jsString(ExecState*, JSString*, JSString*); - friend JSValue jsString(ExecState*, Register*, unsigned count); - friend JSValue jsStringFromArguments(ExecState*, JSValue thisValue); friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length); }; + class JSRopeString : public JSString { + friend class JSString; + + friend JSRopeString* jsStringBuilder(JSGlobalData*); + + class RopeBuilder { + public: + RopeBuilder(JSGlobalData& globalData) + : m_globalData(globalData) + , m_jsString(jsStringBuilder(&globalData)) + , m_index(0) + { + } + + void append(JSString* jsString) + { + if (m_index == JSRopeString::s_maxInternalRopeLength) + expand(); + m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString); + m_jsString->m_length += jsString->m_length; + m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit; + } + + JSRopeString* release() + { + JSRopeString* tmp = m_jsString; + m_jsString = 0; + return tmp; + } + + unsigned length() { return m_jsString->m_length; } + + private: + void expand(); + + JSGlobalData& m_globalData; + JSRopeString* m_jsString; + size_t m_index; + }; + + private: + JSRopeString(JSGlobalData& globalData) + : JSString(globalData) + { + } + + void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2) + { + Base::finishCreation(globalData); + m_length = s1->length() + s2->length(); + m_is8Bit = (s1->is8Bit() && s2->is8Bit()); + m_fibers[0].set(globalData, this, s1); + m_fibers[1].set(globalData, this, s2); + } + + void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + { + Base::finishCreation(globalData); + m_length = s1->length() + s2->length() + s3->length(); + m_is8Bit = (s1->is8Bit() && s2->is8Bit() && s3->is8Bit()); + m_fibers[0].set(globalData, this, s1); + m_fibers[1].set(globalData, this, s2); + m_fibers[2].set(globalData, this, s3); + } + + void finishCreation(JSGlobalData& globalData) + { + JSString::finishCreation(globalData); + } + + static JSRopeString* createNull(JSGlobalData& globalData) + { + JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData); + newString->finishCreation(globalData); + return newString; + } + + public: + static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2) + { + JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData); + newString->finishCreation(globalData, s1, s2); + return newString; + } + static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + { + JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData); + newString->finishCreation(globalData, s1, s2, s3); + return newString; + } + + void visitFibers(SlotVisitor&); + + private: + friend JSValue jsString(ExecState*, Register*, unsigned); + friend JSValue jsStringFromArguments(ExecState*, JSValue); + + JS_EXPORT_PRIVATE void resolveRope(ExecState*) const; + void resolveRopeSlowCase8(LChar*) const; + void resolveRopeSlowCase(UChar*) const; + void outOfMemory(ExecState*) const; + + JSString* getIndexSlowCase(ExecState*, unsigned); + + static const unsigned s_maxInternalRopeLength = 3; + + mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers; + }; + JSString* asString(JSValue); inline JSString* asString(JSValue value) { ASSERT(value.asCell()->isString()); - return static_cast<JSString*>(value.asCell()); + return jsCast<JSString*>(value.asCell()); } inline JSString* jsEmptyString(JSGlobalData* globalData) @@ -285,14 +304,14 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); } - inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c) + ALWAYS_INLINE JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c) { if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); return JSString::create(*globalData, UString(&c, 1).impl()); } - inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) + ALWAYS_INLINE JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { JSGlobalData* globalData = &exec->globalData(); ASSERT(offset < static_cast<unsigned>(s.length())); @@ -316,11 +335,25 @@ namespace JSC { return JSString::create(*globalData, s.impl()); } + inline const UString& JSString::value(ExecState* exec) const + { + if (isRope()) + static_cast<const JSRopeString*>(this)->resolveRope(exec); + return m_value; + } + + inline const UString& JSString::tryGetValue() const + { + if (isRope()) + static_cast<const JSRopeString*>(this)->resolveRope(0); + return m_value; + } + inline JSString* JSString::getIndex(ExecState* exec, unsigned i) { ASSERT(canGetIndex(i)); if (isRope()) - return getIndexSlowCase(exec, i); + return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i); ASSERT(i < m_value.length()); return jsSingleCharacterSubstring(exec, m_value, i); } @@ -392,9 +425,9 @@ namespace JSC { return JSString::createHasOtherOwner(*globalData, s.impl()); } - inline JSString* jsStringBuilder(JSGlobalData* globalData) + inline JSRopeString* jsStringBuilder(JSGlobalData* globalData) { - return JSString::createNull(*globalData); + return JSRopeString::createNull(*globalData); } inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); } @@ -458,10 +491,43 @@ namespace JSC { inline JSString* JSValue::toString(ExecState* exec) const { if (isString()) - return static_cast<JSString*>(asCell()); + return jsCast<JSString*>(asCell()); return toStringSlowCase(exec); } + inline UString JSValue::toUString(ExecState* exec) const + { + if (isString()) + return static_cast<JSString*>(asCell())->value(exec); + return toUStringSlowCase(exec); + } + + ALWAYS_INLINE UString inlineJSValueNotStringtoUString(const JSValue& value, ExecState* exec) + { + JSGlobalData& globalData = exec->globalData(); + if (value.isInt32()) + return globalData.numericStrings.add(value.asInt32()); + if (value.isDouble()) + return globalData.numericStrings.add(value.asDouble()); + if (value.isTrue()) + return globalData.propertyNames->trueKeyword.ustring(); + if (value.isFalse()) + return globalData.propertyNames->falseKeyword.ustring(); + if (value.isNull()) + return globalData.propertyNames->nullKeyword.ustring(); + if (value.isUndefined()) + return globalData.propertyNames->undefinedKeyword.ustring(); + return value.toString(exec)->value(exec); + } + + ALWAYS_INLINE UString JSValue::toUStringInline(ExecState* exec) const + { + if (isString()) + return static_cast<JSString*>(asCell())->value(exec); + + return inlineJSValueNotStringtoUString(*this, exec); + } + } // namespace JSC #endif // JSString_h |