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 == -1) { | 3860 if (capacity == kUndefinedLength) { |
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 == -1 || capacity / 3 >= string_length) { | 3875 if (capacity == kUndefinedLength || 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, -1, nchars_ref, options); | 3906 return WriteUtf8(buffer, kUndefinedLength, 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; i < len && (capacity == -1 || pos < fast_end); i++) { | 3924 for (i = 0; |
| 3925 i < len && (capacity == kUndefinedLength || pos < fast_end); |
| 3926 i++) { |
3925 i::uc32 c = write_input_buffer.GetNext(); | 3927 i::uc32 c = write_input_buffer.GetNext(); |
3926 int written = unibrow::Utf8::Encode(buffer + pos, c, previous); | 3928 int written = unibrow::Utf8::Encode(buffer + pos, c, previous); |
3927 pos += written; | 3929 pos += written; |
3928 nchars++; | 3930 nchars++; |
3929 previous = c; | 3931 previous = c; |
3930 } | 3932 } |
3931 if (i < len) { | 3933 if (i < len) { |
3932 // For the last characters we need to check the length for each one | 3934 // For the last characters we need to check the length for each one |
3933 // because they may be longer than the remaining space in the | 3935 // because they may be longer than the remaining space in the |
3934 // buffer. | 3936 // buffer. |
(...skipping 25 matching lines...) Expand all Loading... |
3960 } else { | 3962 } else { |
3961 // We've reached the end of the buffer | 3963 // We've reached the end of the buffer |
3962 break; | 3964 break; |
3963 } | 3965 } |
3964 } | 3966 } |
3965 previous = c; | 3967 previous = c; |
3966 } | 3968 } |
3967 } | 3969 } |
3968 if (nchars_ref != NULL) *nchars_ref = nchars; | 3970 if (nchars_ref != NULL) *nchars_ref = nchars; |
3969 if (!(options & NO_NULL_TERMINATION) && | 3971 if (!(options & NO_NULL_TERMINATION) && |
3970 (i == len && (capacity == -1 || pos < capacity))) { | 3972 (i == len && (capacity == kUndefinedLength || pos < capacity))) { |
3971 buffer[pos++] = '\0'; | 3973 buffer[pos++] = '\0'; |
3972 } | 3974 } |
3973 return pos; | 3975 return pos; |
3974 } | 3976 } |
3975 | 3977 |
3976 | 3978 |
3977 int String::WriteAscii(char* buffer, | 3979 int String::WriteAscii(char* buffer, |
3978 int start, | 3980 int start, |
3979 int length, | 3981 int length, |
3980 int options) const { | 3982 int options) const { |
3981 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); | 3983 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); |
3982 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; | 3984 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; |
3983 LOG_API(isolate, "String::WriteAscii"); | 3985 LOG_API(isolate, "String::WriteAscii"); |
3984 ENTER_V8(isolate); | 3986 ENTER_V8(isolate); |
3985 ASSERT(start >= 0 && length >= -1); | 3987 ASSERT(start >= 0 && length >= kUndefinedLength); |
3986 i::Handle<i::String> str = Utils::OpenHandle(this); | 3988 i::Handle<i::String> str = Utils::OpenHandle(this); |
3987 isolate->string_tracker()->RecordWrite(str); | 3989 isolate->string_tracker()->RecordWrite(str); |
3988 if (options & HINT_MANY_WRITES_EXPECTED) { | 3990 if (options & HINT_MANY_WRITES_EXPECTED) { |
3989 FlattenString(str); // Flatten the string for efficiency. | 3991 FlattenString(str); // Flatten the string for efficiency. |
3990 } | 3992 } |
3991 | 3993 |
3992 if (str->IsAsciiRepresentation()) { | 3994 if (str->IsAsciiRepresentation()) { |
3993 // WriteToFlat is faster than using the StringInputBuffer. | 3995 // WriteToFlat is faster than using the StringInputBuffer. |
3994 if (length == -1) length = str->length() + 1; | 3996 if (length == kUndefinedLength) length = str->length() + 1; |
3995 int len = i::Min(length, str->length() - start); | 3997 int len = i::Min(length, str->length() - start); |
3996 i::String::WriteToFlat(*str, buffer, start, start + len); | 3998 i::String::WriteToFlat(*str, buffer, start, start + len); |
3997 if (!(options & PRESERVE_ASCII_NULL)) { | 3999 if (!(options & PRESERVE_ASCII_NULL)) { |
3998 for (int i = 0; i < len; i++) { | 4000 for (int i = 0; i < len; i++) { |
3999 if (buffer[i] == '\0') buffer[i] = ' '; | 4001 if (buffer[i] == '\0') buffer[i] = ' '; |
4000 } | 4002 } |
4001 } | 4003 } |
4002 if (!(options & NO_NULL_TERMINATION) && length > len) { | 4004 if (!(options & NO_NULL_TERMINATION) && length > len) { |
4003 buffer[len] = '\0'; | 4005 buffer[len] = '\0'; |
4004 } | 4006 } |
4005 return len; | 4007 return len; |
4006 } | 4008 } |
4007 | 4009 |
4008 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); | 4010 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); |
4009 int end = length; | 4011 int end = length; |
4010 if ((length == -1) || (length > str->length() - start)) { | 4012 if ((length == kUndefinedLength) || (length > str->length() - start)) { |
4011 end = str->length() - start; | 4013 end = str->length() - start; |
4012 } | 4014 } |
4013 if (end < 0) return 0; | 4015 if (end < 0) return 0; |
4014 write_input_buffer.Reset(start, *str); | 4016 write_input_buffer.Reset(start, *str); |
4015 int i; | 4017 int i; |
4016 for (i = 0; i < end; i++) { | 4018 for (i = 0; i < end; i++) { |
4017 char c = static_cast<char>(write_input_buffer.GetNext()); | 4019 char c = static_cast<char>(write_input_buffer.GetNext()); |
4018 if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' '; | 4020 if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' '; |
4019 buffer[i] = c; | 4021 buffer[i] = c; |
4020 } | 4022 } |
4021 if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) { | 4023 if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) { |
4022 buffer[i] = '\0'; | 4024 buffer[i] = '\0'; |
4023 } | 4025 } |
4024 return i; | 4026 return i; |
4025 } | 4027 } |
4026 | 4028 |
4027 | 4029 |
| 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 |
4028 int String::Write(uint16_t* buffer, | 4055 int String::Write(uint16_t* buffer, |
4029 int start, | 4056 int start, |
4030 int length, | 4057 int length, |
4031 int options) const { | 4058 int options) const { |
4032 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); | 4059 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); |
4033 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0; | 4060 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0; |
4034 LOG_API(isolate, "String::Write"); | 4061 LOG_API(isolate, "String::Write"); |
4035 ENTER_V8(isolate); | 4062 ENTER_V8(isolate); |
4036 ASSERT(start >= 0 && length >= -1); | 4063 ASSERT(start >= 0 && length >= kUndefinedLength); |
4037 i::Handle<i::String> str = Utils::OpenHandle(this); | 4064 i::Handle<i::String> str = Utils::OpenHandle(this); |
4038 isolate->string_tracker()->RecordWrite(str); | 4065 isolate->string_tracker()->RecordWrite(str); |
4039 if (options & HINT_MANY_WRITES_EXPECTED) { | 4066 if (options & HINT_MANY_WRITES_EXPECTED) { |
4040 // Flatten the string for efficiency. This applies whether we are | 4067 // Flatten the string for efficiency. This applies whether we are |
4041 // using StringInputBuffer or Get(i) to access the characters. | 4068 // using StringInputBuffer or Get(i) to access the characters. |
4042 FlattenString(str); | 4069 FlattenString(str); |
4043 } | 4070 } |
4044 int end = start + length; | 4071 int end = start + length; |
4045 if ((length == -1) || (length > str->length() - start) ) | 4072 if ((length == kUndefinedLength) || (length > str->length() - start) ) |
4046 end = str->length(); | 4073 end = str->length(); |
4047 if (end < 0) return 0; | 4074 if (end < 0) return 0; |
4048 i::String::WriteToFlat(*str, buffer, start, end); | 4075 i::String::WriteToFlat(*str, buffer, start, end); |
4049 if (!(options & NO_NULL_TERMINATION) && | 4076 if (!(options & NO_NULL_TERMINATION) && |
4050 (length == -1 || end - start < length)) { | 4077 (length == -1 || end - start < length)) { |
4051 buffer[end - start] = '\0'; | 4078 buffer[end - start] = '\0'; |
4052 } | 4079 } |
4053 return end - start; | 4080 return end - start; |
4054 } | 4081 } |
4055 | 4082 |
(...skipping 10 matching lines...) Expand all Loading... |
4066 | 4093 |
4067 bool v8::String::IsExternalAscii() const { | 4094 bool v8::String::IsExternalAscii() const { |
4068 i::Handle<i::String> str = Utils::OpenHandle(this); | 4095 i::Handle<i::String> str = Utils::OpenHandle(this); |
4069 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternalAscii()")) { | 4096 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternalAscii()")) { |
4070 return false; | 4097 return false; |
4071 } | 4098 } |
4072 return i::StringShape(*str).IsExternalAscii(); | 4099 return i::StringShape(*str).IsExternalAscii(); |
4073 } | 4100 } |
4074 | 4101 |
4075 | 4102 |
4076 void v8::String::VerifyExternalStringResource( | 4103 void v8::String::VerifyExternalStringEncoding(int encoding) const { |
4077 v8::String::ExternalStringResource* value) const { | 4104 typedef internal::Internals I; |
4078 i::Handle<i::String> str = Utils::OpenHandle(this); | 4105 i::Handle<i::String> str = Utils::OpenHandle(this); |
4079 const v8::String::ExternalStringResource* expected; | 4106 switch (encoding) { |
4080 if (i::StringShape(*str).IsExternalTwoByte()) { | 4107 case UTF_16_ENCODING | ASCII_HINT: |
4081 const void* resource = | 4108 CHECK(str->HasOnlyAsciiChars()); |
4082 i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); | 4109 // Fall through |
4083 expected = reinterpret_cast<const ExternalStringResource*>(resource); | 4110 case UTF_16_ENCODING | NOT_ASCII_HINT : |
4084 } else { | 4111 CHECK(str->IsExternalTwoByteString()); |
4085 expected = NULL; | 4112 break; |
| 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; |
4086 } | 4120 } |
4087 CHECK_EQ(expected, value); | |
4088 } | 4121 } |
4089 | 4122 |
4090 | 4123 |
| 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 |
4091 const v8::String::ExternalAsciiStringResource* | 4143 const v8::String::ExternalAsciiStringResource* |
4092 v8::String::GetExternalAsciiStringResource() const { | 4144 v8::String::GetExternalAsciiStringResource() const { |
4093 i::Handle<i::String> str = Utils::OpenHandle(this); | 4145 i::Handle<i::String> str = Utils::OpenHandle(this); |
4094 if (IsDeadCheck(str->GetIsolate(), | 4146 if (IsDeadCheck(str->GetIsolate(), |
4095 "v8::String::GetExternalAsciiStringResource()")) { | 4147 "v8::String::GetExternalAsciiStringResource()")) { |
4096 return NULL; | 4148 return NULL; |
4097 } | 4149 } |
4098 if (i::StringShape(*str).IsExternalAscii()) { | 4150 if (i::StringShape(*str).IsExternalAscii()) { |
4099 const void* resource = | 4151 const void* resource = |
4100 i::Handle<i::ExternalAsciiString>::cast(str)->resource(); | 4152 i::Handle<i::ExternalAsciiString>::cast(str)->resource(); |
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4685 Local<String> v8::String::Empty() { | 4737 Local<String> v8::String::Empty() { |
4686 i::Isolate* isolate = i::Isolate::Current(); | 4738 i::Isolate* isolate = i::Isolate::Current(); |
4687 if (!EnsureInitializedForIsolate(isolate, "v8::String::Empty()")) { | 4739 if (!EnsureInitializedForIsolate(isolate, "v8::String::Empty()")) { |
4688 return v8::Local<String>(); | 4740 return v8::Local<String>(); |
4689 } | 4741 } |
4690 LOG_API(isolate, "String::Empty()"); | 4742 LOG_API(isolate, "String::Empty()"); |
4691 return Utils::ToLocal(isolate->factory()->empty_symbol()); | 4743 return Utils::ToLocal(isolate->factory()->empty_symbol()); |
4692 } | 4744 } |
4693 | 4745 |
4694 | 4746 |
4695 Local<String> v8::String::New(const char* data, int length) { | 4747 static i::Handle<i::String> NewOneByteEncodedString( |
| 4748 i::Factory* factory, const char* data, int length, int encoding) { |
| 4749 if (length == String::kUndefinedLength) length = i::StrLength(data); |
| 4750 typedef v8::String S; |
| 4751 |
| 4752 static const int kAsciiHintShift = 16; |
| 4753 ASSERT(IS_POWER_OF_TWO(encoding & S::kAsciiHintMask)); |
| 4754 i::String::AsciiHint ascii_hint = |
| 4755 static_cast<i::String::AsciiHint>(encoding >> kAsciiHintShift); |
| 4756 STATIC_ASSERT(i::String::MAYBE_ASCII == 0); |
| 4757 STATIC_ASSERT(i::String::NOT_ASCII == |
| 4758 (v8::String::NOT_ASCII_HINT >> kAsciiHintShift)); |
| 4759 STATIC_ASSERT(i::String::ASCII == |
| 4760 (v8::String::ASCII_HINT >> kAsciiHintShift)); |
| 4761 |
| 4762 int masked_encoding = encoding & S::kStringEncodingMask; |
| 4763 |
| 4764 if (masked_encoding == S::UTF_8_ENCODING) { |
| 4765 return factory->NewStringFromUtf8( |
| 4766 i::Vector<const char>(data, length), i::NOT_TENURED, ascii_hint); |
| 4767 } else if (masked_encoding == S::LATIN1_ENCODING) { |
| 4768 return factory->NewStringFromLatin1( |
| 4769 i::Vector<const char>(data, length), i::NOT_TENURED, ascii_hint); |
| 4770 } else { // Wrong encoding. |
| 4771 return i::Handle<i::String>(); |
| 4772 } |
| 4773 } |
| 4774 |
| 4775 |
| 4776 Local<String> v8::String::New( |
| 4777 const char* data, int length, int encoding) { |
4696 i::Isolate* isolate = i::Isolate::Current(); | 4778 i::Isolate* isolate = i::Isolate::Current(); |
4697 EnsureInitializedForIsolate(isolate, "v8::String::New()"); | 4779 EnsureInitializedForIsolate(isolate, "v8::String::New()"); |
4698 LOG_API(isolate, "String::New(char)"); | 4780 LOG_API(isolate, "String::New(char)"); |
4699 if (length == 0) return Empty(); | 4781 if (length == 0) return Empty(); |
4700 ENTER_V8(isolate); | 4782 ENTER_V8(isolate); |
4701 if (length == -1) length = i::StrLength(data); | 4783 return Utils::ToLocal( |
4702 i::Handle<i::String> result = | 4784 NewOneByteEncodedString(isolate->factory(), data, length, encoding)); |
4703 isolate->factory()->NewStringFromUtf8( | |
4704 i::Vector<const char>(data, length)); | |
4705 return Utils::ToLocal(result); | |
4706 } | 4785 } |
4707 | 4786 |
4708 | 4787 |
4709 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) { | 4788 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) { |
4710 i::Handle<i::String> left_string = Utils::OpenHandle(*left); | 4789 i::Handle<i::String> left_string = Utils::OpenHandle(*left); |
4711 i::Isolate* isolate = left_string->GetIsolate(); | 4790 i::Isolate* isolate = left_string->GetIsolate(); |
4712 EnsureInitializedForIsolate(isolate, "v8::String::New()"); | 4791 EnsureInitializedForIsolate(isolate, "v8::String::New()"); |
4713 LOG_API(isolate, "String::New(char)"); | 4792 LOG_API(isolate, "String::New(char)"); |
4714 ENTER_V8(isolate); | 4793 ENTER_V8(isolate); |
4715 i::Handle<i::String> right_string = Utils::OpenHandle(*right); | 4794 i::Handle<i::String> right_string = Utils::OpenHandle(*right); |
4716 i::Handle<i::String> result = isolate->factory()->NewConsString(left_string, | 4795 i::Handle<i::String> result = isolate->factory()->NewConsString(left_string, |
4717 right_string); | 4796 right_string); |
4718 return Utils::ToLocal(result); | 4797 return Utils::ToLocal(result); |
4719 } | 4798 } |
4720 | 4799 |
4721 | 4800 |
4722 Local<String> v8::String::NewUndetectable(const char* data, int length) { | 4801 Local<String> v8::String::NewUndetectable( |
| 4802 const char* data, int length, int encoding) { |
4723 i::Isolate* isolate = i::Isolate::Current(); | 4803 i::Isolate* isolate = i::Isolate::Current(); |
4724 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); | 4804 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); |
4725 LOG_API(isolate, "String::NewUndetectable(char)"); | 4805 LOG_API(isolate, "String::NewUndetectable(char)"); |
4726 ENTER_V8(isolate); | 4806 ENTER_V8(isolate); |
4727 if (length == -1) length = i::StrLength(data); | |
4728 i::Handle<i::String> result = | 4807 i::Handle<i::String> result = |
4729 isolate->factory()->NewStringFromUtf8( | 4808 NewOneByteEncodedString(isolate->factory(), data, length, encoding); |
4730 i::Vector<const char>(data, length)); | |
4731 result->MarkAsUndetectable(); | 4809 result->MarkAsUndetectable(); |
4732 return Utils::ToLocal(result); | 4810 return Utils::ToLocal(result); |
4733 } | 4811 } |
4734 | 4812 |
4735 | 4813 |
4736 static int TwoByteStringLength(const uint16_t* data) { | 4814 static int TwoByteStringLength(const uint16_t* data) { |
4737 int length = 0; | 4815 int length = 0; |
4738 while (data[length] != '\0') length++; | 4816 while (data[length] != '\0') length++; |
4739 return length; | 4817 return length; |
4740 } | 4818 } |
4741 | 4819 |
4742 | 4820 |
4743 Local<String> v8::String::New(const uint16_t* data, int length) { | 4821 Local<String> v8::String::New(const uint16_t* data, int length) { |
4744 i::Isolate* isolate = i::Isolate::Current(); | 4822 i::Isolate* isolate = i::Isolate::Current(); |
4745 EnsureInitializedForIsolate(isolate, "v8::String::New()"); | 4823 EnsureInitializedForIsolate(isolate, "v8::String::New()"); |
4746 LOG_API(isolate, "String::New(uint16_)"); | 4824 LOG_API(isolate, "String::New(uint16_)"); |
4747 if (length == 0) return Empty(); | 4825 if (length == 0) return Empty(); |
4748 ENTER_V8(isolate); | 4826 ENTER_V8(isolate); |
4749 if (length == -1) length = TwoByteStringLength(data); | 4827 if (length == kUndefinedLength) length = TwoByteStringLength(data); |
4750 i::Handle<i::String> result = | 4828 i::Handle<i::String> result = |
4751 isolate->factory()->NewStringFromTwoByte( | 4829 isolate->factory()->NewStringFromTwoByte( |
4752 i::Vector<const uint16_t>(data, length)); | 4830 i::Vector<const uint16_t>(data, length)); |
4753 return Utils::ToLocal(result); | 4831 return Utils::ToLocal(result); |
4754 } | 4832 } |
4755 | 4833 |
4756 | 4834 |
4757 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) { | 4835 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) { |
4758 i::Isolate* isolate = i::Isolate::Current(); | 4836 i::Isolate* isolate = i::Isolate::Current(); |
4759 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); | 4837 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); |
4760 LOG_API(isolate, "String::NewUndetectable(uint16_)"); | 4838 LOG_API(isolate, "String::NewUndetectable(uint16_)"); |
4761 ENTER_V8(isolate); | 4839 ENTER_V8(isolate); |
4762 if (length == -1) length = TwoByteStringLength(data); | 4840 if (length == kUndefinedLength) length = TwoByteStringLength(data); |
4763 i::Handle<i::String> result = | 4841 i::Handle<i::String> result = |
4764 isolate->factory()->NewStringFromTwoByte( | 4842 isolate->factory()->NewStringFromTwoByte( |
4765 i::Vector<const uint16_t>(data, length)); | 4843 i::Vector<const uint16_t>(data, length)); |
4766 result->MarkAsUndetectable(); | 4844 result->MarkAsUndetectable(); |
4767 return Utils::ToLocal(result); | 4845 return Utils::ToLocal(result); |
4768 } | 4846 } |
4769 | 4847 |
4770 | 4848 |
4771 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate, | 4849 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate, |
4772 v8::String::ExternalStringResource* resource) { | 4850 v8::String::ExternalStringResource* resource) { |
(...skipping 17 matching lines...) Expand all Loading... |
4790 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); | 4868 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); |
4791 LOG_API(isolate, "String::NewExternal"); | 4869 LOG_API(isolate, "String::NewExternal"); |
4792 ENTER_V8(isolate); | 4870 ENTER_V8(isolate); |
4793 CHECK(resource && resource->data()); | 4871 CHECK(resource && resource->data()); |
4794 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); | 4872 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); |
4795 isolate->heap()->external_string_table()->AddString(*result); | 4873 isolate->heap()->external_string_table()->AddString(*result); |
4796 return Utils::ToLocal(result); | 4874 return Utils::ToLocal(result); |
4797 } | 4875 } |
4798 | 4876 |
4799 | 4877 |
4800 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { | 4878 template<class StringResourceType> |
4801 i::Handle<i::String> obj = Utils::OpenHandle(this); | 4879 static bool MakeStringExternal( |
4802 i::Isolate* isolate = obj->GetIsolate(); | 4880 i::Handle<i::String> string, StringResourceType* resource) { |
| 4881 i::Isolate* isolate = string->GetIsolate(); |
4803 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; | 4882 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; |
4804 if (i::StringShape(*obj).IsExternalTwoByte()) { | 4883 if (i::StringShape(*string).IsExternal()) { |
4805 return false; // Already an external string. | 4884 return false; // Already an external string. |
4806 } | 4885 } |
4807 ENTER_V8(isolate); | 4886 ENTER_V8(isolate); |
4808 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { | 4887 if (isolate->string_tracker()->IsFreshUnusedString(string)) { |
4809 return false; | 4888 return false; |
4810 } | 4889 } |
4811 if (isolate->heap()->IsInGCPostProcessing()) { | 4890 if (isolate->heap()->IsInGCPostProcessing()) { |
4812 return false; | 4891 return false; |
4813 } | 4892 } |
4814 CHECK(resource && resource->data()); | 4893 CHECK(resource && resource->data()); |
4815 bool result = obj->MakeExternal(resource); | 4894 bool result = string->MakeExternal(resource); |
4816 if (result && !obj->IsSymbol()) { | 4895 if (result && !string->IsSymbol()) { |
4817 isolate->heap()->external_string_table()->AddString(*obj); | 4896 isolate->heap()->external_string_table()->AddString(*string); |
4818 } | 4897 } |
4819 return result; | 4898 return result; |
4820 } | 4899 } |
4821 | 4900 |
4822 | 4901 |
| 4902 bool v8::String::MakeExternal(ExternalStringResource* resource) { |
| 4903 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 4904 return MakeStringExternal(obj, resource); |
| 4905 } |
| 4906 |
| 4907 |
| 4908 bool v8::String::MakeExternal(ExternalAsciiStringResource* resource) { |
| 4909 i::Handle<i::String> obj = Utils::OpenHandle(this); |
| 4910 ASSERT(obj->HasOnlyAsciiChars()); |
| 4911 return MakeStringExternal(obj, resource); |
| 4912 } |
| 4913 |
| 4914 |
4823 Local<String> v8::String::NewExternal( | 4915 Local<String> v8::String::NewExternal( |
4824 v8::String::ExternalAsciiStringResource* resource) { | 4916 v8::String::ExternalAsciiStringResource* resource) { |
4825 i::Isolate* isolate = i::Isolate::Current(); | 4917 i::Isolate* isolate = i::Isolate::Current(); |
4826 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); | 4918 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); |
4827 LOG_API(isolate, "String::NewExternal"); | 4919 LOG_API(isolate, "String::NewExternal"); |
4828 ENTER_V8(isolate); | 4920 ENTER_V8(isolate); |
4829 CHECK(resource && resource->data()); | 4921 CHECK(resource && resource->data()); |
4830 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); | 4922 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); |
4831 isolate->heap()->external_string_table()->AddString(*result); | 4923 isolate->heap()->external_string_table()->AddString(*result); |
4832 return Utils::ToLocal(result); | 4924 return Utils::ToLocal(result); |
4833 } | 4925 } |
4834 | 4926 |
4835 | 4927 |
4836 bool v8::String::MakeExternal( | 4928 Local<String> v8::String::NewExternal(ExternalLatin1StringResource* resource, |
4837 v8::String::ExternalAsciiStringResource* resource) { | 4929 int encoding) { |
4838 i::Handle<i::String> obj = Utils::OpenHandle(this); | 4930 typedef v8::internal::Internals I; |
4839 i::Isolate* isolate = obj->GetIsolate(); | 4931 i::Isolate* isolate = i::Isolate::Current(); |
4840 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; | 4932 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); |
4841 if (i::StringShape(*obj).IsExternalTwoByte()) { | 4933 LOG_API(isolate, "String::NewExternal"); |
4842 return false; // Already an external string. | 4934 ENTER_V8(isolate); |
| 4935 ASSERT((encoding & kStringEncodingMask) == LATIN1_ENCODING); |
| 4936 bool ascii_hint = (encoding & kAsciiHintMask); |
| 4937 i::Handle<i::String> result; |
| 4938 |
| 4939 if (ascii_hint == ASCII_HINT || |
| 4940 (ascii_hint != NOT_ASCII_HINT && |
| 4941 i::String::IsAscii(resource->data(), resource->length()))) { |
| 4942 // Assert that the ascii hint is correct. |
| 4943 ASSERT(ascii_hint != ASCII_HINT || |
| 4944 i::String::IsAscii(resource->data(), resource->length())); |
| 4945 result = NewExternalAsciiStringHandle(isolate, resource); |
| 4946 isolate->heap()->external_string_table()->AddString(*result); |
| 4947 } else { |
| 4948 // We cannot simply take the backing store and use it as an ASCII string, |
| 4949 // since it's not. Instead, we convert it to an internal string and dispose |
| 4950 // the external resource. |
| 4951 result = isolate->factory()->NewStringFromLatin1( |
| 4952 i::Vector<const char>(resource->data(), resource->length()), |
| 4953 i::NOT_TENURED, |
| 4954 i::String::NOT_ASCII); |
| 4955 resource->Dispose(); |
4843 } | 4956 } |
4844 ENTER_V8(isolate); | 4957 return Utils::ToLocal(result); |
4845 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { | |
4846 return false; | |
4847 } | |
4848 if (isolate->heap()->IsInGCPostProcessing()) { | |
4849 return false; | |
4850 } | |
4851 CHECK(resource && resource->data()); | |
4852 bool result = obj->MakeExternal(resource); | |
4853 if (result && !obj->IsSymbol()) { | |
4854 isolate->heap()->external_string_table()->AddString(*obj); | |
4855 } | |
4856 return result; | |
4857 } | 4958 } |
4858 | 4959 |
4859 | 4960 |
4860 bool v8::String::CanMakeExternal() { | 4961 bool v8::String::CanMakeExternal() { |
4861 if (!internal::FLAG_clever_optimizations) return false; | 4962 if (!internal::FLAG_clever_optimizations) return false; |
4862 i::Handle<i::String> obj = Utils::OpenHandle(this); | 4963 i::Handle<i::String> obj = Utils::OpenHandle(this); |
4863 i::Isolate* isolate = obj->GetIsolate(); | 4964 i::Isolate* isolate = obj->GetIsolate(); |
4864 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false; | 4965 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false; |
4865 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false; | 4966 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false; |
4866 int size = obj->Size(); // Byte size of the original string. | 4967 int size = obj->Size(); // Byte size of the original string. |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5109 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon)); | 5210 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon)); |
5110 EXCEPTION_PREAMBLE(isolate); | 5211 EXCEPTION_PREAMBLE(isolate); |
5111 ENTER_V8(isolate); | 5212 ENTER_V8(isolate); |
5112 i::Handle<i::JSObject> result = i::Copy(paragon_handle); | 5213 i::Handle<i::JSObject> result = i::Copy(paragon_handle); |
5113 has_pending_exception = result.is_null(); | 5214 has_pending_exception = result.is_null(); |
5114 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); | 5215 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); |
5115 return Utils::ToLocal(result); | 5216 return Utils::ToLocal(result); |
5116 } | 5217 } |
5117 | 5218 |
5118 | 5219 |
5119 Local<String> v8::String::NewSymbol(const char* data, int length) { | 5220 Local<String> v8::String::NewSymbol( |
| 5221 const char* data, int length, int encoding) { |
5120 i::Isolate* isolate = i::Isolate::Current(); | 5222 i::Isolate* isolate = i::Isolate::Current(); |
5121 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()"); | 5223 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()"); |
5122 LOG_API(isolate, "String::NewSymbol(char)"); | 5224 LOG_API(isolate, "String::NewSymbol(char)"); |
5123 ENTER_V8(isolate); | 5225 ENTER_V8(isolate); |
5124 if (length == -1) length = i::StrLength(data); | 5226 if (length == kUndefinedLength) length = i::StrLength(data); |
5125 i::Handle<i::String> result = | 5227 i::Handle<i::String> result; |
5126 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length)); | 5228 |
| 5229 ASSERT(IS_POWER_OF_TWO(encoding & kAsciiHintMask)); |
| 5230 if (((encoding & kStringEncodingMask) == LATIN1_ENCODING) && |
| 5231 ((encoding & kAsciiHintMask) == NOT_ASCII_HINT || |
| 5232 !i::String::IsAscii(data, length))) { |
| 5233 result = isolate->factory()->NewStringFromLatin1( |
| 5234 i::Vector<const char>(data, length), |
| 5235 i::NOT_TENURED, |
| 5236 i::String::NOT_ASCII); |
| 5237 result = isolate->factory()->LookupSymbol(result); |
| 5238 } else { // We can handle UTF8 and ASCII strings here. |
| 5239 result = |
| 5240 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length)); |
| 5241 } |
5127 return Utils::ToLocal(result); | 5242 return Utils::ToLocal(result); |
5128 } | 5243 } |
5129 | 5244 |
5130 | 5245 |
5131 Local<Number> v8::Number::New(double value) { | 5246 Local<Number> v8::Number::New(double value) { |
5132 i::Isolate* isolate = i::Isolate::Current(); | 5247 i::Isolate* isolate = i::Isolate::Current(); |
5133 EnsureInitializedForIsolate(isolate, "v8::Number::New()"); | 5248 EnsureInitializedForIsolate(isolate, "v8::Number::New()"); |
5134 if (isnan(value)) { | 5249 if (isnan(value)) { |
5135 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. | 5250 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. |
5136 value = i::OS::nan_value(); | 5251 value = i::OS::nan_value(); |
(...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6526 | 6641 |
6527 v->VisitPointers(blocks_.first(), first_block_limit_); | 6642 v->VisitPointers(blocks_.first(), first_block_limit_); |
6528 | 6643 |
6529 for (int i = 1; i < blocks_.length(); i++) { | 6644 for (int i = 1; i < blocks_.length(); i++) { |
6530 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); | 6645 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); |
6531 } | 6646 } |
6532 } | 6647 } |
6533 | 6648 |
6534 | 6649 |
6535 } } // namespace v8::internal | 6650 } } // namespace v8::internal |
OLD | NEW |