Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(344)

Side by Side Diff: src/api.cc

Issue 10828229: Add basic support for Latin1 strings to the API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: removed MakeExternal(ExternalLatin1StringResource*) and added counters. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/v8.h ('k') | src/factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 UTF16_ENCODING | STRICT_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 UTF16_ENCODING | NOT_ASCII_HINT :
4084 } else { 4111 CHECK(str->IsExternalTwoByteString());
4085 expected = NULL; 4112 break;
4113 case LATIN1_ENCODING | STRICT_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
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::STRICT_ASCII ==
4760 (v8::String::STRICT_ASCII_HINT >> kAsciiHintShift));
4761
4762 int masked_encoding = encoding & S::kStringEncodingMask;
4763
4764 if (masked_encoding == S::UTF8_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));
4831 if (result->IsAsciiRepresentation()) {
4832 isolate->counters()->string_length_ascii()->Increment(length);
4833 } else {
4834 isolate->counters()->string_length_utf16()->Increment(length);
4835 }
4753 return Utils::ToLocal(result); 4836 return Utils::ToLocal(result);
4754 } 4837 }
4755 4838
4756 4839
4757 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) { 4840 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
4758 i::Isolate* isolate = i::Isolate::Current(); 4841 i::Isolate* isolate = i::Isolate::Current();
4759 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); 4842 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()");
4760 LOG_API(isolate, "String::NewUndetectable(uint16_)"); 4843 LOG_API(isolate, "String::NewUndetectable(uint16_)");
4761 ENTER_V8(isolate); 4844 ENTER_V8(isolate);
4762 if (length == -1) length = TwoByteStringLength(data); 4845 if (length == kUndefinedLength) length = TwoByteStringLength(data);
4763 i::Handle<i::String> result = 4846 i::Handle<i::String> result =
4764 isolate->factory()->NewStringFromTwoByte( 4847 isolate->factory()->NewStringFromTwoByte(
4765 i::Vector<const uint16_t>(data, length)); 4848 i::Vector<const uint16_t>(data, length));
4766 result->MarkAsUndetectable(); 4849 result->MarkAsUndetectable();
4767 return Utils::ToLocal(result); 4850 return Utils::ToLocal(result);
4768 } 4851 }
4769 4852
4770 4853
4771 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate, 4854 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate,
4772 v8::String::ExternalStringResource* resource) { 4855 v8::String::ExternalStringResource* resource) {
(...skipping 17 matching lines...) Expand all
4790 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); 4873 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
4791 LOG_API(isolate, "String::NewExternal"); 4874 LOG_API(isolate, "String::NewExternal");
4792 ENTER_V8(isolate); 4875 ENTER_V8(isolate);
4793 CHECK(resource && resource->data()); 4876 CHECK(resource && resource->data());
4794 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); 4877 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource);
4795 isolate->heap()->external_string_table()->AddString(*result); 4878 isolate->heap()->external_string_table()->AddString(*result);
4796 return Utils::ToLocal(result); 4879 return Utils::ToLocal(result);
4797 } 4880 }
4798 4881
4799 4882
4800 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { 4883 template<class StringResourceType>
4801 i::Handle<i::String> obj = Utils::OpenHandle(this); 4884 static bool MakeStringExternal(
4802 i::Isolate* isolate = obj->GetIsolate(); 4885 i::Handle<i::String> string, StringResourceType* resource) {
4886 i::Isolate* isolate = string->GetIsolate();
4803 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; 4887 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false;
4804 if (i::StringShape(*obj).IsExternalTwoByte()) { 4888 if (i::StringShape(*string).IsExternal()) {
4805 return false; // Already an external string. 4889 return false; // Already an external string.
4806 } 4890 }
4807 ENTER_V8(isolate); 4891 ENTER_V8(isolate);
4808 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { 4892 if (isolate->string_tracker()->IsFreshUnusedString(string)) {
4809 return false; 4893 return false;
4810 } 4894 }
4811 if (isolate->heap()->IsInGCPostProcessing()) { 4895 if (isolate->heap()->IsInGCPostProcessing()) {
4812 return false; 4896 return false;
4813 } 4897 }
4814 CHECK(resource && resource->data()); 4898 CHECK(resource && resource->data());
4815 bool result = obj->MakeExternal(resource); 4899 bool result = string->MakeExternal(resource);
4816 if (result && !obj->IsSymbol()) { 4900 if (result && !string->IsSymbol()) {
4817 isolate->heap()->external_string_table()->AddString(*obj); 4901 isolate->heap()->external_string_table()->AddString(*string);
4818 } 4902 }
4819 return result; 4903 return result;
4820 } 4904 }
4821 4905
4822 4906
4907 bool v8::String::MakeExternal(ExternalStringResource* resource) {
4908 i::Handle<i::String> obj = Utils::OpenHandle(this);
4909 return MakeStringExternal(obj, resource);
4910 }
4911
4912
4913 bool v8::String::MakeExternal(ExternalAsciiStringResource* resource) {
4914 i::Handle<i::String> obj = Utils::OpenHandle(this);
4915 ASSERT(obj->HasOnlyAsciiChars());
4916 return MakeStringExternal(obj, resource);
4917 }
4918
4919
4823 Local<String> v8::String::NewExternal( 4920 Local<String> v8::String::NewExternal(
4824 v8::String::ExternalAsciiStringResource* resource) { 4921 v8::String::ExternalAsciiStringResource* resource) {
4825 i::Isolate* isolate = i::Isolate::Current(); 4922 i::Isolate* isolate = i::Isolate::Current();
4826 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); 4923 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
4827 LOG_API(isolate, "String::NewExternal"); 4924 LOG_API(isolate, "String::NewExternal");
4828 ENTER_V8(isolate); 4925 ENTER_V8(isolate);
4829 CHECK(resource && resource->data()); 4926 CHECK(resource && resource->data());
4830 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); 4927 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource);
4831 isolate->heap()->external_string_table()->AddString(*result); 4928 isolate->heap()->external_string_table()->AddString(*result);
4832 return Utils::ToLocal(result); 4929 return Utils::ToLocal(result);
4833 } 4930 }
4834 4931
4835 4932
4836 bool v8::String::MakeExternal( 4933 Local<String> v8::String::NewExternal(ExternalLatin1StringResource* resource,
4837 v8::String::ExternalAsciiStringResource* resource) { 4934 int encoding) {
4838 i::Handle<i::String> obj = Utils::OpenHandle(this); 4935 typedef v8::internal::Internals I;
4839 i::Isolate* isolate = obj->GetIsolate(); 4936 i::Isolate* isolate = i::Isolate::Current();
4840 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; 4937 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
4841 if (i::StringShape(*obj).IsExternalTwoByte()) { 4938 LOG_API(isolate, "String::NewExternal");
4842 return false; // Already an external string. 4939 ENTER_V8(isolate);
4940 ASSERT((encoding & kStringEncodingMask) == LATIN1_ENCODING);
4941 bool ascii_hint = (encoding & kAsciiHintMask);
4942 i::Handle<i::String> result;
4943
4944 if (ascii_hint == STRICT_ASCII_HINT ||
4945 (ascii_hint != NOT_ASCII_HINT &&
4946 i::String::IsAscii(resource->data(), resource->length()))) {
4947 // Assert that the ascii hint is correct.
4948 ASSERT(ascii_hint != STRICT_ASCII_HINT ||
4949 i::String::IsAscii(resource->data(), resource->length()));
4950 result = NewExternalAsciiStringHandle(isolate, resource);
4951 isolate->heap()->external_string_table()->AddString(*result);
4952 } else {
4953 // We cannot simply take the backing store and use it as an ASCII string,
4954 // since it's not. Instead, we convert it to an internal string and dispose
4955 // the external resource.
4956 result = isolate->factory()->NewStringFromLatin1(
4957 i::Vector<const char>(resource->data(), resource->length()),
4958 i::NOT_TENURED,
4959 i::String::NOT_ASCII);
4960 resource->Dispose();
4843 } 4961 }
4844 ENTER_V8(isolate); 4962 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 } 4963 }
4858 4964
4859 4965
4860 bool v8::String::CanMakeExternal() { 4966 bool v8::String::CanMakeExternal() {
4861 if (!internal::FLAG_clever_optimizations) return false; 4967 if (!internal::FLAG_clever_optimizations) return false;
4862 i::Handle<i::String> obj = Utils::OpenHandle(this); 4968 i::Handle<i::String> obj = Utils::OpenHandle(this);
4863 i::Isolate* isolate = obj->GetIsolate(); 4969 i::Isolate* isolate = obj->GetIsolate();
4864 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false; 4970 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false;
4865 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false; 4971 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
4866 int size = obj->Size(); // Byte size of the original string. 4972 int size = obj->Size(); // Byte size of the original string.
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
5109 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon)); 5215 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
5110 EXCEPTION_PREAMBLE(isolate); 5216 EXCEPTION_PREAMBLE(isolate);
5111 ENTER_V8(isolate); 5217 ENTER_V8(isolate);
5112 i::Handle<i::JSObject> result = i::Copy(paragon_handle); 5218 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
5113 has_pending_exception = result.is_null(); 5219 has_pending_exception = result.is_null();
5114 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 5220 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
5115 return Utils::ToLocal(result); 5221 return Utils::ToLocal(result);
5116 } 5222 }
5117 5223
5118 5224
5119 Local<String> v8::String::NewSymbol(const char* data, int length) { 5225 Local<String> v8::String::NewSymbol(
5226 const char* data, int length, int encoding) {
5120 i::Isolate* isolate = i::Isolate::Current(); 5227 i::Isolate* isolate = i::Isolate::Current();
5121 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()"); 5228 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()");
5122 LOG_API(isolate, "String::NewSymbol(char)"); 5229 LOG_API(isolate, "String::NewSymbol(char)");
5123 ENTER_V8(isolate); 5230 ENTER_V8(isolate);
5124 if (length == -1) length = i::StrLength(data); 5231 if (length == kUndefinedLength) length = i::StrLength(data);
5125 i::Handle<i::String> result = 5232 i::Handle<i::String> result;
5126 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length)); 5233
5234 ASSERT(IS_POWER_OF_TWO(encoding & kAsciiHintMask));
5235 if (((encoding & kStringEncodingMask) == LATIN1_ENCODING) &&
5236 ((encoding & kAsciiHintMask) == NOT_ASCII_HINT ||
5237 !i::String::IsAscii(data, length))) {
5238 result = isolate->factory()->NewStringFromLatin1(
5239 i::Vector<const char>(data, length),
5240 i::NOT_TENURED,
5241 i::String::NOT_ASCII);
5242 result = isolate->factory()->LookupSymbol(result);
5243 } else { // We can handle UTF8 and ASCII strings here.
5244 result =
5245 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length));
5246 }
5127 return Utils::ToLocal(result); 5247 return Utils::ToLocal(result);
5128 } 5248 }
5129 5249
5130 5250
5131 Local<Number> v8::Number::New(double value) { 5251 Local<Number> v8::Number::New(double value) {
5132 i::Isolate* isolate = i::Isolate::Current(); 5252 i::Isolate* isolate = i::Isolate::Current();
5133 EnsureInitializedForIsolate(isolate, "v8::Number::New()"); 5253 EnsureInitializedForIsolate(isolate, "v8::Number::New()");
5134 if (isnan(value)) { 5254 if (isnan(value)) {
5135 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. 5255 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
5136 value = i::OS::nan_value(); 5256 value = i::OS::nan_value();
(...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after
6526 6646
6527 v->VisitPointers(blocks_.first(), first_block_limit_); 6647 v->VisitPointers(blocks_.first(), first_block_limit_);
6528 6648
6529 for (int i = 1; i < blocks_.length(); i++) { 6649 for (int i = 1; i < blocks_.length(); i++) {
6530 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); 6650 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
6531 } 6651 }
6532 } 6652 }
6533 6653
6534 6654
6535 } } // namespace v8::internal 6655 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « include/v8.h ('k') | src/factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698