1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // This file should only be compiled if you're on Power ISA.
8 #include "nsAlgorithm.h"
9 #include "nsTextFragmentImpl.h"
16 int32_t FirstNon8Bit(const char16_t
* str
, const char16_t
* end
) {
17 const uint32_t numUnicharsPerVector
= 8;
18 const uint32_t numCharsPerVector
= 16;
19 // Paranoia. If this assertion is wrong, change the vector loop below.
20 MOZ_ASSERT((numCharsPerVector
/ numUnicharsPerVector
) == sizeof(char16_t
));
22 typedef Non8BitParameters
<sizeof(size_t)> p
;
23 const uint32_t alignMask
= p::alignMask();
24 const size_t mask
= p::mask();
25 const uint32_t numUnicharsPerWord
= p::numUnicharsPerWord();
27 const uint32_t len
= end
- str
;
29 // i shall count the index in unichars; i2 shall count the index in chars.
33 // Align ourselves to a 16-byte boundary, as required by VMX loads.
34 uint32_t alignLen
= std::min(
35 len
, uint32_t(((-NS_PTR_TO_UINT32(str
)) & 0xf) / sizeof(char16_t
)));
37 if ((len
- alignLen
) >= numUnicharsPerVector
) {
38 for (; i
< alignLen
; i
++) {
39 if (str
[i
] > 255) return i
;
42 // Construct a vector of shorts.
44 const vector
unsigned short gtcompare
=
45 reinterpret_cast<vector
unsigned short>(
46 vec_mergel(vec_splat_s8(-1), vec_splat_s8(0)));
48 const vector
unsigned short gtcompare
=
49 reinterpret_cast<vector
unsigned short>(
50 vec_mergel(vec_splat_s8(0), vec_splat_s8(-1)));
52 const uint32_t vectWalkEnd
=
53 ((len
- i
) / numUnicharsPerVector
) * numUnicharsPerVector
;
54 i2
= i
* sizeof(char16_t
);
57 vector
unsigned short vect
;
59 // Check one VMX register (8 unichars) at a time. The vec_any_gt
60 // intrinsic does exactly what we want. This loop is manually unrolled;
61 // it yields notable performance improvements this way.
62 #define CheckForASCII \
63 vect = vec_ld(i2, reinterpret_cast<const unsigned short*>(str)); \
64 if (vec_any_gt(vect, gtcompare)) return i; \
65 i += numUnicharsPerVector; \
66 if (!(i < vectWalkEnd)) break; \
67 i2 += numCharsPerVector;
69 CheckForASCII CheckForASCII
74 // Align ourselves to a word boundary.
75 alignLen
= std::min(len
, uint32_t(((-NS_PTR_TO_UINT32(str
)) & alignMask
) /
77 for (; i
< alignLen
; i
++) {
78 if (str
[i
] > 255) return i
;
82 // Check one word at a time.
83 const uint32_t wordWalkEnd
=
84 ((len
- i
) / numUnicharsPerWord
) * numUnicharsPerWord
;
85 for (; i
< wordWalkEnd
; i
+= numUnicharsPerWord
) {
86 const size_t word
= *reinterpret_cast<const size_t*>(str
+ i
);
87 if (word
& mask
) return i
;
90 // Take care of the remainder one character at a time.
91 for (; i
< len
; i
++) {
101 } // namespace mozilla