Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/json-stringifier.h

Issue 12690017: Unify code for fast and slow path of JSON.stringify. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/heap.h ('k') | src/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698