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

Side by Side Diff: src/objects.cc

Issue 2549773002: Internalize strings in-place (Closed)
Patch Set: forgot one Created 4 years 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
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 2313 matching lines...) Expand 10 before | Expand all | Expand 10 after
2324 resource->data(), 2324 resource->data(),
2325 resource->length() * sizeof(smart_chars[0])) == 0); 2325 resource->length() * sizeof(smart_chars[0])) == 0);
2326 } 2326 }
2327 #endif // DEBUG 2327 #endif // DEBUG
2328 int size = this->Size(); // Byte size of the original string. 2328 int size = this->Size(); // Byte size of the original string.
2329 // Abort if size does not allow in-place conversion. 2329 // Abort if size does not allow in-place conversion.
2330 if (size < ExternalString::kShortSize) return false; 2330 if (size < ExternalString::kShortSize) return false;
2331 Heap* heap = GetHeap(); 2331 Heap* heap = GetHeap();
2332 bool is_one_byte = this->IsOneByteRepresentation(); 2332 bool is_one_byte = this->IsOneByteRepresentation();
2333 bool is_internalized = this->IsInternalizedString(); 2333 bool is_internalized = this->IsInternalizedString();
2334 bool has_pointers = this->IsConsString() || this->IsSlicedString(); 2334 bool has_pointers =
2335 this->IsConsString() || this->IsSlicedString() || this->IsThinString();
Igor Sheludko 2016/12/20 23:46:58 Suggestion for follow-up CL: bool IsIndirectStrin
Jakob Kummerow 2017/01/04 12:45:06 Done (StringShape supports this already).
2335 2336
2336 // Morph the string to an external string by replacing the map and 2337 // Morph the string to an external string by replacing the map and
2337 // reinitializing the fields. This won't work if the space the existing 2338 // reinitializing the fields. This won't work if the space the existing
2338 // string occupies is too small for a regular external string. 2339 // string occupies is too small for a regular external string.
2339 // Instead, we resort to a short external string instead, omitting 2340 // Instead, we resort to a short external string instead, omitting
2340 // the field caching the address of the backing store. When we encounter 2341 // the field caching the address of the backing store. When we encounter
2341 // short external strings in generated code, we need to bailout to runtime. 2342 // short external strings in generated code, we need to bailout to runtime.
2342 Map* new_map; 2343 Map* new_map;
2343 if (size < ExternalString::kSize) { 2344 if (size < ExternalString::kSize) {
2344 new_map = is_internalized 2345 new_map = is_internalized
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2396 DCHECK(memcmp(smart_chars.start(), 2397 DCHECK(memcmp(smart_chars.start(),
2397 resource->data(), 2398 resource->data(),
2398 resource->length() * sizeof(smart_chars[0])) == 0); 2399 resource->length() * sizeof(smart_chars[0])) == 0);
2399 } 2400 }
2400 #endif // DEBUG 2401 #endif // DEBUG
2401 int size = this->Size(); // Byte size of the original string. 2402 int size = this->Size(); // Byte size of the original string.
2402 // Abort if size does not allow in-place conversion. 2403 // Abort if size does not allow in-place conversion.
2403 if (size < ExternalString::kShortSize) return false; 2404 if (size < ExternalString::kShortSize) return false;
2404 Heap* heap = GetHeap(); 2405 Heap* heap = GetHeap();
2405 bool is_internalized = this->IsInternalizedString(); 2406 bool is_internalized = this->IsInternalizedString();
2406 bool has_pointers = this->IsConsString() || this->IsSlicedString(); 2407 bool has_pointers =
2408 this->IsConsString() || this->IsSlicedString() || this->IsThinString();
Igor Sheludko 2016/12/20 23:46:58 Same here.
Jakob Kummerow 2017/01/04 12:45:06 Done.
2407 2409
2408 // Morph the string to an external string by replacing the map and 2410 // Morph the string to an external string by replacing the map and
2409 // reinitializing the fields. This won't work if the space the existing 2411 // reinitializing the fields. This won't work if the space the existing
2410 // string occupies is too small for a regular external string. 2412 // string occupies is too small for a regular external string.
2411 // Instead, we resort to a short external string instead, omitting 2413 // Instead, we resort to a short external string instead, omitting
2412 // the field caching the address of the backing store. When we encounter 2414 // the field caching the address of the backing store. When we encounter
2413 // short external strings in generated code, we need to bailout to runtime. 2415 // short external strings in generated code, we need to bailout to runtime.
2414 Map* new_map; 2416 Map* new_map;
2415 if (size < ExternalString::kSize) { 2417 if (size < ExternalString::kSize) {
2416 new_map = is_internalized 2418 new_map = is_internalized
(...skipping 8344 matching lines...) Expand 10 before | Expand all | Expand 10 after
10761 while ( 10763 while (
10762 right > left && 10764 right > left &&
10763 unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) { 10765 unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
10764 right--; 10766 right--;
10765 } 10767 }
10766 } 10768 }
10767 10769
10768 return isolate->factory()->NewSubString(string, left, right); 10770 return isolate->factory()->NewSubString(string, left, right);
10769 } 10771 }
10770 10772
10771 bool String::LooksValid() { 10773 bool String::LooksValid() { return GetIsolate()->heap()->Contains(this); }
10772 if (!GetIsolate()->heap()->Contains(this)) return false;
10773 return true;
10774 }
10775
10776 10774
10777 // static 10775 // static
10778 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) { 10776 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) {
10779 if (name->IsString()) return Handle<String>::cast(name); 10777 if (name->IsString()) return Handle<String>::cast(name);
10780 // ES6 section 9.2.11 SetFunctionName, step 4. 10778 // ES6 section 9.2.11 SetFunctionName, step 4.
10781 Isolate* const isolate = name->GetIsolate(); 10779 Isolate* const isolate = name->GetIsolate();
10782 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate); 10780 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
10783 if (description->IsUndefined(isolate)) { 10781 if (description->IsUndefined(isolate)) {
10784 return isolate->factory()->empty_string(); 10782 return isolate->factory()->empty_string();
10785 } 10783 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
10899 StringShape shape(this); 10897 StringShape shape(this);
10900 String* string = this; 10898 String* string = this;
10901 int offset = 0; 10899 int offset = 0;
10902 if (shape.representation_tag() == kConsStringTag) { 10900 if (shape.representation_tag() == kConsStringTag) {
10903 ConsString* cons = ConsString::cast(string); 10901 ConsString* cons = ConsString::cast(string);
10904 if (cons->second()->length() != 0) { 10902 if (cons->second()->length() != 0) {
10905 return FlatContent(); 10903 return FlatContent();
10906 } 10904 }
10907 string = cons->first(); 10905 string = cons->first();
10908 shape = StringShape(string); 10906 shape = StringShape(string);
10907 } else if (shape.representation_tag() == kThinStringTag) {
10908 ThinString* thin = ThinString::cast(string);
10909 string = thin->actual();
10910 shape = StringShape(string);
10909 } 10911 }
10910 if (shape.representation_tag() == kSlicedStringTag) { 10912 if (shape.representation_tag() == kSlicedStringTag) {
10911 SlicedString* slice = SlicedString::cast(string); 10913 SlicedString* slice = SlicedString::cast(string);
10912 offset = slice->offset(); 10914 offset = slice->offset();
10913 string = slice->parent(); 10915 string = slice->parent();
10914 shape = StringShape(string); 10916 shape = StringShape(string);
10915 DCHECK(shape.representation_tag() != kConsStringTag && 10917 DCHECK(shape.representation_tag() != kConsStringTag &&
10916 shape.representation_tag() != kSlicedStringTag); 10918 shape.representation_tag() != kSlicedStringTag);
10917 } 10919 }
10918 if (shape.encoding_tag() == kOneByteStringTag) { 10920 if (shape.encoding_tag() == kOneByteStringTag) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
10993 case kSeqStringTag: 10995 case kSeqStringTag:
10994 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); 10996 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
10995 case kExternalStringTag: 10997 case kExternalStringTag:
10996 return ExternalTwoByteString::cast(this)-> 10998 return ExternalTwoByteString::cast(this)->
10997 ExternalTwoByteStringGetData(start); 10999 ExternalTwoByteStringGetData(start);
10998 case kSlicedStringTag: { 11000 case kSlicedStringTag: {
10999 SlicedString* slice = SlicedString::cast(this); 11001 SlicedString* slice = SlicedString::cast(this);
11000 return slice->parent()->GetTwoByteData(start + slice->offset()); 11002 return slice->parent()->GetTwoByteData(start + slice->offset());
11001 } 11003 }
11002 case kConsStringTag: 11004 case kConsStringTag:
11005 case kThinStringTag:
11003 UNREACHABLE(); 11006 UNREACHABLE();
11004 return NULL; 11007 return NULL;
11005 } 11008 }
11006 UNREACHABLE(); 11009 UNREACHABLE();
11007 return NULL; 11010 return NULL;
11008 } 11011 }
11009 11012
11010 11013
11011 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { 11014 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
11012 return reinterpret_cast<uc16*>( 11015 return reinterpret_cast<uc16*>(
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
11259 } 11262 }
11260 } else { 11263 } else {
11261 return string->Get(index); 11264 return string->Get(index);
11262 } 11265 }
11263 } 11266 }
11264 11267
11265 UNREACHABLE(); 11268 UNREACHABLE();
11266 return 0; 11269 return 0;
11267 } 11270 }
11268 11271
11272 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); }
11269 11273
11270 uint16_t SlicedString::SlicedStringGet(int index) { 11274 uint16_t SlicedString::SlicedStringGet(int index) {
11271 return parent()->Get(offset() + index); 11275 return parent()->Get(offset() + index);
11272 } 11276 }
11273 11277
11274 11278
11275 template <typename sinkchar> 11279 template <typename sinkchar>
11276 void String::WriteToFlat(String* src, 11280 void String::WriteToFlat(String* src,
11277 sinkchar* sink, 11281 sinkchar* sink,
11278 int f, 11282 int f,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
11353 } 11357 }
11354 break; 11358 break;
11355 } 11359 }
11356 case kOneByteStringTag | kSlicedStringTag: 11360 case kOneByteStringTag | kSlicedStringTag:
11357 case kTwoByteStringTag | kSlicedStringTag: { 11361 case kTwoByteStringTag | kSlicedStringTag: {
11358 SlicedString* slice = SlicedString::cast(source); 11362 SlicedString* slice = SlicedString::cast(source);
11359 unsigned offset = slice->offset(); 11363 unsigned offset = slice->offset();
11360 WriteToFlat(slice->parent(), sink, from + offset, to + offset); 11364 WriteToFlat(slice->parent(), sink, from + offset, to + offset);
11361 return; 11365 return;
11362 } 11366 }
11367 case kOneByteStringTag | kThinStringTag:
11368 case kTwoByteStringTag | kThinStringTag:
11369 source = ThinString::cast(source)->actual();
11370 break;
11363 } 11371 }
11364 } 11372 }
11365 } 11373 }
11366 11374
11367 11375
11368 11376
11369 template <typename SourceChar> 11377 template <typename SourceChar>
11370 static void CalculateLineEndsImpl(Isolate* isolate, 11378 static void CalculateLineEndsImpl(Isolate* isolate,
11371 List<int>* line_ends, 11379 List<int>* line_ends,
11372 Vector<const SourceChar> src, 11380 Vector<const SourceChar> src,
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
11574 }; 11582 };
11575 11583
11576 11584
11577 bool String::SlowEquals(String* other) { 11585 bool String::SlowEquals(String* other) {
11578 DisallowHeapAllocation no_gc; 11586 DisallowHeapAllocation no_gc;
11579 // Fast check: negative check with lengths. 11587 // Fast check: negative check with lengths.
11580 int len = length(); 11588 int len = length();
11581 if (len != other->length()) return false; 11589 if (len != other->length()) return false;
11582 if (len == 0) return true; 11590 if (len == 0) return true;
11583 11591
11592 // Fast check: if at least one ThinString is involved, dereference it/them
11593 // and restart.
11594 if (this->IsThinString() || other->IsThinString()) {
11595 if (other->IsThinString()) other = ThinString::cast(other)->actual();
11596 if (this->IsThinString()) {
11597 return ThinString::cast(this)->actual()->Equals(other);
11598 } else {
11599 return this->Equals(other);
11600 }
11601 }
11602
11584 // Fast check: if hash code is computed for both strings 11603 // Fast check: if hash code is computed for both strings
11585 // a fast negative check can be performed. 11604 // a fast negative check can be performed.
11586 if (HasHashCode() && other->HasHashCode()) { 11605 if (HasHashCode() && other->HasHashCode()) {
11587 #ifdef ENABLE_SLOW_DCHECKS 11606 #ifdef ENABLE_SLOW_DCHECKS
11588 if (FLAG_enable_slow_asserts) { 11607 if (FLAG_enable_slow_asserts) {
11589 if (Hash() != other->Hash()) { 11608 if (Hash() != other->Hash()) {
11590 bool found_difference = false; 11609 bool found_difference = false;
11591 for (int i = 0; i < len; i++) { 11610 for (int i = 0; i < len; i++) {
11592 if (Get(i) != other->Get(i)) { 11611 if (Get(i) != other->Get(i)) {
11593 found_difference = true; 11612 found_difference = true;
(...skipping 21 matching lines...) Expand all
11615 return comparator.Equals(this, other); 11634 return comparator.Equals(this, other);
11616 } 11635 }
11617 11636
11618 11637
11619 bool String::SlowEquals(Handle<String> one, Handle<String> two) { 11638 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
11620 // Fast check: negative check with lengths. 11639 // Fast check: negative check with lengths.
11621 int one_length = one->length(); 11640 int one_length = one->length();
11622 if (one_length != two->length()) return false; 11641 if (one_length != two->length()) return false;
11623 if (one_length == 0) return true; 11642 if (one_length == 0) return true;
11624 11643
11644 // Fast check: if at least one ThinString is involved, dereference it/them
11645 // and restart.
11646 if (one->IsThinString() || two->IsThinString()) {
11647 if (one->IsThinString()) one = handle(ThinString::cast(*one)->actual());
11648 if (two->IsThinString()) two = handle(ThinString::cast(*two)->actual());
11649 return String::Equals(one, two);
11650 }
11651
11625 // Fast check: if hash code is computed for both strings 11652 // Fast check: if hash code is computed for both strings
11626 // a fast negative check can be performed. 11653 // a fast negative check can be performed.
11627 if (one->HasHashCode() && two->HasHashCode()) { 11654 if (one->HasHashCode() && two->HasHashCode()) {
11628 #ifdef ENABLE_SLOW_DCHECKS 11655 #ifdef ENABLE_SLOW_DCHECKS
11629 if (FLAG_enable_slow_asserts) { 11656 if (FLAG_enable_slow_asserts) {
11630 if (one->Hash() != two->Hash()) { 11657 if (one->Hash() != two->Hash()) {
11631 bool found_difference = false; 11658 bool found_difference = false;
11632 for (int i = 0; i < one_length; i++) { 11659 for (int i = 0; i < one_length; i++) {
11633 if (one->Get(i) != two->Get(i)) { 11660 if (one->Get(i) != two->Get(i)) {
11634 found_difference = true; 11661 found_difference = true;
(...skipping 5129 matching lines...) Expand 10 before | Expand all | Expand 10 after
16764 Handle<Object> AsHandle(Isolate* isolate) override { 16791 Handle<Object> AsHandle(Isolate* isolate) override {
16765 // Internalize the string if possible. 16792 // Internalize the string if possible.
16766 MaybeHandle<Map> maybe_map = 16793 MaybeHandle<Map> maybe_map =
16767 isolate->factory()->InternalizedStringMapForString(string_); 16794 isolate->factory()->InternalizedStringMapForString(string_);
16768 Handle<Map> map; 16795 Handle<Map> map;
16769 if (maybe_map.ToHandle(&map)) { 16796 if (maybe_map.ToHandle(&map)) {
16770 string_->set_map_no_write_barrier(*map); 16797 string_->set_map_no_write_barrier(*map);
16771 DCHECK(string_->IsInternalizedString()); 16798 DCHECK(string_->IsInternalizedString());
16772 return string_; 16799 return string_;
16773 } 16800 }
16801 // External strings get special treatment, to avoid copying their contents.
16802 if (string_->IsExternalOneByteString()) {
16803 return isolate->factory()
16804 ->InternalizeExternalString<ExternalOneByteString>(string_);
16805 } else if (string_->IsExternalTwoByteString()) {
16806 return isolate->factory()
16807 ->InternalizeExternalString<ExternalTwoByteString>(string_);
16808 }
16774 // Otherwise allocate a new internalized string. 16809 // Otherwise allocate a new internalized string.
16775 return isolate->factory()->NewInternalizedStringImpl( 16810 return isolate->factory()->NewInternalizedStringImpl(
16776 string_, string_->length(), string_->hash_field()); 16811 string_, string_->length(), string_->hash_field());
16777 } 16812 }
16778 16813
16779 static uint32_t StringHash(Object* obj) { 16814 static uint32_t StringHash(Object* obj) {
16780 return String::cast(obj)->Hash(); 16815 return String::cast(obj)->Hash();
16781 } 16816 }
16782 16817
16818 private:
16783 Handle<String> string_; 16819 Handle<String> string_;
16784 }; 16820 };
16785 16821
16786 16822
16787 template<typename Derived, typename Shape, typename Key> 16823 template<typename Derived, typename Shape, typename Key>
16788 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) { 16824 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
16789 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v); 16825 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
16790 } 16826 }
16791 16827
16792 16828
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after
17707 uint32_t hash_; 17743 uint32_t hash_;
17708 }; 17744 };
17709 17745
17710 17746
17711 MaybeHandle<String> StringTable::InternalizeStringIfExists( 17747 MaybeHandle<String> StringTable::InternalizeStringIfExists(
17712 Isolate* isolate, 17748 Isolate* isolate,
17713 Handle<String> string) { 17749 Handle<String> string) {
17714 if (string->IsInternalizedString()) { 17750 if (string->IsInternalizedString()) {
17715 return string; 17751 return string;
17716 } 17752 }
17753 if (string->IsThinString()) {
17754 return handle(Handle<ThinString>::cast(string)->actual(), isolate);
17755 }
17717 return LookupStringIfExists(isolate, string); 17756 return LookupStringIfExists(isolate, string);
17718 } 17757 }
17719 17758
17720 17759
17721 MaybeHandle<String> StringTable::LookupStringIfExists( 17760 MaybeHandle<String> StringTable::LookupStringIfExists(
17722 Isolate* isolate, 17761 Isolate* isolate,
17723 Handle<String> string) { 17762 Handle<String> string) {
17724 Handle<StringTable> string_table = isolate->factory()->string_table(); 17763 Handle<StringTable> string_table = isolate->factory()->string_table();
17725 InternalizedStringKey key(string); 17764 InternalizedStringKey key(string);
17726 int entry = string_table->FindEntry(&key); 17765 int entry = string_table->FindEntry(&key);
(...skipping 26 matching lines...) Expand all
17753 17792
17754 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, 17793 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
17755 int expected) { 17794 int expected) {
17756 Handle<StringTable> table = isolate->factory()->string_table(); 17795 Handle<StringTable> table = isolate->factory()->string_table();
17757 // We need a key instance for the virtual hash function. 17796 // We need a key instance for the virtual hash function.
17758 InternalizedStringKey dummy_key(isolate->factory()->empty_string()); 17797 InternalizedStringKey dummy_key(isolate->factory()->empty_string());
17759 table = StringTable::EnsureCapacity(table, expected, &dummy_key); 17798 table = StringTable::EnsureCapacity(table, expected, &dummy_key);
17760 isolate->heap()->SetRootStringTable(*table); 17799 isolate->heap()->SetRootStringTable(*table);
17761 } 17800 }
17762 17801
17802 namespace {
17803
17804 template <class StringClass>
17805 void MigrateExternalStringResource(Isolate* isolate, Handle<String> from,
17806 Handle<String> to) {
17807 Handle<StringClass> cast_from = Handle<StringClass>::cast(from);
17808 Handle<StringClass> cast_to = Handle<StringClass>::cast(to);
17809 const typename StringClass::Resource* to_resource = cast_to->resource();
17810 if (to_resource == nullptr) {
17811 // |to| is a just-created internalized copy of |from|. Migrate the resource.
17812 cast_to->set_resource(cast_from->resource());
17813 // Zap |from|'s resource pointer to reflect the fact that |from| has
17814 // relinquished ownership of its resource.
17815 cast_from->set_resource(nullptr);
17816 } else if (to_resource != cast_from->resource()) {
17817 // |to| already existed and has its own resource. Finalize |from|.
17818 isolate->heap()->FinalizeExternalString(*from);
17819 }
17820 }
17821
17822 } // namespace
17763 17823
17764 Handle<String> StringTable::LookupString(Isolate* isolate, 17824 Handle<String> StringTable::LookupString(Isolate* isolate,
17765 Handle<String> string) { 17825 Handle<String> string) {
17826 if (string->IsThinString()) {
17827 DCHECK(Handle<ThinString>::cast(string)->actual()->IsInternalizedString());
17828 return handle(Handle<ThinString>::cast(string)->actual(), isolate);
17829 }
17766 if (string->IsConsString() && string->IsFlat()) { 17830 if (string->IsConsString() && string->IsFlat()) {
17767 string = String::Flatten(string); 17831 string = handle(Handle<ConsString>::cast(string)->first(), isolate);
17768 if (string->IsInternalizedString()) return string; 17832 if (string->IsInternalizedString()) return string;
17769 } 17833 }
17770 17834
17771 InternalizedStringKey key(string); 17835 InternalizedStringKey key(string);
17772 Handle<String> result = LookupKey(isolate, &key); 17836 Handle<String> result = LookupKey(isolate, &key);
17773 17837
17774 if (string->IsConsString()) { 17838 if (string->IsExternalString()) {
17775 Handle<ConsString> cons = Handle<ConsString>::cast(string); 17839 if (result->IsExternalOneByteString()) {
17776 cons->set_first(*result); 17840 MigrateExternalStringResource<ExternalOneByteString>(isolate, string,
17777 cons->set_second(isolate->heap()->empty_string()); 17841 result);
17778 } else if (string->IsSlicedString()) { 17842 } else if (result->IsExternalTwoByteString()) {
17779 STATIC_ASSERT(ConsString::kSize == SlicedString::kSize); 17843 MigrateExternalStringResource<ExternalTwoByteString>(isolate, string,
17844 result);
17845 }
17846 }
17847
17848 // The LookupKey() call above tries to internalize the string in-place.
17849 // In cases where that wasn't possible (e.g. new-space strings), turn them
17850 // into ThinStrings referring to their internalized versions now.
17851 if (!string->IsInternalizedString()) {
17780 DisallowHeapAllocation no_gc; 17852 DisallowHeapAllocation no_gc;
17781 bool one_byte = result->IsOneByteRepresentation(); 17853 bool one_byte = result->IsOneByteRepresentation();
17782 Handle<Map> map = one_byte ? isolate->factory()->cons_one_byte_string_map() 17854 Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map()
17783 : isolate->factory()->cons_string_map(); 17855 : isolate->factory()->thin_string_map();
17784 string->set_map(*map); 17856 int old_size = string->Size();
17785 Handle<ConsString> cons = Handle<ConsString>::cast(string); 17857 DCHECK(old_size >= ThinString::kSize);
17786 cons->set_first(*result); 17858 string->synchronized_set_map(*map);
17787 cons->set_second(isolate->heap()->empty_string()); 17859 Handle<ThinString> thin = Handle<ThinString>::cast(string);
17860 thin->set_actual(*result);
17861 Address thin_end = thin->address() + ThinString::kSize;
17862 int size_delta = old_size - ThinString::kSize;
17863 Heap* heap = isolate->heap();
Igor Sheludko 2016/12/20 23:46:58 Maybe wrap below lines in "if (size_delta) {" to s
Jakob Kummerow 2017/01/04 12:45:06 Done.
17864 heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
17865 heap->AdjustLiveBytes(*thin, -size_delta);
17788 } 17866 }
17789 return result; 17867 return result;
17790 } 17868 }
17791 17869
17792 17870
17793 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) { 17871 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
17794 Handle<StringTable> table = isolate->factory()->string_table(); 17872 Handle<StringTable> table = isolate->factory()->string_table();
17795 int entry = table->FindEntry(key); 17873 int entry = table->FindEntry(key);
17796 17874
17797 // String already in table. 17875 // String already in table.
(...skipping 2648 matching lines...) Expand 10 before | Expand all | Expand 10 after
20446 // depend on this. 20524 // depend on this.
20447 return DICTIONARY_ELEMENTS; 20525 return DICTIONARY_ELEMENTS;
20448 } 20526 }
20449 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20527 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20450 return kind; 20528 return kind;
20451 } 20529 }
20452 } 20530 }
20453 20531
20454 } // namespace internal 20532 } // namespace internal
20455 } // namespace v8 20533 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698