Commit 6a10a837 authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4145 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b2b2eb57
......@@ -274,6 +274,25 @@ void Heap::ScavengeObject(HeapObject** p, HeapObject* 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) {
ASSERT(HasBeenSetup());
int amount = amount_of_external_allocated_memory_ + change_in_bytes;
......
......@@ -114,6 +114,8 @@ Heap::HeapState Heap::gc_state_ = NOT_IN_GC;
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::ReportStatisticsAfterGC() {
void Heap::GarbageCollectionPrologue() {
TranscendentalCache::Clear();
gc_count_++;
unflattended_strings_length_ = 0;
#ifdef DEBUG
ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
allow_allocation(false);
......
......@@ -634,6 +634,15 @@ class Heap : public AllStatic {
// 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 @@ class Heap : public AllStatic {
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; \
......
......@@ -5073,7 +5073,7 @@ static Object* FlatStringCompare(String* x, String* y) {
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 @@ static Object* Runtime_StringCompare(Arguments args) {
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);
......
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