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

Side by Side Diff: src/objects.cc

Issue 2626893005: Revert of Internalize strings in-place (Closed)
Patch Set: rebased Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-body-descriptors-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <memory> 9 #include <memory>
10 #include <sstream> 10 #include <sstream>
(...skipping 2496 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-body-descriptors-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698