Append short strings by copying in string builder

This CL changes IncrementalStringBuilder to write short strings
directly to {current_part_} instead of shortening {current_part},
allocating a new part and concatenate everything using ConsString.

This optimization requires the IncrementalStringBuilder to either
use two byte encoding, or the incoming string is flat with one byte
representation.

This CL improves stack trace serialization micro benchmarks up to 10%.

Bug: v8:8742
Change-Id: I5cc8339be8035c42438381883544d108591fb945
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1647696
Commit-Queue: Simon Zünd <szuend@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62075}
This commit is contained in:
Simon Zünd 2019-06-11 09:27:51 +02:00 committed by Commit Bot
parent 563290194f
commit ef2ba53449
2 changed files with 37 additions and 0 deletions

View File

@ -284,6 +284,9 @@ class IncrementalStringBuilder {
Handle<SeqString>::cast(current_part()), current_index_));
}
void AppendStringByCopy(Handle<String> string);
bool CanAppendByCopy(Handle<String> string);
static const int kInitialPartLength = 32;
static const int kMaxPartLength = 16 * 1024;
static const int kPartLengthGrowthFactor = 2;

View File

@ -284,7 +284,41 @@ MaybeHandle<String> IncrementalStringBuilder::Finish() {
return accumulator();
}
// Short strings can be copied directly to {current_part_}.
// Requires the IncrementalStringBuilder to either have two byte encoding or
// the incoming string to have one byte representation "underneath" (The
// one byte check requires the string to be flat).
bool IncrementalStringBuilder::CanAppendByCopy(Handle<String> string) {
constexpr int kMaxStringLengthForCopy = 16;
const bool representation_ok =
encoding_ == String::TWO_BYTE_ENCODING ||
(string->IsFlat() && String::IsOneByteRepresentationUnderneath(*string));
return representation_ok && string->length() <= kMaxStringLengthForCopy &&
CurrentPartCanFit(string->length());
}
void IncrementalStringBuilder::AppendStringByCopy(Handle<String> string) {
DCHECK(CanAppendByCopy(string));
Handle<SeqOneByteString> part =
Handle<SeqOneByteString>::cast(current_part());
{
DisallowHeapAllocation no_gc;
String::WriteToFlat(*string, part->GetChars(no_gc) + current_index_, 0,
string->length());
}
current_index_ += string->length();
DCHECK(current_index_ <= part_length_);
if (current_index_ == part_length_) Extend();
}
void IncrementalStringBuilder::AppendString(Handle<String> string) {
if (CanAppendByCopy(string)) {
AppendStringByCopy(string);
return;
}
ShrinkCurrentPart();
part_length_ = kInitialPartLength; // Allocate conservatively.
Extend(); // Attach current part and allocate new part.