Commit 442bd663 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[snapshot] Use ThinStrings instead of custom forwarding using the hashfield to...

[snapshot] Use ThinStrings instead of custom forwarding using the hashfield to deserialize internalized strings

This is necessary to be able to store the string length next to the hash field in the same 64bit word on 64bit architectures. Otherwise the forwarding pointer will overwrite the length breaking heap guarantees. ThinStrings already just do the right thing, so just use that instead.

Bug: v8:7065
Change-Id: I4922365e72421995cd11437cb91572ff56f8a9e8
Reviewed-on: https://chromium-review.googlesource.com/763231Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49352}
parent 68f1dcf9
......@@ -16748,6 +16748,9 @@ void MigrateExternalStringResource(Isolate* isolate, String* from, String* to) {
}
void MakeStringThin(String* string, String* internalized, Isolate* isolate) {
DCHECK_NE(string, internalized);
DCHECK(internalized->IsInternalizedString());
if (string->IsExternalString()) {
if (internalized->IsExternalOneByteString()) {
MigrateExternalStringResource<ExternalOneByteString>(isolate, string,
......@@ -16763,23 +16766,21 @@ void MakeStringThin(String* string, String* internalized, Isolate* isolate) {
}
}
if (!string->IsInternalizedString()) {
DisallowHeapAllocation no_gc;
int old_size = string->Size();
isolate->heap()->NotifyObjectLayoutChange(string, old_size, no_gc);
bool one_byte = internalized->IsOneByteRepresentation();
Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map()
: isolate->factory()->thin_string_map();
DCHECK_GE(old_size, ThinString::kSize);
string->synchronized_set_map(*map);
ThinString* thin = ThinString::cast(string);
thin->set_actual(internalized);
Address thin_end = thin->address() + ThinString::kSize;
int size_delta = old_size - ThinString::kSize;
if (size_delta != 0) {
Heap* heap = isolate->heap();
heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
}
DisallowHeapAllocation no_gc;
int old_size = string->Size();
isolate->heap()->NotifyObjectLayoutChange(string, old_size, no_gc);
bool one_byte = internalized->IsOneByteRepresentation();
Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map()
: isolate->factory()->thin_string_map();
DCHECK_GE(old_size, ThinString::kSize);
string->synchronized_set_map(*map);
ThinString* thin = ThinString::cast(string);
thin->set_actual(internalized);
Address thin_end = thin->address() + ThinString::kSize;
int size_delta = old_size - ThinString::kSize;
if (size_delta != 0) {
Heap* heap = isolate->heap();
heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
}
}
......@@ -16794,7 +16795,9 @@ Handle<String> StringTable::LookupString(Isolate* isolate,
Handle<String> result = LookupKey(isolate, &key);
if (FLAG_thin_strings) {
MakeStringThin(*string, *result, isolate);
if (!string->IsInternalizedString()) {
MakeStringThin(*string, *result, isolate);
}
} else { // !FLAG_thin_strings
if (string->IsConsString()) {
Handle<ConsString> cons = Handle<ConsString>::cast(string);
......@@ -16989,6 +16992,7 @@ Object* StringTable::LookupStringIfExists_NoAllocate(String* string) {
return Smi::FromInt(ResultSentinel::kUnsupported);
}
DCHECK(!string->IsInternalizedString());
int entry = table->FindEntry(isolate, &key, key.Hash());
if (entry != kNotFound) {
String* internalized = String::cast(table->KeyAt(entry));
......@@ -17002,11 +17006,16 @@ Object* StringTable::LookupStringIfExists_NoAllocate(String* string) {
return Smi::FromInt(ResultSentinel::kNotFound);
}
String* StringTable::LookupKeyIfExists(Isolate* isolate, StringTableKey* key) {
String* StringTable::ForwardStringIfExists(Isolate* isolate,
StringTableKey* key,
String* string) {
Handle<StringTable> table = isolate->factory()->string_table();
int entry = table->FindEntry(isolate, key);
if (entry != kNotFound) return String::cast(table->KeyAt(entry));
return nullptr;
if (entry == kNotFound) return nullptr;
String* canonical = String::cast(table->KeyAt(entry));
if (canonical != string) MakeStringThin(string, canonical, isolate);
return canonical;
}
Handle<StringSet> StringSet::New(Isolate* isolate) {
......
......@@ -666,30 +666,6 @@ bool String::AsArrayIndex(uint32_t* index) {
return SlowAsArrayIndex(index);
}
void String::SetForwardedInternalizedString(String* canonical) {
DCHECK(IsInternalizedString());
DCHECK(HasHashCode());
if (canonical == this) return; // No need to forward.
DCHECK(SlowEquals(canonical));
DCHECK(canonical->IsInternalizedString());
DCHECK(canonical->HasHashCode());
WRITE_FIELD(this, kHashFieldSlot, canonical);
// Setting the hash field to a tagged value sets the LSB, causing the hash
// code to be interpreted as uninitialized. We use this fact to recognize
// that we have a forwarded string.
DCHECK(!HasHashCode());
}
String* String::GetForwardedInternalizedString() {
DCHECK(IsInternalizedString());
if (HasHashCode()) return this;
String* canonical = String::cast(READ_FIELD(this, kHashFieldSlot));
DCHECK(canonical->IsInternalizedString());
DCHECK(SlowEquals(canonical));
DCHECK(canonical->HasHashCode());
return canonical;
}
String::SubStringRange::SubStringRange(String* string, int first, int length)
: string_(string),
first_(first),
......
......@@ -59,7 +59,8 @@ class StringTable : public HashTable<StringTable, StringTableShape> {
V8_EXPORT_PRIVATE static Handle<String> LookupString(Isolate* isolate,
Handle<String> key);
static Handle<String> LookupKey(Isolate* isolate, StringTableKey* key);
static String* LookupKeyIfExists(Isolate* isolate, StringTableKey* key);
static String* ForwardStringIfExists(Isolate* isolate, StringTableKey* key,
String* string);
// Looks up a string that is equal to the given string and returns
// string handle if it is found, or an empty handle otherwise.
......
......@@ -437,11 +437,6 @@ class String : public Name {
static Handle<FixedArray> CalculateLineEnds(Handle<String> string,
bool include_ending_line);
// Use the hash field to forward to the canonical internalized string
// when deserializing an internalized string.
inline void SetForwardedInternalizedString(String* string);
inline String* GetForwardedInternalizedString();
private:
friend class Name;
friend class StringTableInsertionKey;
......
......@@ -156,14 +156,13 @@ HeapObject* Deserializer<AllocatorT>::PostProcessNewObject(HeapObject* obj,
// Canonicalize the internalized string. If it already exists in the
// string table, set it to forward to the existing one.
StringTableInsertionKey key(string);
String* canonical = StringTable::LookupKeyIfExists(isolate_, &key);
if (canonical == nullptr) {
new_internalized_strings_.push_back(handle(string));
return string;
} else {
string->SetForwardedInternalizedString(canonical);
return canonical;
}
String* canonical =
StringTable::ForwardStringIfExists(isolate_, &key, string);
if (canonical != nullptr) return canonical;
new_internalized_strings_.push_back(handle(string));
return string;
}
} else if (obj->IsScript()) {
new_scripts_.push_back(handle(Script::cast(obj)));
......@@ -275,8 +274,8 @@ HeapObject* Deserializer<AllocatorT>::GetBackReferencedObject(int space) {
break;
}
if (deserializing_user_code() && obj->IsInternalizedString()) {
obj = String::cast(obj)->GetForwardedInternalizedString();
if (deserializing_user_code() && obj->IsThinString()) {
obj = ThinString::cast(obj)->actual();
}
hot_objects_.Add(obj);
......
......@@ -103,7 +103,7 @@ void ObjectDeserializer::CommitPostProcessedObjects() {
isolate(), static_cast<int>(new_internalized_strings().size()));
for (Handle<String> string : new_internalized_strings()) {
StringTableInsertionKey key(*string);
DCHECK_NULL(StringTable::LookupKeyIfExists(isolate(), &key));
DCHECK_NULL(StringTable::ForwardStringIfExists(isolate(), &key, *string));
StringTable::LookupKey(isolate(), &key);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment