JSValue::toString() should return a JSString* instead of a UString
https://bugs.webkit.org/show_bug.cgi?id=76861

../JavaScriptCore: 

Reviewed by Gavin Barraclough.
        
This makes the common case -- toString() on a string -- faster and
inline-able. (Not a measureable speedup, but we can now remove a bunch
of duplicate hand-rolled code for this optimization.)
        
This also clarifies the boundary between "C++ strings" and "JS strings".
        
In all cases other than true, false, null, undefined, and multi-digit
numbers, the JS runtime was just retrieving a UString from a JSString,
so returning a JSString* is strictly better. In the other cases, we can
optimize to avoid creating a new JSString if we care to, but it doesn't
seem to be a big deal.

* JavaScriptCore.exp: Export!
        
* jsc.cpp:
(functionPrint):
(functionDebug):
(functionRun):
(functionLoad):
(functionCheckSyntax):
(runWithScripts):
(runInteractive):
* API/JSValueRef.cpp:
(JSValueToStringCopy):
* bytecode/CodeBlock.cpp:
(JSC::valueToSourceString): Call value() after calling toString(), to
convert from "JS string" (JSString*) to "C++ string" (UString), since
toString() no longer returns a "C++ string".

* dfg/DFGOperations.cpp:
(JSC::DFG::operationValueAddNotNumber):
* jit/JITStubs.cpp:
(op_add): Updated for removal of toPrimitiveString():
all '+' operands can use toString(), except for object operands, which
need to take a slow path to call toPrimitive().

* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncPush):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::opIn):
* runtime/DateConstructor.cpp:
(JSC::dateParse):
* runtime/DatePrototype.cpp:
(JSC::formatLocaleDate): Call value() after calling toString(), as above.

* runtime/ErrorInstance.h:
(JSC::ErrorInstance::create): Simplified down to one canonical create()
function, to make string handling easier.

* runtime/ErrorPrototype.cpp:
(JSC::errorProtoFuncToString):
* runtime/ExceptionHelpers.cpp:
(JSC::createInvalidParamError):
(JSC::createNotAConstructorError):
(JSC::createNotAFunctionError):
(JSC::createNotAnObjectError):
* runtime/FunctionConstructor.cpp:
(JSC::constructFunctionSkippingEvalEnabledCheck):
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncBind):
* runtime/JSArray.cpp:
(JSC::JSArray::sort): Call value() after calling toString(), as above.

* runtime/JSCell.cpp:
* runtime/JSCell.h: Removed JSCell::toString() because JSValue does this
job now. Doing it in JSCell is slower (requires extra type checking), and
creates the misimpression that language-defined toString() behavior is
an implementation detail of JSCell.
        
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::encode):
(JSC::decode):
(JSC::globalFuncEval):
(JSC::globalFuncParseInt):
(JSC::globalFuncParseFloat):
(JSC::globalFuncEscape):
(JSC::globalFuncUnescape): Call value() after calling toString(), as above.

* runtime/JSONObject.cpp:
(JSC::unwrapBoxedPrimitive):
(JSC::Stringifier::Stringifier):
(JSC::JSONProtoFuncParse): Removed some manual optimization that toString()
takes care of.

* runtime/JSObject.cpp:
(JSC::JSObject::toString):
* runtime/JSObject.h: Updated to return JSString*.

* runtime/JSString.cpp:
* runtime/JSString.h:
(JSC::JSValue::toString): Removed, since I removed JSCell::toString().

* runtime/JSValue.cpp:
(JSC::JSValue::toStringSlowCase): Removed toPrimitiveString(), and re-
spawned toStringSlowCase() from its zombie corpse, since toPrimitiveString()
basically did what we want all the time. (Note that the toPrimitive()
preference changes from NoPreference to PreferString, because that's
how ToString is defined in the language. op_add does not want this behavior.)

* runtime/NumberPrototype.cpp:
(JSC::numberProtoFuncToString):
(JSC::numberProtoFuncToLocaleString): A little simpler, now that toString()
returns a JSString*.

* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncHasOwnProperty):
(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):
(JSC::objectProtoFuncLookupGetter):
(JSC::objectProtoFuncLookupSetter):
(JSC::objectProtoFuncPropertyIsEnumerable): More calls to value(), as above.

* runtime/Operations.cpp:
(JSC::jsAddSlowCase): Need to check for object before taking the toString()
fast path becuase adding an object to a string requires calling toPrimitive()
on the object, not toString(). (They differ in their preferred conversion
type.)

* runtime/Operations.h:
(JSC::jsString):
(JSC::jsStringFromArguments): This code gets simpler, now that toString()
does the right thing.

(JSC::jsAdd): Now checks for object, just like jsAddSlowCase().

* runtime/RegExpConstructor.cpp:
(JSC::setRegExpConstructorInput):
(JSC::constructRegExp):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::match):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
(JSC::regExpProtoFuncToString): More calls to value(), as above.

* runtime/StringConstructor.cpp:
(JSC::constructWithStringConstructor):
(JSC::callStringConstructor): This code gets simpler, now that toString()
does the right thing.

* runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
(JSC::replaceUsingStringSearch):
(JSC::stringProtoFuncReplace):
(JSC::stringProtoFuncCharAt):
(JSC::stringProtoFuncCharCodeAt):
(JSC::stringProtoFuncConcat):
(JSC::stringProtoFuncIndexOf):
(JSC::stringProtoFuncLastIndexOf):
(JSC::stringProtoFuncMatch):
(JSC::stringProtoFuncSearch):
(JSC::stringProtoFuncSlice):
(JSC::stringProtoFuncSplit):
(JSC::stringProtoFuncSubstr):
(JSC::stringProtoFuncSubstring):
(JSC::stringProtoFuncToLowerCase):
(JSC::stringProtoFuncToUpperCase):
(JSC::stringProtoFuncLocaleCompare):
(JSC::stringProtoFuncBig):
(JSC::stringProtoFuncSmall):
(JSC::stringProtoFuncBlink):
(JSC::stringProtoFuncBold):
(JSC::stringProtoFuncFixed):
(JSC::stringProtoFuncItalics):
(JSC::stringProtoFuncStrike):
(JSC::stringProtoFuncSub):
(JSC::stringProtoFuncSup):
(JSC::stringProtoFuncFontcolor):
(JSC::stringProtoFuncFontsize):
(JSC::stringProtoFuncAnchor):
(JSC::stringProtoFuncLink):
(JSC::trimString): Some of this code gets simpler, now that toString()
does the right thing. More calls to value(), as above.

