Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include <emmintrin.h>
8 :
9 : #include "nsReadableUtilsImpl.h"
10 :
11 : namespace mozilla {
12 : namespace SSE2 {
13 :
14 : static inline bool
15 28780 : is_zero (__m128i x)
16 : {
17 : return
18 86340 : _mm_movemask_epi8(_mm_cmpeq_epi8(x, _mm_setzero_si128())) == 0xffff;
19 : }
20 :
21 : int32_t
22 4047 : FirstNonASCII(const char16_t* aBegin, const char16_t* aEnd)
23 : {
24 4047 : const size_t kNumUnicharsPerVector = sizeof(__m128i) / sizeof(char16_t);
25 : typedef NonASCIIParameters<sizeof(size_t)> p;
26 4047 : const size_t kMask = p::mask();
27 4047 : const uintptr_t kXmmAlignMask = 0xf;
28 4047 : const uint16_t kShortMask = 0xff80;
29 4047 : const size_t kNumUnicharsPerWord = p::numUnicharsPerWord();
30 :
31 4047 : const char16_t* idx = aBegin;
32 :
33 : // Align ourselves to a 16-byte boundary as required by _mm_load_si128
34 26743 : for (; idx != aEnd && ((uintptr_t(idx) & kXmmAlignMask) != 0); idx++) {
35 11348 : if (!IsASCII(*idx)) {
36 0 : return idx - aBegin;
37 : }
38 : }
39 :
40 : // Check one XMM register (16 bytes) at a time.
41 4047 : const char16_t* vectWalkEnd = aligned(aEnd, kXmmAlignMask);
42 4047 : __m128i vectmask = _mm_set1_epi16(static_cast<int16_t>(kShortMask));
43 61607 : for (; idx != vectWalkEnd; idx += kNumUnicharsPerVector) {
44 28780 : const __m128i vect = *reinterpret_cast<const __m128i*>(idx);
45 28780 : if (!is_zero(_mm_and_si128(vect, vectmask))) {
46 0 : return idx - aBegin;
47 : }
48 : }
49 :
50 : // Check one word at a time.
51 4047 : const char16_t* wordWalkEnd = aligned(aEnd, p::alignMask());
52 8791 : for(; idx != wordWalkEnd; idx += kNumUnicharsPerWord) {
53 2372 : const size_t word = *reinterpret_cast<const size_t*>(idx);
54 2372 : if (word & kMask) {
55 0 : return idx - aBegin;
56 : }
57 : }
58 :
59 : // Take care of the remainder one character at a time.
60 15493 : for (; idx != aEnd; idx++) {
61 5723 : if (!IsASCII(*idx)) {
62 0 : return idx - aBegin;
63 : }
64 : }
65 :
66 4047 : return -1;
67 : }
68 :
69 : } // namespace SSE2
70 : } // namespace mozilla
|