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

Side by Side Diff: src/objects.cc

Issue 2627783006: Version 5.7.442.2 (cherry-pick) (Closed)
Patch Set: 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 2495 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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 }
10314 10317
10315 // static 10318 // static
10316 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) { 10319 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) {
10317 if (name->IsString()) return Handle<String>::cast(name); 10320 if (name->IsString()) return Handle<String>::cast(name);
10318 // ES6 section 9.2.11 SetFunctionName, step 4. 10321 // ES6 section 9.2.11 SetFunctionName, step 4.
10319 Isolate* const isolate = name->GetIsolate(); 10322 Isolate* const isolate = name->GetIsolate();
10320 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate); 10323 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
10321 if (description->IsUndefined(isolate)) { 10324 if (description->IsUndefined(isolate)) {
10322 return isolate->factory()->empty_string(); 10325 return isolate->factory()->empty_string();
10323 } 10326 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
10437 StringShape shape(this); 10440 StringShape shape(this);
10438 String* string = this; 10441 String* string = this;
10439 int offset = 0; 10442 int offset = 0;
10440 if (shape.representation_tag() == kConsStringTag) { 10443 if (shape.representation_tag() == kConsStringTag) {
10441 ConsString* cons = ConsString::cast(string); 10444 ConsString* cons = ConsString::cast(string);
10442 if (cons->second()->length() != 0) { 10445 if (cons->second()->length() != 0) {
10443 return FlatContent(); 10446 return FlatContent();
10444 } 10447 }
10445 string = cons->first(); 10448 string = cons->first();
10446 shape = StringShape(string); 10449 shape = StringShape(string);
10447 } else if (shape.representation_tag() == kSlicedStringTag) { 10450 }
10451 if (shape.representation_tag() == kSlicedStringTag) {
10448 SlicedString* slice = SlicedString::cast(string); 10452 SlicedString* slice = SlicedString::cast(string);
10449 offset = slice->offset(); 10453 offset = slice->offset();
10450 string = slice->parent(); 10454 string = slice->parent();
10451 shape = StringShape(string); 10455 shape = StringShape(string);
10452 DCHECK(shape.representation_tag() != kConsStringTag && 10456 DCHECK(shape.representation_tag() != kConsStringTag &&
10453 shape.representation_tag() != kSlicedStringTag); 10457 shape.representation_tag() != kSlicedStringTag);
10454 } 10458 }
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) { 10459 if (shape.encoding_tag() == kOneByteStringTag) {
10463 const uint8_t* start; 10460 const uint8_t* start;
10464 if (shape.representation_tag() == kSeqStringTag) { 10461 if (shape.representation_tag() == kSeqStringTag) {
10465 start = SeqOneByteString::cast(string)->GetChars(); 10462 start = SeqOneByteString::cast(string)->GetChars();
10466 } else { 10463 } else {
10467 start = ExternalOneByteString::cast(string)->GetChars(); 10464 start = ExternalOneByteString::cast(string)->GetChars();
10468 } 10465 }
10469 return FlatContent(start + offset, length); 10466 return FlatContent(start + offset, length);
10470 } else { 10467 } else {
10471 DCHECK(shape.encoding_tag() == kTwoByteStringTag); 10468 DCHECK(shape.encoding_tag() == kTwoByteStringTag);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
10537 case kSeqStringTag: 10534 case kSeqStringTag:
10538 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); 10535 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
10539 case kExternalStringTag: 10536 case kExternalStringTag:
10540 return ExternalTwoByteString::cast(this)-> 10537 return ExternalTwoByteString::cast(this)->
10541 ExternalTwoByteStringGetData(start); 10538 ExternalTwoByteStringGetData(start);
10542 case kSlicedStringTag: { 10539 case kSlicedStringTag: {
10543 SlicedString* slice = SlicedString::cast(this); 10540 SlicedString* slice = SlicedString::cast(this);
10544 return slice->parent()->GetTwoByteData(start + slice->offset()); 10541 return slice->parent()->GetTwoByteData(start + slice->offset());
10545 } 10542 }
10546 case kConsStringTag: 10543 case kConsStringTag:
10547 case kThinStringTag:
10548 UNREACHABLE(); 10544 UNREACHABLE();
10549 return NULL; 10545 return NULL;
10550 } 10546 }
10551 UNREACHABLE(); 10547 UNREACHABLE();
10552 return NULL; 10548 return NULL;
10553 } 10549 }
10554 10550
10555 10551
10556 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) { 10552 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
10557 return reinterpret_cast<uc16*>( 10553 return reinterpret_cast<uc16*>(
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
10804 } 10800 }
10805 } else { 10801 } else {
10806 return string->Get(index); 10802 return string->Get(index);
10807 } 10803 }
10808 } 10804 }
10809 10805
10810 UNREACHABLE(); 10806 UNREACHABLE();
10811 return 0; 10807 return 0;
10812 } 10808 }
10813 10809
10814 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); }
10815 10810
10816 uint16_t SlicedString::SlicedStringGet(int index) { 10811 uint16_t SlicedString::SlicedStringGet(int index) {
10817 return parent()->Get(offset() + index); 10812 return parent()->Get(offset() + index);
10818 } 10813 }
10819 10814
10820 10815
10821 template <typename sinkchar> 10816 template <typename sinkchar>
10822 void String::WriteToFlat(String* src, 10817 void String::WriteToFlat(String* src,
10823 sinkchar* sink, 10818 sinkchar* sink,
10824 int f, 10819 int f,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
10899 } 10894 }
10900 break; 10895 break;
10901 } 10896 }
10902 case kOneByteStringTag | kSlicedStringTag: 10897 case kOneByteStringTag | kSlicedStringTag:
10903 case kTwoByteStringTag | kSlicedStringTag: { 10898 case kTwoByteStringTag | kSlicedStringTag: {
10904 SlicedString* slice = SlicedString::cast(source); 10899 SlicedString* slice = SlicedString::cast(source);
10905 unsigned offset = slice->offset(); 10900 unsigned offset = slice->offset();
10906 WriteToFlat(slice->parent(), sink, from + offset, to + offset); 10901 WriteToFlat(slice->parent(), sink, from + offset, to + offset);
10907 return; 10902 return;
10908 } 10903 }
10909 case kOneByteStringTag | kThinStringTag:
10910 case kTwoByteStringTag | kThinStringTag:
10911 source = ThinString::cast(source)->actual();
10912 break;
10913 } 10904 }
10914 } 10905 }
10915 } 10906 }
10916 10907
10917 10908
10918 10909
10919 template <typename SourceChar> 10910 template <typename SourceChar>
10920 static void CalculateLineEndsImpl(Isolate* isolate, 10911 static void CalculateLineEndsImpl(Isolate* isolate,
10921 List<int>* line_ends, 10912 List<int>* line_ends,
10922 Vector<const SourceChar> src, 10913 Vector<const SourceChar> src,
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
11124 }; 11115 };
11125 11116
11126 11117
11127 bool String::SlowEquals(String* other) { 11118 bool String::SlowEquals(String* other) {
11128 DisallowHeapAllocation no_gc; 11119 DisallowHeapAllocation no_gc;
11129 // Fast check: negative check with lengths. 11120 // Fast check: negative check with lengths.
11130 int len = length(); 11121 int len = length();
11131 if (len != other->length()) return false; 11122 if (len != other->length()) return false;
11132 if (len == 0) return true; 11123 if (len == 0) return true;
11133 11124
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 11125 // Fast check: if hash code is computed for both strings
11146 // a fast negative check can be performed. 11126 // a fast negative check can be performed.
11147 if (HasHashCode() && other->HasHashCode()) { 11127 if (HasHashCode() && other->HasHashCode()) {
11148 #ifdef ENABLE_SLOW_DCHECKS 11128 #ifdef ENABLE_SLOW_DCHECKS
11149 if (FLAG_enable_slow_asserts) { 11129 if (FLAG_enable_slow_asserts) {
11150 if (Hash() != other->Hash()) { 11130 if (Hash() != other->Hash()) {
11151 bool found_difference = false; 11131 bool found_difference = false;
11152 for (int i = 0; i < len; i++) { 11132 for (int i = 0; i < len; i++) {
11153 if (Get(i) != other->Get(i)) { 11133 if (Get(i) != other->Get(i)) {
11154 found_difference = true; 11134 found_difference = true;
(...skipping 21 matching lines...) Expand all
11176 return comparator.Equals(this, other); 11156 return comparator.Equals(this, other);
11177 } 11157 }
11178 11158
11179 11159
11180 bool String::SlowEquals(Handle<String> one, Handle<String> two) { 11160 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
11181 // Fast check: negative check with lengths. 11161 // Fast check: negative check with lengths.
11182 int one_length = one->length(); 11162 int one_length = one->length();
11183 if (one_length != two->length()) return false; 11163 if (one_length != two->length()) return false;
11184 if (one_length == 0) return true; 11164 if (one_length == 0) return true;
11185 11165
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 11166 // Fast check: if hash code is computed for both strings
11195 // a fast negative check can be performed. 11167 // a fast negative check can be performed.
11196 if (one->HasHashCode() && two->HasHashCode()) { 11168 if (one->HasHashCode() && two->HasHashCode()) {
11197 #ifdef ENABLE_SLOW_DCHECKS 11169 #ifdef ENABLE_SLOW_DCHECKS
11198 if (FLAG_enable_slow_asserts) { 11170 if (FLAG_enable_slow_asserts) {
11199 if (one->Hash() != two->Hash()) { 11171 if (one->Hash() != two->Hash()) {
11200 bool found_difference = false; 11172 bool found_difference = false;
11201 for (int i = 0; i < one_length; i++) { 11173 for (int i = 0; i < one_length; i++) {
11202 if (one->Get(i) != two->Get(i)) { 11174 if (one->Get(i) != two->Get(i)) {
11203 found_difference = true; 11175 found_difference = true;
(...skipping 5035 matching lines...) Expand 10 before | Expand all | Expand 10 after
16239 Handle<Object> AsHandle(Isolate* isolate) override { 16211 Handle<Object> AsHandle(Isolate* isolate) override {
16240 // Internalize the string if possible. 16212 // Internalize the string if possible.
16241 MaybeHandle<Map> maybe_map = 16213 MaybeHandle<Map> maybe_map =
16242 isolate->factory()->InternalizedStringMapForString(string_); 16214 isolate->factory()->InternalizedStringMapForString(string_);
16243 Handle<Map> map; 16215 Handle<Map> map;
16244 if (maybe_map.ToHandle(&map)) { 16216 if (maybe_map.ToHandle(&map)) {
16245 string_->set_map_no_write_barrier(*map); 16217 string_->set_map_no_write_barrier(*map);
16246 DCHECK(string_->IsInternalizedString()); 16218 DCHECK(string_->IsInternalizedString());
16247 return string_; 16219 return string_;
16248 } 16220 }
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. 16221 // Otherwise allocate a new internalized string.
16258 return isolate->factory()->NewInternalizedStringImpl( 16222 return isolate->factory()->NewInternalizedStringImpl(
16259 string_, string_->length(), string_->hash_field()); 16223 string_, string_->length(), string_->hash_field());
16260 } 16224 }
16261 16225
16262 static uint32_t StringHash(Object* obj) { 16226 static uint32_t StringHash(Object* obj) {
16263 return String::cast(obj)->Hash(); 16227 return String::cast(obj)->Hash();
16264 } 16228 }
16265 16229
16266 private:
16267 Handle<String> string_; 16230 Handle<String> string_;
16268 }; 16231 };
16269 16232
16270 16233
16271 template<typename Derived, typename Shape, typename Key> 16234 template<typename Derived, typename Shape, typename Key>
16272 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) { 16235 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
16273 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v); 16236 BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
16274 } 16237 }
16275 16238
16276 16239
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after
17191 uint32_t hash_; 17154 uint32_t hash_;
17192 }; 17155 };
17193 17156
17194 17157
17195 MaybeHandle<String> StringTable::InternalizeStringIfExists( 17158 MaybeHandle<String> StringTable::InternalizeStringIfExists(
17196 Isolate* isolate, 17159 Isolate* isolate,
17197 Handle<String> string) { 17160 Handle<String> string) {
17198 if (string->IsInternalizedString()) { 17161 if (string->IsInternalizedString()) {
17199 return string; 17162 return string;
17200 } 17163 }
17201 if (string->IsThinString()) {
17202 return handle(Handle<ThinString>::cast(string)->actual(), isolate);
17203 }
17204 return LookupStringIfExists(isolate, string); 17164 return LookupStringIfExists(isolate, string);
17205 } 17165 }
17206 17166
17207 17167
17208 MaybeHandle<String> StringTable::LookupStringIfExists( 17168 MaybeHandle<String> StringTable::LookupStringIfExists(
17209 Isolate* isolate, 17169 Isolate* isolate,
17210 Handle<String> string) { 17170 Handle<String> string) {
17211 Handle<StringTable> string_table = isolate->factory()->string_table(); 17171 Handle<StringTable> string_table = isolate->factory()->string_table();
17212 InternalizedStringKey key(string); 17172 InternalizedStringKey key(string);
17213 int entry = string_table->FindEntry(&key); 17173 int entry = string_table->FindEntry(&key);
(...skipping 26 matching lines...) Expand all
17240 17200
17241 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, 17201 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
17242 int expected) { 17202 int expected) {
17243 Handle<StringTable> table = isolate->factory()->string_table(); 17203 Handle<StringTable> table = isolate->factory()->string_table();
17244 // We need a key instance for the virtual hash function. 17204 // We need a key instance for the virtual hash function.
17245 InternalizedStringKey dummy_key(isolate->factory()->empty_string()); 17205 InternalizedStringKey dummy_key(isolate->factory()->empty_string());
17246 table = StringTable::EnsureCapacity(table, expected, &dummy_key); 17206 table = StringTable::EnsureCapacity(table, expected, &dummy_key);
17247 isolate->heap()->SetRootStringTable(*table); 17207 isolate->heap()->SetRootStringTable(*table);
17248 } 17208 }
17249 17209
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 17210
17272 Handle<String> StringTable::LookupString(Isolate* isolate, 17211 Handle<String> StringTable::LookupString(Isolate* isolate,
17273 Handle<String> string) { 17212 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()) { 17213 if (string->IsConsString() && string->IsFlat()) {
17279 string = handle(Handle<ConsString>::cast(string)->first(), isolate); 17214 string = String::Flatten(string);
17280 if (string->IsInternalizedString()) return string; 17215 if (string->IsInternalizedString()) return string;
17281 } 17216 }
17282 17217
17283 InternalizedStringKey key(string); 17218 InternalizedStringKey key(string);
17284 Handle<String> result = LookupKey(isolate, &key); 17219 Handle<String> result = LookupKey(isolate, &key);
17285 17220
17286 if (string->IsExternalString()) { 17221 if (string->IsConsString()) {
17287 if (result->IsExternalOneByteString()) { 17222 Handle<ConsString> cons = Handle<ConsString>::cast(string);
17288 MigrateExternalStringResource<ExternalOneByteString>(isolate, string, 17223 cons->set_first(*result);
17289 result); 17224 cons->set_second(isolate->heap()->empty_string());
17290 } else if (result->IsExternalTwoByteString()) { 17225 } else if (string->IsSlicedString()) {
17291 MigrateExternalStringResource<ExternalTwoByteString>(isolate, string, 17226 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; 17227 DisallowHeapAllocation no_gc;
17301 bool one_byte = result->IsOneByteRepresentation(); 17228 bool one_byte = result->IsOneByteRepresentation();
17302 Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map() 17229 Handle<Map> map = one_byte ? isolate->factory()->cons_one_byte_string_map()
17303 : isolate->factory()->thin_string_map(); 17230 : isolate->factory()->cons_string_map();
17304 int old_size = string->Size(); 17231 string->set_map(*map);
17305 DCHECK(old_size >= ThinString::kSize); 17232 Handle<ConsString> cons = Handle<ConsString>::cast(string);
17306 string->synchronized_set_map(*map); 17233 cons->set_first(*result);
17307 Handle<ThinString> thin = Handle<ThinString>::cast(string); 17234 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 } 17235 }
17317 return result; 17236 return result;
17318 } 17237 }
17319 17238
17320 17239
17321 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) { 17240 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
17322 Handle<StringTable> table = isolate->factory()->string_table(); 17241 Handle<StringTable> table = isolate->factory()->string_table();
17323 int entry = table->FindEntry(key); 17242 int entry = table->FindEntry(key);
17324 17243
17325 // String already in table. 17244 // String already in table.
(...skipping 2627 matching lines...) Expand 10 before | Expand all | Expand 10 after
19953 // depend on this. 19872 // depend on this.
19954 return DICTIONARY_ELEMENTS; 19873 return DICTIONARY_ELEMENTS;
19955 } 19874 }
19956 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 19875 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
19957 return kind; 19876 return kind;
19958 } 19877 }
19959 } 19878 }
19960 19879
19961 } // namespace internal 19880 } // namespace internal
19962 } // namespace v8 19881 } // 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