../JavaScriptGlue: 

Reviewed by Gavin Barraclough.

* JSUtils.cpp:
(KJSValueToCFTypeInternal):

../WebCore: 

Reviewed by Gavin Barraclough.

Mechanical changes to call value() after calling toString(), to
convert from "JS string" (JSString*) to "C++ string" (UString), since
toString() no longer returns a "C++ string".

* bindings/js/IDBBindingUtilities.cpp:
(WebCore::createIDBKeyFromValue):
* bindings/js/JSCSSStyleDeclarationCustom.cpp:
(WebCore::JSCSSStyleDeclaration::getPropertyCSSValue):
* bindings/js/JSClipboardCustom.cpp:
(WebCore::JSClipboard::clearData):
(WebCore::JSClipboard::getData):
* bindings/js/JSCustomXPathNSResolver.cpp:
(WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
* bindings/js/JSDOMBinding.cpp:
(WebCore::valueToStringWithNullCheck):
(WebCore::valueToStringWithUndefinedOrNullCheck):
(WebCore::reportException):
* bindings/js/JSDOMFormDataCustom.cpp:
(WebCore::JSDOMFormData::append):
* bindings/js/JSDOMStringMapCustom.cpp:
(WebCore::JSDOMStringMap::putDelegate):
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::setLocation):
(WebCore::JSDOMWindow::open):
(WebCore::JSDOMWindow::addEventListener):
(WebCore::JSDOMWindow::removeEventListener):
* bindings/js/JSDeviceMotionEventCustom.cpp:
(WebCore::JSDeviceMotionEvent::initDeviceMotionEvent):
* bindings/js/JSDeviceOrientationEventCustom.cpp:
(WebCore::JSDeviceOrientationEvent::initDeviceOrientationEvent):
* bindings/js/JSDictionary.cpp:
(WebCore::JSDictionary::convertValue):
* bindings/js/JSDocumentCustom.cpp:
(WebCore::JSDocument::setLocation):
* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent):
* bindings/js/JSHTMLAllCollectionCustom.cpp:
(WebCore::callHTMLAllCollection):
(WebCore::JSHTMLAllCollection::item):
(WebCore::JSHTMLAllCollection::namedItem):
* bindings/js/JSHTMLCanvasElementCustom.cpp:
(WebCore::JSHTMLCanvasElement::getContext):
* bindings/js/JSHTMLCollectionCustom.cpp:
(WebCore::JSHTMLCollection::item):
(WebCore::JSHTMLCollection::namedItem):
* bindings/js/JSHTMLDocumentCustom.cpp:
(WebCore::documentWrite):
* bindings/js/JSHTMLInputElementCustom.cpp:
(WebCore::JSHTMLInputElement::setSelectionDirection):
(WebCore::JSHTMLInputElement::setSelectionRange):
* bindings/js/JSInspectorFrontendHostCustom.cpp:
(WebCore::JSInspectorFrontendHost::showContextMenu):
* bindings/js/JSJavaScriptCallFrameCustom.cpp:
(WebCore::JSJavaScriptCallFrame::evaluate):
* bindings/js/JSLocationCustom.cpp:
(WebCore::JSLocation::setHref):
(WebCore::JSLocation::setProtocol):
(WebCore::JSLocation::setHost):
(WebCore::JSLocation::setHostname):
(WebCore::JSLocation::setPort):
(WebCore::JSLocation::setPathname):
(WebCore::JSLocation::setSearch):
(WebCore::JSLocation::setHash):
(WebCore::JSLocation::replace):
(WebCore::JSLocation::assign):
* bindings/js/JSMessageEventCustom.cpp:
(WebCore::handleInitMessageEvent):
* bindings/js/JSSQLTransactionCustom.cpp:
(WebCore::JSSQLTransaction::executeSql):
* bindings/js/JSSQLTransactionSyncCustom.cpp:
(WebCore::JSSQLTransactionSync::executeSql):
* bindings/js/JSSharedWorkerCustom.cpp:
(WebCore::JSSharedWorkerConstructor::constructJSSharedWorker):
* bindings/js/JSStorageCustom.cpp:
(WebCore::JSStorage::putDelegate):
* bindings/js/JSWebGLRenderingContextCustom.cpp:
(WebCore::JSWebGLRenderingContext::getExtension):
* bindings/js/JSWebSocketCustom.cpp:
(WebCore::JSWebSocketConstructor::constructJSWebSocket):
(WebCore::JSWebSocket::send):
(WebCore::JSWebSocket::close):
* bindings/js/JSWorkerContextCustom.cpp:
(WebCore::JSWorkerContext::importScripts):
* bindings/js/JSWorkerCustom.cpp:
(WebCore::JSWorkerConstructor::constructJSWorker):
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::open):
(WebCore::JSXMLHttpRequest::send):
* bindings/js/JSXSLTProcessorCustom.cpp:
(WebCore::JSXSLTProcessor::setParameter):
(WebCore::JSXSLTProcessor::getParameter):
(WebCore::JSXSLTProcessor::removeParameter):
* bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::create):
* bindings/js/ScriptEventListener.cpp:
(WebCore::eventListenerHandlerBody):
* bindings/js/ScriptValue.cpp:
(WebCore::ScriptValue::toString):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateEventListenerCall):
(JSValueToNative):
(GenerateConstructorDefinition):
* bridge/c/c_utility.cpp:
(JSC::Bindings::convertValueToNPVariant):
* bridge/jni/jni_jsobject.mm:
(JavaJSObject::convertValueToJObject):
* bridge/jni/jsc/JNIUtilityPrivate.cpp:
(JSC::Bindings::convertArrayInstanceToJavaArray):
(JSC::Bindings::convertValueToJValue):
* bridge/jni/jsc/JavaFieldJSC.cpp:
(JavaField::dispatchValueFromInstance):
(JavaField::valueFromInstance):
(JavaField::dispatchSetValueToInstance):
(JavaField::setValueToInstance):
* bridge/jni/jsc/JavaInstanceJSC.cpp:
(JavaInstance::invokeMethod):
* testing/js/JSInternalsCustom.cpp:
(WebCore::JSInternals::setUserPreferredLanguages):

