Commit 94567357 authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Improve string runtime compare performance for flat strings.

Review URL: http://codereview.chromium.org/650058

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3949 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 024faf11
......@@ -4051,10 +4051,6 @@ class SeqString: public String {
// Casting.
static inline SeqString* cast(Object* obj);
// Dispatched behaviour.
// For regexp code.
uint16_t* SeqStringGetTwoByteAddress();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
};
......
......@@ -4593,6 +4593,66 @@ static Object* Runtime_SmiLexicographicCompare(Arguments args) {
}
static Object* StringInputBufferCompare(String* x, String* y) {
static StringInputBuffer bufx;
static StringInputBuffer bufy;
bufx.Reset(x);
bufy.Reset(y);
while (bufx.has_more() && bufy.has_more()) {
int d = bufx.GetNext() - bufy.GetNext();
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
}
// x is (non-trivial) prefix of y:
if (bufy.has_more()) return Smi::FromInt(LESS);
// y is prefix of x:
return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
}
static Object* FlatStringCompare(String* x, String* y) {
ASSERT(x->IsFlat());
ASSERT(y->IsFlat());
Object* equal_prefix_result = Smi::FromInt(EQUAL);
int prefix_length = x->length();
if (y->length() < prefix_length) {
prefix_length = y->length();
equal_prefix_result = Smi::FromInt(GREATER);
} else if (y->length() > prefix_length) {
equal_prefix_result = Smi::FromInt(LESS);
}
int r;
if (x->IsAsciiRepresentation()) {
Vector<const char> x_chars = x->ToAsciiVector();
if (y->IsAsciiRepresentation()) {
Vector<const char> y_chars = y->ToAsciiVector();
r = memcmp(x_chars.start(), y_chars.start(), prefix_length);
} else {
Vector<const uc16> y_chars = y->ToUC16Vector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
}
} else {
Vector<const uc16> x_chars = x->ToUC16Vector();
if (y->IsAsciiRepresentation()) {
Vector<const char> y_chars = y->ToAsciiVector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
} else {
Vector<const uc16> y_chars = y->ToUC16Vector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
}
}
Object* result;
if (r == 0) {
result = equal_prefix_result;
} else {
result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
}
ASSERT(result == StringInputBufferCompare(x, y));
return result;
}
static Object* Runtime_StringCompare(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
......@@ -4618,20 +4678,8 @@ static Object* Runtime_StringCompare(Arguments args) {
x->TryFlattenIfNotFlat();
y->TryFlattenIfNotFlat();
static StringInputBuffer bufx;
static StringInputBuffer bufy;
bufx.Reset(x);
bufy.Reset(y);
while (bufx.has_more() && bufy.has_more()) {
int d = bufx.GetNext() - bufy.GetNext();
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
}
// x is (non-trivial) prefix of y:
if (bufy.has_more()) return Smi::FromInt(LESS);
// y is prefix of x:
return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
: StringInputBufferCompare(x, y);
}
......
......@@ -528,11 +528,11 @@ static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
sinkchar* limit = dest + chars;
#ifdef V8_HOST_CAN_READ_UNALIGNED
if (sizeof(*dest) == sizeof(*src)) {
// Number of characters in a uint32_t.
static const int kStepSize = sizeof(uint32_t) / sizeof(*dest); // NOLINT
// Number of characters in a uintptr_t.
static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT
while (dest <= limit - kStepSize) {
*reinterpret_cast<uint32_t*>(dest) =
*reinterpret_cast<const uint32_t*>(src);
*reinterpret_cast<uintptr_t*>(dest) =
*reinterpret_cast<const uintptr_t*>(src);
dest += kStepSize;
src += kStepSize;
}
......@@ -544,6 +544,34 @@ static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
}
// Compare ASCII/16bit chars to ASCII/16bit chars.
template <typename lchar, typename rchar>
static inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
const lchar* limit = lhs + chars;
#ifdef V8_HOST_CAN_READ_UNALIGNED
if (sizeof(*lhs) == sizeof(*rhs)) {
// Number of characters in a uintptr_t.
static const int kStepSize = sizeof(uintptr_t) / sizeof(*lhs); // NOLINT
while (lhs <= limit - kStepSize) {
if (*reinterpret_cast<const uintptr_t*>(lhs) !=
*reinterpret_cast<const uintptr_t*>(rhs)) {
break;
}
lhs += kStepSize;
rhs += kStepSize;
}
}
#endif
while (lhs < limit) {
int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
if (r != 0) return r;
++lhs;
++rhs;
}
return 0;
}
// Calculate 10^exponent.
int TenToThe(int exponent);
......
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