Commit f2e987d6 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[string] Make WriteToFlat take 'length' instead of 'end'

CopyChars takes a count parameter, not an end parameter, so we can save
some subtractions by passing in the count to WriteToFlat. Most of the
time the start,end arguments into WriteToFlat are 0,length anyway, so
this doesn't change a lot of places.

Change-Id: I9587c7afce529218a16b728c0477b87569df8e21
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3157947Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76813}
parent 9a4f353a
...@@ -5626,12 +5626,13 @@ static inline int WriteHelper(i::Isolate* isolate, const String* string, ...@@ -5626,12 +5626,13 @@ static inline int WriteHelper(i::Isolate* isolate, const String* string,
int end = start + length; int end = start + length;
if ((length == -1) || (length > str->length() - start)) end = str->length(); if ((length == -1) || (length > str->length() - start)) end = str->length();
if (end < 0) return 0; if (end < 0) return 0;
if (start < end) i::String::WriteToFlat(*str, buffer, start, end); int write_length = end - start;
if (start < end) i::String::WriteToFlat(*str, buffer, start, write_length);
if (!(options & String::NO_NULL_TERMINATION) && if (!(options & String::NO_NULL_TERMINATION) &&
(length == -1 || end - start < length)) { (length == -1 || write_length < length)) {
buffer[end - start] = '\0'; buffer[write_length] = '\0';
} }
return end - start; return write_length;
} }
int String::WriteOneByte(Isolate* isolate, uint8_t* buffer, int start, int String::WriteOneByte(Isolate* isolate, uint8_t* buffer, int start,
......
...@@ -8015,28 +8015,28 @@ void CodeStubAssembler::TryToName(TNode<Object> key, Label* if_keyisindex, ...@@ -8015,28 +8015,28 @@ void CodeStubAssembler::TryToName(TNode<Object> key, Label* if_keyisindex,
void CodeStubAssembler::StringWriteToFlatOneByte(TNode<String> source, void CodeStubAssembler::StringWriteToFlatOneByte(TNode<String> source,
TNode<RawPtrT> sink, TNode<RawPtrT> sink,
TNode<Int32T> from, TNode<Int32T> start,
TNode<Int32T> to) { TNode<Int32T> length) {
TNode<ExternalReference> function = TNode<ExternalReference> function =
ExternalConstant(ExternalReference::string_write_to_flat_one_byte()); ExternalConstant(ExternalReference::string_write_to_flat_one_byte());
CallCFunction(function, base::nullopt, CallCFunction(function, base::nullopt,
std::make_pair(MachineType::AnyTagged(), source), std::make_pair(MachineType::AnyTagged(), source),
std::make_pair(MachineType::Pointer(), sink), std::make_pair(MachineType::Pointer(), sink),
std::make_pair(MachineType::Int32(), from), std::make_pair(MachineType::Int32(), start),
std::make_pair(MachineType::Int32(), to)); std::make_pair(MachineType::Int32(), length));
} }
void CodeStubAssembler::StringWriteToFlatTwoByte(TNode<String> source, void CodeStubAssembler::StringWriteToFlatTwoByte(TNode<String> source,
TNode<RawPtrT> sink, TNode<RawPtrT> sink,
TNode<Int32T> from, TNode<Int32T> start,
TNode<Int32T> to) { TNode<Int32T> length) {
TNode<ExternalReference> function = TNode<ExternalReference> function =
ExternalConstant(ExternalReference::string_write_to_flat_two_byte()); ExternalConstant(ExternalReference::string_write_to_flat_two_byte());
CallCFunction(function, base::nullopt, CallCFunction(function, base::nullopt,
std::make_pair(MachineType::AnyTagged(), source), std::make_pair(MachineType::AnyTagged(), source),
std::make_pair(MachineType::Pointer(), sink), std::make_pair(MachineType::Pointer(), sink),
std::make_pair(MachineType::Int32(), from), std::make_pair(MachineType::Int32(), start),
std::make_pair(MachineType::Int32(), to)); std::make_pair(MachineType::Int32(), length));
} }
TNode<RawPtr<Uint8T>> CodeStubAssembler::ExternalOneByteStringGetChars( TNode<RawPtr<Uint8T>> CodeStubAssembler::ExternalOneByteStringGetChars(
......
...@@ -2881,9 +2881,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -2881,9 +2881,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Call non-allocating runtime String::WriteToFlat using fast C-calls. // Call non-allocating runtime String::WriteToFlat using fast C-calls.
void StringWriteToFlatOneByte(TNode<String> source, TNode<RawPtrT> sink, void StringWriteToFlatOneByte(TNode<String> source, TNode<RawPtrT> sink,
TNode<Int32T> from, TNode<Int32T> to); TNode<Int32T> start, TNode<Int32T> length);
void StringWriteToFlatTwoByte(TNode<String> source, TNode<RawPtrT> sink, void StringWriteToFlatTwoByte(TNode<String> source, TNode<RawPtrT> sink,
TNode<Int32T> from, TNode<Int32T> to); TNode<Int32T> start, TNode<Int32T> length);
// Calls External{One,Two}ByteString::GetChars with a fast C-call. // Calls External{One,Two}ByteString::GetChars with a fast C-call.
TNode<RawPtr<Uint8T>> ExternalOneByteStringGetChars( TNode<RawPtr<Uint8T>> ExternalOneByteStringGetChars(
......
...@@ -882,16 +882,16 @@ ExternalReference ExternalReference::search_string_raw_two_two() { ...@@ -882,16 +882,16 @@ ExternalReference ExternalReference::search_string_raw_two_two() {
namespace { namespace {
void StringWriteToFlatOneByte(Address source, uint8_t* sink, int32_t from, void StringWriteToFlatOneByte(Address source, uint8_t* sink, int32_t start,
int32_t to) { int32_t length) {
return String::WriteToFlat<uint8_t>(String::cast(Object(source)), sink, from, return String::WriteToFlat<uint8_t>(String::cast(Object(source)), sink, start,
to); length);
} }
void StringWriteToFlatTwoByte(Address source, uint16_t* sink, int32_t from, void StringWriteToFlatTwoByte(Address source, uint16_t* sink, int32_t start,
int32_t to) { int32_t length) {
return String::WriteToFlat<uint16_t>(String::cast(Object(source)), sink, from, return String::WriteToFlat<uint16_t>(String::cast(Object(source)), sink,
to); start, length);
} }
const uint8_t* ExternalOneByteStringGetChars(Address string) { const uint8_t* ExternalOneByteStringGetChars(Address string) {
......
...@@ -1021,14 +1021,14 @@ Handle<String> Factory::NewProperSubString(Handle<String> str, int begin, ...@@ -1021,14 +1021,14 @@ Handle<String> Factory::NewProperSubString(Handle<String> str, int begin,
NewRawOneByteString(length).ToHandleChecked(); NewRawOneByteString(length).ToHandleChecked();
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
uint8_t* dest = result->GetChars(no_gc); uint8_t* dest = result->GetChars(no_gc);
String::WriteToFlat(*str, dest, begin, end); String::WriteToFlat(*str, dest, begin, length);
return result; return result;
} else { } else {
Handle<SeqTwoByteString> result = Handle<SeqTwoByteString> result =
NewRawTwoByteString(length).ToHandleChecked(); NewRawTwoByteString(length).ToHandleChecked();
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
base::uc16* dest = result->GetChars(no_gc); base::uc16* dest = result->GetChars(no_gc);
String::WriteToFlat(*str, dest, begin, end); String::WriteToFlat(*str, dest, begin, length);
return result; return result;
} }
} }
......
...@@ -645,88 +645,91 @@ std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls, ...@@ -645,88 +645,91 @@ std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
// static // static
template <typename sinkchar> template <typename sinkchar>
void String::WriteToFlat(String source, sinkchar* sink, int from, int to) { void String::WriteToFlat(String source, sinkchar* sink, int start, int length) {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source)); DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source));
return WriteToFlat(source, sink, from, to, GetPtrComprCageBase(source), return WriteToFlat(source, sink, start, length, GetPtrComprCageBase(source),
SharedStringAccessGuardIfNeeded::NotNeeded()); SharedStringAccessGuardIfNeeded::NotNeeded());
} }
// static // static
template <typename sinkchar> template <typename sinkchar>
void String::WriteToFlat(String source, sinkchar* sink, int from, int to, void String::WriteToFlat(String source, sinkchar* sink, int start, int length,
PtrComprCageBase cage_base, PtrComprCageBase cage_base,
const SharedStringAccessGuardIfNeeded& access_guard) { const SharedStringAccessGuardIfNeeded& access_guard) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
if (from == to) return; if (length == 0) return;
while (true) { while (true) {
DCHECK_LT(from, to); DCHECK_LT(0, length);
DCHECK_LE(0, from); DCHECK_LE(0, start);
DCHECK_LE(to, source.length()); DCHECK_LE(length, source.length());
switch (StringShape(source, cage_base).full_representation_tag()) { switch (StringShape(source, cage_base).full_representation_tag()) {
case kOneByteStringTag | kExternalStringTag: case kOneByteStringTag | kExternalStringTag:
CopyChars(sink, ExternalOneByteString::cast(source).GetChars() + from, CopyChars(sink, ExternalOneByteString::cast(source).GetChars() + start,
to - from); length);
return; return;
case kTwoByteStringTag | kExternalStringTag: case kTwoByteStringTag | kExternalStringTag:
CopyChars(sink, ExternalTwoByteString::cast(source).GetChars() + from, CopyChars(sink, ExternalTwoByteString::cast(source).GetChars() + start,
to - from); length);
return; return;
case kOneByteStringTag | kSeqStringTag: case kOneByteStringTag | kSeqStringTag:
CopyChars( CopyChars(sink,
sink, SeqOneByteString::cast(source).GetChars(no_gc, access_guard) +
SeqOneByteString::cast(source).GetChars(no_gc, access_guard) + from, start,
to - from); length);
return; return;
case kTwoByteStringTag | kSeqStringTag: case kTwoByteStringTag | kSeqStringTag:
CopyChars( CopyChars(sink,
sink, SeqTwoByteString::cast(source).GetChars(no_gc, access_guard) +
SeqTwoByteString::cast(source).GetChars(no_gc, access_guard) + from, start,
to - from); length);
return; return;
case kOneByteStringTag | kConsStringTag: case kOneByteStringTag | kConsStringTag:
case kTwoByteStringTag | kConsStringTag: { case kTwoByteStringTag | kConsStringTag: {
ConsString cons_string = ConsString::cast(source); ConsString cons_string = ConsString::cast(source);
String first = cons_string.first(cage_base); String first = cons_string.first(cage_base);
int boundary = first.length(); int boundary = first.length();
if (to - boundary >= boundary - from) { int first_length = boundary - start;
int second_length = start + length - boundary;
if (second_length >= first_length) {
// Right hand side is longer. Recurse over left. // Right hand side is longer. Recurse over left.
if (from < boundary) { if (first_length > 0) {
WriteToFlat(first, sink, from, boundary, cage_base, access_guard); WriteToFlat(first, sink, start, first_length, cage_base,
if (from == 0 && cons_string.second(cage_base) == first) { access_guard);
if (start == 0 && cons_string.second(cage_base) == first) {
CopyChars(sink + boundary, sink, boundary); CopyChars(sink + boundary, sink, boundary);
return; return;
} }
sink += boundary - from; sink += boundary - start;
from = 0; start = 0;
length -= first_length;
} else { } else {
from -= boundary; start -= boundary;
} }
to -= boundary;
source = cons_string.second(cage_base); source = cons_string.second(cage_base);
} else { } else {
// Left hand side is longer. Recurse over right. // Left hand side is longer. Recurse over right.
if (to > boundary) { if (second_length > 0) {
String second = cons_string.second(cage_base); String second = cons_string.second(cage_base);
// When repeatedly appending to a string, we get a cons string that // When repeatedly appending to a string, we get a cons string that
// is unbalanced to the left, a list, essentially. We inline the // is unbalanced to the left, a list, essentially. We inline the
// common case of sequential one-byte right child. // common case of sequential one-byte right child.
if (to - boundary == 1) { if (second_length == 1) {
sink[boundary - from] = sink[boundary - start] =
static_cast<sinkchar>(second.Get(0, cage_base, access_guard)); static_cast<sinkchar>(second.Get(0, cage_base, access_guard));
} else if (second.IsSeqOneByteString(cage_base)) { } else if (second.IsSeqOneByteString(cage_base)) {
CopyChars( CopyChars(
sink + boundary - from, sink + boundary - start,
SeqOneByteString::cast(second).GetChars(no_gc, access_guard), SeqOneByteString::cast(second).GetChars(no_gc, access_guard),
to - boundary); second_length);
} else { } else {
WriteToFlat(second, sink + boundary - from, 0, to - boundary, WriteToFlat(second, sink + boundary - start, 0, second_length,
cage_base, access_guard); cage_base, access_guard);
} }
to = boundary; length -= second_length;
} }
source = first; source = first;
} }
if (from == to) return; if (length == 0) return;
continue; continue;
} }
case kOneByteStringTag | kSlicedStringTag: case kOneByteStringTag | kSlicedStringTag:
...@@ -734,8 +737,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to, ...@@ -734,8 +737,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to,
SlicedString slice = SlicedString::cast(source); SlicedString slice = SlicedString::cast(source);
unsigned offset = slice.offset(); unsigned offset = slice.offset();
source = slice.parent(cage_base); source = slice.parent(cage_base);
from += offset; start += offset;
to += offset;
continue; continue;
} }
case kOneByteStringTag | kThinStringTag: case kOneByteStringTag | kThinStringTag:
......
...@@ -595,7 +595,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalAtomRegExpWithString( ...@@ -595,7 +595,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalAtomRegExpWithString(
// Copy non-matched subject content. // Copy non-matched subject content.
if (subject_pos < index) { if (subject_pos < index) {
String::WriteToFlat(*subject, result->GetChars(no_gc) + result_pos, String::WriteToFlat(*subject, result->GetChars(no_gc) + result_pos,
subject_pos, index); subject_pos, index - subject_pos);
result_pos += index - subject_pos; result_pos += index - subject_pos;
} }
...@@ -611,7 +611,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalAtomRegExpWithString( ...@@ -611,7 +611,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalAtomRegExpWithString(
// Add remaining subject content at the end. // Add remaining subject content at the end.
if (subject_pos < subject_len) { if (subject_pos < subject_len) {
String::WriteToFlat(*subject, result->GetChars(no_gc) + result_pos, String::WriteToFlat(*subject, result->GetChars(no_gc) + result_pos,
subject_pos, subject_len); subject_pos, subject_len - subject_pos);
} }
int32_t match_indices[] = {indices->back(), indices->back() + pattern_len}; int32_t match_indices[] = {indices->back(), indices->back() + pattern_len};
...@@ -753,7 +753,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalRegExpWithEmptyString( ...@@ -753,7 +753,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalRegExpWithEmptyString(
if (prev < start) { if (prev < start) {
// Add substring subject[prev;start] to answer string. // Add substring subject[prev;start] to answer string.
String::WriteToFlat(*subject, answer->GetChars(no_gc) + position, prev, String::WriteToFlat(*subject, answer->GetChars(no_gc) + position, prev,
start); start - prev);
position += start - prev; position += start - prev;
} }
prev = end; prev = end;
...@@ -769,7 +769,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalRegExpWithEmptyString( ...@@ -769,7 +769,7 @@ V8_WARN_UNUSED_RESULT static Object StringReplaceGlobalRegExpWithEmptyString(
if (prev < subject_length) { if (prev < subject_length) {
// Add substring subject[prev;length] to answer string. // Add substring subject[prev;length] to answer string.
String::WriteToFlat(*subject, answer->GetChars(no_gc) + position, prev, String::WriteToFlat(*subject, answer->GetChars(no_gc) + position, prev,
subject_length); subject_length - prev);
position += subject_length - prev; position += subject_length - prev;
} }
......
...@@ -34,7 +34,7 @@ void StringBuilderConcatHelper(String special, sinkchar* sink, ...@@ -34,7 +34,7 @@ void StringBuilderConcatHelper(String special, sinkchar* sink,
pos = Smi::ToInt(obj); pos = Smi::ToInt(obj);
len = -encoded_slice; len = -encoded_slice;
} }
String::WriteToFlat(special, sink + position, pos, pos + len); String::WriteToFlat(special, sink + position, pos, len);
position += len; position += len;
} else { } else {
String string = String::cast(element); String string = String::cast(element);
......
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