Commit 2c4c2ad6 authored by Rodrigo Bruno's avatar Rodrigo Bruno Committed by Commit Bot

Avoiding re-externalization of strings.

Bug: chromium:845409
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I75bddcf0e8879d2161486f24d1cd4e46d8fe008d
Reviewed-on: https://chromium-review.googlesource.com/1139056
Commit-Queue: Rodrigo Bruno <rfbpb@google.com>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54599}
parent d20883f4
...@@ -3048,6 +3048,12 @@ class V8_EXPORT String : public Name { ...@@ -3048,6 +3048,12 @@ class V8_EXPORT String : public Name {
void VerifyExternalStringResourceBase(ExternalStringResourceBase* v, void VerifyExternalStringResourceBase(ExternalStringResourceBase* v,
Encoding encoding) const; Encoding encoding) const;
void VerifyExternalStringResource(ExternalStringResource* val) const; void VerifyExternalStringResource(ExternalStringResource* val) const;
ExternalStringResource* GetExternalStringResourceSlow() const;
ExternalStringResourceBase* GetExternalStringResourceBaseSlow(
String::Encoding* encoding_out) const;
const ExternalOneByteStringResource* GetExternalOneByteStringResourceSlow()
const;
static void CheckCast(v8::Value* obj); static void CheckCast(v8::Value* obj);
}; };
...@@ -10182,12 +10188,13 @@ String::ExternalStringResource* String::GetExternalStringResource() const { ...@@ -10182,12 +10188,13 @@ String::ExternalStringResource* String::GetExternalStringResource() const {
typedef internal::Object O; typedef internal::Object O;
typedef internal::Internals I; typedef internal::Internals I;
O* obj = *reinterpret_cast<O* const*>(this); O* obj = *reinterpret_cast<O* const*>(this);
String::ExternalStringResource* result;
ExternalStringResource* result;
if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) { if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
void* value = I::ReadField<void*>(obj, I::kStringResourceOffset); void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
result = reinterpret_cast<String::ExternalStringResource*>(value); result = reinterpret_cast<String::ExternalStringResource*>(value);
} else { } else {
result = NULL; result = GetExternalStringResourceSlow();
} }
#ifdef V8_ENABLE_CHECKS #ifdef V8_ENABLE_CHECKS
VerifyExternalStringResource(result); VerifyExternalStringResource(result);
...@@ -10203,14 +10210,16 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBase( ...@@ -10203,14 +10210,16 @@ String::ExternalStringResourceBase* String::GetExternalStringResourceBase(
O* obj = *reinterpret_cast<O* const*>(this); O* obj = *reinterpret_cast<O* const*>(this);
int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask; int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask;
*encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask); *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
ExternalStringResourceBase* resource = NULL; ExternalStringResourceBase* resource;
if (type == I::kExternalOneByteRepresentationTag || if (type == I::kExternalOneByteRepresentationTag ||
type == I::kExternalTwoByteRepresentationTag) { type == I::kExternalTwoByteRepresentationTag) {
void* value = I::ReadField<void*>(obj, I::kStringResourceOffset); void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
resource = static_cast<ExternalStringResourceBase*>(value); resource = static_cast<ExternalStringResourceBase*>(value);
} else {
resource = GetExternalStringResourceBaseSlow(encoding_out);
} }
#ifdef V8_ENABLE_CHECKS #ifdef V8_ENABLE_CHECKS
VerifyExternalStringResourceBase(resource, *encoding_out); VerifyExternalStringResourceBase(resource, *encoding_out);
#endif #endif
return resource; return resource;
} }
......
...@@ -5961,15 +5961,74 @@ void v8::String::VerifyExternalStringResourceBase( ...@@ -5961,15 +5961,74 @@ void v8::String::VerifyExternalStringResourceBase(
CHECK_EQ(expectedEncoding, encoding); CHECK_EQ(expectedEncoding, encoding);
} }
const v8::String::ExternalOneByteStringResource* String::ExternalStringResource* String::GetExternalStringResourceSlow() const {
v8::String::GetExternalOneByteStringResource() const { typedef internal::Internals I;
i::Handle<i::String> str = Utils::OpenHandle(this);
ExternalStringResource* result = nullptr;
internal::Object* obj;
if (str->IsThinString()) {
obj = i::Handle<i::ThinString>::cast(str)->actual();
} else {
obj = *str;
}
if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
result = reinterpret_cast<String::ExternalStringResource*>(value);
}
return result;
}
String::ExternalStringResourceBase* String::GetExternalStringResourceBaseSlow(
String::Encoding* encoding_out) const {
typedef internal::Internals I;
i::Handle<i::String> str = Utils::OpenHandle(this); i::Handle<i::String> str = Utils::OpenHandle(this);
ExternalStringResourceBase* resource = nullptr;
internal::Object* obj;
if (str->IsThinString()) {
obj = i::Handle<i::ThinString>::cast(str)->actual();
} else {
obj = *str;
}
int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask;
*encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
if (type == I::kExternalOneByteRepresentationTag ||
type == I::kExternalTwoByteRepresentationTag) {
void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
resource = static_cast<ExternalStringResourceBase*>(value);
}
return resource;
}
const String::ExternalOneByteStringResource*
String::GetExternalOneByteStringResourceSlow() const {
i::Handle<i::String> str = Utils::OpenHandle(this);
if (str->IsThinString()) {
i::MemoryChunk* chunk = i::MemoryChunk::FromHeapObject(*str);
str = i::Handle<i::String>(i::Handle<i::ThinString>::cast(str)->actual(),
chunk->heap()->isolate());
}
if (i::StringShape(*str).IsExternalOneByte()) { if (i::StringShape(*str).IsExternalOneByte()) {
const void* resource = const void* resource =
i::Handle<i::ExternalOneByteString>::cast(str)->resource(); i::Handle<i::ExternalOneByteString>::cast(str)->resource();
return reinterpret_cast<const ExternalOneByteStringResource*>(resource); return reinterpret_cast<const ExternalOneByteStringResource*>(resource);
}
return nullptr;
}
const v8::String::ExternalOneByteStringResource*
v8::String::GetExternalOneByteStringResource() const {
i::Handle<i::String> str = Utils::OpenHandle(this);
if (i::StringShape(*str).IsExternalOneByte()) {
const void* value =
i::Handle<i::ExternalOneByteString>::cast(str)->resource();
return reinterpret_cast<const ExternalOneByteStringResource*>(value);
} else { } else {
return nullptr; return GetExternalOneByteStringResourceSlow();
} }
} }
...@@ -6864,6 +6923,10 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { ...@@ -6864,6 +6923,10 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
return false; return false;
} }
if (obj->IsThinString()) {
obj = i::Handle<i::String>(i::ThinString::cast(*obj)->actual(), isolate);
}
if (i::StringShape(*obj).IsExternal()) { if (i::StringShape(*obj).IsExternal()) {
return false; // Already an external string. return false; // Already an external string.
} }
...@@ -6875,7 +6938,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { ...@@ -6875,7 +6938,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
bool result = obj->MakeExternal(resource); bool result = obj->MakeExternal(resource);
// Assert that if CanMakeExternal(), then externalizing actually succeeds. // Assert that if CanMakeExternal(), then externalizing actually succeeds.
DCHECK(!CanMakeExternal() || result); DCHECK(!Utils::ToLocal(obj)->CanMakeExternal() || result);
if (result) { if (result) {
DCHECK(obj->IsExternalString()); DCHECK(obj->IsExternalString());
} }
...@@ -6893,6 +6956,10 @@ bool v8::String::MakeExternal( ...@@ -6893,6 +6956,10 @@ bool v8::String::MakeExternal(
return false; return false;
} }
if (obj->IsThinString()) {
obj = i::Handle<i::String>(i::ThinString::cast(*obj)->actual(), isolate);
}
if (i::StringShape(*obj).IsExternal()) { if (i::StringShape(*obj).IsExternal()) {
return false; // Already an external string. return false; // Already an external string.
} }
...@@ -6904,7 +6971,7 @@ bool v8::String::MakeExternal( ...@@ -6904,7 +6971,7 @@ bool v8::String::MakeExternal(
bool result = obj->MakeExternal(resource); bool result = obj->MakeExternal(resource);
// Assert that if CanMakeExternal(), then externalizing actually succeeds. // Assert that if CanMakeExternal(), then externalizing actually succeeds.
DCHECK(!CanMakeExternal() || result); DCHECK(!Utils::ToLocal(obj)->CanMakeExternal() || result);
if (result) { if (result) {
DCHECK(obj->IsExternalString()); DCHECK(obj->IsExternalString());
} }
......
...@@ -530,6 +530,8 @@ Isolate* Heap::isolate() { ...@@ -530,6 +530,8 @@ Isolate* Heap::isolate() {
void Heap::ExternalStringTable::AddString(String* string) { void Heap::ExternalStringTable::AddString(String* string) {
DCHECK(string->IsExternalString()); DCHECK(string->IsExternalString());
DCHECK(!Contains(string));
if (InNewSpace(string)) { if (InNewSpace(string)) {
new_space_strings_.push_back(string); new_space_strings_.push_back(string);
} else { } else {
......
...@@ -2296,6 +2296,16 @@ void Heap::ProtectUnprotectedMemoryChunks() { ...@@ -2296,6 +2296,16 @@ void Heap::ProtectUnprotectedMemoryChunks() {
unprotected_memory_chunks_.clear(); unprotected_memory_chunks_.clear();
} }
bool Heap::ExternalStringTable::Contains(HeapObject* obj) {
for (size_t i = 0; i < new_space_strings_.size(); ++i) {
if (new_space_strings_[i] == obj) return true;
}
for (size_t i = 0; i < old_space_strings_.size(); ++i) {
if (old_space_strings_[i] == obj) return true;
}
return false;
}
String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
Object** p) { Object** p) {
MapWord first_word = HeapObject::cast(*p)->map_word(); MapWord first_word = HeapObject::cast(*p)->map_word();
......
...@@ -1481,6 +1481,7 @@ class Heap { ...@@ -1481,6 +1481,7 @@ class Heap {
// Registers an external string. // Registers an external string.
inline void AddString(String* string); inline void AddString(String* string);
bool Contains(HeapObject* obj);
void IterateAll(RootVisitor* v); void IterateAll(RootVisitor* v);
void IterateNewSpaceStrings(RootVisitor* v); void IterateNewSpaceStrings(RootVisitor* v);
......
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