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