Index: src/json-stringifier.h |
diff --git a/src/json-stringifier.h b/src/json-stringifier.h |
index ad9ef3ddb71e86b17a9aa39caacecf94ebcaad81..418d4794595367f088e09cbb519d65209ff7bd96 100644 |
--- a/src/json-stringifier.h |
+++ b/src/json-stringifier.h |
@@ -41,6 +41,9 @@ class BasicJsonStringifier BASE_EMBEDDED { |
MaybeObject* Stringify(Handle<Object> object); |
+ INLINE(static MaybeObject* StringifyString(Isolate* isolate, |
+ Handle<String> object)); |
+ |
private: |
static const int kInitialPartLength = 32; |
static const int kMaxPartLength = 16 * 1024; |
@@ -84,6 +87,11 @@ class BasicJsonStringifier BASE_EMBEDDED { |
bool deferred_comma, |
bool deferred_key); |
+ template <typename StringType> |
+ INLINE(static MaybeObject* StringifyString_(Isolate* isolate, |
+ Handle<String> string, |
+ Handle<String> result)); |
+ |
// Entry point to serialize the object. |
INLINE(Result SerializeObject(Handle<Object> obj)) { |
return Serialize_<false>(obj, false, factory_->empty_string()); |
@@ -135,18 +143,18 @@ class BasicJsonStringifier BASE_EMBEDDED { |
void SerializeString(Handle<String> object); |
template <typename SrcChar, typename DestChar> |
- INLINE(void SerializeStringUnchecked_(const SrcChar* src, |
- DestChar* dest, |
- int length)); |
+ INLINE(static int SerializeStringUnchecked_(const SrcChar* src, |
+ DestChar* dest, |
+ int length)); |
template <bool is_ascii, typename Char> |
INLINE(void SerializeString_(Handle<String> string)); |
template <typename Char> |
- INLINE(bool DoNotEscape(Char c)); |
+ INLINE(static bool DoNotEscape(Char c)); |
template <typename Char> |
- INLINE(Vector<const Char> GetCharVector(Handle<String> string)); |
+ INLINE(static Vector<const Char> GetCharVector(Handle<String> string)); |
Result StackPush(Handle<Object> object); |
void StackPop(); |
@@ -244,15 +252,15 @@ const char* const BasicJsonStringifier::JsonEscapeTable = |
"\370\0 \371\0 \372\0 \373\0 " |
"\374\0 \375\0 \376\0 \377\0 "; |
+ |
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
: isolate_(isolate), current_index_(0), is_ascii_(true) { |
factory_ = isolate_->factory(); |
accumulator_store_ = Handle<JSValue>::cast( |
factory_->ToObject(factory_->empty_string())); |
part_length_ = kInitialPartLength; |
- current_part_ = factory_->NewRawOneByteString(kInitialPartLength); |
- tojson_string_ = |
- factory_->InternalizeOneByteString(STATIC_ASCII_VECTOR("toJSON")); |
+ current_part_ = factory_->NewRawOneByteString(part_length_); |
+ tojson_string_ = factory_->toJSON_string(); |
stack_ = factory_->NewJSArray(8); |
} |
@@ -275,6 +283,57 @@ MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { |
} |
+MaybeObject* BasicJsonStringifier::StringifyString(Isolate* isolate, |
+ Handle<String> object) { |
+ static const int kJsonQuoteWorstCaseBlowup = 6; |
+ static const int kSpaceForQuotes = 2; |
+ int worst_case_length = |
+ object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
+ |
+ if (worst_case_length > 32 * KB) { // Slow path if too large. |
+ BasicJsonStringifier stringifier(isolate); |
+ return stringifier.Stringify(object); |
+ } |
+ |
+ object = FlattenGetString(object); |
+ if (object->IsSeqOneByteString()) { |
+ return StringifyString_<SeqOneByteString>( |
+ isolate, |
+ object, |
+ isolate->factory()->NewRawOneByteString(worst_case_length)); |
+ } else { |
+ return StringifyString_<SeqTwoByteString>( |
+ isolate, |
+ object, |
+ isolate->factory()->NewRawTwoByteString(worst_case_length)); |
+ } |
+} |
+ |
+ |
+template <typename StringType> |
+MaybeObject* BasicJsonStringifier::StringifyString_(Isolate* isolate, |
+ Handle<String> string, |
+ Handle<String> result) { |
+ AssertNoAllocation no_allocation; |
+ int final_size = 0; |
+ StringType* dest = StringType::cast(*result); |
+ dest->Set(final_size++, '\"'); |
+ final_size += SerializeStringUnchecked_(StringType::cast(*string)->GetChars(), |
+ dest->GetChars() + 1, |
+ string->length()); |
+ dest->Set(final_size++, '\"'); |
+ if (isolate->heap()->InNewSpace(*result)) { |
+ // In new space, simply lower the allocation top to fit the actual size. |
+ isolate->heap()->new_space()->ShrinkStringAtAllocationBoundary<StringType>( |
+ *result, final_size); |
+ return *result; |
+ } else { |
+ // Not in new space, need to fill the wasted space with filler objects. |
+ return SeqString::cast(*result)->Truncate(final_size); |
+ } |
+} |
+ |
+ |
template <bool is_ascii, typename Char> |
void BasicJsonStringifier::Append_(Char c) { |
if (is_ascii) { |
@@ -667,10 +726,9 @@ void BasicJsonStringifier::ChangeEncoding() { |
template <typename SrcChar, typename DestChar> |
-void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
- DestChar* dest, |
- int length) { |
- dest += current_index_; |
+int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
+ DestChar* dest, |
+ int length) { |
DestChar* dest_start = dest; |
// Assert that uc16 character is not truncated down to 8 bit. |
@@ -688,7 +746,7 @@ void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
} |
} |
- current_index_ += static_cast<int>(dest - dest_start); |
+ return static_cast<int>(dest - dest_start); |
} |
@@ -705,14 +763,14 @@ void BasicJsonStringifier::SerializeString_(Handle<String> string) { |
AssertNoAllocation no_allocation; |
Vector<const Char> vector = GetCharVector<Char>(string); |
if (is_ascii) { |
- SerializeStringUnchecked_( |
+ current_index_ += SerializeStringUnchecked_( |
vector.start(), |
- SeqOneByteString::cast(*current_part_)->GetChars(), |
+ SeqOneByteString::cast(*current_part_)->GetChars() + current_index_, |
length); |
} else { |
- SerializeStringUnchecked_( |
+ current_index_ += SerializeStringUnchecked_( |
vector.start(), |
- SeqTwoByteString::cast(*current_part_)->GetChars(), |
+ SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_, |
length); |
} |
} else { |