+ ASSERT(string.is8Bit());
+ m_accumulatedStringsLength += string.length();
+ m_strings.uncheckedAppend({ string, string });
+}
+
+ALWAYS_INLINE void JSStringJoiner::appendLiteral(const Identifier& literal)
+{
+ m_accumulatedStringsLength += literal.length();
+ ASSERT(literal.string().is8Bit());
+ m_strings.uncheckedAppend({ literal.string(), { } });
+}
+
+ALWAYS_INLINE void JSStringJoiner::appendEmptyString()
+{
+ m_strings.uncheckedAppend({ { }, { } });
+}
+
+ALWAYS_INLINE void JSStringJoiner::append(ExecState& state, JSValue value)
+{
+ // The following code differs from using the result of JSValue::toString in the following ways:
+ // 1) It's inlined more than JSValue::toString is.
+ // 2) It includes conversion to WTF::String in a way that avoids allocating copies of substrings.
+ // 3) It doesn't create a JSString for numbers, true, or false.
+ // 4) It turns undefined and null into the empty string instead of "undefined" and "null".
+ // 5) It uses optimized code paths for all the cases known to be 8-bit and for the empty string.
+
+ if (value.isCell()) {
+ if (value.asCell()->isString()) {
+ append(asString(value)->viewWithUnderlyingString(state));
+ return;
+ }
+ append(value.toString(&state)->viewWithUnderlyingString(state));