5 #include "src/string-builder-inl.h" 7 #include "src/isolate-inl.h" 8 #include "src/objects/fixed-array-inl.h" 9 #include "src/objects/js-array-inl.h" 14 template <
typename sink
char>
15 void StringBuilderConcatHelper(String special, sinkchar* sink,
16 FixedArray fixed_array,
int array_length) {
17 DisallowHeapAllocation no_gc;
19 for (
int i = 0;
i < array_length;
i++) {
20 Object* element = fixed_array->get(
i);
21 if (element->IsSmi()) {
23 int encoded_slice = Smi::ToInt(element);
26 if (encoded_slice > 0) {
28 pos = StringBuilderSubstringPosition::decode(encoded_slice);
29 len = StringBuilderSubstringLength::decode(encoded_slice);
32 Object* obj = fixed_array->get(++
i);
34 pos = Smi::ToInt(obj);
37 String::WriteToFlat(special, sink + position, pos, pos + len);
40 String
string = String::cast(element);
41 int element_length =
string->length();
42 String::WriteToFlat(
string, sink + position, 0, element_length);
43 position += element_length;
48 template void StringBuilderConcatHelper<uint8_t>(String special, uint8_t* sink,
49 FixedArray fixed_array,
52 template void StringBuilderConcatHelper<uc16>(String special, uc16* sink,
53 FixedArray fixed_array,
56 int StringBuilderConcatLength(
int special_length, FixedArray fixed_array,
57 int array_length,
bool* one_byte) {
58 DisallowHeapAllocation no_gc;
60 for (
int i = 0;
i < array_length;
i++) {
62 Object* elt = fixed_array->get(
i);
65 int smi_value = Smi::ToInt(elt);
70 pos = StringBuilderSubstringPosition::decode(smi_value);
71 len = StringBuilderSubstringLength::decode(smi_value);
77 if (
i >= array_length)
return -1;
78 Object* next_smi = fixed_array->get(
i);
79 if (!next_smi->IsSmi())
return -1;
80 pos = Smi::ToInt(next_smi);
81 if (pos < 0)
return -1;
85 if (pos > special_length || len > special_length - pos)
return -1;
87 }
else if (elt->IsString()) {
88 String element = String::cast(elt);
89 int element_length = element->length();
90 increment = element_length;
91 if (*one_byte && !element->HasOnlyOneByteChars()) {
97 if (increment > String::kMaxLength - position) {
100 position += increment;
105 FixedArrayBuilder::FixedArrayBuilder(Isolate* isolate,
int initial_capacity)
106 : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
108 has_non_smi_elements_(false) {
111 DCHECK_GT(initial_capacity, 0);
114 FixedArrayBuilder::FixedArrayBuilder(Handle<FixedArray> backing_store)
115 : array_(backing_store), length_(0), has_non_smi_elements_(false) {
118 DCHECK_GT(backing_store->length(), 0);
121 bool FixedArrayBuilder::HasCapacity(
int elements) {
122 int length = array_->length();
123 int required_length = length_ + elements;
124 return (length >= required_length);
127 void FixedArrayBuilder::EnsureCapacity(Isolate* isolate,
int elements) {
128 int length = array_->length();
129 int required_length = length_ + elements;
130 if (length < required_length) {
131 int new_length = length;
134 }
while (new_length < required_length);
135 Handle<FixedArray> extended_array =
136 isolate->factory()->NewFixedArrayWithHoles(new_length);
137 array_->CopyTo(0, *extended_array, 0, length_);
138 array_ = extended_array;
142 void FixedArrayBuilder::Add(Object* value) {
143 DCHECK(!value->IsSmi());
144 DCHECK(length_ < capacity());
145 array_->set(length_, value);
147 has_non_smi_elements_ =
true;
150 void FixedArrayBuilder::Add(Smi value) {
151 DCHECK(value->IsSmi());
152 DCHECK(length_ < capacity());
153 array_->set(length_, value);
157 int FixedArrayBuilder::capacity() {
return array_->length(); }
159 Handle<JSArray> FixedArrayBuilder::ToJSArray(Handle<JSArray> target_array) {
160 JSArray::SetContent(target_array, array_);
161 target_array->set_length(Smi::FromInt(length_));
165 ReplacementStringBuilder::ReplacementStringBuilder(Heap* heap,
166 Handle<String> subject,
167 int estimated_part_count)
169 array_builder_(heap->isolate(), estimated_part_count),
172 is_one_byte_(subject->IsOneByteRepresentation()) {
175 DCHECK_GT(estimated_part_count, 0);
178 void ReplacementStringBuilder::EnsureCapacity(
int elements) {
179 array_builder_.EnsureCapacity(heap_->isolate(), elements);
182 void ReplacementStringBuilder::AddString(Handle<String>
string) {
183 int length =
string->length();
184 DCHECK_GT(length, 0);
186 if (!string->IsOneByteRepresentation()) {
187 is_one_byte_ =
false;
189 IncrementCharacterCount(length);
192 MaybeHandle<String> ReplacementStringBuilder::ToString() {
193 Isolate* isolate = heap_->isolate();
194 if (array_builder_.length() == 0) {
195 return isolate->factory()->empty_string();
198 Handle<String> joined_string;
200 Handle<SeqOneByteString> seq;
201 ASSIGN_RETURN_ON_EXCEPTION(
202 isolate, seq, isolate->factory()->NewRawOneByteString(character_count_),
205 DisallowHeapAllocation no_gc;
206 uint8_t* char_buffer = seq->GetChars();
207 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
208 array_builder_.length());
209 joined_string = Handle<String>::cast(seq);
212 Handle<SeqTwoByteString> seq;
213 ASSIGN_RETURN_ON_EXCEPTION(
214 isolate, seq, isolate->factory()->NewRawTwoByteString(character_count_),
217 DisallowHeapAllocation no_gc;
218 uc16* char_buffer = seq->GetChars();
219 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
220 array_builder_.length());
221 joined_string = Handle<String>::cast(seq);
223 return joined_string;
226 void ReplacementStringBuilder::AddElement(Object* element) {
227 DCHECK(element->IsSmi() || element->IsString());
228 DCHECK(array_builder_.capacity() > array_builder_.length());
229 array_builder_.Add(element);
232 IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate)
234 encoding_(String::ONE_BYTE_ENCODING),
236 part_length_(kInitialPartLength),
240 Handle<String>::New(ReadOnlyRoots(isolate).empty_string(), isolate);
242 factory()->NewRawOneByteString(part_length_).ToHandleChecked();
245 int IncrementalStringBuilder::Length()
const {
246 return accumulator_->length() + current_index_;
249 void IncrementalStringBuilder::Accumulate(Handle<String> new_part) {
250 Handle<String> new_accumulator;
251 if (accumulator()->length() + new_part->length() > String::kMaxLength) {
253 new_accumulator = factory()->empty_string();
257 factory()->NewConsString(accumulator(), new_part).ToHandleChecked();
259 set_accumulator(new_accumulator);
263 void IncrementalStringBuilder::Extend() {
264 DCHECK_EQ(current_index_, current_part()->length());
265 Accumulate(current_part());
266 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
267 part_length_ *= kPartLengthGrowthFactor;
269 Handle<String> new_part;
270 if (encoding_ == String::ONE_BYTE_ENCODING) {
271 new_part = factory()->NewRawOneByteString(part_length_).ToHandleChecked();
273 new_part = factory()->NewRawTwoByteString(part_length_).ToHandleChecked();
276 set_current_part(new_part);
281 MaybeHandle<String> IncrementalStringBuilder::Finish() {
283 Accumulate(current_part());
285 THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), String);
287 return accumulator();
291 void IncrementalStringBuilder::AppendString(Handle<String>
string) {
293 part_length_ = kInitialPartLength;