Bug 1402247 part 8 - Remove LossyConvertEncoding8to16 and LossyConvertEncoding16to8. draft
authorHenri Sivonen <hsivonen@hsivonen.fi>
Thu, 15 Mar 2018 13:56:19 +0200
changeset 768034 c766164e384ccc9251b8efeb56a50cbe4b3e985c
parent 768033 b8b72e2d353ba24a5efbffdab728463533b54ed3
child 768035 6d78b771b19ab880c1217618f3daa3eb7aefd018
push id102784
push userbmo:hsivonen@hsivonen.fi
push dateThu, 15 Mar 2018 16:05:17 +0000
bugs1402247
milestone61.0a1
Bug 1402247 part 8 - Remove LossyConvertEncoding8to16 and LossyConvertEncoding16to8. MozReview-Commit-ID: Jjxjh7uw6Ng
dom/base/nsTextFragment.cpp
parser/html/nsHtml5String.cpp
xpcom/string/moz.build
xpcom/string/nsUTF8Utils.h
xpcom/string/nsUTF8UtilsNEON.cpp
xpcom/string/nsUTF8UtilsSSE2.cpp
--- a/dom/base/nsTextFragment.cpp
+++ b/dom/base/nsTextFragment.cpp
@@ -11,17 +11,16 @@
  */
 
 #include "nsTextFragment.h"
 #include "nsCRT.h"
 #include "nsReadableUtils.h"
 #include "nsMemory.h"
 #include "nsBidiUtils.h"
 #include "nsUnicharUtils.h"
-#include "nsUTF8Utils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/SSE.h"
 #include "nsTextFragmentImpl.h"
 #include <algorithm>
 
 #define TEXTFRAG_WHITE_AFTER_NEWLINE 50
 #define TEXTFRAG_MAX_NEWLINES 7
@@ -314,18 +313,17 @@ nsTextFragment::SetTo(const char16_t* aB
   } else {
     // Use 1 byte storage because we can
     char* buff = static_cast<char*>(malloc(aLength));
     if (!buff) {
       return false;
     }
 
     // Copy data
-    LossyConvertEncoding16to8 converter(buff);
-    copy_string(aBuffer, aBuffer+aLength, converter);
+    LossyConvertUTF16toLatin1(MakeSpan(aBuffer, aLength), MakeSpan(buff, aLength));
     m1b = buff;
     mState.mIs2b = false;
   }
 
   // Setup our fields
   mState.mInHeap = true;
   mState.mLength = aLength;
 
@@ -346,19 +344,17 @@ nsTextFragment::CopyTo(char16_t *aDest, 
     aCount = mState.mLength - aOffset;
   }
 
   if (aCount != 0) {
     if (mState.mIs2b) {
       memcpy(aDest, Get2b() + aOffset, sizeof(char16_t) * aCount);
     } else {
       const char *cp = m1b + aOffset;
-      const char *end = cp + aCount;
-      LossyConvertEncoding8to16 converter(aDest);
-      copy_string(cp, end, converter);
+      ConvertLatin1toUTF16(MakeSpan(cp, aCount), MakeSpan(aDest, aCount));
     }
   }
 }
 
 bool
 nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength,
                        bool aUpdateBidi, bool aForce2b)
 {
@@ -431,18 +427,17 @@ nsTextFragment::Append(const char16_t* a
     // all to 2-byte
     nsStringBuffer* buff = nsStringBuffer::Alloc(size).take();
     if (!buff) {
       return false;
     }
 
     // Copy data into buff
     char16_t* data = static_cast<char16_t*>(buff->Data());
-    LossyConvertEncoding8to16 converter(data);
-    copy_string(m1b, m1b+mState.mLength, converter);
+    ConvertLatin1toUTF16(MakeSpan(m1b, mState.mLength), MakeSpan(data, mState.mLength));
 
     memcpy(data + mState.mLength, aBuffer, aLength * sizeof(char16_t));
     mState.mLength += aLength;
     mState.mIs2b = true;
 
     if (mState.mInHeap) {
       free(const_cast<char*>(m1b));
     }
@@ -474,18 +469,17 @@ nsTextFragment::Append(const char16_t* a
       return false;
     }
 
     memcpy(buff, m1b, mState.mLength);
     mState.mInHeap = true;
   }
 
   // Copy aBuffer into buff.
-  LossyConvertEncoding16to8 converter(buff + mState.mLength);
-  copy_string(aBuffer, aBuffer + aLength, converter);
+  LossyConvertUTF16toLatin1(MakeSpan(aBuffer, aLength), MakeSpan(buff + mState.mLength, aLength));
 
   m1b = buff;
   mState.mLength += aLength;
 
   return true;
 }
 
 /* virtual */ size_t
