Chromium Code Reviews| 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 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 HEAP->CollectAllAvailableGarbage(); | 702 HEAP->CollectAllAvailableGarbage(); |
| 703 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); | 703 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); |
| 704 } | 704 } |
| 705 i::Isolate::Current()->compilation_cache()->Clear(); | 705 i::Isolate::Current()->compilation_cache()->Clear(); |
| 706 HEAP->CollectAllAvailableGarbage(); | 706 HEAP->CollectAllAvailableGarbage(); |
| 707 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); | 707 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); |
| 708 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count); | 708 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count); |
| 709 } | 709 } |
| 710 | 710 |
| 711 | 711 |
| 712 static void TestNewLatin1String(int encoding1, int encoding2) { | |
| 713 const char* chars1 = "ASCII 123"; | |
| 714 const char* chars1js = "'ASCII 123'"; | |
| 715 int str1_len = strlen(chars1); | |
| 716 const char* chars2 = "Non-ASCII \xAB\xCD\xEF"; | |
| 717 const char* chars2js = "'Non-ASCII \\u00ab\\u00cd\\u00ef'"; | |
| 718 int str2_len = strlen(chars2); | |
| 719 | |
| 720 Local<String> str1 = String::New(chars1, str1_len, encoding1); | |
| 721 Local<String> str2 = String::New(chars2, str2_len, encoding2); | |
| 722 Local<String> str1_compare = CompileRun(chars1js)->ToString(); | |
| 723 Local<String> str2_compare = CompileRun(chars2js)->ToString(); | |
| 724 | |
| 725 if (encoding1 & String::NOT_ASCII_HINT) { | |
| 726 CHECK(v8::Utils::OpenHandle(*str1)->IsSeqTwoByteString()); | |
| 727 } else { | |
| 728 CHECK(v8::Utils::OpenHandle(*str1)->IsSeqAsciiString()); | |
| 729 } | |
| 730 CHECK(v8::Utils::OpenHandle(*str1_compare)->IsSeqAsciiString()); | |
| 731 CHECK(v8::Utils::OpenHandle(*str2)->IsSeqTwoByteString()); | |
| 732 CHECK(v8::Utils::OpenHandle(*str2_compare)->IsSeqTwoByteString()); | |
| 733 | |
| 734 CHECK(str1_compare->Equals(str1)); | |
| 735 CHECK(str2_compare->Equals(str2)); | |
| 736 } | |
| 737 | |
| 738 | |
| 739 TEST(CreateLatin1String) { | |
| 740 v8::HandleScope scope; | |
| 741 LocalContext env; | |
| 742 | |
| 743 int latin1 = String::LATIN1_ENCODING; | |
| 744 int l_noascii = String::LATIN1_ENCODING | String::NOT_ASCII_HINT; | |
| 745 int l_ascii = String::LATIN1_ENCODING | String::STRICT_ASCII_HINT; | |
| 746 | |
| 747 TestNewLatin1String(latin1, latin1); | |
| 748 TestNewLatin1String(l_ascii, latin1); | |
| 749 TestNewLatin1String(l_noascii, l_noascii); | |
| 750 } | |
| 751 | |
| 752 | |
| 753 TEST(ExternalStringEncoding) { | |
| 754 v8::HandleScope scope; | |
| 755 LocalContext env; | |
| 756 int counter = 0; | |
| 757 | |
| 758 { HandleScope scope; | |
| 759 uint16_t* two_byte_ascii = AsciiToTwoByteString("two byte ascii"); | |
| 760 uint16_t* two_byte = AsciiToTwoByteString("two byte non-ascii \x99"); | |
| 761 char* ascii = i::StrDup("ascii"); | |
| 762 | |
| 763 TestResource* two_byte_resource = new TestResource(two_byte, &counter); | |
| 764 TestResource* two_byte_ascii_resource = | |
| 765 new TestResource(two_byte_ascii, &counter); | |
| 766 TestAsciiResource* ascii_resource = | |
| 767 new TestAsciiResource(ascii, &counter); | |
| 768 | |
| 769 Local<String> two_byte_external = String::NewExternal(two_byte_resource); | |
| 770 Local<String> two_byte_ascii_external = | |
| 771 String::NewExternal(two_byte_ascii_resource); | |
| 772 Local<String> ascii_external = String::NewExternal(ascii_resource); | |
| 773 Local<String> not_external = v8_str("not external"); | |
| 774 | |
| 775 CHECK_EQ(String::UTF16_ENCODING | String::NOT_ASCII_HINT, | |
| 776 two_byte_external->GetExternalStringEncoding()); | |
| 777 CHECK_EQ(String::UTF16_ENCODING | String::STRICT_ASCII_HINT, | |
| 778 two_byte_ascii_external->GetExternalStringEncoding()); | |
| 779 CHECK_EQ(String::LATIN1_ENCODING | String::STRICT_ASCII_HINT, | |
| 780 ascii_external->GetExternalStringEncoding()); | |
| 781 CHECK_EQ(String::INVALID_ENCODING, | |
| 782 not_external->GetExternalStringEncoding()); | |
| 783 | |
| 784 CHECK_EQ(two_byte_resource, two_byte_external->GetExternalStringResource()); | |
| 785 CHECK_EQ(two_byte_ascii_resource, | |
| 786 two_byte_ascii_external->GetExternalStringResourceBase()); | |
| 787 CHECK_EQ(ascii_resource, ascii_external->GetExternalStringResourceBase()); | |
| 788 | |
| 789 CHECK_EQ(0, counter); | |
| 790 } | |
| 791 | |
| 792 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | |
| 793 | |
| 794 CHECK_EQ(3, counter); | |
| 795 } | |
| 796 | |
| 797 | |
| 798 TEST(WriteLatin1String) { | |
| 799 HandleScope scope; | |
| 800 LocalContext env; | |
| 801 const char* latin1_ascii = "latin1 ascii"; | |
| 802 const char* latin1 = "\x99 latin1 non-ascii \xF8"; | |
| 803 const char* concat = "latin1 ascii\x99 latin1 non-ascii \xF8"; | |
| 804 const char* sub = "latin1 non-ascii \xF8"; | |
| 805 | |
| 806 Local<String> latin1_ascii_string = String::New(latin1_ascii, | |
| 807 String::kUndefinedLength, | |
| 808 String::LATIN1_ENCODING); | |
| 809 Local<String> latin1_string = String::New(latin1, | |
| 810 String::kUndefinedLength, | |
| 811 String::LATIN1_ENCODING); | |
| 812 Local<String> concat_string = String::Concat(latin1_ascii_string, | |
| 813 latin1_string); | |
| 814 Local<String> sub_string = v8::Utils::ToLocal( | |
| 815 FACTORY->NewSubString( | |
| 816 v8::Utils::OpenHandle(*latin1_string), 2, latin1_string->Length())); | |
| 817 | |
| 818 CHECK(v8::Utils::OpenHandle(*latin1_ascii_string)->IsSeqAsciiString()); | |
| 819 CHECK(v8::Utils::OpenHandle(*latin1_string)->IsSeqTwoByteString()); | |
| 820 CHECK(v8::Utils::OpenHandle(*concat_string)->IsConsString()); | |
| 821 CHECK(v8::Utils::OpenHandle(*sub_string)->IsSlicedString()); | |
| 822 | |
| 823 char buffer[64]; | |
| 824 CHECK_EQ(strlen(latin1_ascii), latin1_ascii_string->WriteLatin1(buffer)); | |
| 825 CHECK_EQ(0, strcmp(latin1_ascii, buffer)); | |
| 826 CHECK_EQ(strlen(latin1), latin1_string->WriteLatin1(buffer)); | |
| 827 CHECK_EQ(0, strcmp(latin1, buffer)); | |
| 828 CHECK_EQ(strlen(concat), concat_string->WriteLatin1(buffer)); | |
| 829 CHECK_EQ(0, strcmp(concat, buffer)); | |
| 830 CHECK_EQ(strlen(sub), sub_string->WriteLatin1(buffer)); | |
| 831 CHECK_EQ(0, strcmp(sub, buffer)); | |
| 832 | |
| 833 memset(buffer, 0x1, sizeof(buffer)); | |
| 834 CHECK_EQ(strlen(latin1), | |
| 835 latin1_string->WriteLatin1(buffer, | |
| 836 0, | |
| 837 String::kUndefinedLength, | |
| 838 String::NO_NULL_TERMINATION)); | |
| 839 CHECK_EQ(0, strncmp(latin1, buffer, strlen(latin1))); | |
| 840 CHECK_NE(0, strcmp(latin1, buffer)); | |
| 841 buffer[strlen(latin1)] = '\0'; | |
| 842 CHECK_EQ(0, strcmp(latin1, buffer)); | |
| 843 | |
| 844 CHECK_EQ(strlen(latin1) - 2, | |
| 845 latin1_string->WriteLatin1(buffer, 2)); | |
| 846 CHECK_EQ(0, strncmp(latin1 + 2, buffer, strlen(latin1))); | |
| 847 } | |
| 848 | |
| 849 | |
| 850 class TestLatin1Resource: public String::ExternalLatin1StringResource { | |
| 851 public: | |
| 852 explicit TestLatin1Resource(const char* data, int* counter = NULL) | |
| 853 : data_(data), length_(strlen(data)), counter_(counter) { } | |
| 854 | |
| 855 ~TestLatin1Resource() { | |
| 856 i::DeleteArray(data_); | |
| 857 if (counter_ != NULL) ++*counter_; | |
| 858 } | |
| 859 | |
| 860 const char* data() const { | |
| 861 return data_; | |
| 862 } | |
| 863 | |
| 864 size_t length() const { | |
| 865 return length_; | |
| 866 } | |
| 867 private: | |
| 868 const char* data_; | |
| 869 size_t length_; | |
| 870 int* counter_; | |
| 871 }; | |
| 872 | |
| 873 | |
| 874 TEST(ExternalLatin1String) { | |
| 875 HandleScope scope; | |
| 876 LocalContext env; | |
| 877 int counter = 0; | |
| 878 | |
| 879 { HandleScope scope; | |
| 880 char* latin1_ascii_a = i::StrDup("latin1 ascii a"); | |
| 881 char* latin1_ascii_b = i::StrDup("latin1 ascii b"); | |
| 882 char* latin1_a = i::StrDup("latin non-ascii \xAA"); | |
| 883 char* latin1_b = i::StrDup("latin non-ascii \xBB"); | |
| 884 | |
| 885 TestLatin1Resource* latin1_ascii_a_resource = | |
| 886 new TestLatin1Resource(latin1_ascii_a, &counter); | |
| 887 TestLatin1Resource* latin1_ascii_b_resource = | |
| 888 new TestLatin1Resource(latin1_ascii_b, &counter); | |
| 889 TestLatin1Resource* latin1_a_resource = | |
| 890 new TestLatin1Resource(latin1_a, &counter); | |
| 891 TestLatin1Resource* latin1_b_resource = | |
| 892 new TestLatin1Resource(latin1_b, &counter); | |
| 893 | |
| 894 Local<String> latin1_ascii_a_external = | |
| 895 String::NewExternal(latin1_ascii_a_resource); | |
| 896 Local<String> latin1_ascii_b_external = String::NewExternal( | |
| 897 latin1_ascii_b_resource, | |
| 898 String::LATIN1_ENCODING | String::STRICT_ASCII_HINT); | |
| 899 CHECK_EQ(0, counter); | |
| 900 | |
| 901 // Non-ascii latin1 strings are internalized immediately as two-byte | |
| 902 // string and the external resource is disposed. | |
| 903 Local<String> latin1_a_external = String::NewExternal(latin1_a_resource); | |
| 904 Local<String> latin1_b_external = String::NewExternal( | |
| 905 latin1_b_resource, String::LATIN1_ENCODING | String::NOT_ASCII_HINT); | |
| 906 CHECK(v8::Utils::OpenHandle(*latin1_a_external)->IsSeqTwoByteString()); | |
| 907 CHECK(v8::Utils::OpenHandle(*latin1_b_external)->IsSeqTwoByteString()); | |
| 908 CHECK_EQ(2, counter); | |
| 909 | |
| 910 CHECK_EQ(latin1_ascii_a_external->GetExternalStringEncoding(), | |
| 911 (v8::String::LATIN1_ENCODING | v8::String::STRICT_ASCII_HINT)); | |
| 912 CHECK_EQ(latin1_ascii_b_external->GetExternalStringEncoding(), | |
| 913 (v8::String::LATIN1_ENCODING | v8::String::STRICT_ASCII_HINT)); | |
| 914 CHECK_EQ(latin1_a_external->GetExternalStringEncoding(), | |
| 915 v8::String::INVALID_ENCODING); | |
| 916 CHECK_EQ(latin1_b_external->GetExternalStringEncoding(), | |
| 917 v8::String::INVALID_ENCODING); | |
| 918 | |
| 919 CHECK_EQ(latin1_ascii_a_resource, | |
| 920 latin1_ascii_a_external->GetExternalStringResourceBase()); | |
| 921 CHECK_EQ(latin1_ascii_b_resource, | |
| 922 latin1_ascii_b_external->GetExternalStringResourceBase()); | |
| 923 } | |
| 924 | |
| 925 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | |
| 926 CHECK_EQ(4, counter); | |
| 927 } | |
| 928 | |
| 929 | |
| 930 TEST(ExternalizeLatin1String) { | |
| 931 HandleScope scope; | |
| 932 LocalContext env; | |
| 933 int counter = 0; | |
| 934 | |
| 935 { HandleScope scope; | |
| 936 Local<String> latin1_a_ascii = String::New("latin1 a ascii"); | |
| 937 Local<String> latin1_b_ascii = String::New("latin1 b ascii"); | |
| 938 Local<String> latin1_a = String::New("latin1 non-ascii \xAA", | |
| 939 String::kUndefinedLength, | |
| 940 String::LATIN1_ENCODING); | |
| 941 Local<String> latin1_b = String::New("latin1 non-ascii \xBB", | |
| 942 String::kUndefinedLength, | |
| 943 String::LATIN1_ENCODING); | |
| 944 | |
| 945 CHECK(v8::Utils::OpenHandle(*latin1_a_ascii)->IsSeqAsciiString()); | |
| 946 CHECK(v8::Utils::OpenHandle(*latin1_b_ascii)->IsSeqAsciiString()); | |
| 947 CHECK(v8::Utils::OpenHandle(*latin1_a)->IsSeqTwoByteString()); | |
| 948 CHECK(v8::Utils::OpenHandle(*latin1_b)->IsSeqTwoByteString()); | |
| 949 | |
| 950 // Run GC twice to put those strings into old space for externalizing. | |
| 951 HEAP->CollectGarbage(i::NEW_SPACE); | |
| 952 HEAP->CollectGarbage(i::NEW_SPACE); | |
| 953 | |
| 954 char* latin1_a_ascii_chars = i::NewArray<char>(64); | |
| 955 uint16_t* latin1_b_ascii_chars = i::NewArray<uint16_t>(64); | |
| 956 char* latin1_a_chars = i::NewArray<char>(64); | |
| 957 uint16_t* latin1_b_chars = i::NewArray<uint16_t>(64); | |
| 958 | |
| 959 latin1_a_ascii->WriteLatin1(latin1_a_ascii_chars); | |
| 960 latin1_b_ascii->Write(latin1_b_ascii_chars); | |
| 961 latin1_a->WriteLatin1(latin1_a_chars); | |
| 962 latin1_b->Write(latin1_b_chars); | |
| 963 | |
| 964 TestLatin1Resource* latin1_a_ascii_resource = | |
| 965 new TestLatin1Resource(latin1_a_ascii_chars, &counter); | |
| 966 TestResource* latin1_b_ascii_resource = | |
| 967 new TestResource(latin1_b_ascii_chars, &counter); | |
| 968 TestLatin1Resource* latin1_a_resource = | |
| 969 new TestLatin1Resource(latin1_a_chars, &counter); | |
| 970 TestResource* latin1_b_resource = | |
| 971 new TestResource(latin1_b_chars, &counter); | |
| 972 | |
| 973 CHECK(latin1_a_ascii->MakeExternal(latin1_a_ascii_resource)); | |
| 974 CHECK(latin1_a_ascii->IsExternalAscii()); | |
| 975 CHECK_EQ(latin1_a_ascii->GetExternalStringEncoding(), | |
| 976 (v8::String::LATIN1_ENCODING | v8::String::STRICT_ASCII_HINT)); | |
| 977 CHECK_EQ(latin1_a_ascii_resource, | |
| 978 latin1_a_ascii->GetExternalStringResourceBase()); | |
| 979 CHECK(latin1_a_ascii->Equals(String::New("latin1 a ascii"))); | |
| 980 | |
| 981 CHECK(latin1_b_ascii->MakeExternal(latin1_b_ascii_resource)); | |
| 982 CHECK(latin1_b_ascii->IsExternal()); | |
| 983 CHECK_EQ(latin1_b_ascii->GetExternalStringEncoding(), | |
| 984 (v8::String::UTF16_ENCODING | v8::String::STRICT_ASCII_HINT)); | |
| 985 CHECK_EQ(latin1_b_ascii_resource, | |
| 986 latin1_b_ascii->GetExternalStringResourceBase()); | |
| 987 CHECK(latin1_b_ascii->Equals(String::New("latin1 b ascii"))); | |
| 988 | |
| 989 CHECK(!latin1_a->MakeExternal(latin1_a_resource)); | |
|
Yang
2012/08/10 13:14:45
This would be the use case of MakeExternal(Externa
| |
| 990 i::DeleteArray(latin1_a_chars); | |
| 991 | |
| 992 CHECK(latin1_b->MakeExternal(latin1_b_resource)); | |
| 993 CHECK(latin1_b->IsExternal()); | |
| 994 CHECK_EQ(latin1_b->GetExternalStringEncoding(), | |
| 995 (v8::String::UTF16_ENCODING | v8::String::NOT_ASCII_HINT)); | |
| 996 CHECK_EQ(latin1_b_resource, | |
| 997 latin1_b->GetExternalStringResourceBase()); | |
| 998 CHECK(latin1_b->Equals(String::New("latin1 non-ascii \xBB", | |
| 999 String::kUndefinedLength, | |
| 1000 String::LATIN1_ENCODING))); | |
| 1001 } | |
| 1002 | |
| 1003 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | |
| 1004 CHECK_EQ(3, counter); | |
| 1005 } | |
| 1006 | |
| 1007 | |
| 712 THREADED_TEST(StringConcat) { | 1008 THREADED_TEST(StringConcat) { |
| 713 { | 1009 { |
| 714 v8::HandleScope scope; | 1010 HandleScope scope; |
| 715 LocalContext env; | 1011 LocalContext env; |
| 716 const char* one_byte_string_1 = "function a_times_t"; | 1012 const char* one_byte_string_1 = "function a_times_t"; |
| 717 const char* two_byte_string_1 = "wo_plus_b(a, b) {return "; | 1013 const char* two_byte_string_1 = "wo_plus_b(a, b) {return "; |
| 718 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + "; | 1014 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + "; |
| 719 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + "; | 1015 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + "; |
| 720 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + "; | 1016 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + "; |
| 721 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + "; | 1017 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + "; |
| 722 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);"; | 1018 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);"; |
| 723 Local<String> left = v8_str(one_byte_string_1); | 1019 Local<String> left = v8_str(one_byte_string_1); |
| 724 | 1020 |
| (...skipping 16383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17108 v8::HandleScope scope; | 17404 v8::HandleScope scope; |
| 17109 LocalContext context; | 17405 LocalContext context; |
| 17110 | 17406 |
| 17111 // Compile a try-finally clause where the finally block causes a GC | 17407 // Compile a try-finally clause where the finally block causes a GC |
| 17112 // while there still is a message pending for external reporting. | 17408 // while there still is a message pending for external reporting. |
| 17113 TryCatch try_catch; | 17409 TryCatch try_catch; |
| 17114 try_catch.SetVerbose(true); | 17410 try_catch.SetVerbose(true); |
| 17115 CompileRun("try { throw new Error(); } finally { gc(); }"); | 17411 CompileRun("try { throw new Error(); } finally { gc(); }"); |
| 17116 CHECK(try_catch.HasCaught()); | 17412 CHECK(try_catch.HasCaught()); |
| 17117 } | 17413 } |
| OLD | NEW |