../WebKit/mac: 

Reviewed by Gavin Barraclough.

Mechanical changes to call value() after calling toString(), to
convert from "JS string" (JSString*) to "C++ string" (UString), since
toString() no longer returns a "C++ string".

* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::addValueToArray):
* WebView/WebFrame.mm:
(-[WebFrame _stringByEvaluatingJavaScriptFromString:forceUserGesture:]):
(-[WebFrame _stringByEvaluatingJavaScriptFromString:withGlobalObject:inScriptWorld:]):

../WebKit2: 

Reviewed by Gavin Barraclough.

Mechanical changes to call value() after calling toString(), to
convert from "JS string" (JSString*) to "C++ string" (UString), since
toString() no longer returns a "C++ string".

* WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:
(WebKit::NPRuntimeObjectMap::convertJSValueToNPVariant):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@105698 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
index dcf7a2f..22d6804 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -197,7 +197,7 @@
         if (element.isUndefinedOrNull())
             continue;
         
-        UString str = element.toString(exec);
+        UString str = element.toString(exec)->value(exec);
         strBuffer[k] = str.impl();
         totalSize += str.length();
         allStrings8Bit = allStrings8Bit && str.is8Bit();
@@ -272,9 +272,9 @@
             CallData callData;
             CallType callType = getCallData(conversionFunction, callData);
             if (callType != CallTypeNone)
-                str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
+                str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec);
             else
-                str = element.toString(exec);
+                str = element.toString(exec)->value(exec);
             strBuffer.append(str);
         }
     }
@@ -297,7 +297,7 @@
 
     UString separator;
     if (!exec->argument(0).isUndefined())
-        separator = exec->argument(0).toString(exec);
+        separator = exec->argument(0).toString(exec)->value(exec);
 
     unsigned k = 0;
     if (isJSArray(thisObj)) {
@@ -308,7 +308,7 @@
                 goto skipFirstLoop;
             JSValue element = array->getIndex(k);
             if (!element.isUndefinedOrNull())
-                strBuffer.append(element.toString(exec));
+                strBuffer.append(element.toString(exec)->value(exec));
             k++;
         }
 
@@ -319,7 +319,7 @@
                 strBuffer.append(',');
                 JSValue element = array->getIndex(k);
                 if (!element.isUndefinedOrNull())
-                    strBuffer.append(element.toString(exec));
+                    strBuffer.append(element.toString(exec)->value(exec));
             }
         } else {
             for (; k < length; k++) {
@@ -328,7 +328,7 @@
                 strBuffer.append(separator);
                 JSValue element = array->getIndex(k);
                 if (!element.isUndefinedOrNull())
-                    strBuffer.append(element.toString(exec));
+                    strBuffer.append(element.toString(exec)->value(exec));
             }
         }
     }
@@ -343,7 +343,7 @@
 
         JSValue element = thisObj->get(exec, k);
         if (!element.isUndefinedOrNull())
-            strBuffer.append(element.toString(exec));
+            strBuffer.append(element.toString(exec)->value(exec));
     }
 
     return JSValue::encode(strBuffer.build(exec));
@@ -429,7 +429,7 @@
             thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n));
         else {
             PutPropertySlot slot;
-            Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec));
+            Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec));
             thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
         }
     }
diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
index ab4de7d..86c4bd5 100644
--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h
+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
@@ -76,7 +76,7 @@
     if (propName.getUInt32(i))
         return baseObj->hasProperty(exec, i);
 
-    Identifier property(exec, propName.toString(exec));
+    Identifier property(exec, propName.toString(exec)->value(exec));
     if (exec->globalData().exception)
         return false;
     return baseObj->hasProperty(exec, property);
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp
index 79c5181..3651722 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp
@@ -185,7 +185,7 @@
 
 static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec)
 {
-    return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec))));
+    return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec)->value(exec))));
 }
 
 static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*)
diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp
index 96dea01..93261f6 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp
@@ -154,13 +154,13 @@
     bool useCustomFormat = false;
     UString customFormatString;
 
-    UString arg0String = exec->argument(0).toString(exec);
+    UString arg0String = exec->argument(0).toString(exec)->value(exec);
     if (arg0String == "custom" && !exec->argument(1).isUndefined()) {
         useCustomFormat = true;
-        customFormatString = exec->argument(1).toString(exec);
+        customFormatString = exec->argument(1).toString(exec)->value(exec);
     } else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) {
         dateStyle = styleFromArgString(arg0String, dateStyle);
-        timeStyle = styleFromArgString(exec->argument(1).toString(exec), timeStyle);
+        timeStyle = styleFromArgString(exec->argument(1).toString(exec)->value(exec), timeStyle);
     } else if (format != LocaleTime && !exec->argument(0).isUndefined())
         dateStyle = styleFromArgString(arg0String, dateStyle);
     else if (format != LocaleDate && !exec->argument(0).isUndefined())
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h
index 888bfe8..d6fa32f 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.h
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.h
@@ -42,14 +42,10 @@
             instance->finishCreation(globalData, message);
             return instance;
         }
