| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 namespace v8 { | 35 namespace v8 { |
| 36 namespace internal { | 36 namespace internal { |
| 37 | 37 |
| 38 class BasicJsonStringifier BASE_EMBEDDED { | 38 class BasicJsonStringifier BASE_EMBEDDED { |
| 39 public: | 39 public: |
| 40 explicit BasicJsonStringifier(Isolate* isolate); | 40 explicit BasicJsonStringifier(Isolate* isolate); |
| 41 | 41 |
| 42 MaybeObject* Stringify(Handle<Object> object); | 42 MaybeObject* Stringify(Handle<Object> object); |
| 43 | 43 |
| 44 INLINE(static MaybeObject* StringifyString(Isolate* isolate, | |
| 45 Handle<String> object)); | |
| 46 | |
| 47 private: | 44 private: |
| 48 static const int kInitialPartLength = 32; | 45 static const int kInitialPartLength = 32; |
| 49 static const int kMaxPartLength = 16 * 1024; | 46 static const int kMaxPartLength = 16 * 1024; |
| 50 static const int kPartLengthGrowthFactor = 2; | 47 static const int kPartLengthGrowthFactor = 2; |
| 51 | 48 |
| 52 enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW }; | 49 enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW }; |
| 53 | 50 |
| 54 void Extend(); | 51 void Extend(); |
| 55 | 52 |
| 56 void ChangeEncoding(); | 53 void ChangeEncoding(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 80 } | 77 } |
| 81 | 78 |
| 82 Handle<Object> ApplyToJsonFunction(Handle<Object> object, | 79 Handle<Object> ApplyToJsonFunction(Handle<Object> object, |
| 83 Handle<Object> key); | 80 Handle<Object> key); |
| 84 | 81 |
| 85 Result SerializeGeneric(Handle<Object> object, | 82 Result SerializeGeneric(Handle<Object> object, |
| 86 Handle<Object> key, | 83 Handle<Object> key, |
| 87 bool deferred_comma, | 84 bool deferred_comma, |
| 88 bool deferred_key); | 85 bool deferred_key); |
| 89 | 86 |
| 90 template <typename StringType> | |
| 91 INLINE(static MaybeObject* StringifyString_(Isolate* isolate, | |
| 92 Handle<String> string, | |
| 93 Handle<String> result)); | |
| 94 | |
| 95 // Entry point to serialize the object. | 87 // Entry point to serialize the object. |
| 96 INLINE(Result SerializeObject(Handle<Object> obj)) { | 88 INLINE(Result SerializeObject(Handle<Object> obj)) { |
| 97 return Serialize_<false>(obj, false, factory_->empty_string()); | 89 return Serialize_<false>(obj, false, factory_->empty_string()); |
| 98 } | 90 } |
| 99 | 91 |
| 100 // Serialize an array element. | 92 // Serialize an array element. |
| 101 // The index may serve as argument for the toJSON function. | 93 // The index may serve as argument for the toJSON function. |
| 102 INLINE(Result SerializeElement(Isolate* isolate, | 94 INLINE(Result SerializeElement(Isolate* isolate, |
| 103 Handle<Object> object, | 95 Handle<Object> object, |
| 104 int i)) { | 96 int i)) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 Result SerializeJSValue(Handle<JSValue> object); | 128 Result SerializeJSValue(Handle<JSValue> object); |
| 137 | 129 |
| 138 INLINE(Result SerializeJSArray(Handle<JSArray> object)); | 130 INLINE(Result SerializeJSArray(Handle<JSArray> object)); |
| 139 INLINE(Result SerializeJSObject(Handle<JSObject> object)); | 131 INLINE(Result SerializeJSObject(Handle<JSObject> object)); |
| 140 | 132 |
| 141 Result SerializeJSArraySlow(Handle<JSArray> object, int length); | 133 Result SerializeJSArraySlow(Handle<JSArray> object, int length); |
| 142 | 134 |
| 143 void SerializeString(Handle<String> object); | 135 void SerializeString(Handle<String> object); |
| 144 | 136 |
| 145 template <typename SrcChar, typename DestChar> | 137 template <typename SrcChar, typename DestChar> |
| 146 INLINE(static int SerializeStringUnchecked_(const SrcChar* src, | 138 INLINE(void SerializeStringUnchecked_(const SrcChar* src, |
| 147 DestChar* dest, | 139 DestChar* dest, |
| 148 int length)); | 140 int length)); |
| 149 | 141 |
| 150 template <bool is_ascii, typename Char> | 142 template <bool is_ascii, typename Char> |
| 151 INLINE(void SerializeString_(Handle<String> string)); | 143 INLINE(void SerializeString_(Handle<String> string)); |
| 152 | 144 |
| 153 template <typename Char> | 145 template <typename Char> |
| 154 INLINE(static bool DoNotEscape(Char c)); | 146 INLINE(bool DoNotEscape(Char c)); |
| 155 | 147 |
| 156 template <typename Char> | 148 template <typename Char> |
| 157 INLINE(static Vector<const Char> GetCharVector(Handle<String> string)); | 149 INLINE(Vector<const Char> GetCharVector(Handle<String> string)); |
| 158 | 150 |
| 159 Result StackPush(Handle<Object> object); | 151 Result StackPush(Handle<Object> object); |
| 160 void StackPop(); | 152 void StackPop(); |
| 161 | 153 |
| 162 INLINE(Handle<String> accumulator()) { | 154 INLINE(Handle<String> accumulator()) { |
| 163 return Handle<String>(String::cast(accumulator_store_->value()), isolate_); | 155 return Handle<String>(String::cast(accumulator_store_->value()), isolate_); |
| 164 } | 156 } |
| 165 | 157 |
| 166 INLINE(void set_accumulator(Handle<String> string)) { | 158 INLINE(void set_accumulator(Handle<String> string)) { |
| 167 return accumulator_store_->set_value(*string); | 159 return accumulator_store_->set_value(*string); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 "\334\0 \335\0 \336\0 \337\0 " | 237 "\334\0 \335\0 \336\0 \337\0 " |
| 246 "\340\0 \341\0 \342\0 \343\0 " | 238 "\340\0 \341\0 \342\0 \343\0 " |
| 247 "\344\0 \345\0 \346\0 \347\0 " | 239 "\344\0 \345\0 \346\0 \347\0 " |
| 248 "\350\0 \351\0 \352\0 \353\0 " | 240 "\350\0 \351\0 \352\0 \353\0 " |
| 249 "\354\0 \355\0 \356\0 \357\0 " | 241 "\354\0 \355\0 \356\0 \357\0 " |
| 250 "\360\0 \361\0 \362\0 \363\0 " | 242 "\360\0 \361\0 \362\0 \363\0 " |
| 251 "\364\0 \365\0 \366\0 \367\0 " | 243 "\364\0 \365\0 \366\0 \367\0 " |
| 252 "\370\0 \371\0 \372\0 \373\0 " | 244 "\370\0 \371\0 \372\0 \373\0 " |
| 253 "\374\0 \375\0 \376\0 \377\0 "; | 245 "\374\0 \375\0 \376\0 \377\0 "; |
| 254 | 246 |
| 255 | |
| 256 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) | 247 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
| 257 : isolate_(isolate), current_index_(0), is_ascii_(true) { | 248 : isolate_(isolate), current_index_(0), is_ascii_(true) { |
| 258 factory_ = isolate_->factory(); | 249 factory_ = isolate_->factory(); |
| 259 accumulator_store_ = Handle<JSValue>::cast( | 250 accumulator_store_ = Handle<JSValue>::cast( |
| 260 factory_->ToObject(factory_->empty_string())); | 251 factory_->ToObject(factory_->empty_string())); |
| 261 part_length_ = kInitialPartLength; | 252 part_length_ = kInitialPartLength; |
| 262 current_part_ = factory_->NewRawOneByteString(part_length_); | 253 current_part_ = factory_->NewRawOneByteString(kInitialPartLength); |
| 263 tojson_string_ = factory_->toJSON_string(); | 254 tojson_string_ = |
| 255 factory_->InternalizeOneByteString(STATIC_ASCII_VECTOR("toJSON")); |
| 264 stack_ = factory_->NewJSArray(8); | 256 stack_ = factory_->NewJSArray(8); |
| 265 } | 257 } |
| 266 | 258 |
| 267 | 259 |
| 268 MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { | 260 MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { |
| 269 switch (SerializeObject(object)) { | 261 switch (SerializeObject(object)) { |
| 270 case UNCHANGED: | 262 case UNCHANGED: |
| 271 return isolate_->heap()->undefined_value(); | 263 return isolate_->heap()->undefined_value(); |
| 272 case SUCCESS: | 264 case SUCCESS: |
| 273 ShrinkCurrentPart(); | 265 ShrinkCurrentPart(); |
| 274 return *factory_->NewConsString(accumulator(), current_part_); | 266 return *factory_->NewConsString(accumulator(), current_part_); |
| 275 case CIRCULAR: | 267 case CIRCULAR: |
| 276 return isolate_->Throw(*factory_->NewTypeError( | 268 return isolate_->Throw(*factory_->NewTypeError( |
| 277 "circular_structure", HandleVector<Object>(NULL, 0))); | 269 "circular_structure", HandleVector<Object>(NULL, 0))); |
| 278 case STACK_OVERFLOW: | 270 case STACK_OVERFLOW: |
| 279 return isolate_->StackOverflow(); | 271 return isolate_->StackOverflow(); |
| 280 default: | 272 default: |
| 281 return Failure::Exception(); | 273 return Failure::Exception(); |
| 282 } | 274 } |
| 283 } | 275 } |
| 284 | 276 |
| 285 | 277 |
| 286 MaybeObject* BasicJsonStringifier::StringifyString(Isolate* isolate, | |
| 287 Handle<String> object) { | |
| 288 static const int kJsonQuoteWorstCaseBlowup = 6; | |
| 289 static const int kSpaceForQuotes = 2; | |
| 290 int worst_case_length = | |
| 291 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | |
| 292 | |
| 293 if (worst_case_length > 32 * KB) { // Slow path if too large. | |
| 294 BasicJsonStringifier stringifier(isolate); | |
| 295 return stringifier.Stringify(object); | |
| 296 } | |
| 297 | |
| 298 object = FlattenGetString(object); | |
| 299 if (object->IsSeqOneByteString()) { | |
| 300 return StringifyString_<SeqOneByteString>( | |
| 301 isolate, | |
| 302 object, | |
| 303 isolate->factory()->NewRawOneByteString(worst_case_length)); | |
| 304 } else { | |
| 305 return StringifyString_<SeqTwoByteString>( | |
| 306 isolate, | |
| 307 object, | |
| 308 isolate->factory()->NewRawTwoByteString(worst_case_length)); | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 | |
| 313 template <typename StringType> | |
| 314 MaybeObject* BasicJsonStringifier::StringifyString_(Isolate* isolate, | |
| 315 Handle<String> string, | |
| 316 Handle<String> result) { | |
| 317 AssertNoAllocation no_allocation; | |
| 318 int final_size = 0; | |
| 319 StringType* dest = StringType::cast(*result); | |
| 320 dest->Set(final_size++, '\"'); | |
| 321 final_size += SerializeStringUnchecked_(StringType::cast(*string)->GetChars(), | |
| 322 dest->GetChars() + 1, | |
| 323 string->length()); | |
| 324 dest->Set(final_size++, '\"'); | |
| 325 if (isolate->heap()->InNewSpace(*result)) { | |
| 326 // In new space, simply lower the allocation top to fit the actual size. | |
| 327 isolate->heap()->new_space()->ShrinkStringAtAllocationBoundary<StringType>( | |
| 328 *result, final_size); | |
| 329 return *result; | |
| 330 } else { | |
| 331 // Not in new space, need to fill the wasted space with filler objects. | |
| 332 return SeqString::cast(*result)->Truncate(final_size); | |
| 333 } | |
| 334 } | |
| 335 | |
| 336 | |
| 337 template <bool is_ascii, typename Char> | 278 template <bool is_ascii, typename Char> |
| 338 void BasicJsonStringifier::Append_(Char c) { | 279 void BasicJsonStringifier::Append_(Char c) { |
| 339 if (is_ascii) { | 280 if (is_ascii) { |
| 340 SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet( | 281 SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet( |
| 341 current_index_++, c); | 282 current_index_++, c); |
| 342 } else { | 283 } else { |
| 343 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( | 284 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( |
| 344 current_index_++, c); | 285 current_index_++, c); |
| 345 } | 286 } |
| 346 if (current_index_ == part_length_) Extend(); | 287 if (current_index_ == part_length_) Extend(); |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 void BasicJsonStringifier::ChangeEncoding() { | 660 void BasicJsonStringifier::ChangeEncoding() { |
| 720 ShrinkCurrentPart(); | 661 ShrinkCurrentPart(); |
| 721 set_accumulator(factory_->NewConsString(accumulator(), current_part_)); | 662 set_accumulator(factory_->NewConsString(accumulator(), current_part_)); |
| 722 current_part_ = factory_->NewRawTwoByteString(part_length_); | 663 current_part_ = factory_->NewRawTwoByteString(part_length_); |
| 723 current_index_ = 0; | 664 current_index_ = 0; |
| 724 is_ascii_ = false; | 665 is_ascii_ = false; |
| 725 } | 666 } |
| 726 | 667 |
| 727 | 668 |
| 728 template <typename SrcChar, typename DestChar> | 669 template <typename SrcChar, typename DestChar> |
| 729 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, | 670 void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
| 730 DestChar* dest, | 671 DestChar* dest, |
| 731 int length) { | 672 int length) { |
| 673 dest += current_index_; |
| 732 DestChar* dest_start = dest; | 674 DestChar* dest_start = dest; |
| 733 | 675 |
| 734 // Assert that uc16 character is not truncated down to 8 bit. | 676 // Assert that uc16 character is not truncated down to 8 bit. |
| 735 // The <uc16, char> version of this method must not be called. | 677 // The <uc16, char> version of this method must not be called. |
| 736 ASSERT(sizeof(*dest) >= sizeof(*src)); | 678 ASSERT(sizeof(*dest) >= sizeof(*src)); |
| 737 | 679 |
| 738 for (int i = 0; i < length; i++) { | 680 for (int i = 0; i < length; i++) { |
| 739 SrcChar c = src[i]; | 681 SrcChar c = src[i]; |
| 740 if (DoNotEscape(c)) { | 682 if (DoNotEscape(c)) { |
| 741 *(dest++) = static_cast<DestChar>(c); | 683 *(dest++) = static_cast<DestChar>(c); |
| 742 } else { | 684 } else { |
| 743 const uint8_t* chars = reinterpret_cast<const uint8_t*>( | 685 const uint8_t* chars = reinterpret_cast<const uint8_t*>( |
| 744 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 686 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
| 745 while (*chars != '\0') *(dest++) = *(chars++); | 687 while (*chars != '\0') *(dest++) = *(chars++); |
| 746 } | 688 } |
| 747 } | 689 } |
| 748 | 690 |
| 749 return static_cast<int>(dest - dest_start); | 691 current_index_ += static_cast<int>(dest - dest_start); |
| 750 } | 692 } |
| 751 | 693 |
| 752 | 694 |
| 753 template <bool is_ascii, typename Char> | 695 template <bool is_ascii, typename Char> |
| 754 void BasicJsonStringifier::SerializeString_(Handle<String> string) { | 696 void BasicJsonStringifier::SerializeString_(Handle<String> string) { |
| 755 int length = string->length(); | 697 int length = string->length(); |
| 756 Append_<is_ascii, char>('"'); | 698 Append_<is_ascii, char>('"'); |
| 757 // We make a rough estimate to find out if the current string can be | 699 // We make a rough estimate to find out if the current string can be |
| 758 // serialized without allocating a new string part. The worst case length of | 700 // serialized without allocating a new string part. The worst case length of |
| 759 // an escaped character is 6. Shifting the remainin string length right by 3 | 701 // an escaped character is 6. Shifting the remainin string length right by 3 |
| 760 // is a more pessimistic estimate, but faster to calculate. | 702 // is a more pessimistic estimate, but faster to calculate. |
| 761 | 703 |
| 762 if (((part_length_ - current_index_) >> 3) > length) { | 704 if (((part_length_ - current_index_) >> 3) > length) { |
| 763 AssertNoAllocation no_allocation; | 705 AssertNoAllocation no_allocation; |
| 764 Vector<const Char> vector = GetCharVector<Char>(string); | 706 Vector<const Char> vector = GetCharVector<Char>(string); |
| 765 if (is_ascii) { | 707 if (is_ascii) { |
| 766 current_index_ += SerializeStringUnchecked_( | 708 SerializeStringUnchecked_( |
| 767 vector.start(), | 709 vector.start(), |
| 768 SeqOneByteString::cast(*current_part_)->GetChars() + current_index_, | 710 SeqOneByteString::cast(*current_part_)->GetChars(), |
| 769 length); | 711 length); |
| 770 } else { | 712 } else { |
| 771 current_index_ += SerializeStringUnchecked_( | 713 SerializeStringUnchecked_( |
| 772 vector.start(), | 714 vector.start(), |
| 773 SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_, | 715 SeqTwoByteString::cast(*current_part_)->GetChars(), |
| 774 length); | 716 length); |
| 775 } | 717 } |
| 776 } else { | 718 } else { |
| 777 String* string_location = *string; | 719 String* string_location = *string; |
| 778 Vector<const Char> vector = GetCharVector<Char>(string); | 720 Vector<const Char> vector = GetCharVector<Char>(string); |
| 779 for (int i = 0; i < length; i++) { | 721 for (int i = 0; i < length; i++) { |
| 780 Char c = vector[i]; | 722 Char c = vector[i]; |
| 781 if (DoNotEscape(c)) { | 723 if (DoNotEscape(c)) { |
| 782 Append_<is_ascii, Char>(c); | 724 Append_<is_ascii, Char>(c); |
| 783 } else { | 725 } else { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 SerializeString_<false, uint8_t>(object); | 782 SerializeString_<false, uint8_t>(object); |
| 841 } else { | 783 } else { |
| 842 SerializeString_<false, uc16>(object); | 784 SerializeString_<false, uc16>(object); |
| 843 } | 785 } |
| 844 } | 786 } |
| 845 } | 787 } |
| 846 | 788 |
| 847 } } // namespace v8::internal | 789 } } // namespace v8::internal |
| 848 | 790 |
| 849 #endif // V8_JSON_STRINGIFIER_H_ | 791 #endif // V8_JSON_STRINGIFIER_H_ |
| OLD | NEW |