Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(968)

Side by Side Diff: src/objects.cc

Issue 2076010: Try flattening strings before comparing for equality. (Closed)
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 // allowed. This is to avoid an assertion failure when allocating. 624 // allowed. This is to avoid an assertion failure when allocating.
625 // Flattening strings is the only case where we always allow 625 // Flattening strings is the only case where we always allow
626 // allocation because no GC is performed if the allocation fails. 626 // allocation because no GC is performed if the allocation fails.
627 if (!Heap::IsAllocationAllowed()) return this; 627 if (!Heap::IsAllocationAllowed()) return this;
628 #endif 628 #endif
629 629
630 switch (StringShape(this).representation_tag()) { 630 switch (StringShape(this).representation_tag()) {
631 case kConsStringTag: { 631 case kConsStringTag: {
632 ConsString* cs = ConsString::cast(this); 632 ConsString* cs = ConsString::cast(this);
633 if (cs->second()->length() == 0) { 633 if (cs->second()->length() == 0) {
634 return this; 634 return cs->first();
635 } 635 }
636 // There's little point in putting the flat string in new space if the 636 // There's little point in putting the flat string in new space if the
637 // cons string is in old space. It can never get GCed until there is 637 // cons string is in old space. It can never get GCed until there is
638 // an old space GC. 638 // an old space GC.
639 PretenureFlag tenure = Heap::InNewSpace(this) ? pretenure : TENURED; 639 PretenureFlag tenure = Heap::InNewSpace(this) ? pretenure : TENURED;
640 int len = length(); 640 int len = length();
641 Object* object; 641 Object* object;
642 String* result; 642 String* result;
643 if (IsAsciiRepresentation()) { 643 if (IsAsciiRepresentation()) {
644 object = Heap::AllocateRawAsciiString(len, tenure); 644 object = Heap::AllocateRawAsciiString(len, tenure);
(...skipping 17 matching lines...) Expand all
662 int first_length = first->length(); 662 int first_length = first->length();
663 WriteToFlat(first, dest, 0, first_length); 663 WriteToFlat(first, dest, 0, first_length);
664 String* second = cs->second(); 664 String* second = cs->second();
665 WriteToFlat(second, 665 WriteToFlat(second,
666 dest + first_length, 666 dest + first_length,
667 0, 667 0,
668 len - first_length); 668 len - first_length);
669 } 669 }
670 cs->set_first(result); 670 cs->set_first(result);
671 cs->set_second(Heap::empty_string()); 671 cs->set_second(Heap::empty_string());
672 return this; 672 return result;
673 } 673 }
674 default: 674 default:
675 return this; 675 return this;
676 } 676 }
677 } 677 }
678 678
679 679
680 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { 680 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
681 #ifdef DEBUG 681 #ifdef DEBUG
682 if (FLAG_enable_slow_asserts) { 682 if (FLAG_enable_slow_asserts) {
(...skipping 3890 matching lines...) Expand 10 before | Expand all | Expand 10 after
4573 int len = length(); 4573 int len = length();
4574 if (len != other->length()) return false; 4574 if (len != other->length()) return false;
4575 if (len == 0) return true; 4575 if (len == 0) return true;
4576 4576
4577 // Fast check: if hash code is computed for both strings 4577 // Fast check: if hash code is computed for both strings
4578 // a fast negative check can be performed. 4578 // a fast negative check can be performed.
4579 if (HasHashCode() && other->HasHashCode()) { 4579 if (HasHashCode() && other->HasHashCode()) {
4580 if (Hash() != other->Hash()) return false; 4580 if (Hash() != other->Hash()) return false;
4581 } 4581 }
4582 4582
4583 if (StringShape(this).IsSequentialAscii() && 4583 // We know the strings are both non-empty. Compare the first chars
4584 StringShape(other).IsSequentialAscii()) { 4584 // before we try to flatten the strings.
4585 const char* str1 = SeqAsciiString::cast(this)->GetChars(); 4585 if (this->Get(0) != other->Get(0)) return false;
4586 const char* str2 = SeqAsciiString::cast(other)->GetChars(); 4586
4587 String* lhs = this->TryFlattenGetString();
4588 String* rhs = other->TryFlattenGetString();
4589
4590 if (StringShape(lhs).IsSequentialAscii() &&
Mads Ager (chromium) 2010/05/19 12:27:43 lhs->IsSeqAsciiString() and rhs->IsSeqAsciiString(
4591 StringShape(rhs).IsSequentialAscii()) {
4592 const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
4593 const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
4587 return CompareRawStringContents(Vector<const char>(str1, len), 4594 return CompareRawStringContents(Vector<const char>(str1, len),
4588 Vector<const char>(str2, len)); 4595 Vector<const char>(str2, len));
4589 } 4596 }
4590 4597
4591 if (this->IsFlat()) { 4598 if (lhs->IsFlat()) {
4592 if (IsAsciiRepresentation()) { 4599 if (IsAsciiRepresentation()) {
4593 Vector<const char> vec1 = this->ToAsciiVector(); 4600 Vector<const char> vec1 = lhs->ToAsciiVector();
4594 if (other->IsFlat()) { 4601 if (rhs->IsFlat()) {
4595 if (other->IsAsciiRepresentation()) { 4602 if (rhs->IsAsciiRepresentation()) {
4596 Vector<const char> vec2 = other->ToAsciiVector(); 4603 Vector<const char> vec2 = rhs->ToAsciiVector();
4597 return CompareRawStringContents(vec1, vec2); 4604 return CompareRawStringContents(vec1, vec2);
4598 } else { 4605 } else {
4599 VectorIterator<char> buf1(vec1); 4606 VectorIterator<char> buf1(vec1);
4600 VectorIterator<uc16> ib(other->ToUC16Vector()); 4607 VectorIterator<uc16> ib(rhs->ToUC16Vector());
4601 return CompareStringContents(&buf1, &ib); 4608 return CompareStringContents(&buf1, &ib);
4602 } 4609 }
4603 } else { 4610 } else {
4604 VectorIterator<char> buf1(vec1); 4611 VectorIterator<char> buf1(vec1);
4605 string_compare_buffer_b.Reset(0, other); 4612 string_compare_buffer_b.Reset(0, rhs);
4606 return CompareStringContents(&buf1, &string_compare_buffer_b); 4613 return CompareStringContents(&buf1, &string_compare_buffer_b);
4607 } 4614 }
4608 } else { 4615 } else {
4609 Vector<const uc16> vec1 = this->ToUC16Vector(); 4616 Vector<const uc16> vec1 = lhs->ToUC16Vector();
4610 if (other->IsFlat()) { 4617 if (rhs->IsFlat()) {
4611 if (other->IsAsciiRepresentation()) { 4618 if (rhs->IsAsciiRepresentation()) {
4612 VectorIterator<uc16> buf1(vec1); 4619 VectorIterator<uc16> buf1(vec1);
4613 VectorIterator<char> ib(other->ToAsciiVector()); 4620 VectorIterator<char> ib(rhs->ToAsciiVector());
4614 return CompareStringContents(&buf1, &ib); 4621 return CompareStringContents(&buf1, &ib);
4615 } else { 4622 } else {
4616 Vector<const uc16> vec2(other->ToUC16Vector()); 4623 Vector<const uc16> vec2(rhs->ToUC16Vector());
4617 return CompareRawStringContents(vec1, vec2); 4624 return CompareRawStringContents(vec1, vec2);
4618 } 4625 }
4619 } else { 4626 } else {
4620 VectorIterator<uc16> buf1(vec1); 4627 VectorIterator<uc16> buf1(vec1);
4621 string_compare_buffer_b.Reset(0, other); 4628 string_compare_buffer_b.Reset(0, rhs);
4622 return CompareStringContents(&buf1, &string_compare_buffer_b); 4629 return CompareStringContents(&buf1, &string_compare_buffer_b);
4623 } 4630 }
4624 } 4631 }
4625 } else { 4632 } else {
4626 string_compare_buffer_a.Reset(0, this); 4633 string_compare_buffer_a.Reset(0, lhs);
4627 return CompareStringContentsPartial(&string_compare_buffer_a, other); 4634 return CompareStringContentsPartial(&string_compare_buffer_a, rhs);
4628 } 4635 }
4629 } 4636 }
4630 4637
4631 4638
4632 bool String::MarkAsUndetectable() { 4639 bool String::MarkAsUndetectable() {
4633 if (StringShape(this).IsSymbol()) return false; 4640 if (StringShape(this).IsSymbol()) return false;
4634 4641
4635 Map* map = this->map(); 4642 Map* map = this->map();
4636 if (map == Heap::string_map()) { 4643 if (map == Heap::string_map()) {
4637 this->set_map(Heap::undetectable_string_map()); 4644 this->set_map(Heap::undetectable_string_map());
(...skipping 2393 matching lines...) Expand 10 before | Expand all | Expand 10 after
7031 return String::cast(string)->Equals(string_); 7038 return String::cast(string)->Equals(string_);
7032 } 7039 }
7033 7040
7034 uint32_t Hash() { return string_->Hash(); } 7041 uint32_t Hash() { return string_->Hash(); }
7035 7042
7036 uint32_t HashForObject(Object* other) { 7043 uint32_t HashForObject(Object* other) {
7037 return String::cast(other)->Hash(); 7044 return String::cast(other)->Hash();
7038 } 7045 }
7039 7046
7040 Object* AsObject() { 7047 Object* AsObject() {
7041 // If the string is a cons string, attempt to flatten it so that 7048 // Attempt to flatten the string, so that symbols will most often
7042 // symbols will most often be flat strings. 7049 // be flat strings.
7043 if (StringShape(string_).IsCons()) { 7050 string_ = string_->TryFlattenGetString();
7044 ConsString* cons_string = ConsString::cast(string_);
7045 cons_string->TryFlatten();
7046 if (cons_string->second()->length() == 0) {
7047 string_ = cons_string->first();
7048 }
7049 }
7050 // Transform string to symbol if possible. 7051 // Transform string to symbol if possible.
7051 Map* map = Heap::SymbolMapForString(string_); 7052 Map* map = Heap::SymbolMapForString(string_);
7052 if (map != NULL) { 7053 if (map != NULL) {
7053 string_->set_map(map); 7054 string_->set_map(map);
7054 ASSERT(string_->IsSymbol()); 7055 ASSERT(string_->IsSymbol());
7055 return string_; 7056 return string_;
7056 } 7057 }
7057 // Otherwise allocate a new symbol. 7058 // Otherwise allocate a new symbol.
7058 StringInputBuffer buffer(string_); 7059 StringInputBuffer buffer(string_);
7059 return Heap::AllocateInternalSymbol(&buffer, 7060 return Heap::AllocateInternalSymbol(&buffer,
(...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after
8548 if (break_point_objects()->IsUndefined()) return 0; 8549 if (break_point_objects()->IsUndefined()) return 0;
8549 // Single beak point. 8550 // Single beak point.
8550 if (!break_point_objects()->IsFixedArray()) return 1; 8551 if (!break_point_objects()->IsFixedArray()) return 1;
8551 // Multiple break points. 8552 // Multiple break points.
8552 return FixedArray::cast(break_point_objects())->length(); 8553 return FixedArray::cast(break_point_objects())->length();
8553 } 8554 }
8554 #endif 8555 #endif
8555 8556
8556 8557
8557 } } // namespace v8::internal 8558 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | src/objects-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698