+
         static ErrorInstance* create(ExecState* exec, Structure* structure, JSValue message)
         {
-            if (message.isUndefined()) {
-                ErrorInstance* instance = new (NotNull, allocateCell<ErrorInstance>(*exec->heap())) ErrorInstance(exec->globalData(), structure);
-                instance->finishCreation(exec->globalData(), UString());
-                return instance;
-            }
-            return create(exec->globalData(), structure, message.toString(exec));
+            return create(exec->globalData(), structure, message.isUndefined() ? UString() : message.toString(exec)->value(exec));
         }
 
         bool appendSourceToMessage() { return m_appendSourceToMessage; }
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
index e1a395c..7af29478 100644
--- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -101,7 +101,7 @@
     if (name.isUndefined())
         nameString = "Error";
     else {
-        nameString = name.toString(exec);
+        nameString = name.toString(exec)->value(exec);
         if (exec->hadException())
             return JSValue::encode(jsUndefined());
     }
@@ -118,7 +118,7 @@
     if (message.isUndefined())
         messageString = "";
     else {
-        messageString = message.toString(exec);
+        messageString = message.toString(exec)->value(exec);
         if (exec->hadException())
             return JSValue::encode(jsUndefined());
     }
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
index 05e971f..ce63ae9 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -113,7 +113,7 @@
     
 JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not a valid argument for '", op, "'");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a valid argument for '", op, "'");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -122,7 +122,7 @@
 
 JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not a constructor");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a constructor");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -131,7 +131,7 @@
 
 JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not a function");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a function");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -140,7 +140,7 @@
 
 JSObject* createNotAnObjectError(ExecState* exec, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not an object");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not an object");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
index e08e58c..956b216 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -96,17 +96,17 @@
     if (args.isEmpty())
         program = "(function() { \n})";
     else if (args.size() == 1)
-        program = makeUString("(function() { ", args.at(0).toString(exec), "\n})");
+        program = makeUString("(function() { ", args.at(0).toString(exec)->value(exec), "\n})");
     else {
         UStringBuilder builder;
         builder.append("(function(");
-        builder.append(args.at(0).toString(exec));
+        builder.append(args.at(0).toString(exec)->value(exec));
         for (size_t i = 1; i < args.size() - 1; i++) {
             builder.append(",");
-            builder.append(args.at(i).toString(exec));
+            builder.append(args.at(i).toString(exec)->value(exec));
         }
         builder.append(") { ");
-        builder.append(args.at(args.size() - 1).toString(exec));
+        builder.append(args.at(args.size() - 1).toString(exec)->value(exec));
         builder.append("\n})");
         program = builder.toUString();
     }
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
index 049b7b9..266ddc2 100644
--- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -207,7 +207,7 @@
             length = targetLength - numBoundArgs;
     }
 
-    Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec));
+    Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec)->value(exec));
 
     return JSValue::encode(JSBoundFunction::create(exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name));
 }
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index fa658a6..2afb6a0 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -1448,7 +1448,7 @@
     // a toString call raises an exception.
 
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
-        values[i].second = values[i].first.toString(exec);
+        values[i].second = values[i].first.toString(exec)->value(exec);
 
     if (exec->hadException()) {
         Heap::heap(this)->popTempSortVector(&values);
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index 144e377..9dcd636 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -145,13 +145,6 @@
     return static_cast<const JSObject*>(this)->toNumber(exec);
 }
 
