| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 static const int kPartLengthGrowthFactor = 2; | 47 static const int kPartLengthGrowthFactor = 2; |
| 48 | 48 |
| 49 enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW }; | 49 enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW }; |
| 50 | 50 |
| 51 void Extend(); | 51 void Extend(); |
| 52 | 52 |
| 53 void ChangeEncoding(); | 53 void ChangeEncoding(); |
| 54 | 54 |
| 55 void ShrinkCurrentPart(); | 55 void ShrinkCurrentPart(); |
| 56 | 56 |
| 57 template <bool is_ascii, typename Char> | 57 template <bool ascii_mode, typename Char> |
| 58 INLINE(void Append_(Char c)); | 58 INLINE(void Append_(Char c)); |
| 59 | 59 |
| 60 template <bool is_ascii, typename Char> | 60 template <bool ascii_mode, typename Char> |
| 61 INLINE(void Append_(const Char* chars)); | 61 INLINE(void Append_(const Char* chars)); |
| 62 | 62 |
| 63 INLINE(void Append(uint8_t c)) { | 63 INLINE(void Append(uint8_t c)) { |
| 64 if (is_ascii_) { | 64 if (ascii_mode_) { |
| 65 Append_<true>(c); | 65 Append_<true>(c); |
| 66 } else { | 66 } else { |
| 67 Append_<false>(c); | 67 Append_<false>(c); |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 | 70 |
| 71 INLINE(void AppendAscii(const char* chars)) { | 71 INLINE(void AppendAscii(const char* chars)) { |
| 72 if (is_ascii_) { | 72 if (ascii_mode_) { |
| 73 Append_<true>(reinterpret_cast<const uint8_t*>(chars)); | 73 Append_<true>(reinterpret_cast<const uint8_t*>(chars)); |
| 74 } else { | 74 } else { |
| 75 Append_<false>(reinterpret_cast<const uint8_t*>(chars)); | 75 Append_<false>(reinterpret_cast<const uint8_t*>(chars)); |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 | 78 |
| 79 Handle<Object> ApplyToJsonFunction(Handle<Object> object, | 79 Handle<Object> ApplyToJsonFunction(Handle<Object> object, |
| 80 Handle<Object> key); | 80 Handle<Object> key); |
| 81 | 81 |
| 82 Result SerializeGeneric(Handle<Object> object, | 82 Result SerializeGeneric(Handle<Object> object, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 | 123 |
| 124 Result SerializeJSValue(Handle<JSValue> object); | 124 Result SerializeJSValue(Handle<JSValue> object); |
| 125 | 125 |
| 126 INLINE(Result SerializeJSArray(Handle<JSArray> object)); | 126 INLINE(Result SerializeJSArray(Handle<JSArray> object)); |
| 127 INLINE(Result SerializeJSObject(Handle<JSObject> object)); | 127 INLINE(Result SerializeJSObject(Handle<JSObject> object)); |
| 128 | 128 |
| 129 Result SerializeJSArraySlow(Handle<JSArray> object, int length); | 129 Result SerializeJSArraySlow(Handle<JSArray> object, int length); |
| 130 | 130 |
| 131 void SerializeString(Handle<String> object); | 131 void SerializeString(Handle<String> object); |
| 132 | 132 |
| 133 template <typename SrcChar, typename DestChar> | 133 template <bool printable_ascii_only, typename SrcChar, typename DestChar> |
| 134 INLINE(void SerializeStringUnchecked_(const SrcChar* src, | 134 INLINE(void SerializeStringUnchecked_(const SrcChar* src, |
| 135 DestChar* dest, | 135 DestChar* dest, |
| 136 int length)); | 136 int length)); |
| 137 | 137 |
| 138 template <bool is_ascii, typename Char> | 138 template <bool printable_ascii_only, bool ascii_mode, typename Char> |
| 139 INLINE(void SerializeString_(Handle<String> string)); | 139 INLINE(void SerializeString_(Handle<String> string)); |
| 140 | 140 |
| 141 template <typename Char> | 141 template <bool printable_ascii_only, typename Char> |
| 142 INLINE(bool DoNotEscape(Char c)); | 142 INLINE(bool DoNotEscape(Char c)); |
| 143 | 143 |
| 144 template <typename Char> | 144 template <typename Char> |
| 145 INLINE(Vector<const Char> GetCharVector(Handle<String> string)); | 145 INLINE(Vector<const Char> GetCharVector(Handle<String> string)); |
| 146 | 146 |
| 147 Result StackPush(Handle<Object> object); | 147 Result StackPush(Handle<Object> object); |
| 148 void StackPop(); | 148 void StackPop(); |
| 149 | 149 |
| 150 INLINE(Handle<String> accumulator()) { | 150 INLINE(Handle<String> accumulator()) { |
| 151 return Handle<String>(String::cast(accumulator_store_->value()), isolate_); | 151 return Handle<String>(String::cast(accumulator_store_->value()), isolate_); |
| 152 } | 152 } |
| 153 | 153 |
| 154 INLINE(void set_accumulator(Handle<String> string)) { | 154 INLINE(void set_accumulator(Handle<String> string)) { |
| 155 return accumulator_store_->set_value(*string); | 155 return accumulator_store_->set_value(*string); |
| 156 } | 156 } |
| 157 | 157 |
| 158 Isolate* isolate_; | 158 Isolate* isolate_; |
| 159 Factory* factory_; | 159 Factory* factory_; |
| 160 // We use a value wrapper for the string accumulator to keep the | 160 // We use a value wrapper for the string accumulator to keep the |
| 161 // (indirect) handle to it in the outermost handle scope. | 161 // (indirect) handle to it in the outermost handle scope. |
| 162 Handle<JSValue> accumulator_store_; | 162 Handle<JSValue> accumulator_store_; |
| 163 Handle<String> current_part_; | 163 Handle<String> current_part_; |
| 164 Handle<String> tojson_symbol_; | 164 Handle<String> tojson_symbol_; |
| 165 Handle<JSArray> stack_; | 165 Handle<JSArray> stack_; |
| 166 int current_index_; | 166 int current_index_; |
| 167 int part_length_; | 167 int part_length_; |
| 168 bool is_ascii_; | 168 bool ascii_mode_; |
| 169 | 169 |
| 170 static const int kJsonEscapeTableEntrySize = 8; | 170 static const int kJsonEscapeTableEntrySize = 8; |
| 171 static const char* const JsonEscapeTable; | 171 static const char* const JsonEscapeTable; |
| 172 }; | 172 }; |
| 173 | 173 |
| 174 | 174 |
| 175 // Translation table to escape ASCII characters. | 175 // Translation table to escape ASCII characters. |
| 176 // Table entries start at a multiple of 8 and are null-terminated. | 176 // Table entries start at a multiple of 8 and are null-terminated. |
| 177 const char* const BasicJsonStringifier::JsonEscapeTable = | 177 const char* const BasicJsonStringifier::JsonEscapeTable = |
| 178 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 178 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
| (...skipping 24 matching lines...) Expand all Loading... |
| 203 "d\0 e\0 f\0 g\0 " | 203 "d\0 e\0 f\0 g\0 " |
| 204 "h\0 i\0 j\0 k\0 " | 204 "h\0 i\0 j\0 k\0 " |
| 205 "l\0 m\0 n\0 o\0 " | 205 "l\0 m\0 n\0 o\0 " |
| 206 "p\0 q\0 r\0 s\0 " | 206 "p\0 q\0 r\0 s\0 " |
| 207 "t\0 u\0 v\0 w\0 " | 207 "t\0 u\0 v\0 w\0 " |
| 208 "x\0 y\0 z\0 {\0 " | 208 "x\0 y\0 z\0 {\0 " |
| 209 "|\0 }\0 ~\0 \177\0 "; | 209 "|\0 }\0 ~\0 \177\0 "; |
| 210 | 210 |
| 211 | 211 |
| 212 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) | 212 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
| 213 : isolate_(isolate), current_index_(0), is_ascii_(true) { | 213 : isolate_(isolate), current_index_(0), ascii_mode_(true) { |
| 214 factory_ = isolate_->factory(); | 214 factory_ = isolate_->factory(); |
| 215 accumulator_store_ = Handle<JSValue>::cast( | 215 accumulator_store_ = Handle<JSValue>::cast( |
| 216 factory_->ToObject(factory_->empty_string())); | 216 factory_->ToObject(factory_->empty_string())); |
| 217 part_length_ = kInitialPartLength; | 217 part_length_ = kInitialPartLength; |
| 218 current_part_ = factory_->NewRawOneByteString(kInitialPartLength); | 218 current_part_ = factory_->NewRawOneByteString(kInitialPartLength); |
| 219 tojson_symbol_ = | 219 tojson_symbol_ = |
| 220 factory_->LookupOneByteSymbol(STATIC_ASCII_VECTOR("toJSON")); | 220 factory_->LookupOneByteSymbol(STATIC_ASCII_VECTOR("toJSON")); |
| 221 stack_ = factory_->NewJSArray(8); | 221 stack_ = factory_->NewJSArray(8); |
| 222 } | 222 } |
| 223 | 223 |
| 224 | 224 |
| 225 MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { | 225 MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { |
| 226 switch (SerializeObject(object)) { | 226 switch (SerializeObject(object)) { |
| 227 case UNCHANGED: | 227 case UNCHANGED: |
| 228 return isolate_->heap()->undefined_value(); | 228 return isolate_->heap()->undefined_value(); |
| 229 case SUCCESS: | 229 case SUCCESS: |
| 230 ShrinkCurrentPart(); | 230 ShrinkCurrentPart(); |
| 231 return *factory_->NewConsString(accumulator(), current_part_); | 231 return *factory_->NewConsString(accumulator(), current_part_); |
| 232 case CIRCULAR: | 232 case CIRCULAR: |
| 233 return isolate_->Throw(*factory_->NewTypeError( | 233 return isolate_->Throw(*factory_->NewTypeError( |
| 234 "circular_structure", HandleVector<Object>(NULL, 0))); | 234 "circular_structure", HandleVector<Object>(NULL, 0))); |
| 235 case STACK_OVERFLOW: | 235 case STACK_OVERFLOW: |
| 236 return isolate_->StackOverflow(); | 236 return isolate_->StackOverflow(); |
| 237 default: | 237 default: |
| 238 return Failure::Exception(); | 238 return Failure::Exception(); |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 | 241 |
| 242 | 242 |
| 243 template <bool is_ascii, typename Char> | 243 template <bool ascii_mode, typename Char> |
| 244 void BasicJsonStringifier::Append_(Char c) { | 244 void BasicJsonStringifier::Append_(Char c) { |
| 245 if (is_ascii) { | 245 if (ascii_mode) { |
| 246 SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet( | 246 SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet( |
| 247 current_index_++, c); | 247 current_index_++, c); |
| 248 } else { | 248 } else { |
| 249 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( | 249 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( |
| 250 current_index_++, c); | 250 current_index_++, c); |
| 251 } | 251 } |
| 252 if (current_index_ == part_length_) Extend(); | 252 if (current_index_ == part_length_) Extend(); |
| 253 } | 253 } |
| 254 | 254 |
| 255 | 255 |
| 256 template <bool is_ascii, typename Char> | 256 template <bool ascii_mode, typename Char> |
| 257 void BasicJsonStringifier::Append_(const Char* chars) { | 257 void BasicJsonStringifier::Append_(const Char* chars) { |
| 258 for ( ; *chars != '\0'; chars++) Append_<is_ascii, Char>(*chars); | 258 for ( ; *chars != '\0'; chars++) Append_<ascii_mode, Char>(*chars); |
| 259 } | 259 } |
| 260 | 260 |
| 261 | 261 |
| 262 Handle<Object> BasicJsonStringifier::ApplyToJsonFunction( | 262 Handle<Object> BasicJsonStringifier::ApplyToJsonFunction( |
| 263 Handle<Object> object, Handle<Object> key) { | 263 Handle<Object> object, Handle<Object> key) { |
| 264 LookupResult lookup(isolate_); | 264 LookupResult lookup(isolate_); |
| 265 JSObject::cast(*object)->LookupRealNamedProperty(*tojson_symbol_, &lookup); | 265 JSObject::cast(*object)->LookupRealNamedProperty(*tojson_symbol_, &lookup); |
| 266 if (!lookup.IsProperty()) return object; | 266 if (!lookup.IsProperty()) return object; |
| 267 PropertyAttributes attr; | 267 PropertyAttributes attr; |
| 268 Handle<Object> fun = | 268 Handle<Object> fun = |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 current_part_ = Handle<String>( | 601 current_part_ = Handle<String>( |
| 602 SeqString::cast(*current_part_)->Truncate(current_index_), isolate_); | 602 SeqString::cast(*current_part_)->Truncate(current_index_), isolate_); |
| 603 } | 603 } |
| 604 | 604 |
| 605 | 605 |
| 606 void BasicJsonStringifier::Extend() { | 606 void BasicJsonStringifier::Extend() { |
| 607 set_accumulator(factory_->NewConsString(accumulator(), current_part_)); | 607 set_accumulator(factory_->NewConsString(accumulator(), current_part_)); |
| 608 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { | 608 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { |
| 609 part_length_ *= kPartLengthGrowthFactor; | 609 part_length_ *= kPartLengthGrowthFactor; |
| 610 } | 610 } |
| 611 if (is_ascii_) { | 611 if (ascii_mode_) { |
| 612 current_part_ = factory_->NewRawOneByteString(part_length_); | 612 current_part_ = factory_->NewRawOneByteString(part_length_); |
| 613 } else { | 613 } else { |
| 614 current_part_ = factory_->NewRawTwoByteString(part_length_); | 614 current_part_ = factory_->NewRawTwoByteString(part_length_); |
| 615 } | 615 } |
| 616 current_index_ = 0; | 616 current_index_ = 0; |
| 617 } | 617 } |
| 618 | 618 |
| 619 | 619 |
| 620 void BasicJsonStringifier::ChangeEncoding() { | 620 void BasicJsonStringifier::ChangeEncoding() { |
| 621 ShrinkCurrentPart(); | 621 ShrinkCurrentPart(); |
| 622 set_accumulator(factory_->NewConsString(accumulator(), current_part_)); | 622 set_accumulator(factory_->NewConsString(accumulator(), current_part_)); |
| 623 current_part_ = factory_->NewRawTwoByteString(part_length_); | 623 current_part_ = factory_->NewRawTwoByteString(part_length_); |
| 624 current_index_ = 0; | 624 current_index_ = 0; |
| 625 is_ascii_ = false; | 625 ascii_mode_ = false; |
| 626 } | 626 } |
| 627 | 627 |
| 628 | 628 |
| 629 template <typename SrcChar, typename DestChar> | 629 template < bool printable_ascii_only, typename SrcChar, typename DestChar> |
| 630 void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, | 630 void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
| 631 DestChar* dest, | 631 DestChar* dest, |
| 632 int length) { | 632 int length) { |
| 633 dest += current_index_; | 633 dest += current_index_; |
| 634 DestChar* dest_start = dest; | 634 DestChar* dest_start = dest; |
| 635 | 635 |
| 636 // Assert that uc16 character is not truncated down to 8 bit. | 636 // Assert that uc16 character is not truncated down to 8 bit. |
| 637 // The <uc16, char> version of this method must not be called. | 637 // The <uc16, char> version of this method must not be called. |
| 638 ASSERT(sizeof(*dest) >= sizeof(*src)); | 638 ASSERT(sizeof(*dest) >= sizeof(*src)); |
| 639 | 639 |
| 640 for (int i = 0; i < length; i++) { | 640 for (int i = 0; i < length; i++) { |
| 641 SrcChar c = src[i]; | 641 SrcChar c = src[i]; |
| 642 if (DoNotEscape(c)) { | 642 if (DoNotEscape<printable_ascii_only>(c)) { |
| 643 *(dest++) = static_cast<DestChar>(c); | 643 *(dest++) = static_cast<DestChar>(c); |
| 644 } else { | 644 } else { |
| 645 const char* chars = &JsonEscapeTable[c * kJsonEscapeTableEntrySize]; | 645 const char* chars = &JsonEscapeTable[c * kJsonEscapeTableEntrySize]; |
| 646 while (*chars != '\0') *(dest++) = *(chars++); | 646 while (*chars != '\0') *(dest++) = *(chars++); |
| 647 } | 647 } |
| 648 } | 648 } |
| 649 | 649 |
| 650 current_index_ += static_cast<int>(dest - dest_start); | 650 current_index_ += static_cast<int>(dest - dest_start); |
| 651 } | 651 } |
| 652 | 652 |
| 653 | 653 |
| 654 template <bool is_ascii, typename Char> | 654 template <bool printable_ascii_only, bool ascii_mode, typename Char> |
| 655 void BasicJsonStringifier::SerializeString_(Handle<String> string) { | 655 void BasicJsonStringifier::SerializeString_(Handle<String> string) { |
| 656 int length = string->length(); | 656 int length = string->length(); |
| 657 Append_<is_ascii, char>('"'); | 657 Append_<ascii_mode, char>('"'); |
| 658 // We make a rough estimate to find out if the current string can be | 658 // We make a rough estimate to find out if the current string can be |
| 659 // serialized without allocating a new string part. The worst case length of | 659 // serialized without allocating a new string part. The worst case length of |
| 660 // an escaped character is 6. Shifting the remainin string length right by 3 | 660 // an escaped character is 6. Shifting the remainin string length right by 3 |
| 661 // is a more pessimistic estimate, but faster to calculate. | 661 // is a more pessimistic estimate, but faster to calculate. |
| 662 | 662 |
| 663 if (((part_length_ - current_index_) >> 3) > length) { | 663 if (((part_length_ - current_index_) >> 3) > length) { |
| 664 AssertNoAllocation no_allocation; | 664 AssertNoAllocation no_allocation; |
| 665 Vector<const Char> vector = GetCharVector<Char>(string); | 665 Vector<const Char> vector = GetCharVector<Char>(string); |
| 666 if (is_ascii) { | 666 if (ascii_mode) { |
| 667 SerializeStringUnchecked_( | 667 SerializeStringUnchecked_<printable_ascii_only>( |
| 668 vector.start(), | 668 vector.start(), |
| 669 SeqOneByteString::cast(*current_part_)->GetChars(), | 669 SeqOneByteString::cast(*current_part_)->GetChars(), |
| 670 length); | 670 length); |
| 671 } else { | 671 } else { |
| 672 SerializeStringUnchecked_( | 672 SerializeStringUnchecked_<printable_ascii_only>( |
| 673 vector.start(), | 673 vector.start(), |
| 674 SeqTwoByteString::cast(*current_part_)->GetChars(), | 674 SeqTwoByteString::cast(*current_part_)->GetChars(), |
| 675 length); | 675 length); |
| 676 } | 676 } |
| 677 } else { | 677 } else { |
| 678 String* string_location = *string; | 678 String* string_location = *string; |
| 679 Vector<const Char> vector = GetCharVector<Char>(string); | 679 Vector<const Char> vector = GetCharVector<Char>(string); |
| 680 for (int i = 0; i < length; i++) { | 680 for (int i = 0; i < length; i++) { |
| 681 Char c = vector[i]; | 681 Char c = vector[i]; |
| 682 if (DoNotEscape(c)) { | 682 if (DoNotEscape<printable_ascii_only>(c)) { |
| 683 Append_<is_ascii, Char>(c); | 683 Append_<ascii_mode, Char>(c); |
| 684 } else { | 684 } else { |
| 685 Append_<is_ascii, uint8_t>( | 685 Append_<ascii_mode, uint8_t>( |
| 686 reinterpret_cast<const uint8_t*>( | 686 reinterpret_cast<const uint8_t*>( |
| 687 &JsonEscapeTable[c * kJsonEscapeTableEntrySize])); | 687 &JsonEscapeTable[c * kJsonEscapeTableEntrySize])); |
| 688 } | 688 } |
| 689 // If GC moved the string, we need to refresh the vector. | 689 // If GC moved the string, we need to refresh the vector. |
| 690 if (*string != string_location) { | 690 if (*string != string_location) { |
| 691 vector = GetCharVector<Char>(string); | 691 vector = GetCharVector<Char>(string); |
| 692 string_location = *string; | 692 string_location = *string; |
| 693 } | 693 } |
| 694 } | 694 } |
| 695 } | 695 } |
| 696 | 696 |
| 697 Append_<is_ascii, uint8_t>('"'); | 697 Append_<ascii_mode, uint8_t>('"'); |
| 698 } | 698 } |
| 699 | 699 |
| 700 | 700 |
| 701 template <typename Char> | 701 template <bool printable_ascii_only, typename Char> |
| 702 bool BasicJsonStringifier::DoNotEscape(Char c) { | 702 bool BasicJsonStringifier::DoNotEscape(Char c) { |
| 703 return (c >= 0x80) || (c >= '#' && c <= '~' && c != '\\'); | 703 // "Printable" ASCII is in the range 0x20 .. 0x7e. |
| 704 return (c != '"' && c != '\\') && |
| 705 (printable_ascii_only || (c != 0x7f && c >= 0x20)); |
| 704 } | 706 } |
| 705 | 707 |
| 706 | 708 |
| 707 template <> | 709 template <> |
| 708 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( | 710 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( |
| 709 Handle<String> string) { | 711 Handle<String> string) { |
| 710 String::FlatContent flat = string->GetFlatContent(); | 712 String::FlatContent flat = string->GetFlatContent(); |
| 711 ASSERT(flat.IsAscii()); | 713 ASSERT(flat.IsAscii()); |
| 712 return flat.ToOneByteVector(); | 714 return flat.ToOneByteVector(); |
| 713 } | 715 } |
| 714 | 716 |
| 715 | 717 |
| 716 template <> | 718 template <> |
| 717 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { | 719 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { |
| 718 String::FlatContent flat = string->GetFlatContent(); | 720 String::FlatContent flat = string->GetFlatContent(); |
| 719 ASSERT(flat.IsTwoByte()); | 721 ASSERT(flat.IsTwoByte()); |
| 720 return flat.ToUC16Vector(); | 722 return flat.ToUC16Vector(); |
| 721 } | 723 } |
| 722 | 724 |
| 723 | 725 |
| 724 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 726 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
| 725 FlattenString(object); | 727 FlattenString(object); |
| 726 String::FlatContent flat = object->GetFlatContent(); | 728 String::FlatContent flat = object->GetFlatContent(); |
| 727 if (is_ascii_) { | 729 if (ascii_mode_) { |
| 728 if (flat.IsAscii()) { | 730 if (flat.IsAscii()) { |
| 729 SerializeString_<true, uint8_t>(object); | 731 if (object->map() == isolate_->heap()->printable_ascii_symbol_map()) { |
| 732 SerializeString_<true, true, uint8_t>(object); |
| 733 } else { |
| 734 SerializeString_<false, true, uint8_t>(object); |
| 735 } |
| 730 } else { | 736 } else { |
| 731 ChangeEncoding(); | 737 ChangeEncoding(); |
| 732 SerializeString(object); | 738 SerializeString(object); |
| 733 } | 739 } |
| 734 } else { | 740 } else { |
| 735 if (flat.IsAscii()) { | 741 if (flat.IsAscii()) { |
| 736 SerializeString_<false, uint8_t>(object); | 742 if (object->map() == isolate_->heap()->printable_ascii_symbol_map()) { |
| 743 SerializeString_<true, false, uint8_t>(object); |
| 744 } else { |
| 745 SerializeString_<false, false, uint8_t>(object); |
| 746 } |
| 737 } else { | 747 } else { |
| 738 SerializeString_<false, uc16>(object); | 748 SerializeString_<false, false, uc16>(object); |
| 739 } | 749 } |
| 740 } | 750 } |
| 741 } | 751 } |
| 742 | 752 |
| 743 } } // namespace v8::internal | 753 } } // namespace v8::internal |
| 744 | 754 |
| 745 #endif // V8_JSON_STRINGIFIER_H_ | 755 #endif // V8_JSON_STRINGIFIER_H_ |
| OLD | NEW |