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 |