From bdc903b086f71f09a799af4c02324f9a1016b019 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Thu, 28 Mar 2013 11:19:38 +0000 Subject: [PATCH] Improve SeqString::Truncate for latest allocated strings. R=hpayer@chromium.org BUG= Review URL: https://chromiumcodereview.appspot.com/12440061 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14088 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/json-parser.h | 48 ++++++++++++++++++-------------------------- src/json-stringifier.h | 16 ++++----------- src/objects.cc | 54 ++++++++++++++++++++++++++++++-------------------- src/objects.h | 4 ++-- src/runtime.cc | 6 +++--- src/spaces-inl.h | 17 ---------------- src/spaces.h | 5 ----- 7 files changed, 61 insertions(+), 89 deletions(-) diff --git a/src/json-parser.h b/src/json-parser.h index f50c352..ac34c59 100644 --- a/src/json-parser.h +++ b/src/json-parser.h @@ -504,10 +504,10 @@ Handle JsonParser::SlowScanJsonString( int count = end - start; int max_length = count + source_length_ - position_; int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count)); - Handle seq_str = + Handle seq_string = NewRawString(factory(), length, pretenure_); // Copy prefix into seq_str. - SinkChar* dest = seq_str->GetChars(); + SinkChar* dest = seq_string->GetChars(); String::WriteToFlat(*prefix, dest, start, end); while (c0_ != '"') { @@ -515,7 +515,7 @@ Handle JsonParser::SlowScanJsonString( if (c0_ < 0x20) return Handle::null(); if (count >= length) { // We need to create a longer sequential string for the result. - return SlowScanJsonString(seq_str, 0, count); + return SlowScanJsonString(seq_string, 0, count); } if (c0_ != '\\') { // If the sink can contain UC16 characters, or source_ contains only @@ -525,11 +525,11 @@ Handle JsonParser::SlowScanJsonString( if (sizeof(SinkChar) == kUC16Size || seq_ascii || c0_ <= String::kMaxOneByteCharCode) { - SeqStringSet(seq_str, count++, c0_); + SeqStringSet(seq_string, count++, c0_); Advance(); } else { // StringType is SeqOneByteString and we just read a non-ASCII char. - return SlowScanJsonString(seq_str, 0, count); + return SlowScanJsonString(seq_string, 0, count); } } else { Advance(); // Advance past the \. @@ -537,22 +537,22 @@ Handle JsonParser::SlowScanJsonString( case '"': case '\\': case '/': - SeqStringSet(seq_str, count++, c0_); + SeqStringSet(seq_string, count++, c0_); break; case 'b': - SeqStringSet(seq_str, count++, '\x08'); + SeqStringSet(seq_string, count++, '\x08'); break; case 'f': - SeqStringSet(seq_str, count++, '\x0c'); + SeqStringSet(seq_string, count++, '\x0c'); break; case 'n': - SeqStringSet(seq_str, count++, '\x0a'); + SeqStringSet(seq_string, count++, '\x0a'); break; case 'r': - SeqStringSet(seq_str, count++, '\x0d'); + SeqStringSet(seq_string, count++, '\x0d'); break; case 't': - SeqStringSet(seq_str, count++, '\x09'); + SeqStringSet(seq_string, count++, '\x09'); break; case 'u': { uc32 value = 0; @@ -566,13 +566,13 @@ Handle JsonParser::SlowScanJsonString( } if (sizeof(SinkChar) == kUC16Size || value <= String::kMaxOneByteCharCode) { - SeqStringSet(seq_str, count++, value); + SeqStringSet(seq_string, count++, value); break; } else { // StringType is SeqOneByteString and we just read a non-ASCII char. position_ -= 6; // Rewind position_ to \ in \uxxxx. Advance(); - return SlowScanJsonString(seq_str, + return SlowScanJsonString(seq_string, 0, count); } @@ -583,23 +583,13 @@ Handle JsonParser::SlowScanJsonString( Advance(); } } - // Shrink seq_string length to count. - if (isolate()->heap()->InNewSpace(*seq_str)) { - isolate()->heap()->new_space()-> - template ShrinkStringAtAllocationBoundary( - *seq_str, count); - } else { - int string_size = StringType::SizeFor(count); - int allocated_string_size = StringType::SizeFor(length); - int delta = allocated_string_size - string_size; - Address start_filler_object = seq_str->address() + string_size; - seq_str->set_length(count); - isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta); - } + ASSERT_EQ('"', c0_); // Advance past the last '"'. AdvanceSkipWhitespace(); - return seq_str; + + // Shrink seq_string length to count and return. + return SeqString::Truncate(seq_string, count); } @@ -626,8 +616,8 @@ Handle JsonParser::ScanJsonString() { int beg_pos = position_; position_ = position; return SlowScanJsonString(source_, - beg_pos, - position_); + beg_pos, + position_); } if (c0 < 0x20) return Handle::null(); if (static_cast(c0) > diff --git a/src/json-stringifier.h b/src/json-stringifier.h index 60614f4..bcdd64c 100644 --- a/src/json-stringifier.h +++ b/src/json-stringifier.h @@ -55,7 +55,7 @@ class BasicJsonStringifier BASE_EMBEDDED { void ChangeEncoding(); - void ShrinkCurrentPart(); + INLINE(void ShrinkCurrentPart()); template INLINE(void Append_(Char c)); @@ -324,15 +324,7 @@ MaybeObject* BasicJsonStringifier::StringifyString_(Isolate* isolate, dest->GetChars() + 1, vector.length()); dest->Set(final_size++, '\"'); - if (isolate->heap()->InNewSpace(*result)) { - // In new space, simply lower the allocation top to fit the actual size. - isolate->heap()->new_space()->ShrinkStringAtAllocationBoundary( - *result, final_size); - return *result; - } else { - // Not in new space, need to fill the wasted space with filler objects. - return SeqString::cast(*result)->Truncate(final_size); - } + return *SeqString::Truncate(Handle::cast(result), final_size); } @@ -699,8 +691,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( void BasicJsonStringifier::ShrinkCurrentPart() { ASSERT(current_index_ < part_length_); - current_part_ = Handle( - SeqString::cast(*current_part_)->Truncate(current_index_), isolate_); + current_part_ = SeqString::Truncate(Handle::cast(current_part_), + current_index_); } diff --git a/src/objects.cc b/src/objects.cc index 9d6c055..acdc6bf 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -7649,33 +7649,45 @@ bool String::SlowAsArrayIndex(uint32_t* index) { } -String* SeqString::Truncate(int new_length) { - Heap* heap = GetHeap(); - if (new_length <= 0) return heap->empty_string(); +Handle SeqString::Truncate(Handle string, int new_length) { + int new_size, old_size; + int old_length = string->length(); + if (old_length <= new_length) return string; + + if (string->IsSeqOneByteString()) { + old_size = SeqOneByteString::SizeFor(old_length); + new_size = SeqOneByteString::SizeFor(new_length); + } else { + ASSERT(string->IsSeqTwoByteString()); + old_size = SeqTwoByteString::SizeFor(old_length); + new_size = SeqTwoByteString::SizeFor(new_length); + } + + int delta = old_size - new_size; + string->set_length(new_length); - int string_size, allocated_string_size; - int old_length = length(); - if (old_length <= new_length) return this; + Address start_of_string = string->address(); + ASSERT_OBJECT_ALIGNED(start_of_string); + ASSERT_OBJECT_ALIGNED(start_of_string + new_size); - if (IsSeqOneByteString()) { - allocated_string_size = SeqOneByteString::SizeFor(old_length); - string_size = SeqOneByteString::SizeFor(new_length); + Heap* heap = string->GetHeap(); + NewSpace* newspace = heap->new_space(); + if (newspace->Contains(start_of_string) && + newspace->top() == start_of_string + old_size) { + // Last allocated object in new space. Simply lower allocation top. + *(newspace->allocation_top_address()) = start_of_string + new_size; } else { - allocated_string_size = SeqTwoByteString::SizeFor(old_length); - string_size = SeqTwoByteString::SizeFor(new_length); + // Sizes are pointer size aligned, so that we can use filler objects + // that are a multiple of pointer size. + heap->CreateFillerObjectAt(start_of_string + new_size, delta); + } + if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) { + MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta); } - int delta = allocated_string_size - string_size; - set_length(new_length); - // String sizes are pointer size aligned, so that we can use filler objects - // that are a multiple of pointer size. - Address end_of_string = address() + string_size; - heap->CreateFillerObjectAt(end_of_string, delta); - if (Marking::IsBlack(Marking::MarkBitFrom(this))) { - MemoryChunk::IncrementLiveBytesFromMutator(address(), -delta); - } - return this; + if (new_length == 0) return heap->isolate()->factory()->empty_string(); + return string; } diff --git a/src/objects.h b/src/objects.h index b19db9e..e81966c 100644 --- a/src/objects.h +++ b/src/objects.h @@ -7762,8 +7762,8 @@ class SeqString: public String { // Truncate the string in-place if possible and return the result. // In case of new_length == 0, the empty string is returned without // truncating the original string. - MUST_USE_RESULT String* Truncate(int new_length); - + MUST_USE_RESULT static Handle Truncate(Handle string, + int new_length); private: DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString); }; diff --git a/src/runtime.cc b/src/runtime.cc index 1ea9274..71c7c0b 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -5155,10 +5155,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) { RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) { - NoHandleAllocation ha(isolate); - CONVERT_ARG_CHECKED(SeqString, string, 0); + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0); CONVERT_SMI_ARG_CHECKED(new_length, 1); - return string->Truncate(new_length); + return *SeqString::Truncate(string, new_length); } diff --git a/src/spaces-inl.h b/src/spaces-inl.h index aeac570..77117b8 100644 --- a/src/spaces-inl.h +++ b/src/spaces-inl.h @@ -351,23 +351,6 @@ intptr_t LargeObjectSpace::Available() { } -template -void NewSpace::ShrinkStringAtAllocationBoundary(String* string, int length) { - ASSERT(length <= string->length()); - ASSERT(string->IsSeqString()); - ASSERT(string->address() + StringType::SizeFor(string->length()) == - allocation_info_.top); - Address old_top = allocation_info_.top; - allocation_info_.top = - string->address() + StringType::SizeFor(length); - string->set_length(length); - if (Marking::IsBlack(Marking::MarkBitFrom(string))) { - int delta = static_cast(old_top - allocation_info_.top); - MemoryChunk::IncrementLiveBytesFromMutator(string->address(), -delta); - } -} - - bool FreeListNode::IsFreeListNode(HeapObject* object) { Map* map = object->map(); Heap* heap = object->GetHeap(); diff --git a/src/spaces.h b/src/spaces.h index 39c19a4..65eefd0 100644 --- a/src/spaces.h +++ b/src/spaces.h @@ -2419,11 +2419,6 @@ class NewSpace : public Space { virtual bool ReserveSpace(int bytes); - // Resizes a sequential string which must be the most recent thing that was - // allocated in new space. - template - inline void ShrinkStringAtAllocationBoundary(String* string, int len); - #ifdef VERIFY_HEAP // Verify the active semispace. virtual void Verify(); -- 2.7.4