Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: src/string-builder.h

Issue 713223002: Abstract string building in JSON-stringifier into IncrementalStringBuilder. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime/string-builder.h ('k') | src/string-builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_RUNTIME_STRING_BUILDER_H_ 5 #ifndef V8_STRING_BUILDER_H_
6 #define V8_RUNTIME_STRING_BUILDER_H_ 6 #define V8_STRING_BUILDER_H_
7
8 #include "src/v8.h"
7 9
8 namespace v8 { 10 namespace v8 {
9 namespace internal { 11 namespace internal {
10 12
11 const int kStringBuilderConcatHelperLengthBits = 11; 13 const int kStringBuilderConcatHelperLengthBits = 11;
12 const int kStringBuilderConcatHelperPositionBits = 19; 14 const int kStringBuilderConcatHelperPositionBits = 19;
13 15
14 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits> 16 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
15 StringBuilderSubstringLength; 17 StringBuilderSubstringLength;
16 typedef BitField<int, kStringBuilderConcatHelperLengthBits, 18 typedef BitField<int, kStringBuilderConcatHelperLengthBits,
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 int length = string->length(); 228 int length = string->length();
227 DCHECK(length > 0); 229 DCHECK(length > 0);
228 AddElement(*string); 230 AddElement(*string);
229 if (!string->IsOneByteRepresentation()) { 231 if (!string->IsOneByteRepresentation()) {
230 is_one_byte_ = false; 232 is_one_byte_ = false;
231 } 233 }
232 IncrementCharacterCount(length); 234 IncrementCharacterCount(length);
233 } 235 }
234 236
235 237
236 MaybeHandle<String> ToString() { 238 MaybeHandle<String> ToString();
237 Isolate* isolate = heap_->isolate();
238 if (array_builder_.length() == 0) {
239 return isolate->factory()->empty_string();
240 }
241
242 Handle<String> joined_string;
243 if (is_one_byte_) {
244 Handle<SeqOneByteString> seq;
245 ASSIGN_RETURN_ON_EXCEPTION(
246 isolate, seq,
247 isolate->factory()->NewRawOneByteString(character_count_), String);
248
249 DisallowHeapAllocation no_gc;
250 uint8_t* char_buffer = seq->GetChars();
251 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
252 array_builder_.length());
253 joined_string = Handle<String>::cast(seq);
254 } else {
255 // Two-byte.
256 Handle<SeqTwoByteString> seq;
257 ASSIGN_RETURN_ON_EXCEPTION(
258 isolate, seq,
259 isolate->factory()->NewRawTwoByteString(character_count_), String);
260
261 DisallowHeapAllocation no_gc;
262 uc16* char_buffer = seq->GetChars();
263 StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
264 array_builder_.length());
265 joined_string = Handle<String>::cast(seq);
266 }
267 return joined_string;
268 }
269 239
270 240
271 void IncrementCharacterCount(int by) { 241 void IncrementCharacterCount(int by) {
272 if (character_count_ > String::kMaxLength - by) { 242 if (character_count_ > String::kMaxLength - by) {
273 STATIC_ASSERT(String::kMaxLength < kMaxInt); 243 STATIC_ASSERT(String::kMaxLength < kMaxInt);
274 character_count_ = kMaxInt; 244 character_count_ = kMaxInt;
275 } else { 245 } else {
276 character_count_ += by; 246 character_count_ += by;
277 } 247 }
278 } 248 }
279 249
280 private: 250 private:
281 void AddElement(Object* element) { 251 void AddElement(Object* element) {
282 DCHECK(element->IsSmi() || element->IsString()); 252 DCHECK(element->IsSmi() || element->IsString());
283 DCHECK(array_builder_.capacity() > array_builder_.length()); 253 DCHECK(array_builder_.capacity() > array_builder_.length());
284 array_builder_.Add(element); 254 array_builder_.Add(element);
285 } 255 }
286 256
287 Heap* heap_; 257 Heap* heap_;
288 FixedArrayBuilder array_builder_; 258 FixedArrayBuilder array_builder_;
289 Handle<String> subject_; 259 Handle<String> subject_;
290 int character_count_; 260 int character_count_;
291 bool is_one_byte_; 261 bool is_one_byte_;
292 }; 262 };
263
264
265 class IncrementalStringBuilder {
266 public:
267 explicit IncrementalStringBuilder(Isolate* isolate);
268
269 INLINE(String::Encoding CurrentEncoding()) { return encoding_; }
270
271 template <typename SrcChar, typename DestChar>
272 INLINE(void Append(SrcChar c));
273
274 INLINE(void AppendCharacter(uint8_t c)) {
275 if (encoding_ == String::ONE_BYTE_ENCODING) {
276 Append<uint8_t, uint8_t>(c);
277 } else {
278 Append<uint8_t, uc16>(c);
279 }
280 }
281
282 INLINE(void AppendCString(const char* s)) {
283 const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
284 if (encoding_ == String::ONE_BYTE_ENCODING) {
285 while (*u != '\0') Append<uint8_t, uint8_t>(*(u++));
286 } else {
287 while (*u != '\0') Append<uint8_t, uc16>(*(u++));
288 }
289 }
290
291 INLINE(bool CurrentPartCanFit(int length)) {
292 return part_length_ - current_index_ > length;
293 }
294
295 void AppendString(Handle<String> string);
296
297 MaybeHandle<String> Finish();
298
299 // Change encoding to two-byte.
300 void ChangeEncoding() {
301 DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
302 ShrinkCurrentPart();
303 encoding_ = String::TWO_BYTE_ENCODING;
304 Extend();
305 }
306
307 template <typename DestChar>
308 class NoExtend {
309 public:
310 explicit NoExtend(Handle<String> string, int offset) {
311 DCHECK(string->IsSeqOneByteString() || string->IsSeqTwoByteString());
312 if (sizeof(DestChar) == 1) {
313 start_ = reinterpret_cast<DestChar*>(
314 Handle<SeqOneByteString>::cast(string)->GetChars() + offset);
315 } else {
316 start_ = reinterpret_cast<DestChar*>(
317 Handle<SeqTwoByteString>::cast(string)->GetChars() + offset);
318 }
319 cursor_ = start_;
320 }
321
322 INLINE(void Append(DestChar c)) { *(cursor_++) = c; }
323 INLINE(void AppendCString(const char* s)) {
324 const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
325 while (*u != '\0') Append(*(u++));
326 }
327
328 int written() { return cursor_ - start_; }
329
330 private:
331 DestChar* start_;
332 DestChar* cursor_;
333 DisallowHeapAllocation no_gc_;
334 };
335
336 template <typename DestChar>
337 class NoExtendString : public NoExtend<DestChar> {
338 public:
339 NoExtendString(Handle<String> string, int required_length)
340 : NoExtend<DestChar>(string, 0), string_(string) {
341 DCHECK(string->length() >= required_length);
342 }
343
344 ~NoExtendString() {
345 Handle<SeqString> string = Handle<SeqString>::cast(string_);
346 int length = NoExtend<DestChar>::written();
347 *string_.location() = *SeqString::Truncate(string, length);
348 }
349
350 private:
351 Handle<String> string_;
352 };
353
354 template <typename DestChar>
355 class NoExtendBuilder : public NoExtend<DestChar> {
356 public:
357 NoExtendBuilder(IncrementalStringBuilder* builder, int required_length)
358 : NoExtend<DestChar>(builder->current_part(), builder->current_index_),
359 builder_(builder) {
360 DCHECK(builder->CurrentPartCanFit(required_length));
361 }
362
363 ~NoExtendBuilder() {
364 builder_->current_index_ += NoExtend<DestChar>::written();
365 }
366
367 private:
368 IncrementalStringBuilder* builder_;
369 };
370
371 private:
372 Factory* factory() { return isolate_->factory(); }
373
374 INLINE(Handle<String> accumulator()) { return accumulator_; }
375
376 INLINE(void set_accumulator(Handle<String> string)) {
377 *accumulator_.location() = *string;
378 }
379
380 INLINE(Handle<String> current_part()) { return current_part_; }
381
382 INLINE(void set_current_part(Handle<String> string)) {
383 *current_part_.location() = *string;
384 }
385
386 // Add the current part to the accumulator.
387 void Accumulate();
388
389 // Finish the current part and allocate a new part.
390 void Extend();
391
392 // Shrink current part to the right size.
393 void ShrinkCurrentPart() {
394 DCHECK(current_index_ < part_length_);
395 set_current_part(SeqString::Truncate(
396 Handle<SeqString>::cast(current_part()), current_index_));
397 }
398
399 static const int kInitialPartLength = 32;
400 static const int kMaxPartLength = 16 * 1024;
401 static const int kPartLengthGrowthFactor = 2;
402
403 Isolate* isolate_;
404 String::Encoding encoding_;
405 bool overflowed_;
406 int part_length_;
407 int current_index_;
408 Handle<String> accumulator_;
409 Handle<String> current_part_;
410 };
411
412
413 template <typename SrcChar, typename DestChar>
414 void IncrementalStringBuilder::Append(SrcChar c) {
415 DCHECK_EQ(encoding_ == String::ONE_BYTE_ENCODING, sizeof(DestChar) == 1);
416 if (sizeof(DestChar) == 1) {
417 DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
418 SeqOneByteString::cast(*current_part_)
419 ->SeqOneByteStringSet(current_index_++, c);
420 } else {
421 DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding_);
422 SeqTwoByteString::cast(*current_part_)
423 ->SeqTwoByteStringSet(current_index_++, c);
424 }
425 if (current_index_ == part_length_) Extend();
426 }
293 } 427 }
294 } // namespace v8::internal 428 } // namespace v8::internal
295 429
296 #endif // V8_RUNTIME_STRING_BUILDER_H_ 430 #endif // V8_STRING_BUILDER_H_
OLDNEW
« no previous file with comments | « src/runtime/string-builder.h ('k') | src/string-builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698