Bug 1482093 - Make conversions from UTF-16 and Latin1 to UTF-8 utilize the slop in the first ASCII-sized allocation. r=nika
authorHenri Sivonen <hsivonen@hsivonen.fi>
Mon, 20 Aug 2018 18:47:39 +0000
changeset 487574 e35c67de74b1eec697be6db697bde8d790b92594
parent 487573 7c934a5a2c05b8dff1b60315dba9c29e1e3f8ad3
child 487575 feaff184f7758a2aecd7ba36d274759dfac49208
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1482093
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1482093 - Make conversions from UTF-16 and Latin1 to UTF-8 utilize the slop in the first ASCII-sized allocation. r=nika MozReview-Commit-ID: 4Y8K1JZkXWq Differential Revision: https://phabricator.services.mozilla.com/D3016
servo/support/gecko/nsstring/src/conversions.rs
--- a/servo/support/gecko/nsstring/src/conversions.rs
+++ b/servo/support/gecko/nsstring/src/conversions.rs
@@ -325,45 +325,45 @@ impl nsACString {
             if worst_case <= inline_capacity {
                 Some(worst_case)
             } else {
                 None
             }
         } else {
             None
         };
-        let (filled, num_ascii, mut handle) = if worst_case_needed.is_none() &&
+        let (filled, read, mut handle) = if worst_case_needed.is_none() &&
                                                  long_string_stars_with_basic_latin(other) {
             let new_len_with_ascii = old_len.checked_add(other.len()).ok_or(())?;
             let mut handle = unsafe { self.bulk_write(new_len_with_ascii, old_len, false)? };
-            let num_ascii = copy_basic_latin_to_ascii(other, &mut handle.as_mut_slice()[old_len..]);
-            let left = other.len() - num_ascii;
+            let (read, written) = convert_utf16_to_utf8_partial(other, &mut handle.as_mut_slice()[old_len..]);
+            let left = other.len() - read;
             if left == 0 {
-                return Ok(handle.finish(old_len + num_ascii, true));
+                return Ok(handle.finish(old_len + written, true));
             }
-            let filled = old_len + num_ascii;
+            let filled = old_len + written;
             let needed = times_three_plus_one(left).ok_or(())?;
             let new_len = filled.checked_add(needed).ok_or(())?;
             unsafe {
                 handle.restart_bulk_write(new_len, filled, false)?;
             }
-            (filled, num_ascii, handle)
+            (filled, read, handle)
         } else {
             // Started with non-ASCII. Compute worst case
             let needed = if let Some(n) = worst_case_needed {
                 n
             } else {
                 times_three_plus_one(other.len()).ok_or(())?
             };
             let new_len = old_len.checked_add(needed).ok_or(())?;
             let mut handle = unsafe { self.bulk_write(new_len, old_len, false)? };
             (old_len, 0, handle)
         };
         let written =
-            convert_utf16_to_utf8(&other[num_ascii..], &mut handle.as_mut_slice()[filled..]);
+            convert_utf16_to_utf8(&other[read..], &mut handle.as_mut_slice()[filled..]);
         Ok(handle.finish(filled + written, true))
     }
 
     /// Convert a potentially-invalid UTF-16 string into valid UTF-8
     /// (replacing invalid sequences with the REPLACEMENT CHARACTER) and
     /// replace the content of this string with the conversion result.
     pub fn assign_utf16_to_utf8(&mut self, other: &[u16]) {
         self.fallible_append_utf16_to_utf8_impl(other, 0)
@@ -572,17 +572,17 @@ impl nsACString {
     );
 
     fn fallible_append_latin1_to_utf8_impl(
         &mut self,
         other: &[u8],
         old_len: usize,
         maybe_num_ascii: Option<usize>,
     ) -> Result<BulkWriteOk, ()> {
-        let (filled, num_ascii, mut handle) = if let Some(num_ascii) = maybe_num_ascii {
+        let (filled, read, mut handle) = if let Some(num_ascii) = maybe_num_ascii {
             // Wrapper checked for ASCII
             let left = other.len() - num_ascii;
             let filled = old_len + num_ascii;
             let needed = left.checked_mul(2).ok_or(())?;
             let new_len = filled.checked_add(needed).ok_or(())?;
             let mut handle = unsafe { self.bulk_write(new_len, old_len, false)? };
             if num_ascii != 0 {
                 (&mut handle.as_mut_slice()[old_len..filled]).copy_from_slice(&other[..num_ascii]);
@@ -600,43 +600,43 @@ impl nsACString {
                 None
             };
             if worst_case_needed.is_none() && long_string_starts_with_ascii(other) {
                 // Wrapper didn't check for ASCII, so let's see if `other` starts with ASCII
                 // `other` starts with ASCII, so let's first size the buffer
                 // with optimism that it's ASCII-only.
                 let new_len_with_ascii = old_len.checked_add(other.len()).ok_or(())?;
                 let mut handle = unsafe { self.bulk_write(new_len_with_ascii, old_len, false)? };
-                let num_ascii = copy_ascii_to_ascii(other, &mut handle.as_mut_slice()[old_len..]);
-                let left = other.len() - num_ascii;
-                let filled = old_len + num_ascii;
+                let (read, written) = convert_latin1_to_utf8_partial(other, &mut handle.as_mut_slice()[old_len..]);
+                let left = other.len() - read;
+                let filled = old_len + written;
                 if left == 0 {
-                    // `other` was all ASCII
+                    // `other` fit in the initial allocation
                     return Ok(handle.finish(filled, true));
                 }
                 let needed = left.checked_mul(2).ok_or(())?;
                 let new_len = filled.checked_add(needed).ok_or(())?;
                 unsafe {
                     handle.restart_bulk_write(new_len, filled, false)?;
                 }
-                (filled, num_ascii, handle)
+                (filled, read, handle)
             } else {
                 // Started with non-ASCII. Assume worst case.
                 let needed = if let Some(n) = worst_case_needed {
                     n
                 } else {
                     other.len().checked_mul(2).ok_or(())?
                 };
                 let new_len = old_len.checked_add(needed).ok_or(())?;
                 let mut handle = unsafe { self.bulk_write(new_len, old_len, false)? };
                 (old_len, 0, handle)
             }
         };
         let written =
-            convert_latin1_to_utf8(&other[num_ascii..], &mut handle.as_mut_slice()[filled..]);
+            convert_latin1_to_utf8(&other[read..], &mut handle.as_mut_slice()[filled..]);
         Ok(handle.finish(filled + written, true))
     }
 
     /// Convert a Latin1 (i.e. byte value equals scalar value; not windows-1252!)
     /// into UTF-8 and replace the content of this string with the conversion result.
     pub fn assign_latin1_to_utf8<T: Latin1StringLike + ?Sized>(&mut self, other: &T) {
         self.fallible_append_latin1_to_utf8_check(other, 0)
             .expect("Out of memory");