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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 template <bool is_ascii> void Extend(); | 52 template <bool is_ascii> void Extend(); |
53 | 53 |
54 void ChangeEncoding(); | 54 void ChangeEncoding(); |
55 | 55 |
56 void ShrinkCurrentPart(); | 56 void ShrinkCurrentPart(); |
57 | 57 |
58 template <bool is_ascii, typename Char> | 58 template <bool is_ascii, typename Char> |
59 INLINE(void Append_(Char c)); | 59 INLINE(void Append_(Char c)); |
60 | 60 |
61 template <bool is_ascii, typename Char> | 61 template <bool is_ascii, typename Char> |
62 INLINE(void AppendUnchecked_(Char c)); | |
63 | |
64 template <bool is_ascii, typename Char> | |
65 INLINE(void Append_(const Char* chars)); | 62 INLINE(void Append_(const Char* chars)); |
66 | 63 |
67 template <bool is_ascii, typename Char> | |
68 INLINE(void AppendUnchecked_(const Char* chars)); | |
69 | |
70 INLINE(void Append(char c)) { | 64 INLINE(void Append(char c)) { |
71 if (is_ascii_) { | 65 if (is_ascii_) { |
72 Append_<true>(c); | 66 Append_<true>(c); |
73 } else { | 67 } else { |
74 Append_<false>(c); | 68 Append_<false>(c); |
75 } | 69 } |
76 } | 70 } |
77 | 71 |
78 INLINE(void Append(const char* chars)) { | 72 INLINE(void Append(const char* chars)) { |
79 if (is_ascii_) { | 73 if (is_ascii_) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 INLINE(Result SerializeDouble(double number)); | 110 INLINE(Result SerializeDouble(double number)); |
117 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { | 111 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { |
118 return SerializeDouble(object->value()); | 112 return SerializeDouble(object->value()); |
119 } | 113 } |
120 | 114 |
121 Result SerializeArray(Handle<JSArray> object); | 115 Result SerializeArray(Handle<JSArray> object); |
122 Result SerializeObject(Handle<JSObject> object); | 116 Result SerializeObject(Handle<JSObject> object); |
123 | 117 |
124 void SerializeString(Handle<String> object); | 118 void SerializeString(Handle<String> object); |
125 | 119 |
| 120 template <typename SrcChar, typename DestChar> |
| 121 INLINE(void SerializeStringUnchecked_(const SrcChar* src, |
| 122 DestChar* dest, |
| 123 int length)); |
| 124 |
126 template <bool is_ascii, typename Char> | 125 template <bool is_ascii, typename Char> |
127 INLINE(void SerializeString_(Vector<const Char> vector, | 126 INLINE(void SerializeString_(Vector<const Char> vector, |
128 Handle<String> string)); | 127 Handle<String> string)); |
129 | 128 |
130 template <typename Char> | 129 template <typename Char> |
| 130 INLINE(bool DoNotEscape(Char c)); |
| 131 |
| 132 template <typename Char> |
131 INLINE(Vector<const Char> GetCharVector(Handle<String> string)); | 133 INLINE(Vector<const Char> GetCharVector(Handle<String> string)); |
132 | 134 |
133 INLINE(Result StackPush(Handle<Object> object)); | 135 INLINE(Result StackPush(Handle<Object> object)); |
134 INLINE(void StackPop()); | 136 INLINE(void StackPop()); |
135 | 137 |
136 INLINE(Handle<String> accumulator()) { | 138 INLINE(Handle<String> accumulator()) { |
137 return Handle<String>(String::cast(accumulator_store_->value())); | 139 return Handle<String>(String::cast(accumulator_store_->value())); |
138 } | 140 } |
139 | 141 |
140 INLINE(void set_accumulator(Handle<String> string)) { | 142 INLINE(void set_accumulator(Handle<String> string)) { |
141 return accumulator_store_->set_value(*string); | 143 return accumulator_store_->set_value(*string); |
142 } | 144 } |
143 | 145 |
144 Isolate* isolate_; | 146 Isolate* isolate_; |
145 // We use a value wrapper for the string accumulator to keep the | 147 // We use a value wrapper for the string accumulator to keep the |
146 // (indirect) handle to it in the outermost handle scope. | 148 // (indirect) handle to it in the outermost handle scope. |
147 Handle<JSValue> accumulator_store_; | 149 Handle<JSValue> accumulator_store_; |
148 Handle<String> current_part_; | 150 Handle<String> current_part_; |
149 Handle<String> tojson_symbol_; | 151 Handle<String> tojson_symbol_; |
150 Handle<JSArray> stack_; | 152 Handle<JSArray> stack_; |
151 int current_index_; | 153 int current_index_; |
152 int part_length_; | 154 int part_length_; |
153 bool is_ascii_; | 155 bool is_ascii_; |
154 | 156 |
155 static const int kJsonQuotesCharactersPerEntry = 8; | 157 static const int kJsonEscapeTableEntrySize = 8; |
156 static const char* const JsonQuotes; | 158 static const char* const JsonEscapeTable; |
157 }; | 159 }; |
158 | 160 |
159 | 161 |
160 const char* const BasicJsonStringifier::JsonQuotes = | 162 // Translation table to escape ASCII characters. |
| 163 // Table entries start at a multiple of 8 and are null-terminated. |
| 164 const char* const BasicJsonStringifier::JsonEscapeTable = |
161 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 165 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
162 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " | 166 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " |
163 "\\b\0 \\t\0 \\n\0 \\u000b\0 " | 167 "\\b\0 \\t\0 \\n\0 \\u000b\0 " |
164 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " | 168 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " |
165 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " | 169 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " |
166 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " | 170 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " |
167 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " | 171 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " |
168 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 " | 172 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 " |
169 " \0 !\0 \\\"\0 #\0 " | 173 " \0 !\0 \\\"\0 #\0 " |
170 "$\0 %\0 &\0 '\0 " | 174 "$\0 %\0 &\0 '\0 " |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 current_index_++, c); | 233 current_index_++, c); |
230 } else { | 234 } else { |
231 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( | 235 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( |
232 current_index_++, c); | 236 current_index_++, c); |
233 } | 237 } |
234 if (current_index_ == part_length_) Extend<is_ascii>(); | 238 if (current_index_ == part_length_) Extend<is_ascii>(); |
235 } | 239 } |
236 | 240 |
237 | 241 |
238 template <bool is_ascii, typename Char> | 242 template <bool is_ascii, typename Char> |
239 void BasicJsonStringifier::AppendUnchecked_(Char c) { | |
240 if (is_ascii) { | |
241 SeqAsciiString::cast(*current_part_)->SeqAsciiStringSet( | |
242 current_index_++, c); | |
243 } else { | |
244 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( | |
245 current_index_++, c); | |
246 } | |
247 ASSERT(current_index_ < part_length_); | |
248 } | |
249 | |
250 | |
251 template <bool is_ascii, typename Char> | |
252 void BasicJsonStringifier::Append_(const Char* chars) { | 243 void BasicJsonStringifier::Append_(const Char* chars) { |
253 for ( ; *chars != '\0'; chars++) Append_<is_ascii, Char>(*chars); | 244 for ( ; *chars != '\0'; chars++) Append_<is_ascii, Char>(*chars); |
254 } | 245 } |
255 | 246 |
256 | 247 |
257 template <bool is_ascii, typename Char> | |
258 void BasicJsonStringifier::AppendUnchecked_(const Char* chars) { | |
259 for ( ; *chars != '\0'; chars++) AppendUnchecked_<is_ascii, Char>(*chars); | |
260 } | |
261 | |
262 | |
263 Handle<Object> BasicJsonStringifier::GetProperty(Handle<JSObject> object, | 248 Handle<Object> BasicJsonStringifier::GetProperty(Handle<JSObject> object, |
264 Handle<String> key) { | 249 Handle<String> key) { |
265 LookupResult lookup(isolate_); | 250 LookupResult lookup(isolate_); |
266 object->LocalLookupRealNamedProperty(*key, &lookup); | 251 object->LocalLookupRealNamedProperty(*key, &lookup); |
267 if (!lookup.IsProperty()) return isolate_->factory()->undefined_value(); | 252 if (!lookup.IsProperty()) return isolate_->factory()->undefined_value(); |
268 switch (lookup.type()) { | 253 switch (lookup.type()) { |
269 case NORMAL: { | 254 case NORMAL: { |
270 Object* value = lookup.holder()->GetNormalizedProperty(&lookup); | 255 Object* value = lookup.holder()->GetNormalizedProperty(&lookup); |
271 ASSERT(!value->IsTheHole()); | 256 ASSERT(!value->IsTheHole()); |
272 return Handle<Object>(value); | 257 return Handle<Object>(value); |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 ShrinkCurrentPart(); | 557 ShrinkCurrentPart(); |
573 set_accumulator( | 558 set_accumulator( |
574 isolate_->factory()->NewConsString(accumulator(), current_part_)); | 559 isolate_->factory()->NewConsString(accumulator(), current_part_)); |
575 current_part_ = | 560 current_part_ = |
576 isolate_->factory()->NewRawTwoByteString(part_length_); | 561 isolate_->factory()->NewRawTwoByteString(part_length_); |
577 current_index_ = 0; | 562 current_index_ = 0; |
578 is_ascii_ = false; | 563 is_ascii_ = false; |
579 } | 564 } |
580 | 565 |
581 | 566 |
| 567 template <typename SrcChar, typename DestChar> |
| 568 void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
| 569 DestChar* dest, |
| 570 int length) { |
| 571 dest += current_index_; |
| 572 DestChar* dest_start = dest; |
| 573 |
| 574 *(dest++) = '"'; |
| 575 for (int i = 0; i < length; i++) { |
| 576 SrcChar c = src[i]; |
| 577 if (DoNotEscape(c)) { |
| 578 *(dest++) = c; |
| 579 } else { |
| 580 const char* chars = &JsonEscapeTable[c * kJsonEscapeTableEntrySize]; |
| 581 while (*chars != '\0') *(dest++) = *(chars++); |
| 582 } |
| 583 } |
| 584 |
| 585 *(dest++) = '"'; |
| 586 current_index_ += dest - dest_start; |
| 587 } |
| 588 |
| 589 |
582 template <bool is_ascii, typename Char> | 590 template <bool is_ascii, typename Char> |
583 void BasicJsonStringifier::SerializeString_(Vector<const Char> vector, | 591 void BasicJsonStringifier::SerializeString_(Vector<const Char> vector, |
584 Handle<String> string) { | 592 Handle<String> string) { |
585 int length = vector.length(); | 593 int length = vector.length(); |
586 if (current_index_ + (length << 3) < (part_length_ - 2)) { | 594 // We do a rough estimate to find out if the current string can be |
587 AssertNoAllocation no_allocation_scope; | 595 // serialized without allocating a new string part. The worst case length of |
588 AppendUnchecked_<is_ascii, char>('"'); | 596 // an escaped character is 6. Shifting left by 3 is a more pessimistic |
589 for (int i = 0; i < length; i++) { | 597 // estimate than multiplying by 6, but faster to calculate. |
590 Char c = vector[i]; | 598 static const int kEnclosingQuotesLength = 2; |
591 if ((c >= '#' && c <= '~' && c != '\\') || | 599 if (current_index_ + (length << 3) + kEnclosingQuotesLength < part_length_) { |
592 (!is_ascii && ((c & 0xFF80) != 0))) { | 600 if (is_ascii) { |
593 AppendUnchecked_<is_ascii, Char>(c); | 601 SerializeStringUnchecked_( |
594 } else { | 602 vector.start(), |
595 AppendUnchecked_<is_ascii, char>( | 603 SeqAsciiString::cast(*current_part_)->GetChars(), |
596 &JsonQuotes[c * kJsonQuotesCharactersPerEntry]); | 604 length); |
597 } | 605 } else { |
| 606 SerializeStringUnchecked_( |
| 607 vector.start(), |
| 608 SeqTwoByteString::cast(*current_part_)->GetChars(), |
| 609 length); |
598 } | 610 } |
599 AppendUnchecked_<is_ascii, char>('"'); | |
600 } else { | 611 } else { |
601 Append_<is_ascii, char>('"'); | 612 Append_<is_ascii, char>('"'); |
602 String* string_location = *string; | 613 String* string_location = *string; |
603 for (int i = 0; i < length; i++) { | 614 for (int i = 0; i < length; i++) { |
604 Char c = vector[i]; | 615 Char c = vector[i]; |
605 if ((c >= '#' && c <= '~' && c != '\\') || | 616 if (DoNotEscape(c)) { |
606 (!is_ascii && ((c & 0xFF80) != 0))) { | |
607 Append_<is_ascii, Char>(c); | 617 Append_<is_ascii, Char>(c); |
608 } else { | 618 } else { |
609 Append_<is_ascii, char>(&JsonQuotes[c * kJsonQuotesCharactersPerEntry]); | 619 Append_<is_ascii, char>( |
| 620 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
610 } | 621 } |
611 // If GC moved the string, we need to refresh the vector. | 622 // If GC moved the string, we need to refresh the vector. |
612 if (*string != string_location) { | 623 if (*string != string_location) { |
613 vector = GetCharVector<Char>(string); | 624 vector = GetCharVector<Char>(string); |
614 string_location = *string; | 625 string_location = *string; |
615 } | 626 } |
616 } | 627 } |
617 Append_<is_ascii, char>('"'); | 628 Append_<is_ascii, char>('"'); |
618 } | 629 } |
619 } | 630 } |
620 | 631 |
621 | 632 |
622 template <> | 633 template <> |
| 634 bool BasicJsonStringifier::DoNotEscape(char c) { |
| 635 return c >= '#' && c <= '~' && c != '\\'; |
| 636 } |
| 637 |
| 638 |
| 639 template <> |
| 640 bool BasicJsonStringifier::DoNotEscape(uc16 c) { |
| 641 return (c >= 0x80) || (c >= '#' && c <= '~' && c != '\\'); |
| 642 } |
| 643 |
| 644 |
| 645 template <> |
623 Vector<const char> BasicJsonStringifier::GetCharVector(Handle<String> string) { | 646 Vector<const char> BasicJsonStringifier::GetCharVector(Handle<String> string) { |
624 String::FlatContent flat = string->GetFlatContent(); | 647 String::FlatContent flat = string->GetFlatContent(); |
625 ASSERT(flat.IsAscii()); | 648 ASSERT(flat.IsAscii()); |
626 return flat.ToAsciiVector(); | 649 return flat.ToAsciiVector(); |
627 } | 650 } |
628 | 651 |
629 | 652 |
630 template <> | 653 template <> |
631 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { | 654 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { |
632 String::FlatContent flat = string->GetFlatContent(); | 655 String::FlatContent flat = string->GetFlatContent(); |
(...skipping 17 matching lines...) Expand all Loading... |
650 SerializeString_<false, char>(flat.ToAsciiVector(), object); | 673 SerializeString_<false, char>(flat.ToAsciiVector(), object); |
651 } else { | 674 } else { |
652 SerializeString_<false, uc16>(flat.ToUC16Vector(), object); | 675 SerializeString_<false, uc16>(flat.ToUC16Vector(), object); |
653 } | 676 } |
654 } | 677 } |
655 } | 678 } |
656 | 679 |
657 } } // namespace v8::internal | 680 } } // namespace v8::internal |
658 | 681 |
659 #endif // V8_JSON_STRINGIFIER_H_ | 682 #endif // V8_JSON_STRINGIFIER_H_ |
OLD | NEW |