"A + B" with strings shouldn't copy if A or B is empty.
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Oct 2015 19:44:52 +0000 (19:44 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Oct 2015 19:44:52 +0000 (19:44 +0000)
<https://webkit.org/b/150034>

Reviewed by Anders Carlsson.

Source/JavaScriptCore:

* runtime/JSStringBuilder.h:
(JSC::jsMakeNontrivialString):
* runtime/Lookup.cpp:
(JSC::reifyStaticAccessor):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncToString):

Source/WTF:

Add a fast path to WTF's operator+ magic for concatenation of two strings where
one of them is empty. In that case, try to avoid allocation altogether by returning
the non-empty string.

Spotted this while analyzing memory peaks during page load; it turns out we were
duplicating whole text resources (JS, CSS) at the end of decoding, below
TextResourceDecoder::decodeAndFlush(). That function effectively does:

    return decode() + flush();

Very often, flush() returns an empty string, so due to the naive operator+,
we'd allocate a new StringImpl of length (decode().length() + flush().length())
and copy the return value from decode() into it. So silly!

Had to make the tryMakeString() machinery use String as a return type instead of
RefPtr<StringImpl> to make all the right overloads gel. StringTypeAdapter templates
are now required to provide a toString() function.

* wtf/text/StringConcatenate.h:
(WTF::StringTypeAdapter<char>::toString):
(WTF::StringTypeAdapter<UChar>::toString):
(WTF::StringTypeAdapter<Vector<char>>::toString):
(WTF::StringTypeAdapter<String>::toString):
(WTF::tryMakeString):
(WTF::makeString):
* wtf/text/StringOperators.h:
(WTF::StringAppend::operator String):
* wtf/text/StringView.h:
(WTF::StringTypeAdapter<StringView>::toString):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@190882 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSStringBuilder.h
Source/JavaScriptCore/runtime/Lookup.cpp
Source/JavaScriptCore/runtime/ObjectPrototype.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/text/StringConcatenate.h
Source/WTF/wtf/text/StringOperators.h
Source/WTF/wtf/text/StringView.h

index 5fa7b65..f646fae 100644 (file)
@@ -1,3 +1,17 @@
+2015-10-12  Andreas Kling  <akling@apple.com>
+
+        "A + B" with strings shouldn't copy if A or B is empty.
+        <https://webkit.org/b/150034>
+
+        Reviewed by Anders Carlsson.
+
+        * runtime/JSStringBuilder.h:
+        (JSC::jsMakeNontrivialString):
+        * runtime/Lookup.cpp:
+        (JSC::reifyStaticAccessor):
+        * runtime/ObjectPrototype.cpp:
+        (JSC::objectProtoFuncToString):
+
 2015-10-12  Joseph Pecoraro  <pecoraro@apple.com>
 
         VisitedValueCount GC Counter misses parallel SlotVisitors
index 34f43c4..32b39f0 100644 (file)
@@ -127,10 +127,10 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType&& string)
 template<typename StringType, typename... StringTypes>
 inline JSValue jsMakeNontrivialString(ExecState* exec, const StringType& string, const StringTypes&... strings)
 {
-    RefPtr<StringImpl> result = WTF::tryMakeString(string, strings...);
+    String result = WTF::tryMakeString(string, strings...);
     if (!result)
         return throwOutOfMemoryError(exec);
-    return jsNontrivialString(exec, result.release());
+    return jsNontrivialString(exec, result);
 }
 
 }
index bf8844b..dcee6ba 100644 (file)
@@ -32,12 +32,12 @@ void reifyStaticAccessor(VM& vm, const HashTableValue& value, JSObject& thisObj,
     JSGlobalObject* globalObject = thisObj.globalObject();
     GetterSetter* accessor = GetterSetter::create(vm, globalObject);
     if (value.accessorGetter()) {
-        RefPtr<StringImpl> getterName = WTF::tryMakeString(ASCIILiteral("get "), String(*propertyName.publicName()));
+        String getterName = WTF::tryMakeString(ASCIILiteral("get "), String(*propertyName.publicName()));
         if (!getterName)
             return;
         accessor->setGetter(vm, globalObject, value.attributes() & Builtin
-            ? JSFunction::createBuiltinFunction(vm, value.builtinAccessorGetterGenerator()(vm), globalObject, *getterName)
-            : JSFunction::create(vm, globalObject, 0, *getterName, value.accessorGetter()));
+            ? JSFunction::createBuiltinFunction(vm, value.builtinAccessorGetterGenerator()(vm), globalObject, getterName)
+            : JSFunction::create(vm, globalObject, 0, getterName, value.accessorGetter()));
     }
     thisObj.putDirectNonIndexAccessor(vm, propertyName, accessor, attributesForStructure(value.attributes()));
 }
