| 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 3839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3850 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; | 3850 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; |
| 3851 LOG_API(isolate, "String::WriteUtf8"); | 3851 LOG_API(isolate, "String::WriteUtf8"); |
| 3852 ENTER_V8(isolate); | 3852 ENTER_V8(isolate); |
| 3853 i::Handle<i::String> str = Utils::OpenHandle(this); | 3853 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 3854 if (options & HINT_MANY_WRITES_EXPECTED) { | 3854 if (options & HINT_MANY_WRITES_EXPECTED) { |
| 3855 FlattenString(str); // Flatten the string for efficiency. | 3855 FlattenString(str); // Flatten the string for efficiency. |
| 3856 } | 3856 } |
| 3857 int string_length = str->length(); | 3857 int string_length = str->length(); |
| 3858 if (str->IsAsciiRepresentation()) { | 3858 if (str->IsAsciiRepresentation()) { |
| 3859 int len; | 3859 int len; |
| 3860 if (capacity == kUndefinedLength) { | 3860 if (capacity == -1) { |
| 3861 capacity = str->length() + 1; | 3861 capacity = str->length() + 1; |
| 3862 len = string_length; | 3862 len = string_length; |
| 3863 } else { | 3863 } else { |
| 3864 len = i::Min(capacity, str->length()); | 3864 len = i::Min(capacity, str->length()); |
| 3865 } | 3865 } |
| 3866 i::String::WriteToFlat(*str, buffer, 0, len); | 3866 i::String::WriteToFlat(*str, buffer, 0, len); |
| 3867 if (nchars_ref != NULL) *nchars_ref = len; | 3867 if (nchars_ref != NULL) *nchars_ref = len; |
| 3868 if (!(options & NO_NULL_TERMINATION) && capacity > len) { | 3868 if (!(options & NO_NULL_TERMINATION) && capacity > len) { |
| 3869 buffer[len] = '\0'; | 3869 buffer[len] = '\0'; |
| 3870 return len + 1; | 3870 return len + 1; |
| 3871 } | 3871 } |
| 3872 return len; | 3872 return len; |
| 3873 } | 3873 } |
| 3874 | 3874 |
| 3875 if (capacity == kUndefinedLength || capacity / 3 >= string_length) { | 3875 if (capacity == -1 || capacity / 3 >= string_length) { |
| 3876 int32_t previous = unibrow::Utf16::kNoPreviousCharacter; | 3876 int32_t previous = unibrow::Utf16::kNoPreviousCharacter; |
| 3877 const int kMaxRecursion = 100; | 3877 const int kMaxRecursion = 100; |
| 3878 int utf8_bytes = | 3878 int utf8_bytes = |
| 3879 RecursivelySerializeToUtf8(*str, | 3879 RecursivelySerializeToUtf8(*str, |
| 3880 buffer, | 3880 buffer, |
| 3881 0, | 3881 0, |
| 3882 string_length, | 3882 string_length, |
| 3883 kMaxRecursion, | 3883 kMaxRecursion, |
| 3884 previous, | 3884 previous, |
| 3885 &previous); | 3885 &previous); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3896 // Recurse once. This time around the string is flat and the serializing | 3896 // Recurse once. This time around the string is flat and the serializing |
| 3897 // with recursion will certainly succeed. | 3897 // with recursion will certainly succeed. |
| 3898 return WriteUtf8(buffer, capacity, nchars_ref, options); | 3898 return WriteUtf8(buffer, capacity, nchars_ref, options); |
| 3899 } else if (capacity >= string_length) { | 3899 } else if (capacity >= string_length) { |
| 3900 // First check that the buffer is large enough. If it is, then recurse | 3900 // First check that the buffer is large enough. If it is, then recurse |
| 3901 // once without a capacity limit, which will get into the other branch of | 3901 // once without a capacity limit, which will get into the other branch of |
| 3902 // this 'if'. | 3902 // this 'if'. |
| 3903 int utf8_bytes = i::Utf8Length(str); | 3903 int utf8_bytes = i::Utf8Length(str); |
| 3904 if ((options & NO_NULL_TERMINATION) == 0) utf8_bytes++; | 3904 if ((options & NO_NULL_TERMINATION) == 0) utf8_bytes++; |
| 3905 if (utf8_bytes <= capacity) { | 3905 if (utf8_bytes <= capacity) { |
| 3906 return WriteUtf8(buffer, kUndefinedLength, nchars_ref, options); | 3906 return WriteUtf8(buffer, -1, nchars_ref, options); |
| 3907 } | 3907 } |
| 3908 } | 3908 } |
| 3909 | 3909 |
| 3910 // Slow case. | 3910 // Slow case. |
| 3911 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); | 3911 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); |
| 3912 isolate->string_tracker()->RecordWrite(str); | 3912 isolate->string_tracker()->RecordWrite(str); |
| 3913 | 3913 |
| 3914 write_input_buffer.Reset(0, *str); | 3914 write_input_buffer.Reset(0, *str); |
| 3915 int len = str->length(); | 3915 int len = str->length(); |
| 3916 // Encode the first K - 3 bytes directly into the buffer since we | 3916 // Encode the first K - 3 bytes directly into the buffer since we |
| 3917 // know there's room for them. If no capacity is given we copy all | 3917 // know there's room for them. If no capacity is given we copy all |
| 3918 // of them here. | 3918 // of them here. |
| 3919 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1); | 3919 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1); |
| 3920 int i; | 3920 int i; |
| 3921 int pos = 0; | 3921 int pos = 0; |
| 3922 int nchars = 0; | 3922 int nchars = 0; |
| 3923 int previous = unibrow::Utf16::kNoPreviousCharacter; | 3923 int previous = unibrow::Utf16::kNoPreviousCharacter; |
| 3924 for (i = 0; | 3924 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) { |
| 3925 i < len && (capacity == kUndefinedLength || pos < fast_end); | |
| 3926 i++) { | |
| 3927 i::uc32 c = write_input_buffer.GetNext(); | 3925 i::uc32 c = write_input_buffer.GetNext(); |
| 3928 int written = unibrow::Utf8::Encode(buffer + pos, c, previous); | 3926 int written = unibrow::Utf8::Encode(buffer + pos, c, previous); |
| 3929 pos += written; | 3927 pos += written; |
| 3930 nchars++; | 3928 nchars++; |
| 3931 previous = c; | 3929 previous = c; |
| 3932 } | 3930 } |
| 3933 if (i < len) { | 3931 if (i < len) { |
| 3934 // For the last characters we need to check the length for each one | 3932 // For the last characters we need to check the length for each one |
| 3935 // because they may be longer than the remaining space in the | 3933 // because they may be longer than the remaining space in the |
| 3936 // buffer. | 3934 // buffer. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3962 } else { | 3960 } else { |
| 3963 // We've reached the end of the buffer | 3961 // We've reached the end of the buffer |
| 3964 break; | 3962 break; |
| 3965 } | 3963 } |
| 3966 } | 3964 } |
| 3967 previous = c; | 3965 previous = c; |
| 3968 } | 3966 } |
| 3969 } | 3967 } |
| 3970 if (nchars_ref != NULL) *nchars_ref = nchars; | 3968 if (nchars_ref != NULL) *nchars_ref = nchars; |
| 3971 if (!(options & NO_NULL_TERMINATION) && | 3969 if (!(options & NO_NULL_TERMINATION) && |
| 3972 (i == len && (capacity == kUndefinedLength || pos < capacity))) { | 3970 (i == len && (capacity == -1 || pos < capacity))) { |
| 3973 buffer[pos++] = '\0'; | 3971 buffer[pos++] = '\0'; |
| 3974 } | 3972 } |
| 3975 return pos; | 3973 return pos; |
| 3976 } | 3974 } |
| 3977 | 3975 |
| 3978 | 3976 |
| 3979 int String::WriteAscii(char* buffer, | 3977 int String::WriteAscii(char* buffer, |
| 3980 int start, | 3978 int start, |
| 3981 int length, | 3979 int length, |
| 3982 int options) const { | 3980 int options) const { |
| 3983 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); | 3981 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); |
| 3984 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; | 3982 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; |
| 3985 LOG_API(isolate, "String::WriteAscii"); | 3983 LOG_API(isolate, "String::WriteAscii"); |
| 3986 ENTER_V8(isolate); | 3984 ENTER_V8(isolate); |
| 3987 ASSERT(start >= 0 && length >= kUndefinedLength); | 3985 ASSERT(start >= 0 && length >= -1); |
| 3988 i::Handle<i::String> str = Utils::OpenHandle(this); | 3986 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 3989 isolate->string_tracker()->RecordWrite(str); | 3987 isolate->string_tracker()->RecordWrite(str); |
| 3990 if (options & HINT_MANY_WRITES_EXPECTED) { | 3988 if (options & HINT_MANY_WRITES_EXPECTED) { |
| 3991 FlattenString(str); // Flatten the string for efficiency. | 3989 FlattenString(str); // Flatten the string for efficiency. |
| 3992 } | 3990 } |
| 3993 | 3991 |
| 3994 if (str->IsAsciiRepresentation()) { | 3992 if (str->IsAsciiRepresentation()) { |
| 3995 // WriteToFlat is faster than using the StringInputBuffer. | 3993 // WriteToFlat is faster than using the StringInputBuffer. |
| 3996 if (length == kUndefinedLength) length = str->length() + 1; | 3994 if (length == -1) length = str->length() + 1; |
| 3997 int len = i::Min(length, str->length() - start); | 3995 int len = i::Min(length, str->length() - start); |
| 3998 i::String::WriteToFlat(*str, buffer, start, start + len); | 3996 i::String::WriteToFlat(*str, buffer, start, start + len); |
| 3999 if (!(options & PRESERVE_ASCII_NULL)) { | 3997 if (!(options & PRESERVE_ASCII_NULL)) { |
| 4000 for (int i = 0; i < len; i++) { | 3998 for (int i = 0; i < len; i++) { |
| 4001 if (buffer[i] == '\0') buffer[i] = ' '; | 3999 if (buffer[i] == '\0') buffer[i] = ' '; |
| 4002 } | 4000 } |
| 4003 } | 4001 } |
| 4004 if (!(options & NO_NULL_TERMINATION) && length > len) { | 4002 if (!(options & NO_NULL_TERMINATION) && length > len) { |
| 4005 buffer[len] = '\0'; | 4003 buffer[len] = '\0'; |
| 4006 } | 4004 } |
| 4007 return len; | 4005 return len; |
| 4008 } | 4006 } |
| 4009 | 4007 |
| 4010 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); | 4008 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); |
| 4011 int end = length; | 4009 int end = length; |
| 4012 if ((length == kUndefinedLength) || (length > str->length() - start)) { | 4010 if ((length == -1) || (length > str->length() - start)) { |
| 4013 end = str->length() - start; | 4011 end = str->length() - start; |
| 4014 } | 4012 } |
| 4015 if (end < 0) return 0; | 4013 if (end < 0) return 0; |
| 4016 write_input_buffer.Reset(start, *str); | 4014 write_input_buffer.Reset(start, *str); |
| 4017 int i; | 4015 int i; |
| 4018 for (i = 0; i < end; i++) { | 4016 for (i = 0; i < end; i++) { |
| 4019 char c = static_cast<char>(write_input_buffer.GetNext()); | 4017 char c = static_cast<char>(write_input_buffer.GetNext()); |
| 4020 if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' '; | 4018 if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' '; |
| 4021 buffer[i] = c; | 4019 buffer[i] = c; |
| 4022 } | 4020 } |
| 4023 if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) { | 4021 if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) { |
| 4024 buffer[i] = '\0'; | 4022 buffer[i] = '\0'; |
| 4025 } | 4023 } |
| 4026 return i; | 4024 return i; |
| 4027 } | 4025 } |
| 4028 | 4026 |
| 4029 | 4027 |
| 4030 int String::WriteLatin1(char* buffer, | |
| 4031 int start, | |
| 4032 int length, | |
| 4033 int options) const { | |
| 4034 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); | |
| 4035 if (IsDeadCheck(isolate, "v8::String::WriteLatin1()")) return 0; | |
| 4036 LOG_API(isolate, "String::WriteLatin1"); | |
| 4037 ENTER_V8(isolate); | |
| 4038 ASSERT(start >= 0 && length >= kUndefinedLength); | |
| 4039 i::Handle<i::String> str = Utils::OpenHandle(this); | |
| 4040 isolate->string_tracker()->RecordWrite(str); | |
| 4041 if (options & HINT_MANY_WRITES_EXPECTED) { | |
| 4042 FlattenString(str); // Flatten the string for efficiency. | |
| 4043 } | |
| 4044 | |
| 4045 if (length == kUndefinedLength) length = str->length() + 1; | |
| 4046 int len = i::Min(length, str->length() - start); | |
| 4047 i::String::WriteToFlat(*str, buffer, start, start + len); | |
| 4048 if (!(options & NO_NULL_TERMINATION) && length > len) { | |
| 4049 buffer[len] = '\0'; | |
| 4050 } | |
| 4051 return len; | |
| 4052 } | |
| 4053 | |
| 4054 | |
| 4055 int String::Write(uint16_t* buffer, | 4028 int String::Write(uint16_t* buffer, |
| 4056 int start, | 4029 int start, |
| 4057 int length, | 4030 int length, |
| 4058 int options) const { | 4031 int options) const { |
| 4059 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); | 4032 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); |
| 4060 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0; | 4033 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0; |
| 4061 LOG_API(isolate, "String::Write"); | 4034 LOG_API(isolate, "String::Write"); |
| 4062 ENTER_V8(isolate); | 4035 ENTER_V8(isolate); |
| 4063 ASSERT(start >= 0 && length >= kUndefinedLength); | 4036 ASSERT(start >= 0 && length >= -1); |
| 4064 i::Handle<i::String> str = Utils::OpenHandle(this); | 4037 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 4065 isolate->string_tracker()->RecordWrite(str); | 4038 isolate->string_tracker()->RecordWrite(str); |
| 4066 if (options & HINT_MANY_WRITES_EXPECTED) { | 4039 if (options & HINT_MANY_WRITES_EXPECTED) { |
| 4067 // Flatten the string for efficiency. This applies whether we are | 4040 // Flatten the string for efficiency. This applies whether we are |
| 4068 // using StringInputBuffer or Get(i) to access the characters. | 4041 // using StringInputBuffer or Get(i) to access the characters. |
| 4069 FlattenString(str); | 4042 FlattenString(str); |
| 4070 } | 4043 } |
| 4071 int end = start + length; | 4044 int end = start + length; |
| 4072 if ((length == kUndefinedLength) || (length > str->length() - start) ) | 4045 if ((length == -1) || (length > str->length() - start) ) |
| 4073 end = str->length(); | 4046 end = str->length(); |
| 4074 if (end < 0) return 0; | 4047 if (end < 0) return 0; |
| 4075 i::String::WriteToFlat(*str, buffer, start, end); | 4048 i::String::WriteToFlat(*str, buffer, start, end); |
| 4076 if (!(options & NO_NULL_TERMINATION) && | 4049 if (!(options & NO_NULL_TERMINATION) && |
| 4077 (length == -1 || end - start < length)) { | 4050 (length == -1 || end - start < length)) { |
| 4078 buffer[end - start] = '\0'; | 4051 buffer[end - start] = '\0'; |
| 4079 } | 4052 } |
| 4080 return end - start; | 4053 return end - start; |
| 4081 } | 4054 } |
| 4082 | 4055 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4093 | 4066 |
| 4094 bool v8::String::IsExternalAscii() const { | 4067 bool v8::String::IsExternalAscii() const { |
| 4095 i::Handle<i::String> str = Utils::OpenHandle(this); | 4068 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 4096 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternalAscii()")) { | 4069 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternalAscii()")) { |
| 4097 return false; | 4070 return false; |
| 4098 } | 4071 } |
| 4099 return i::StringShape(*str).IsExternalAscii(); | 4072 return i::StringShape(*str).IsExternalAscii(); |
| 4100 } | 4073 } |
| 4101 | 4074 |
| 4102 | 4075 |
| 4103 void v8::String::VerifyExternalStringEncoding(int encoding) const { | 4076 void v8::String::VerifyExternalStringResource( |
| 4104 typedef internal::Internals I; | 4077 v8::String::ExternalStringResource* value) const { |
| 4105 i::Handle<i::String> str = Utils::OpenHandle(this); | 4078 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 4106 switch (encoding) { | 4079 const v8::String::ExternalStringResource* expected; |
| 4107 case UTF_16_ENCODING | ASCII_HINT: | 4080 if (i::StringShape(*str).IsExternalTwoByte()) { |
| 4108 CHECK(str->HasOnlyAsciiChars()); | 4081 const void* resource = |
| 4109 // Fall through | 4082 i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); |
| 4110 case UTF_16_ENCODING | NOT_ASCII_HINT : | 4083 expected = reinterpret_cast<const ExternalStringResource*>(resource); |
| 4111 CHECK(str->IsExternalTwoByteString()); | 4084 } else { |
| 4112 break; | 4085 expected = NULL; |
| 4113 case LATIN1_ENCODING | ASCII_HINT: | |
| 4114 CHECK(str->IsExternalAsciiString()); | |
| 4115 break; | |
| 4116 default: | |
| 4117 CHECK_EQ(INVALID_ENCODING, encoding); | |
| 4118 CHECK(!str->IsExternalString()); | |
| 4119 break; | |
| 4120 } | 4086 } |
| 4087 CHECK_EQ(expected, value); |
| 4121 } | 4088 } |
| 4122 | 4089 |
| 4123 | 4090 |
| 4124 void v8::String::VerifyExternalStringResourceBase( | |
| 4125 v8::String::ExternalStringResourceBase* value) const { | |
| 4126 i::Handle<i::String> str = Utils::OpenHandle(this); | |
| 4127 i::StringShape shape(*str); | |
| 4128 const void* expected; | |
| 4129 // We expect an external string at this point since GetExternalStringEncoding | |
| 4130 // should have already been called to rule out non-external strings. | |
| 4131 if (i::StringShape(*str).IsExternalTwoByte()) { | |
| 4132 expected = i::ExternalTwoByteString::cast(*str)->resource(); | |
| 4133 } else { | |
| 4134 ASSERT(i::StringShape(*str).IsExternalAscii()); | |
| 4135 expected = i::ExternalAsciiString::cast(*str)->resource(); | |
| 4136 } | |
| 4137 | |
| 4138 CHECK_EQ(expected, | |
| 4139 reinterpret_cast<const ExternalStringResourceBase*>(value)); | |
| 4140 } | |
| 4141 | |
| 4142 | |
| 4143 const v8::String::ExternalAsciiStringResource* | 4091 const v8::String::ExternalAsciiStringResource* |
| 4144 v8::String::GetExternalAsciiStringResource() const { | 4092 v8::String::GetExternalAsciiStringResource() const { |
| 4145 i::Handle<i::String> str = Utils::OpenHandle(this); | 4093 i::Handle<i::String> str = Utils::OpenHandle(this); |
| 4146 if (IsDeadCheck(str->GetIsolate(), | 4094 if (IsDeadCheck(str->GetIsolate(), |
| 4147 "v8::String::GetExternalAsciiStringResource()")) { | 4095 "v8::String::GetExternalAsciiStringResource()")) { |
| 4148 return NULL; | 4096 return NULL; |
| 4149 } | 4097 } |
| 4150 if (i::StringShape(*str).IsExternalAscii()) { | 4098 if (i::StringShape(*str).IsExternalAscii()) { |
| 4151 const void* resource = | 4099 const void* resource = |
| 4152 i::Handle<i::ExternalAsciiString>::cast(str)->resource(); | 4100 i::Handle<i::ExternalAsciiString>::cast(str)->resource(); |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4746 Local<String> v8::String::Empty() { | 4694 Local<String> v8::String::Empty() { |
| 4747 i::Isolate* isolate = i::Isolate::Current(); | 4695 i::Isolate* isolate = i::Isolate::Current(); |
| 4748 if (!EnsureInitializedForIsolate(isolate, "v8::String::Empty()")) { | 4696 if (!EnsureInitializedForIsolate(isolate, "v8::String::Empty()")) { |
| 4749 return v8::Local<String>(); | 4697 return v8::Local<String>(); |
| 4750 } | 4698 } |
| 4751 LOG_API(isolate, "String::Empty()"); | 4699 LOG_API(isolate, "String::Empty()"); |
| 4752 return Utils::ToLocal(isolate->factory()->empty_symbol()); | 4700 return Utils::ToLocal(isolate->factory()->empty_symbol()); |
| 4753 } | 4701 } |
| 4754 | 4702 |
| 4755 | 4703 |
| 4756 static i::Handle<i::String> NewOneByteEncodedString( | 4704 Local<String> v8::String::New(const char* data, int length) { |
| 4757 i::Factory* factory, const char* data, int length, int encoding) { | |
| 4758 if (length == String::kUndefinedLength) length = i::StrLength(data); | |
| 4759 typedef v8::String S; | |
| 4760 | |
| 4761 static const int kAsciiHintShift = 16; | |
| 4762 ASSERT(IS_POWER_OF_TWO(encoding & S::kAsciiHintMask)); | |
| 4763 i::String::AsciiHint ascii_hint = | |
| 4764 static_cast<i::String::AsciiHint>(encoding >> kAsciiHintShift); | |
| 4765 STATIC_ASSERT(i::String::MAYBE_ASCII == 0); | |
| 4766 STATIC_ASSERT(i::String::NOT_ASCII == | |
| 4767 (v8::String::NOT_ASCII_HINT >> kAsciiHintShift)); | |
| 4768 STATIC_ASSERT(i::String::ASCII == | |
| 4769 (v8::String::ASCII_HINT >> kAsciiHintShift)); | |
| 4770 | |
| 4771 int masked_encoding = encoding & S::kStringEncodingMask; | |
| 4772 | |
| 4773 if (masked_encoding == S::UTF_8_ENCODING) { | |
| 4774 return factory->NewStringFromUtf8( | |
| 4775 i::Vector<const char>(data, length), i::NOT_TENURED, ascii_hint); | |
| 4776 } else if (masked_encoding == S::LATIN1_ENCODING) { | |
| 4777 return factory->NewStringFromLatin1( | |
| 4778 i::Vector<const char>(data, length), i::NOT_TENURED, ascii_hint); | |
| 4779 } else { // Wrong encoding. | |
| 4780 return i::Handle<i::String>(); | |
| 4781 } | |
| 4782 } | |
| 4783 | |
| 4784 | |
| 4785 Local<String> v8::String::New( | |
| 4786 const char* data, int length, int encoding) { | |
| 4787 i::Isolate* isolate = i::Isolate::Current(); | 4705 i::Isolate* isolate = i::Isolate::Current(); |
| 4788 EnsureInitializedForIsolate(isolate, "v8::String::New()"); | 4706 EnsureInitializedForIsolate(isolate, "v8::String::New()"); |
| 4789 LOG_API(isolate, "String::New(char)"); | 4707 LOG_API(isolate, "String::New(char)"); |
| 4790 if (length == 0) return Empty(); | 4708 if (length == 0) return Empty(); |
| 4791 ENTER_V8(isolate); | 4709 ENTER_V8(isolate); |
| 4792 return Utils::ToLocal( | 4710 if (length == -1) length = i::StrLength(data); |
| 4793 NewOneByteEncodedString(isolate->factory(), data, length, encoding)); | 4711 i::Handle<i::String> result = |
| 4712 isolate->factory()->NewStringFromUtf8( |
| 4713 i::Vector<const char>(data, length)); |
| 4714 return Utils::ToLocal(result); |
| 4794 } | 4715 } |
| 4795 | 4716 |
| 4796 | 4717 |
| 4797 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) { | 4718 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) { |
| 4798 i::Handle<i::String> left_string = Utils::OpenHandle(*left); | 4719 i::Handle<i::String> left_string = Utils::OpenHandle(*left); |
| 4799 i::Isolate* isolate = left_string->GetIsolate(); | 4720 i::Isolate* isolate = left_string->GetIsolate(); |
| 4800 EnsureInitializedForIsolate(isolate, "v8::String::New()"); | 4721 EnsureInitializedForIsolate(isolate, "v8::String::New()"); |
| 4801 LOG_API(isolate, "String::New(char)"); | 4722 LOG_API(isolate, "String::New(char)"); |
| 4802 ENTER_V8(isolate); | 4723 ENTER_V8(isolate); |
| 4803 i::Handle<i::String> right_string = Utils::OpenHandle(*right); | 4724 i::Handle<i::String> right_string = Utils::OpenHandle(*right); |
| 4804 i::Handle<i::String> result = isolate->factory()->NewConsString(left_string, | 4725 i::Handle<i::String> result = isolate->factory()->NewConsString(left_string, |
| 4805 right_string); | 4726 right_string); |
| 4806 return Utils::ToLocal(result); | 4727 return Utils::ToLocal(result); |
| 4807 } | 4728 } |
| 4808 | 4729 |
| 4809 | 4730 |
| 4810 Local<String> v8::String::NewUndetectable( | 4731 Local<String> v8::String::NewUndetectable(const char* data, int length) { |
| 4811 const char* data, int length, int encoding) { | |
| 4812 i::Isolate* isolate = i::Isolate::Current(); | 4732 i::Isolate* isolate = i::Isolate::Current(); |
| 4813 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); | 4733 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); |
| 4814 LOG_API(isolate, "String::NewUndetectable(char)"); | 4734 LOG_API(isolate, "String::NewUndetectable(char)"); |
| 4815 ENTER_V8(isolate); | 4735 ENTER_V8(isolate); |
| 4736 if (length == -1) length = i::StrLength(data); |
| 4816 i::Handle<i::String> result = | 4737 i::Handle<i::String> result = |
| 4817 NewOneByteEncodedString(isolate->factory(), data, length, encoding); | 4738 isolate->factory()->NewStringFromUtf8( |
| 4739 i::Vector<const char>(data, length)); |
| 4818 result->MarkAsUndetectable(); | 4740 result->MarkAsUndetectable(); |
| 4819 return Utils::ToLocal(result); | 4741 return Utils::ToLocal(result); |
| 4820 } | 4742 } |
| 4821 | 4743 |
| 4822 | 4744 |
| 4823 static int TwoByteStringLength(const uint16_t* data) { | 4745 static int TwoByteStringLength(const uint16_t* data) { |
| 4824 int length = 0; | 4746 int length = 0; |
| 4825 while (data[length] != '\0') length++; | 4747 while (data[length] != '\0') length++; |
| 4826 return length; | 4748 return length; |
| 4827 } | 4749 } |
| 4828 | 4750 |
| 4829 | 4751 |
| 4830 Local<String> v8::String::New(const uint16_t* data, int length) { | 4752 Local<String> v8::String::New(const uint16_t* data, int length) { |
| 4831 i::Isolate* isolate = i::Isolate::Current(); | 4753 i::Isolate* isolate = i::Isolate::Current(); |
| 4832 EnsureInitializedForIsolate(isolate, "v8::String::New()"); | 4754 EnsureInitializedForIsolate(isolate, "v8::String::New()"); |
| 4833 LOG_API(isolate, "String::New(uint16_)"); | 4755 LOG_API(isolate, "String::New(uint16_)"); |
| 4834 if (length == 0) return Empty(); | 4756 if (length == 0) return Empty(); |
| 4835 ENTER_V8(isolate); | 4757 ENTER_V8(isolate); |
| 4836 if (length == kUndefinedLength) length = TwoByteStringLength(data); | 4758 if (length == -1) length = TwoByteStringLength(data); |
| 4837 i::Handle<i::String> result = | 4759 i::Handle<i::String> result = |
| 4838 isolate->factory()->NewStringFromTwoByte( | 4760 isolate->factory()->NewStringFromTwoByte( |
| 4839 i::Vector<const uint16_t>(data, length)); | 4761 i::Vector<const uint16_t>(data, length)); |
| 4840 return Utils::ToLocal(result); | 4762 return Utils::ToLocal(result); |
| 4841 } | 4763 } |
| 4842 | 4764 |
| 4843 | 4765 |
| 4844 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) { | 4766 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) { |
| 4845 i::Isolate* isolate = i::Isolate::Current(); | 4767 i::Isolate* isolate = i::Isolate::Current(); |
| 4846 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); | 4768 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); |
| 4847 LOG_API(isolate, "String::NewUndetectable(uint16_)"); | 4769 LOG_API(isolate, "String::NewUndetectable(uint16_)"); |
| 4848 ENTER_V8(isolate); | 4770 ENTER_V8(isolate); |
| 4849 if (length == kUndefinedLength) length = TwoByteStringLength(data); | 4771 if (length == -1) length = TwoByteStringLength(data); |
| 4850 i::Handle<i::String> result = | 4772 i::Handle<i::String> result = |
| 4851 isolate->factory()->NewStringFromTwoByte( | 4773 isolate->factory()->NewStringFromTwoByte( |
| 4852 i::Vector<const uint16_t>(data, length)); | 4774 i::Vector<const uint16_t>(data, length)); |
| 4853 result->MarkAsUndetectable(); | 4775 result->MarkAsUndetectable(); |
| 4854 return Utils::ToLocal(result); | 4776 return Utils::ToLocal(result); |
| 4855 } | 4777 } |
| 4856 | 4778 |
| 4857 | 4779 |
| 4858 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate, | 4780 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate, |
| 4859 v8::String::ExternalStringResource* resource) { | 4781 v8::String::ExternalStringResource* resource) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4877 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); | 4799 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); |
| 4878 LOG_API(isolate, "String::NewExternal"); | 4800 LOG_API(isolate, "String::NewExternal"); |
| 4879 ENTER_V8(isolate); | 4801 ENTER_V8(isolate); |
| 4880 CHECK(resource && resource->data()); | 4802 CHECK(resource && resource->data()); |
| 4881 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); | 4803 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); |
| 4882 isolate->heap()->external_string_table()->AddString(*result); | 4804 isolate->heap()->external_string_table()->AddString(*result); |
| 4883 return Utils::ToLocal(result); | 4805 return Utils::ToLocal(result); |
| 4884 } | 4806 } |
| 4885 | 4807 |
| 4886 | 4808 |
| 4887 template<class StringResourceType> | 4809 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 4888 static bool MakeStringExternal( | 4810 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 4889 i::Handle<i::String> string, StringResourceType* resource) { | 4811 i::Isolate* isolate = obj->GetIsolate(); |
| 4890 i::Isolate* isolate = string->GetIsolate(); | |
| 4891 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; | 4812 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; |
| 4892 if (i::StringShape(*string).IsExternal()) { | 4813 if (i::StringShape(*obj).IsExternalTwoByte()) { |
| 4893 return false; // Already an external string. | 4814 return false; // Already an external string. |
| 4894 } | 4815 } |
| 4895 ENTER_V8(isolate); | 4816 ENTER_V8(isolate); |
| 4896 if (isolate->string_tracker()->IsFreshUnusedString(string)) { | 4817 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { |
| 4897 return false; | 4818 return false; |
| 4898 } | 4819 } |
| 4899 if (isolate->heap()->IsInGCPostProcessing()) { | 4820 if (isolate->heap()->IsInGCPostProcessing()) { |
| 4900 return false; | 4821 return false; |
| 4901 } | 4822 } |
| 4902 CHECK(resource && resource->data()); | 4823 CHECK(resource && resource->data()); |
| 4903 bool result = string->MakeExternal(resource); | 4824 bool result = obj->MakeExternal(resource); |
| 4904 if (result && !string->IsSymbol()) { | 4825 if (result && !obj->IsSymbol()) { |
| 4905 isolate->heap()->external_string_table()->AddString(*string); | 4826 isolate->heap()->external_string_table()->AddString(*obj); |
| 4906 } | 4827 } |
| 4907 return result; | 4828 return result; |
| 4908 } | 4829 } |
| 4909 | 4830 |
| 4910 | 4831 |
| 4911 bool v8::String::MakeExternal(ExternalStringResource* resource) { | |
| 4912 i::Handle<i::String> obj = Utils::OpenHandle(this); | |
| 4913 return MakeStringExternal(obj, resource); | |
| 4914 } | |
| 4915 | |
| 4916 | |
| 4917 bool v8::String::MakeExternal(ExternalAsciiStringResource* resource) { | |
| 4918 i::Handle<i::String> obj = Utils::OpenHandle(this); | |
| 4919 ASSERT(obj->HasOnlyAsciiChars()); | |
| 4920 return MakeStringExternal(obj, resource); | |
| 4921 } | |
| 4922 | |
| 4923 | |
| 4924 Local<String> v8::String::NewExternal( | 4832 Local<String> v8::String::NewExternal( |
| 4925 v8::String::ExternalAsciiStringResource* resource) { | 4833 v8::String::ExternalAsciiStringResource* resource) { |
| 4926 i::Isolate* isolate = i::Isolate::Current(); | 4834 i::Isolate* isolate = i::Isolate::Current(); |
| 4927 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); | 4835 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); |
| 4928 LOG_API(isolate, "String::NewExternal"); | 4836 LOG_API(isolate, "String::NewExternal"); |
| 4929 ENTER_V8(isolate); | 4837 ENTER_V8(isolate); |
| 4930 CHECK(resource && resource->data()); | 4838 CHECK(resource && resource->data()); |
| 4931 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); | 4839 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); |
| 4932 isolate->heap()->external_string_table()->AddString(*result); | 4840 isolate->heap()->external_string_table()->AddString(*result); |
| 4933 return Utils::ToLocal(result); | 4841 return Utils::ToLocal(result); |
| 4934 } | 4842 } |
| 4935 | 4843 |
| 4936 | 4844 |
| 4937 Local<String> v8::String::NewExternal(ExternalLatin1StringResource* resource, | 4845 bool v8::String::MakeExternal( |
| 4938 int encoding) { | 4846 v8::String::ExternalAsciiStringResource* resource) { |
| 4939 typedef v8::internal::Internals I; | 4847 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 4940 i::Isolate* isolate = i::Isolate::Current(); | 4848 i::Isolate* isolate = obj->GetIsolate(); |
| 4941 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); | 4849 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; |
| 4942 LOG_API(isolate, "String::NewExternal"); | 4850 if (i::StringShape(*obj).IsExternalTwoByte()) { |
| 4851 return false; // Already an external string. |
| 4852 } |
| 4943 ENTER_V8(isolate); | 4853 ENTER_V8(isolate); |
| 4944 ASSERT((encoding & kStringEncodingMask) == LATIN1_ENCODING); | 4854 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { |
| 4855 return false; |
| 4856 } |
| 4857 if (isolate->heap()->IsInGCPostProcessing()) { |
| 4858 return false; |
| 4859 } |
| 4945 CHECK(resource && resource->data()); | 4860 CHECK(resource && resource->data()); |
| 4946 int ascii_hint = (encoding & kAsciiHintMask); | 4861 bool result = obj->MakeExternal(resource); |
| 4947 i::Handle<i::String> result; | 4862 if (result && !obj->IsSymbol()) { |
| 4948 | 4863 isolate->heap()->external_string_table()->AddString(*obj); |
| 4949 if (ascii_hint == ASCII_HINT || | |
| 4950 (ascii_hint != NOT_ASCII_HINT && | |
| 4951 i::String::IsAscii(resource->data(), | |
| 4952 static_cast<int>(resource->length())))) { | |
| 4953 // Assert that the ascii hint is correct. | |
| 4954 ASSERT(ascii_hint != ASCII_HINT || | |
| 4955 i::String::IsAscii(resource->data(), | |
| 4956 static_cast<int>(resource->length()))); | |
| 4957 result = NewExternalAsciiStringHandle(isolate, resource); | |
| 4958 isolate->heap()->external_string_table()->AddString(*result); | |
| 4959 } else { | |
| 4960 // We cannot simply take the backing store and use it as an ASCII string, | |
| 4961 // since it's not. Instead, we convert it to an internal string and dispose | |
| 4962 // the external resource. | |
| 4963 result = isolate->factory()->NewStringFromLatin1( | |
| 4964 i::Vector<const char>(resource->data(), | |
| 4965 static_cast<int>(resource->length())), | |
| 4966 i::NOT_TENURED, | |
| 4967 i::String::NOT_ASCII); | |
| 4968 resource->Dispose(); | |
| 4969 } | 4864 } |
| 4970 return Utils::ToLocal(result); | 4865 return result; |
| 4971 } | 4866 } |
| 4972 | 4867 |
| 4973 | 4868 |
| 4974 bool v8::String::CanMakeExternal() { | 4869 bool v8::String::CanMakeExternal() { |
| 4975 if (!internal::FLAG_clever_optimizations) return false; | 4870 if (!internal::FLAG_clever_optimizations) return false; |
| 4976 i::Handle<i::String> obj = Utils::OpenHandle(this); | 4871 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 4977 i::Isolate* isolate = obj->GetIsolate(); | 4872 i::Isolate* isolate = obj->GetIsolate(); |
| 4978 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false; | 4873 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false; |
| 4979 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false; | 4874 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false; |
| 4980 int size = obj->Size(); // Byte size of the original string. | 4875 int size = obj->Size(); // Byte size of the original string. |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5223 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon)); | 5118 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon)); |
| 5224 EXCEPTION_PREAMBLE(isolate); | 5119 EXCEPTION_PREAMBLE(isolate); |
| 5225 ENTER_V8(isolate); | 5120 ENTER_V8(isolate); |
| 5226 i::Handle<i::JSObject> result = i::Copy(paragon_handle); | 5121 i::Handle<i::JSObject> result = i::Copy(paragon_handle); |
| 5227 has_pending_exception = result.is_null(); | 5122 has_pending_exception = result.is_null(); |
| 5228 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); | 5123 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); |
| 5229 return Utils::ToLocal(result); | 5124 return Utils::ToLocal(result); |
| 5230 } | 5125 } |
| 5231 | 5126 |
| 5232 | 5127 |
| 5233 Local<String> v8::String::NewSymbol( | 5128 Local<String> v8::String::NewSymbol(const char* data, int length) { |
| 5234 const char* data, int length, int encoding) { | |
| 5235 i::Isolate* isolate = i::Isolate::Current(); | 5129 i::Isolate* isolate = i::Isolate::Current(); |
| 5236 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()"); | 5130 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()"); |
| 5237 LOG_API(isolate, "String::NewSymbol(char)"); | 5131 LOG_API(isolate, "String::NewSymbol(char)"); |
| 5238 ENTER_V8(isolate); | 5132 ENTER_V8(isolate); |
| 5239 if (length == kUndefinedLength) length = i::StrLength(data); | 5133 if (length == -1) length = i::StrLength(data); |
| 5240 i::Handle<i::String> result; | 5134 i::Handle<i::String> result = |
| 5241 | 5135 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length)); |
| 5242 ASSERT(IS_POWER_OF_TWO(encoding & kAsciiHintMask)); | |
| 5243 if (((encoding & kStringEncodingMask) == LATIN1_ENCODING) && | |
| 5244 ((encoding & kAsciiHintMask) == NOT_ASCII_HINT || | |
| 5245 !i::String::IsAscii(data, length))) { | |
| 5246 result = isolate->factory()->NewStringFromLatin1( | |
| 5247 i::Vector<const char>(data, length), | |
| 5248 i::NOT_TENURED, | |
| 5249 i::String::NOT_ASCII); | |
| 5250 result = isolate->factory()->LookupSymbol(result); | |
| 5251 } else { // We can handle UTF8 and ASCII strings here. | |
| 5252 result = | |
| 5253 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length)); | |
| 5254 } | |
| 5255 return Utils::ToLocal(result); | 5136 return Utils::ToLocal(result); |
| 5256 } | 5137 } |
| 5257 | 5138 |
| 5258 | 5139 |
| 5259 Local<Number> v8::Number::New(double value) { | 5140 Local<Number> v8::Number::New(double value) { |
| 5260 i::Isolate* isolate = i::Isolate::Current(); | 5141 i::Isolate* isolate = i::Isolate::Current(); |
| 5261 EnsureInitializedForIsolate(isolate, "v8::Number::New()"); | 5142 EnsureInitializedForIsolate(isolate, "v8::Number::New()"); |
| 5262 if (isnan(value)) { | 5143 if (isnan(value)) { |
| 5263 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. | 5144 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. |
| 5264 value = i::OS::nan_value(); | 5145 value = i::OS::nan_value(); |
| (...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6654 | 6535 |
| 6655 v->VisitPointers(blocks_.first(), first_block_limit_); | 6536 v->VisitPointers(blocks_.first(), first_block_limit_); |
| 6656 | 6537 |
| 6657 for (int i = 1; i < blocks_.length(); i++) { | 6538 for (int i = 1; i < blocks_.length(); i++) { |
| 6658 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); | 6539 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); |
| 6659 } | 6540 } |
| 6660 } | 6541 } |
| 6661 | 6542 |
| 6662 | 6543 |
| 6663 } } // namespace v8::internal | 6544 } } // namespace v8::internal |
| OLD | NEW |