| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_JSON_STRINGIFIER_H_ | 5 #ifndef V8_JSON_STRINGIFIER_H_ |
| 6 #define V8_JSON_STRINGIFIER_H_ | 6 #define V8_JSON_STRINGIFIER_H_ |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 false, | 88 false, |
| 89 Handle<Object>(Smi::FromInt(i), isolate)); | 89 Handle<Object>(Smi::FromInt(i), isolate)); |
| 90 } | 90 } |
| 91 | 91 |
| 92 // Serialize a object property. | 92 // Serialize a object property. |
| 93 // The key may or may not be serialized depending on the property. | 93 // The key may or may not be serialized depending on the property. |
| 94 // The key may also serve as argument for the toJSON function. | 94 // The key may also serve as argument for the toJSON function. |
| 95 INLINE(Result SerializeProperty(Handle<Object> object, | 95 INLINE(Result SerializeProperty(Handle<Object> object, |
| 96 bool deferred_comma, | 96 bool deferred_comma, |
| 97 Handle<String> deferred_key)) { | 97 Handle<String> deferred_key)) { |
| 98 ASSERT(!deferred_key.is_null()); | 98 DCHECK(!deferred_key.is_null()); |
| 99 return Serialize_<true>(object, deferred_comma, deferred_key); | 99 return Serialize_<true>(object, deferred_comma, deferred_key); |
| 100 } | 100 } |
| 101 | 101 |
| 102 template <bool deferred_string_key> | 102 template <bool deferred_string_key> |
| 103 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); | 103 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); |
| 104 | 104 |
| 105 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { | 105 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { |
| 106 if (deferred_comma) Append(','); | 106 if (deferred_comma) Append(','); |
| 107 SerializeString(Handle<String>::cast(deferred_key)); | 107 SerializeString(Handle<String>::cast(deferred_key)); |
| 108 Append(':'); | 108 Append(':'); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 if (result == UNCHANGED) return isolate_->factory()->undefined_value(); | 256 if (result == UNCHANGED) return isolate_->factory()->undefined_value(); |
| 257 if (result == SUCCESS) { | 257 if (result == SUCCESS) { |
| 258 ShrinkCurrentPart(); | 258 ShrinkCurrentPart(); |
| 259 Accumulate(); | 259 Accumulate(); |
| 260 if (overflowed_) { | 260 if (overflowed_) { |
| 261 return isolate_->Throw<Object>( | 261 return isolate_->Throw<Object>( |
| 262 isolate_->factory()->NewInvalidStringLengthError()); | 262 isolate_->factory()->NewInvalidStringLengthError()); |
| 263 } | 263 } |
| 264 return accumulator(); | 264 return accumulator(); |
| 265 } | 265 } |
| 266 ASSERT(result == EXCEPTION); | 266 DCHECK(result == EXCEPTION); |
| 267 return MaybeHandle<Object>(); | 267 return MaybeHandle<Object>(); |
| 268 } | 268 } |
| 269 | 269 |
| 270 | 270 |
| 271 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 271 MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
| 272 Isolate* isolate, Handle<String> object) { | 272 Isolate* isolate, Handle<String> object) { |
| 273 static const int kJsonQuoteWorstCaseBlowup = 6; | 273 static const int kJsonQuoteWorstCaseBlowup = 6; |
| 274 static const int kSpaceForQuotes = 2; | 274 static const int kSpaceForQuotes = 2; |
| 275 int worst_case_length = | 275 int worst_case_length = |
| 276 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 276 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
| 277 | 277 |
| 278 if (worst_case_length > 32 * KB) { // Slow path if too large. | 278 if (worst_case_length > 32 * KB) { // Slow path if too large. |
| 279 BasicJsonStringifier stringifier(isolate); | 279 BasicJsonStringifier stringifier(isolate); |
| 280 return stringifier.Stringify(object); | 280 return stringifier.Stringify(object); |
| 281 } | 281 } |
| 282 | 282 |
| 283 object = String::Flatten(object); | 283 object = String::Flatten(object); |
| 284 ASSERT(object->IsFlat()); | 284 DCHECK(object->IsFlat()); |
| 285 if (object->IsOneByteRepresentationUnderneath()) { | 285 if (object->IsOneByteRepresentationUnderneath()) { |
| 286 Handle<String> result = isolate->factory()->NewRawOneByteString( | 286 Handle<String> result = isolate->factory()->NewRawOneByteString( |
| 287 worst_case_length).ToHandleChecked(); | 287 worst_case_length).ToHandleChecked(); |
| 288 DisallowHeapAllocation no_gc; | 288 DisallowHeapAllocation no_gc; |
| 289 return StringifyString_<SeqOneByteString>( | 289 return StringifyString_<SeqOneByteString>( |
| 290 isolate, | 290 isolate, |
| 291 object->GetFlatContent().ToOneByteVector(), | 291 object->GetFlatContent().ToOneByteVector(), |
| 292 result); | 292 result); |
| 293 } else { | 293 } else { |
| 294 Handle<String> result = isolate->factory()->NewRawTwoByteString( | 294 Handle<String> result = isolate->factory()->NewRawTwoByteString( |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 499 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 500 isolate_, value, Execution::ToString(isolate_, object), EXCEPTION); | 500 isolate_, value, Execution::ToString(isolate_, object), EXCEPTION); |
| 501 SerializeString(Handle<String>::cast(value)); | 501 SerializeString(Handle<String>::cast(value)); |
| 502 } else if (class_name == isolate_->heap()->Number_string()) { | 502 } else if (class_name == isolate_->heap()->Number_string()) { |
| 503 Handle<Object> value; | 503 Handle<Object> value; |
| 504 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 504 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 505 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); | 505 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); |
| 506 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 506 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
| 507 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 507 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
| 508 } else { | 508 } else { |
| 509 ASSERT(class_name == isolate_->heap()->Boolean_string()); | 509 DCHECK(class_name == isolate_->heap()->Boolean_string()); |
| 510 Object* value = JSValue::cast(*object)->value(); | 510 Object* value = JSValue::cast(*object)->value(); |
| 511 ASSERT(value->IsBoolean()); | 511 DCHECK(value->IsBoolean()); |
| 512 AppendAscii(value->IsTrue() ? "true" : "false"); | 512 AppendAscii(value->IsTrue() ? "true" : "false"); |
| 513 } | 513 } |
| 514 return SUCCESS; | 514 return SUCCESS; |
| 515 } | 515 } |
| 516 | 516 |
| 517 | 517 |
| 518 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 518 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { |
| 519 static const int kBufferSize = 100; | 519 static const int kBufferSize = 100; |
| 520 char chars[kBufferSize]; | 520 char chars[kBufferSize]; |
| 521 Vector<char> buffer(chars, kBufferSize); | 521 Vector<char> buffer(chars, kBufferSize); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 } | 624 } |
| 625 return SUCCESS; | 625 return SUCCESS; |
| 626 } | 626 } |
| 627 | 627 |
| 628 | 628 |
| 629 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 629 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
| 630 Handle<JSObject> object) { | 630 Handle<JSObject> object) { |
| 631 HandleScope handle_scope(isolate_); | 631 HandleScope handle_scope(isolate_); |
| 632 Result stack_push = StackPush(object); | 632 Result stack_push = StackPush(object); |
| 633 if (stack_push != SUCCESS) return stack_push; | 633 if (stack_push != SUCCESS) return stack_push; |
| 634 ASSERT(!object->IsJSGlobalProxy() && !object->IsGlobalObject()); | 634 DCHECK(!object->IsJSGlobalProxy() && !object->IsGlobalObject()); |
| 635 | 635 |
| 636 Append('{'); | 636 Append('{'); |
| 637 bool comma = false; | 637 bool comma = false; |
| 638 | 638 |
| 639 if (object->HasFastProperties() && | 639 if (object->HasFastProperties() && |
| 640 !object->HasIndexedInterceptor() && | 640 !object->HasIndexedInterceptor() && |
| 641 !object->HasNamedInterceptor() && | 641 !object->HasNamedInterceptor() && |
| 642 object->elements()->length() == 0) { | 642 object->elements()->length() == 0) { |
| 643 Handle<Map> map(object->map()); | 643 Handle<Map> map(object->map()); |
| 644 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 644 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 670 EXCEPTION); | 670 EXCEPTION); |
| 671 | 671 |
| 672 for (int i = 0; i < contents->length(); i++) { | 672 for (int i = 0; i < contents->length(); i++) { |
| 673 Object* key = contents->get(i); | 673 Object* key = contents->get(i); |
| 674 Handle<String> key_handle; | 674 Handle<String> key_handle; |
| 675 MaybeHandle<Object> maybe_property; | 675 MaybeHandle<Object> maybe_property; |
| 676 if (key->IsString()) { | 676 if (key->IsString()) { |
| 677 key_handle = Handle<String>(String::cast(key), isolate_); | 677 key_handle = Handle<String>(String::cast(key), isolate_); |
| 678 maybe_property = Object::GetPropertyOrElement(object, key_handle); | 678 maybe_property = Object::GetPropertyOrElement(object, key_handle); |
| 679 } else { | 679 } else { |
| 680 ASSERT(key->IsNumber()); | 680 DCHECK(key->IsNumber()); |
| 681 key_handle = factory_->NumberToString(Handle<Object>(key, isolate_)); | 681 key_handle = factory_->NumberToString(Handle<Object>(key, isolate_)); |
| 682 uint32_t index; | 682 uint32_t index; |
| 683 if (key->IsSmi()) { | 683 if (key->IsSmi()) { |
| 684 maybe_property = Object::GetElement( | 684 maybe_property = Object::GetElement( |
| 685 isolate_, object, Smi::cast(key)->value()); | 685 isolate_, object, Smi::cast(key)->value()); |
| 686 } else if (key_handle->AsArrayIndex(&index)) { | 686 } else if (key_handle->AsArrayIndex(&index)) { |
| 687 maybe_property = Object::GetElement(isolate_, object, index); | 687 maybe_property = Object::GetElement(isolate_, object, index); |
| 688 } else { | 688 } else { |
| 689 maybe_property = Object::GetPropertyOrElement(object, key_handle); | 689 maybe_property = Object::GetPropertyOrElement(object, key_handle); |
| 690 } | 690 } |
| 691 } | 691 } |
| 692 Handle<Object> property; | 692 Handle<Object> property; |
| 693 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 693 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 694 isolate_, property, maybe_property, EXCEPTION); | 694 isolate_, property, maybe_property, EXCEPTION); |
| 695 Result result = SerializeProperty(property, comma, key_handle); | 695 Result result = SerializeProperty(property, comma, key_handle); |
| 696 if (!comma && result == SUCCESS) comma = true; | 696 if (!comma && result == SUCCESS) comma = true; |
| 697 if (result == EXCEPTION) return result; | 697 if (result == EXCEPTION) return result; |
| 698 } | 698 } |
| 699 } | 699 } |
| 700 | 700 |
| 701 Append('}'); | 701 Append('}'); |
| 702 StackPop(); | 702 StackPop(); |
| 703 current_part_ = handle_scope.CloseAndEscape(current_part_); | 703 current_part_ = handle_scope.CloseAndEscape(current_part_); |
| 704 return SUCCESS; | 704 return SUCCESS; |
| 705 } | 705 } |
| 706 | 706 |
| 707 | 707 |
| 708 void BasicJsonStringifier::ShrinkCurrentPart() { | 708 void BasicJsonStringifier::ShrinkCurrentPart() { |
| 709 ASSERT(current_index_ < part_length_); | 709 DCHECK(current_index_ < part_length_); |
| 710 current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_), | 710 current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_), |
| 711 current_index_); | 711 current_index_); |
| 712 } | 712 } |
| 713 | 713 |
| 714 | 714 |
| 715 void BasicJsonStringifier::Accumulate() { | 715 void BasicJsonStringifier::Accumulate() { |
| 716 if (accumulator()->length() + current_part_->length() > String::kMaxLength) { | 716 if (accumulator()->length() + current_part_->length() > String::kMaxLength) { |
| 717 // Screw it. Simply set the flag and carry on. Throw exception at the end. | 717 // Screw it. Simply set the flag and carry on. Throw exception at the end. |
| 718 set_accumulator(factory_->empty_string()); | 718 set_accumulator(factory_->empty_string()); |
| 719 overflowed_ = true; | 719 overflowed_ = true; |
| 720 } else { | 720 } else { |
| 721 set_accumulator(factory_->NewConsString(accumulator(), | 721 set_accumulator(factory_->NewConsString(accumulator(), |
| 722 current_part_).ToHandleChecked()); | 722 current_part_).ToHandleChecked()); |
| 723 } | 723 } |
| 724 } | 724 } |
| 725 | 725 |
| 726 | 726 |
| 727 void BasicJsonStringifier::Extend() { | 727 void BasicJsonStringifier::Extend() { |
| 728 Accumulate(); | 728 Accumulate(); |
| 729 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { | 729 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { |
| 730 part_length_ *= kPartLengthGrowthFactor; | 730 part_length_ *= kPartLengthGrowthFactor; |
| 731 } | 731 } |
| 732 if (is_ascii_) { | 732 if (is_ascii_) { |
| 733 current_part_ = | 733 current_part_ = |
| 734 factory_->NewRawOneByteString(part_length_).ToHandleChecked(); | 734 factory_->NewRawOneByteString(part_length_).ToHandleChecked(); |
| 735 } else { | 735 } else { |
| 736 current_part_ = | 736 current_part_ = |
| 737 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | 737 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); |
| 738 } | 738 } |
| 739 ASSERT(!current_part_.is_null()); | 739 DCHECK(!current_part_.is_null()); |
| 740 current_index_ = 0; | 740 current_index_ = 0; |
| 741 } | 741 } |
| 742 | 742 |
| 743 | 743 |
| 744 void BasicJsonStringifier::ChangeEncoding() { | 744 void BasicJsonStringifier::ChangeEncoding() { |
| 745 ShrinkCurrentPart(); | 745 ShrinkCurrentPart(); |
| 746 Accumulate(); | 746 Accumulate(); |
| 747 current_part_ = | 747 current_part_ = |
| 748 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | 748 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); |
| 749 ASSERT(!current_part_.is_null()); | 749 DCHECK(!current_part_.is_null()); |
| 750 current_index_ = 0; | 750 current_index_ = 0; |
| 751 is_ascii_ = false; | 751 is_ascii_ = false; |
| 752 } | 752 } |
| 753 | 753 |
| 754 | 754 |
| 755 template <typename SrcChar, typename DestChar> | 755 template <typename SrcChar, typename DestChar> |
| 756 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, | 756 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
| 757 DestChar* dest, | 757 DestChar* dest, |
| 758 int length) { | 758 int length) { |
| 759 DestChar* dest_start = dest; | 759 DestChar* dest_start = dest; |
| 760 | 760 |
| 761 // Assert that uc16 character is not truncated down to 8 bit. | 761 // Assert that uc16 character is not truncated down to 8 bit. |
| 762 // The <uc16, char> version of this method must not be called. | 762 // The <uc16, char> version of this method must not be called. |
| 763 ASSERT(sizeof(*dest) >= sizeof(*src)); | 763 DCHECK(sizeof(*dest) >= sizeof(*src)); |
| 764 | 764 |
| 765 for (int i = 0; i < length; i++) { | 765 for (int i = 0; i < length; i++) { |
| 766 SrcChar c = src[i]; | 766 SrcChar c = src[i]; |
| 767 if (DoNotEscape(c)) { | 767 if (DoNotEscape(c)) { |
| 768 *(dest++) = static_cast<DestChar>(c); | 768 *(dest++) = static_cast<DestChar>(c); |
| 769 } else { | 769 } else { |
| 770 const uint8_t* chars = reinterpret_cast<const uint8_t*>( | 770 const uint8_t* chars = reinterpret_cast<const uint8_t*>( |
| 771 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 771 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
| 772 while (*chars != '\0') *(dest++) = *(chars++); | 772 while (*chars != '\0') *(dest++) = *(chars++); |
| 773 } | 773 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 template <> | 834 template <> |
| 835 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { | 835 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { |
| 836 return c >= '#' && c != '\\' && c != 0x7f; | 836 return c >= '#' && c != '\\' && c != 0x7f; |
| 837 } | 837 } |
| 838 | 838 |
| 839 | 839 |
| 840 template <> | 840 template <> |
| 841 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( | 841 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( |
| 842 Handle<String> string) { | 842 Handle<String> string) { |
| 843 String::FlatContent flat = string->GetFlatContent(); | 843 String::FlatContent flat = string->GetFlatContent(); |
| 844 ASSERT(flat.IsAscii()); | 844 DCHECK(flat.IsAscii()); |
| 845 return flat.ToOneByteVector(); | 845 return flat.ToOneByteVector(); |
| 846 } | 846 } |
| 847 | 847 |
| 848 | 848 |
| 849 template <> | 849 template <> |
| 850 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { | 850 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { |
| 851 String::FlatContent flat = string->GetFlatContent(); | 851 String::FlatContent flat = string->GetFlatContent(); |
| 852 ASSERT(flat.IsTwoByte()); | 852 DCHECK(flat.IsTwoByte()); |
| 853 return flat.ToUC16Vector(); | 853 return flat.ToUC16Vector(); |
| 854 } | 854 } |
| 855 | 855 |
| 856 | 856 |
| 857 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 857 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
| 858 object = String::Flatten(object); | 858 object = String::Flatten(object); |
| 859 if (is_ascii_) { | 859 if (is_ascii_) { |
| 860 if (object->IsOneByteRepresentationUnderneath()) { | 860 if (object->IsOneByteRepresentationUnderneath()) { |
| 861 SerializeString_<true, uint8_t>(object); | 861 SerializeString_<true, uint8_t>(object); |
| 862 } else { | 862 } else { |
| 863 ChangeEncoding(); | 863 ChangeEncoding(); |
| 864 SerializeString(object); | 864 SerializeString(object); |
| 865 } | 865 } |
| 866 } else { | 866 } else { |
| 867 if (object->IsOneByteRepresentationUnderneath()) { | 867 if (object->IsOneByteRepresentationUnderneath()) { |
| 868 SerializeString_<false, uint8_t>(object); | 868 SerializeString_<false, uint8_t>(object); |
| 869 } else { | 869 } else { |
| 870 SerializeString_<false, uc16>(object); | 870 SerializeString_<false, uc16>(object); |
| 871 } | 871 } |
| 872 } | 872 } |
| 873 } | 873 } |
| 874 | 874 |
| 875 } } // namespace v8::internal | 875 } } // namespace v8::internal |
| 876 | 876 |
| 877 #endif // V8_JSON_STRINGIFIER_H_ | 877 #endif // V8_JSON_STRINGIFIER_H_ |
| OLD | NEW |