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 2313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |