Commit 8c892ea2 authored by dcarney@chromium.org's avatar dcarney@chromium.org

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
parent 5b514e89
...@@ -4315,17 +4315,49 @@ class ContainsOnlyOneByteHelper { ...@@ -4315,17 +4315,49 @@ class ContainsOnlyOneByteHelper {
void VisitOneByteString(const uint8_t* chars, int length) { void VisitOneByteString(const uint8_t* chars, int length) {
// Nothing to do. // Nothing to do.
} }
// TODO(dcarney): do word aligned read.
void VisitTwoByteString(const uint16_t* chars, int length) { void VisitTwoByteString(const uint16_t* chars, int length) {
// Check whole string without breaking. // Accumulated bits.
uint16_t total = 0; uintptr_t acc = 0;
for (int i = 0; i < length; i++) { // Align to uintptr_t.
total |= chars[i] >> 8; 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;
}
} }
if (total != 0) is_one_byte_ = false; // Read the rest.
while (chars != end) {
acc |= *chars++;
}
// Check result.
if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
} }
private: 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) { bool CheckCons(i::ConsString* cons_string) {
while (true) { while (true) {
// Check left side if flat. // Check left side if flat.
......
...@@ -17033,8 +17033,12 @@ TEST(ContainsOnlyOneByte) { ...@@ -17033,8 +17033,12 @@ TEST(ContainsOnlyOneByte) {
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
// Make a buffer long enough that it won't automatically be converted. // Make a buffer long enough that it won't automatically be converted.
const int length = 200; const int length = 512;
i::SmartArrayPointer<uint16_t> string_contents(new uint16_t[length]); // 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. // Set to contain only one byte.
for (int i = 0; i < length-1; i++) { for (int i = 0; i < length-1; i++) {
string_contents[i] = 0x41; string_contents[i] = 0x41;
...@@ -17042,10 +17046,10 @@ TEST(ContainsOnlyOneByte) { ...@@ -17042,10 +17046,10 @@ TEST(ContainsOnlyOneByte) {
string_contents[length-1] = 0; string_contents[length-1] = 0;
// Simple case. // Simple case.
Handle<String> string; Handle<String> string;
string = String::NewExternal(new TestResource(*string_contents)); string = String::NewExternal(new TestResource(string_contents));
CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte()); CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
// Counter example. // Counter example.
string = String::NewFromTwoByte(isolate, *string_contents); string = String::NewFromTwoByte(isolate, string_contents);
CHECK(string->IsOneByte() && string->ContainsOnlyOneByte()); CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
// Test left right and balanced cons strings. // Test left right and balanced cons strings.
Handle<String> base = String::NewFromUtf8(isolate, "a"); Handle<String> base = String::NewFromUtf8(isolate, "a");
...@@ -17059,7 +17063,7 @@ TEST(ContainsOnlyOneByte) { ...@@ -17059,7 +17063,7 @@ TEST(ContainsOnlyOneByte) {
balanced = String::Concat(balanced, right); balanced = String::Concat(balanced, right);
Handle<String> cons_strings[] = {left, balanced, right}; Handle<String> cons_strings[] = {left, balanced, right};
Handle<String> two_byte = 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++) { for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
// Base assumptions. // Base assumptions.
string = cons_strings[i]; string = cons_strings[i];
...@@ -17070,6 +17074,24 @@ TEST(ContainsOnlyOneByte) { ...@@ -17070,6 +17074,24 @@ TEST(ContainsOnlyOneByte) {
string = String::Concat(cons_strings[i], two_byte); string = String::Concat(cons_strings[i], two_byte);
CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte()); 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;
}
}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment