| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 2494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2505 resource->data(), | 2505 resource->data(), |
| 2506 resource->length() * sizeof(smart_chars[0])) == 0); | 2506 resource->length() * sizeof(smart_chars[0])) == 0); |
| 2507 } | 2507 } |
| 2508 #endif // DEBUG | 2508 #endif // DEBUG |
| 2509 int size = this->Size(); // Byte size of the original string. | 2509 int size = this->Size(); // Byte size of the original string. |
| 2510 // Abort if size does not allow in-place conversion. | 2510 // Abort if size does not allow in-place conversion. |
| 2511 if (size < ExternalString::kShortSize) return false; | 2511 if (size < ExternalString::kShortSize) return false; |
| 2512 Heap* heap = GetHeap(); | 2512 Heap* heap = GetHeap(); |
| 2513 bool is_one_byte = this->IsOneByteRepresentation(); | 2513 bool is_one_byte = this->IsOneByteRepresentation(); |
| 2514 bool is_internalized = this->IsInternalizedString(); | 2514 bool is_internalized = this->IsInternalizedString(); |
| 2515 bool has_pointers = StringShape(this).IsIndirect(); | 2515 bool has_pointers = this->IsConsString() || this->IsSlicedString(); |
| 2516 | 2516 |
| 2517 // Morph the string to an external string by replacing the map and | 2517 // Morph the string to an external string by replacing the map and |
| 2518 // reinitializing the fields. This won't work if the space the existing | 2518 // reinitializing the fields. This won't work if the space the existing |
| 2519 // string occupies is too small for a regular external string. | 2519 // string occupies is too small for a regular external string. |
| 2520 // Instead, we resort to a short external string instead, omitting | 2520 // Instead, we resort to a short external string instead, omitting |
| 2521 // the field caching the address of the backing store. When we encounter | 2521 // the field caching the address of the backing store. When we encounter |
| 2522 // short external strings in generated code, we need to bailout to runtime. | 2522 // short external strings in generated code, we need to bailout to runtime. |
| 2523 Map* new_map; | 2523 Map* new_map; |
| 2524 if (size < ExternalString::kSize) { | 2524 if (size < ExternalString::kSize) { |
| 2525 new_map = is_internalized | 2525 new_map = is_internalized |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2577 DCHECK(memcmp(smart_chars.start(), | 2577 DCHECK(memcmp(smart_chars.start(), |
| 2578 resource->data(), | 2578 resource->data(), |
| 2579 resource->length() * sizeof(smart_chars[0])) == 0); | 2579 resource->length() * sizeof(smart_chars[0])) == 0); |
| 2580 } | 2580 } |
| 2581 #endif // DEBUG | 2581 #endif // DEBUG |
| 2582 int size = this->Size(); // Byte size of the original string. | 2582 int size = this->Size(); // Byte size of the original string. |
| 2583 // Abort if size does not allow in-place conversion. | 2583 // Abort if size does not allow in-place conversion. |
| 2584 if (size < ExternalString::kShortSize) return false; | 2584 if (size < ExternalString::kShortSize) return false; |
| 2585 Heap* heap = GetHeap(); | 2585 Heap* heap = GetHeap(); |
| 2586 bool is_internalized = this->IsInternalizedString(); | 2586 bool is_internalized = this->IsInternalizedString(); |
| 2587 bool has_pointers = StringShape(this).IsIndirect(); | 2587 bool has_pointers = this->IsConsString() || this->IsSlicedString(); |
| 2588 | 2588 |
| 2589 // Morph the string to an external string by replacing the map and | 2589 // Morph the string to an external string by replacing the map and |
| 2590 // reinitializing the fields. This won't work if the space the existing | 2590 // reinitializing the fields. This won't work if the space the existing |
| 2591 // string occupies is too small for a regular external string. | 2591 // string occupies is too small for a regular external string. |
| 2592 // Instead, we resort to a short external string instead, omitting | 2592 // Instead, we resort to a short external string instead, omitting |
| 2593 // the field caching the address of the backing store. When we encounter | 2593 // the field caching the address of the backing store. When we encounter |
| 2594 // short external strings in generated code, we need to bailout to runtime. | 2594 // short external strings in generated code, we need to bailout to runtime. |
| 2595 Map* new_map; | 2595 Map* new_map; |
| 2596 if (size < ExternalString::kSize) { | 2596 if (size < ExternalString::kSize) { |
| 2597 new_map = is_internalized | 2597 new_map = is_internalized |
| (...skipping 8323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10921 while ( | 10921 while ( |
| 10922 right > left && | 10922 right > left && |
| 10923 unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) { | 10923 unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) { |
| 10924 right--; | 10924 right--; |
| 10925 } | 10925 } |
| 10926 } | 10926 } |
| 10927 | 10927 |
| 10928 return isolate->factory()->NewSubString(string, left, right); | 10928 return isolate->factory()->NewSubString(string, left, right); |
| 10929 } | 10929 } |
| 10930 | 10930 |
| 10931 bool String::LooksValid() { return GetIsolate()->heap()->Contains(this); } | 10931 bool String::LooksValid() { |
| 10932 if (!GetIsolate()->heap()->Contains(this)) return false; |
| 10933 return true; |
| 10934 } |
| 10935 |
| 10932 | 10936 |
| 10933 // static | 10937 // static |
| 10934 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) { | 10938 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) { |
| 10935 if (name->IsString()) return Handle<String>::cast(name); | 10939 if (name->IsString()) return Handle<String>::cast(name); |
| 10936 // ES6 section 9.2.11 SetFunctionName, step 4. | 10940 // ES6 section 9.2.11 SetFunctionName, step 4. |
| 10937 Isolate* const isolate = name->GetIsolate(); | 10941 Isolate* const isolate = name->GetIsolate(); |
| 10938 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate); | 10942 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate); |
| 10939 if (description->IsUndefined(isolate)) { | 10943 if (description->IsUndefined(isolate)) { |
| 10940 return isolate->factory()->empty_string(); | 10944 return isolate->factory()->empty_string(); |
| 10941 } | 10945 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11055 StringShape shape(this); | 11059 StringShape shape(this); |
| 11056 String* string = this; | 11060 String* string = this; |
| 11057 int offset = 0; | 11061 int offset = 0; |
| 11058 if (shape.representation_tag() == kConsStringTag) { | 11062 if (shape.representation_tag() == kConsStringTag) { |
| 11059 ConsString* cons = ConsString::cast(string); | 11063 ConsString* cons = ConsString::cast(string); |
| 11060 if (cons->second()->length() != 0) { | 11064 if (cons->second()->length() != 0) { |
| 11061 return FlatContent(); | 11065 return FlatContent(); |
| 11062 } | 11066 } |
| 11063 string = cons->first(); | 11067 string = cons->first(); |
| 11064 shape = StringShape(string); | 11068 shape = StringShape(string); |
| 11065 } else if (shape.representation_tag() == kSlicedStringTag) { | 11069 } |
| 11070 if (shape.representation_tag() == kSlicedStringTag) { |
| 11066 SlicedString* slice = SlicedString::cast(string); | 11071 SlicedString* slice = SlicedString::cast(string); |
| 11067 offset = slice->offset(); | 11072 offset = slice->offset(); |
| 11068 string = slice->parent(); | 11073 string = slice->parent(); |
| 11069 shape = StringShape(string); | 11074 shape = StringShape(string); |
| 11070 DCHECK(shape.representation_tag() != kConsStringTag && | 11075 DCHECK(shape.representation_tag() != kConsStringTag && |
| 11071 shape.representation_tag() != kSlicedStringTag); | 11076 shape.representation_tag() != kSlicedStringTag); |
| 11072 } | 11077 } |
| 11073 if (shape.representation_tag() == kThinStringTag) { | |
| 11074 ThinString* thin = ThinString::cast(string); | |
| 11075 string = thin->actual(); | |
| 11076 shape = StringShape(string); | |
| 11077 DCHECK(!shape.IsCons()); | |
| 11078 DCHECK(!shape.IsSliced()); | |
| 11079 } | |
| 11080 if (shape.encoding_tag() == kOneByteStringTag) { | 11078 if (shape.encoding_tag() == kOneByteStringTag) { |
| 11081 const uint8_t* start; | 11079 const uint8_t* start; |
| 11082 if (shape.representation_tag() == kSeqStringTag) { | 11080 if (shape.representation_tag() == kSeqStringTag) { |
| 11083 start = SeqOneByteString::cast(string)->GetChars(); | 11081 start = SeqOneByteString::cast(string)->GetChars(); |
| 11084 } else { | 11082 } else { |
| 11085 start = ExternalOneByteString::cast(string)->GetChars(); | 11083 start = ExternalOneByteString::cast(string)->GetChars(); |
| 11086 } | 11084 } |
| 11087 return FlatContent(start + offset, length); | 11085 return FlatContent(start + offset, length); |
| 11088 } else { | 11086 } else { |
| 11089 DCHECK(shape.encoding_tag() == kTwoByteStringTag); | 11087 DCHECK(shape.encoding_tag() == kTwoByteStringTag); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11155 case kSeqStringTag: | 11153 case kSeqStringTag: |
| 11156 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); | 11154 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); |
| 11157 case kExternalStringTag: | 11155 case kExternalStringTag: |
| 11158 return ExternalTwoByteString::cast(this)-> | 11156 return ExternalTwoByteString::cast(this)-> |
| 11159 ExternalTwoByteStringGetData(start); | 11157 ExternalTwoByteStringGetData(start); |
| 11160 case kSlicedStringTag: { | 11158 case kSlicedStringTag: { |
| 11161 SlicedString* slice = SlicedString::cast(this); | 11159 SlicedString* slice = SlicedString::cast(this); |
| 11162 return slice->parent()->GetTwoByteData(start + slice->offset()); | 11160 return slice->parent()->GetTwoByteData(start + slice->offset()); |
| 11163 } | 11161 } |
| 11164 case kConsStringTag: | 11162 case kConsStringTag: |
| 11165 case kThinStringTag: | |
| 11166 UNREACHABLE(); | 11163 UNREACHABLE(); |
| 11167 return NULL; | 11164 return NULL; |
| 11168 } | 11165 } |
| 11169 UNREACHABLE(); | 11166 UNREACHABLE(); |
| 11170 return NULL; | 11167 return NULL; |
| 11171 } | 11168 } |
| 11172 | 11169 |
| 11173 | 11170 |
| 11174 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { | 11171 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { |
| 11175 return reinterpret_cast<uc16*>( | 11172 return reinterpret_cast<uc16*>( |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11422 } | 11419 } |
| 11423 } else { | 11420 } else { |
| 11424 return string->Get(index); | 11421 return string->Get(index); |
| 11425 } | 11422 } |
| 11426 } | 11423 } |
| 11427 | 11424 |
| 11428 UNREACHABLE(); | 11425 UNREACHABLE(); |
| 11429 return 0; | 11426 return 0; |
| 11430 } | 11427 } |
| 11431 | 11428 |
| 11432 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); } | |
| 11433 | 11429 |
| 11434 uint16_t SlicedString::SlicedStringGet(int index) { | 11430 uint16_t SlicedString::SlicedStringGet(int index) { |
| 11435 return parent()->Get(offset() + index); | 11431 return parent()->Get(offset() + index); |
| 11436 } | 11432 } |
| 11437 | 11433 |
| 11438 | 11434 |
| 11439 template <typename sinkchar> | 11435 template <typename sinkchar> |
| 11440 void String::WriteToFlat(String* src, | 11436 void String::WriteToFlat(String* src, |
| 11441 sinkchar* sink, | 11437 sinkchar* sink, |
| 11442 int f, | 11438 int f, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11517 } | 11513 } |
| 11518 break; | 11514 break; |
| 11519 } | 11515 } |
| 11520 case kOneByteStringTag | kSlicedStringTag: | 11516 case kOneByteStringTag | kSlicedStringTag: |
| 11521 case kTwoByteStringTag | kSlicedStringTag: { | 11517 case kTwoByteStringTag | kSlicedStringTag: { |
| 11522 SlicedString* slice = SlicedString::cast(source); | 11518 SlicedString* slice = SlicedString::cast(source); |
| 11523 unsigned offset = slice->offset(); | 11519 unsigned offset = slice->offset(); |
| 11524 WriteToFlat(slice->parent(), sink, from + offset, to + offset); | 11520 WriteToFlat(slice->parent(), sink, from + offset, to + offset); |
| 11525 return; | 11521 return; |
| 11526 } | 11522 } |
| 11527 case kOneByteStringTag | kThinStringTag: | |
| 11528 case kTwoByteStringTag | kThinStringTag: | |
| 11529 source = ThinString::cast(source)->actual(); | |
| 11530 break; | |
| 11531 } | 11523 } |
| 11532 } | 11524 } |
| 11533 } | 11525 } |
| 11534 | 11526 |
| 11535 | 11527 |
| 11536 | 11528 |
| 11537 template <typename SourceChar> | 11529 template <typename SourceChar> |
| 11538 static void CalculateLineEndsImpl(Isolate* isolate, | 11530 static void CalculateLineEndsImpl(Isolate* isolate, |
| 11539 List<int>* line_ends, | 11531 List<int>* line_ends, |
| 11540 Vector<const SourceChar> src, | 11532 Vector<const SourceChar> src, |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11742 }; | 11734 }; |
| 11743 | 11735 |
| 11744 | 11736 |
| 11745 bool String::SlowEquals(String* other) { | 11737 bool String::SlowEquals(String* other) { |
| 11746 DisallowHeapAllocation no_gc; | 11738 DisallowHeapAllocation no_gc; |
| 11747 // Fast check: negative check with lengths. | 11739 // Fast check: negative check with lengths. |
| 11748 int len = length(); | 11740 int len = length(); |
| 11749 if (len != other->length()) return false; | 11741 if (len != other->length()) return false; |
| 11750 if (len == 0) return true; | 11742 if (len == 0) return true; |
| 11751 | 11743 |
| 11752 // Fast check: if at least one ThinString is involved, dereference it/them | |
| 11753 // and restart. | |
| 11754 if (this->IsThinString() || other->IsThinString()) { | |
| 11755 if (other->IsThinString()) other = ThinString::cast(other)->actual(); | |
| 11756 if (this->IsThinString()) { | |
| 11757 return ThinString::cast(this)->actual()->Equals(other); | |
| 11758 } else { | |
| 11759 return this->Equals(other); | |
| 11760 } | |
| 11761 } | |
| 11762 | |
| 11763 // Fast check: if hash code is computed for both strings | 11744 // Fast check: if hash code is computed for both strings |
| 11764 // a fast negative check can be performed. | 11745 // a fast negative check can be performed. |
| 11765 if (HasHashCode() && other->HasHashCode()) { | 11746 if (HasHashCode() && other->HasHashCode()) { |
| 11766 #ifdef ENABLE_SLOW_DCHECKS | 11747 #ifdef ENABLE_SLOW_DCHECKS |
| 11767 if (FLAG_enable_slow_asserts) { | 11748 if (FLAG_enable_slow_asserts) { |
| 11768 if (Hash() != other->Hash()) { | 11749 if (Hash() != other->Hash()) { |
| 11769 bool found_difference = false; | 11750 bool found_difference = false; |
| 11770 for (int i = 0; i < len; i++) { | 11751 for (int i = 0; i < len; i++) { |
| 11771 if (Get(i) != other->Get(i)) { | 11752 if (Get(i) != other->Get(i)) { |
| 11772 found_difference = true; | 11753 found_difference = true; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 11794 return comparator.Equals(this, other); | 11775 return comparator.Equals(this, other); |
| 11795 } | 11776 } |
| 11796 | 11777 |
| 11797 | 11778 |
| 11798 bool String::SlowEquals(Handle<String> one, Handle<String> two) { | 11779 bool String::SlowEquals(Handle<String> one, Handle<String> two) { |
| 11799 // Fast check: negative check with lengths. | 11780 // Fast check: negative check with lengths. |
| 11800 int one_length = one->length(); | 11781 int one_length = one->length(); |
| 11801 if (one_length != two->length()) return false; | 11782 if (one_length != two->length()) return false; |
| 11802 if (one_length == 0) return true; | 11783 if (one_length == 0) return true; |
| 11803 | 11784 |
| 11804 // Fast check: if at least one ThinString is involved, dereference it/them | |
| 11805 // and restart. | |
| 11806 if (one->IsThinString() || two->IsThinString()) { | |
| 11807 if (one->IsThinString()) one = handle(ThinString::cast(*one)->actual()); | |
| 11808 if (two->IsThinString()) two = handle(ThinString::cast(*two)->actual()); | |
| 11809 return String::Equals(one, two); | |
| 11810 } | |
| 11811 | |
| 11812 // Fast check: if hash code is computed for both strings | 11785 // Fast check: if hash code is computed for both strings |
| 11813 // a fast negative check can be performed. | 11786 // a fast negative check can be performed. |
| 11814 if (one->HasHashCode() && two->HasHashCode()) { | 11787 if (one->HasHashCode() && two->HasHashCode()) { |
| 11815 #ifdef ENABLE_SLOW_DCHECKS | 11788 #ifdef ENABLE_SLOW_DCHECKS |
| 11816 if (FLAG_enable_slow_asserts) { | 11789 if (FLAG_enable_slow_asserts) { |
| 11817 if (one->Hash() != two->Hash()) { | 11790 if (one->Hash() != two->Hash()) { |
| 11818 bool found_difference = false; | 11791 bool found_difference = false; |
| 11819 for (int i = 0; i < one_length; i++) { | 11792 for (int i = 0; i < one_length; i++) { |
| 11820 if (one->Get(i) != two->Get(i)) { | 11793 if (one->Get(i) != two->Get(i)) { |
| 11821 found_difference = true; | 11794 found_difference = true; |
| (...skipping 5035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16857 Handle<Object> AsHandle(Isolate* isolate) override { | 16830 Handle<Object> AsHandle(Isolate* isolate) override { |
| 16858 // Internalize the string if possible. | 16831 // Internalize the string if possible. |
| 16859 MaybeHandle<Map> maybe_map = | 16832 MaybeHandle<Map> maybe_map = |
| 16860 isolate->factory()->InternalizedStringMapForString(string_); | 16833 isolate->factory()->InternalizedStringMapForString(string_); |
| 16861 Handle<Map> map; | 16834 Handle<Map> map; |
| 16862 if (maybe_map.ToHandle(&map)) { | 16835 if (maybe_map.ToHandle(&map)) { |
| 16863 string_->set_map_no_write_barrier(*map); | 16836 string_->set_map_no_write_barrier(*map); |
| 16864 DCHECK(string_->IsInternalizedString()); | 16837 DCHECK(string_->IsInternalizedString()); |
| 16865 return string_; | 16838 return string_; |
| 16866 } | 16839 } |
| 16867 // External strings get special treatment, to avoid copying their contents. | |
| 16868 if (string_->IsExternalOneByteString()) { | |
| 16869 return isolate->factory() | |
| 16870 ->InternalizeExternalString<ExternalOneByteString>(string_); | |
| 16871 } else if (string_->IsExternalTwoByteString()) { | |
| 16872 return isolate->factory() | |
| 16873 ->InternalizeExternalString<ExternalTwoByteString>(string_); | |
| 16874 } | |
| 16875 // Otherwise allocate a new internalized string. | 16840 // Otherwise allocate a new internalized string. |
| 16876 return isolate->factory()->NewInternalizedStringImpl( | 16841 return isolate->factory()->NewInternalizedStringImpl( |
| 16877 string_, string_->length(), string_->hash_field()); | 16842 string_, string_->length(), string_->hash_field()); |
| 16878 } | 16843 } |
| 16879 | 16844 |
| 16880 static uint32_t StringHash(Object* obj) { | 16845 static uint32_t StringHash(Object* obj) { |
| 16881 return String::cast(obj)->Hash(); | 16846 return String::cast(obj)->Hash(); |
| 16882 } | 16847 } |
| 16883 | 16848 |
| 16884 private: | |
| 16885 Handle<String> string_; | 16849 Handle<String> string_; |
| 16886 }; | 16850 }; |
| 16887 | 16851 |
| 16888 | 16852 |
| 16889 template<typename Derived, typename Shape, typename Key> | 16853 template<typename Derived, typename Shape, typename Key> |
| 16890 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) { | 16854 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) { |
| 16891 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v); | 16855 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v); |
| 16892 } | 16856 } |
| 16893 | 16857 |
| 16894 | 16858 |
| (...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17809 uint32_t hash_; | 17773 uint32_t hash_; |
| 17810 }; | 17774 }; |
| 17811 | 17775 |
| 17812 | 17776 |
| 17813 MaybeHandle<String> StringTable::InternalizeStringIfExists( | 17777 MaybeHandle<String> StringTable::InternalizeStringIfExists( |
| 17814 Isolate* isolate, | 17778 Isolate* isolate, |
| 17815 Handle<String> string) { | 17779 Handle<String> string) { |
| 17816 if (string->IsInternalizedString()) { | 17780 if (string->IsInternalizedString()) { |
| 17817 return string; | 17781 return string; |
| 17818 } | 17782 } |
| 17819 if (string->IsThinString()) { | |
| 17820 return handle(Handle<ThinString>::cast(string)->actual(), isolate); | |
| 17821 } | |
| 17822 return LookupStringIfExists(isolate, string); | 17783 return LookupStringIfExists(isolate, string); |
| 17823 } | 17784 } |
| 17824 | 17785 |
| 17825 | 17786 |
| 17826 MaybeHandle<String> StringTable::LookupStringIfExists( | 17787 MaybeHandle<String> StringTable::LookupStringIfExists( |
| 17827 Isolate* isolate, | 17788 Isolate* isolate, |
| 17828 Handle<String> string) { | 17789 Handle<String> string) { |
| 17829 Handle<StringTable> string_table = isolate->factory()->string_table(); | 17790 Handle<StringTable> string_table = isolate->factory()->string_table(); |
| 17830 InternalizedStringKey key(string); | 17791 InternalizedStringKey key(string); |
| 17831 int entry = string_table->FindEntry(&key); | 17792 int entry = string_table->FindEntry(&key); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 17858 | 17819 |
| 17859 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, | 17820 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, |
| 17860 int expected) { | 17821 int expected) { |
| 17861 Handle<StringTable> table = isolate->factory()->string_table(); | 17822 Handle<StringTable> table = isolate->factory()->string_table(); |
| 17862 // We need a key instance for the virtual hash function. | 17823 // We need a key instance for the virtual hash function. |
| 17863 InternalizedStringKey dummy_key(isolate->factory()->empty_string()); | 17824 InternalizedStringKey dummy_key(isolate->factory()->empty_string()); |
| 17864 table = StringTable::EnsureCapacity(table, expected, &dummy_key); | 17825 table = StringTable::EnsureCapacity(table, expected, &dummy_key); |
| 17865 isolate->heap()->SetRootStringTable(*table); | 17826 isolate->heap()->SetRootStringTable(*table); |
| 17866 } | 17827 } |
| 17867 | 17828 |
| 17868 namespace { | |
| 17869 | |
| 17870 template <class StringClass> | |
| 17871 void MigrateExternalStringResource(Isolate* isolate, Handle<String> from, | |
| 17872 Handle<String> to) { | |
| 17873 Handle<StringClass> cast_from = Handle<StringClass>::cast(from); | |
| 17874 Handle<StringClass> cast_to = Handle<StringClass>::cast(to); | |
| 17875 const typename StringClass::Resource* to_resource = cast_to->resource(); | |
| 17876 if (to_resource == nullptr) { | |
| 17877 // |to| is a just-created internalized copy of |from|. Migrate the resource. | |
| 17878 cast_to->set_resource(cast_from->resource()); | |
| 17879 // Zap |from|'s resource pointer to reflect the fact that |from| has | |
| 17880 // relinquished ownership of its resource. | |
| 17881 cast_from->set_resource(nullptr); | |
| 17882 } else if (to_resource != cast_from->resource()) { | |
| 17883 // |to| already existed and has its own resource. Finalize |from|. | |
| 17884 isolate->heap()->FinalizeExternalString(*from); | |
| 17885 } | |
| 17886 } | |
| 17887 | |
| 17888 } // namespace | |
| 17889 | 17829 |
| 17890 Handle<String> StringTable::LookupString(Isolate* isolate, | 17830 Handle<String> StringTable::LookupString(Isolate* isolate, |
| 17891 Handle<String> string) { | 17831 Handle<String> string) { |
| 17892 if (string->IsThinString()) { | |
| 17893 DCHECK(Handle<ThinString>::cast(string)->actual()->IsInternalizedString()); | |
| 17894 return handle(Handle<ThinString>::cast(string)->actual(), isolate); | |
| 17895 } | |
| 17896 if (string->IsConsString() && string->IsFlat()) { | 17832 if (string->IsConsString() && string->IsFlat()) { |
| 17897 string = handle(Handle<ConsString>::cast(string)->first(), isolate); | 17833 string = String::Flatten(string); |
| 17898 if (string->IsInternalizedString()) return string; | 17834 if (string->IsInternalizedString()) return string; |
| 17899 } | 17835 } |
| 17900 | 17836 |
| 17901 InternalizedStringKey key(string); | 17837 InternalizedStringKey key(string); |
| 17902 Handle<String> result = LookupKey(isolate, &key); | 17838 Handle<String> result = LookupKey(isolate, &key); |
| 17903 | 17839 |
| 17904 if (string->IsExternalString()) { | 17840 if (string->IsConsString()) { |
| 17905 if (result->IsExternalOneByteString()) { | 17841 Handle<ConsString> cons = Handle<ConsString>::cast(string); |
| 17906 MigrateExternalStringResource<ExternalOneByteString>(isolate, string, | 17842 cons->set_first(*result); |
| 17907 result); | 17843 cons->set_second(isolate->heap()->empty_string()); |
| 17908 } else if (result->IsExternalTwoByteString()) { | 17844 } else if (string->IsSlicedString()) { |
| 17909 MigrateExternalStringResource<ExternalTwoByteString>(isolate, string, | 17845 STATIC_ASSERT(ConsString::kSize == SlicedString::kSize); |
| 17910 result); | |
| 17911 } | |
| 17912 } | |
| 17913 | |
| 17914 // The LookupKey() call above tries to internalize the string in-place. | |
| 17915 // In cases where that wasn't possible (e.g. new-space strings), turn them | |
| 17916 // into ThinStrings referring to their internalized versions now. | |
| 17917 if (!string->IsInternalizedString()) { | |
| 17918 DisallowHeapAllocation no_gc; | 17846 DisallowHeapAllocation no_gc; |
| 17919 bool one_byte = result->IsOneByteRepresentation(); | 17847 bool one_byte = result->IsOneByteRepresentation(); |
| 17920 Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map() | 17848 Handle<Map> map = one_byte ? isolate->factory()->cons_one_byte_string_map() |
| 17921 : isolate->factory()->thin_string_map(); | 17849 : isolate->factory()->cons_string_map(); |
| 17922 int old_size = string->Size(); | 17850 string->set_map(*map); |
| 17923 DCHECK(old_size >= ThinString::kSize); | 17851 Handle<ConsString> cons = Handle<ConsString>::cast(string); |
| 17924 string->synchronized_set_map(*map); | 17852 cons->set_first(*result); |
| 17925 Handle<ThinString> thin = Handle<ThinString>::cast(string); | 17853 cons->set_second(isolate->heap()->empty_string()); |
| 17926 thin->set_actual(*result); | |
| 17927 Address thin_end = thin->address() + ThinString::kSize; | |
| 17928 int size_delta = old_size - ThinString::kSize; | |
| 17929 if (size_delta != 0) { | |
| 17930 Heap* heap = isolate->heap(); | |
| 17931 heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo); | |
| 17932 heap->AdjustLiveBytes(*thin, -size_delta); | |
| 17933 } | |
| 17934 } | 17854 } |
| 17935 return result; | 17855 return result; |
| 17936 } | 17856 } |
| 17937 | 17857 |
| 17938 | 17858 |
| 17939 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) { | 17859 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) { |
| 17940 Handle<StringTable> table = isolate->factory()->string_table(); | 17860 Handle<StringTable> table = isolate->factory()->string_table(); |
| 17941 int entry = table->FindEntry(key); | 17861 int entry = table->FindEntry(key); |
| 17942 | 17862 |
| 17943 // String already in table. | 17863 // String already in table. |
| (...skipping 2627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20571 // depend on this. | 20491 // depend on this. |
| 20572 return DICTIONARY_ELEMENTS; | 20492 return DICTIONARY_ELEMENTS; |
| 20573 } | 20493 } |
| 20574 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20494 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 20575 return kind; | 20495 return kind; |
| 20576 } | 20496 } |
| 20577 } | 20497 } |
| 20578 | 20498 |
| 20579 } // namespace internal | 20499 } // namespace internal |
| 20580 } // namespace v8 | 20500 } // namespace v8 |
| OLD | NEW |