Revision: 4145
Author: [email protected]
Date: Tue Mar 16 05:30:04 2010
Log: Add heuristic for flattening strings before comparing them.

Also switched to using CompareChars instead of memcmp since it's
faster than gcc's builtin and on par with msvc's builtin.

Review URL: http://codereview.chromium.org/991002
http://code.google.com/p/v8/source/detail?r=4145

Modified:
 /branches/bleeding_edge/src/heap-inl.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/runtime.cc

=======================================
--- /branches/bleeding_edge/src/heap-inl.h      Tue Mar 16 03:38:17 2010
+++ /branches/bleeding_edge/src/heap-inl.h      Tue Mar 16 05:30:04 2010
@@ -272,6 +272,25 @@
   // Call the slow part of scavenge object.
   return ScavengeObjectSlow(p, object);
 }
+
+
+Object* Heap::PrepareForCompare(String* str) {
+  // Always flatten small strings and force flattening of long strings
+  // after we have accumulated a certain amount we failed to flatten.
+  static const int kMaxAlwaysFlattenLength = 32;
+  static const int kFlattenLongThreshold = 16*KB;
+
+  const int length = str->length();
+  Object* obj = str->TryFlatten();
+  if (length <= kMaxAlwaysFlattenLength ||
+      unflattended_strings_length_ >= kFlattenLongThreshold) {
+    return obj;
+  }
+  if (obj->IsFailure()) {
+    unflattended_strings_length_ += length;
+  }
+  return str;
+}


 int Heap::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
=======================================
--- /branches/bleeding_edge/src/heap.cc Mon Mar 15 14:06:51 2010
+++ /branches/bleeding_edge/src/heap.cc Tue Mar 16 05:30:04 2010
@@ -114,6 +114,8 @@
 int Heap::mc_count_ = 0;
 int Heap::gc_count_ = 0;

+int Heap::unflattended_strings_length_ = 0;
+
 int Heap::always_allocate_scope_depth_ = 0;
 int Heap::linear_allocation_scope_depth_ = 0;
 int Heap::contexts_disposed_ = 0;
@@ -302,6 +304,7 @@
 void Heap::GarbageCollectionPrologue() {
   TranscendentalCache::Clear();
   gc_count_++;
+  unflattended_strings_length_ = 0;
 #ifdef DEBUG
   ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
   allow_allocation(false);
=======================================
--- /branches/bleeding_edge/src/heap.h  Mon Mar 15 14:06:51 2010
+++ /branches/bleeding_edge/src/heap.h  Tue Mar 16 05:30:04 2010
@@ -634,6 +634,15 @@
   // NULL is returned if string is in new space or not flattened.
   static Map* SymbolMapForString(String* str);

+  // Tries to flatten a string before compare operation.
+  //
+  // Returns a failure in case it was decided that flattening was
+  // necessary and failed.  Note, if flattening is not necessary the
+  // string might stay non-flat even when not a failure is returned.
+  //
+  // Please note this function does not perform a garbage collection.
+  static inline Object* PrepareForCompare(String* str);
+
   // Converts the given boolean condition to JavaScript boolean value.
   static Object* ToBoolean(bool condition) {
     return condition ? true_value() : false_value();
@@ -955,6 +964,9 @@
   static int mc_count_;  // how many mark-compact collections happened
   static int gc_count_;  // how many gc happened

+  // Total length of the strings we failed to flatten since the last GC.
+  static int unflattended_strings_length_;
+
#define ROOT_ACCESSOR(type, name, camel_name) \ static inline void set_##name(type* value) { \ roots_[k##camel_name##RootIndex] = value; \
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Mar 16 02:10:11 2010
+++ /branches/bleeding_edge/src/runtime.cc      Tue Mar 16 05:30:04 2010
@@ -5073,7 +5073,7 @@
     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);
+      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);
@@ -5121,8 +5121,10 @@
   if (d < 0) return Smi::FromInt(LESS);
   else if (d > 0) return Smi::FromInt(GREATER);

-  x->TryFlatten();
-  y->TryFlatten();
+  Object* obj = Heap::PrepareForCompare(x);
+  if (obj->IsFailure()) return obj;
+  obj = Heap::PrepareForCompare(y);
+  if (obj->IsFailure()) return obj;

   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
                                       : StringInputBufferCompare(x, y);

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to