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;
         }