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