Index: src/json-stringifier.h |
diff --git a/src/json-stringifier.h b/src/json-stringifier.h |
index f95e8c4f68eb0c935e0ba1477da15d83d62d0421..43edfd136022cdf1a42fc4905adcce9f7d6ff806 100644 |
--- a/src/json-stringifier.h |
+++ b/src/json-stringifier.h |
@@ -42,7 +42,9 @@ class BasicJsonStringifier BASE_EMBEDDED { |
MaybeObject* Stringify(Handle<Object> object); |
private: |
- static const int kPartLength = 8 * 1024; |
+ static const int kInitialPartLength = 32; |
+ static const int kMaxPartLength = 16 * 1024; |
+ static const int kPartLengthGrowthFactor = 2; |
static const int kStackLimit = 8 * 1024; |
enum Result { UNCHANGED, SUCCESS, BAILOUT, CIRCULAR, STACK_OVERFLOW }; |
@@ -130,12 +132,23 @@ class BasicJsonStringifier BASE_EMBEDDED { |
INLINE(Result StackPush(Handle<Object> object)); |
INLINE(void StackPop()); |
+ INLINE(Handle<String> accumulator()) { |
+ return Handle<String>(String::cast(accumulator_store_->value())); |
+ } |
+ |
+ INLINE(void set_accumulator(Handle<String> string)) { |
+ return accumulator_store_->set_value(*string); |
+ } |
+ |
Isolate* isolate_; |
- Handle<String> accumulator_; |
+ // We use a value wrapper for the string accumulator to keep the |
+ // (indirect) handle to it in the outermost handle scope. |
+ Handle<JSValue> accumulator_store_; |
Handle<String> current_part_; |
Handle<String> tojson_symbol_; |
Handle<JSArray> stack_; |
int current_index_; |
+ int part_length_; |
bool is_ascii_; |
static const int kJsonQuotesCharactersPerEntry = 8; |
@@ -180,9 +193,11 @@ const char* const BasicJsonStringifier::JsonQuotes = |
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
: isolate_(isolate), current_index_(0), is_ascii_(true) { |
- accumulator_ = isolate_->factory()->empty_string(); |
+ accumulator_store_ = Handle<JSValue>::cast( |
+ isolate_->factory()->ToObject(isolate_->factory()->empty_string())); |
+ part_length_ = kInitialPartLength; |
current_part_ = |
- isolate_->factory()->NewRawAsciiString(kPartLength); |
+ isolate_->factory()->NewRawAsciiString(kInitialPartLength); |
tojson_symbol_ = isolate_->factory()->LookupAsciiSymbol("toJSON"); |
stack_ = isolate_->factory()->NewJSArray(8); |
} |
@@ -192,7 +207,7 @@ MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { |
switch (Serialize(object)) { |
case SUCCESS: |
ShrinkCurrentPart(); |
- return *isolate_->factory()->NewConsString(accumulator_, current_part_); |
+ return *isolate_->factory()->NewConsString(accumulator(), current_part_); |
case UNCHANGED: |
return isolate_->heap()->undefined_value(); |
case CIRCULAR: |
@@ -215,7 +230,7 @@ void BasicJsonStringifier::Append_(Char c) { |
SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( |
current_index_++, c); |
} |
- if (current_index_ == kPartLength) Extend<is_ascii>(); |
+ if (current_index_ == part_length_) Extend<is_ascii>(); |
} |
@@ -228,7 +243,7 @@ void BasicJsonStringifier::AppendUnchecked_(Char c) { |
SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( |
current_index_++, c); |
} |
- ASSERT(current_index_ < kPartLength); |
+ ASSERT(current_index_ < part_length_); |
} |
@@ -403,6 +418,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( |
BasicJsonStringifier::Result BasicJsonStringifier::SerializeArray( |
Handle<JSArray> object) { |
+ HandleScope handle_scope(isolate_); |
if (StackPush(object) == CIRCULAR) return CIRCULAR; |
int length = Smi::cast(object->length())->value(); |
Append('['); |
@@ -460,12 +476,14 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeArray( |
} |
Append(']'); |
StackPop(); |
+ current_part_ = handle_scope.CloseAndEscape(current_part_); |
return SUCCESS; |
} |
BasicJsonStringifier::Result BasicJsonStringifier::SerializeObject( |
Handle<JSObject> object) { |
+ HandleScope handle_scope(isolate_); |
Result stack_push = StackPush(object); |
if (stack_push != SUCCESS) return stack_push; |
if (object->IsJSGlobalProxy()) return BAILOUT; |
@@ -502,12 +520,13 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeObject( |
} |
Append('}'); |
StackPop(); |
+ current_part_ = handle_scope.CloseAndEscape(current_part_); |
return SUCCESS; |
} |
void BasicJsonStringifier::ShrinkCurrentPart() { |
- ASSERT(current_index_ < kPartLength); |
+ ASSERT(current_index_ < part_length_); |
if (current_index_ == 0) { |
current_part_ = isolate_->factory()->empty_string(); |
return; |
@@ -515,10 +534,10 @@ void BasicJsonStringifier::ShrinkCurrentPart() { |
int string_size, allocated_string_size; |
if (is_ascii_) { |
- allocated_string_size = SeqAsciiString::SizeFor(kPartLength); |
+ allocated_string_size = SeqAsciiString::SizeFor(part_length_); |
string_size = SeqAsciiString::SizeFor(current_index_); |
} else { |
- allocated_string_size = SeqTwoByteString::SizeFor(kPartLength); |
+ allocated_string_size = SeqTwoByteString::SizeFor(part_length_); |
string_size = SeqTwoByteString::SizeFor(current_index_); |
} |
@@ -538,14 +557,17 @@ void BasicJsonStringifier::ShrinkCurrentPart() { |
template <bool is_ascii> |
void BasicJsonStringifier::Extend() { |
- accumulator_ = |
- isolate_->factory()->NewConsString(accumulator_, current_part_); |
+ set_accumulator( |
+ isolate_->factory()->NewConsString(accumulator(), current_part_)); |
+ if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { |
+ part_length_ *= kPartLengthGrowthFactor; |
+ } |
if (is_ascii) { |
current_part_ = |
- isolate_->factory()->NewRawAsciiString(kPartLength); |
+ isolate_->factory()->NewRawAsciiString(part_length_); |
} else { |
current_part_ = |
- isolate_->factory()->NewRawTwoByteString(kPartLength); |
+ isolate_->factory()->NewRawTwoByteString(part_length_); |
} |
current_index_ = 0; |
} |
@@ -553,10 +575,10 @@ void BasicJsonStringifier::Extend() { |
void BasicJsonStringifier::ChangeEncoding() { |
ShrinkCurrentPart(); |
- accumulator_ = isolate_->factory()->NewConsString(accumulator_, |
- current_part_); |
+ set_accumulator( |
+ isolate_->factory()->NewConsString(accumulator(), current_part_)); |
current_part_ = |
- isolate_->factory()->NewRawTwoByteString(kPartLength); |
+ isolate_->factory()->NewRawTwoByteString(part_length_); |
current_index_ = 0; |
is_ascii_ = false; |
} |
@@ -565,7 +587,7 @@ void BasicJsonStringifier::ChangeEncoding() { |
template <bool is_ascii, typename Char> |
void BasicJsonStringifier::SerializeString_(Vector<const Char> vector) { |
int length = vector.length(); |
- if (current_index_ + (length << 3) < (kPartLength - 2)) { |
+ if (current_index_ + (length << 3) < (part_length_ - 2)) { |
AppendUnchecked_<is_ascii, char>('"'); |
for (int i = 0; i < length; i++) { |
Char c = vector[i]; |