| 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 {
|
|
|