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.
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
// Make a buffer long enough that it won't automatically be converted.
- const int length = 200;
- i::SmartArrayPointer<uint16_t> string_contents(new uint16_t[length]);
+ const int length = 512;
+ // Ensure word aligned assignment.
+ const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
+ i::SmartArrayPointer<uintptr_t>
+ aligned_contents(new uintptr_t[aligned_length]);
+ uint16_t* string_contents = reinterpret_cast<uint16_t*>(*aligned_contents);
// Set to contain only one byte.
for (int i = 0; i < length-1; i++) {
string_contents[i] = 0x41;
string_contents[length-1] = 0;
// Simple case.
Handle<String> string;
- string = String::NewExternal(new TestResource(*string_contents));
+ string = String::NewExternal(new TestResource(string_contents));
CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
// Counter example.
- string = String::NewFromTwoByte(isolate, *string_contents);
+ string = String::NewFromTwoByte(isolate, string_contents);
CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
// Test left right and balanced cons strings.
Handle<String> base = String::NewFromUtf8(isolate, "a");
balanced = String::Concat(balanced, right);
Handle<String> cons_strings[] = {left, balanced, right};
Handle<String> two_byte =
- String::NewExternal(new TestResource(*string_contents));
+ String::NewExternal(new TestResource(string_contents));
for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
// Base assumptions.
string = cons_strings[i];
string = String::Concat(cons_strings[i], two_byte);
CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
}
+ // Set bits in different positions
+ // for strings of different lengths and alignments.
+ for (int alignment = 0; alignment < 7; alignment++) {
+ for (int size = 2; alignment + size < length; size *= 2) {
+ int zero_offset = size + alignment;
+ string_contents[zero_offset] = 0;
+ for (int i = 0; i < size; i++) {
+ int shift = 8 + (i % 7);
+ string_contents[alignment + i] = 1 << shift;
+ string =
+ String::NewExternal(new TestResource(string_contents + alignment));
+ CHECK_EQ(size, string->Length());
+ CHECK(!string->ContainsOnlyOneByte());
+ string_contents[alignment + i] = 0x41;
+ }
+ string_contents[zero_offset] = 0x41;
+ }
+ }
}