Chromium Code Reviews| Index: src/api.cc |
| diff --git a/src/api.cc b/src/api.cc |
| index 4cdd77ef05a6908c5cc5ebf0fa3398ab0c1f3e72..05b58b48b196f06899b0143c58a3974bbedaa813 100644 |
| --- a/src/api.cc |
| +++ b/src/api.cc |
| @@ -4304,6 +4304,25 @@ bool String::IsOneByte() const { |
| } |
| +// Helpers for ContainsOnlyOneByteHelper |
| +template<size_t size> struct OneByteMask; |
| +template<> struct OneByteMask<4> { |
| + static const uint32_t value = 0xFF00FF00U; |
| +}; |
| +template<> struct OneByteMask<8> { |
| + static const uint64_t value = 0xFF00FF00FF00ULL; |
|
Yang
2013/06/07 09:19:06
Shouldn't this be 0xFF00FF00FF00FF00ULL (missing o
|
| +}; |
| +static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value; |
|
Yang
2013/06/07 09:19:06
I guess you could also just static_cast<uintptr_t>
|
| +static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1; |
| +static inline bool Unaligned(const uint16_t* chars) { |
| + return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask; |
| +} |
| +static inline const uint16_t* Align(const uint16_t* chars) { |
| + return reinterpret_cast<uint16_t*>( |
| + reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask); |
| +} |
| + |
| + |
| class ContainsOnlyOneByteHelper { |
| public: |
| ContainsOnlyOneByteHelper() : is_one_byte_(true) {} |
| @@ -4315,14 +4334,36 @@ class ContainsOnlyOneByteHelper { |
| void VisitOneByteString(const uint8_t* chars, int length) { |
| // Nothing to do. |
| } |
| - // TODO(dcarney): do word aligned read. |
| void VisitTwoByteString(const uint16_t* chars, int length) { |
| - // Check whole string without breaking. |
| - uint16_t total = 0; |
| - for (int i = 0; i < length; i++) { |
| - total |= chars[i] >> 8; |
| + // Accumulated bits. |
| + uintptr_t acc = 0; |
| + // Align to uintptr_t. |
| + const uint16_t* end = chars + length; |
| + while (Unaligned(chars) && chars != end) { |
| + acc |= *chars++; |
| + } |
| + // Read word aligned in blocks, |
| + // checking the return value at the end of each block. |
| + const uint16_t* aligned_end = Align(end); |
| + const int increment = sizeof(uintptr_t)/sizeof(uint16_t); |
| + const int inner_loops = 16; |
| + while (chars + inner_loops*increment < aligned_end) { |
| + for (int i = 0; i < inner_loops; i++) { |
| + acc |= *reinterpret_cast<const uintptr_t*>(chars); |
| + chars += increment; |
| + } |
| + // Check for early return. |
| + if ((acc & kOneByteMask) != 0) { |
| + is_one_byte_ = false; |
| + return; |
| + } |
| + } |
| + // Read the rest. |
| + while (chars != end) { |
| + acc |= *chars++; |
| } |
| - if (total != 0) is_one_byte_ = false; |
| + // Check result. |
| + if ((acc & kOneByteMask) != 0) is_one_byte_ = false; |
| } |
| private: |