-UString JSCell::toString(ExecState* exec) const
-{
-    if (isString())
-        return static_cast<const JSString*>(this)->toString(exec);
-    return static_cast<const JSObject*>(this)->toString(exec);
-}
-
 JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const
 {
     if (isString())
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index cf66ee9..a36bb7d 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -96,7 +96,6 @@
         bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
         bool toBoolean(ExecState*) const;
         JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
-        JS_EXPORT_PRIVATE UString toString(ExecState*) const;
         JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
         static void visitChildren(JSCell*, SlotVisitor&);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index bf6b31e..b82ab62 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -51,8 +51,7 @@
 
 static JSValue encode(ExecState* exec, const char* doNotEscape)
 {
-    UString str = exec->argument(0).toString(exec);
-    CString cstr = str.utf8(true);
+    CString cstr = exec->argument(0).toString(exec)->value(exec).utf8(true);
     if (!cstr.data())
         return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence."));
 
@@ -143,7 +142,7 @@
 static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
 {
     JSStringBuilder builder;
-    UString str = exec->argument(0).toString(exec);
+    UString str = exec->argument(0).toString(exec)->value(exec);
     
     if (str.is8Bit())
         return decode(exec, str.characters8(), str.length(), doNotUnescape, strict);
@@ -513,7 +512,7 @@
     if (!x.isString())
         return JSValue::encode(x);
 
-    UString s = x.toString(exec);
+    UString s = x.toString(exec)->value(exec);
 
     if (s.is8Bit()) {
         LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON);
@@ -556,7 +555,7 @@
     }
 
     // If ToString throws, we shouldn't call ToInt32.
-    UString s = value.toString(exec);
+    UString s = value.toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
@@ -565,7 +564,7 @@
 
 EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
 {
-    return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec))));
+    return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec)->value(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
@@ -623,7 +622,7 @@
         "*+-./@_";
 
     JSStringBuilder builder;
-    UString str = exec->argument(0).toString(exec);
+    UString str = exec->argument(0).toString(exec)->value(exec);
     if (str.is8Bit()) {
         const LChar* c = str.characters8();
         for (unsigned k = 0; k < str.length(); k++, c++) {
@@ -662,7 +661,7 @@
 EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec)
 {
     UStringBuilder builder;
-    UString str = exec->argument(0).toString(exec);
+    UString str = exec->argument(0).toString(exec)->value(exec);
     int k = 0;
     int len = str.length();
     
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index 05c6c29..83b1184 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -142,7 +142,7 @@
     if (object->inherits(&NumberObject::s_info))
         return jsNumber(object->toNumber(exec));
     if (object->inherits(&StringObject::s_info))
-        return jsString(exec, object->toString(exec));
+        return object->toString(exec);
     if (object->inherits(&BooleanObject::s_info))
         return object->toPrimitive(exec);
     return value;
@@ -223,25 +223,12 @@
             if (exec->hadException())
                 break;
 
-            UString propertyName;
-            if (name.getString(exec, propertyName)) {
-                m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
-                continue;
-            }
-
-            if (name.isNumber()) {
-                m_arrayReplacerPropertyNames.add(Identifier::from(exec, name.asNumber()));
-                continue;
-            }
-
             if (name.isObject()) {
                 if (!asObject(name)->inherits(&NumberObject::s_info) && !asObject(name)->inherits(&StringObject::s_info))
                     continue;
-                propertyName = name.toString(exec);
-                if (exec->hadException())
-                    break;
-                m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
             }
+
+            m_arrayReplacerPropertyNames.add(Identifier(exec, name.toString(exec)->value(exec)));
         }
         return;
     }
@@ -825,8 +812,7 @@
 {
     if (!exec->argumentCount())
         return throwVMError(exec, createError(exec, "JSON.parse requires at least one parameter"));
-    JSValue value = exec->argument(0);
-    UString source = value.toString(exec);
+    UString source = exec->argument(0).toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
 
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 653ddf0..060fcff 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -518,11 +518,11 @@
     return primitive.toNumber(exec);
 }
 
-UString JSObject::toString(ExecState* exec) const
+JSString* JSObject::toString(ExecState* exec) const
 {
     JSValue primitive = toPrimitive(exec, PreferString);
     if (exec->hadException())
-        return "";
+        return jsEmptyString(exec);
     return primitive.toString(exec);
 }
 
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index 6d45e82..7774920 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -141,7 +141,7 @@
         JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const;
         bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
         JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
-        JS_EXPORT_PRIVATE UString toString(ExecState*) const;
+        JS_EXPORT_PRIVATE JSString* toString(ExecState*) const;
 
         // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0,
         // because this call may come from inside the compiler.
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index 93193b5..4e98f9d 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -229,11 +229,6 @@
     return jsToNumber(value(exec));
 }
 
-UString JSString::toString(ExecState* exec) const
-{
-    return value(exec);
-}
-
 inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
     StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), globalObject->stringObjectStructure());
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index 7ca90de..c0637a6 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -217,7 +217,6 @@
         JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const;
         bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
         JSObject* toObject(ExecState*, JSGlobalObject*) const;
-        UString toString(ExecState*) const;
         double toNumber(ExecState*) const;
         
         bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
@@ -453,24 +452,11 @@
         return isTrue(); // false, null, and undefined all convert to false.
     }
 
-    inline UString JSValue::toString(ExecState* exec) const
+    inline JSString* JSValue::toString(ExecState* exec) const
     {
         if (isString())
-            return static_cast<JSString*>(asCell())->value(exec);
-        if (isInt32())
-            return exec->globalData().numericStrings.add(asInt32());
-        if (isDouble())
-            return exec->globalData().numericStrings.add(asDouble());
-        if (isTrue())
-            return "true";
-        if (isFalse())
-            return "false";
-        if (isNull())
-            return "null";
-        if (isUndefined())
-            return "undefined";
-        ASSERT(isCell());
-        return asCell()->toString(exec);
+            return static_cast<JSString*>(asCell());
+        return toStringSlowCase(exec);
     }
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp
index a5d3d93..6b803c3 100644
--- a/Source/JavaScriptCore/runtime/JSValue.cpp
+++ b/Source/JavaScriptCore/runtime/JSValue.cpp
@@ -204,10 +204,9 @@
     return asObject(asCell())->globalObject();
 }
 
-JSString* JSValue::toPrimitiveString(ExecState* exec) const
+JSString* JSValue::toStringSlowCase(ExecState* exec) const
 {
-    if (isString())
-        return static_cast<JSString*>(asCell());
+    ASSERT(!isString());
     if (isInt32())
         return jsString(&exec->globalData(), exec->globalData().numericStrings.add(asInt32()));
     if (isDouble())
@@ -222,10 +221,11 @@
         return jsNontrivialString(exec, exec->propertyNames().undefined.ustring());
 
     ASSERT(isCell());
-    JSValue v = asCell()->toPrimitive(exec, NoPreference);
-    if (v.isString())
-        return static_cast<JSString*>(v.asCell());
-    return jsString(&exec->globalData(), v.toString(exec));
+    JSValue value = asCell()->toPrimitive(exec, PreferString);
+    if (exec->hadException())
+        return jsEmptyString(exec);
+    ASSERT(!value.isObject());
+    return value.toString(exec);
 }
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index de5e181..e3415eb 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -197,8 +197,7 @@
         // toNumber conversion is expected to be side effect free if an exception has
         // been set in the ExecState already.
         double toNumber(ExecState*) const;
-        UString toString(ExecState*) const;
-        JSString* toPrimitiveString(ExecState*) const;
+        JSString* toString(ExecState*) const;
         JSObject* toObject(ExecState*) const;
         JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
@@ -245,6 +244,7 @@
 
         inline const JSValue asValue() const { return *this; }
         JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
+        JSString* toStringSlowCase(ExecState*) const;
         JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
         JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
 
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
index 4612b56..fb90bcd 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -447,7 +447,7 @@
         radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0
 
     if (radix == 10)
