Revision: 3949
Author: [email protected]
Date: Thu Feb 25 04:49:23 2010
Log: Improve string runtime compare performance for flat strings.
Review URL: http://codereview.chromium.org/650058
http://code.google.com/p/v8/source/detail?r=3949
Modified:
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/utils.h
=======================================
--- /branches/bleeding_edge/src/objects.h Fri Feb 19 02:02:04 2010
+++ /branches/bleeding_edge/src/objects.h Thu Feb 25 04:49:23 2010
@@ -4051,10 +4051,6 @@
// Casting.
static inline SeqString* cast(Object* obj);
- // Dispatched behaviour.
- // For regexp code.
- uint16_t* SeqStringGetTwoByteAddress();
-
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
};
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Feb 23 02:29:02 2010
+++ /branches/bleeding_edge/src/runtime.cc Thu Feb 25 04:49:23 2010
@@ -4591,6 +4591,66 @@
// lexicographic ordering.
return Smi::FromInt(x_index - y_index);
}
+
+
+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) {
@@ -4618,20 +4678,8 @@
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);
}
=======================================
--- /branches/bleeding_edge/src/utils.h Fri Feb 19 02:02:04 2010
+++ /branches/bleeding_edge/src/utils.h Thu Feb 25 04:49:23 2010
@@ -528,11 +528,11 @@
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;
}
@@ -542,6 +542,34 @@
*dest++ = static_cast<sinkchar>(*src++);
}
}
+
+
+// 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.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev