diff options
Diffstat (limited to 'deps/v8/src/string-builder.cc')
-rw-r--r-- | deps/v8/src/string-builder.cc | 191 |
1 files changed, 189 insertions, 2 deletions
diff --git a/deps/v8/src/string-builder.cc b/deps/v8/src/string-builder.cc index bee5db95085..66ccb771848 100644 --- a/deps/v8/src/string-builder.cc +++ b/deps/v8/src/string-builder.cc @@ -2,14 +2,193 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/string-builder.h" +#include "src/string-builder-inl.h" #include "src/isolate-inl.h" -#include "src/objects-inl.h" +#include "src/objects/fixed-array-inl.h" +#include "src/objects/js-array-inl.h" namespace v8 { namespace internal { +template <typename sinkchar> +void StringBuilderConcatHelper(String* special, sinkchar* sink, + FixedArray* fixed_array, int array_length) { + DisallowHeapAllocation no_gc; + int position = 0; + for (int i = 0; i < array_length; i++) { + Object* element = fixed_array->get(i); + if (element->IsSmi()) { + // Smi encoding of position and length. + int encoded_slice = Smi::ToInt(element); + int pos; + int len; + if (encoded_slice > 0) { + // Position and length encoded in one smi. + pos = StringBuilderSubstringPosition::decode(encoded_slice); + len = StringBuilderSubstringLength::decode(encoded_slice); + } else { + // Position and length encoded in two smis. + Object* obj = fixed_array->get(++i); + DCHECK(obj->IsSmi()); + pos = Smi::ToInt(obj); + len = -encoded_slice; + } + String::WriteToFlat(special, sink + position, pos, pos + len); + position += len; + } else { + String* string = String::cast(element); + int element_length = string->length(); + String::WriteToFlat(string, sink + position, 0, element_length); + position += element_length; + } + } +} + +template void StringBuilderConcatHelper<uint8_t>(String* special, uint8_t* sink, + FixedArray* fixed_array, + int array_length); + +template void StringBuilderConcatHelper<uc16>(String* special, uc16* sink, + FixedArray* fixed_array, + int array_length); + +int StringBuilderConcatLength(int special_length, FixedArray* fixed_array, + int array_length, bool* one_byte) { + DisallowHeapAllocation no_gc; + int position = 0; + for (int i = 0; i < array_length; i++) { + int increment = 0; + Object* elt = fixed_array->get(i); + if (elt->IsSmi()) { + // Smi encoding of position and length. + int smi_value = Smi::ToInt(elt); + int pos; + int len; + if (smi_value > 0) { + // Position and length encoded in one smi. + pos = StringBuilderSubstringPosition::decode(smi_value); + len = StringBuilderSubstringLength::decode(smi_value); + } else { + // Position and length encoded in two smis. + len = -smi_value; + // Get the position and check that it is a positive smi. + i++; + if (i >= array_length) return -1; + Object* next_smi = fixed_array->get(i); + if (!next_smi->IsSmi()) return -1; + pos = Smi::ToInt(next_smi); + if (pos < 0) return -1; + } + DCHECK_GE(pos, 0); + DCHECK_GE(len, 0); + if (pos > special_length || len > special_length - pos) return -1; + increment = len; + } else if (elt->IsString()) { + String* element = String::cast(elt); + int element_length = element->length(); + increment = element_length; + if (*one_byte && !element->HasOnlyOneByteChars()) { + *one_byte = false; + } + } else { + return -1; + } + if (increment > String::kMaxLength - position) { + return kMaxInt; // Provoke throw on allocation. + } + position += increment; + } + return position; +} + +FixedArrayBuilder::FixedArrayBuilder(Isolate* isolate, int initial_capacity) + : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)), + length_(0), + has_non_smi_elements_(false) { + // Require a non-zero initial size. Ensures that doubling the size to + // extend the array will work. + DCHECK_GT(initial_capacity, 0); +} + +FixedArrayBuilder::FixedArrayBuilder(Handle<FixedArray> backing_store) + : array_(backing_store), length_(0), has_non_smi_elements_(false) { + // Require a non-zero initial size. Ensures that doubling the size to + // extend the array will work. + DCHECK_GT(backing_store->length(), 0); +} + +bool FixedArrayBuilder::HasCapacity(int elements) { + int length = array_->length(); + int required_length = length_ + elements; + return (length >= required_length); +} + +void FixedArrayBuilder::EnsureCapacity(Isolate* isolate, int elements) { + int length = array_->length(); + int required_length = length_ + elements; + if (length < required_length) { + int new_length = length; + do { + new_length *= 2; + } while (new_length < required_length); + Handle<FixedArray> extended_array = + isolate->factory()->NewFixedArrayWithHoles(new_length); + array_->CopyTo(0, *extended_array, 0, length_); + array_ = extended_array; + } +} + +void FixedArrayBuilder::Add(Object* value) { + DCHECK(!value->IsSmi()); + DCHECK(length_ < capacity()); + array_->set(length_, value); + length_++; + has_non_smi_elements_ = true; +} + +void FixedArrayBuilder::Add(Smi* value) { + DCHECK(value->IsSmi()); + DCHECK(length_ < capacity()); + array_->set(length_, value); + length_++; +} + +int FixedArrayBuilder::capacity() { return array_->length(); } + +Handle<JSArray> FixedArrayBuilder::ToJSArray(Handle<JSArray> target_array) { + JSArray::SetContent(target_array, array_); + target_array->set_length(Smi::FromInt(length_)); + return target_array; +} + +ReplacementStringBuilder::ReplacementStringBuilder(Heap* heap, + Handle<String> subject, + int estimated_part_count) + : heap_(heap), + array_builder_(heap->isolate(), estimated_part_count), + subject_(subject), + character_count_(0), + is_one_byte_(subject->IsOneByteRepresentation()) { + // Require a non-zero initial size. Ensures that doubling the size to + // extend the array will work. + DCHECK_GT(estimated_part_count, 0); +} + +void ReplacementStringBuilder::EnsureCapacity(int elements) { + array_builder_.EnsureCapacity(heap_->isolate(), elements); +} + +void ReplacementStringBuilder::AddString(Handle<String> string) { + int length = string->length(); + DCHECK_GT(length, 0); + AddElement(*string); + if (!string->IsOneByteRepresentation()) { + is_one_byte_ = false; + } + IncrementCharacterCount(length); +} + MaybeHandle<String> ReplacementStringBuilder::ToString() { Isolate* isolate = heap_->isolate(); if (array_builder_.length() == 0) { @@ -44,6 +223,11 @@ MaybeHandle<String> ReplacementStringBuilder::ToString() { return joined_string; } +void ReplacementStringBuilder::AddElement(Object* element) { + DCHECK(element->IsSmi() || element->IsString()); + DCHECK(array_builder_.capacity() > array_builder_.length()); + array_builder_.Add(element); +} IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate) : isolate_(isolate), @@ -58,6 +242,9 @@ IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate) factory()->NewRawOneByteString(part_length_).ToHandleChecked(); } +int IncrementalStringBuilder::Length() const { + return accumulator_->length() + current_index_; +} void IncrementalStringBuilder::Accumulate(Handle<String> new_part) { Handle<String> new_accumulator; |