--- a/parser/html/nsHtml5String.cpp
+++ b/parser/html/nsHtml5String.cpp
@@ -164,18 +164,17 @@ nsHtml5String::FromLiteral(const char* a
   // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
   // copy.
   RefPtr<nsStringBuffer> buffer(
     nsStringBuffer::Alloc((length + 1) * sizeof(char16_t)));
   if (!buffer) {
     MOZ_CRASH("Out of memory.");
   }
   char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
-  LossyConvertEncoding8to16 converter(data);
-  converter.write(aLiteral, length);
+  ConvertLatin1toUTF16(MakeSpan(aLiteral, length), MakeSpan(data, length));
   data[length] = 0;
   return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) | eStringBuffer);
 }
 
 // static
 nsHtml5String
 nsHtml5String::FromString(const nsAString& aString)
 {
--- a/xpcom/string/moz.build
+++ b/xpcom/string/moz.build
@@ -44,26 +44,16 @@ UNIFIED_SOURCES += [
     'nsStringComparator.cpp',
     'nsStringObsolete.cpp',
     'nsSubstring.cpp',
     'nsTextFormatter.cpp',
     'nsTSubstringTuple.cpp',
     'precompiled_templates.cpp',
 ]
 
-# Are we targeting x86 or x86-64?  If so, compile the SSE2 functions for
-# nsUTF8Utils.cpp and nsReadableUtils.cpp.
-if CONFIG['INTEL_ARCHITECTURE']:
-    SOURCES += ['nsUTF8UtilsSSE2.cpp']
-    SOURCES['nsUTF8UtilsSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
-
-if CONFIG['BUILD_ARM_NEON'] or CONFIG['CPU_ARCH'] == 'aarch64':
-    SOURCES += ['nsUTF8UtilsNEON.cpp']
-    SOURCES['nsUTF8UtilsNEON.cpp'].flags += CONFIG['NEON_FLAGS']
-
 # MSVC 2017 has a bug that incorrectly generates C5037 warning which
 # hits the template string code. We need to disable this warning as a
 # workaround. See https://developercommunity.visualstudio.com/
 # content/problem/81223/incorrect-error-c5037-with-permissive.html
 if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
     CXXFLAGS += ['-wd5037']
 
 FINAL_LIBRARY = 'xul'
--- a/xpcom/string/nsUTF8Utils.h
+++ b/xpcom/string/nsUTF8Utils.h
@@ -6,20 +6,18 @@
 #ifndef nsUTF8Utils_h_
 #define nsUTF8Utils_h_
 
 // This file may be used in two ways: if MOZILLA_INTERNAL_API is defined, this
 // file will provide signatures for the Mozilla abstract string types. It will
 // use XPCOM assertion/debugging macros, etc.
 
 #include "nscore.h"
-#include "mozilla/arm.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/EndianUtils.h"
-#include "mozilla/SSE.h"
 #include "mozilla/TypeTraits.h"
 
 #include "nsCharTraits.h"
 
 #ifdef MOZILLA_INTERNAL_API
 #define UTF8UTILS_WARNING(msg) NS_WARNING(msg)
 #else
 #define UTF8UTILS_WARNING(msg)
@@ -273,130 +271,16 @@ public:
       *aBuffer = p;
       return 0xFFFD;
     }
 
     MOZ_ASSERT_UNREACHABLE("Impossible UCS-2 character value.");
   }
 };
 
