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

Side by Side Diff: src/api.cc

Issue 10810056: Improve String::WriteAscii and add PRESERVE_ASCII_NULL option. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: addressed comments Created 8 years, 5 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') | test/cctest/test-api.cc » ('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 3829 matching lines...) Expand 10 before | Expand all | Expand 10 after
3840 3840
3841 int String::WriteUtf8(char* buffer, 3841 int String::WriteUtf8(char* buffer,
3842 int capacity, 3842 int capacity,
3843 int* nchars_ref, 3843 int* nchars_ref,
3844 int options) const { 3844 int options) const {
3845 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3845 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3846 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; 3846 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
3847 LOG_API(isolate, "String::WriteUtf8"); 3847 LOG_API(isolate, "String::WriteUtf8");
3848 ENTER_V8(isolate); 3848 ENTER_V8(isolate);
3849 i::Handle<i::String> str = Utils::OpenHandle(this); 3849 i::Handle<i::String> str = Utils::OpenHandle(this);
3850 if (options & HINT_MANY_WRITES_EXPECTED) {
3851 FlattenString(str); // Flatten the string for efficiency.
3852 }
3850 int string_length = str->length(); 3853 int string_length = str->length();
3851 if (str->IsAsciiRepresentation()) { 3854 if (str->IsAsciiRepresentation()) {
3852 int len; 3855 int len;
3853 if (capacity == -1) { 3856 if (capacity == -1) {
3854 capacity = str->length() + 1; 3857 capacity = str->length() + 1;
3855 len = string_length; 3858 len = string_length;
3856 } else { 3859 } else {
3857 len = i::Min(capacity, str->length()); 3860 len = i::Min(capacity, str->length());
3858 } 3861 }
3859 i::String::WriteToFlat(*str, buffer, 0, len); 3862 i::String::WriteToFlat(*str, buffer, 0, len);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3896 int utf8_bytes = i::Utf8Length(str); 3899 int utf8_bytes = i::Utf8Length(str);
3897 if ((options & NO_NULL_TERMINATION) == 0) utf8_bytes++; 3900 if ((options & NO_NULL_TERMINATION) == 0) utf8_bytes++;
3898 if (utf8_bytes <= capacity) { 3901 if (utf8_bytes <= capacity) {
3899 return WriteUtf8(buffer, -1, nchars_ref, options); 3902 return WriteUtf8(buffer, -1, nchars_ref, options);
3900 } 3903 }
3901 } 3904 }
3902 3905
3903 // Slow case. 3906 // Slow case.
3904 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); 3907 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
3905 isolate->string_tracker()->RecordWrite(str); 3908 isolate->string_tracker()->RecordWrite(str);
3906 if (options & HINT_MANY_WRITES_EXPECTED) { 3909
3907 // Flatten the string for efficiency. This applies whether we are
3908 // using StringInputBuffer or Get(i) to access the characters.
3909 FlattenString(str);
3910 }
3911 write_input_buffer.Reset(0, *str); 3910 write_input_buffer.Reset(0, *str);
3912 int len = str->length(); 3911 int len = str->length();
3913 // Encode the first K - 3 bytes directly into the buffer since we 3912 // Encode the first K - 3 bytes directly into the buffer since we
3914 // know there's room for them. If no capacity is given we copy all 3913 // know there's room for them. If no capacity is given we copy all
3915 // of them here. 3914 // of them here.
3916 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1); 3915 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
3917 int i; 3916 int i;
3918 int pos = 0; 3917 int pos = 0;
3919 int nchars = 0; 3918 int nchars = 0;
3920 int previous = unibrow::Utf16::kNoPreviousCharacter; 3919 int previous = unibrow::Utf16::kNoPreviousCharacter;
(...skipping 21 matching lines...) Expand all
3942 int written = unibrow::Utf8::Encode(buffer + pos, c, previous); 3941 int written = unibrow::Utf8::Encode(buffer + pos, c, previous);
3943 ASSERT(written == 1); 3942 ASSERT(written == 1);
3944 pos += written; 3943 pos += written;
3945 nchars++; 3944 nchars++;
3946 } else { 3945 } else {
3947 int written = 3946 int written =
3948 unibrow::Utf8::Encode(intermediate, 3947 unibrow::Utf8::Encode(intermediate,
3949 c, 3948 c,
3950 unibrow::Utf16::kNoPreviousCharacter); 3949 unibrow::Utf16::kNoPreviousCharacter);
3951 if (pos + written <= capacity) { 3950 if (pos + written <= capacity) {
3952 for (int j = 0; j < written; j++) 3951 for (int j = 0; j < written; j++) {
3953 buffer[pos + j] = intermediate[j]; 3952 buffer[pos + j] = intermediate[j];
3953 }
3954 pos += written; 3954 pos += written;
3955 nchars++; 3955 nchars++;
3956 } else { 3956 } else {
3957 // We've reached the end of the buffer 3957 // We've reached the end of the buffer
3958 break; 3958 break;
3959 } 3959 }
3960 } 3960 }
3961 previous = c; 3961 previous = c;
3962 } 3962 }
3963 } 3963 }
3964 if (nchars_ref != NULL) *nchars_ref = nchars; 3964 if (nchars_ref != NULL) *nchars_ref = nchars;
3965 if (!(options & NO_NULL_TERMINATION) && 3965 if (!(options & NO_NULL_TERMINATION) &&
3966 (i == len && (capacity == -1 || pos < capacity))) 3966 (i == len && (capacity == -1 || pos < capacity))) {
3967 buffer[pos++] = '\0'; 3967 buffer[pos++] = '\0';
3968 }
3968 return pos; 3969 return pos;
3969 } 3970 }
3970 3971
3971 3972
3972 int String::WriteAscii(char* buffer, 3973 int String::WriteAscii(char* buffer,
3973 int start, 3974 int start,
3974 int length, 3975 int length,
3975 int options) const { 3976 int options) const {
3976 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3977 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3977 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; 3978 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0;
3978 LOG_API(isolate, "String::WriteAscii"); 3979 LOG_API(isolate, "String::WriteAscii");
3979 ENTER_V8(isolate); 3980 ENTER_V8(isolate);
3980 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
3981 ASSERT(start >= 0 && length >= -1); 3981 ASSERT(start >= 0 && length >= -1);
3982 i::Handle<i::String> str = Utils::OpenHandle(this); 3982 i::Handle<i::String> str = Utils::OpenHandle(this);
3983 isolate->string_tracker()->RecordWrite(str); 3983 isolate->string_tracker()->RecordWrite(str);
3984 if (options & HINT_MANY_WRITES_EXPECTED) { 3984 if (options & HINT_MANY_WRITES_EXPECTED) {
3985 // Flatten the string for efficiency. This applies whether we are 3985 FlattenString(str); // Flatten the string for efficiency.
3986 // using StringInputBuffer or Get(i) to access the characters.
3987 str->TryFlatten();
3988 } 3986 }
3987
3988 if (str->IsAsciiRepresentation()) {
3989 // WriteToFlat is faster than using the StringInputBuffer.
3990 if (length == -1) length = str->length() + 1;
3991 int len = i::Min(length, str->length() - start);
3992 i::String::WriteToFlat(*str, buffer, start, start + len);
3993 if (!(options & PRESERVE_ASCII_NULL)) {
3994 for (int i = 0; i < len; i++) {
3995 if (buffer[i] == '\0') buffer[i] = ' ';
3996 }
3997 }
3998 if (!(options & NO_NULL_TERMINATION) && length > len) {
3999 buffer[len] = '\0';
4000 }
4001 return len;
4002 }
4003
4004 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
3989 int end = length; 4005 int end = length;
3990 if ( (length == -1) || (length > str->length() - start) ) 4006 if ((length == -1) || (length > str->length() - start)) {
3991 end = str->length() - start; 4007 end = str->length() - start;
4008 }
3992 if (end < 0) return 0; 4009 if (end < 0) return 0;
3993 write_input_buffer.Reset(start, *str); 4010 write_input_buffer.Reset(start, *str);
3994 int i; 4011 int i;
3995 for (i = 0; i < end; i++) { 4012 for (i = 0; i < end; i++) {
3996 char c = static_cast<char>(write_input_buffer.GetNext()); 4013 char c = static_cast<char>(write_input_buffer.GetNext());
3997 if (c == '\0') c = ' '; 4014 if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' ';
3998 buffer[i] = c; 4015 buffer[i] = c;
3999 } 4016 }
4000 if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) 4017 if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) {
4001 buffer[i] = '\0'; 4018 buffer[i] = '\0';
4019 }
4002 return i; 4020 return i;
4003 } 4021 }
4004 4022
4005 4023
4006 int String::Write(uint16_t* buffer, 4024 int String::Write(uint16_t* buffer,
4007 int start, 4025 int start,
4008 int length, 4026 int length,
4009 int options) const { 4027 int options) const {
4010 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4028 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4011 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0; 4029 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0;
4012 LOG_API(isolate, "String::Write"); 4030 LOG_API(isolate, "String::Write");
4013 ENTER_V8(isolate); 4031 ENTER_V8(isolate);
4014 ASSERT(start >= 0 && length >= -1); 4032 ASSERT(start >= 0 && length >= -1);
4015 i::Handle<i::String> str = Utils::OpenHandle(this); 4033 i::Handle<i::String> str = Utils::OpenHandle(this);
4016 isolate->string_tracker()->RecordWrite(str); 4034 isolate->string_tracker()->RecordWrite(str);
4017 if (options & HINT_MANY_WRITES_EXPECTED) { 4035 if (options & HINT_MANY_WRITES_EXPECTED) {
4018 // Flatten the string for efficiency. This applies whether we are 4036 // Flatten the string for efficiency. This applies whether we are
4019 // using StringInputBuffer or Get(i) to access the characters. 4037 // using StringInputBuffer or Get(i) to access the characters.
4020 str->TryFlatten(); 4038 FlattenString(str);
4021 } 4039 }
4022 int end = start + length; 4040 int end = start + length;
4023 if ((length == -1) || (length > str->length() - start) ) 4041 if ((length == -1) || (length > str->length() - start) )
4024 end = str->length(); 4042 end = str->length();
4025 if (end < 0) return 0; 4043 if (end < 0) return 0;
4026 i::String::WriteToFlat(*str, buffer, start, end); 4044 i::String::WriteToFlat(*str, buffer, start, end);
4027 if (!(options & NO_NULL_TERMINATION) && 4045 if (!(options & NO_NULL_TERMINATION) &&
4028 (length == -1 || end - start < length)) { 4046 (length == -1 || end - start < length)) {
4029 buffer[end - start] = '\0'; 4047 buffer[end - start] = '\0';
4030 } 4048 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
4196 void v8::Object::SetPointerInInternalField(int index, void* value) { 4214 void v8::Object::SetPointerInInternalField(int index, void* value) {
4197 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4215 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4198 ENTER_V8(isolate); 4216 ENTER_V8(isolate);
4199 if (CanBeEncodedAsSmi(value)) { 4217 if (CanBeEncodedAsSmi(value)) {
4200 Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value)); 4218 Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value));
4201 } else { 4219 } else {
4202 HandleScope scope; 4220 HandleScope scope;
4203 i::Handle<i::Foreign> foreign = 4221 i::Handle<i::Foreign> foreign =
4204 isolate->factory()->NewForeign( 4222 isolate->factory()->NewForeign(
4205 reinterpret_cast<i::Address>(value), i::TENURED); 4223 reinterpret_cast<i::Address>(value), i::TENURED);
4206 if (!foreign.is_null()) 4224 if (!foreign.is_null()) {
4207 Utils::OpenHandle(this)->SetInternalField(index, *foreign); 4225 Utils::OpenHandle(this)->SetInternalField(index, *foreign);
4226 }
4208 } 4227 }
4209 ASSERT_EQ(value, GetPointerFromInternalField(index)); 4228 ASSERT_EQ(value, GetPointerFromInternalField(index));
4210 } 4229 }
4211 4230
4212 4231
4213 // --- E n v i r o n m e n t --- 4232 // --- E n v i r o n m e n t ---
4214 4233
4215 4234
4216 bool v8::V8::Initialize() { 4235 bool v8::V8::Initialize() {
4217 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 4236 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
(...skipping 2278 matching lines...) Expand 10 before | Expand all | Expand 10 after
6496 6515
6497 v->VisitPointers(blocks_.first(), first_block_limit_); 6516 v->VisitPointers(blocks_.first(), first_block_limit_);
6498 6517
6499 for (int i = 1; i < blocks_.length(); i++) { 6518 for (int i = 1; i < blocks_.length(); i++) {
6500 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); 6519 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
6501 } 6520 }
6502 } 6521 }
6503 6522
6504 6523
6505 } } // namespace v8::internal 6524 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « include/v8.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698