1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#ifndef V8_STRING_BUILDER_H_
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define V8_STRING_BUILDER_H_
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/assert-scope.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/factory.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/utils.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst int kStringBuilderConcatHelperLengthBits = 11;
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst int kStringBuilderConcatHelperPositionBits = 19;
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    StringBuilderSubstringLength;
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef BitField<int, kStringBuilderConcatHelperLengthBits,
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 kStringBuilderConcatHelperPositionBits>
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    StringBuilderSubstringPosition;
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <typename sinkchar>
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic inline void StringBuilderConcatHelper(String* special, sinkchar* sink,
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                             FixedArray* fixed_array,
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                             int array_length) {
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DisallowHeapAllocation no_gc;
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int position = 0;
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < array_length; i++) {
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Object* element = fixed_array->get(i);
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (element->IsSmi()) {
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Smi encoding of position and length.
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int encoded_slice = Smi::cast(element)->value();
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int pos;
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int len;
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (encoded_slice > 0) {
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Position and length encoded in one smi.
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pos = StringBuilderSubstringPosition::decode(encoded_slice);
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        len = StringBuilderSubstringLength::decode(encoded_slice);
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Position and length encoded in two smis.
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Object* obj = fixed_array->get(++i);
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(obj->IsSmi());
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pos = Smi::cast(obj)->value();
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        len = -encoded_slice;
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String::WriteToFlat(special, sink + position, pos, pos + len);
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      position += len;
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String* string = String::cast(element);
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int element_length = string->length();
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String::WriteToFlat(string, sink + position, 0, element_length);
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      position += element_length;
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Returns the result length of the concatenation.
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On illegal argument, -1 is returned.
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic inline int StringBuilderConcatLength(int special_length,
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                            FixedArray* fixed_array,
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                            int array_length, bool* one_byte) {
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DisallowHeapAllocation no_gc;
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int position = 0;
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < array_length; i++) {
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int increment = 0;
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Object* elt = fixed_array->get(i);
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (elt->IsSmi()) {
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Smi encoding of position and length.
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int smi_value = Smi::cast(elt)->value();
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int pos;
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int len;
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (smi_value > 0) {
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Position and length encoded in one smi.
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pos = StringBuilderSubstringPosition::decode(smi_value);
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        len = StringBuilderSubstringLength::decode(smi_value);
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Position and length encoded in two smis.
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        len = -smi_value;
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Get the position and check that it is a positive smi.
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        i++;
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (i >= array_length) return -1;
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Object* next_smi = fixed_array->get(i);
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (!next_smi->IsSmi()) return -1;
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        pos = Smi::cast(next_smi)->value();
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (pos < 0) return -1;
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(pos >= 0);
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(len >= 0);
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (pos > special_length || len > special_length - pos) return -1;
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      increment = len;
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (elt->IsString()) {
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String* element = String::cast(elt);
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int element_length = element->length();
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      increment = element_length;
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (*one_byte && !element->HasOnlyOneByteChars()) {
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        *one_byte = false;
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return -1;
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (increment > String::kMaxLength - position) {
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return kMaxInt;  // Provoke throw on allocation.
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    position += increment;
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return position;
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass FixedArrayBuilder {
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        length_(0),
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        has_non_smi_elements_(false) {
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Require a non-zero initial size. Ensures that doubling the size to
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // extend the array will work.
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(initial_capacity > 0);
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      : array_(backing_store), length_(0), has_non_smi_elements_(false) {
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Require a non-zero initial size. Ensures that doubling the size to
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // extend the array will work.
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(backing_store->length() > 0);
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool HasCapacity(int elements) {
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int length = array_->length();
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int required_length = length_ + elements;
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (length >= required_length);
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EnsureCapacity(int elements) {
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int length = array_->length();
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int required_length = length_ + elements;
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (length < required_length) {
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int new_length = length;
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      do {
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        new_length *= 2;
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } while (new_length < required_length);
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<FixedArray> extended_array =
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      array_->CopyTo(0, *extended_array, 0, length_);
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      array_ = extended_array;
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Add(Object* value) {
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!value->IsSmi());
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(length_ < capacity());
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    array_->set(length_, value);
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    length_++;
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    has_non_smi_elements_ = true;
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Add(Smi* value) {
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(value->IsSmi());
166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(length_ < capacity());
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    array_->set(length_, value);
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    length_++;
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<FixedArray> array() { return array_; }
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int length() { return length_; }
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int capacity() { return array_->length(); }
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    JSArray::SetContent(target_array, array_);
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    target_array->set_length(Smi::FromInt(length_));
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return target_array;
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<FixedArray> array_;
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int length_;
186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool has_non_smi_elements_;
187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass ReplacementStringBuilder {
191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ReplacementStringBuilder(Heap* heap, Handle<String> subject,
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           int estimated_part_count)
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      : heap_(heap),
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        array_builder_(heap->isolate(), estimated_part_count),
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        subject_(subject),
197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        character_count_(0),
198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        is_one_byte_(subject->IsOneByteRepresentation()) {
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Require a non-zero initial size. Ensures that doubling the size to
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // extend the array will work.
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(estimated_part_count > 0);
202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static inline void AddSubjectSlice(FixedArrayBuilder* builder, int from,
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     int to) {
206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(from >= 0);
207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int length = to - from;
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(length > 0);
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (StringBuilderSubstringLength::is_valid(length) &&
210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        StringBuilderSubstringPosition::is_valid(from)) {
211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int encoded_slice = StringBuilderSubstringLength::encode(length) |
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                          StringBuilderSubstringPosition::encode(from);
213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      builder->Add(Smi::FromInt(encoded_slice));
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Otherwise encode as two smis.
216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      builder->Add(Smi::FromInt(-length));
217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      builder->Add(Smi::FromInt(from));
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void EnsureCapacity(int elements) { array_builder_.EnsureCapacity(elements); }
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddSubjectSlice(int from, int to) {
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    AddSubjectSlice(&array_builder_, from, to);
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    IncrementCharacterCount(to - from);
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddString(Handle<String> string) {
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int length = string->length();
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(length > 0);
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    AddElement(*string);
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!string->IsOneByteRepresentation()) {
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      is_one_byte_ = false;
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    IncrementCharacterCount(length);
239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MaybeHandle<String> ToString();
243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void IncrementCharacterCount(int by) {
246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (character_count_ > String::kMaxLength - by) {
247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      STATIC_ASSERT(String::kMaxLength < kMaxInt);
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      character_count_ = kMaxInt;
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      character_count_ += by;
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddElement(Object* element) {
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(element->IsSmi() || element->IsString());
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(array_builder_.capacity() > array_builder_.length());
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    array_builder_.Add(element);
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Heap* heap_;
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FixedArrayBuilder array_builder_;
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<String> subject_;
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int character_count_;
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool is_one_byte_;
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass IncrementalStringBuilder {
270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit IncrementalStringBuilder(Isolate* isolate);
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(String::Encoding CurrentEncoding()) { return encoding_; }
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <typename SrcChar, typename DestChar>
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(void Append(SrcChar c));
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(void AppendCharacter(uint8_t c)) {
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (encoding_ == String::ONE_BYTE_ENCODING) {
280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Append<uint8_t, uint8_t>(c);
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Append<uint8_t, uc16>(c);
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(void AppendCString(const char* s)) {
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (encoding_ == String::ONE_BYTE_ENCODING) {
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      while (*u != '\0') Append<uint8_t, uint8_t>(*(u++));
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      while (*u != '\0') Append<uint8_t, uc16>(*(u++));
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
29513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  INLINE(void AppendCString(const uc16* s)) {
29613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (encoding_ == String::ONE_BYTE_ENCODING) {
29713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      while (*s != '\0') Append<uc16, uint8_t>(*(s++));
29813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
29913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      while (*s != '\0') Append<uc16, uc16>(*(s++));
30013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
30113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
30213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(bool CurrentPartCanFit(int length)) {
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return part_length_ - current_index_ > length;
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AppendString(Handle<String> string);
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MaybeHandle<String> Finish();
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
31113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  INLINE(bool HasOverflowed()) const { return overflowed_; }
31213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Change encoding to two-byte.
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ChangeEncoding() {
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ShrinkCurrentPart();
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    encoding_ = String::TWO_BYTE_ENCODING;
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Extend();
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <typename DestChar>
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class NoExtend {
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   public:
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    explicit NoExtend(Handle<String> string, int offset) {
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(string->IsSeqOneByteString() || string->IsSeqTwoByteString());
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (sizeof(DestChar) == 1) {
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        start_ = reinterpret_cast<DestChar*>(
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Handle<SeqOneByteString>::cast(string)->GetChars() + offset);
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        start_ = reinterpret_cast<DestChar*>(
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Handle<SeqTwoByteString>::cast(string)->GetChars() + offset);
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      cursor_ = start_;
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    INLINE(void Append(DestChar c)) { *(cursor_++) = c; }
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    INLINE(void AppendCString(const char* s)) {
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      while (*u != '\0') Append(*(u++));
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int written() { return static_cast<int>(cursor_ - start_); }
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   private:
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DestChar* start_;
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DestChar* cursor_;
347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DisallowHeapAllocation no_gc_;
348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <typename DestChar>
351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class NoExtendString : public NoExtend<DestChar> {
352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   public:
353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    NoExtendString(Handle<String> string, int required_length)
354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        : NoExtend<DestChar>(string, 0), string_(string) {
355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(string->length() >= required_length);
356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<String> Finalize() {
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<SeqString> string = Handle<SeqString>::cast(string_);
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int length = NoExtend<DestChar>::written();
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<String> result = SeqString::Truncate(string, length);
362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      string_ = Handle<String>();
363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return result;
364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   private:
367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<String> string_;
368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <typename DestChar>
371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class NoExtendBuilder : public NoExtend<DestChar> {
372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   public:
373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    NoExtendBuilder(IncrementalStringBuilder* builder, int required_length)
374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        : NoExtend<DestChar>(builder->current_part(), builder->current_index_),
375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          builder_(builder) {
376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(builder->CurrentPartCanFit(required_length));
377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ~NoExtendBuilder() {
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      builder_->current_index_ += NoExtend<DestChar>::written();
381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier   private:
384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    IncrementalStringBuilder* builder_;
385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Factory* factory() { return isolate_->factory(); }
389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(Handle<String> accumulator()) { return accumulator_; }
391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(void set_accumulator(Handle<String> string)) {
393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    *accumulator_.location() = *string;
394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(Handle<String> current_part()) { return current_part_; }
397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  INLINE(void set_current_part(Handle<String> string)) {
399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    *current_part_.location() = *string;
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Add the current part to the accumulator.
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Accumulate(Handle<String> new_part);
404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Finish the current part and allocate a new part.
406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Extend();
407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Shrink current part to the right size.
409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ShrinkCurrentPart() {
410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(current_index_ < part_length_);
411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    set_current_part(SeqString::Truncate(
412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Handle<SeqString>::cast(current_part()), current_index_));
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kInitialPartLength = 32;
416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kMaxPartLength = 16 * 1024;
417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kPartLengthGrowthFactor = 2;
418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Isolate* isolate_;
420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  String::Encoding encoding_;
421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool overflowed_;
422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int part_length_;
423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int current_index_;
424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<String> accumulator_;
425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<String> current_part_;
426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <typename SrcChar, typename DestChar>
430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid IncrementalStringBuilder::Append(SrcChar c) {
431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_EQ(encoding_ == String::ONE_BYTE_ENCODING, sizeof(DestChar) == 1);
432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (sizeof(DestChar) == 1) {
433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SeqOneByteString::cast(*current_part_)
435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        ->SeqOneByteStringSet(current_index_++, c);
436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding_);
438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SeqTwoByteString::cast(*current_part_)
439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        ->SeqTwoByteStringSet(current_index_++, c);
440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (current_index_ == part_length_) Extend();
442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif  // V8_STRING_BUILDER_H_
447