}
+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;
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;
void Heap::GarbageCollectionPrologue() {
TranscendentalCache::Clear();
gc_count_++;
+ unflattended_strings_length_ = 0;
#ifdef DEBUG
ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
allow_allocation(false);
// 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();
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; \
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);
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);