-#ifdef MOZILLA_INTERNAL_API
-/**
- * A character sink that performs a |reinterpret_cast|-style conversion
- * from char to char16_t.
- */
-class LossyConvertEncoding8to16
-{
-public:
-  typedef char value_type;
-  typedef char input_type;
-  typedef char16_t output_type;
-
-public:
-  explicit LossyConvertEncoding8to16(char16_t* aDestination) :
-    mDestination(aDestination)
-  {
-  }
-
-  void
-  write(const char* aSource, uint32_t aSourceLength)
-  {
-#ifdef MOZILLA_MAY_SUPPORT_SSE2
-    if (mozilla::supports_sse2()) {
-      write_sse2(aSource, aSourceLength);
-      return;
-    }
-#endif
-#if defined(MOZILLA_MAY_SUPPORT_NEON) && defined(MOZ_LITTLE_ENDIAN)
-    if (mozilla::supports_neon()) {
-      write_neon(aSource, aSourceLength);
-      return;
-    }
-#endif
-    const char* done_writing = aSource + aSourceLength;
-    while (aSource < done_writing) {
-      *mDestination++ = (char16_t)(unsigned char)(*aSource++);
-    }
-  }
-
-  void
-  write_sse2(const char* aSource, uint32_t aSourceLength);
-#if defined(MOZILLA_MAY_SUPPORT_NEON) && defined(MOZ_LITTLE_ENDIAN)
-  void
-  write_neon(const char* aSource, uint32_t aSourceLength);
-#endif
-
-  void
-  write_terminator()
-  {
-    *mDestination = (char16_t)(0);
-  }
-
-private:
-  char16_t* mDestination;
-};
-
-/**
- * A character sink that performs a |reinterpret_cast|-style conversion
- * from char16_t to char.
- */
-class LossyConvertEncoding16to8
-{
-public:
-  typedef char16_t value_type;
-  typedef char16_t input_type;
-  typedef char output_type;
-
-  explicit LossyConvertEncoding16to8(char* aDestination)
-    : mDestination(aDestination)
-  {
-  }
-
-  void
-  write(const char16_t* aSource, uint32_t aSourceLength)
-  {
-#ifdef MOZILLA_MAY_SUPPORT_SSE2
-    if (mozilla::supports_sse2()) {
-      write_sse2(aSource, aSourceLength);
-      return;
-    }
-#endif
-#if defined(MOZILLA_MAY_SUPPORT_NEON) && defined(MOZ_LITTLE_ENDIAN)
-    if (mozilla::supports_neon()) {
-      write_neon(aSource, aSourceLength);
-      return;
-    }
-#endif
-    const char16_t* done_writing = aSource + aSourceLength;
-    while (aSource < done_writing) {
-      *mDestination++ = (char)(*aSource++);
-    }
-  }
-
-#ifdef MOZILLA_MAY_SUPPORT_SSE2
-  void
-  write_sse2(const char16_t* aSource, uint32_t aSourceLength);
-#endif
-#if defined(MOZILLA_MAY_SUPPORT_NEON) && defined(MOZ_LITTLE_ENDIAN)
-  void
-  write_neon(const char16_t* aSource, uint32_t aSourceLength);
-#endif
-
-  void
-  write_terminator()
-  {
-    *mDestination = '\0';
-  }
-
-private:
-  char* mDestination;
-};
-#endif // MOZILLA_INTERNAL_API
-
-
 template<typename Char, typename UnsignedT>
 inline UnsignedT
 RewindToPriorUTF8Codepoint(const Char* utf8Chars, UnsignedT index)
 {
   static_assert(mozilla::IsSame<Char, char>::value ||
                 mozilla::IsSame<Char, unsigned char>::value ||
                 mozilla::IsSame<Char, signed char>::value,
                 "UTF-8 data must be in 8-bit units");
deleted file mode 100644
--- a/xpcom/string/nsUTF8UtilsNEON.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nscore.h"
-#include "nsAlgorithm.h"
-#include "nsUTF8Utils.h"
-
-#include <arm_neon.h>
-
-void
-LossyConvertEncoding16to8::write_neon(const char16_t* aSource,
-                                      uint32_t aSourceLength)
-{
-  char* dest = mDestination;
-
-  // Align source to a 16-byte boundary and destination to 8-bytes boundary.
-  uint32_t i = 0;
-  while (((reinterpret_cast<uintptr_t>(aSource + i) & 0xf) ||
-          (reinterpret_cast<uintptr_t>(dest + i) & 0x7)) &&
-         i < aSourceLength) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-    i++;
-  }
-
-  while ((reinterpret_cast<uintptr_t>(dest + i) & 0xf) &&
-         aSourceLength - i > 7) {
-    // source is aligned, but destination isn't aligned by 16-byte yet
-    uint16x8_t s =
-      vld1q_u16(reinterpret_cast<const uint16_t*>(
-                  __builtin_assume_aligned(aSource + i, 16)));
-    vst1_u8(reinterpret_cast<uint8_t*>(
-              __builtin_assume_aligned(dest + i, 8)),
-            vmovn_u16(s));
-    i += 8;
-  }
-
-  // Align source and destination to a 16-byte boundary.
-  while (aSourceLength - i > 15) {
-    uint16x8_t low =
-      vld1q_u16(reinterpret_cast<const uint16_t*>(
-                  __builtin_assume_aligned(aSource + i, 16)));
-    uint16x8_t high =
-      vld1q_u16(reinterpret_cast<const uint16_t*>(
-                  __builtin_assume_aligned(aSource + i + 8, 16)));
-    vst1q_u8(reinterpret_cast<uint8_t*>(
-               __builtin_assume_aligned(dest + i, 16)),
-             vcombine_u8(vmovn_u16(low), vmovn_u16(high)));
-    i += 16;
-  }
-
-  if (aSourceLength - i > 7) {
-    uint16x8_t s = vld1q_u16(reinterpret_cast<const uint16_t*>(
-                               __builtin_assume_aligned(aSource + i, 16)));
-    vst1_u8(reinterpret_cast<uint8_t*>(
-              __builtin_assume_aligned(dest + i, 8)),
-            vmovn_u16(s));
-    i += 8;
-  }
-
-  // Finish up the rest.
-  for (; i < aSourceLength; ++i) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-  }
-
-  mDestination += i;
-}
-
-void
-LossyConvertEncoding8to16::write_neon(const char* aSource,
-                                      uint32_t aSourceLength)
-{
-  char16_t* dest = mDestination;
-
-  // Align source to a 8-byte boundary and destination to 16-bytes boundary.
-  uint32_t i = 0;
-  while (((reinterpret_cast<uintptr_t>(aSource + i) & 0x7) ||
-          (reinterpret_cast<uintptr_t>(dest + i) & 0xf)) &&
-         i < aSourceLength) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-    i++;
-  }
-
-  if ((uintptr_t(aSource + i) & 0xf) && aSourceLength - i > 7) {
-    // destination is aligned, but source isn't aligned by 16-byte yet
-    uint8x8_t s =
-      vld1_u8(reinterpret_cast<const uint8_t*>(
-                __builtin_assume_aligned(aSource + i, 8)));
-    vst1q_u16(reinterpret_cast<uint16_t*>(
-                __builtin_assume_aligned(dest + i, 16)),
-              vmovl_u8(s));
-    i += 8;
-  }
-
-  // Align source and destination to a 16-byte boundary.
-  while (aSourceLength - i > 15) {
-    uint8x16_t s =
-      vld1q_u8(reinterpret_cast<const uint8_t*>(
-                 __builtin_assume_aligned(aSource + i, 16)));
-    uint16x8_t low = vmovl_u8(vget_low_u8(s));
-    uint16x8_t high = vmovl_u8(vget_high_u8(s));
-    vst1q_u16(reinterpret_cast<uint16_t*>(
-                __builtin_assume_aligned(dest + i, 16)),
-              low);
-    vst1q_u16(reinterpret_cast<uint16_t*>(
-                __builtin_assume_aligned(dest + i + 8, 16)),
-              high);
-    i += 16;
-  }
-
-  if (aSourceLength - i > 7) {
-    uint8x8_t s =
-      vld1_u8(reinterpret_cast<const uint8_t*>(
-                __builtin_assume_aligned(aSource + i, 8)));
-    vst1q_u16(reinterpret_cast<uint16_t*>(
-                __builtin_assume_aligned(dest + i, 16)),
-              vmovl_u8(s));
-    i += 8;
-  }
-
-  // Finish up whatever's left.
-  for (; i < aSourceLength; ++i) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-  }
-
-  mDestination += i;
-}
deleted file mode 100644
--- a/xpcom/string/nsUTF8UtilsSSE2.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nscore.h"
-#include "nsAlgorithm.h"
-#include <emmintrin.h>
-#include <nsUTF8Utils.h>
-
-void
-LossyConvertEncoding16to8::write_sse2(const char16_t* aSource,
-                                      uint32_t aSourceLength)
-{
-  char* dest = mDestination;
-
-  // Align source to a 16-byte boundary.
-  uint32_t i = 0;
-  uint32_t alignLen =
-    XPCOM_MIN<uint32_t>(aSourceLength,
-                        uint32_t(-NS_PTR_TO_INT32(aSource) & 0xf) / sizeof(char16_t));
-  for (; i < alignLen; ++i) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-  }
-
-  // Walk 64 bytes (four XMM registers) at a time.
-  __m128i vectmask = _mm_set1_epi16(0x00ff);
-  for (; aSourceLength - i > 31; i += 32) {
-    __m128i source1 = _mm_load_si128(reinterpret_cast<const __m128i*>(aSource + i));
-    source1 = _mm_and_si128(source1, vectmask);
-
-    __m128i source2 = _mm_load_si128(reinterpret_cast<const __m128i*>(aSource + i + 8));
-    source2 = _mm_and_si128(source2, vectmask);
-
-    __m128i source3 = _mm_load_si128(reinterpret_cast<const __m128i*>(aSource + i + 16));
-    source3 = _mm_and_si128(source3, vectmask);
-
-    __m128i source4 = _mm_load_si128(reinterpret_cast<const __m128i*>(aSource + i + 24));
-    source4 = _mm_and_si128(source4, vectmask);
-
-
-    // Pack the source data.  SSE2 views this as a saturating uint16_t to
-    // uint8_t conversion, but since we masked off the high-order byte of every
-    // uint16_t, we're really just grabbing the low-order bytes of source1 and
-    // source2.
-    __m128i packed1 = _mm_packus_epi16(source1, source2);
-    __m128i packed2 = _mm_packus_epi16(source3, source4);
-
-    // This store needs to be unaligned since there's no guarantee that the
-    // alignment we did above for the source will align the destination.
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(dest + i),      packed1);
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(dest + i + 16), packed2);
-  }
-
-  // Finish up the rest.
-  for (; i < aSourceLength; ++i) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-  }
-
-  mDestination += i;
-}
-
-void
-LossyConvertEncoding8to16::write_sse2(const char* aSource,
-                                      uint32_t aSourceLength)
-{
-  char16_t* dest = mDestination;
-
-  // Align source to a 16-byte boundary.  We choose to align source rather than
-  // dest because we'd rather have our loads than our stores be fast. You have
-  // to wait for a load to complete, but you can keep on moving after issuing a
-  // store.
-  uint32_t i = 0;
-  uint32_t alignLen = XPCOM_MIN(aSourceLength,
-                                uint32_t(-NS_PTR_TO_INT32(aSource) & 0xf));
-  for (; i < alignLen; ++i) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-  }
-
-  // Walk 32 bytes (two XMM registers) at a time.
-  for (; aSourceLength - i > 31; i += 32) {
-    __m128i source1 = _mm_load_si128(reinterpret_cast<const __m128i*>(aSource + i));
-    __m128i source2 = _mm_load_si128(reinterpret_cast<const __m128i*>(aSource + i + 16));
-
-    // Interleave 0s in with the bytes of source to create lo and hi.
-    __m128i lo1 = _mm_unpacklo_epi8(source1, _mm_setzero_si128());
-    __m128i hi1 = _mm_unpackhi_epi8(source1, _mm_setzero_si128());
-    __m128i lo2 = _mm_unpacklo_epi8(source2, _mm_setzero_si128());
-    __m128i hi2 = _mm_unpackhi_epi8(source2, _mm_setzero_si128());
-
-    // store lo and hi into dest.
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(dest + i),      lo1);
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(dest + i + 8),  hi1);
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(dest + i + 16), lo2);
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(dest + i + 24), hi2);
-  }
-
-  // Finish up whatever's left.
-  for (; i < aSourceLength; ++i) {
-    dest[i] = static_cast<unsigned char>(aSource[i]);
-  }
-
-  mDestination += i;
-}