-        return JSValue::encode(jsString(exec, jsNumber(x).toString(exec)));
+        return JSValue::encode(jsNumber(x).toString(exec));
 
     // Fast path for number to character conversion.
     if (radix == 36) {
@@ -474,7 +474,7 @@
     if (!toThisNumber(exec->hostThisValue(), x))
         return throwVMTypeError(exec);
 
-    return JSValue::encode(jsString(exec, jsNumber(x).toString(exec)));
+    return JSValue::encode(jsNumber(x).toString(exec));
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec)
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index abcff8c..d96c1de 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -149,7 +149,7 @@
 {
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested property descriptor of a value that is not an object."));
-    UString propertyName = exec->argument(1).toString(exec);
+    UString propertyName = exec->argument(1).toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
     JSObject* object = asObject(exec->argument(0));
@@ -292,7 +292,7 @@
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Properties can only be defined on Objects."));
     JSObject* O = asObject(exec->argument(0));
-    UString propertyName = exec->argument(1).toString(exec);
+    UString propertyName = exec->argument(1).toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
     PropertyDescriptor descriptor;
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
index 3f4dc19..7ca7dae6 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -118,7 +118,7 @@
 EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)))));
+    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))));
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
@@ -149,7 +149,7 @@
     CallData callData;
     if (getCallData(exec->argument(1), callData) == CallTypeNone)
         return throwVMError(exec, createSyntaxError(exec, "invalid getter usage"));
-    thisObject->methodTable()->defineGetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)), 0);
+    thisObject->methodTable()->defineGetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), asObject(exec->argument(1)), 0);
     return JSValue::encode(jsUndefined());
 }
 
@@ -162,7 +162,7 @@
     CallData callData;
     if (getCallData(exec->argument(1), callData) == CallTypeNone)
         return throwVMError(exec, createSyntaxError(exec, "invalid setter usage"));
-    thisObject->methodTable()->defineSetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)), 0);
+    thisObject->methodTable()->defineSetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), asObject(exec->argument(1)), 0);
     return JSValue::encode(jsUndefined());
 }
 
@@ -172,7 +172,7 @@
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
-    return JSValue::encode(thisObject->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
+    return JSValue::encode(thisObject->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
@@ -181,13 +181,13 @@
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
-    return JSValue::encode(thisObject->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
+    return JSValue::encode(thisObject->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)))));
+    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))));
 }
 
 // 15.2.4.3 Object.prototype.toLocaleString()
diff --git a/Source/JavaScriptCore/runtime/Operations.cpp b/Source/JavaScriptCore/runtime/Operations.cpp
index b89746f..459feb4 100644
--- a/Source/JavaScriptCore/runtime/Operations.cpp
+++ b/Source/JavaScriptCore/runtime/Operations.cpp
@@ -47,13 +47,11 @@
     JSValue p1 = v1.toPrimitive(callFrame);
     JSValue p2 = v2.toPrimitive(callFrame);
 
-    if (p1.isString()) {
-        return p2.isString()
-            ? jsString(callFrame, asString(p1), asString(p2))
-            : jsString(callFrame, asString(p1), jsString(callFrame, p2.toString(callFrame)));
-    }
+    if (p1.isString())
+        return jsString(callFrame, asString(p1), p2.toString(callFrame));
+
     if (p2.isString())
-        return jsString(callFrame, jsString(callFrame, p1.toString(callFrame)), asString(p2));
+        return jsString(callFrame, p1.toString(callFrame), asString(p2));
 
     return jsNumber(p1.toNumber(callFrame) + p2.toNumber(callFrame));
 }
diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h
index ca2174f..9452838 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -81,10 +81,7 @@
 
         for (unsigned i = 0; i < count; ++i) {
             JSValue v = strings[i].jsValue();
-            if (v.isString())
-                ropeBuilder.append(asString(v));
-            else
-                ropeBuilder.append(jsString(globalData, v.toString(exec)));
+            ropeBuilder.append(v.toString(exec));
 
             if (ropeBuilder.length() < oldLength) // True for overflow
                 return throwOutOfMemoryError(exec);
@@ -97,20 +94,13 @@
     {
         JSGlobalData* globalData = &exec->globalData();
         JSString::RopeBuilder ropeBuilder(*globalData);
-
-        if (thisValue.isString())
-            ropeBuilder.append(asString(thisValue));
-        else
-            ropeBuilder.append(jsString(globalData, thisValue.toString(exec)));
+        ropeBuilder.append(thisValue.toString(exec));
 
         unsigned oldLength = 0;
 
         for (unsigned i = 0; i < exec->argumentCount(); ++i) {
             JSValue v = exec->argument(i);
-            if (v.isString())
-                ropeBuilder.append(asString(v));
-            else
-                ropeBuilder.append(jsString(globalData, v.toString(exec)));
+            ropeBuilder.append(v.toString(exec));
 
             if (ropeBuilder.length() < oldLength) // True for overflow
                 return throwOutOfMemoryError(exec);
@@ -300,11 +290,8 @@
         if (v1.isNumber() && v2.isNumber())
             return jsNumber(v1.asNumber() + v2.asNumber());
         
-        if (v1.isString()) {
-            return v2.isString()
-                ? jsString(callFrame, asString(v1), asString(v2))
-                : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
-        }
+        if (v1.isString() && !v2.isObject())
+            return jsString(callFrame, asString(v1), v2.toString(callFrame));
 
         // All other cases are pretty uncommon
         return jsAddSlowCase(callFrame, v1, v2);
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index c0a71de..53e880e 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -298,7 +298,7 @@
 
 void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value)
 {
-    asRegExpConstructor(baseObject)->setInput(value.toString(exec));
+    asRegExpConstructor(baseObject)->setInput(value.toString(exec)->value(exec));
 }
 
 void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value)
@@ -323,13 +323,13 @@
         return asObject(arg0);
     }
 
