Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/string-builder.h"
6 :
7 : #include "src/isolate-inl.h"
8 : #include "src/objects-inl.h"
9 :
10 : namespace v8 {
11 : namespace internal {
12 :
13 8643 : MaybeHandle<String> ReplacementStringBuilder::ToString() {
14 8643 : Isolate* isolate = heap_->isolate();
15 17231 : if (array_builder_.length() == 0) {
16 36 : return isolate->factory()->empty_string();
17 : }
18 :
19 : Handle<String> joined_string;
20 8607 : if (is_one_byte_) {
21 : Handle<SeqOneByteString> seq;
22 16960 : ASSIGN_RETURN_ON_EXCEPTION(
23 : isolate, seq, isolate->factory()->NewRawOneByteString(character_count_),
24 : String);
25 :
26 : DisallowHeapAllocation no_gc;
27 8461 : uint8_t* char_buffer = seq->GetChars();
28 : StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
29 8461 : array_builder_.length());
30 : joined_string = Handle<String>::cast(seq);
31 : } else {
32 : // Two-byte.
33 : Handle<SeqTwoByteString> seq;
34 254 : ASSIGN_RETURN_ON_EXCEPTION(
35 : isolate, seq, isolate->factory()->NewRawTwoByteString(character_count_),
36 : String);
37 :
38 : DisallowHeapAllocation no_gc;
39 127 : uc16* char_buffer = seq->GetChars();
40 : StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
41 127 : array_builder_.length());
42 : joined_string = Handle<String>::cast(seq);
43 : }
44 8588 : return joined_string;
45 : }
46 :
47 :
48 17657126 : IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate)
49 : : isolate_(isolate),
50 : encoding_(String::ONE_BYTE_ENCODING),
51 : overflowed_(false),
52 : part_length_(kInitialPartLength),
53 8828563 : current_index_(0) {
54 : // Create an accumulator handle starting with the empty string.
55 17657126 : accumulator_ = Handle<String>::New(isolate->heap()->empty_string(), isolate);
56 : current_part_ =
57 26485689 : factory()->NewRawOneByteString(part_length_).ToHandleChecked();
58 8828563 : }
59 :
60 :
61 71924284 : void IncrementalStringBuilder::Accumulate(Handle<String> new_part) {
62 : Handle<String> new_accumulator;
63 35962142 : if (accumulator()->length() + new_part->length() > String::kMaxLength) {
64 : // Set the flag and carry on. Delay throwing the exception till the end.
65 : new_accumulator = factory()->empty_string();
66 50 : overflowed_ = true;
67 : } else {
68 : new_accumulator =
69 71924185 : factory()->NewConsString(accumulator(), new_part).ToHandleChecked();
70 : }
71 : set_accumulator(new_accumulator);
72 35962143 : }
73 :
74 :
75 28659246 : void IncrementalStringBuilder::Extend() {
76 : DCHECK_EQ(current_index_, current_part()->length());
77 14329623 : Accumulate(current_part());
78 14329623 : if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
79 14158223 : part_length_ *= kPartLengthGrowthFactor;
80 : }
81 : Handle<String> new_part;
82 14329623 : if (encoding_ == String::ONE_BYTE_ENCODING) {
83 40729398 : new_part = factory()->NewRawOneByteString(part_length_).ToHandleChecked();
84 : } else {
85 2259471 : new_part = factory()->NewRawTwoByteString(part_length_).ToHandleChecked();
86 : }
87 : // Reuse the same handle to avoid being invalidated when exiting handle scope.
88 : set_current_part(new_part);
89 14329623 : current_index_ = 0;
90 14329623 : }
91 :
92 :
93 8828023 : MaybeHandle<String> IncrementalStringBuilder::Finish() {
94 8828023 : ShrinkCurrentPart();
95 8828023 : Accumulate(current_part());
96 8828023 : if (overflowed_) {
97 50 : THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), String);
98 : }
99 8827973 : return accumulator();
100 : }
101 :
102 :
103 12804497 : void IncrementalStringBuilder::AppendString(Handle<String> string) {
104 12804497 : ShrinkCurrentPart();
105 12804497 : part_length_ = kInitialPartLength; // Allocate conservatively.
106 12804497 : Extend(); // Attach current part and allocate new part.
107 12804497 : Accumulate(string);
108 12804497 : }
109 : } // namespace internal
110 : } // namespace v8
|