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:
parent
5b514e89ff
commit
8c892ea2a8
44
src/api.cc
44
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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user