Chromium Code Reviews| Index: runtime/vm/object.cc |
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
| index b5adbd1b34d54de05ba344002f91293159025420..06e15cc99613e77e1958cc987c8b37bdddad4322 100644 |
| --- a/runtime/vm/object.cc |
| +++ b/runtime/vm/object.cc |
| @@ -388,6 +388,15 @@ void Object::Init(Isolate* isolate) { |
| cls = Class::New<FourByteString>(); |
| object_store->set_four_byte_string_class(cls); |
| + cls = Class::New<ExternalOneByteString>(); |
| + object_store->set_external_one_byte_string_class(cls); |
| + |
| + cls = Class::New<ExternalTwoByteString>(); |
| + object_store->set_external_two_byte_string_class(cls); |
| + |
| + cls = Class::New<ExternalFourByteString>(); |
| + object_store->set_external_four_byte_string_class(cls); |
| + |
| cls = Class::New<Bool>(); |
| object_store->set_bool_class(cls); |
| @@ -457,6 +466,24 @@ void Object::Init(Isolate* isolate) { |
| cls.set_script(impl_script); |
| core_impl_lib.AddClass(cls); |
| + name = String::NewSymbol("ExternalOneByteString"); |
| + cls = object_store->external_one_byte_string_class(); |
| + cls.set_name(name); |
| + cls.set_script(impl_script); |
| + core_impl_lib.AddClass(cls); |
| + |
| + name = String::NewSymbol("ExternalTwoByteString"); |
| + cls = object_store->external_two_byte_string_class(); |
| + cls.set_name(name); |
| + cls.set_script(impl_script); |
| + core_impl_lib.AddClass(cls); |
| + |
| + name = String::NewSymbol("ExternalFourByteString"); |
| + cls = object_store->external_four_byte_string_class(); |
| + cls.set_name(name); |
| + cls.set_script(impl_script); |
| + core_impl_lib.AddClass(cls); |
| + |
| name = String::NewSymbol("Mint"); |
| cls = object_store->mint_class(); |
| cls.set_name(name); |
| @@ -632,6 +659,15 @@ void Object::InitFromSnapshot(Isolate* isolate) { |
| cls = Class::New<FourByteString>(); |
| object_store->set_four_byte_string_class(cls); |
| + cls = Class::New<ExternalOneByteString>(); |
| + object_store->set_external_one_byte_string_class(cls); |
| + |
| + cls = Class::New<ExternalTwoByteString>(); |
| + object_store->set_external_two_byte_string_class(cls); |
| + |
| + cls = Class::New<ExternalFourByteString>(); |
| + object_store->set_external_four_byte_string_class(cls); |
| + |
| cls = Class::New<Bool>(); |
| object_store->set_bool_class(cls); |
| @@ -1082,6 +1118,15 @@ RawClass* Class::GetClass(ObjectKind kind) { |
| case kFourByteString: |
| ASSERT(object_store->four_byte_string_class() != Class::null()); |
| return object_store->four_byte_string_class(); |
| + case kExternalOneByteString: |
| + ASSERT(object_store->external_one_byte_string_class() != Class::null()); |
| + return object_store->external_one_byte_string_class(); |
| + case kExternalTwoByteString: |
| + ASSERT(object_store->external_two_byte_string_class() != Class::null()); |
| + return object_store->external_two_byte_string_class(); |
| + case kExternalFourByteString: |
| + ASSERT(object_store->external_four_byte_string_class() != Class::null()); |
| + return object_store->external_four_byte_string_class(); |
| case kBool: |
| ASSERT(object_store->bool_class() != Class::null()); |
| return object_store->bool_class(); |
| @@ -5569,19 +5614,18 @@ RawString* String::New(const String& str, Heap::Space space) { |
| // Once we have external string support, this will also create a heap copy of |
|
turnidge
2011/10/25 18:07:20
Update this comment?
cshapiro
2011/10/25 20:42:47
Yes, indeed. Thanks for pointing that out.
|
| // the string if necessary. Some optimizations are possible, such as not |
| // copying internal strings into the same space. |
| - if (str.IsOneByteString()) { |
| - OneByteString& one_byte_str = OneByteString::Handle(); |
| - one_byte_str ^= str.raw(); |
| - return OneByteString::New(one_byte_str, space); |
| - } else if (str.IsTwoByteString()) { |
| - TwoByteString& two_byte_str = TwoByteString::Handle(); |
| - two_byte_str ^= str.raw(); |
| - return TwoByteString::New(two_byte_str, space); |
| + intptr_t len = str.Length(); |
| + String& result = String::Handle(); |
| + if (str.HasOneByteChar()) { |
| + result ^= OneByteString::New(len, space); |
| + } else if (str.HasTwoByteChar()) { |
| + result ^= TwoByteString::New(len, space); |
| + } else { |
| + ASSERT(str.HasFourByteChar()); |
| + result ^= FourByteString::New(len, space); |
| } |
| - ASSERT(str.IsFourByteString()); |
| - FourByteString& four_byte_str = FourByteString::Handle(); |
| - four_byte_str ^= str.raw(); |
| - return FourByteString::New(four_byte_str, space); |
| + String::Copy(result, 0, str, 0, len); |
| + return result.raw(); |
| } |
| @@ -5693,22 +5737,46 @@ void String::Copy(const String& dst, intptr_t dst_offset, |
| ASSERT(len <= (dst.Length() - dst_offset)); |
| ASSERT(len <= (src.Length() - src_offset)); |
| if (len > 0) { |
| - if (src.IsOneByteString()) { |
| - OneByteString& onestr = OneByteString::Handle(); |
| - onestr ^= src.raw(); |
| - NoGCScope no_gc; |
| - String::Copy(dst, dst_offset, onestr.CharAddr(0) + src_offset, len); |
| - } else if (src.IsTwoByteString()) { |
| - TwoByteString& twostr = TwoByteString::Handle(); |
| - twostr ^= src.raw(); |
| - NoGCScope no_gc; |
| - String::Copy(dst, dst_offset, twostr.CharAddr(0) + src_offset, len); |
| + if (src.HasOneByteChar()) { |
| + if (src.IsOneByteString()) { |
| + OneByteString& onestr = OneByteString::Handle(); |
| + onestr ^= src.raw(); |
| + NoGCScope no_gc; |
| + String::Copy(dst, dst_offset, onestr.CharAddr(0) + src_offset, len); |
| + } else { |
| + ASSERT(src.IsExternalOneByteString()); |
| + ExternalOneByteString& onestr = ExternalOneByteString::Handle(); |
| + onestr ^= src.raw(); |
| + NoGCScope no_gc; |
| + String::Copy(dst, dst_offset, onestr.CharAddr(0) + src_offset, len); |
| + } |
| + } else if (src.HasTwoByteChar()) { |
| + if (src.IsTwoByteString()) { |
| + TwoByteString& twostr = TwoByteString::Handle(); |
| + twostr ^= src.raw(); |
| + NoGCScope no_gc; |
| + String::Copy(dst, dst_offset, twostr.CharAddr(0) + src_offset, len); |
| + } else { |
| + ASSERT(src.IsExternalTwoByteString()); |
| + ExternalTwoByteString& twostr = ExternalTwoByteString::Handle(); |
| + twostr ^= src.raw(); |
| + NoGCScope no_gc; |
| + String::Copy(dst, dst_offset, twostr.CharAddr(0) + src_offset, len); |
| + } |
| } else { |
| - ASSERT(src.IsFourByteString()); |
| - FourByteString& fourstr = FourByteString::Handle(); |
| - fourstr ^= src.raw(); |
| - NoGCScope no_gc; |
| - String::Copy(dst, dst_offset, fourstr.CharAddr(0) + src_offset, len); |
| + ASSERT(src.HasFourByteChar()); |
| + if (src.IsFourByteString()) { |
| + FourByteString& fourstr = FourByteString::Handle(); |
| + fourstr ^= src.raw(); |
| + NoGCScope no_gc; |
| + String::Copy(dst, dst_offset, fourstr.CharAddr(0) + src_offset, len); |
| + } else { |
| + ASSERT(src.IsExternalFourByteString()); |
| + ExternalFourByteString& fourstr = ExternalFourByteString::Handle(); |
| + fourstr ^= src.raw(); |
| + NoGCScope no_gc; |
| + String::Copy(dst, dst_offset, fourstr.CharAddr(0) + src_offset, len); |
| + } |
| } |
| } |
| } |
| @@ -5870,13 +5938,13 @@ RawString* String::Concat(const String& str1, |
| const String& str2, |
| Heap::Space space) { |
| ASSERT(!str1.IsNull() && !str2.IsNull()); |
| - if (str1.IsFourByteString() || str2.IsFourByteString()) { |
| + if (str1.HasFourByteChar() || str2.HasFourByteChar()) { |
| return FourByteString::Concat(str1, str2, space); |
| } |
| - if (str1.IsTwoByteString() || str2.IsTwoByteString()) { |
| + if (str1.HasTwoByteChar() || str2.HasTwoByteChar()) { |
| return TwoByteString::Concat(str1, str2, space); |
| } |
| - ASSERT(str1.IsOneByteString() && str2.IsOneByteString()); |
| + ASSERT(str1.HasOneByteChar() && str2.HasOneByteChar()); |
| return OneByteString::Concat(str1, str2, space); |
| } |
| @@ -5892,10 +5960,10 @@ RawString* String::ConcatAll(const Array& strings, |
| for (intptr_t i = 0; i < strings_len; i++) { |
| str ^= strings.At(i); |
| result_len += str.Length(); |
| - if (str.IsFourByteString()) { |
| + if (str.HasFourByteChar()) { |
| is_one_byte_string = false; |
| is_two_byte_string = false; |
| - } else if (str.IsTwoByteString()) { |
| + } else if (str.HasTwoByteChar()) { |
| is_one_byte_string = false; |
| } |
| } |
| @@ -5929,19 +5997,39 @@ RawString* String::SubString(const String& str, |
| if (begin_index >= str.Length()) { |
| return String::null(); |
| } |
| - if (str.IsOneByteString()) { |
| - OneByteString& obstr = OneByteString::Handle(); |
| - obstr ^= str.raw(); |
| - return OneByteString::SubString(obstr, begin_index, length, space); |
| - } else if (str.IsTwoByteString()) { |
| - TwoByteString& twostr = TwoByteString::Handle(); |
| - twostr ^= str.raw(); |
| - return TwoByteString::SubString(twostr, begin_index, length, space); |
| + String& result = String::Handle(); |
| + bool is_one_byte_string = true; |
| + bool is_two_byte_string = true; |
| + if (str.HasOneByteChar()) { |
| + // do nothing |
| + } else if (str.HasTwoByteChar()) { |
| + for (intptr_t i = begin_index; i < begin_index + length; ++i) { |
| + if (str.CharAt(i) > 0xFF) { |
| + is_one_byte_string = false; |
| + break; |
| + } |
| + } |
| + } else { |
| + ASSERT(str.HasFourByteChar()); |
| + for (intptr_t i = begin_index; i < begin_index + length; ++i) { |
| + if (str.CharAt(i) > 0xFFFF) { |
| + is_one_byte_string = false; |
| + is_two_byte_string = false; |
| + break; |
| + } else if (str.CharAt(i) > 0xFF) { |
| + is_one_byte_string = false; |
| + } |
| + } |
| + } |
| + if (is_one_byte_string) { |
| + result ^= OneByteString::New(length, space); |
| + } else if (is_two_byte_string) { |
| + result ^= TwoByteString::New(length, space); |
| + } else { |
| + result ^= FourByteString::New(length, space); |
| } |
| - ASSERT(str.IsFourByteString()); |
| - FourByteString& fourstr = FourByteString::Handle(); |
| - fourstr ^= str.raw(); |
| - return FourByteString::SubString(fourstr, begin_index, length, space); |
| + String::Copy(result, 0, str, begin_index, length); |
| + return result.raw(); |
| } |
| @@ -6089,22 +6177,6 @@ RawOneByteString* OneByteString::ConcatAll(const Array& strings, |
| } |
| -RawString* OneByteString::SubString(const OneByteString& str, |
| - intptr_t begin_index, |
| - intptr_t length, |
| - Heap::Space space) { |
| - ASSERT(!str.IsNull()); |
| - ASSERT(begin_index < str.Length()); |
| - OneByteString& result = OneByteString::Handle(); |
| - if (length <= (str.Length() - begin_index)) { |
| - result ^= OneByteString::New(length, space); |
| - String::Copy(result, 0, str, begin_index, length); |
| - } |
| - // TODO(5418937): return a non-null object on error. |
| - return result.raw(); |
| -} |
| - |
| - |
| RawOneByteString* OneByteString::Transform(int32_t (*mapping)(int32_t ch), |
| const String& str, |
| Heap::Space space) { |
| @@ -6208,33 +6280,6 @@ RawTwoByteString* TwoByteString::ConcatAll(const Array& strings, |
| } |
| -RawString* TwoByteString::SubString(const TwoByteString& str, |
| - intptr_t begin_index, |
| - intptr_t length, |
| - Heap::Space space) { |
| - ASSERT(!str.IsNull()); |
| - ASSERT(begin_index < str.Length()); |
| - String& result = String::Handle(); |
| - if (length <= (str.Length() - begin_index)) { |
| - bool is_one_byte_string = true; |
| - for (intptr_t i = begin_index; i < begin_index + length; ++i) { |
| - if (str.CharAt(i) > 0xFF) { |
| - is_one_byte_string = false; |
| - break; |
| - } |
| - } |
| - if (is_one_byte_string) { |
| - result ^= OneByteString::New(length, space); |
| - } else { |
| - result ^= TwoByteString::New(length, space); |
| - } |
| - String::Copy(result, 0, str, begin_index, length); |
| - } |
| - // TODO(5418937): return a non-null object on error. |
| - return result.raw(); |
| -} |
| - |
| - |
| RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch), |
| const String& str, |
| Heap::Space space) { |
| @@ -6326,39 +6371,6 @@ RawFourByteString* FourByteString::ConcatAll(const Array& strings, |
| } |
| -RawString* FourByteString::SubString(const FourByteString& str, |
| - intptr_t begin_index, |
| - intptr_t length, |
| - Heap::Space space) { |
| - ASSERT(!str.IsNull()); |
| - ASSERT(begin_index < str.Length()); |
| - String& result = String::Handle(); |
| - if (length <= (str.Length() - begin_index)) { |
| - bool is_one_byte_string = true; |
| - bool is_two_byte_string = true; |
| - for (intptr_t i = begin_index; i < begin_index + length; ++i) { |
| - if (str.CharAt(i) > 0xFFFF) { |
| - is_one_byte_string = false; |
| - is_two_byte_string = false; |
| - break; |
| - } else if (str.CharAt(i) > 0xFF) { |
| - is_one_byte_string = false; |
| - } |
| - } |
| - if (is_one_byte_string) { |
| - result ^= OneByteString::New(length, space); |
| - } else if (is_two_byte_string) { |
| - result ^= TwoByteString::New(length, space); |
| - } else { |
| - result ^= FourByteString::New(length, space); |
| - } |
| - String::Copy(result, 0, str, begin_index, length); |
| - } |
| - // TODO(5418937): return a non-null object on error. |
| - return result.raw(); |
| -} |
| - |
| - |
| RawFourByteString* FourByteString::Transform(int32_t (*mapping)(int32_t ch), |
| const String& str, |
| Heap::Space space) { |
| @@ -6380,6 +6392,90 @@ const char* FourByteString::ToCString() const { |
| } |
| +RawExternalOneByteString* ExternalOneByteString::New(const uint8_t* data, |
| + intptr_t len, |
| + Finalizer finalizer, |
| + Heap::Space space) { |
| + Isolate* isolate = Isolate::Current(); |
| + |
| + const Class& cls = |
| + Class::Handle(isolate->object_store()->external_one_byte_string_class()); |
| + ExternalOneByteString& result = ExternalOneByteString::Handle(); |
| + { |
| + RawObject* raw = Object::Allocate(cls, |
| + ExternalOneByteString::InstanceSize(), |
| + space); |
| + NoGCScope no_gc; |
| + result ^= raw; |
| + result.SetLength(len); |
| + result.SetHash(0); |
| + result.SetData(data); |
| + } |
| + return result.raw(); |
| +} |
| + |
| + |
| +const char* ExternalOneByteString::ToCString() const { |
| + return String::ToCString(); |
| +} |
| + |
| + |
| +RawExternalTwoByteString* ExternalTwoByteString::New(const uint16_t* data, |
| + intptr_t len, |
| + Finalizer finalizer, |
| + Heap::Space space) { |
| + Isolate* isolate = Isolate::Current(); |
| + |
| + const Class& cls = |
| + Class::Handle(isolate->object_store()->external_two_byte_string_class()); |
| + ExternalTwoByteString& result = ExternalTwoByteString::Handle(); |
| + { |
| + RawObject* raw = Object::Allocate(cls, |
| + ExternalTwoByteString::InstanceSize(), |
| + space); |
| + NoGCScope no_gc; |
| + result ^= raw; |
| + result.SetLength(len); |
| + result.SetHash(0); |
| + result.SetData(data); |
| + } |
| + return result.raw(); |
| +} |
| + |
| + |
| +const char* ExternalTwoByteString::ToCString() const { |
| + return String::ToCString(); |
| +} |
| + |
| + |
| +RawExternalFourByteString* ExternalFourByteString::New(const uint32_t* data, |
| + intptr_t len, |
| + Finalizer finalizer, |
| + Heap::Space space) { |
| + Isolate* isolate = Isolate::Current(); |
| + |
| + const Class& cls = |
| + Class::Handle(isolate->object_store()->external_four_byte_string_class()); |
| + ExternalFourByteString& result = ExternalFourByteString::Handle(); |
| + { |
| + RawObject* raw = Object::Allocate(cls, |
| + ExternalFourByteString::InstanceSize(), |
| + space); |
| + NoGCScope no_gc; |
| + result ^= raw; |
| + result.SetLength(len); |
| + result.SetHash(0); |
| + result.SetData(data); |
| + } |
| + return result.raw(); |
| +} |
| + |
| + |
| +const char* ExternalFourByteString::ToCString() const { |
| + return String::ToCString(); |
| +} |
| + |
| + |
| RawBool* Bool::True() { |
| return Isolate::Current()->object_store()->true_value(); |
| } |