Commit bdc903b0 authored by yangguo@chromium.org's avatar yangguo@chromium.org

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
parent 9155d202
......@@ -504,10 +504,10 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
int count = end - start;
int max_length = count + source_length_ - position_;
int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
Handle<StringType> seq_str =
Handle<StringType> seq_string =
NewRawString<StringType>(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<String> JsonParser<seq_ascii>::SlowScanJsonString(
if (c0_ < 0x20) return Handle<String>::null();
if (count >= length) {
// We need to create a longer sequential string for the result.
return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count);
return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
}
if (c0_ != '\\') {
// If the sink can contain UC16 characters, or source_ contains only
......@@ -525,11 +525,11 @@ Handle<String> JsonParser<seq_ascii>::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<SeqTwoByteString, uc16>(seq_str, 0, count);
return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
}
} else {
Advance(); // Advance past the \.
......@@ -537,22 +537,22 @@ Handle<String> JsonParser<seq_ascii>::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<String> JsonParser<seq_ascii>::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<SeqTwoByteString, uc16>(seq_str,
return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
0,
count);
}
......@@ -583,23 +583,13 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
Advance();
}
}
// Shrink seq_string length to count.
if (isolate()->heap()->InNewSpace(*seq_str)) {
isolate()->heap()->new_space()->
template ShrinkStringAtAllocationBoundary<StringType>(
*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<String> JsonParser<seq_ascii>::ScanJsonString() {
int beg_pos = position_;
position_ = position;
return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
beg_pos,
position_);
beg_pos,
position_);
}
if (c0 < 0x20) return Handle<String>::null();
if (static_cast<uint32_t>(c0) >
......
......@@ -55,7 +55,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
void ChangeEncoding();
void ShrinkCurrentPart();
INLINE(void ShrinkCurrentPart());
template <bool is_ascii, typename Char>
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<ResultType>(
*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<SeqString>::cast(result), final_size);
}
......@@ -699,8 +691,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
void BasicJsonStringifier::ShrinkCurrentPart() {
ASSERT(current_index_ < part_length_);
current_part_ = Handle<String>(
SeqString::cast(*current_part_)->Truncate(current_index_), isolate_);
current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_),
current_index_);
}
......
......@@ -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<String> SeqString::Truncate(Handle<SeqString> 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;
}
......
......@@ -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<String> Truncate(Handle<SeqString> string,
int new_length);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
};
......
......@@ -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);
}
......
......@@ -351,23 +351,6 @@ intptr_t LargeObjectSpace::Available() {
}
template <typename StringType>
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<int>(old_top - allocation_info_.top);
MemoryChunk::IncrementLiveBytesFromMutator(string->address(), -delta);
}
}
bool FreeListNode::IsFreeListNode(HeapObject* object) {
Map* map = object->map();
Heap* heap = object->GetHeap();
......
......@@ -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 <typename StringType>
inline void ShrinkStringAtAllocationBoundary(String* string, int len);
#ifdef VERIFY_HEAP
// Verify the active semispace.
virtual void Verify();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment