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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime/string-builder.h ('k') | src/string-builder.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/string-builder.h
diff --git a/src/runtime/string-builder.h b/src/string-builder.h
similarity index 62%
rename from src/runtime/string-builder.h
rename to src/string-builder.h
index 890b7f6be1bb0198c3681890991c29e142d42bf4..f64f679870daa00def5f22bb2306764b72a9bafd 100644
--- a/src/runtime/string-builder.h
+++ b/src/string-builder.h
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef V8_RUNTIME_STRING_BUILDER_H_
-#define V8_RUNTIME_STRING_BUILDER_H_
+#ifndef V8_STRING_BUILDER_H_
+#define V8_STRING_BUILDER_H_
+
+#include "src/v8.h"
namespace v8 {
namespace internal {
@@ -233,39 +235,7 @@ class ReplacementStringBuilder {
}
- MaybeHandle<String> ToString() {
- Isolate* isolate = heap_->isolate();
- if (array_builder_.length() == 0) {
- return isolate->factory()->empty_string();
- }
-
- Handle<String> joined_string;
- if (is_one_byte_) {
- Handle<SeqOneByteString> seq;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, seq,
- isolate->factory()->NewRawOneByteString(character_count_), String);
-
- DisallowHeapAllocation no_gc;
- uint8_t* char_buffer = seq->GetChars();
- StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
- array_builder_.length());
- joined_string = Handle<String>::cast(seq);
- } else {
- // Two-byte.
- Handle<SeqTwoByteString> seq;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, seq,
- isolate->factory()->NewRawTwoByteString(character_count_), String);
-
- DisallowHeapAllocation no_gc;
- uc16* char_buffer = seq->GetChars();
- StringBuilderConcatHelper(*subject_, char_buffer, *array_builder_.array(),
- array_builder_.length());
- joined_string = Handle<String>::cast(seq);
- }
- return joined_string;
- }
+ MaybeHandle<String> ToString();
void IncrementCharacterCount(int by) {
@@ -290,7 +260,171 @@ class ReplacementStringBuilder {
int character_count_;
bool is_one_byte_;
};
+
+
+class IncrementalStringBuilder {
+ public:
+ explicit IncrementalStringBuilder(Isolate* isolate);
+
+ INLINE(String::Encoding CurrentEncoding()) { return encoding_; }
+
+ template <typename SrcChar, typename DestChar>
+ INLINE(void Append(SrcChar c));
+
+ INLINE(void AppendCharacter(uint8_t c)) {
+ if (encoding_ == String::ONE_BYTE_ENCODING) {
+ Append<uint8_t, uint8_t>(c);
+ } else {
+ Append<uint8_t, uc16>(c);
+ }
+ }
+
+ INLINE(void AppendCString(const char* s)) {
+ const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
+ if (encoding_ == String::ONE_BYTE_ENCODING) {
+ while (*u != '\0') Append<uint8_t, uint8_t>(*(u++));
+ } else {
+ while (*u != '\0') Append<uint8_t, uc16>(*(u++));
+ }
+ }
+
+ INLINE(bool CurrentPartCanFit(int length)) {
+ return part_length_ - current_index_ > length;
+ }
+
+ void AppendString(Handle<String> string);
+
+ MaybeHandle<String> Finish();
+
+ // Change encoding to two-byte.
+ void ChangeEncoding() {
+ DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
+ ShrinkCurrentPart();
+ encoding_ = String::TWO_BYTE_ENCODING;
+ Extend();
+ }
+
+ template <typename DestChar>
+ class NoExtend {
+ public:
+ explicit NoExtend(Handle<String> string, int offset) {
+ DCHECK(string->IsSeqOneByteString() || string->IsSeqTwoByteString());
+ if (sizeof(DestChar) == 1) {
+ start_ = reinterpret_cast<DestChar*>(
+ Handle<SeqOneByteString>::cast(string)->GetChars() + offset);
+ } else {
+ start_ = reinterpret_cast<DestChar*>(
+ Handle<SeqTwoByteString>::cast(string)->GetChars() + offset);
+ }
+ cursor_ = start_;
+ }
+
+ INLINE(void Append(DestChar c)) { *(cursor_++) = c; }
+ INLINE(void AppendCString(const char* s)) {
+ const uint8_t* u = reinterpret_cast<const uint8_t*>(s);
+ while (*u != '\0') Append(*(u++));
+ }
+
+ int written() { return cursor_ - start_; }
+
+ private:
+ DestChar* start_;
+ DestChar* cursor_;
+ DisallowHeapAllocation no_gc_;
+ };
+
+ template <typename DestChar>
+ class NoExtendString : public NoExtend<DestChar> {
+ public:
+ NoExtendString(Handle<String> string, int required_length)
+ : NoExtend<DestChar>(string, 0), string_(string) {
+ DCHECK(string->length() >= required_length);
+ }
+
+ ~NoExtendString() {
+ Handle<SeqString> string = Handle<SeqString>::cast(string_);
+ int length = NoExtend<DestChar>::written();
+ *string_.location() = *SeqString::Truncate(string, length);
+ }
+
+ private:
+ Handle<String> string_;
+ };
+
+ template <typename DestChar>
+ class NoExtendBuilder : public NoExtend<DestChar> {
+ public:
+ NoExtendBuilder(IncrementalStringBuilder* builder, int required_length)
+ : NoExtend<DestChar>(builder->current_part(), builder->current_index_),
+ builder_(builder) {
+ DCHECK(builder->CurrentPartCanFit(required_length));
+ }
+
+ ~NoExtendBuilder() {
+ builder_->current_index_ += NoExtend<DestChar>::written();
+ }
+
+ private:
+ IncrementalStringBuilder* builder_;
+ };
+
+ private:
+ Factory* factory() { return isolate_->factory(); }
+
+ INLINE(Handle<String> accumulator()) { return accumulator_; }
+
+ INLINE(void set_accumulator(Handle<String> string)) {
+ *accumulator_.location() = *string;
+ }
+
+ INLINE(Handle<String> current_part()) { return current_part_; }
+
+ INLINE(void set_current_part(Handle<String> string)) {
+ *current_part_.location() = *string;
+ }
+
+ // Add the current part to the accumulator.
+ void Accumulate();
+
+ // Finish the current part and allocate a new part.
+ void Extend();
+
+ // Shrink current part to the right size.
+ void ShrinkCurrentPart() {
+ DCHECK(current_index_ < part_length_);
+ set_current_part(SeqString::Truncate(
+ Handle<SeqString>::cast(current_part()), current_index_));
+ }
+
+ static const int kInitialPartLength = 32;
+ static const int kMaxPartLength = 16 * 1024;
+ static const int kPartLengthGrowthFactor = 2;
+
+ Isolate* isolate_;
+ String::Encoding encoding_;
+ bool overflowed_;
+ int part_length_;
+ int current_index_;
+ Handle<String> accumulator_;
+ Handle<String> current_part_;
+};
+
+
+template <typename SrcChar, typename DestChar>
+void IncrementalStringBuilder::Append(SrcChar c) {
+ DCHECK_EQ(encoding_ == String::ONE_BYTE_ENCODING, sizeof(DestChar) == 1);
+ if (sizeof(DestChar) == 1) {
+ DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
+ SeqOneByteString::cast(*current_part_)
+ ->SeqOneByteStringSet(current_index_++, c);
+ } else {
+ DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding_);
+ SeqTwoByteString::cast(*current_part_)
+ ->SeqTwoByteStringSet(current_index_++, c);
+ }
+ if (current_index_ == part_length_) Extend();
+}
}
} // namespace v8::internal
-#endif // V8_RUNTIME_STRING_BUILDER_H_
+#endif // V8_STRING_BUILDER_H_
« 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