From 608a99a90cd86eb0f61705fd362c6907cea0d389 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Tue, 17 Mar 2009 09:33:06 +0000 Subject: [PATCH] Remove all uses of StringShape variables, since that has proven to be error-prone and of little benefit in terms of performance. Review URL: http://codereview.chromium.org/45010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1521 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/api.cc | 10 +- src/codegen.cc | 3 +- src/conversions.cc | 11 +- src/factory.cc | 8 +- src/factory.h | 4 +- src/handles.cc | 4 +- src/heap.cc | 71 +++---- src/heap.h | 1 - src/interpreter-irregexp.cc | 5 +- src/jsregexp.cc | 81 +------- src/jsregexp.h | 9 - src/log.cc | 16 +- src/objects-debug.cc | 9 +- src/objects-inl.h | 82 ++++---- src/objects.cc | 234 ++++++++++------------- src/objects.h | 32 ++-- src/parser.cc | 10 +- src/prettyprinter.cc | 5 +- src/regexp-macro-assembler-ia32.cc | 13 +- src/runtime.cc | 289 +++++++++++++---------------- test/cctest/test-heap.cc | 7 +- test/cctest/test-regexp.cc | 6 +- test/cctest/test-strings.cc | 54 ++---- 23 files changed, 360 insertions(+), 604 deletions(-) diff --git a/src/api.cc b/src/api.cc index bb0747a14..985c60de8 100644 --- a/src/api.cc +++ b/src/api.cc @@ -2034,7 +2034,7 @@ int String::WriteAscii(char* buffer, int start, int length) const { i::Handle str = Utils::OpenHandle(this); // Flatten the string for efficiency. This applies whether we are // using StringInputBuffer or Get(i) to access the characters. - str->TryFlattenIfNotFlat(i::StringShape(*str)); + str->TryFlattenIfNotFlat(); int end = length; if ( (length == -1) || (length > str->length() - start) ) end = str->length() - start; @@ -2059,7 +2059,7 @@ int String::Write(uint16_t* buffer, int start, int length) const { i::Handle str = Utils::OpenHandle(this); // Flatten the string for efficiency. This applies whether we are // using StringInputBuffer or Get(i) to access the characters. - str->TryFlattenIfNotFlat(i::StringShape(*str)); + str->TryFlattenIfNotFlat(); int end = length; if ( (length == -1) || (length > str->length() - start) ) end = str->length() - start; @@ -2077,16 +2077,14 @@ int String::Write(uint16_t* buffer, int start, int length) const { bool v8::String::IsExternal() const { EnsureInitialized("v8::String::IsExternal()"); i::Handle str = Utils::OpenHandle(this); - i::StringShape shape(*str); - return shape.IsExternalTwoByte(); + return i::StringShape(*str).IsExternalTwoByte(); } bool v8::String::IsExternalAscii() const { EnsureInitialized("v8::String::IsExternalAscii()"); i::Handle str = Utils::OpenHandle(this); - i::StringShape shape(*str); - return shape.IsExternalAscii(); + return i::StringShape(*str).IsExternalAscii(); } diff --git a/src/codegen.cc b/src/codegen.cc index 558e85485..0e623acf0 100644 --- a/src/codegen.cc +++ b/src/codegen.cc @@ -402,8 +402,7 @@ bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) { "_Log"} }; Handle name = node->name(); - StringShape shape(*name); - if (name->length(shape) > 0 && name->Get(shape, 0) == '_') { + if (name->length() > 0 && name->Get(0) == '_') { for (unsigned i = 0; i < sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT); i++) { diff --git a/src/conversions.cc b/src/conversions.cc index 4b4faa551..57a45688f 100644 --- a/src/conversions.cc +++ b/src/conversions.cc @@ -55,8 +55,7 @@ static inline int GetChar(const char* str, int index) { static inline int GetChar(String* str, int index) { - StringShape shape(str); - return str->Get(shape, index); + return str->Get(index); } @@ -76,11 +75,10 @@ static inline const char* GetCString(const char* str, int index) { static inline const char* GetCString(String* str, int index) { - StringShape shape(str); - int length = str->length(shape); + int length = str->length(); char* result = NewArray(length + 1); for (int i = index; i < length; i++) { - uc16 c = str->Get(shape, i); + uc16 c = str->Get(i); if (c <= 127) { result[i - index] = static_cast(c); } else { @@ -108,8 +106,7 @@ static inline bool IsSpace(const char* str, int index) { static inline bool IsSpace(String* str, int index) { - StringShape shape(str); - return Scanner::kIsWhiteSpace.get(str->Get(shape, index)); + return Scanner::kIsWhiteSpace.get(str->Get(index)); } diff --git a/src/factory.cc b/src/factory.cc index ead40b47a..e29c84d2b 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -90,11 +90,9 @@ Handle Factory::NewRawTwoByteString(int length, Handle Factory::NewConsString(Handle first, - StringShape first_shape, - Handle second, - StringShape second_shape) { - if (first->length(first_shape) == 0) return second; - if (second->length(second_shape) == 0) return first; + Handle second) { + if (first->length() == 0) return second; + if (second->length() == 0) return first; CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String); } diff --git a/src/factory.h b/src/factory.h index 754c6da43..38d1a5bc5 100644 --- a/src/factory.h +++ b/src/factory.h @@ -98,9 +98,7 @@ class Factory : public AllStatic { // Create a new cons string object which consists of a pair of strings. static Handle NewConsString(Handle first, - StringShape first_shape, - Handle second, - StringShape second_shape); + Handle second); // Create a new sliced string object which represents a substring of a // backing string. diff --git a/src/handles.cc b/src/handles.cc index 48065dd4d..41323ed74 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -186,8 +186,8 @@ void TransformToFastProperties(Handle object, void FlattenString(Handle string) { - CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat(StringShape(*string))); - ASSERT(string->IsFlat(StringShape(*string))); + CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat()); + ASSERT(string->IsFlat()); } diff --git a/src/heap.cc b/src/heap.cc index eade646b8..daefaaf1b 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -230,7 +230,6 @@ void Heap::ReportStatisticsAfterGC() { void Heap::GarbageCollectionPrologue() { - RegExpImpl::NewSpaceCollectionPrologue(); gc_count_++; #ifdef DEBUG ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); @@ -475,7 +474,6 @@ void Heap::MarkCompactPrologue(bool is_compacting) { ClearKeyedLookupCache(); CompilationCache::MarkCompactPrologue(); - RegExpImpl::OldSpaceCollectionPrologue(); Top::MarkCompactPrologue(is_compacting); ThreadManager::MarkCompactPrologue(is_compacting); @@ -1392,41 +1390,31 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) { Object* Heap::AllocateConsString(String* first, String* second) { - StringShape first_shape(first); - StringShape second_shape(second); - int first_length = first->length(first_shape); - int second_length = second->length(second_shape); + int first_length = first->length(); + int second_length = second->length(); int length = first_length + second_length; - bool is_ascii = first_shape.IsAsciiRepresentation() - && second_shape.IsAsciiRepresentation(); + bool is_ascii = StringShape(first).IsAsciiRepresentation() + && StringShape(second).IsAsciiRepresentation(); // If the resulting string is small make a flat string. if (length < String::kMinNonFlatLength) { - ASSERT(first->IsFlat(first_shape)); - ASSERT(second->IsFlat(second_shape)); + ASSERT(first->IsFlat()); + ASSERT(second->IsFlat()); if (is_ascii) { Object* result = AllocateRawAsciiString(length); if (result->IsFailure()) return result; // Copy the characters into the new object. char* dest = SeqAsciiString::cast(result)->GetChars(); - String::WriteToFlat(first, first_shape, dest, 0, first_length); - String::WriteToFlat(second, - second_shape, - dest + first_length, - 0, - second_length); + String::WriteToFlat(first, dest, 0, first_length); + String::WriteToFlat(second, dest + first_length, 0, second_length); return result; } else { Object* result = AllocateRawTwoByteString(length); if (result->IsFailure()) return result; // Copy the characters into the new object. uc16* dest = SeqTwoByteString::cast(result)->GetChars(); - String::WriteToFlat(first, first_shape, dest, 0, first_length); - String::WriteToFlat(second, - second_shape, - dest + first_length, - 0, - second_length); + String::WriteToFlat(first, dest, 0, first_length); + String::WriteToFlat(second, dest + first_length, 0, second_length); return result; } } @@ -1457,25 +1445,24 @@ Object* Heap::AllocateConsString(String* first, Object* Heap::AllocateSlicedString(String* buffer, int start, int end) { - StringShape buffer_shape(buffer); int length = end - start; // If the resulting string is small make a sub string. if (end - start <= String::kMinNonFlatLength) { - return Heap::AllocateSubString(buffer, buffer_shape, start, end); + return Heap::AllocateSubString(buffer, start, end); } Map* map; if (length <= String::kMaxShortStringSize) { - map = buffer_shape.IsAsciiRepresentation() ? + map = StringShape(buffer).IsAsciiRepresentation() ? short_sliced_ascii_string_map() : short_sliced_string_map(); } else if (length <= String::kMaxMediumStringSize) { - map = buffer_shape.IsAsciiRepresentation() ? + map = StringShape(buffer).IsAsciiRepresentation() ? medium_sliced_ascii_string_map() : medium_sliced_string_map(); } else { - map = buffer_shape.IsAsciiRepresentation() ? + map = StringShape(buffer).IsAsciiRepresentation() ? long_sliced_ascii_string_map() : long_sliced_string_map(); } @@ -1493,41 +1480,38 @@ Object* Heap::AllocateSlicedString(String* buffer, Object* Heap::AllocateSubString(String* buffer, - StringShape buffer_shape, int start, int end) { int length = end - start; if (length == 1) { return Heap::LookupSingleCharacterStringFromCode( - buffer->Get(buffer_shape, start)); + buffer->Get(start)); } // Make an attempt to flatten the buffer to reduce access time. - if (!buffer->IsFlat(buffer_shape)) { - buffer->TryFlatten(buffer_shape); - buffer_shape = StringShape(buffer); + if (!buffer->IsFlat()) { + buffer->TryFlatten(); } - Object* result = buffer_shape.IsAsciiRepresentation() + Object* result = StringShape(buffer).IsAsciiRepresentation() ? AllocateRawAsciiString(length) : AllocateRawTwoByteString(length); if (result->IsFailure()) return result; // Copy the characters into the new object. String* string_result = String::cast(result); - StringShape result_shape(string_result); StringHasher hasher(length); int i = 0; for (; i < length && hasher.is_array_index(); i++) { - uc32 c = buffer->Get(buffer_shape, start + i); + uc32 c = buffer->Get(start + i); hasher.AddCharacter(c); - string_result->Set(result_shape, i, c); + string_result->Set(i, c); } for (; i < length; i++) { - uc32 c = buffer->Get(buffer_shape, start + i); + uc32 c = buffer->Get(start + i); hasher.AddCharacterNoIndex(c); - string_result->Set(result_shape, i, c); + string_result->Set(i, c); } string_result->set_length_field(hasher.GetHashField()); return result; @@ -1590,7 +1574,7 @@ Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { Object* result = Heap::AllocateRawTwoByteString(1); if (result->IsFailure()) return result; String* answer = String::cast(result); - answer->Set(StringShape(answer), 0, code); + answer->Set(0, code); return answer; } @@ -2016,10 +2000,9 @@ Object* Heap::AllocateStringFromUtf8(Vector string, // Convert and copy the characters into the new object. String* string_result = String::cast(result); decoder->Reset(string.start(), string.length()); - StringShape result_shape(string_result); for (int i = 0; i < chars; i++) { uc32 r = decoder->GetNext(); - string_result->Set(result_shape, i, r); + string_result->Set(i, r); } return result; } @@ -2042,9 +2025,8 @@ Object* Heap::AllocateStringFromTwoByte(Vector string, // Copy the characters into the new object, which may be either ASCII or // UTF-16. String* string_result = String::cast(result); - StringShape result_shape(string_result); for (int i = 0; i < string.length(); i++) { - string_result->Set(result_shape, i, string[i]); + string_result->Set(i, string[i]); } return result; } @@ -2163,14 +2145,13 @@ Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, reinterpret_cast(result)->set_map(map); // The hash value contains the length of the string. String* answer = String::cast(result); - StringShape answer_shape(answer); answer->set_length_field(length_field); ASSERT_EQ(size, answer->Size()); // Fill in the characters. for (int i = 0; i < chars; i++) { - answer->Set(answer_shape, i, buffer->GetNext()); + answer->Set(i, buffer->GetNext()); } return answer; } diff --git a/src/heap.h b/src/heap.h index 5a099343f..a13f027ec 100644 --- a/src/heap.h +++ b/src/heap.h @@ -532,7 +532,6 @@ class Heap : public AllStatic { // failed. // Please note this does not perform a garbage collection. static Object* AllocateSubString(String* buffer, - StringShape buffer_shape, int start, int end); diff --git a/src/interpreter-irregexp.cc b/src/interpreter-irregexp.cc index 33f6ec613..1cc5c5a1d 100644 --- a/src/interpreter-irregexp.cc +++ b/src/interpreter-irregexp.cc @@ -569,13 +569,12 @@ bool IrregexpInterpreter::Match(Handle code_array, Handle subject, int* registers, int start_position) { - ASSERT(subject->IsFlat(StringShape(*subject))); + ASSERT(subject->IsFlat()); AssertNoAllocation a; const byte* code_base = code_array->GetDataStartAddress(); - StringShape subject_shape(*subject); uc16 previous_char = '\n'; - if (subject_shape.IsAsciiRepresentation()) { + if (StringShape(*subject).IsAsciiRepresentation()) { Vector subject_vector = subject->ToAsciiVector(); if (start_position != 0) previous_char = subject_vector[start_position - 1]; return RawMatch(code_base, diff --git a/src/jsregexp.cc b/src/jsregexp.cc index 147afd30c..7acf639b5 100644 --- a/src/jsregexp.cc +++ b/src/jsregexp.cc @@ -55,27 +55,6 @@ namespace v8 { namespace internal { -String* RegExpImpl::last_ascii_string_ = NULL; -String* RegExpImpl::two_byte_cached_string_ = NULL; - - -void RegExpImpl::NewSpaceCollectionPrologue() { - // The two byte string is always in the old space. The Ascii string may be - // in either place. If it is in the old space we don't need to do anything. - if (Heap::InNewSpace(last_ascii_string_)) { - // Invalidate the cache. - last_ascii_string_ = NULL; - two_byte_cached_string_ = NULL; - } -} - - -void RegExpImpl::OldSpaceCollectionPrologue() { - last_ascii_string_ = NULL; - two_byte_cached_string_ = NULL; -} - - Handle RegExpImpl::CreateRegExpLiteral(Handle constructor, Handle pattern, Handle flags, @@ -92,55 +71,10 @@ Handle RegExpImpl::CreateRegExpLiteral(Handle constructor, } -// Converts a source string to a 16 bit flat string or a SlicedString containing -// a 16 bit flat string). -Handle RegExpImpl::CachedStringToTwoByte(Handle subject) { - if (*subject == last_ascii_string_) { - ASSERT(two_byte_cached_string_ != NULL); - return Handle(String::cast(two_byte_cached_string_)); - } - Handle two_byte_string = StringToTwoByte(subject); - last_ascii_string_ = *subject; - two_byte_cached_string_ = *two_byte_string; - return two_byte_string; -} - - -// Converts a source string to a 16 bit flat string or a SlicedString containing -// a 16 bit flat string). -Handle RegExpImpl::StringToTwoByte(Handle pattern) { - StringShape shape(*pattern); - if (!pattern->IsFlat(shape)) { - FlattenString(pattern); - shape = StringShape(*pattern); - } - Handle flat_string(shape.IsCons() ? - String::cast(ConsString::cast(*pattern)->first()) : - *pattern); - ASSERT(flat_string->IsString()); - StringShape flat_shape(*flat_string); - ASSERT(!flat_shape.IsCons()); - ASSERT(flat_shape.IsSequential() || - flat_shape.IsSliced() || - flat_shape.IsExternal()); - if (!flat_shape.IsAsciiRepresentation()) { - return flat_string; - } - - int len = flat_string->length(flat_shape); - Handle two_byte_string = - Factory::NewRawTwoByteString(len, TENURED); - uc16* dest = SeqTwoByteString::cast(*two_byte_string)->GetChars(); - String::WriteToFlat(*flat_string, flat_shape, dest, 0, len); - return two_byte_string; -} - - static JSRegExp::Flags RegExpFlagsFromString(Handle str) { int flags = JSRegExp::NONE; - StringShape shape(*str); - for (int i = 0; i < str->length(shape); i++) { - switch (str->Get(shape, i)) { + for (int i = 0; i < str->length(); i++) { + switch (str->Get(i)) { case 'i': flags |= JSRegExp::IGNORE_CASE; break; @@ -421,7 +355,7 @@ bool RegExpImpl::EnsureCompiledIrregexp(Handle re, JSRegExp::Flags flags = re->GetFlags(); Handle pattern(re->Pattern()); - if (!pattern->IsFlat(StringShape(*pattern))) { + if (!pattern->IsFlat()) { FlattenString(pattern); } @@ -552,7 +486,7 @@ Handle RegExpImpl::IrregexpExec(Handle regexp, } #endif - if (!subject->IsFlat(StringShape(*subject))) { + if (!subject->IsFlat()) { FlattenString(subject); } @@ -590,7 +524,7 @@ Handle RegExpImpl::IrregexpExecGlobal(Handle regexp, int result_length = 0; Handle matches; - if (!subject->IsFlat(StringShape(*subject))) { + if (!subject->IsFlat()) { FlattenString(subject); } @@ -659,9 +593,8 @@ Handle RegExpImpl::IrregexpExecOnce(Handle regexp, int previous_index, int* offsets_vector, int offsets_vector_length) { - StringShape shape(*subject); - ASSERT(subject->IsFlat(shape)); - bool is_ascii = shape.IsAsciiRepresentation(); + ASSERT(subject->IsFlat()); + bool is_ascii = StringShape(*subject).IsAsciiRepresentation(); bool rc; Handle original_subject = subject; diff --git a/src/jsregexp.h b/src/jsregexp.h index 145cb26f2..f6e2052cf 100644 --- a/src/jsregexp.h +++ b/src/jsregexp.h @@ -108,15 +108,6 @@ class RegExpImpl { Handle subject, Handle lastMatchInfo); - static void NewSpaceCollectionPrologue(); - static void OldSpaceCollectionPrologue(); - - // Converts a source string to a 16 bit flat string. The string - // will be either sequential or it will be a SlicedString backed - // by a flat string. - static Handle StringToTwoByte(Handle pattern); - static Handle CachedStringToTwoByte(Handle pattern); - // Offsets in the lastMatchInfo array. static const int kLastCaptureCount = 0; static const int kLastSubject = 1; diff --git a/src/log.cc b/src/log.cc index 805bb519c..bb895e289 100644 --- a/src/log.cc +++ b/src/log.cc @@ -362,29 +362,27 @@ void LogMessageBuilder::Append(const char c) { // Append a heap string. void LogMessageBuilder::Append(String* str) { AssertNoAllocation no_heap_allocation; // Ensure string stay valid. - StringShape shape(str); - int length = str->length(shape); + int length = str->length(); for (int i = 0; i < length; i++) { - Append(static_cast(str->Get(shape, i))); + Append(static_cast(str->Get(i))); } } void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { AssertNoAllocation no_heap_allocation; // Ensure string stay valid. - StringShape shape(str); - int len = str->length(shape); + int len = str->length(); if (len > 0x1000) len = 0x1000; if (show_impl_info) { - Append(shape.IsAsciiRepresentation() ? 'a' : '2'); - if (shape.IsExternal()) + Append(StringShape(str).IsAsciiRepresentation() ? 'a' : '2'); + if (StringShape(str).IsExternal()) Append('e'); - if (shape.IsSymbol()) + if (StringShape(str).IsSymbol()) Append('#'); Append(":%i:", str->length()); } for (int i = 0; i < len; i++) { - uc32 c = str->Get(shape, i); + uc32 c = str->Get(i); if (c > 0xff) { Append("\\u%04x", c); } else if (c < 32 || c > 126) { diff --git a/src/objects-debug.cc b/src/objects-debug.cc index de5b1ddbe..f40fd3e6b 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -491,20 +491,19 @@ void JSValue::JSValueVerify() { void String::StringPrint() { - StringShape shape(this); - if (shape.IsSymbol()) { + if (StringShape(this).IsSymbol()) { PrintF("#"); - } else if (shape.IsCons()) { + } else if (StringShape(this).IsCons()) { PrintF("c\""); } else { PrintF("\""); } for (int i = 0; i < length(); i++) { - PrintF("%c", Get(shape, i)); + PrintF("%c", Get(i)); } - if (!shape.IsSymbol()) PrintF("\""); + if (!StringShape(this).IsSymbol()) PrintF("\""); } diff --git a/src/objects-inl.h b/src/objects-inl.h index af2f0f04b..bfa92ee6a 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -143,15 +143,15 @@ bool Object::IsSeqString() { bool Object::IsSeqAsciiString() { if (!IsString()) return false; - StringShape shape(String::cast(this)); - return shape.IsSequential() && shape.IsAsciiRepresentation(); + return StringShape(String::cast(this)).IsSequential() && + StringShape(String::cast(this)).IsAsciiRepresentation(); } bool Object::IsSeqTwoByteString() { if (!IsString()) return false; - StringShape shape(String::cast(this)); - return shape.IsSequential() && shape.IsTwoByteRepresentation(); + return StringShape(String::cast(this)).IsSequential() && + StringShape(String::cast(this)).IsTwoByteRepresentation(); } @@ -163,15 +163,15 @@ bool Object::IsExternalString() { bool Object::IsExternalAsciiString() { if (!IsString()) return false; - StringShape shape(String::cast(this)); - return shape.IsExternal() && shape.IsAsciiRepresentation(); + return StringShape(String::cast(this)).IsExternal() && + StringShape(String::cast(this)).IsAsciiRepresentation(); } bool Object::IsExternalTwoByteString() { if (!IsString()) return false; - StringShape shape(String::cast(this)); - return shape.IsExternal() && shape.IsTwoByteRepresentation(); + return StringShape(String::cast(this)).IsExternal() && + StringShape(String::cast(this)).IsTwoByteRepresentation(); } @@ -1243,15 +1243,13 @@ void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { int DescriptorArray::Search(String* name) { SLOW_ASSERT(IsSortedNoDuplicates()); - StringShape shape(name); - // Check for empty descriptor array. int nof = number_of_descriptors(); if (nof == 0) return kNotFound; // Fast case: do linear search for small arrays. const int kMaxElementsForLinearSearch = 8; - if (shape.IsSymbol() && nof < kMaxElementsForLinearSearch) { + if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { return LinearSearch(name, nof); } @@ -1392,27 +1390,21 @@ INT_ACCESSORS(Array, length, kLengthOffset) bool String::Equals(String* other) { if (other == this) return true; - StringShape this_shape(this); - StringShape other_shape(other); - if (this_shape.IsSymbol() && other_shape.IsSymbol()) return false; - return SlowEquals(this_shape, other, other_shape); + if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) { + return false; + } + return SlowEquals(other); } -int String::length(StringShape shape) { - ASSERT(shape.type() == StringShape(this).type()); +int String::length() { uint32_t len = READ_INT_FIELD(this, kLengthOffset); ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); ASSERT(kLongStringTag == 0); - return len >> (shape.size_tag() + kLongLengthShift); -} - - -int String::length() { - return length(StringShape(this)); + return len >> (StringShape(this).size_tag() + kLongLengthShift); } @@ -1421,10 +1413,9 @@ void String::set_length(int value) { ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift); ASSERT(kLongStringTag == 0); - StringShape shape(this); WRITE_INT_FIELD(this, kLengthOffset, - value << (shape.size_tag() + kLongLengthShift)); + value << (StringShape(this).size_tag() + kLongLengthShift)); } @@ -1438,21 +1429,19 @@ void String::set_length_field(uint32_t value) { } -Object* String::TryFlattenIfNotFlat(StringShape shape) { - ASSERT(shape.type() == StringShape(this).type()); +Object* String::TryFlattenIfNotFlat() { // 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(shape)) { - return TryFlatten(shape); + if (!IsFlat()) { + return TryFlatten(); } return this; } -uint16_t String::Get(StringShape shape, int index) { - ASSERT(shape.type() == StringShape(this).type()); - ASSERT(index >= 0 && index < length(shape)); - switch (shape.full_representation_tag()) { +uint16_t String::Get(int index) { + ASSERT(index >= 0 && index < length()); + switch (StringShape(this).full_representation_tag()) { case kSeqStringTag | kAsciiStringTag: return SeqAsciiString::cast(this)->SeqAsciiStringGet(index); case kSeqStringTag | kTwoByteStringTag: @@ -1476,29 +1465,26 @@ uint16_t String::Get(StringShape shape, int index) { } -void String::Set(StringShape shape, int index, uint16_t value) { - ASSERT(shape.type() == StringShape(this).type()); - ASSERT(shape.type() == StringShape(this).type()); - ASSERT(index >= 0 && index < length(shape)); - ASSERT(shape.IsSequential()); +void String::Set(int index, uint16_t value) { + ASSERT(index >= 0 && index < length()); + ASSERT(StringShape(this).IsSequential()); - return shape.IsAsciiRepresentation() + return StringShape(this).IsAsciiRepresentation() ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); } -bool String::IsFlat(StringShape shape) { - ASSERT(shape.type() == StringShape(this).type()); - switch (shape.representation_tag()) { +bool String::IsFlat() { + switch (StringShape(this).representation_tag()) { case kConsStringTag: { String* second = ConsString::cast(this)->second(); // Only flattened strings have second part empty. return second->length() == 0; } case kSlicedStringTag: { - StringShape slice_shape = StringShape(SlicedString::cast(this)->buffer()); - StringRepresentationTag tag = slice_shape.representation_tag(); + StringRepresentationTag tag = + StringShape(SlicedString::cast(this)->buffer()).representation_tag(); return tag == kSeqStringTag || tag == kExternalStringTag; } default: @@ -1552,7 +1538,7 @@ void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { } -int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) { +int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { uint32_t length = READ_INT_FIELD(this, kLengthOffset); ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); @@ -1561,13 +1547,13 @@ int SeqTwoByteString::SeqTwoByteStringSize(StringShape shape) { // Use the map (and not 'this') to compute the size tag, since // TwoByteStringSize is called during GC when maps are encoded. - length >>= shape.size_tag() + kLongLengthShift; + length >>= StringShape(instance_type).size_tag() + kLongLengthShift; return SizeFor(length); } -int SeqAsciiString::SeqAsciiStringSize(StringShape shape) { +int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) { uint32_t length = READ_INT_FIELD(this, kLengthOffset); ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift); @@ -1576,7 +1562,7 @@ int SeqAsciiString::SeqAsciiStringSize(StringShape shape) { // Use the map (and not 'this') to compute the size tag, since // AsciiStringSize is called during GC when maps are encoded. - length >>= shape.size_tag() + kLongLengthShift; + length >>= StringShape(instance_type).size_tag() + kLongLengthShift; return SizeFor(length); } diff --git a/src/objects.cc b/src/objects.cc index 15ce483d0..42c9d2af8 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -575,10 +575,9 @@ Failure* Failure::RetryAfterGC(int requested_bytes, AllocationSpace space) { // We don't use the BBC's overcorrect "an historic occasion" though if // you speak a dialect you may well say "an 'istoric occasion". static bool AnWord(String* str) { - StringShape shape(str); - if (str->length(shape) == 0) return false; // A nothing. - int c0 = str->Get(shape, 0); - int c1 = str->length(shape) > 1 ? str->Get(shape, 1) : 0; + if (str->length() == 0) return false; // A nothing. + int c0 = str->Get(0); + int c1 = str->length() > 1 ? str->Get(1) : 0; if (c0 == 'U') { if (c1 > 'Z') { return true; // An Umpire, but a UTF8String, a U. @@ -594,7 +593,7 @@ static bool AnWord(String* str) { } -Object* String::TryFlatten(StringShape shape) { +Object* String::TryFlatten() { #ifdef DEBUG // Do not attempt to flatten in debug mode when allocation is not // allowed. This is to avoid an assertion failure when allocating. @@ -603,7 +602,7 @@ Object* String::TryFlatten(StringShape shape) { if (!Heap::IsAllocationAllowed()) return this; #endif - switch (shape.representation_tag()) { + switch (StringShape(this).representation_tag()) { case kSlicedStringTag: { SlicedString* ss = SlicedString::cast(this); // The SlicedString constructor should ensure that there are no @@ -611,7 +610,7 @@ Object* String::TryFlatten(StringShape shape) { // SlicedStrings. String* buf = ss->buffer(); ASSERT(!buf->IsSlicedString()); - Object* ok = buf->TryFlatten(StringShape(buf)); + Object* ok = buf->TryFlatten(); if (ok->IsFailure()) return ok; // Under certain circumstances (TryFlattenIfNotFlat fails in // String::Slice) we can have a cons string under a slice. @@ -630,21 +629,19 @@ Object* String::TryFlatten(StringShape shape) { // cons string is in old space. It can never get GCed until there is // an old space GC. PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; - int len = length(shape); + int len = length(); Object* object; String* result; - if (shape.IsAsciiRepresentation()) { + if (StringShape(this).IsAsciiRepresentation()) { object = Heap::AllocateRawAsciiString(len, tenure); if (object->IsFailure()) return object; result = String::cast(object); String* first = cs->first(); - StringShape first_shape(first); - int first_length = first->length(first_shape); + int first_length = first->length(); char* dest = SeqAsciiString::cast(result)->GetChars(); - WriteToFlat(first, first_shape, dest, 0, first_length); + WriteToFlat(first, dest, 0, first_length); String* second = cs->second(); WriteToFlat(second, - StringShape(second), dest + first_length, 0, len - first_length); @@ -654,12 +651,10 @@ Object* String::TryFlatten(StringShape shape) { result = String::cast(object); uc16* dest = SeqTwoByteString::cast(result)->GetChars(); String* first = cs->first(); - StringShape first_shape(first); - int first_length = first->length(first_shape); - WriteToFlat(first, first_shape, dest, 0, first_length); + int first_length = first->length(); + WriteToFlat(first, dest, 0, first_length); String* second = cs->second(); WriteToFlat(second, - StringShape(second), dest + first_length, 0, len - first_length); @@ -761,8 +756,7 @@ bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { void String::StringShortPrint(StringStream* accumulator) { - StringShape shape(this); - int len = length(shape); + int len = length(); if (len > kMaxMediumStringSize) { accumulator->Add("", len); return; @@ -790,7 +784,7 @@ void String::StringShortPrint(StringStream* accumulator) { } buf.Reset(this); if (ascii) { - accumulator->Add("Add("Put(buf.GetNext()); } @@ -798,7 +792,7 @@ void String::StringShortPrint(StringStream* accumulator) { } else { // Backslash indicates that the string contains control // characters and that backslashes are therefore escaped. - accumulator->Add("Add("(this)->SeqAsciiStringSize(shape); + if (StringShape(instance_type).IsAsciiRepresentation()) { + SeqAsciiString* seq_ascii_this = reinterpret_cast(this); + return seq_ascii_this->SeqAsciiStringSize(instance_type); } else { SeqTwoByteString* self = reinterpret_cast(this); - return self->SeqTwoByteStringSize(shape); + return self->SeqTwoByteStringSize(instance_type); } } @@ -2559,7 +2553,7 @@ Object* JSObject::DefineGetterSetter(String* name, } // Try to flatten before operating on the string. - name->TryFlattenIfNotFlat(StringShape(name)); + name->TryFlattenIfNotFlat(); // Check if there is an API defined callback object which prohibits // callback overwriting in this object or it's prototype chain. @@ -3274,13 +3268,12 @@ bool String::LooksValid() { int String::Utf8Length() { - StringShape shape(this); - if (shape.IsAsciiRepresentation()) return length(shape); + if (StringShape(this).IsAsciiRepresentation()) return length(); // Attempt to flatten before accessing the string. It probably // doesn't make Utf8Length faster, but it is very likely that // the string will be accessed later (for example by WriteUtf8) // so it's still a good idea. - TryFlattenIfNotFlat(shape); // shape is now no longer valid. + TryFlattenIfNotFlat(); Access buffer(&string_input_buffer); buffer->Reset(0, this); int result = 0; @@ -3291,26 +3284,23 @@ int String::Utf8Length() { Vector String::ToAsciiVector() { - StringShape shape(this); - ASSERT(shape.IsAsciiRepresentation()); - ASSERT(IsFlat(shape)); + ASSERT(StringShape(this).IsAsciiRepresentation()); + ASSERT(IsFlat()); int offset = 0; - int length = this->length(shape); - StringRepresentationTag string_tag = shape.representation_tag(); + int length = this->length(); + StringRepresentationTag string_tag = StringShape(this).representation_tag(); String* string = this; if (string_tag == kSlicedStringTag) { SlicedString* sliced = SlicedString::cast(string); offset += sliced->start(); string = sliced->buffer(); - shape = StringShape(string); - string_tag = shape.representation_tag(); + string_tag = StringShape(string).representation_tag(); } else if (string_tag == kConsStringTag) { ConsString* cons = ConsString::cast(string); - ASSERT(cons->second()->length(StringShape(cons->second())) == 0); + ASSERT(cons->second()->length() == 0); string = cons->first(); - shape = StringShape(string); - string_tag = shape.representation_tag(); + string_tag = StringShape(string).representation_tag(); } if (string_tag == kSeqStringTag) { SeqAsciiString* seq = SeqAsciiString::cast(string); @@ -3325,26 +3315,23 @@ Vector String::ToAsciiVector() { Vector String::ToUC16Vector() { - StringShape shape(this); - ASSERT(shape.IsTwoByteRepresentation()); - ASSERT(IsFlat(shape)); + ASSERT(StringShape(this).IsTwoByteRepresentation()); + ASSERT(IsFlat()); int offset = 0; - int length = this->length(shape); - StringRepresentationTag string_tag = shape.representation_tag(); + int length = this->length(); + StringRepresentationTag string_tag = StringShape(this).representation_tag(); String* string = this; if (string_tag == kSlicedStringTag) { SlicedString* sliced = SlicedString::cast(string); offset += sliced->start(); string = String::cast(sliced->buffer()); - shape = StringShape(string); - string_tag = shape.representation_tag(); + string_tag = StringShape(string).representation_tag(); } else if (string_tag == kConsStringTag) { ConsString* cons = ConsString::cast(string); - ASSERT(cons->second()->length(StringShape(cons->second())) == 0); + ASSERT(cons->second()->length() == 0); string = cons->first(); - shape = StringShape(string); - string_tag = shape.representation_tag(); + string_tag = StringShape(string).representation_tag(); } if (string_tag == kSeqStringTag) { SeqTwoByteString* seq = SeqTwoByteString::cast(string); @@ -3424,9 +3411,8 @@ const uc16* String::GetTwoByteData() { const uc16* String::GetTwoByteData(unsigned start) { - StringShape shape(this); - ASSERT(!shape.IsAsciiRepresentation()); - switch (shape.representation_tag()) { + ASSERT(!StringShape(this).IsAsciiRepresentation()); + switch (StringShape(this).representation_tag()) { case kSeqStringTag: return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); case kExternalStringTag: @@ -3438,7 +3424,7 @@ const uc16* String::GetTwoByteData(unsigned start) { if (StringShape(buffer).IsCons()) { ConsString* cs = ConsString::cast(buffer); // Flattened string. - ASSERT(cs->second()->length(StringShape(cs->second())) == 0); + ASSERT(cs->second()->length() == 0); buffer = cs->first(); } return buffer->GetTwoByteData(start + sliced_string->start()); @@ -3541,8 +3527,7 @@ const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb, while (true) { String* left = current->first(); - StringShape left_shape(left); - unsigned left_length = (unsigned)left->length(left_shape); + unsigned left_length = (unsigned)left->length(); if (left_length > offset && (max_chars <= left_length - offset || (rbb->capacity <= left_length - offset && @@ -3554,7 +3539,7 @@ const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb, // the point where we switch to the -IntoBuffer routines (below) in order // to maximize the chances of delegating a big chunk of work to the // efficient *AsciiStringReadBlock routines. - if (left_shape.IsCons()) { + if (StringShape(left).IsCons()) { current = ConsString::cast(left); continue; } else { @@ -3719,10 +3704,9 @@ const unibrow::byte* String::ReadBlock(String* input, rbb->remaining = 0; return NULL; } - StringShape shape(input); - switch (shape.representation_tag()) { + switch (StringShape(input).representation_tag()) { case kSeqStringTag: - if (shape.IsAsciiRepresentation()) { + if (StringShape(input).IsAsciiRepresentation()) { SeqAsciiString* str = SeqAsciiString::cast(input); return str->SeqAsciiStringReadBlock(&rbb->remaining, offset_ptr, @@ -3743,7 +3727,7 @@ const unibrow::byte* String::ReadBlock(String* input, offset_ptr, max_chars); case kExternalStringTag: - if (shape.IsAsciiRepresentation()) { + if (StringShape(input).IsAsciiRepresentation()) { return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock( &rbb->remaining, offset_ptr, @@ -3795,9 +3779,8 @@ FlatStringReader::~FlatStringReader() { void FlatStringReader::RefreshState() { if (str_ == NULL) return; Handle str(str_); - StringShape shape(*str); - ASSERT(str->IsFlat(shape)); - is_ascii_ = shape.IsAsciiRepresentation(); + ASSERT(str->IsFlat()); + is_ascii_ = StringShape(*str).IsAsciiRepresentation(); if (is_ascii_) { start_ = str->ToAsciiVector().start(); } else { @@ -3833,13 +3816,12 @@ void String::ReadBlockIntoBuffer(String* input, ReadBlockBuffer* rbb, unsigned* offset_ptr, unsigned max_chars) { - StringShape shape(input); - ASSERT(*offset_ptr <= (unsigned)input->length(shape)); + ASSERT(*offset_ptr <= (unsigned)input->length()); if (max_chars == 0) return; - switch (shape.representation_tag()) { + switch (StringShape(input).representation_tag()) { case kSeqStringTag: - if (shape.IsAsciiRepresentation()) { + if (StringShape(input).IsAsciiRepresentation()) { SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); @@ -3861,7 +3843,7 @@ void String::ReadBlockIntoBuffer(String* input, max_chars); return; case kExternalStringTag: - if (shape.IsAsciiRepresentation()) { + if (StringShape(input).IsAsciiRepresentation()) { ExternalAsciiString::cast(input)-> ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); } else { @@ -3885,12 +3867,11 @@ const unibrow::byte* String::ReadBlock(String* input, unsigned capacity, unsigned* remaining, unsigned* offset_ptr) { - StringShape shape(input); - ASSERT(*offset_ptr <= (unsigned)input->length(shape)); - unsigned chars = input->length(shape) - *offset_ptr; + ASSERT(*offset_ptr <= (unsigned)input->length()); + unsigned chars = input->length() - *offset_ptr; ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars); - ASSERT(rbb.remaining <= static_cast(input->length(shape))); + ASSERT(rbb.remaining <= static_cast(input->length())); *remaining = rbb.remaining; return answer; } @@ -3901,14 +3882,13 @@ const unibrow::byte* String::ReadBlock(String** raw_input, unsigned capacity, unsigned* remaining, unsigned* offset_ptr) { - StringShape shape(*raw_input); Handle input(raw_input); - ASSERT(*offset_ptr <= (unsigned)input->length(shape)); - unsigned chars = input->length(shape) - *offset_ptr; + ASSERT(*offset_ptr <= (unsigned)input->length()); + unsigned chars = input->length() - *offset_ptr; if (chars > capacity) chars = capacity; ReadBlockBuffer rbb(util_buffer, 0, capacity, 0); ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars); - ASSERT(rbb.remaining <= static_cast(input->length(shape))); + ASSERT(rbb.remaining <= static_cast(input->length())); *remaining = rbb.remaining; return rbb.util_buffer; } @@ -3928,13 +3908,12 @@ void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb, while (true) { String* left = current->first(); - StringShape left_shape(left); - unsigned left_length = (unsigned)left->length(left_shape); + unsigned left_length = (unsigned)left->length(); if (left_length > offset && max_chars <= left_length - offset) { // Left hand side only - iterate unless we have reached the bottom of // the cons tree. - if (left_shape.IsCons()) { + if (StringShape(left).IsCons()) { current = ConsString::cast(left); continue; } else { @@ -4002,27 +3981,23 @@ uint16_t ConsString::ConsStringGet(int index) { // Check for a flattened cons string if (second()->length() == 0) { String* left = first(); - return left->Get(StringShape(left), index); + return left->Get(index); } String* string = String::cast(this); - StringShape shape(string); while (true) { - if (shape.IsCons()) { + if (StringShape(string).IsCons()) { ConsString* cons_string = ConsString::cast(string); String* left = cons_string->first(); - StringShape left_shape(left); - if (left->length(left_shape) > index) { + if (left->length() > index) { string = left; - shape = left_shape; } else { - index -= left->length(left_shape); + index -= left->length(); string = cons_string->second(); - shape = StringShape(string); } } else { - return string->Get(shape, index); + return string->Get(index); } } @@ -4033,17 +4008,15 @@ uint16_t ConsString::ConsStringGet(int index) { template void String::WriteToFlat(String* src, - StringShape src_shape, sinkchar* sink, int f, int t) { String* source = src; - StringShape shape = src_shape; int from = f; int to = t; while (true) { - ASSERT(0 <= from && from <= to && to <= source->length(shape)); - switch (shape.full_representation_tag()) { + ASSERT(0 <= from && from <= to && to <= source->length()); + switch (StringShape(source).full_representation_tag()) { case kAsciiStringTag | kExternalStringTag: { CopyChars(sink, ExternalAsciiString::cast(source)->resource()->data() + from, @@ -4077,19 +4050,17 @@ void String::WriteToFlat(String* src, from += start; to += start; source = String::cast(sliced_string->buffer()); - shape = StringShape(source); break; } case kAsciiStringTag | kConsStringTag: case kTwoByteStringTag | kConsStringTag: { ConsString* cons_string = ConsString::cast(source); String* first = cons_string->first(); - StringShape first_shape(first); - int boundary = first->length(first_shape); + int boundary = first->length(); if (to - boundary >= boundary - from) { // Right hand side is longer. Recurse over left. if (from < boundary) { - WriteToFlat(first, first_shape, sink, from, boundary); + WriteToFlat(first, sink, from, boundary); sink += boundary - from; from = 0; } else { @@ -4097,20 +4068,17 @@ void String::WriteToFlat(String* src, } to -= boundary; source = cons_string->second(); - shape = StringShape(source); } else { // Left hand side is longer. Recurse over right. if (to > boundary) { String* second = cons_string->second(); WriteToFlat(second, - StringShape(second), sink + boundary - from, 0, to - boundary); to = boundary; } source = first; - shape = first_shape; } break; } @@ -4128,7 +4096,7 @@ uint16_t SlicedString::SlicedStringGet(int index) { ASSERT(index >= 0 && index < this->length()); // Delegate to the buffer string. String* underlying = buffer(); - return underlying->Get(StringShape(underlying), start() + index); + return underlying->Get(start() + index); } @@ -4192,9 +4160,8 @@ static StringInputBuffer string_compare_buffer_b; template static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { - StringShape b_shape(b); - if (b->IsFlat(b_shape)) { - if (b_shape.IsAsciiRepresentation()) { + if (b->IsFlat()) { + if (StringShape(b).IsAsciiRepresentation()) { VectorIterator ib(b->ToAsciiVector()); return CompareStringContents(ia, &ib); } else { @@ -4211,12 +4178,10 @@ static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { static StringInputBuffer string_compare_buffer_a; -bool String::SlowEquals(StringShape this_shape, - String* other, - StringShape other_shape) { +bool String::SlowEquals(String* other) { // Fast check: negative check with lengths. - int len = length(this_shape); - if (len != other->length(other_shape)) return false; + int len = length(); + if (len != other->length()) return false; if (len == 0) return true; // Fast check: if hash code is computed for both strings @@ -4225,18 +4190,18 @@ bool String::SlowEquals(StringShape this_shape, if (Hash() != other->Hash()) return false; } - if (this_shape.IsSequentialAscii() && other_shape.IsSequentialAscii()) { + if (StringShape(this).IsSequentialAscii() && StringShape(other).IsSequentialAscii()) { const char* str1 = SeqAsciiString::cast(this)->GetChars(); const char* str2 = SeqAsciiString::cast(other)->GetChars(); return CompareRawStringContents(Vector(str1, len), Vector(str2, len)); } - if (this->IsFlat(this_shape)) { - if (this_shape.IsAsciiRepresentation()) { + if (this->IsFlat()) { + if (StringShape(this).IsAsciiRepresentation()) { Vector vec1 = this->ToAsciiVector(); - if (other->IsFlat(other_shape)) { - if (other_shape.IsAsciiRepresentation()) { + if (other->IsFlat()) { + if (StringShape(other).IsAsciiRepresentation()) { Vector vec2 = other->ToAsciiVector(); return CompareRawStringContents(vec1, vec2); } else { @@ -4251,8 +4216,8 @@ bool String::SlowEquals(StringShape this_shape, } } else { Vector vec1 = this->ToUC16Vector(); - if (other->IsFlat(other_shape)) { - if (other_shape.IsAsciiRepresentation()) { + if (other->IsFlat()) { + if (StringShape(other).IsAsciiRepresentation()) { VectorIterator buf1(vec1); VectorIterator ib(other->ToAsciiVector()); return CompareStringContents(&buf1, &ib); @@ -4302,14 +4267,13 @@ bool String::MarkAsUndetectable() { bool String::IsEqualTo(Vector str) { - StringShape this_shape(this); - int slen = length(this_shape); + int slen = length(); Access decoder(Scanner::utf8_decoder()); decoder->Reset(str.start(), str.length()); int i; for (i = 0; i < slen && decoder->has_more(); i++) { uc32 r = decoder->GetNext(); - if (Get(this_shape, i) != r) return false; + if (Get(i) != r) return false; } return i == slen && !decoder->has_more(); } @@ -4363,8 +4327,7 @@ bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, bool String::SlowAsArrayIndex(uint32_t* index) { - StringShape shape(this); - if (length(shape) <= kMaxCachedArrayIndexLength) { + if (length() <= kMaxCachedArrayIndexLength) { Hash(); // force computation of hash code uint32_t field = length_field(); if ((field & kIsArrayIndexMask) == 0) return false; @@ -4372,7 +4335,7 @@ bool String::SlowAsArrayIndex(uint32_t* index) { return true; } else { StringInputBuffer buffer(this); - return ComputeArrayIndex(&buffer, index, length(shape)); + return ComputeArrayIndex(&buffer, index, length()); } } @@ -4433,9 +4396,8 @@ uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer, Object* String::Slice(int start, int end) { - StringShape shape(this); - if (start == 0 && end == length(shape)) return this; - if (shape.representation_tag() == kSlicedStringTag) { + if (start == 0 && end == length()) return this; + if (StringShape(this).representation_tag() == kSlicedStringTag) { // Translate slices of a SlicedString into slices of the // underlying string buffer. SlicedString* str = SlicedString::cast(this); @@ -4459,14 +4421,13 @@ Object* String::Slice(int start, int end) { // if Heap::AllocateSlicedString actually returned a SlicedString. It will // return flat strings for small slices for efficiency reasons. String* answer = String::cast(result); - StringShape answer_shape(answer); - if (answer_shape.IsSliced() && - shape.representation_tag() == kConsStringTag) { - TryFlatten(shape); + if (StringShape(answer).IsSliced() && + StringShape(this).representation_tag() == kConsStringTag) { + TryFlatten(); // If the flatten succeeded we might as well make the sliced string point // to the flat string rather than the cons string. String* second = ConsString::cast(this)->second(); - if (second->length(StringShape(second)) == 0) { + if (second->length() == 0) { SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first()); } } @@ -4475,10 +4436,9 @@ Object* String::Slice(int start, int end) { void String::PrintOn(FILE* file) { - StringShape shape(this); - int length = this->length(shape); + int length = this->length(); for (int i = 0; i < length; i++) { - fprintf(file, "%c", Get(shape, i)); + fprintf(file, "%c", Get(i)); } } @@ -6034,13 +5994,12 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, Object* val = JSValue::cast(this)->value(); if (val->IsString()) { String* str = String::cast(val); - StringShape shape(str); if (storage) { - for (int i = 0; i < str->length(shape); i++) { + for (int i = 0; i < str->length(); i++) { storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); } } - counter += str->length(shape); + counter += str->length(); } } ASSERT(!storage || storage->length() == counter); @@ -6288,10 +6247,9 @@ class SymbolKey : public HashTableKey { Object* GetObject() { // If the string is a cons string, attempt to flatten it so that // symbols will most often be flat strings. - StringShape shape(string_); - if (shape.IsCons()) { + if (StringShape(string_).IsCons()) { ConsString* cons_string = ConsString::cast(string_); - cons_string->TryFlatten(shape); + cons_string->TryFlatten(); if (cons_string->second() == Heap::empty_string()) { string_ = cons_string->first(); } diff --git a/src/objects.h b/src/objects.h index e6be74bee..d43d616ec 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3139,13 +3139,9 @@ class StringHasher { // to be passed by value and is immutable, but be aware that flattening a // string can potentially alter its shape. Also be aware that a GC caused by // something else can alter the shape of a string due to ConsString -// shortcutting. -// -// Most of the methods designed to interrogate a string as to its exact nature -// have been made into methods on StringShape in order to encourage the use of -// StringShape. The String class has both a length() and a length(StringShape) -// operation. The former is simpler to type, but the latter is faster if you -// need the StringShape for some other operation immediately before or after. +// shortcutting. Keeping these restrictions in mind has proven to be error- +// prone and so we no longer put StringShapes in variables unless there is a +// concrete performance benefit at that particular point in the code. class StringShape BASE_EMBEDDED { public: inline explicit StringShape(String* s); @@ -3194,9 +3190,6 @@ class StringShape BASE_EMBEDDED { class String: public HeapObject { public: // Get and set the length of the string. - // Fast version. - inline int length(StringShape shape); - // Easy version. inline int length(); inline void set_length(int value); @@ -3208,22 +3201,22 @@ class String: public HeapObject { inline void set_length_field(uint32_t value); // Get and set individual two byte chars in the string. - inline void Set(StringShape shape, int index, uint16_t value); + inline void Set(int index, uint16_t value); // Get individual two byte char in the string. Repeated calls // to this method are not efficient unless the string is flat. - inline uint16_t Get(StringShape shape, int index); + 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 or a // SlicedString. Flatten mutates the ConsString and might return a // failure. - Object* TryFlatten(StringShape shape); + Object* TryFlatten(); // Try to flatten the string. Checks first inline to see if it is necessary. // Do not handle allocation failures. After calling TryFlattenIfNotFlat, the // string could still be a ConsString, in which case a failure is returned. // Use FlattenString from Handles.cc to be sure to flatten. - inline Object* TryFlattenIfNotFlat(StringShape shape); + inline Object* TryFlattenIfNotFlat(); Vector ToAsciiVector(); Vector ToUC16Vector(); @@ -3302,7 +3295,7 @@ class String: public HeapObject { void StringPrint(); void StringVerify(); #endif - inline bool IsFlat(StringShape shape); + inline bool IsFlat(); // Layout description. static const int kLengthOffset = HeapObject::kHeaderSize; @@ -3364,7 +3357,6 @@ class String: public HeapObject { // Helper function for flattening strings. template static void WriteToFlat(String* source, - StringShape shape, sinkchar* sink, int from, int to); @@ -3405,9 +3397,7 @@ class String: public HeapObject { private: // Slow case of String::Equals. This implementation works on any strings // but it is most efficient on strings that are almost flat. - bool SlowEquals(StringShape this_shape, - String* other, - StringShape other_shape); + bool SlowEquals(String* other); // Slow case of AsArrayIndex. bool SlowAsArrayIndex(uint32_t* index); @@ -3454,7 +3444,7 @@ class SeqAsciiString: public SeqString { // Garbage collection support. This method is called by the // garbage collector to compute the actual size of an AsciiString // instance. - inline int SeqAsciiStringSize(StringShape shape); + inline int SeqAsciiStringSize(InstanceType instance_type); // Computes the size for an AsciiString instance of a given length. static int SizeFor(int length) { @@ -3499,7 +3489,7 @@ class SeqTwoByteString: public SeqString { // Garbage collection support. This method is called by the // garbage collector to compute the actual size of a TwoByteString // instance. - inline int SeqTwoByteStringSize(StringShape shape); + inline int SeqTwoByteStringSize(InstanceType instance_type); // Computes the size for a TwoByteString instance of a given length. static int SizeFor(int length) { diff --git a/src/parser.cc b/src/parser.cc index 973a7fcd8..a760772a3 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -1097,11 +1097,10 @@ FunctionLiteral* Parser::ParseProgram(Handle source, ZoneScope zone_scope(DONT_DELETE_ON_EXIT); HistogramTimerScope timer(&Counters::parse); - StringShape shape(*source); - Counters::total_parse_size.Increment(source->length(shape)); + Counters::total_parse_size.Increment(source->length()); // Initialize parser state. - source->TryFlattenIfNotFlat(shape); + source->TryFlattenIfNotFlat(); scanner_.Init(source, stream, 0); ASSERT(target_stack_ == NULL); @@ -1150,9 +1149,8 @@ FunctionLiteral* Parser::ParseLazy(Handle source, bool is_expression) { ZoneScope zone_scope(DONT_DELETE_ON_EXIT); HistogramTimerScope timer(&Counters::parse_lazy); - source->TryFlattenIfNotFlat(StringShape(*source)); - StringShape shape(*source); - Counters::total_parse_size.Increment(source->length(shape)); + source->TryFlattenIfNotFlat(); + Counters::total_parse_size.Increment(source->length()); SafeStringInputBuffer buffer(source.location()); // Initialize parser state. diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc index c3bf53146..0a1a169ed 100644 --- a/src/prettyprinter.cc +++ b/src/prettyprinter.cc @@ -517,10 +517,9 @@ void PrettyPrinter::PrintLiteral(Handle value, bool quote) { Object* object = *value; if (object->IsString()) { String* string = String::cast(object); - StringShape shape(string); if (quote) Print("\""); - for (int i = 0; i < string->length(shape); i++) { - Print("%c", string->Get(shape, i)); + for (int i = 0; i < string->length(); i++) { + Print("%c", string->Get(i)); } if (quote) Print("\""); } else if (object == Heap::null_value()) { diff --git a/src/regexp-macro-assembler-ia32.cc b/src/regexp-macro-assembler-ia32.cc index 031558651..e6e07168a 100644 --- a/src/regexp-macro-assembler-ia32.cc +++ b/src/regexp-macro-assembler-ia32.cc @@ -985,16 +985,14 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match( int* offsets_vector, int offsets_vector_length, int previous_index) { - StringShape shape(*subject); - // Character offsets into string. int start_offset = previous_index; - int end_offset = subject->length(shape); + int end_offset = subject->length(); - if (shape.IsCons()) { + if (StringShape(*subject).IsCons()) { subject = Handle(String::cast(ConsString::cast(*subject)->first())); - } else if (shape.IsSliced()) { + } else if (StringShape(*subject).IsSliced()) { SlicedString* slice = SlicedString::cast(*subject); start_offset += slice->start(); end_offset += slice->start(); @@ -1002,13 +1000,12 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match( } // String is now either Sequential or External - StringShape flatshape(*subject); - bool is_ascii = flatshape.IsAsciiRepresentation(); + bool is_ascii = StringShape(*subject).IsAsciiRepresentation(); int char_size_shift = is_ascii ? 0 : 1; RegExpMacroAssemblerIA32::Result res; - if (flatshape.IsExternal()) { + if (StringShape(*subject).IsExternal()) { const byte* address; if (is_ascii) { ExternalAsciiString* ext = ExternalAsciiString::cast(*subject); diff --git a/src/runtime.cc b/src/runtime.cc index 51dc24e98..0705e2c2a 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -1077,12 +1077,11 @@ static Object* CharCodeAt(String* subject, Object* index) { // Flatten the string. If someone wants to get a char at an index // in a cons string, it is likely that more indices will be // accessed. - subject->TryFlattenIfNotFlat(StringShape(subject)); - StringShape shape(subject); - if (i >= static_cast(subject->length(shape))) { + subject->TryFlattenIfNotFlat(); + if (i >= static_cast(subject->length())) { return Heap::nan_value(); } - return Smi::FromInt(subject->Get(shape, i)); + return Smi::FromInt(subject->Get(i)); } @@ -1114,7 +1113,6 @@ static const int kStringBuilderConcatHelperPositionBits = 19; template static inline void StringBuilderConcatHelper(String*, - StringShape, schar*, FixedArray*, int); @@ -1170,11 +1168,10 @@ class ReplacementStringBuilder { void AddString(Handle string) { - StringShape shape(*string); - int length = string->length(shape); + int length = string->length(); ASSERT(length > 0); AddElement(*string); - if (!shape.IsAsciiRepresentation()) { + if (!StringShape(*string).IsAsciiRepresentation()) { is_ascii_ = false; } IncrementCharacterCount(length); @@ -1193,7 +1190,6 @@ class ReplacementStringBuilder { SeqAsciiString* seq = SeqAsciiString::cast(*joined_string); char* char_buffer = seq->GetChars(); StringBuilderConcatHelper(*subject_, - StringShape(*subject_), char_buffer, *parts_, part_count_); @@ -1204,7 +1200,6 @@ class ReplacementStringBuilder { SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string); uc16* char_buffer = seq->GetChars(); StringBuilderConcatHelper(*subject_, - StringShape(*subject_), char_buffer, *parts_, part_count_); @@ -1432,16 +1427,15 @@ class CompiledReplacement { void CompiledReplacement::Compile(Handle replacement, int capture_count, int subject_length) { - StringShape shape(*replacement); - ASSERT(replacement->IsFlat(shape)); - if (shape.IsAsciiRepresentation()) { + ASSERT(replacement->IsFlat()); + if (StringShape(*replacement).IsAsciiRepresentation()) { AssertNoAllocation no_alloc; ParseReplacementPattern(&parts_, replacement->ToAsciiVector(), capture_count, subject_length); } else { - ASSERT(shape.IsTwoByteRepresentation()); + ASSERT(StringShape(*replacement).IsTwoByteRepresentation()); AssertNoAllocation no_alloc; ParseReplacementPattern(&parts_, @@ -1514,8 +1508,8 @@ static Object* StringReplaceRegExpWithString(String* subject, JSRegExp* regexp, String* replacement, JSArray* last_match_info) { - ASSERT(subject->IsFlat(StringShape(subject))); - ASSERT(replacement->IsFlat(StringShape(replacement))); + ASSERT(subject->IsFlat()); + ASSERT(replacement->IsFlat()); HandleScope handles; @@ -1619,9 +1613,8 @@ static Object* Runtime_StringReplaceRegExpWithString(Arguments args) { ASSERT(args.length() == 4); CONVERT_CHECKED(String, subject, args[0]); - StringShape subject_shape(subject); - if (!subject->IsFlat(subject_shape)) { - Object* flat_subject = subject->TryFlatten(subject_shape); + if (!subject->IsFlat()) { + Object* flat_subject = subject->TryFlatten(); if (flat_subject->IsFailure()) { return flat_subject; } @@ -1629,9 +1622,8 @@ static Object* Runtime_StringReplaceRegExpWithString(Arguments args) { } CONVERT_CHECKED(String, replacement, args[2]); - StringShape replacement_shape(replacement); - if (!replacement->IsFlat(replacement_shape)) { - Object* flat_replacement = replacement->TryFlatten(replacement_shape); + if (!replacement->IsFlat()) { + Object* flat_replacement = replacement->TryFlatten(); if (flat_replacement->IsFailure()) { return flat_replacement; } @@ -2002,27 +1994,24 @@ int Runtime::StringMatch(Handle sub, Handle pat, int start_index) { ASSERT(0 <= start_index); - StringShape sub_shape(*sub); - ASSERT(start_index <= sub->length(sub_shape)); + ASSERT(start_index <= sub->length()); int pattern_length = pat->length(); if (pattern_length == 0) return start_index; - int subject_length = sub->length(sub_shape); + int subject_length = sub->length(); if (start_index + pattern_length > subject_length) return -1; - if (!sub->IsFlat(sub_shape)) { + if (!sub->IsFlat()) { FlattenString(sub); - sub_shape = StringShape(*sub); } - StringShape pat_shape(*pat); // Searching for one specific character is common. For one // character patterns linear search is necessary, so any smart // algorithm is unnecessary overhead. if (pattern_length == 1) { AssertNoAllocation no_heap_allocation; // ensure vectors stay valid - if (sub_shape.IsAsciiRepresentation()) { - uc16 pchar = pat->Get(pat_shape, 0); + if (StringShape(*sub).IsAsciiRepresentation()) { + uc16 pchar = pat->Get(0); if (pchar > String::kMaxAsciiCharCode) { return -1; } @@ -2037,28 +2026,24 @@ int Runtime::StringMatch(Handle sub, return reinterpret_cast(pos) - ascii_vector.start() + start_index; } - return SingleCharIndexOf(sub->ToUC16Vector(), - pat->Get(pat_shape, 0), - start_index); + return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index); } - if (!pat->IsFlat(pat_shape)) { + if (!pat->IsFlat()) { FlattenString(pat); - pat_shape = StringShape(*pat); - sub_shape = StringShape(*sub); } AssertNoAllocation no_heap_allocation; // ensure vectors stay valid // dispatch on type of strings - if (pat_shape.IsAsciiRepresentation()) { + if (StringShape(*pat).IsAsciiRepresentation()) { Vector pat_vector = pat->ToAsciiVector(); - if (sub_shape.IsAsciiRepresentation()) { + if (StringShape(*sub).IsAsciiRepresentation()) { return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); } return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); } Vector pat_vector = pat->ToUC16Vector(); - if (sub_shape.IsAsciiRepresentation()) { + if (StringShape(*sub).IsAsciiRepresentation()) { return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); } return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); @@ -2090,17 +2075,14 @@ static Object* Runtime_StringLastIndexOf(Arguments args) { CONVERT_CHECKED(String, pat, args[1]); Object* index = args[2]; - sub->TryFlattenIfNotFlat(StringShape(sub)); - pat->TryFlattenIfNotFlat(StringShape(pat)); - - StringShape sub_shape(sub); - StringShape pat_shape(pat); + sub->TryFlattenIfNotFlat(); + pat->TryFlattenIfNotFlat(); uint32_t start_index; if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); - uint32_t pattern_length = pat->length(pat_shape); - uint32_t sub_length = sub->length(sub_shape); + uint32_t pattern_length = pat->length(); + uint32_t sub_length = sub->length(); if (start_index + pattern_length > sub_length) { start_index = sub_length - pattern_length; @@ -2109,7 +2091,7 @@ static Object* Runtime_StringLastIndexOf(Arguments args) { for (int i = start_index; i >= 0; i--) { bool found = true; for (uint32_t j = 0; j < pattern_length; j++) { - if (sub->Get(sub_shape, i + j) != pat->Get(pat_shape, j)) { + if (sub->Get(i + j) != pat->Get(j)) { found = false; break; } @@ -2129,10 +2111,8 @@ static Object* Runtime_StringLocaleCompare(Arguments args) { CONVERT_CHECKED(String, str2, args[1]); if (str1 == str2) return Smi::FromInt(0); // Equal. - StringShape shape1(str1); - StringShape shape2(str2); - int str1_length = str1->length(shape1); - int str2_length = str2->length(shape2); + int str1_length = str1->length(); + int str2_length = str2->length(); // Decide trivial cases without flattening. if (str1_length == 0) { @@ -2147,11 +2127,11 @@ static Object* Runtime_StringLocaleCompare(Arguments args) { // No need to flatten if we are going to find the answer on the first // character. At this point we know there is at least one character // in each string, due to the trivial case handling above. - int d = str1->Get(shape1, 0) - str2->Get(shape2, 0); + int d = str1->Get(0) - str2->Get(0); if (d != 0) return Smi::FromInt(d); - str1->TryFlattenIfNotFlat(shape1); // Shapes are no longer valid now! - str2->TryFlattenIfNotFlat(shape2); + str1->TryFlattenIfNotFlat(); + str2->TryFlattenIfNotFlat(); static StringInputBuffer buf1; static StringInputBuffer buf2; @@ -2286,11 +2266,10 @@ static Object* Runtime_NumberToPrecision(Arguments args) { // Returns a single character string where first character equals // string->Get(index). static Handle GetCharAt(Handle string, uint32_t index) { - StringShape shape(*string); - if (index < static_cast(string->length(shape))) { - string->TryFlattenIfNotFlat(shape); // Invalidates shape! + if (index < static_cast(string->length())) { + string->TryFlattenIfNotFlat(); return LookupSingleCharacterStringFromCode( - string->Get(StringShape(*string), index)); + string->Get(index)); } return Execution::CharAt(string, index); } @@ -2481,7 +2460,7 @@ Object* Runtime::SetObjectProperty(Handle object, result = SetElement(js_object, index, value); } else { Handle key_string = Handle::cast(key); - key_string->TryFlattenIfNotFlat(StringShape(*key_string)); + key_string->TryFlattenIfNotFlat(); result = SetProperty(js_object, key_string, value, attr); } if (result.is_null()) return Failure::Exception(); @@ -2775,7 +2754,7 @@ static Object* Runtime_StringToNumber(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); CONVERT_CHECKED(String, subject, args[0]); - subject->TryFlattenIfNotFlat(StringShape(subject)); + subject->TryFlattenIfNotFlat(); return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX)); } @@ -2805,11 +2784,10 @@ static Object* Runtime_StringFromCharCodeArray(Arguments args) { if (object->IsFailure()) return object; String* result = String::cast(object); - StringShape result_shape(result); for (int i = 0; i < length; i++) { Object* element = codes->GetElement(i); CONVERT_NUMBER_CHECKED(int, chr, Int32, element); - result->Set(result_shape, i, chr & 0xffff); + result->Set(i, chr & 0xffff); } return result; } @@ -2858,7 +2836,7 @@ static Object* Runtime_URIEscape(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(String, source, args[0]); - source->TryFlattenIfNotFlat(StringShape(source)); + source->TryFlattenIfNotFlat(); int escaped_length = 0; int length = source->length(); @@ -2888,7 +2866,6 @@ static Object* Runtime_URIEscape(Arguments args) { Object* o = Heap::AllocateRawAsciiString(escaped_length); if (o->IsFailure()) return o; String* destination = String::cast(o); - StringShape dshape(destination); int dest_position = 0; Access buffer(&runtime_string_input_buffer); @@ -2896,20 +2873,20 @@ static Object* Runtime_URIEscape(Arguments args) { while (buffer->has_more()) { uint16_t chr = buffer->GetNext(); if (chr >= 256) { - destination->Set(dshape, dest_position, '%'); - destination->Set(dshape, dest_position+1, 'u'); - destination->Set(dshape, dest_position+2, hex_chars[chr >> 12]); - destination->Set(dshape, dest_position+3, hex_chars[(chr >> 8) & 0xf]); - destination->Set(dshape, dest_position+4, hex_chars[(chr >> 4) & 0xf]); - destination->Set(dshape, dest_position+5, hex_chars[chr & 0xf]); + destination->Set(dest_position, '%'); + destination->Set(dest_position+1, 'u'); + destination->Set(dest_position+2, hex_chars[chr >> 12]); + destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]); + destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]); + destination->Set(dest_position+5, hex_chars[chr & 0xf]); dest_position += 6; } else if (IsNotEscaped(chr)) { - destination->Set(dshape, dest_position, chr); + destination->Set(dest_position, chr); dest_position++; } else { - destination->Set(dshape, dest_position, '%'); - destination->Set(dshape, dest_position+1, hex_chars[chr >> 4]); - destination->Set(dshape, dest_position+2, hex_chars[chr & 0xf]); + destination->Set(dest_position, '%'); + destination->Set(dest_position+1, hex_chars[chr >> 4]); + destination->Set(dest_position+2, hex_chars[chr & 0xf]); dest_position += 3; } } @@ -2938,26 +2915,25 @@ static inline int TwoDigitHex(uint16_t character1, uint16_t character2) { static inline int Unescape(String* source, - StringShape shape, int i, int length, int* step) { - uint16_t character = source->Get(shape, i); + uint16_t character = source->Get(i); int32_t hi = 0; int32_t lo = 0; if (character == '%' && i <= length - 6 && - source->Get(shape, i + 1) == 'u' && - (hi = TwoDigitHex(source->Get(shape, i + 2), - source->Get(shape, i + 3))) != -1 && - (lo = TwoDigitHex(source->Get(shape, i + 4), - source->Get(shape, i + 5))) != -1) { + source->Get(i + 1) == 'u' && + (hi = TwoDigitHex(source->Get(i + 2), + source->Get(i + 3))) != -1 && + (lo = TwoDigitHex(source->Get(i + 4), + source->Get(i + 5))) != -1) { *step = 6; return (hi << 8) + lo; } else if (character == '%' && i <= length - 3 && - (lo = TwoDigitHex(source->Get(shape, i + 1), - source->Get(shape, i + 2))) != -1) { + (lo = TwoDigitHex(source->Get(i + 1), + source->Get(i + 2))) != -1) { *step = 3; return lo; } else { @@ -2972,22 +2948,17 @@ static Object* Runtime_URIUnescape(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(String, source, args[0]); - source->TryFlattenIfNotFlat(StringShape(source)); - StringShape source_shape(source); + source->TryFlattenIfNotFlat(); bool ascii = true; - int length = source->length(source_shape); + int length = source->length(); int unescaped_length = 0; for (int i = 0; i < length; unescaped_length++) { int step; - if (Unescape(source, - source_shape, - i, - length, - &step) > - String::kMaxAsciiCharCode) + if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) { ascii = false; + } i += step; } @@ -3000,14 +2971,11 @@ static Object* Runtime_URIUnescape(Arguments args) { Heap::AllocateRawTwoByteString(unescaped_length); if (o->IsFailure()) return o; String* destination = String::cast(o); - StringShape destination_shape(destination); int dest_position = 0; for (int i = 0; i < length; dest_position++) { int step; - destination->Set(destination_shape, - dest_position, - Unescape(source, source_shape, i, length, &step)); + destination->Set(dest_position, Unescape(source, i, length, &step)); i += step; } return destination; @@ -3021,33 +2989,31 @@ static Object* Runtime_StringParseInt(Arguments args) { CONVERT_DOUBLE_CHECKED(n, args[1]); int radix = FastD2I(n); - s->TryFlattenIfNotFlat(StringShape(s)); - - StringShape shape(s); + s->TryFlattenIfNotFlat(); - int len = s->length(shape); + int len = s->length(); int i; // Skip leading white space. - for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(shape, i)); i++) ; + for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ; if (i == len) return Heap::nan_value(); // Compute the sign (default to +). int sign = 1; - if (s->Get(shape, i) == '-') { + if (s->Get(i) == '-') { sign = -1; i++; - } else if (s->Get(shape, i) == '+') { + } else if (s->Get(i) == '+') { i++; } // Compute the radix if 0. if (radix == 0) { radix = 10; - if (i < len && s->Get(shape, i) == '0') { + if (i < len && s->Get(i) == '0') { radix = 8; if (i + 1 < len) { - int c = s->Get(shape, i + 1); + int c = s->Get(i + 1); if (c == 'x' || c == 'X') { radix = 16; i += 2; @@ -3056,8 +3022,8 @@ static Object* Runtime_StringParseInt(Arguments args) { } } else if (radix == 16) { // Allow 0x or 0X prefix if radix is 16. - if (i + 1 < len && s->Get(shape, i) == '0') { - int c = s->Get(shape, i + 1); + if (i + 1 < len && s->Get(i) == '0') { + int c = s->Get(i + 1); if (c == 'x' || c == 'X') i += 2; } } @@ -3089,40 +3055,26 @@ static unibrow::Mapping to_lower_mapping; template -static Object* ConvertCase(Arguments args, - unibrow::Mapping* mapping) { - NoHandleAllocation ha; - - CONVERT_CHECKED(String, s, args[0]); - s->TryFlattenIfNotFlat(StringShape(s)); - StringShape shape(s); - - int raw_string_length = s->length(shape); - // Assume that the string is not empty; we need this assumption later - if (raw_string_length == 0) return s; - int length = raw_string_length; - - - // We try this twice, once with the assumption that the result is - // no longer than the input and, if that assumption breaks, again - // with the exact length. This is implemented using a goto back - // to this label if we discover that the assumption doesn't hold. - // I apologize sincerely for this and will give a vaffel-is to - // the first person who can implement it in a nicer way. - try_convert: - +static Object* ConvertCaseHelper(String* s, + int length, + int input_string_length, + unibrow::Mapping* mapping) { + // We try this twice, once with the assumption that the result is no longer + // than the input and, if that assumption breaks, again with the exact + // length. This may not be pretty, but it is nicer than what was here before + // and I hereby claim my vaffel-is. + // // Allocate the resulting string. // // NOTE: This assumes that the upper/lower case of an ascii // character is also ascii. This is currently the case, but it // might break in the future if we implement more context and locale // dependent upper/lower conversions. - Object* o = shape.IsAsciiRepresentation() + Object* o = StringShape(s).IsAsciiRepresentation() ? Heap::AllocateRawAsciiString(length) : Heap::AllocateRawTwoByteString(length); if (o->IsFailure()) return o; String* result = String::cast(o); - StringShape result_shape(result); bool has_changed_character = false; // Convert all characters to upper case, assuming that they will fit @@ -3130,24 +3082,23 @@ static Object* ConvertCase(Arguments args, Access buffer(&runtime_string_input_buffer); buffer->Reset(s); unibrow::uchar chars[Converter::kMaxWidth]; - int i = 0; // We can assume that the string is not empty uc32 current = buffer->GetNext(); - while (i < length) { + for (int i = 0; i < length; ) { bool has_next = buffer->has_more(); uc32 next = has_next ? buffer->GetNext() : 0; int char_length = mapping->get(current, next, chars); if (char_length == 0) { // The case conversion of this character is the character itself. - result->Set(result_shape, i, current); + result->Set(i, current); i++; } else if (char_length == 1) { // Common case: converting the letter resulted in one character. ASSERT(static_cast(chars[0]) != current); - result->Set(result_shape, i, chars[0]); + result->Set(i, chars[0]); has_changed_character = true; i++; - } else if (length == raw_string_length) { + } else if (length == input_string_length) { // We've assumed that the result would be as long as the // input but here is a character that converts to several // characters. No matter, we calculate the exact length @@ -3174,12 +3125,16 @@ static Object* ConvertCase(Arguments args, int char_length = mapping->get(current, 0, chars); if (char_length == 0) char_length = 1; current_length += char_length; + if (current_length > Smi::kMaxValue) { + Top::context()->mark_out_of_memory(); + return Failure::OutOfMemoryException(); + } } - length = current_length; - goto try_convert; + // Try again with the real length. + return Smi::FromInt(current_length); } else { for (int j = 0; j < char_length; j++) { - result->Set(result_shape, i, chars[j]); + result->Set(i, chars[j]); i++; } has_changed_character = true; @@ -3198,6 +3153,28 @@ static Object* ConvertCase(Arguments args, } +template +static Object* ConvertCase(Arguments args, + unibrow::Mapping* mapping) { + NoHandleAllocation ha; + + CONVERT_CHECKED(String, s, args[0]); + s->TryFlattenIfNotFlat(); + + int input_string_length = s->length(); + // Assume that the string is not empty; we need this assumption later + if (input_string_length == 0) return s; + int length = input_string_length; + + Object* answer = ConvertCaseHelper(s, length, length, mapping); + if (answer->IsSmi()) { + // Retry with correct length. + answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping); + } + return answer; // This may be a failure. +} + + static Object* Runtime_StringToLowerCase(Arguments args) { return ConvertCase(args, &to_lower_mapping); } @@ -3384,7 +3361,6 @@ static Object* Runtime_StringAdd(Arguments args) { template static inline void StringBuilderConcatHelper(String* special, - StringShape special_shape, sinkchar* sink, FixedArray* fixed_array, int array_length) { @@ -3396,16 +3372,14 @@ static inline void StringBuilderConcatHelper(String* special, int pos = StringBuilderSubstringPosition::decode(encoded_slice); int len = StringBuilderSubstringLength::decode(encoded_slice); String::WriteToFlat(special, - special_shape, sink + position, pos, pos + len); position += len; } else { String* string = String::cast(element); - StringShape shape(string); - int element_length = string->length(shape); - String::WriteToFlat(string, shape, sink + position, 0, element_length); + int element_length = string->length(); + String::WriteToFlat(string, sink + position, 0, element_length); position += element_length; } } @@ -3417,8 +3391,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(JSArray, array, args[0]); CONVERT_CHECKED(String, special, args[1]); - StringShape special_shape(special); - int special_length = special->length(special_shape); + int special_length = special->length(); Object* smi_array_length = array->length(); if (!smi_array_length->IsSmi()) { Top::context()->mark_out_of_memory(); @@ -3440,7 +3413,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { if (first->IsString()) return first; } - bool ascii = special_shape.IsAsciiRepresentation(); + bool ascii = StringShape(special).IsAsciiRepresentation(); int position = 0; for (int i = 0; i < array_length; i++) { Object* elt = fixed_array->get(i); @@ -3454,14 +3427,13 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { position += len; } else if (elt->IsString()) { String* element = String::cast(elt); - StringShape element_shape(element); - int element_length = element->length(element_shape); + int element_length = element->length(); if (!Smi::IsValid(element_length + position)) { Top::context()->mark_out_of_memory(); return Failure::OutOfMemoryException(); } position += element_length; - if (ascii && !element_shape.IsAsciiRepresentation()) { + if (ascii && !StringShape(element).IsAsciiRepresentation()) { ascii = false; } } else { @@ -3477,7 +3449,6 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { if (object->IsFailure()) return object; SeqAsciiString* answer = SeqAsciiString::cast(object); StringBuilderConcatHelper(special, - special_shape, answer->GetChars(), fixed_array, array_length); @@ -3487,7 +3458,6 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { if (object->IsFailure()) return object; SeqTwoByteString* answer = SeqTwoByteString::cast(object); StringBuilderConcatHelper(special, - special_shape, answer->GetChars(), fixed_array, array_length); @@ -3682,24 +3652,21 @@ static Object* Runtime_StringCompare(Arguments args) { CONVERT_CHECKED(String, x, args[0]); CONVERT_CHECKED(String, y, args[1]); - StringShape x_shape(x); - StringShape y_shape(y); - // A few fast case tests before we flatten. if (x == y) return Smi::FromInt(EQUAL); - if (y->length(y_shape) == 0) { - if (x->length(x_shape) == 0) return Smi::FromInt(EQUAL); + if (y->length() == 0) { + if (x->length() == 0) return Smi::FromInt(EQUAL); return Smi::FromInt(GREATER); - } else if (x->length(x_shape) == 0) { + } else if (x->length() == 0) { return Smi::FromInt(LESS); } - int d = x->Get(x_shape, 0) - y->Get(y_shape, 0); + int d = x->Get(0) - y->Get(0); if (d < 0) return Smi::FromInt(LESS); else if (d > 0) return Smi::FromInt(GREATER); - x->TryFlattenIfNotFlat(x_shape); // Shapes are no longer valid! - y->TryFlattenIfNotFlat(y_shape); + x->TryFlattenIfNotFlat(); + y->TryFlattenIfNotFlat(); static StringInputBuffer bufx; static StringInputBuffer bufy; diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index a146c4cdf..e35ac5fba 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -254,10 +254,9 @@ TEST(GarbageCollection) { static void VerifyStringAllocation(const char* string) { String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string))); - StringShape shape(s); - CHECK_EQ(static_cast(strlen(string)), s->length(shape)); - for (int index = 0; index < s->length(shape); index++) { - CHECK_EQ(static_cast(string[index]), s->Get(shape, index)); } + CHECK_EQ(static_cast(strlen(string)), s->length()); + for (int index = 0; index < s->length(); index++) { + CHECK_EQ(static_cast(string[index]), s->Get(index)); } } diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc index ed2e9ab21..50fe8625e 100644 --- a/test/cctest/test-regexp.cc +++ b/test/cctest/test-regexp.cc @@ -643,8 +643,7 @@ TEST(MacroAssembler) { Handle f1 = Factory::NewStringFromAscii(CStrVector("foobar")); - Handle f1_16 = RegExpImpl::StringToTwoByte(f1); - CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0)); + CHECK(IrregexpInterpreter::Match(array, f1, captures, 0)); CHECK_EQ(0, captures[0]); CHECK_EQ(3, captures[1]); CHECK_EQ(1, captures[2]); @@ -653,8 +652,7 @@ TEST(MacroAssembler) { Handle f2 = Factory::NewStringFromAscii(CStrVector("barfoo")); - Handle f2_16 = RegExpImpl::StringToTwoByte(f2); - CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0)); + CHECK(!IrregexpInterpreter::Match(array, f2, captures, 0)); CHECK_EQ(42, captures[0]); } diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc index 0c154bc7c..f8c1a4692 100644 --- a/test/cctest/test-strings.cc +++ b/test/cctest/test-strings.cc @@ -62,8 +62,7 @@ static void InitializeBuildingBlocks( building_blocks[i] = Factory::NewStringFromTwoByte(Vector(buf, len)); for (int j = 0; j < len; j++) { - StringShape shape(*building_blocks[i]); - CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j)); + CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } break; } @@ -75,8 +74,7 @@ static void InitializeBuildingBlocks( building_blocks[i] = Factory::NewStringFromAscii(Vector(buf, len)); for (int j = 0; j < len; j++) { - StringShape shape(*building_blocks[i]); - CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j)); + CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } break; } @@ -101,8 +99,7 @@ static void InitializeBuildingBlocks( Resource* resource = new Resource(Vector(buf, len)); building_blocks[i] = Factory::NewExternalStringFromTwoByte(resource); for (int j = 0; j < len; j++) { - StringShape shape(*building_blocks[i]); - CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j)); + CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } break; } @@ -114,8 +111,7 @@ static void InitializeBuildingBlocks( building_blocks[i] = Factory::NewStringFromAscii(Vector(buf, len)); for (int j = 0; j < len; j++) { - StringShape shape(*building_blocks[i]); - CHECK_EQ(buf[j], building_blocks[i]->Get(shape, j)); + CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } DeleteArray(buf); break; @@ -132,9 +128,7 @@ static Handle ConstructLeft( for (int i = 0; i < depth; i++) { answer = Factory::NewConsString( answer, - StringShape(*answer), - building_blocks[i % NUMBER_OF_BUILDING_BLOCKS], - StringShape(*building_blocks[i % NUMBER_OF_BUILDING_BLOCKS])); + building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]); } return answer; } @@ -147,9 +141,7 @@ static Handle ConstructRight( for (int i = depth - 1; i >= 0; i--) { answer = Factory::NewConsString( building_blocks[i % NUMBER_OF_BUILDING_BLOCKS], - StringShape(*building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]), - answer, - StringShape(*answer)); + answer); } return answer; } @@ -166,19 +158,13 @@ static Handle ConstructBalancedHelper( if (to - from == 2) { return Factory::NewConsString( building_blocks[from % NUMBER_OF_BUILDING_BLOCKS], - StringShape(*building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]), - building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS], - StringShape(*building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS])); + building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]); } Handle part1 = ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2)); Handle part2 = ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to); - return Factory::NewConsString( - part1, - StringShape(*part1), - part2, - StringShape(*part2)); + return Factory::NewConsString(part1, part2); } @@ -216,8 +202,8 @@ static void TraverseFirst(Handle s1, Handle s2, int chars) { CHECK_EQ(c, buffer2.GetNext()); i++; } - s1->Get(StringShape(*s1), s1->length() - 1); - s2->Get(StringShape(*s2), s2->length() - 1); + s1->Get(s1->length() - 1); + s2->Get(s2->length() - 1); } @@ -299,19 +285,13 @@ static Handle ConstructSliceTree( Handle rhs = building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]; if (gen() % 2 == 0) rhs = SliceOf(rhs); - return Factory::NewConsString(lhs, - StringShape(*lhs), - rhs, - StringShape(*rhs)); + return Factory::NewConsString(lhs, rhs); } Handle part1 = ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2)); Handle part2 = ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to); - Handle branch = Factory::NewConsString(part1, - StringShape(*part1), - part2, - StringShape(*part2)); + Handle branch = Factory::NewConsString(part1, part2); if (gen() % 2 == 0) return branch; return(SliceOf(branch)); @@ -351,15 +331,9 @@ TEST(DeepAscii) { Factory::NewStringFromAscii(Vector(foo, DEEP_ASCII_DEPTH)); Handle foo_string = Factory::NewStringFromAscii(CStrVector("foo")); for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) { - string = Factory::NewConsString(string, - StringShape(*string), - foo_string, - StringShape(*foo_string)); + string = Factory::NewConsString(string, foo_string); } - Handle flat_string = Factory::NewConsString(string, - StringShape(*string), - foo_string, - StringShape(*foo_string)); + Handle flat_string = Factory::NewConsString(string, foo_string); FlattenString(flat_string); for (int i = 0; i < 500; i++) { -- 2.34.1