Index: src/api.cc |
diff --git a/src/api.cc b/src/api.cc |
index ed1e26525aa9a75dfb1f0d3e1731020c607c179f..3c1a003809bbb4efd0021c1bc8c45e5144b5a051 100644 |
--- a/src/api.cc |
+++ b/src/api.cc |
@@ -4315,17 +4315,49 @@ 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++; |
} |
- if (total != 0) is_one_byte_ = false; |
+ // 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++; |
+ } |
+ // Check result. |
+ if ((acc & kOneByteMask) != 0) is_one_byte_ = false; |
} |
private: |
+ static const uintptr_t kOneByteMask = |
+ static_cast<uintptr_t>(0xFF00FF00FF00FF00ULL); |
+ 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); |
+ } |
bool CheckCons(i::ConsString* cons_string) { |
while (true) { |
// Check left side if flat. |