-    UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
+    UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec)->value(exec);
     if (exec->hadException())
         return 0;
 
     RegExpFlags flags = NoFlags;
     if (!arg1.isUndefined()) {
-        flags = regExpFlags(arg1.toString(exec));
+        flags = regExpFlags(arg1.toString(exec)->value(exec));
         if (exec->hadException())
             return 0;
         if (flags == InvalidFlags)
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index 4553f7a..4c192ff 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -231,7 +231,7 @@
 bool RegExpObject::match(ExecState* exec)
 {
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
-    UString input = exec->argument(0).toString(exec);
+    UString input = exec->argument(0).toString(exec)->value(exec);
     JSGlobalData* globalData = &exec->globalData();
     if (!regExp()->global()) {
         int position;
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
index 6c79f94..9074e97 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -110,13 +110,13 @@
             return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
         regExp = asRegExpObject(arg0)->regExp();
     } else {
-        UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec);
+        UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec)->value(exec);
         if (exec->hadException())
             return JSValue::encode(jsUndefined());
 
         RegExpFlags flags = NoFlags;
         if (!arg1.isUndefined()) {
-            flags = regExpFlags(arg1.toString(exec));
+            flags = regExpFlags(arg1.toString(exec)->value(exec));
             if (exec->hadException())
                 return JSValue::encode(jsUndefined());
             if (flags == InvalidFlags)
@@ -153,7 +153,7 @@
         postfix[index++] = 'i';
     if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec))
         postfix[index] = 'm';
-    UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec);
+    UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec);
     // If source is empty, use "/(?:)/" to avoid colliding with comment syntax
     return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix));
 }
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp
index d2f75a0..e03a87f 100644
--- a/Source/JavaScriptCore/runtime/StringConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp
@@ -95,10 +95,7 @@
     if (!exec->argumentCount())
         return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure()));
     
-    JSString* string = exec->argument(0).isString()
-        ? asString(exec->argument(0))
-        : jsString(exec, exec->argument(0).toString(exec));
-    return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure(), string));
+    return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec)));
 }
 
 ConstructType StringConstructor::getConstructData(JSCell*, ConstructData& constructData)
@@ -111,7 +108,7 @@
 {
     if (!exec->argumentCount())
         return JSValue::encode(jsEmptyString(exec));
-    return JSValue::encode(jsString(exec, exec->argument(0).toString(exec)));
+    return JSValue::encode(exec->argument(0).toString(exec));
 }
 
 CallType StringConstructor::getCallData(JSCell*, CallData& callData)
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 9dd4f81..00f1ceb 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -445,7 +445,7 @@
     CallData callData;
     CallType callType = getCallData(replaceValue, callData);
     if (callType == CallTypeNone)
-        replacementString = replaceValue.toString(exec);
+        replacementString = replaceValue.toString(exec)->value(exec);
 
     const UString& source = string->value(exec);
     unsigned sourceLen = source.length();
@@ -502,10 +502,7 @@
 
                 cachedCall.setThis(jsUndefined());
                 JSValue result = cachedCall.call();
-                if (LIKELY(result.isString()))
-                    replacements.append(asString(result)->value(exec));
-                else
-                    replacements.append(result.toString(cachedCall.newCallFrame(exec)));
+                replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec));
                 if (exec->hadException())
                     break;
 
@@ -547,10 +544,7 @@
 
                 cachedCall.setThis(jsUndefined());
                 JSValue result = cachedCall.call();
-                if (LIKELY(result.isString()))
-                    replacements.append(asString(result)->value(exec));
-                else
-                    replacements.append(result.toString(cachedCall.newCallFrame(exec)));
+                replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec));
                 if (exec->hadException())
                     break;
 
@@ -594,7 +588,7 @@
                 args.append(jsNumber(completeMatchStart));
                 args.append(string);
 
-                replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec));
+                replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec)->value(exec));
                 if (exec->hadException())
                     break;
             } else {
@@ -633,7 +627,7 @@
 static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue, JSValue replaceValue)
 {
     const UString& string = jsString->value(exec);
-    UString searchString = searchValue.toString(exec);
+    UString searchString = searchValue.toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
@@ -653,7 +647,7 @@
             return JSValue::encode(jsUndefined());
     }
 
-    UString replaceString = replaceValue.toString(exec);
+    UString replaceString = replaceValue.toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
@@ -665,12 +659,9 @@
 EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    if (!thisValue.isString()) {
-        if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
-            return throwVMTypeError(exec);
-        thisValue = jsString(exec, thisValue.toString(exec));
-    }
-    JSString* string = asString(thisValue);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    JSString* string = thisValue.toString(exec);
     JSValue searchValue = exec->argument(0);
     JSValue replaceValue = exec->argument(1);
 
@@ -698,7 +689,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     unsigned len = s.length();
     JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
@@ -718,7 +709,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     unsigned len = s.length();
     JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
@@ -739,12 +730,9 @@
 EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    if (thisValue.isString() && (exec->argumentCount() == 1)) {
-        JSValue v = exec->argument(0);
-        return JSValue::encode(v.isString()
-            ? jsString(exec, asString(thisValue), asString(v))
-            : jsString(exec, asString(thisValue), jsString(&exec->globalData(), v.toString(exec))));
-    }
+    if (thisValue.isString() && (exec->argumentCount() == 1))
+        return JSValue::encode(jsString(exec, asString(thisValue), exec->argument(0).toString(exec)));
+
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     return JSValue::encode(jsStringFromArguments(exec, thisValue));
@@ -755,12 +743,12 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     int len = s.length();
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
-    UString u2 = a0.toString(exec);
+    UString u2 = a0.toString(exec)->value(exec);
     int pos;
     if (a1.isUndefined())
         pos = 0;
