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

Side by Side Diff: src/objects.cc

Issue 2625073002: Revert of Internalize strings in-place (Closed)
Patch Set: Created 3 years, 11 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
« no previous file with comments | « src/objects.h ('k') | src/objects-body-descriptors-inl.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 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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-body-descriptors-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698