| 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 2496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2507 resource->data(), | 2507 resource->data(), |
| 2508 resource->length() * sizeof(smart_chars[0])) == 0); | 2508 resource->length() * sizeof(smart_chars[0])) == 0); |
| 2509 } | 2509 } |
| 2510 #endif // DEBUG | 2510 #endif // DEBUG |
| 2511 int size = this->Size(); // Byte size of the original string. | 2511 int size = this->Size(); // Byte size of the original string. |
| 2512 // Abort if size does not allow in-place conversion. | 2512 // Abort if size does not allow in-place conversion. |
| 2513 if (size < ExternalString::kShortSize) return false; | 2513 if (size < ExternalString::kShortSize) return false; |
| 2514 Heap* heap = GetHeap(); | 2514 Heap* heap = GetHeap(); |
| 2515 bool is_one_byte = this->IsOneByteRepresentation(); | 2515 bool is_one_byte = this->IsOneByteRepresentation(); |
| 2516 bool is_internalized = this->IsInternalizedString(); | 2516 bool is_internalized = this->IsInternalizedString(); |
| 2517 bool has_pointers = StringShape(this).IsIndirect(); | 2517 bool has_pointers = this->IsConsString() || this->IsSlicedString(); |
| 2518 | 2518 |
| 2519 // Morph the string to an external string by replacing the map and | 2519 // Morph the string to an external string by replacing the map and |
| 2520 // reinitializing the fields. This won't work if the space the existing | 2520 // reinitializing the fields. This won't work if the space the existing |
| 2521 // string occupies is too small for a regular external string. | 2521 // string occupies is too small for a regular external string. |
| 2522 // Instead, we resort to a short external string instead, omitting | 2522 // Instead, we resort to a short external string instead, omitting |
| 2523 // the field caching the address of the backing store. When we encounter | 2523 // the field caching the address of the backing store. When we encounter |
| 2524 // short external strings in generated code, we need to bailout to runtime. | 2524 // short external strings in generated code, we need to bailout to runtime. |
| 2525 Map* new_map; | 2525 Map* new_map; |
| 2526 if (size < ExternalString::kSize) { | 2526 if (size < ExternalString::kSize) { |
| 2527 new_map = is_internalized | 2527 new_map = is_internalized |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2579 DCHECK(memcmp(smart_chars.start(), | 2579 DCHECK(memcmp(smart_chars.start(), |
| 2580 resource->data(), | 2580 resource->data(), |
| 2581 resource->length() * sizeof(smart_chars[0])) == 0); | 2581 resource->length() * sizeof(smart_chars[0])) == 0); |
| 2582 } | 2582 } |
| 2583 #endif // DEBUG | 2583 #endif // DEBUG |
| 2584 int size = this->Size(); // Byte size of the original string. | 2584 int size = this->Size(); // Byte size of the original string. |
| 2585 // Abort if size does not allow in-place conversion. | 2585 // Abort if size does not allow in-place conversion. |
| 2586 if (size < ExternalString::kShortSize) return false; | 2586 if (size < ExternalString::kShortSize) return false; |
| 2587 Heap* heap = GetHeap(); | 2587 Heap* heap = GetHeap(); |
| 2588 bool is_internalized = this->IsInternalizedString(); | 2588 bool is_internalized = this->IsInternalizedString(); |
| 2589 bool has_pointers = StringShape(this).IsIndirect(); | 2589 bool has_pointers = this->IsConsString() || this->IsSlicedString(); |
| 2590 | 2590 |
| 2591 // Morph the string to an external string by replacing the map and | 2591 // Morph the string to an external string by replacing the map and |
| 2592 // reinitializing the fields. This won't work if the space the existing | 2592 // reinitializing the fields. This won't work if the space the existing |
| 2593 // string occupies is too small for a regular external string. | 2593 // string occupies is too small for a regular external string. |
| 2594 // Instead, we resort to a short external string instead, omitting | 2594 // Instead, we resort to a short external string instead, omitting |
| 2595 // the field caching the address of the backing store. When we encounter | 2595 // the field caching the address of the backing store. When we encounter |
| 2596 // short external strings in generated code, we need to bailout to runtime. | 2596 // short external strings in generated code, we need to bailout to runtime. |
| 2597 Map* new_map; | 2597 Map* new_map; |
| 2598 if (size < ExternalString::kSize) { | 2598 if (size < ExternalString::kSize) { |
| 2599 new_map = is_internalized | 2599 new_map = is_internalized |
| (...skipping 7704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10304 while ( | 10304 while ( |
| 10305 right > left && | 10305 right > left && |
| 10306 unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) { | 10306 unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) { |
| 10307 right--; | 10307 right--; |
| 10308 } | 10308 } |
| 10309 } | 10309 } |
| 10310 | 10310 |
| 10311 return isolate->factory()->NewSubString(string, left, right); | 10311 return isolate->factory()->NewSubString(string, left, right); |
| 10312 } | 10312 } |
| 10313 | 10313 |
| 10314 bool String::LooksValid() { return GetIsolate()->heap()->Contains(this); } | 10314 bool String::LooksValid() { |
| 10315 if (!GetIsolate()->heap()->Contains(this)) return false; |
| 10316 return true; |
| 10317 } |
| 10315 | 10318 |
| 10316 // static | 10319 // static |
| 10317 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) { | 10320 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) { |
| 10318 if (name->IsString()) return Handle<String>::cast(name); | 10321 if (name->IsString()) return Handle<String>::cast(name); |
| 10319 // ES6 section 9.2.11 SetFunctionName, step 4. | 10322 // ES6 section 9.2.11 SetFunctionName, step 4. |
| 10320 Isolate* const isolate = name->GetIsolate(); | 10323 Isolate* const isolate = name->GetIsolate(); |
| 10321 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate); | 10324 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate); |
| 10322 if (description->IsUndefined(isolate)) { | 10325 if (description->IsUndefined(isolate)) { |
| 10323 return isolate->factory()->empty_string(); | 10326 return isolate->factory()->empty_string(); |
| 10324 } | 10327 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10438 StringShape shape(this); | 10441 StringShape shape(this); |
| 10439 String* string = this; | 10442 String* string = this; |
| 10440 int offset = 0; | 10443 int offset = 0; |
| 10441 if (shape.representation_tag() == kConsStringTag) { | 10444 if (shape.representation_tag() == kConsStringTag) { |
| 10442 ConsString* cons = ConsString::cast(string); | 10445 ConsString* cons = ConsString::cast(string); |
| 10443 if (cons->second()->length() != 0) { | 10446 if (cons->second()->length() != 0) { |
| 10444 return FlatContent(); | 10447 return FlatContent(); |
| 10445 } | 10448 } |
| 10446 string = cons->first(); | 10449 string = cons->first(); |
| 10447 shape = StringShape(string); | 10450 shape = StringShape(string); |
| 10448 } else if (shape.representation_tag() == kSlicedStringTag) { | 10451 } |
| 10452 if (shape.representation_tag() == kSlicedStringTag) { |
| 10449 SlicedString* slice = SlicedString::cast(string); | 10453 SlicedString* slice = SlicedString::cast(string); |
| 10450 offset = slice->offset(); | 10454 offset = slice->offset(); |
| 10451 string = slice->parent(); | 10455 string = slice->parent(); |
| 10452 shape = StringShape(string); | 10456 shape = StringShape(string); |
| 10453 DCHECK(shape.representation_tag() != kConsStringTag && | 10457 DCHECK(shape.representation_tag() != kConsStringTag && |
| 10454 shape.representation_tag() != kSlicedStringTag); | 10458 shape.representation_tag() != kSlicedStringTag); |
| 10455 } | 10459 } |
| 10456 if (shape.representation_tag() == kThinStringTag) { | |
| 10457 ThinString* thin = ThinString::cast(string); | |
| 10458 string = thin->actual(); | |
| 10459 shape = StringShape(string); | |
| 10460 DCHECK(!shape.IsCons()); | |
| 10461 DCHECK(!shape.IsSliced()); | |
| 10462 } | |
| 10463 if (shape.encoding_tag() == kOneByteStringTag) { | 10460 if (shape.encoding_tag() == kOneByteStringTag) { |
| 10464 const uint8_t* start; | 10461 const uint8_t* start; |
| 10465 if (shape.representation_tag() == kSeqStringTag) { | 10462 if (shape.representation_tag() == kSeqStringTag) { |
| 10466 start = SeqOneByteString::cast(string)->GetChars(); | 10463 start = SeqOneByteString::cast(string)->GetChars(); |
| 10467 } else { | 10464 } else { |
| 10468 start = ExternalOneByteString::cast(string)->GetChars(); | 10465 start = ExternalOneByteString::cast(string)->GetChars(); |
| 10469 } | 10466 } |
| 10470 return FlatContent(start + offset, length); | 10467 return FlatContent(start + offset, length); |
| 10471 } else { | 10468 } else { |
| 10472 DCHECK(shape.encoding_tag() == kTwoByteStringTag); | 10469 DCHECK(shape.encoding_tag() == kTwoByteStringTag); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10538 case kSeqStringTag: | 10535 case kSeqStringTag: |
| 10539 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); | 10536 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); |
| 10540 case kExternalStringTag: | 10537 case kExternalStringTag: |
| 10541 return ExternalTwoByteString::cast(this)-> | 10538 return ExternalTwoByteString::cast(this)-> |
| 10542 ExternalTwoByteStringGetData(start); | 10539 ExternalTwoByteStringGetData(start); |
| 10543 case kSlicedStringTag: { | 10540 case kSlicedStringTag: { |
| 10544 SlicedString* slice = SlicedString::cast(this); | 10541 SlicedString* slice = SlicedString::cast(this); |
| 10545 return slice->parent()->GetTwoByteData(start + slice->offset()); | 10542 return slice->parent()->GetTwoByteData(start + slice->offset()); |
| 10546 } | 10543 } |
| 10547 case kConsStringTag: | 10544 case kConsStringTag: |
| 10548 case kThinStringTag: | |
| 10549 UNREACHABLE(); | 10545 UNREACHABLE(); |
| 10550 return NULL; | 10546 return NULL; |
| 10551 } | 10547 } |
| 10552 UNREACHABLE(); | 10548 UNREACHABLE(); |
| 10553 return NULL; | 10549 return NULL; |
| 10554 } | 10550 } |
| 10555 | 10551 |
| 10556 | 10552 |
| 10557 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { | 10553 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { |
| 10558 return reinterpret_cast<uc16*>( | 10554 return reinterpret_cast<uc16*>( |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10805 } | 10801 } |
| 10806 } else { | 10802 } else { |
| 10807 return string->Get(index); | 10803 return string->Get(index); |
| 10808 } | 10804 } |
| 10809 } | 10805 } |
| 10810 | 10806 |
| 10811 UNREACHABLE(); | 10807 UNREACHABLE(); |
| 10812 return 0; | 10808 return 0; |
| 10813 } | 10809 } |
| 10814 | 10810 |
| 10815 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); } | |
| 10816 | 10811 |
| 10817 uint16_t SlicedString::SlicedStringGet(int index) { | 10812 uint16_t SlicedString::SlicedStringGet(int index) { |
| 10818 return parent()->Get(offset() + index); | 10813 return parent()->Get(offset() + index); |
| 10819 } | 10814 } |
| 10820 | 10815 |
| 10821 | 10816 |
| 10822 template <typename sinkchar> | 10817 template <typename sinkchar> |
| 10823 void String::WriteToFlat(String* src, | 10818 void String::WriteToFlat(String* src, |
| 10824 sinkchar* sink, | 10819 sinkchar* sink, |
| 10825 int f, | 10820 int f, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10900 } | 10895 } |
| 10901 break; | 10896 break; |
| 10902 } | 10897 } |
| 10903 case kOneByteStringTag | kSlicedStringTag: | 10898 case kOneByteStringTag | kSlicedStringTag: |
| 10904 case kTwoByteStringTag | kSlicedStringTag: { | 10899 case kTwoByteStringTag | kSlicedStringTag: { |
| 10905 SlicedString* slice = SlicedString::cast(source); | 10900 SlicedString* slice = SlicedString::cast(source); |
| 10906 unsigned offset = slice->offset(); | 10901 unsigned offset = slice->offset(); |
| 10907 WriteToFlat(slice->parent(), sink, from + offset, to + offset); | 10902 WriteToFlat(slice->parent(), sink, from + offset, to + offset); |
| 10908 return; | 10903 return; |
| 10909 } | 10904 } |
| 10910 case kOneByteStringTag | kThinStringTag: | |
| 10911 case kTwoByteStringTag | kThinStringTag: | |
| 10912 source = ThinString::cast(source)->actual(); | |
| 10913 break; | |
| 10914 } | 10905 } |
| 10915 } | 10906 } |
| 10916 } | 10907 } |
| 10917 | 10908 |
| 10918 | 10909 |
| 10919 | 10910 |
| 10920 template <typename SourceChar> | 10911 template <typename SourceChar> |
| 10921 static void CalculateLineEndsImpl(Isolate* isolate, | 10912 static void CalculateLineEndsImpl(Isolate* isolate, |
| 10922 List<int>* line_ends, | 10913 List<int>* line_ends, |
| 10923 Vector<const SourceChar> src, | 10914 Vector<const SourceChar> src, |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11125 }; | 11116 }; |
| 11126 | 11117 |
| 11127 | 11118 |
| 11128 bool String::SlowEquals(String* other) { | 11119 bool String::SlowEquals(String* other) { |
| 11129 DisallowHeapAllocation no_gc; | 11120 DisallowHeapAllocation no_gc; |
| 11130 // Fast check: negative check with lengths. | 11121 // Fast check: negative check with lengths. |
| 11131 int len = length(); | 11122 int len = length(); |
| 11132 if (len != other->length()) return false; | 11123 if (len != other->length()) return false; |
| 11133 if (len == 0) return true; | 11124 if (len == 0) return true; |
| 11134 | 11125 |
| 11135 // Fast check: if at least one ThinString is involved, dereference it/them | |
| 11136 // and restart. | |
| 11137 if (this->IsThinString() || other->IsThinString()) { | |
| 11138 if (other->IsThinString()) other = ThinString::cast(other)->actual(); | |
| 11139 if (this->IsThinString()) { | |
| 11140 return ThinString::cast(this)->actual()->Equals(other); | |
| 11141 } else { | |
| 11142 return this->Equals(other); | |
| 11143 } | |
| 11144 } | |
| 11145 | |
| 11146 // Fast check: if hash code is computed for both strings | 11126 // Fast check: if hash code is computed for both strings |
| 11147 // a fast negative check can be performed. | 11127 // a fast negative check can be performed. |
| 11148 if (HasHashCode() && other->HasHashCode()) { | 11128 if (HasHashCode() && other->HasHashCode()) { |
| 11149 #ifdef ENABLE_SLOW_DCHECKS | 11129 #ifdef ENABLE_SLOW_DCHECKS |
| 11150 if (FLAG_enable_slow_asserts) { | 11130 if (FLAG_enable_slow_asserts) { |
| 11151 if (Hash() != other->Hash()) { | 11131 if (Hash() != other->Hash()) { |
| 11152 bool found_difference = false; | 11132 bool found_difference = false; |
| 11153 for (int i = 0; i < len; i++) { | 11133 for (int i = 0; i < len; i++) { |
| 11154 if (Get(i) != other->Get(i)) { | 11134 if (Get(i) != other->Get(i)) { |
| 11155 found_difference = true; | 11135 found_difference = true; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 11177 return comparator.Equals(this, other); | 11157 return comparator.Equals(this, other); |
| 11178 } | 11158 } |
| 11179 | 11159 |
| 11180 | 11160 |
| 11181 bool String::SlowEquals(Handle<String> one, Handle<String> two) { | 11161 bool String::SlowEquals(Handle<String> one, Handle<String> two) { |
| 11182 // Fast check: negative check with lengths. | 11162 // Fast check: negative check with lengths. |
| 11183 int one_length = one->length(); | 11163 int one_length = one->length(); |
| 11184 if (one_length != two->length()) return false; | 11164 if (one_length != two->length()) return false; |
| 11185 if (one_length == 0) return true; | 11165 if (one_length == 0) return true; |
| 11186 | 11166 |
| 11187 // Fast check: if at least one ThinString is involved, dereference it/them | |
| 11188 // and restart. | |
| 11189 if (one->IsThinString() || two->IsThinString()) { | |
| 11190 if (one->IsThinString()) one = handle(ThinString::cast(*one)->actual()); | |
| 11191 if (two->IsThinString()) two = handle(ThinString::cast(*two)->actual()); | |
| 11192 return String::Equals(one, two); | |
| 11193 } | |
| 11194 | |
| 11195 // Fast check: if hash code is computed for both strings | 11167 // Fast check: if hash code is computed for both strings |
| 11196 // a fast negative check can be performed. | 11168 // a fast negative check can be performed. |
| 11197 if (one->HasHashCode() && two->HasHashCode()) { | 11169 if (one->HasHashCode() && two->HasHashCode()) { |
| 11198 #ifdef ENABLE_SLOW_DCHECKS | 11170 #ifdef ENABLE_SLOW_DCHECKS |
| 11199 if (FLAG_enable_slow_asserts) { | 11171 if (FLAG_enable_slow_asserts) { |
| 11200 if (one->Hash() != two->Hash()) { | 11172 if (one->Hash() != two->Hash()) { |
| 11201 bool found_difference = false; | 11173 bool found_difference = false; |
| 11202 for (int i = 0; i < one_length; i++) { | 11174 for (int i = 0; i < one_length; i++) { |
| 11203 if (one->Get(i) != two->Get(i)) { | 11175 if (one->Get(i) != two->Get(i)) { |
| 11204 found_difference = true; | 11176 found_difference = true; |
| (...skipping 5030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16235 Handle<Object> AsHandle(Isolate* isolate) override { | 16207 Handle<Object> AsHandle(Isolate* isolate) override { |
| 16236 // Internalize the string if possible. | 16208 // Internalize the string if possible. |
| 16237 MaybeHandle<Map> maybe_map = | 16209 MaybeHandle<Map> maybe_map = |
| 16238 isolate->factory()->InternalizedStringMapForString(string_); | 16210 isolate->factory()->InternalizedStringMapForString(string_); |
| 16239 Handle<Map> map; | 16211 Handle<Map> map; |
| 16240 if (maybe_map.ToHandle(&map)) { | 16212 if (maybe_map.ToHandle(&map)) { |
| 16241 string_->set_map_no_write_barrier(*map); | 16213 string_->set_map_no_write_barrier(*map); |
| 16242 DCHECK(string_->IsInternalizedString()); | 16214 DCHECK(string_->IsInternalizedString()); |
| 16243 return string_; | 16215 return string_; |
| 16244 } | 16216 } |
| 16245 // External strings get special treatment, to avoid copying their contents. | |
| 16246 if (string_->IsExternalOneByteString()) { | |
| 16247 return isolate->factory() | |
| 16248 ->InternalizeExternalString<ExternalOneByteString>(string_); | |
| 16249 } else if (string_->IsExternalTwoByteString()) { | |
| 16250 return isolate->factory() | |
| 16251 ->InternalizeExternalString<ExternalTwoByteString>(string_); | |
| 16252 } | |
| 16253 // Otherwise allocate a new internalized string. | 16217 // Otherwise allocate a new internalized string. |
| 16254 return isolate->factory()->NewInternalizedStringImpl( | 16218 return isolate->factory()->NewInternalizedStringImpl( |
| 16255 string_, string_->length(), string_->hash_field()); | 16219 string_, string_->length(), string_->hash_field()); |
| 16256 } | 16220 } |
| 16257 | 16221 |
| 16258 static uint32_t StringHash(Object* obj) { | 16222 static uint32_t StringHash(Object* obj) { |
| 16259 return String::cast(obj)->Hash(); | 16223 return String::cast(obj)->Hash(); |
| 16260 } | 16224 } |
| 16261 | 16225 |
| 16262 private: | |
| 16263 Handle<String> string_; | 16226 Handle<String> string_; |
| 16264 }; | 16227 }; |
| 16265 | 16228 |
| 16266 | 16229 |
| 16267 template<typename Derived, typename Shape, typename Key> | 16230 template<typename Derived, typename Shape, typename Key> |
| 16268 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) { | 16231 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) { |
| 16269 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v); | 16232 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v); |
| 16270 } | 16233 } |
| 16271 | 16234 |
| 16272 | 16235 |
| (...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17187 uint32_t hash_; | 17150 uint32_t hash_; |
| 17188 }; | 17151 }; |
| 17189 | 17152 |
| 17190 | 17153 |
| 17191 MaybeHandle<String> StringTable::InternalizeStringIfExists( | 17154 MaybeHandle<String> StringTable::InternalizeStringIfExists( |
| 17192 Isolate* isolate, | 17155 Isolate* isolate, |
| 17193 Handle<String> string) { | 17156 Handle<String> string) { |
| 17194 if (string->IsInternalizedString()) { | 17157 if (string->IsInternalizedString()) { |
| 17195 return string; | 17158 return string; |
| 17196 } | 17159 } |
| 17197 if (string->IsThinString()) { | |
| 17198 return handle(Handle<ThinString>::cast(string)->actual(), isolate); | |
| 17199 } | |
| 17200 return LookupStringIfExists(isolate, string); | 17160 return LookupStringIfExists(isolate, string); |
| 17201 } | 17161 } |
| 17202 | 17162 |
| 17203 | 17163 |
| 17204 MaybeHandle<String> StringTable::LookupStringIfExists( | 17164 MaybeHandle<String> StringTable::LookupStringIfExists( |
| 17205 Isolate* isolate, | 17165 Isolate* isolate, |
| 17206 Handle<String> string) { | 17166 Handle<String> string) { |
| 17207 Handle<StringTable> string_table = isolate->factory()->string_table(); | 17167 Handle<StringTable> string_table = isolate->factory()->string_table(); |
| 17208 InternalizedStringKey key(string); | 17168 InternalizedStringKey key(string); |
| 17209 int entry = string_table->FindEntry(&key); | 17169 int entry = string_table->FindEntry(&key); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 17236 | 17196 |
| 17237 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, | 17197 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, |
| 17238 int expected) { | 17198 int expected) { |
| 17239 Handle<StringTable> table = isolate->factory()->string_table(); | 17199 Handle<StringTable> table = isolate->factory()->string_table(); |
| 17240 // We need a key instance for the virtual hash function. | 17200 // We need a key instance for the virtual hash function. |
| 17241 InternalizedStringKey dummy_key(isolate->factory()->empty_string()); | 17201 InternalizedStringKey dummy_key(isolate->factory()->empty_string()); |
| 17242 table = StringTable::EnsureCapacity(table, expected, &dummy_key); | 17202 table = StringTable::EnsureCapacity(table, expected, &dummy_key); |
| 17243 isolate->heap()->SetRootStringTable(*table); | 17203 isolate->heap()->SetRootStringTable(*table); |
| 17244 } | 17204 } |
| 17245 | 17205 |
| 17246 namespace { | |
| 17247 | |
| 17248 template <class StringClass> | |
| 17249 void MigrateExternalStringResource(Isolate* isolate, Handle<String> from, | |
| 17250 Handle<String> to) { | |
| 17251 Handle<StringClass> cast_from = Handle<StringClass>::cast(from); | |
| 17252 Handle<StringClass> cast_to = Handle<StringClass>::cast(to); | |
| 17253 const typename StringClass::Resource* to_resource = cast_to->resource(); | |
| 17254 if (to_resource == nullptr) { | |
| 17255 // |to| is a just-created internalized copy of |from|. Migrate the resource. | |
| 17256 cast_to->set_resource(cast_from->resource()); | |
| 17257 // Zap |from|'s resource pointer to reflect the fact that |from| has | |
| 17258 // relinquished ownership of its resource. | |
| 17259 cast_from->set_resource(nullptr); | |
| 17260 } else if (to_resource != cast_from->resource()) { | |
| 17261 // |to| already existed and has its own resource. Finalize |from|. | |
| 17262 isolate->heap()->FinalizeExternalString(*from); | |
| 17263 } | |
| 17264 } | |
| 17265 | |
| 17266 } // namespace | |
| 17267 | 17206 |
| 17268 Handle<String> StringTable::LookupString(Isolate* isolate, | 17207 Handle<String> StringTable::LookupString(Isolate* isolate, |
| 17269 Handle<String> string) { | 17208 Handle<String> string) { |
| 17270 if (string->IsThinString()) { | |
| 17271 DCHECK(Handle<ThinString>::cast(string)->actual()->IsInternalizedString()); | |
| 17272 return handle(Handle<ThinString>::cast(string)->actual(), isolate); | |
| 17273 } | |
| 17274 if (string->IsConsString() && string->IsFlat()) { | 17209 if (string->IsConsString() && string->IsFlat()) { |
| 17275 string = handle(Handle<ConsString>::cast(string)->first(), isolate); | 17210 string = String::Flatten(string); |
| 17276 if (string->IsInternalizedString()) return string; | 17211 if (string->IsInternalizedString()) return string; |
| 17277 } | 17212 } |
| 17278 | 17213 |
| 17279 InternalizedStringKey key(string); | 17214 InternalizedStringKey key(string); |
| 17280 Handle<String> result = LookupKey(isolate, &key); | 17215 Handle<String> result = LookupKey(isolate, &key); |
| 17281 | 17216 |
| 17282 if (string->IsExternalString()) { | 17217 if (string->IsConsString()) { |
| 17283 if (result->IsExternalOneByteString()) { | 17218 Handle<ConsString> cons = Handle<ConsString>::cast(string); |
| 17284 MigrateExternalStringResource<ExternalOneByteString>(isolate, string, | 17219 cons->set_first(*result); |
| 17285 result); | 17220 cons->set_second(isolate->heap()->empty_string()); |
| 17286 } else if (result->IsExternalTwoByteString()) { | 17221 } else if (string->IsSlicedString()) { |
| 17287 MigrateExternalStringResource<ExternalTwoByteString>(isolate, string, | 17222 STATIC_ASSERT(ConsString::kSize == SlicedString::kSize); |
| 17288 result); | |
| 17289 } | |
| 17290 } | |
| 17291 | |
| 17292 // The LookupKey() call above tries to internalize the string in-place. | |
| 17293 // In cases where that wasn't possible (e.g. new-space strings), turn them | |
| 17294 // into ThinStrings referring to their internalized versions now. | |
| 17295 if (!string->IsInternalizedString()) { | |
| 17296 DisallowHeapAllocation no_gc; | 17223 DisallowHeapAllocation no_gc; |
| 17297 bool one_byte = result->IsOneByteRepresentation(); | 17224 bool one_byte = result->IsOneByteRepresentation(); |
| 17298 Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map() | 17225 Handle<Map> map = one_byte ? isolate->factory()->cons_one_byte_string_map() |
| 17299 : isolate->factory()->thin_string_map(); | 17226 : isolate->factory()->cons_string_map(); |
| 17300 int old_size = string->Size(); | 17227 string->set_map(*map); |
| 17301 DCHECK(old_size >= ThinString::kSize); | 17228 Handle<ConsString> cons = Handle<ConsString>::cast(string); |
| 17302 string->synchronized_set_map(*map); | 17229 cons->set_first(*result); |
| 17303 Handle<ThinString> thin = Handle<ThinString>::cast(string); | 17230 cons->set_second(isolate->heap()->empty_string()); |
| 17304 thin->set_actual(*result); | |
| 17305 Address thin_end = thin->address() + ThinString::kSize; | |
| 17306 int size_delta = old_size - ThinString::kSize; | |
| 17307 if (size_delta != 0) { | |
| 17308 Heap* heap = isolate->heap(); | |
| 17309 heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo); | |
| 17310 heap->AdjustLiveBytes(*thin, -size_delta); | |
| 17311 } | |
| 17312 } | 17231 } |
| 17313 return result; | 17232 return result; |
| 17314 } | 17233 } |
| 17315 | 17234 |
| 17316 | 17235 |
| 17317 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) { | 17236 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) { |
| 17318 Handle<StringTable> table = isolate->factory()->string_table(); | 17237 Handle<StringTable> table = isolate->factory()->string_table(); |
| 17319 int entry = table->FindEntry(key); | 17238 int entry = table->FindEntry(key); |
| 17320 | 17239 |
| 17321 // String already in table. | 17240 // String already in table. |
| (...skipping 2627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19949 // depend on this. | 19868 // depend on this. |
| 19950 return DICTIONARY_ELEMENTS; | 19869 return DICTIONARY_ELEMENTS; |
| 19951 } | 19870 } |
| 19952 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 19871 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 19953 return kind; | 19872 return kind; |
| 19954 } | 19873 } |
| 19955 } | 19874 } |
| 19956 | 19875 |
| 19957 } // namespace internal | 19876 } // namespace internal |
| 19958 } // namespace v8 | 19877 } // namespace v8 |
| OLD | NEW |