index 905d0d2..7e09f14 100644 (file)
@@ -245,11 +245,11 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec)
 
     JSString* result = thisObject->structure(vm)->objectToStringValue();
     if (!result) {
-        RefPtr<StringImpl> newString = WTF::tryMakeString("[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]");
+        String newString = WTF::tryMakeString("[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]");
         if (!newString)
             return JSValue::encode(throwOutOfMemoryError(exec));
 
-        result = jsNontrivialString(&vm, newString.release());
+        result = jsNontrivialString(&vm, newString);
         thisObject->structure(vm)->setObjectToStringValue(vm, result);
     }
     return JSValue::encode(result);
index 85e13a9..ac74456 100644 (file)
@@ -1,3 +1,40 @@
+2015-10-12  Andreas Kling  <akling@apple.com>
+
+        "A + B" with strings shouldn't copy if A or B is empty.
+        <https://webkit.org/b/150034>
+
+        Reviewed by Anders Carlsson.
+
+        Add a fast path to WTF's operator+ magic for concatenation of two strings where
+        one of them is empty. In that case, try to avoid allocation altogether by returning
+        the non-empty string.
+
+        Spotted this while analyzing memory peaks during page load; it turns out we were
+        duplicating whole text resources (JS, CSS) at the end of decoding, below
+        TextResourceDecoder::decodeAndFlush(). That function effectively does:
+
+            return decode() + flush();
+
+        Very often, flush() returns an empty string, so due to the naive operator+,
+        we'd allocate a new StringImpl of length (decode().length() + flush().length())
+        and copy the return value from decode() into it. So silly!
+
+        Had to make the tryMakeString() machinery use String as a return type instead of
+        RefPtr<StringImpl> to make all the right overloads gel. StringTypeAdapter templates
+        are now required to provide a toString() function.
+
+        * wtf/text/StringConcatenate.h:
+        (WTF::StringTypeAdapter<char>::toString):
+        (WTF::StringTypeAdapter<UChar>::toString):
+        (WTF::StringTypeAdapter<Vector<char>>::toString):
+        (WTF::StringTypeAdapter<String>::toString):
+        (WTF::tryMakeString):
+        (WTF::makeString):
+        * wtf/text/StringOperators.h:
+        (WTF::StringAppend::operator String):
+        * wtf/text/StringView.h:
+        (WTF::StringTypeAdapter<StringView>::toString):
+
 2015-10-12  Filip Pizlo  <fpizlo@apple.com>
 
         Unreviewed, fix style in the hopes that it fixes Windows.
index 8cc4b58..1deebe6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -68,6 +68,8 @@ public:
         *destination = m_character;
     }
 
+    String toString() const { return String(&m_character, 1); }
+
 private:
     char m_character;
 };
@@ -94,6 +96,8 @@ public:
         *destination = m_character;
     }
 
+    String toString() const { return String(&m_character, 1); }
+
 private:
     UChar m_character;
 };
@@ -120,6 +124,8 @@ public:
         StringView(m_characters, m_length).getCharactersWithUpconvert(destination);
     }
 
+    String toString() const { return String(m_characters, 1); }
+
 private:
     const LChar* m_characters;
     unsigned m_length;
@@ -154,6 +160,8 @@ public:
         memcpy(destination, m_characters, m_length * sizeof(UChar));
     }
 
+    String toString() const { return String(m_characters, 1); }
+
 private:
     const UChar* m_characters;
     unsigned m_length;
@@ -207,6 +215,8 @@ public:
         StringView(reinterpret_cast<const LChar*>(m_vector.data()), m_vector.size()).getCharactersWithUpconvert(destination);
     }
 
+    String toString() const { return String(m_vector.data(), m_vector.size()); }
+
 private:
     const Vector<char>& m_vector;
 };
@@ -234,6 +244,8 @@ public:
         WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
     }
 
+    String toString() const { return m_string; }
+
 private:
     const String& m_string;
 };
@@ -256,22 +268,27 @@ inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
 }
 
 template<typename StringType1, typename StringType2>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2)
+String tryMakeString(StringType1 string1, StringType2 string2)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
 
+    if (adapter1.length() && !adapter2.length())
+        return adapter1.toString();
+    if (!adapter1.length() && adapter2.length())
+        return adapter2.toString();
+
     bool overflow = false;
     unsigned length = adapter1.length();
     sumWithOverflow(length, adapter2.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -284,7 +301,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2)
     UChar* buffer;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -295,7 +312,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2)
 }
 
 template<typename StringType1, typename StringType2, typename StringType3>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
+String tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
@@ -306,13 +323,13 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     sumWithOverflow(length, adapter2.length(), overflow);
     sumWithOverflow(length, adapter3.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -327,7 +344,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     UChar* buffer = 0;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -340,7 +357,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+String tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
@@ -353,13 +370,13 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     sumWithOverflow(length, adapter3.length(), overflow);
     sumWithOverflow(length, adapter4.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -376,7 +393,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     UChar* buffer;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -391,7 +408,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
+String tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
@@ -406,13 +423,13 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     sumWithOverflow(length, adapter4.length(), overflow);
     sumWithOverflow(length, adapter5.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -431,7 +448,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     UChar* buffer;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -448,7 +465,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
+String tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
@@ -465,13 +482,13 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     sumWithOverflow(length, adapter5.length(), overflow);
     sumWithOverflow(length, adapter6.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -492,7 +509,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     UChar* buffer;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -511,7 +528,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
+String tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
@@ -530,13 +547,13 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     sumWithOverflow(length, adapter6.length(), overflow);
     sumWithOverflow(length, adapter7.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -559,7 +576,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     UChar* buffer;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -580,7 +597,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
+String tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
@@ -601,13 +618,13 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     sumWithOverflow(length, adapter7.length(), overflow);
     sumWithOverflow(length, adapter8.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -632,7 +649,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     UChar* buffer;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -655,7 +672,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
-RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
+String tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
 {
     StringTypeAdapter<StringType1> adapter1(string1);
     StringTypeAdapter<StringType2> adapter2(string2);
@@ -678,13 +695,13 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     sumWithOverflow(length, adapter8.length(), overflow);
     sumWithOverflow(length, adapter9.length(), overflow);
     if (overflow)
-        return nullptr;
+        return String();
 
     if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit() && adapter9.is8Bit()) {
         LChar* buffer;
         RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
         if (!resultImpl)
-            return nullptr;
+            return String();
 
         LChar* result = buffer;
         adapter1.writeTo(result);
@@ -711,7 +728,7 @@ RefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, Strin
     UChar* buffer;
     RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
     if (!resultImpl)
-        return nullptr;
+        return String();
 
     UChar* result = buffer;
     adapter1.writeTo(result);
@@ -746,73 +763,73 @@ String makeString(StringType1 string1)
 template<typename StringType1, typename StringType2>
 String makeString(StringType1 string1, StringType2 string2)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 template<typename StringType1, typename StringType2, typename StringType3>
 String makeString(StringType1 string1, StringType2 string2, StringType3 string3)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2, string3);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2, string3, string4);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2, string3, string4, string5);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2, string3, string4, string5, string6);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
 {
-    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9);
-    if (!resultImpl)
+    String result = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9);
+    if (!result)
         CRASH();
-    return WTF::move(resultImpl);
+    return result;
 }
 
 } // namespace WTF
index cfd2f6d..5a24356 100644 (file)
@@ -35,10 +35,10 @@ public:
 
     operator String() const
     {
-        RefPtr<StringImpl> resultImpl = tryMakeString(m_string1, m_string2);
-        if (!resultImpl)
+        String result = tryMakeString(m_string1, m_string2);
+        if (!result)
             CRASH();
-        return resultImpl.release();
+        return result;
     }
 
     operator AtomicString() const
@@ -97,6 +97,8 @@ public:
     void writeTo(LChar* destination) { m_buffer.writeTo(destination); }
     void writeTo(UChar* destination) { m_buffer.writeTo(destination); }
 
+    String toString() const { return m_buffer; }
+
 private:
     StringAppend<StringType1, StringType2>& m_buffer;
 };
index 662da87..fb72bb6 100644 (file)
@@ -497,6 +497,8 @@ public:
     void writeTo(LChar* destination) { m_string.getCharactersWithUpconvert(destination); }
     void writeTo(UChar* destination) { m_string.getCharactersWithUpconvert(destination); }
 
+    String toString() const { return m_string.toString(); }
+
 private:
     StringView m_string;
 };