@@ -786,13 +774,13 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     int len = s.length();
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
 
-    UString u2 = a0.toString(exec);
+    UString u2 = a0.toString(exec)->value(exec);
     double dpos = a1.toIntegerPreserveNaN(exec);
     if (dpos < 0)
         dpos = 0;
@@ -810,7 +798,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSGlobalData* globalData = &exec->globalData();
 
     JSValue a0 = exec->argument(0);
@@ -825,7 +813,7 @@
          *  replaced with the result of the expression new RegExp(regexp).
          *  Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
          */
-        reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec), NoFlags);
+        reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags);
         if (!reg->isValid())
             return throwVMError(exec, createSyntaxError(exec, reg->errorMessage()));
     }
@@ -862,7 +850,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSGlobalData* globalData = &exec->globalData();
 
     JSValue a0 = exec->argument(0);
@@ -877,7 +865,7 @@
          *  replaced with the result of the expression new RegExp(regexp).
          *  Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
          */
-        reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec), NoFlags);
+        reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags);
         if (!reg->isValid())
             return throwVMError(exec, createSyntaxError(exec, reg->errorMessage()));
     }
@@ -893,7 +881,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     int len = s.length();
 
     JSValue a0 = exec->argument(0);
@@ -925,7 +913,7 @@
 
     // 2. Let S be the result of calling ToString, giving it the this value as its argument.
     // 6. Let s be the number of characters in S.
-    UString input = thisValue.toString(exec);
+    UString input = thisValue.toString(exec)->value(exec);
 
     // 3. Let A be a new array created as if by the expression new Array()
     //    where Array is the standard built-in constructor with that name.
@@ -1027,7 +1015,7 @@
             }
         }
     } else {
-        UString separator = separatorValue.toString(exec);
+        UString separator = separatorValue.toString(exec)->value(exec);
 
         // 9. If lim == 0, return A.
         if (!limit)
@@ -1114,7 +1102,7 @@
         // CheckObjectCoercible
         return throwVMTypeError(exec);
     } else {
-        uString = thisValue.toString(exec);
+        uString = thisValue.toString(exec)->value(exec);
         if (exec->hadException())
             return JSValue::encode(jsUndefined());
         len = uString.length();
@@ -1144,24 +1132,16 @@
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    int len;
-    JSString* jsString = 0;
-    UString uString;
-    if (thisValue.isString()) {
-        jsString = static_cast<JSString*>(thisValue.asCell());
-        len = jsString->length();
-    } else if (thisValue.isUndefinedOrNull()) {
-        // CheckObjectCoercible
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    } else {
-        uString = thisValue.toString(exec);
-        if (exec->hadException())
-            return JSValue::encode(jsUndefined());
-        len = uString.length();
-    }
+
+    JSString* jsString = thisValue.toString(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
+    int len = jsString->length();
 
     double start = a0.toNumber(exec);
     double end;
@@ -1185,9 +1165,7 @@
     }
     unsigned substringStart = static_cast<unsigned>(start);
     unsigned substringLength = static_cast<unsigned>(end) - substringStart;
-    if (jsString)
-        return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
-    return JSValue::encode(jsSubstring(exec, uString, substringStart, substringLength));
+    return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
@@ -1195,7 +1173,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    JSString* sVal = thisValue.isString() ? asString(thisValue) : jsString(exec, thisValue.toString(exec));
+    JSString* sVal = thisValue.toString(exec);
     const UString& s = sVal->value(exec);
 
     int sSize = s.length();
@@ -1214,7 +1192,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    JSString* sVal = thisValue.isString() ? asString(thisValue) : jsString(exec, thisValue.toString(exec));
+    JSString* sVal = thisValue.toString(exec);
     const UString& s = sVal->value(exec);
 
     int sSize = s.length();
@@ -1257,10 +1235,10 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
 
     JSValue a0 = exec->argument(0);
-    return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec))));
+    return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec)->value(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec)
@@ -1268,7 +1246,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<big>", s, "</big>"));
 }
 
@@ -1277,7 +1255,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<small>", s, "</small>"));
 }
 
@@ -1286,7 +1264,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<blink>", s, "</blink>"));
 }
 
@@ -1295,7 +1273,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<b>", s, "</b>"));
 }
 
@@ -1304,7 +1282,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<tt>", s, "</tt>"));
 }
 
@@ -1313,7 +1291,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<i>", s, "</i>"));
 }
 
@@ -1322,7 +1300,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<strike>", s, "</strike>"));
 }
 
@@ -1331,7 +1309,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<sub>", s, "</sub>"));
 }
 
@@ -1340,7 +1318,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<sup>", s, "</sup>"));
 }
 
@@ -1349,9 +1327,9 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
-    return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>"));
+    return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec)->value(exec), "\">", s, "</font>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
@@ -1359,7 +1337,7 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
 
     uint32_t smallInteger;
@@ -1396,7 +1374,7 @@
         return JSValue::encode(jsNontrivialString(exec, impl));
     }
 
-    return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>"));
+    return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec)->value(exec), "\">", s, "</font>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec)
@@ -1404,9 +1382,9 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
-    return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>"));
+    return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec)->value(exec), "\">", s, "</a>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec)
@@ -1414,9 +1392,9 @@
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
-    UString linkText = a0.toString(exec);
+    UString linkText = a0.toString(exec)->value(exec);
 
     unsigned linkTextSize = linkText.length();
     unsigned stringSize = s.length();
@@ -1459,7 +1437,7 @@
 {
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwTypeError(exec);
-    UString str = thisValue.toString(exec);
+    UString str = thisValue.toString(exec)->value(exec);
     unsigned left = 0;
     if (trimKind & TrimLeft) {
         while (left < str.length() && isTrimWhitespace(str[left]))