Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (241254 => 241255)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2019-02-11 03:25:52 UTC (rev 241254)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2019-02-11 04:10:08 UTC (rev 241255)
@@ -517,11 +517,19 @@
auto bytecode = pc->as<OpAdd>();
JSValue v1 = GET_C(bytecode.m_lhs).jsValue();
JSValue v2 = GET_C(bytecode.m_rhs).jsValue();
+ JSValue result;
ArithProfile& arithProfile = *exec->codeBlock()->arithProfileForPC(pc);
arithProfile.observeLHSAndRHS(v1, v2);
- JSValue result = jsAdd(exec, v1, v2);
+ if (v1.isString() && !v2.isObject()) {
+ JSString* v2String = v2.toString(exec);
+ if (LIKELY(!throwScope.exception()))
+ result = jsString(exec, asString(v1), v2String);
+ } else if (v1.isNumber() && v2.isNumber())
+ result = jsNumber(v1.asNumber() + v2.asNumber());
+ else
+ result = jsAddSlowCase(exec, v1, v2);
RETURN_WITH_PROFILING(result, {
updateArithProfileForBinaryArithOp(exec, pc, result, v1, v2);
Modified: trunk/Source/_javascript_Core/runtime/JSString.h (241254 => 241255)
--- trunk/Source/_javascript_Core/runtime/JSString.h 2019-02-11 03:25:52 UTC (rev 241254)
+++ trunk/Source/_javascript_Core/runtime/JSString.h 2019-02-11 04:10:08 UTC (rev 241255)
@@ -486,8 +486,6 @@
friend JSString* jsString(ExecState*, JSString*, JSString*);
- friend JSString* jsString(ExecState*, const String&, JSString*);
- friend JSString* jsString(ExecState*, JSString*, const String&);
friend JSString* jsString(ExecState*, JSString*, JSString*, JSString*);
friend JSString* jsString(ExecState*, const String&, const String&, const String&);
};
Modified: trunk/Source/_javascript_Core/runtime/Operations.cpp (241254 => 241255)
--- trunk/Source/_javascript_Core/runtime/Operations.cpp 2019-02-11 03:25:52 UTC (rev 241254)
+++ trunk/Source/_javascript_Core/runtime/Operations.cpp 2019-02-11 04:10:08 UTC (rev 241255)
@@ -52,23 +52,13 @@
RETURN_IF_EXCEPTION(scope, { });
if (p1.isString()) {
- if (p2.isCell()) {
- JSString* p2String = p2.toString(callFrame);
- RETURN_IF_EXCEPTION(scope, { });
- RELEASE_AND_RETURN(scope, jsString(callFrame, asString(p1), p2String));
- }
- String p2String = p2.toWTFString(callFrame);
+ JSString* p2String = p2.toString(callFrame);
RETURN_IF_EXCEPTION(scope, { });
RELEASE_AND_RETURN(scope, jsString(callFrame, asString(p1), p2String));
}
if (p2.isString()) {
- if (p2.isCell()) {
- JSString* p1String = p1.toString(callFrame);
- RETURN_IF_EXCEPTION(scope, { });
- RELEASE_AND_RETURN(scope, jsString(callFrame, p1String, asString(p2)));
- }
- String p1String = p1.toWTFString(callFrame);
+ JSString* p1String = p1.toString(callFrame);
RETURN_IF_EXCEPTION(scope, { });
RELEASE_AND_RETURN(scope, jsString(callFrame, p1String, asString(p2)));
}
Modified: trunk/Source/_javascript_Core/runtime/Operations.h (241254 => 241255)
--- trunk/Source/_javascript_Core/runtime/Operations.h 2019-02-11 03:25:52 UTC (rev 241254)
+++ trunk/Source/_javascript_Core/runtime/Operations.h 2019-02-11 04:10:08 UTC (rev 241255)
@@ -37,50 +37,6 @@
bool jsIsObjectTypeOrNull(CallFrame*, JSValue);
size_t normalizePrototypeChain(CallFrame*, JSCell*, bool& sawPolyProto);
-// This is a lower bound on the extra memory we expect to write if we were to allocate a rope instead of copying.
-// Note, it doesn't differentiate between 8 and 16-bit strings because 16-bit strings are relatively rare.
-constexpr unsigned minRopeStringLength = sizeof(JSRopeString);
-
-ALWAYS_INLINE JSString* jsString(ExecState* exec, const String& u1, JSString* s2)
-{
- VM& vm = exec->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- unsigned length1 = u1.length();
- if (!length1)
- return s2;
- unsigned length2 = s2->length();
- if (!length2)
- return jsString(&vm, u1);
-
- if (length1 + length2 >= minRopeStringLength)
- return jsString(exec, jsString(&vm, u1), s2);
-
- const String& u2 = s2->value(exec);
- RETURN_IF_EXCEPTION(scope, { });
- return JSString::create(vm, makeString(u1, u2).releaseImpl().releaseNonNull());
-}
-
-ALWAYS_INLINE JSString* jsString(ExecState* exec, JSString* s1, const String& u2)
-{
- VM& vm = exec->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- unsigned length1 = s1->length();
- if (!length1)
- return jsString(&vm, u2);
- unsigned length2 = u2.length();
- if (!length2)
- return s1;
-
- if (length1 + length2 >= minRopeStringLength)
- return jsString(exec, s1, jsString(&vm, u2));
-
- const String& u1 = s1->value(exec);
- RETURN_IF_EXCEPTION(scope, { });
- return JSString::create(vm, makeString(u1, u2).releaseImpl().releaseNonNull());
-}
-
ALWAYS_INLINE JSString* jsString(ExecState* exec, JSString* s1, JSString* s2)
{
VM& vm = exec->vm();
@@ -98,14 +54,7 @@
return nullptr;
}
- if (length1 + length2 >= minRopeStringLength)
- return JSRopeString::create(vm, s1, s2);
-
- const String& u1 = s1->value(exec);
- RETURN_IF_EXCEPTION(scope, { });
- const String& u2 = s2->value(exec);
- RETURN_IF_EXCEPTION(scope, { });
- return JSString::create(vm, makeString(u1, u2).releaseImpl().releaseNonNull());
+ return JSRopeString::create(vm, s1, s2);
}
ALWAYS_INLINE JSString* jsString(ExecState* exec, JSString* s1, JSString* s2, JSString* s3)
@@ -130,17 +79,7 @@
throwOutOfMemoryError(exec, scope);
return nullptr;
}
-
- if (length1 + length2 + length3 >= minRopeStringLength)
- return JSRopeString::create(vm, s1, s2, s3);
-
- const String& u1 = s1->value(exec);
- RETURN_IF_EXCEPTION(scope, { });
- const String& u2 = s2->value(exec);
- RETURN_IF_EXCEPTION(scope, { });
- const String& u3 = s3->value(exec);
- RETURN_IF_EXCEPTION(scope, { });
- return JSString::create(vm, makeString(u1, u2, u3).releaseImpl().releaseNonNull());
+ return JSRopeString::create(vm, s1, s2, s3);
}
ALWAYS_INLINE JSString* jsString(ExecState* exec, const String& u1, const String& u2, const String& u3)
@@ -170,10 +109,7 @@
return nullptr;
}
- if (length1 + length2 + length3 >= minRopeStringLength)
- return JSRopeString::create(*vm, jsString(vm, u1), jsString(vm, u2), jsString(vm, u3));
-
- return JSString::create(*vm, makeString(u1, u2, u3).releaseImpl().releaseNonNull());
+ return JSRopeString::create(*vm, jsString(vm, u1), jsString(vm, u2), jsString(vm, u3));
}
ALWAYS_INLINE JSValue jsStringFromRegisterArray(ExecState* exec, Register* strings, unsigned count)
@@ -389,31 +325,16 @@
// 13962 Add case: 5 3
// 4000 Add case: 3 5
-
-ALWAYS_INLINE JSValue jsAddNonNumber(CallFrame* callFrame, JSValue v1, JSValue v2)
-{
- VM& vm = callFrame->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
- ASSERT(!v1.isNumber() || !v2.isNumber());
-
- if (v1.isString() && !v2.isObject()) {
- if (v2.isString())
- RELEASE_AND_RETURN(scope, jsString(callFrame, asString(v1), asString(v2)));
- String s2 = v2.toWTFString(callFrame);
- RETURN_IF_EXCEPTION(scope, { });
- RELEASE_AND_RETURN(scope, jsString(callFrame, asString(v1), s2));
- }
-
- // All other cases are pretty uncommon
- RELEASE_AND_RETURN(scope, jsAddSlowCase(callFrame, v1, v2));
-}
-
ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
{
if (v1.isNumber() && v2.isNumber())
return jsNumber(v1.asNumber() + v2.asNumber());
- return jsAddNonNumber(callFrame, v1, v2);
+ if (v1.isString() && !v2.isObject())
+ return jsString(callFrame, asString(v1), v2.toString(callFrame));
+
+ // All other cases are pretty uncommon
+ return jsAddSlowCase(callFrame, v1, v2);
}
ALWAYS_INLINE JSValue jsSub(ExecState* exec, JSValue v1, JSValue v2)