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

Side by Side Diff: src/objects.cc

Issue 2624203002: Version 5.7.440.1 (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 }
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
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
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
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
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
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
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
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
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
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
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
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