11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/base/strings.h"
61cb0ef41Sopenharmony_ci#include "src/execution/isolate-inl.h"
71cb0ef41Sopenharmony_ci#include "src/objects/fixed-array-inl.h"
81cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h"
91cb0ef41Sopenharmony_ci#include "src/strings/string-builder-inl.h"
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cinamespace v8 {
121cb0ef41Sopenharmony_cinamespace internal {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_citemplate <typename sinkchar>
151cb0ef41Sopenharmony_civoid StringBuilderConcatHelper(String special, sinkchar* sink,
161cb0ef41Sopenharmony_ci                               FixedArray fixed_array, int array_length) {
171cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
181cb0ef41Sopenharmony_ci  int position = 0;
191cb0ef41Sopenharmony_ci  for (int i = 0; i < array_length; i++) {
201cb0ef41Sopenharmony_ci    Object element = fixed_array.get(i);
211cb0ef41Sopenharmony_ci    if (element.IsSmi()) {
221cb0ef41Sopenharmony_ci      // Smi encoding of position and length.
231cb0ef41Sopenharmony_ci      int encoded_slice = Smi::ToInt(element);
241cb0ef41Sopenharmony_ci      int pos;
251cb0ef41Sopenharmony_ci      int len;
261cb0ef41Sopenharmony_ci      if (encoded_slice > 0) {
271cb0ef41Sopenharmony_ci        // Position and length encoded in one smi.
281cb0ef41Sopenharmony_ci        pos = StringBuilderSubstringPosition::decode(encoded_slice);
291cb0ef41Sopenharmony_ci        len = StringBuilderSubstringLength::decode(encoded_slice);
301cb0ef41Sopenharmony_ci      } else {
311cb0ef41Sopenharmony_ci        // Position and length encoded in two smis.
321cb0ef41Sopenharmony_ci        Object obj = fixed_array.get(++i);
331cb0ef41Sopenharmony_ci        DCHECK(obj.IsSmi());
341cb0ef41Sopenharmony_ci        pos = Smi::ToInt(obj);
351cb0ef41Sopenharmony_ci        len = -encoded_slice;
361cb0ef41Sopenharmony_ci      }
371cb0ef41Sopenharmony_ci      String::WriteToFlat(special, sink + position, pos, len);
381cb0ef41Sopenharmony_ci      position += len;
391cb0ef41Sopenharmony_ci    } else {
401cb0ef41Sopenharmony_ci      String string = String::cast(element);
411cb0ef41Sopenharmony_ci      int element_length = string.length();
421cb0ef41Sopenharmony_ci      String::WriteToFlat(string, sink + position, 0, element_length);
431cb0ef41Sopenharmony_ci      position += element_length;
441cb0ef41Sopenharmony_ci    }
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_citemplate void StringBuilderConcatHelper<uint8_t>(String special, uint8_t* sink,
491cb0ef41Sopenharmony_ci                                                 FixedArray fixed_array,
501cb0ef41Sopenharmony_ci                                                 int array_length);
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_citemplate void StringBuilderConcatHelper<base::uc16>(String special,
531cb0ef41Sopenharmony_ci                                                    base::uc16* sink,
541cb0ef41Sopenharmony_ci                                                    FixedArray fixed_array,
551cb0ef41Sopenharmony_ci                                                    int array_length);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ciint StringBuilderConcatLength(int special_length, FixedArray fixed_array,
581cb0ef41Sopenharmony_ci                              int array_length, bool* one_byte) {
591cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
601cb0ef41Sopenharmony_ci  int position = 0;
611cb0ef41Sopenharmony_ci  for (int i = 0; i < array_length; i++) {
621cb0ef41Sopenharmony_ci    int increment = 0;
631cb0ef41Sopenharmony_ci    Object elt = fixed_array.get(i);
641cb0ef41Sopenharmony_ci    if (elt.IsSmi()) {
651cb0ef41Sopenharmony_ci      // Smi encoding of position and length.
661cb0ef41Sopenharmony_ci      int smi_value = Smi::ToInt(elt);
671cb0ef41Sopenharmony_ci      int pos;
681cb0ef41Sopenharmony_ci      int len;
691cb0ef41Sopenharmony_ci      if (smi_value > 0) {
701cb0ef41Sopenharmony_ci        // Position and length encoded in one smi.
711cb0ef41Sopenharmony_ci        pos = StringBuilderSubstringPosition::decode(smi_value);
721cb0ef41Sopenharmony_ci        len = StringBuilderSubstringLength::decode(smi_value);
731cb0ef41Sopenharmony_ci      } else {
741cb0ef41Sopenharmony_ci        // Position and length encoded in two smis.
751cb0ef41Sopenharmony_ci        len = -smi_value;
761cb0ef41Sopenharmony_ci        // Get the position and check that it is a positive smi.
771cb0ef41Sopenharmony_ci        i++;
781cb0ef41Sopenharmony_ci        if (i >= array_length) return -1;
791cb0ef41Sopenharmony_ci        Object next_smi = fixed_array.get(i);
801cb0ef41Sopenharmony_ci        if (!next_smi.IsSmi()) return -1;
811cb0ef41Sopenharmony_ci        pos = Smi::ToInt(next_smi);
821cb0ef41Sopenharmony_ci        if (pos < 0) return -1;
831cb0ef41Sopenharmony_ci      }
841cb0ef41Sopenharmony_ci      DCHECK_GE(pos, 0);
851cb0ef41Sopenharmony_ci      DCHECK_GE(len, 0);
861cb0ef41Sopenharmony_ci      if (pos > special_length || len > special_length - pos) return -1;
871cb0ef41Sopenharmony_ci      increment = len;
881cb0ef41Sopenharmony_ci    } else if (elt.IsString()) {
891cb0ef41Sopenharmony_ci      String element = String::cast(elt);
901cb0ef41Sopenharmony_ci      int element_length = element.length();
911cb0ef41Sopenharmony_ci      increment = element_length;
921cb0ef41Sopenharmony_ci      if (*one_byte && !element.IsOneByteRepresentation()) {
931cb0ef41Sopenharmony_ci        *one_byte = false;
941cb0ef41Sopenharmony_ci      }
951cb0ef41Sopenharmony_ci    } else {
961cb0ef41Sopenharmony_ci      return -1;
971cb0ef41Sopenharmony_ci    }
981cb0ef41Sopenharmony_ci    if (increment > String::kMaxLength - position) {
991cb0ef41Sopenharmony_ci      return kMaxInt;  // Provoke throw on allocation.
1001cb0ef41Sopenharmony_ci    }
1011cb0ef41Sopenharmony_ci    position += increment;
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci  return position;
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ciFixedArrayBuilder::FixedArrayBuilder(Isolate* isolate, int initial_capacity)
1071cb0ef41Sopenharmony_ci    : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
1081cb0ef41Sopenharmony_ci      length_(0),
1091cb0ef41Sopenharmony_ci      has_non_smi_elements_(false) {
1101cb0ef41Sopenharmony_ci  // Require a non-zero initial size. Ensures that doubling the size to
1111cb0ef41Sopenharmony_ci  // extend the array will work.
1121cb0ef41Sopenharmony_ci  DCHECK_GT(initial_capacity, 0);
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ciFixedArrayBuilder::FixedArrayBuilder(Handle<FixedArray> backing_store)
1161cb0ef41Sopenharmony_ci    : array_(backing_store), length_(0), has_non_smi_elements_(false) {
1171cb0ef41Sopenharmony_ci  // Require a non-zero initial size. Ensures that doubling the size to
1181cb0ef41Sopenharmony_ci  // extend the array will work.
1191cb0ef41Sopenharmony_ci  DCHECK_GT(backing_store->length(), 0);
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_cibool FixedArrayBuilder::HasCapacity(int elements) {
1231cb0ef41Sopenharmony_ci  int length = array_->length();
1241cb0ef41Sopenharmony_ci  int required_length = length_ + elements;
1251cb0ef41Sopenharmony_ci  return (length >= required_length);
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_civoid FixedArrayBuilder::EnsureCapacity(Isolate* isolate, int elements) {
1291cb0ef41Sopenharmony_ci  int length = array_->length();
1301cb0ef41Sopenharmony_ci  int required_length = length_ + elements;
1311cb0ef41Sopenharmony_ci  if (length < required_length) {
1321cb0ef41Sopenharmony_ci    int new_length = length;
1331cb0ef41Sopenharmony_ci    do {
1341cb0ef41Sopenharmony_ci      new_length *= 2;
1351cb0ef41Sopenharmony_ci    } while (new_length < required_length);
1361cb0ef41Sopenharmony_ci    Handle<FixedArray> extended_array =
1371cb0ef41Sopenharmony_ci        isolate->factory()->NewFixedArrayWithHoles(new_length);
1381cb0ef41Sopenharmony_ci    array_->CopyTo(0, *extended_array, 0, length_);
1391cb0ef41Sopenharmony_ci    array_ = extended_array;
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_civoid FixedArrayBuilder::Add(Object value) {
1441cb0ef41Sopenharmony_ci  DCHECK(!value.IsSmi());
1451cb0ef41Sopenharmony_ci  array_->set(length_, value);
1461cb0ef41Sopenharmony_ci  length_++;
1471cb0ef41Sopenharmony_ci  has_non_smi_elements_ = true;
1481cb0ef41Sopenharmony_ci}
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_civoid FixedArrayBuilder::Add(Smi value) {
1511cb0ef41Sopenharmony_ci  DCHECK(value.IsSmi());
1521cb0ef41Sopenharmony_ci  array_->set(length_, value);
1531cb0ef41Sopenharmony_ci  length_++;
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ciint FixedArrayBuilder::capacity() { return array_->length(); }
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciHandle<JSArray> FixedArrayBuilder::ToJSArray(Handle<JSArray> target_array) {
1591cb0ef41Sopenharmony_ci  JSArray::SetContent(target_array, array_);
1601cb0ef41Sopenharmony_ci  target_array->set_length(Smi::FromInt(length_));
1611cb0ef41Sopenharmony_ci  return target_array;
1621cb0ef41Sopenharmony_ci}
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ciReplacementStringBuilder::ReplacementStringBuilder(Heap* heap,
1651cb0ef41Sopenharmony_ci                                                   Handle<String> subject,
1661cb0ef41Sopenharmony_ci                                                   int estimated_part_count)
1671cb0ef41Sopenharmony_ci    : heap_(heap),
1681cb0ef41Sopenharmony_ci      array_builder_(Isolate::FromHeap(heap), estimated_part_count),
1691cb0ef41Sopenharmony_ci      subject_(subject),
1701cb0ef41Sopenharmony_ci      character_count_(0),
1711cb0ef41Sopenharmony_ci      is_one_byte_(subject->IsOneByteRepresentation()) {
1721cb0ef41Sopenharmony_ci  // Require a non-zero initial size. Ensures that doubling the size to
1731cb0ef41Sopenharmony_ci  // extend the array will work.
1741cb0ef41Sopenharmony_ci  DCHECK_GT(estimated_part_count, 0);
1751cb0ef41Sopenharmony_ci}
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_civoid ReplacementStringBuilder::EnsureCapacity(int elements) {
1781cb0ef41Sopenharmony_ci  array_builder_.EnsureCapacity(Isolate::FromHeap(heap_), elements);
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_civoid ReplacementStringBuilder::AddString(Handle<String> string) {
1821cb0ef41Sopenharmony_ci  int length = string->length();
1831cb0ef41Sopenharmony_ci  DCHECK_GT(length, 0);
1841cb0ef41Sopenharmony_ci  AddElement(string);
1851cb0ef41Sopenharmony_ci  if (!string->IsOneByteRepresentation()) {
1861cb0ef41Sopenharmony_ci    is_one_byte_ = false;
1871cb0ef41Sopenharmony_ci  }
1881cb0ef41Sopenharmony_ci  IncrementCharacterCount(length);
1891cb0ef41Sopenharmony_ci}
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ciMaybeHandle<String> ReplacementStringBuilder::ToString() {
1921cb0ef41Sopenharmony_ci  Isolate* isolate = Isolate::FromHeap(heap_);
1931cb0ef41Sopenharmony_ci  if (array_builder_.length() == 0) {
1941cb0ef41Sopenharmony_ci    return isolate->factory()->empty_string();
1951cb0ef41Sopenharmony_ci  }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  Handle<String> joined_string;
1981cb0ef41Sopenharmony_ci  if (is_one_byte_) {
1991cb0ef41Sopenharmony_ci    Handle<SeqOneByteString> seq;
2001cb0ef41Sopenharmony_ci    ASSIGN_RETURN_ON_EXCEPTION(
2011cb0ef41Sopenharmony_ci        isolate, seq, isolate->factory()->NewRawOneByteString(character_count_),
2021cb0ef41Sopenharmony_ci        String);
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci    DisallowGarbageCollection no_gc;
2051cb0ef41Sopenharmony_ci    uint8_t* char_buffer = seq->GetChars(no_gc);
2061cb0ef41Sopenharmony_ci    StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
2071cb0ef41Sopenharmony_ci                              array_builder_.length());
2081cb0ef41Sopenharmony_ci    joined_string = Handle<String>::cast(seq);
2091cb0ef41Sopenharmony_ci  } else {
2101cb0ef41Sopenharmony_ci    // Two-byte.
2111cb0ef41Sopenharmony_ci    Handle<SeqTwoByteString> seq;
2121cb0ef41Sopenharmony_ci    ASSIGN_RETURN_ON_EXCEPTION(
2131cb0ef41Sopenharmony_ci        isolate, seq, isolate->factory()->NewRawTwoByteString(character_count_),
2141cb0ef41Sopenharmony_ci        String);
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci    DisallowGarbageCollection no_gc;
2171cb0ef41Sopenharmony_ci    base::uc16* char_buffer = seq->GetChars(no_gc);
2181cb0ef41Sopenharmony_ci    StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
2191cb0ef41Sopenharmony_ci                              array_builder_.length());
2201cb0ef41Sopenharmony_ci    joined_string = Handle<String>::cast(seq);
2211cb0ef41Sopenharmony_ci  }
2221cb0ef41Sopenharmony_ci  return joined_string;
2231cb0ef41Sopenharmony_ci}
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_civoid ReplacementStringBuilder::AddElement(Handle<Object> element) {
2261cb0ef41Sopenharmony_ci  DCHECK(element->IsSmi() || element->IsString());
2271cb0ef41Sopenharmony_ci  EnsureCapacity(1);
2281cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
2291cb0ef41Sopenharmony_ci  array_builder_.Add(*element);
2301cb0ef41Sopenharmony_ci}
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ciIncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate)
2331cb0ef41Sopenharmony_ci    : isolate_(isolate),
2341cb0ef41Sopenharmony_ci      encoding_(String::ONE_BYTE_ENCODING),
2351cb0ef41Sopenharmony_ci      overflowed_(false),
2361cb0ef41Sopenharmony_ci      part_length_(kInitialPartLength),
2371cb0ef41Sopenharmony_ci      current_index_(0) {
2381cb0ef41Sopenharmony_ci  // Create an accumulator handle starting with the empty string.
2391cb0ef41Sopenharmony_ci  accumulator_ =
2401cb0ef41Sopenharmony_ci      Handle<String>::New(ReadOnlyRoots(isolate).empty_string(), isolate);
2411cb0ef41Sopenharmony_ci  current_part_ =
2421cb0ef41Sopenharmony_ci      factory()->NewRawOneByteString(part_length_).ToHandleChecked();
2431cb0ef41Sopenharmony_ci}
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ciint IncrementalStringBuilder::Length() const {
2461cb0ef41Sopenharmony_ci  return accumulator_->length() + current_index_;
2471cb0ef41Sopenharmony_ci}
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_cibool IncrementalStringBuilder::HasValidCurrentIndex() const {
2501cb0ef41Sopenharmony_ci  return current_index_ < part_length_;
2511cb0ef41Sopenharmony_ci}
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_civoid IncrementalStringBuilder::Accumulate(Handle<String> new_part) {
2541cb0ef41Sopenharmony_ci  Handle<String> new_accumulator;
2551cb0ef41Sopenharmony_ci  if (accumulator()->length() + new_part->length() > String::kMaxLength) {
2561cb0ef41Sopenharmony_ci    // Set the flag and carry on. Delay throwing the exception till the end.
2571cb0ef41Sopenharmony_ci    new_accumulator = factory()->empty_string();
2581cb0ef41Sopenharmony_ci    overflowed_ = true;
2591cb0ef41Sopenharmony_ci  } else {
2601cb0ef41Sopenharmony_ci    new_accumulator =
2611cb0ef41Sopenharmony_ci        factory()->NewConsString(accumulator(), new_part).ToHandleChecked();
2621cb0ef41Sopenharmony_ci  }
2631cb0ef41Sopenharmony_ci  set_accumulator(new_accumulator);
2641cb0ef41Sopenharmony_ci}
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_civoid IncrementalStringBuilder::Extend() {
2671cb0ef41Sopenharmony_ci  DCHECK_EQ(current_index_, current_part()->length());
2681cb0ef41Sopenharmony_ci  Accumulate(current_part());
2691cb0ef41Sopenharmony_ci  if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
2701cb0ef41Sopenharmony_ci    part_length_ *= kPartLengthGrowthFactor;
2711cb0ef41Sopenharmony_ci  }
2721cb0ef41Sopenharmony_ci  Handle<String> new_part;
2731cb0ef41Sopenharmony_ci  if (encoding_ == String::ONE_BYTE_ENCODING) {
2741cb0ef41Sopenharmony_ci    new_part = factory()->NewRawOneByteString(part_length_).ToHandleChecked();
2751cb0ef41Sopenharmony_ci  } else {
2761cb0ef41Sopenharmony_ci    new_part = factory()->NewRawTwoByteString(part_length_).ToHandleChecked();
2771cb0ef41Sopenharmony_ci  }
2781cb0ef41Sopenharmony_ci  // Reuse the same handle to avoid being invalidated when exiting handle scope.
2791cb0ef41Sopenharmony_ci  set_current_part(new_part);
2801cb0ef41Sopenharmony_ci  current_index_ = 0;
2811cb0ef41Sopenharmony_ci}
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ciMaybeHandle<String> IncrementalStringBuilder::Finish() {
2841cb0ef41Sopenharmony_ci  ShrinkCurrentPart();
2851cb0ef41Sopenharmony_ci  Accumulate(current_part());
2861cb0ef41Sopenharmony_ci  if (overflowed_) {
2871cb0ef41Sopenharmony_ci    THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), String);
2881cb0ef41Sopenharmony_ci  }
2891cb0ef41Sopenharmony_ci  return accumulator();
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci// Short strings can be copied directly to {current_part_}.
2931cb0ef41Sopenharmony_ci// Requires the IncrementalStringBuilder to either have two byte encoding or
2941cb0ef41Sopenharmony_ci// the incoming string to have one byte representation "underneath" (The
2951cb0ef41Sopenharmony_ci// one byte check requires the string to be flat).
2961cb0ef41Sopenharmony_cibool IncrementalStringBuilder::CanAppendByCopy(Handle<String> string) {
2971cb0ef41Sopenharmony_ci  constexpr int kMaxStringLengthForCopy = 16;
2981cb0ef41Sopenharmony_ci  const bool representation_ok =
2991cb0ef41Sopenharmony_ci      encoding_ == String::TWO_BYTE_ENCODING ||
3001cb0ef41Sopenharmony_ci      (string->IsFlat() && String::IsOneByteRepresentationUnderneath(*string));
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  return representation_ok && string->length() <= kMaxStringLengthForCopy &&
3031cb0ef41Sopenharmony_ci         CurrentPartCanFit(string->length());
3041cb0ef41Sopenharmony_ci}
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_civoid IncrementalStringBuilder::AppendStringByCopy(Handle<String> string) {
3071cb0ef41Sopenharmony_ci  DCHECK(CanAppendByCopy(string));
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  Handle<SeqOneByteString> part =
3101cb0ef41Sopenharmony_ci      Handle<SeqOneByteString>::cast(current_part());
3111cb0ef41Sopenharmony_ci  {
3121cb0ef41Sopenharmony_ci    DisallowGarbageCollection no_gc;
3131cb0ef41Sopenharmony_ci    String::WriteToFlat(*string, part->GetChars(no_gc) + current_index_, 0,
3141cb0ef41Sopenharmony_ci                        string->length());
3151cb0ef41Sopenharmony_ci  }
3161cb0ef41Sopenharmony_ci  current_index_ += string->length();
3171cb0ef41Sopenharmony_ci  DCHECK(current_index_ <= part_length_);
3181cb0ef41Sopenharmony_ci  if (current_index_ == part_length_) Extend();
3191cb0ef41Sopenharmony_ci}
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_civoid IncrementalStringBuilder::AppendString(Handle<String> string) {
3221cb0ef41Sopenharmony_ci  if (CanAppendByCopy(string)) {
3231cb0ef41Sopenharmony_ci    AppendStringByCopy(string);
3241cb0ef41Sopenharmony_ci    return;
3251cb0ef41Sopenharmony_ci  }
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  ShrinkCurrentPart();
3281cb0ef41Sopenharmony_ci  part_length_ = kInitialPartLength;  // Allocate conservatively.
3291cb0ef41Sopenharmony_ci  Extend();  // Attach current part and allocate new part.
3301cb0ef41Sopenharmony_ci  Accumulate(string);
3311cb0ef41Sopenharmony_ci}
3321cb0ef41Sopenharmony_ci}  // namespace internal
3331cb0ef41Sopenharmony_ci}  // namespace v8
334