OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |