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::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::UTF_16_ENCODING | String::NOT_ASCII_HINT, |
| 776 two_byte_external->GetExternalStringEncoding()); |
| 777 CHECK_EQ(String::UTF_16_ENCODING | String::ASCII_HINT, |
| 778 two_byte_ascii_external->GetExternalStringEncoding()); |
| 779 CHECK_EQ(String::LATIN1_ENCODING | String::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::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::ASCII_HINT)); |
| 912 CHECK_EQ(latin1_ascii_b_external->GetExternalStringEncoding(), |
| 913 (v8::String::LATIN1_ENCODING | v8::String::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 = String::New("latin1 non-ascii \xAA", |
| 939 String::kUndefinedLength, |
| 940 String::LATIN1_ENCODING); |
| 941 |
| 942 CHECK(v8::Utils::OpenHandle(*latin1_a_ascii)->IsSeqAsciiString()); |
| 943 CHECK(v8::Utils::OpenHandle(*latin1_b_ascii)->IsSeqAsciiString()); |
| 944 CHECK(v8::Utils::OpenHandle(*latin1)->IsSeqTwoByteString()); |
| 945 |
| 946 // Run GC twice to put those strings into old space for externalizing. |
| 947 HEAP->CollectGarbage(i::NEW_SPACE); |
| 948 HEAP->CollectGarbage(i::NEW_SPACE); |
| 949 |
| 950 char* latin1_a_ascii_chars = i::NewArray<char>(64); |
| 951 uint16_t* latin1_b_ascii_chars = i::NewArray<uint16_t>(64); |
| 952 uint16_t* latin1_chars = i::NewArray<uint16_t>(64); |
| 953 |
| 954 latin1_a_ascii->WriteLatin1(latin1_a_ascii_chars); |
| 955 latin1_b_ascii->Write(latin1_b_ascii_chars); |
| 956 latin1->Write(latin1_chars); |
| 957 |
| 958 TestLatin1Resource* latin1_a_ascii_resource = |
| 959 new TestLatin1Resource(latin1_a_ascii_chars, &counter); |
| 960 TestResource* latin1_b_ascii_resource = |
| 961 new TestResource(latin1_b_ascii_chars, &counter); |
| 962 TestResource* latin1_resource = |
| 963 new TestResource(latin1_chars, &counter); |
| 964 |
| 965 CHECK(latin1_a_ascii->MakeExternal(latin1_a_ascii_resource)); |
| 966 CHECK(latin1_a_ascii->IsExternalAscii()); |
| 967 CHECK_EQ(latin1_a_ascii->GetExternalStringEncoding(), |
| 968 (v8::String::LATIN1_ENCODING | v8::String::ASCII_HINT)); |
| 969 CHECK_EQ(latin1_a_ascii_resource, |
| 970 latin1_a_ascii->GetExternalStringResourceBase()); |
| 971 CHECK(latin1_a_ascii->Equals(String::New("latin1 a ascii"))); |
| 972 |
| 973 CHECK(latin1_b_ascii->MakeExternal(latin1_b_ascii_resource)); |
| 974 CHECK(latin1_b_ascii->IsExternal()); |
| 975 CHECK_EQ(latin1_b_ascii->GetExternalStringEncoding(), |
| 976 (v8::String::UTF_16_ENCODING | v8::String::ASCII_HINT)); |
| 977 CHECK_EQ(latin1_b_ascii_resource, |
| 978 latin1_b_ascii->GetExternalStringResourceBase()); |
| 979 CHECK(latin1_b_ascii->Equals(String::New("latin1 b ascii"))); |
| 980 |
| 981 CHECK(latin1->MakeExternal(latin1_resource)); |
| 982 CHECK(latin1->IsExternal()); |
| 983 CHECK_EQ(latin1->GetExternalStringEncoding(), |
| 984 (v8::String::UTF_16_ENCODING | v8::String::NOT_ASCII_HINT)); |
| 985 CHECK_EQ(latin1_resource, |
| 986 latin1->GetExternalStringResourceBase()); |
| 987 CHECK(latin1->Equals(String::New("latin1 non-ascii \xAA", |
| 988 String::kUndefinedLength, |
| 989 String::LATIN1_ENCODING))); |
| 990 } |
| 991 |
| 992 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 993 CHECK_EQ(3, counter); |
| 994 } |
| 995 |
| 996 |
712 THREADED_TEST(StringConcat) { | 997 THREADED_TEST(StringConcat) { |
713 { | 998 { |
714 v8::HandleScope scope; | 999 HandleScope scope; |
715 LocalContext env; | 1000 LocalContext env; |
716 const char* one_byte_string_1 = "function a_times_t"; | 1001 const char* one_byte_string_1 = "function a_times_t"; |
717 const char* two_byte_string_1 = "wo_plus_b(a, b) {return "; | 1002 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) + "; | 1003 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) + "; | 1004 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) + "; | 1005 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) + "; | 1006 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);"; | 1007 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);"; |
723 Local<String> left = v8_str(one_byte_string_1); | 1008 Local<String> left = v8_str(one_byte_string_1); |
724 | 1009 |
(...skipping 16419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17144 v8::HandleScope scope; | 17429 v8::HandleScope scope; |
17145 LocalContext context; | 17430 LocalContext context; |
17146 | 17431 |
17147 // Compile a try-finally clause where the finally block causes a GC | 17432 // Compile a try-finally clause where the finally block causes a GC |
17148 // while there still is a message pending for external reporting. | 17433 // while there still is a message pending for external reporting. |
17149 TryCatch try_catch; | 17434 TryCatch try_catch; |
17150 try_catch.SetVerbose(true); | 17435 try_catch.SetVerbose(true); |
17151 CompileRun("try { throw new Error(); } finally { gc(); }"); | 17436 CompileRun("try { throw new Error(); } finally { gc(); }"); |
17152 CHECK(try_catch.HasCaught()); | 17437 CHECK(try_catch.HasCaught()); |
17153 } | 17438 } |
OLD | NEW |