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

Side by Side Diff: src/objects.cc

Issue 2621913002: 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() == kThinStringTag) {
11066 ThinString* thin = ThinString::cast(string);
11067 string = thin->actual();
11068 shape = StringShape(string);
11069 } 11069 }
11070 if (shape.representation_tag() == kSlicedStringTag) { 11070 if (shape.representation_tag() == kSlicedStringTag) {
11071 SlicedString* slice = SlicedString::cast(string); 11071 SlicedString* slice = SlicedString::cast(string);
11072 offset = slice->offset(); 11072 offset = slice->offset();
11073 string = slice->parent(); 11073 string = slice->parent();
11074 shape = StringShape(string); 11074 shape = StringShape(string);
11075 DCHECK(shape.representation_tag() != kConsStringTag && 11075 DCHECK(shape.representation_tag() != kConsStringTag &&
11076 shape.representation_tag() != kSlicedStringTag); 11076 shape.representation_tag() != kSlicedStringTag);
11077 } 11077 }
11078 if (shape.encoding_tag() == kOneByteStringTag) { 11078 if (shape.encoding_tag() == kOneByteStringTag) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
11153 case kSeqStringTag: 11153 case kSeqStringTag:
11154 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); 11154 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
11155 case kExternalStringTag: 11155 case kExternalStringTag:
11156 return ExternalTwoByteString::cast(this)-> 11156 return ExternalTwoByteString::cast(this)->
11157 ExternalTwoByteStringGetData(start); 11157 ExternalTwoByteStringGetData(start);
11158 case kSlicedStringTag: { 11158 case kSlicedStringTag: {
11159 SlicedString* slice = SlicedString::cast(this); 11159 SlicedString* slice = SlicedString::cast(this);
11160 return slice->parent()->GetTwoByteData(start + slice->offset()); 11160 return slice->parent()->GetTwoByteData(start + slice->offset());
11161 } 11161 }
11162 case kConsStringTag: 11162 case kConsStringTag:
11163 case kThinStringTag:
11164 UNREACHABLE(); 11163 UNREACHABLE();
11165 return NULL; 11164 return NULL;
11166 } 11165 }
11167 UNREACHABLE(); 11166 UNREACHABLE();
11168 return NULL; 11167 return NULL;
11169 } 11168 }
11170 11169
11171 11170
11172 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { 11171 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
11173 return reinterpret_cast<uc16*>( 11172 return reinterpret_cast<uc16*>(
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
11420 } 11419 }
11421 } else { 11420 } else {
11422 return string->Get(index); 11421 return string->Get(index);
11423 } 11422 }
11424 } 11423 }
11425 11424
11426 UNREACHABLE(); 11425 UNREACHABLE();
11427 return 0; 11426 return 0;
11428 } 11427 }
11429 11428
11430 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); }
11431 11429
11432 uint16_t SlicedString::SlicedStringGet(int index) { 11430 uint16_t SlicedString::SlicedStringGet(int index) {
11433 return parent()->Get(offset() + index); 11431 return parent()->Get(offset() + index);
11434 } 11432 }
11435 11433
11436 11434
11437 template <typename sinkchar> 11435 template <typename sinkchar>
11438 void String::WriteToFlat(String* src, 11436 void String::WriteToFlat(String* src,
11439 sinkchar* sink, 11437 sinkchar* sink,
11440 int f, 11438 int f,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
11515 } 11513 }
11516 break; 11514 break;
11517 } 11515 }
11518 case kOneByteStringTag | kSlicedStringTag: 11516 case kOneByteStringTag | kSlicedStringTag:
11519 case kTwoByteStringTag | kSlicedStringTag: { 11517 case kTwoByteStringTag | kSlicedStringTag: {
11520 SlicedString* slice = SlicedString::cast(source); 11518 SlicedString* slice = SlicedString::cast(source);
11521 unsigned offset = slice->offset(); 11519 unsigned offset = slice->offset();
11522 WriteToFlat(slice->parent(), sink, from + offset, to + offset); 11520 WriteToFlat(slice->parent(), sink, from + offset, to + offset);
11523 return; 11521 return;
11524 } 11522 }
11525 case kOneByteStringTag | kThinStringTag:
11526 case kTwoByteStringTag | kThinStringTag:
11527 source = ThinString::cast(source)->actual();
11528 break;
11529 } 11523 }
11530 } 11524 }
11531 } 11525 }
11532 11526
11533 11527
11534 11528
11535 template <typename SourceChar> 11529 template <typename SourceChar>
11536 static void CalculateLineEndsImpl(Isolate* isolate, 11530 static void CalculateLineEndsImpl(Isolate* isolate,
11537 List<int>* line_ends, 11531 List<int>* line_ends,
11538 Vector<const SourceChar> src, 11532 Vector<const SourceChar> src,
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
11740 }; 11734 };
11741 11735
11742 11736
11743 bool String::SlowEquals(String* other) { 11737 bool String::SlowEquals(String* other) {
11744 DisallowHeapAllocation no_gc; 11738 DisallowHeapAllocation no_gc;
11745 // Fast check: negative check with lengths. 11739 // Fast check: negative check with lengths.
11746 int len = length(); 11740 int len = length();
11747 if (len != other->length()) return false; 11741 if (len != other->length()) return false;
11748 if (len == 0) return true; 11742 if (len == 0) return true;
11749 11743
11750 // Fast check: if at least one ThinString is involved, dereference it/them
11751 // and restart.
11752 if (this->IsThinString() || other->IsThinString()) {
11753 if (other->IsThinString()) other = ThinString::cast(other)->actual();
11754 if (this->IsThinString()) {
11755 return ThinString::cast(this)->actual()->Equals(other);
11756 } else {
11757 return this->Equals(other);
11758 }
11759 }
11760
11761 // Fast check: if hash code is computed for both strings 11744 // Fast check: if hash code is computed for both strings
11762 // a fast negative check can be performed. 11745 // a fast negative check can be performed.
11763 if (HasHashCode() && other->HasHashCode()) { 11746 if (HasHashCode() && other->HasHashCode()) {
11764 #ifdef ENABLE_SLOW_DCHECKS 11747 #ifdef ENABLE_SLOW_DCHECKS
11765 if (FLAG_enable_slow_asserts) { 11748 if (FLAG_enable_slow_asserts) {
11766 if (Hash() != other->Hash()) { 11749 if (Hash() != other->Hash()) {
11767 bool found_difference = false; 11750 bool found_difference = false;
11768 for (int i = 0; i < len; i++) { 11751 for (int i = 0; i < len; i++) {
11769 if (Get(i) != other->Get(i)) { 11752 if (Get(i) != other->Get(i)) {
11770 found_difference = true; 11753 found_difference = true;
(...skipping 21 matching lines...) Expand all
11792 return comparator.Equals(this, other); 11775 return comparator.Equals(this, other);
11793 } 11776 }
11794 11777
11795 11778
11796 bool String::SlowEquals(Handle<String> one, Handle<String> two) { 11779 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
11797 // Fast check: negative check with lengths. 11780 // Fast check: negative check with lengths.
11798 int one_length = one->length(); 11781 int one_length = one->length();
11799 if (one_length != two->length()) return false; 11782 if (one_length != two->length()) return false;
11800 if (one_length == 0) return true; 11783 if (one_length == 0) return true;
11801 11784
11802 // Fast check: if at least one ThinString is involved, dereference it/them
11803 // and restart.
11804 if (one->IsThinString() || two->IsThinString()) {
11805 if (one->IsThinString()) one = handle(ThinString::cast(*one)->actual());
11806 if (two->IsThinString()) two = handle(ThinString::cast(*two)->actual());
11807 return String::Equals(one, two);
11808 }
11809
11810 // Fast check: if hash code is computed for both strings 11785 // Fast check: if hash code is computed for both strings
11811 // a fast negative check can be performed. 11786 // a fast negative check can be performed.
11812 if (one->HasHashCode() && two->HasHashCode()) { 11787 if (one->HasHashCode() && two->HasHashCode()) {
11813 #ifdef ENABLE_SLOW_DCHECKS 11788 #ifdef ENABLE_SLOW_DCHECKS
11814 if (FLAG_enable_slow_asserts) { 11789 if (FLAG_enable_slow_asserts) {
11815 if (one->Hash() != two->Hash()) { 11790 if (one->Hash() != two->Hash()) {
11816 bool found_difference = false; 11791 bool found_difference = false;
11817 for (int i = 0; i < one_length; i++) { 11792 for (int i = 0; i < one_length; i++) {
11818 if (one->Get(i) != two->Get(i)) { 11793 if (one->Get(i) != two->Get(i)) {
11819 found_difference = true; 11794 found_difference = true;
(...skipping 5035 matching lines...) Expand 10 before | Expand all | Expand 10 after
16855 Handle<Object> AsHandle(Isolate* isolate) override { 16830 Handle<Object> AsHandle(Isolate* isolate) override {
16856 // Internalize the string if possible. 16831 // Internalize the string if possible.
16857 MaybeHandle<Map> maybe_map = 16832 MaybeHandle<Map> maybe_map =
16858 isolate->factory()->InternalizedStringMapForString(string_); 16833 isolate->factory()->InternalizedStringMapForString(string_);
16859 Handle<Map> map; 16834 Handle<Map> map;
16860 if (maybe_map.ToHandle(&map)) { 16835 if (maybe_map.ToHandle(&map)) {
16861 string_->set_map_no_write_barrier(*map); 16836 string_->set_map_no_write_barrier(*map);
16862 DCHECK(string_->IsInternalizedString()); 16837 DCHECK(string_->IsInternalizedString());
16863 return string_; 16838 return string_;
16864 } 16839 }
16865 // External strings get special treatment, to avoid copying their contents.
16866 if (string_->IsExternalOneByteString()) {
16867 return isolate->factory()
16868 ->InternalizeExternalString<ExternalOneByteString>(string_);
16869 } else if (string_->IsExternalTwoByteString()) {
16870 return isolate->factory()
16871 ->InternalizeExternalString<ExternalTwoByteString>(string_);
16872 }
16873 // Otherwise allocate a new internalized string. 16840 // Otherwise allocate a new internalized string.
16874 return isolate->factory()->NewInternalizedStringImpl( 16841 return isolate->factory()->NewInternalizedStringImpl(
16875 string_, string_->length(), string_->hash_field()); 16842 string_, string_->length(), string_->hash_field());
16876 } 16843 }
16877 16844
16878 static uint32_t StringHash(Object* obj) { 16845 static uint32_t StringHash(Object* obj) {
16879 return String::cast(obj)->Hash(); 16846 return String::cast(obj)->Hash();
16880 } 16847 }
16881 16848
16882 private:
16883 Handle<String> string_; 16849 Handle<String> string_;
16884 }; 16850 };
16885 16851
16886 16852
16887 template<typename Derived, typename Shape, typename Key> 16853 template<typename Derived, typename Shape, typename Key>
16888 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) { 16854 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
16889 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v); 16855 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
16890 } 16856 }
16891 16857
16892 16858
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after
17807 uint32_t hash_; 17773 uint32_t hash_;
17808 }; 17774 };
17809 17775
17810 17776
17811 MaybeHandle<String> StringTable::InternalizeStringIfExists( 17777 MaybeHandle<String> StringTable::InternalizeStringIfExists(
17812 Isolate* isolate, 17778 Isolate* isolate,
17813 Handle<String> string) { 17779 Handle<String> string) {
17814 if (string->IsInternalizedString()) { 17780 if (string->IsInternalizedString()) {
17815 return string; 17781 return string;
17816 } 17782 }
17817 if (string->IsThinString()) {
17818 return handle(Handle<ThinString>::cast(string)->actual(), isolate);
17819 }
17820 return LookupStringIfExists(isolate, string); 17783 return LookupStringIfExists(isolate, string);
17821 } 17784 }
17822 17785
17823 17786
17824 MaybeHandle<String> StringTable::LookupStringIfExists( 17787 MaybeHandle<String> StringTable::LookupStringIfExists(
17825 Isolate* isolate, 17788 Isolate* isolate,
17826 Handle<String> string) { 17789 Handle<String> string) {
17827 Handle<StringTable> string_table = isolate->factory()->string_table(); 17790 Handle<StringTable> string_table = isolate->factory()->string_table();
17828 InternalizedStringKey key(string); 17791 InternalizedStringKey key(string);
17829 int entry = string_table->FindEntry(&key); 17792 int entry = string_table->FindEntry(&key);
(...skipping 26 matching lines...) Expand all
17856 17819
17857 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, 17820 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
17858 int expected) { 17821 int expected) {
17859 Handle<StringTable> table = isolate->factory()->string_table(); 17822 Handle<StringTable> table = isolate->factory()->string_table();
17860 // We need a key instance for the virtual hash function. 17823 // We need a key instance for the virtual hash function.
17861 InternalizedStringKey dummy_key(isolate->factory()->empty_string()); 17824 InternalizedStringKey dummy_key(isolate->factory()->empty_string());
17862 table = StringTable::EnsureCapacity(table, expected, &dummy_key); 17825 table = StringTable::EnsureCapacity(table, expected, &dummy_key);
17863 isolate->heap()->SetRootStringTable(*table); 17826 isolate->heap()->SetRootStringTable(*table);
17864 } 17827 }
17865 17828
17866 namespace {
17867
17868 template <class StringClass>
17869 void MigrateExternalStringResource(Isolate* isolate, Handle<String> from,
17870 Handle<String> to) {
17871 Handle<StringClass> cast_from = Handle<StringClass>::cast(from);
17872 Handle<StringClass> cast_to = Handle<StringClass>::cast(to);
17873 const typename StringClass::Resource* to_resource = cast_to->resource();
17874 if (to_resource == nullptr) {
17875 // |to| is a just-created internalized copy of |from|. Migrate the resource.
17876 cast_to->set_resource(cast_from->resource());
17877 // Zap |from|'s resource pointer to reflect the fact that |from| has
17878 // relinquished ownership of its resource.
17879 cast_from->set_resource(nullptr);
17880 } else if (to_resource != cast_from->resource()) {
17881 // |to| already existed and has its own resource. Finalize |from|.
17882 isolate->heap()->FinalizeExternalString(*from);
17883 }
17884 }
17885
17886 } // namespace
17887 17829
17888 Handle<String> StringTable::LookupString(Isolate* isolate, 17830 Handle<String> StringTable::LookupString(Isolate* isolate,
17889 Handle<String> string) { 17831 Handle<String> string) {
17890 if (string->IsThinString()) {
17891 DCHECK(Handle<ThinString>::cast(string)->actual()->IsInternalizedString());
17892 return handle(Handle<ThinString>::cast(string)->actual(), isolate);
17893 }
17894 if (string->IsConsString() && string->IsFlat()) { 17832 if (string->IsConsString() && string->IsFlat()) {
17895 string = handle(Handle<ConsString>::cast(string)->first(), isolate); 17833 string = String::Flatten(string);
17896 if (string->IsInternalizedString()) return string; 17834 if (string->IsInternalizedString()) return string;
17897 } 17835 }
17898 17836
17899 InternalizedStringKey key(string); 17837 InternalizedStringKey key(string);
17900 Handle<String> result = LookupKey(isolate, &key); 17838 Handle<String> result = LookupKey(isolate, &key);
17901 17839
17902 if (string->IsExternalString()) { 17840 if (string->IsConsString()) {
17903 if (result->IsExternalOneByteString()) { 17841 Handle<ConsString> cons = Handle<ConsString>::cast(string);
17904 MigrateExternalStringResource<ExternalOneByteString>(isolate, string, 17842 cons->set_first(*result);
17905 result); 17843 cons->set_second(isolate->heap()->empty_string());
17906 } else if (result->IsExternalTwoByteString()) { 17844 } else if (string->IsSlicedString()) {
17907 MigrateExternalStringResource<ExternalTwoByteString>(isolate, string, 17845 STATIC_ASSERT(ConsString::kSize == SlicedString::kSize);
17908 result);
17909 }
17910 }
17911
17912 // The LookupKey() call above tries to internalize the string in-place.
17913 // In cases where that wasn't possible (e.g. new-space strings), turn them
17914 // into ThinStrings referring to their internalized versions now.
17915 if (!string->IsInternalizedString()) {
17916 DisallowHeapAllocation no_gc; 17846 DisallowHeapAllocation no_gc;
17917 bool one_byte = result->IsOneByteRepresentation(); 17847 bool one_byte = result->IsOneByteRepresentation();
17918 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()
17919 : isolate->factory()->thin_string_map(); 17849 : isolate->factory()->cons_string_map();
17920 int old_size = string->Size(); 17850 string->set_map(*map);
17921 DCHECK(old_size >= ThinString::kSize); 17851 Handle<ConsString> cons = Handle<ConsString>::cast(string);
17922 string->synchronized_set_map(*map); 17852 cons->set_first(*result);
17923 Handle<ThinString> thin = Handle<ThinString>::cast(string); 17853 cons->set_second(isolate->heap()->empty_string());
17924 thin->set_actual(*result);
17925 Address thin_end = thin->address() + ThinString::kSize;
17926 int size_delta = old_size - ThinString::kSize;
17927 if (size_delta != 0) {
17928 Heap* heap = isolate->heap();
17929 heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
17930 heap->AdjustLiveBytes(*thin, -size_delta);
17931 }
17932 } 17854 }
17933 return result; 17855 return result;
17934 } 17856 }
17935 17857
17936 17858
17937 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) { 17859 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
17938 Handle<StringTable> table = isolate->factory()->string_table(); 17860 Handle<StringTable> table = isolate->factory()->string_table();
17939 int entry = table->FindEntry(key); 17861 int entry = table->FindEntry(key);
17940 17862
17941 // String already in table. 17863 // String already in table.
(...skipping 2627 matching lines...) Expand 10 before | Expand all | Expand 10 after
20569 // depend on this. 20491 // depend on this.
20570 return DICTIONARY_ELEMENTS; 20492 return DICTIONARY_ELEMENTS;
20571 } 20493 }
20572 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20494 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20573 return kind; 20495 return kind;
20574 } 20496 }
20575 } 20497 }
20576 20498
20577 } // namespace internal 20499 } // namespace internal
20578 } // 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