REGRESSION(r168256): JSString can get 8-bit flag wrong when re-using AtomicStrings.
<https://webkit.org/b/133574>
<rdar://problem/18051847>
Source/JavaScriptCore:
The optimization that resolves JSRopeStrings into an existing
AtomicString (to save time and memory by avoiding StringImpl allocation)
had a bug that it wasn't copying the 8-bit flag from the AtomicString.
This could lead to a situation where a 16-bit StringImpl containing
only 8-bit characters is sitting in the AtomicString table, is found
by the rope resolution optimization, and gives you a rope that thinks
it's all 8-bit, but has a fiber with 16-bit characters.
Resolving that rope will then yield incorrect results.
This was all caught by an assertion, but very hard to reproduce.
Test: js/dopey-rope-with-16-bit-propertyname.html
Reviewed by Darin Adler.
* runtime/JSString.cpp:
(JSC::JSRopeString::resolveRopeToAtomicString):
(JSC::JSRopeString::resolveRopeToExistingAtomicString):
* runtime/JSString.h:
(JSC::JSString::setIs8Bit):
(JSC::JSString::toExistingAtomicString):
LayoutTests:
Add a tests that creates a 16-bit AtomicString with only 8-bit characters,
then tiers up into baseline JIT and uses that string as part of a rope-within-a-rope
and serializes that rope to get an incorrect concatenation.
Reviewed by Darin Adler.
* js/dopey-rope-with-16-bit-propertyname-expected.txt: Added.
* js/dopey-rope-with-16-bit-propertyname.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@172727 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index ff3b628..3ea2b7e 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -161,6 +161,7 @@
if (m_length > maxLengthForOnStackResolve) {
resolveRope(exec);
m_value = AtomicString(m_value);
+ setIs8Bit(m_value.impl()->is8Bit());
return;
}
@@ -168,10 +169,12 @@
LChar buffer[maxLengthForOnStackResolve];
resolveRopeInternal8(buffer);
m_value = AtomicString(buffer, m_length);
+ setIs8Bit(m_value.impl()->is8Bit());
} else {
UChar buffer[maxLengthForOnStackResolve];
resolveRopeInternal16(buffer);
m_value = AtomicString(buffer, m_length);
+ setIs8Bit(m_value.impl()->is8Bit());
}
clearFibers();
@@ -193,6 +196,7 @@
resolveRope(exec);
if (AtomicStringImpl* existingAtomicString = AtomicString::find(m_value.impl())) {
m_value = *existingAtomicString;
+ setIs8Bit(m_value.impl()->is8Bit());
clearFibers();
return existingAtomicString;
}
@@ -204,6 +208,7 @@
resolveRopeInternal8(buffer);
if (AtomicStringImpl* existingAtomicString = AtomicString::find(buffer, m_length)) {
m_value = *existingAtomicString;
+ setIs8Bit(m_value.impl()->is8Bit());
clearFibers();
return existingAtomicString;
}
@@ -212,6 +217,7 @@
resolveRopeInternal16(buffer);
if (AtomicStringImpl* existingAtomicString = AtomicString::find(buffer, m_length)) {
m_value = *existingAtomicString;
+ setIs8Bit(m_value.impl()->is8Bit());
clearFibers();
return existingAtomicString;
}