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