| 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 |