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
This commit is contained in:
parent
9155d20282
commit
bdc903b086
@ -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;
|
||||
|
||||
int string_size, allocated_string_size;
|
||||
int old_length = length();
|
||||
if (old_length <= new_length) return this;
|
||||
|
||||
if (IsSeqOneByteString()) {
|
||||
allocated_string_size = SeqOneByteString::SizeFor(old_length);
|
||||
string_size = SeqOneByteString::SizeFor(new_length);
|
||||
if (string->IsSeqOneByteString()) {
|
||||
old_size = SeqOneByteString::SizeFor(old_length);
|
||||
new_size = SeqOneByteString::SizeFor(new_length);
|
||||
} else {
|
||||
allocated_string_size = SeqTwoByteString::SizeFor(old_length);
|
||||
string_size = SeqTwoByteString::SizeFor(new_length);
|
||||
ASSERT(string->IsSeqTwoByteString());
|
||||
old_size = SeqTwoByteString::SizeFor(old_length);
|
||||
new_size = SeqTwoByteString::SizeFor(new_length);
|
||||
}
|
||||
|
||||
int delta = allocated_string_size - string_size;
|
||||
set_length(new_length);
|
||||
int delta = old_size - new_size;
|
||||
string->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);
|
||||
Address start_of_string = string->address();
|
||||
ASSERT_OBJECT_ALIGNED(start_of_string);
|
||||
ASSERT_OBJECT_ALIGNED(start_of_string + new_size);
|
||||
|
||||
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 {
|
||||
// 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);
|
||||
}
|
||||
return this;
|
||||
if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) {
|
||||
MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user