do aligned reads in ContainsOnlyOneByte

R=yangguo@chromium.org
BUG=

Review URL: https://codereview.chromium.org/16147004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15023 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dcarney@chromium.org 2013-06-10 07:34:58 +00:00
parent 5b514e89ff
commit 8c892ea2a8
2 changed files with 65 additions and 11 deletions

View File

@ -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.

View File

@ -17033,8 +17033,12 @@ TEST(ContainsOnlyOneByte) {
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;
@ -17042,10 +17046,10 @@ TEST(ContainsOnlyOneByte) {
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");
@ -17059,7 +17063,7 @@ TEST(ContainsOnlyOneByte) {
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];
@ -17070,6 +17074,24 @@ TEST(ContainsOnlyOneByte) {
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;
}
}
}