Try flattening strings before comparing for equality.
Review URL: http://codereview.chromium.org/2076010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4684 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
af70ad5fdc
commit
91cbd98dfc
@ -2080,7 +2080,7 @@ Object* Heap::AllocateSubString(String* buffer,
|
||||
}
|
||||
|
||||
// Make an attempt to flatten the buffer to reduce access time.
|
||||
buffer->TryFlatten();
|
||||
buffer = buffer->TryFlattenGetString();
|
||||
|
||||
Object* result = buffer->IsAsciiRepresentation()
|
||||
? AllocateRawAsciiString(length, pretenure )
|
||||
|
@ -1691,13 +1691,19 @@ bool String::Equals(String* other) {
|
||||
|
||||
|
||||
Object* String::TryFlatten(PretenureFlag pretenure) {
|
||||
// We don't need to flatten strings that are already flat. Since this code
|
||||
// is inlined, it can be helpful in the flat case to not call out to Flatten.
|
||||
if (IsFlat()) return this;
|
||||
if (!StringShape(this).IsCons()) return this;
|
||||
ConsString* cons = ConsString::cast(this);
|
||||
if (cons->second()->length() == 0) return cons->first();
|
||||
return SlowTryFlatten(pretenure);
|
||||
}
|
||||
|
||||
|
||||
String* String::TryFlattenGetString(PretenureFlag pretenure) {
|
||||
Object* flat = TryFlatten(pretenure);
|
||||
return flat->IsFailure() ? this : String::cast(flat);
|
||||
}
|
||||
|
||||
|
||||
uint16_t String::Get(int index) {
|
||||
ASSERT(index >= 0 && index < length());
|
||||
switch (StringShape(this).full_representation_tag()) {
|
||||
|
@ -631,7 +631,7 @@ Object* String::SlowTryFlatten(PretenureFlag pretenure) {
|
||||
case kConsStringTag: {
|
||||
ConsString* cs = ConsString::cast(this);
|
||||
if (cs->second()->length() == 0) {
|
||||
return this;
|
||||
return cs->first();
|
||||
}
|
||||
// There's little point in putting the flat string in new space if the
|
||||
// cons string is in old space. It can never get GCed until there is
|
||||
@ -669,7 +669,7 @@ Object* String::SlowTryFlatten(PretenureFlag pretenure) {
|
||||
}
|
||||
cs->set_first(result);
|
||||
cs->set_second(Heap::empty_string());
|
||||
return this;
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
return this;
|
||||
@ -4580,51 +4580,58 @@ bool String::SlowEquals(String* other) {
|
||||
if (Hash() != other->Hash()) return false;
|
||||
}
|
||||
|
||||
if (StringShape(this).IsSequentialAscii() &&
|
||||
StringShape(other).IsSequentialAscii()) {
|
||||
const char* str1 = SeqAsciiString::cast(this)->GetChars();
|
||||
const char* str2 = SeqAsciiString::cast(other)->GetChars();
|
||||
// We know the strings are both non-empty. Compare the first chars
|
||||
// before we try to flatten the strings.
|
||||
if (this->Get(0) != other->Get(0)) return false;
|
||||
|
||||
String* lhs = this->TryFlattenGetString();
|
||||
String* rhs = other->TryFlattenGetString();
|
||||
|
||||
if (StringShape(lhs).IsSequentialAscii() &&
|
||||
StringShape(rhs).IsSequentialAscii()) {
|
||||
const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
|
||||
const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
|
||||
return CompareRawStringContents(Vector<const char>(str1, len),
|
||||
Vector<const char>(str2, len));
|
||||
}
|
||||
|
||||
if (this->IsFlat()) {
|
||||
if (lhs->IsFlat()) {
|
||||
if (IsAsciiRepresentation()) {
|
||||
Vector<const char> vec1 = this->ToAsciiVector();
|
||||
if (other->IsFlat()) {
|
||||
if (other->IsAsciiRepresentation()) {
|
||||
Vector<const char> vec2 = other->ToAsciiVector();
|
||||
Vector<const char> vec1 = lhs->ToAsciiVector();
|
||||
if (rhs->IsFlat()) {
|
||||
if (rhs->IsAsciiRepresentation()) {
|
||||
Vector<const char> vec2 = rhs->ToAsciiVector();
|
||||
return CompareRawStringContents(vec1, vec2);
|
||||
} else {
|
||||
VectorIterator<char> buf1(vec1);
|
||||
VectorIterator<uc16> ib(other->ToUC16Vector());
|
||||
VectorIterator<uc16> ib(rhs->ToUC16Vector());
|
||||
return CompareStringContents(&buf1, &ib);
|
||||
}
|
||||
} else {
|
||||
VectorIterator<char> buf1(vec1);
|
||||
string_compare_buffer_b.Reset(0, other);
|
||||
string_compare_buffer_b.Reset(0, rhs);
|
||||
return CompareStringContents(&buf1, &string_compare_buffer_b);
|
||||
}
|
||||
} else {
|
||||
Vector<const uc16> vec1 = this->ToUC16Vector();
|
||||
if (other->IsFlat()) {
|
||||
if (other->IsAsciiRepresentation()) {
|
||||
Vector<const uc16> vec1 = lhs->ToUC16Vector();
|
||||
if (rhs->IsFlat()) {
|
||||
if (rhs->IsAsciiRepresentation()) {
|
||||
VectorIterator<uc16> buf1(vec1);
|
||||
VectorIterator<char> ib(other->ToAsciiVector());
|
||||
VectorIterator<char> ib(rhs->ToAsciiVector());
|
||||
return CompareStringContents(&buf1, &ib);
|
||||
} else {
|
||||
Vector<const uc16> vec2(other->ToUC16Vector());
|
||||
Vector<const uc16> vec2(rhs->ToUC16Vector());
|
||||
return CompareRawStringContents(vec1, vec2);
|
||||
}
|
||||
} else {
|
||||
VectorIterator<uc16> buf1(vec1);
|
||||
string_compare_buffer_b.Reset(0, other);
|
||||
string_compare_buffer_b.Reset(0, rhs);
|
||||
return CompareStringContents(&buf1, &string_compare_buffer_b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
string_compare_buffer_a.Reset(0, this);
|
||||
return CompareStringContentsPartial(&string_compare_buffer_a, other);
|
||||
string_compare_buffer_a.Reset(0, lhs);
|
||||
return CompareStringContentsPartial(&string_compare_buffer_a, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7038,15 +7045,9 @@ class SymbolKey : public HashTableKey {
|
||||
}
|
||||
|
||||
Object* AsObject() {
|
||||
// If the string is a cons string, attempt to flatten it so that
|
||||
// symbols will most often be flat strings.
|
||||
if (StringShape(string_).IsCons()) {
|
||||
ConsString* cons_string = ConsString::cast(string_);
|
||||
cons_string->TryFlatten();
|
||||
if (cons_string->second()->length() == 0) {
|
||||
string_ = cons_string->first();
|
||||
}
|
||||
}
|
||||
// Attempt to flatten the string, so that symbols will most often
|
||||
// be flat strings.
|
||||
string_ = string_->TryFlattenGetString();
|
||||
// Transform string to symbol if possible.
|
||||
Map* map = Heap::SymbolMapForString(string_);
|
||||
if (map != NULL) {
|
||||
|
@ -4001,17 +4001,28 @@ class String: public HeapObject {
|
||||
// to this method are not efficient unless the string is flat.
|
||||
inline uint16_t Get(int index);
|
||||
|
||||
// Try to flatten the top level ConsString that is hiding behind this
|
||||
// string. This is a no-op unless the string is a ConsString. Flatten
|
||||
// mutates the ConsString and might return a failure.
|
||||
Object* SlowTryFlatten(PretenureFlag pretenure);
|
||||
|
||||
// Try to flatten the string. Checks first inline to see if it is necessary.
|
||||
// Do not handle allocation failures. After calling TryFlatten, the
|
||||
// string could still be a ConsString, in which case a failure is returned.
|
||||
// Use FlattenString from Handles.cc to be sure to flatten.
|
||||
// Try to flatten the string. Checks first inline to see if it is
|
||||
// necessary. Does nothing if the string is not a cons string.
|
||||
// Flattening allocates a sequential string with the same data as
|
||||
// the given string and mutates the cons string to a degenerate
|
||||
// form, where the first component is the new sequential string and
|
||||
// the second component is the empty string. If allocation fails,
|
||||
// this function returns a failure. If flattening succeeds, this
|
||||
// function returns the sequential string that is now the first
|
||||
// component of the cons string.
|
||||
//
|
||||
// Degenerate cons strings are handled specially by the garbage
|
||||
// collector (see IsShortcutCandidate).
|
||||
//
|
||||
// Use FlattenString from Handles.cc to flatten even in case an
|
||||
// allocation failure happens.
|
||||
inline Object* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
// Convenience function. Has exactly the same behavior as
|
||||
// TryFlatten(), except in the case of failure returns the original
|
||||
// string.
|
||||
inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
Vector<const char> ToAsciiVector();
|
||||
Vector<const uc16> ToUC16Vector();
|
||||
|
||||
@ -4197,6 +4208,11 @@ class String: public HeapObject {
|
||||
unsigned max_chars);
|
||||
|
||||
private:
|
||||
// Try to flatten the top level ConsString that is hiding behind this
|
||||
// string. This is a no-op unless the string is a ConsString. Flatten
|
||||
// mutates the ConsString and might return a failure.
|
||||
Object* SlowTryFlatten(PretenureFlag pretenure);
|
||||
|
||||
// Slow case of String::Equals. This implementation works on any strings
|
||||
// but it is most efficient on strings that are almost flat.
|
||||
bool SlowEquals(String* other);
|
||||
|
Loading…
Reference in New Issue
Block a user