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

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

Issue 12993003: Revert r14023 (Unify code for fast and slow path of JSON.stringify) from trunk. (Closed) Base URL: https://v8.googlecode.com/svn/trunk
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
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
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
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
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
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
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_
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