Added string equality by reading int-sized blocks of characters for
authorchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 20 Oct 2008 11:38:32 +0000 (11:38 +0000)
committerchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 20 Oct 2008 11:38:32 +0000 (11:38 +0000)
flat strings with the same representation.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@528 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/objects-inl.h
src/objects.cc
src/objects.h

index c7d93e3fb51811a48d867db90827f39d8b2b0fca..da814a0e454da2d4676e903230720ea927961ce0 100644 (file)
@@ -125,6 +125,12 @@ bool Object::IsSeqAsciiString() {
 }
 
 
+bool String::IsSeqAsciiString() {
+  return (this->representation_tag() == kSeqStringTag)
+    && is_ascii_representation();
+}
+
+
 bool Object::IsSeqTwoByteString() {
   return IsSeqString()
       && !String::cast(this)->IsAsciiRepresentation();
@@ -1408,6 +1414,11 @@ Address SeqAsciiString::GetCharsAddress() {
 }
 
 
+const char* SeqAsciiString::GetChars() {
+  return reinterpret_cast<const char*>(GetCharsAddress());
+}
+
+
 Address SeqTwoByteString::GetCharsAddress() {
   return FIELD_ADDR(this, kHeaderSize);
 }
index bfcedb262e711a3678302e8508ec114ddf2857bd..a1722f85e15ae071686d420ea64b7e2f1b7888af 100644 (file)
@@ -3646,6 +3646,37 @@ static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
 }
 
 
+// Compares the contents of two strings by reading and comparing
+// int-sized blocks of characters.
+template <typename Char>
+static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
+  // Lint complains about taking sizeof a type rather than a variable.
+  // That's just stupid in this case so I'm turning it off.
+  const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
+  int length = a.length();
+  ASSERT_EQ(length, b.length());
+  int endpoint = length - kStepSize;
+  const Char* pa = a.start();
+  const Char* pb = b.start();
+  int i;
+  // Compare blocks until we reach near the end of the string.
+  for (i = 0; i <= endpoint; i += kStepSize) {
+    uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
+    uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
+    if (wa != wb) {
+      return false;
+    }
+  }
+  // Compare the remaining characters that didn't fit into a block.
+  for (; i < length; i++) {
+    if (a[i] != b[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
 static StringInputBuffer string_compare_buffer_b;
 
 
@@ -3681,13 +3712,46 @@ bool String::SlowEquals(String* other) {
     if (Hash() != other->Hash()) return false;
   }
 
+  if (this->IsSeqAsciiString() && other->IsSeqAsciiString()) {
+    const char* str1 = SeqAsciiString::cast(this)->GetChars();
+    const char* str2 = SeqAsciiString::cast(other)->GetChars();
+    return CompareRawStringContents(Vector<const char>(str1, len),
+                                    Vector<const char>(str2, len));
+  }
+
   if (this->IsFlat()) {
     if (this->IsAsciiRepresentation()) {
-      VectorIterator<char> buf1(this->ToAsciiVector());
-      return CompareStringContentsPartial(&buf1, other);
+      Vector<const char> vec1 = this->ToAsciiVector();
+      if (other->IsFlat()) {
+        if (other->IsAsciiRepresentation()) {
+          Vector<const char> vec2 = other->ToAsciiVector();
+          return CompareRawStringContents(vec1, vec2);
+        } else {
+          VectorIterator<char> buf1(vec1);
+          VectorIterator<uc16> ib(other->ToUC16Vector());
+          return CompareStringContents(&buf1, &ib);
+        }
+      } else {
+        VectorIterator<char> buf1(vec1);
+        string_compare_buffer_b.Reset(0, other);
+        return CompareStringContents(&buf1, &string_compare_buffer_b);
+      }
     } else {
-      VectorIterator<uc16> buf1(this->ToUC16Vector());
-      return CompareStringContentsPartial(&buf1, other);
+      Vector<const uc16> vec1 = this->ToUC16Vector();
+      if (other->IsFlat()) {
+        if (other->IsAsciiRepresentation()) {
+          VectorIterator<uc16> buf1(vec1);
+          VectorIterator<char> ib(other->ToAsciiVector());
+          return CompareStringContents(&buf1, &ib);
+        } else {
+          Vector<const uc16> vec2(other->ToUC16Vector());
+          return CompareRawStringContents(vec1, vec2);
+        }
+      } else {
+        VectorIterator<uc16> buf1(vec1);
+        string_compare_buffer_b.Reset(0, other);
+        return CompareStringContents(&buf1, &string_compare_buffer_b);
+      }
     }
   } else {
     string_compare_buffer_a.Reset(0, this);
index 943784436691a635ecf3bf9e6272b7ea58642674..819739a98aee5c258b1cadbb6a432207bc5ff7e8 100644 (file)
@@ -2956,6 +2956,10 @@ class String: public HeapObject {
   // Is this string an ascii string.
   inline bool IsAsciiRepresentation();
 
+  // Specialization of this function from Object that skips the
+  // string check.
+  inline bool IsSeqAsciiString();
+
   // Fast testing routines that assume the receiver is a string and
   // just check whether it is a certain kind of string.
   inline bool StringIsSlicedString();
@@ -3183,6 +3187,8 @@ class SeqAsciiString: public SeqString {
   // Get the address of the characters in this string.
   inline Address GetCharsAddress();
 
+  inline const char* GetChars();
+
   // Casting
   static inline SeqAsciiString* cast(Object* obj);