| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 1b29071324ae6cdaf9b23bbcc45f8dfb1678ef2e..031c8bba22b1a9f463aa063672a266a30115b72d 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -5038,55 +5038,38 @@ int String::Utf8Length() {
|
| }
|
|
|
|
|
| -Vector<const char> String::ToAsciiVector() {
|
| - ASSERT(IsAsciiRepresentation());
|
| - ASSERT(IsFlat());
|
| -
|
| - int offset = 0;
|
| - int length = this->length();
|
| - StringRepresentationTag string_tag = StringShape(this).representation_tag();
|
| - String* string = this;
|
| - if (string_tag == kConsStringTag) {
|
| - ConsString* cons = ConsString::cast(string);
|
| - ASSERT(cons->second()->length() == 0);
|
| - string = cons->first();
|
| - string_tag = StringShape(string).representation_tag();
|
| - }
|
| - if (string_tag == kSeqStringTag) {
|
| - SeqAsciiString* seq = SeqAsciiString::cast(string);
|
| - char* start = seq->GetChars();
|
| - return Vector<const char>(start + offset, length);
|
| - }
|
| - ASSERT(string_tag == kExternalStringTag);
|
| - ExternalAsciiString* ext = ExternalAsciiString::cast(string);
|
| - const char* start = ext->resource()->data();
|
| - return Vector<const char>(start + offset, length);
|
| -}
|
| -
|
| -
|
| -Vector<const uc16> String::ToUC16Vector() {
|
| - ASSERT(IsTwoByteRepresentation());
|
| - ASSERT(IsFlat());
|
| -
|
| - int offset = 0;
|
| +String::FlatContent String::GetFlatContent(const AssertNoAllocation& promise) {
|
| + // Argument isn't used, it's only there to ensure that the user is
|
| + // aware that the extracted vectors may not survive a GC.
|
| int length = this->length();
|
| - StringRepresentationTag string_tag = StringShape(this).representation_tag();
|
| + StringShape shape(this);
|
| String* string = this;
|
| - if (string_tag == kConsStringTag) {
|
| + if (shape.representation_tag() == kConsStringTag) {
|
| ConsString* cons = ConsString::cast(string);
|
| - ASSERT(cons->second()->length() == 0);
|
| + if (cons->second()->length() != 0) {
|
| + return FlatContent();
|
| + }
|
| string = cons->first();
|
| - string_tag = StringShape(string).representation_tag();
|
| + shape = StringShape(string);
|
| }
|
| - if (string_tag == kSeqStringTag) {
|
| - SeqTwoByteString* seq = SeqTwoByteString::cast(string);
|
| - return Vector<const uc16>(seq->GetChars() + offset, length);
|
| + if (shape.encoding_tag() == kAsciiStringTag) {
|
| + const char* start;
|
| + if (shape.representation_tag() == kSeqStringTag) {
|
| + start = SeqAsciiString::cast(string)->GetChars();
|
| + } else {
|
| + start = ExternalAsciiString::cast(string)->resource()->data();
|
| + }
|
| + return FlatContent(Vector<const char>(start, length));
|
| + } else {
|
| + ASSERT(shape.encoding_tag() == kTwoByteStringTag);
|
| + const uc16* start;
|
| + if (shape.representation_tag() == kSeqStringTag) {
|
| + start = SeqTwoByteString::cast(string)->GetChars();
|
| + } else {
|
| + start = ExternalTwoByteString::cast(string)->resource()->data();
|
| + }
|
| + return FlatContent(Vector<const uc16>(start, length));
|
| }
|
| - ASSERT(string_tag == kExternalStringTag);
|
| - ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
|
| - const uc16* start =
|
| - reinterpret_cast<const uc16*>(ext->resource()->data());
|
| - return Vector<const uc16>(start + offset, length);
|
| }
|
|
|
|
|
| @@ -5536,11 +5519,14 @@ void FlatStringReader::PostGarbageCollection() {
|
| if (str_ == NULL) return;
|
| Handle<String> str(str_);
|
| ASSERT(str->IsFlat());
|
| - is_ascii_ = str->IsAsciiRepresentation();
|
| + AssertNoAllocation no_alloc;
|
| + String::FlatContent content = str->GetFlatContent(no_alloc);
|
| + ASSERT(content.is_flat());
|
| + is_ascii_ = content.IsAscii();
|
| if (is_ascii_) {
|
| - start_ = str->ToAsciiVector().start();
|
| + start_ = content.ToAsciiVector().start();
|
| } else {
|
| - start_ = str->ToUC16Vector().start();
|
| + start_ = content.ToUC16Vector().start();
|
| }
|
| }
|
|
|
| @@ -5860,12 +5846,14 @@ template <typename IteratorA>
|
| static inline bool CompareStringContentsPartial(Isolate* isolate,
|
| IteratorA* ia,
|
| String* b) {
|
| - if (b->IsFlat()) {
|
| - if (b->IsAsciiRepresentation()) {
|
| - VectorIterator<char> ib(b->ToAsciiVector());
|
| + AssertNoAllocation no_alloc;
|
| + String::FlatContent content = b->GetFlatContent(no_alloc);
|
| + if (content.IsFlat()) {
|
| + if (content.IsAscii()) {
|
| + VectorIterator<char> ib(content.ToAsciiVector());
|
| return CompareStringContents(ia, &ib);
|
| } else {
|
| - VectorIterator<uc16> ib(b->ToUC16Vector());
|
| + VectorIterator<uc16> ib(content.ToUC16Vector());
|
| return CompareStringContents(ia, &ib);
|
| }
|
| } else {
|
| @@ -5895,6 +5883,8 @@ bool String::SlowEquals(String* other) {
|
| String* lhs = this->TryFlattenGetString();
|
| String* rhs = other->TryFlattenGetString();
|
|
|
| + AssertNoAllocation no_alloc;
|
| +
|
| if (StringShape(lhs).IsSequentialAscii() &&
|
| StringShape(rhs).IsSequentialAscii()) {
|
| const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
|
| @@ -5904,16 +5894,18 @@ bool String::SlowEquals(String* other) {
|
| }
|
|
|
| Isolate* isolate = GetIsolate();
|
| - if (lhs->IsFlat()) {
|
| - if (lhs->IsAsciiRepresentation()) {
|
| - Vector<const char> vec1 = lhs->ToAsciiVector();
|
| - if (rhs->IsFlat()) {
|
| - if (rhs->IsAsciiRepresentation()) {
|
| - Vector<const char> vec2 = rhs->ToAsciiVector();
|
| + String::FlatContent lhs_content = lhs->GetFlatContent(no_alloc);
|
| + String::FlatContent rhs_content = rhs->GetFlatContent(no_alloc);
|
| + if (lhs_content.IsFlat()) {
|
| + if (lhs_content.IsAscii()) {
|
| + Vector<const char> vec1 = lhs_content.ToAsciiVector();
|
| + if (rhs_content.IsFlat()) {
|
| + if (rhs_content.IsAscii()) {
|
| + Vector<const char> vec2 = rhs_content.ToAsciiVector();
|
| return CompareRawStringContents(vec1, vec2);
|
| } else {
|
| VectorIterator<char> buf1(vec1);
|
| - VectorIterator<uc16> ib(rhs->ToUC16Vector());
|
| + VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
|
| return CompareStringContents(&buf1, &ib);
|
| }
|
| } else {
|
| @@ -5923,14 +5915,14 @@ bool String::SlowEquals(String* other) {
|
| isolate->objects_string_compare_buffer_b());
|
| }
|
| } else {
|
| - Vector<const uc16> vec1 = lhs->ToUC16Vector();
|
| - if (rhs->IsFlat()) {
|
| - if (rhs->IsAsciiRepresentation()) {
|
| + Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
|
| + if (rhs_content.IsFlat()) {
|
| + if (rhs_content.IsAscii()) {
|
| VectorIterator<uc16> buf1(vec1);
|
| - VectorIterator<char> ib(rhs->ToAsciiVector());
|
| + VectorIterator<char> ib(rhs_content.ToAsciiVector());
|
| return CompareStringContents(&buf1, &ib);
|
| } else {
|
| - Vector<const uc16> vec2(rhs->ToUC16Vector());
|
| + Vector<const uc16> vec2(rhs_content.ToUC16Vector());
|
| return CompareRawStringContents(vec1, vec2);
|
| }
|
| } else {
|
| @@ -5981,10 +5973,13 @@ bool String::IsEqualTo(Vector<const char> str) {
|
|
|
|
|
| bool String::IsAsciiEqualTo(Vector<const char> str) {
|
| + AssertNoAllocation no_alloc;
|
| int slen = length();
|
| if (str.length() != slen) return false;
|
| - if (IsFlat() && IsAsciiRepresentation()) {
|
| - return CompareChars(ToAsciiVector().start(), str.start(), slen) == 0;
|
| + FlatContent content = GetFlatContent(no_alloc);
|
| + if (content.IsAscii()) {
|
| + return CompareChars(content.ToAsciiVector().start(),
|
| + str.start(), slen) == 0;
|
| }
|
| for (int i = 0; i < slen; i++) {
|
| if (Get(i) != static_cast<uint16_t>(str[i])) return false;
|
| @@ -5994,10 +5989,12 @@ bool String::IsAsciiEqualTo(Vector<const char> str) {
|
|
|
|
|
| bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
|
| + AssertNoAllocation no_alloc;
|
| int slen = length();
|
| if (str.length() != slen) return false;
|
| - if (IsFlat() && IsTwoByteRepresentation()) {
|
| - return CompareChars(ToUC16Vector().start(), str.start(), slen) == 0;
|
| + FlatContent content = GetFlatContent(no_alloc);
|
| + if (content.IsTwoByte()) {
|
| + return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
|
| }
|
| for (int i = 0; i < slen; i++) {
|
| if (Get(i) != str[i]) return false;
|
|
|