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