diff options
author | Michaël Zasso <targos@protonmail.com> | 2021-02-11 19:03:35 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2021-02-11 19:09:18 +0100 |
commit | c7b329225126ad3b9eeb2408e0f0801f1aea5eb1 (patch) | |
tree | 193c193111d5f302031ad345bc94d17a3f67bf66 /deps/v8/src/objects/string.cc | |
parent | 6ea9af9906cd74ed07ca05cf6aa44382025a6044 (diff) | |
download | node-new-c7b329225126ad3b9eeb2408e0f0801f1aea5eb1.tar.gz |
deps: update V8 to 8.8.278.17
PR-URL: https://github.com/nodejs/node/pull/36139
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Shelley Vohr <codebytere@gmail.com>
Diffstat (limited to 'deps/v8/src/objects/string.cc')
-rw-r--r-- | deps/v8/src/objects/string.cc | 83 |
1 files changed, 51 insertions, 32 deletions
diff --git a/deps/v8/src/objects/string.cc b/deps/v8/src/objects/string.cc index c450485a1b..4c023f9801 100644 --- a/deps/v8/src/objects/string.cc +++ b/deps/v8/src/objects/string.cc @@ -6,6 +6,7 @@ #include "src/common/assert-scope.h" #include "src/common/globals.h" +#include "src/execution/thread-id.h" #include "src/handles/handles-inl.h" #include "src/heap/heap-inl.h" #include "src/heap/memory-chunk.h" @@ -117,17 +118,16 @@ void String::MakeThin(Isolate* isolate, String internalized) { bool has_pointers = StringShape(*this).IsIndirect(); int old_size = this->Size(); - // Slot invalidation is not necessary here: ThinString only stores tagged - // value, so it can't store an untagged value in a recorded slot. - isolate->heap()->NotifyObjectLayoutChange(*this, no_gc, - InvalidateRecordedSlots::kNo); bool one_byte = internalized.IsOneByteRepresentation(); Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map() : isolate->factory()->thin_string_map(); + // Update actual first and then do release store on the map word. This ensures + // that the concurrent marker will read the pointer when visiting a + // ThinString. + ThinString thin = ThinString::unchecked_cast(*this); + thin.set_actual(internalized); DCHECK_GE(old_size, ThinString::kSize); this->synchronized_set_map(*map); - ThinString thin = ThinString::cast(*this); - thin.set_actual(internalized); Address thin_end = thin.address() + ThinString::kSize; int size_delta = old_size - ThinString::kSize; if (size_delta != 0) { @@ -168,6 +168,11 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) { isolate->heap()->NotifyObjectLayoutChange(*this, no_allocation, InvalidateRecordedSlots::kYes); } + + // Disallow garbage collection to avoid possible GC vs string access deadlock. + DisallowGarbageCollection no_gc; + base::SharedMutexGuard<base::kExclusive> shared_mutex_guard( + isolate->string_access()); // Morph the string to an external string by replacing the map and // reinitializing the fields. This won't work if the space the existing // string occupies is too small for a regular external string. Instead, we @@ -198,6 +203,7 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) { this->synchronized_set_map(new_map); ExternalTwoByteString self = ExternalTwoByteString::cast(*this); + self.AllocateExternalPointerEntries(isolate); self.SetResource(isolate, resource); isolate->heap()->RegisterExternalString(*this); if (is_internalized) self.Hash(); // Force regeneration of the hash value. @@ -239,6 +245,11 @@ bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) { isolate->heap()->NotifyObjectLayoutChange(*this, no_allocation, InvalidateRecordedSlots::kYes); } + + // Disallow garbage collection to avoid possible GC vs string access deadlock. + DisallowGarbageCollection no_gc; + base::SharedMutexGuard<base::kExclusive> shared_mutex_guard( + isolate->string_access()); // Morph the string to an external string by replacing the map and // reinitializing the fields. This won't work if the space the existing // string occupies is too small for a regular external string. Instead, we @@ -268,6 +279,7 @@ bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) { this->synchronized_set_map(new_map); ExternalOneByteString self = ExternalOneByteString::cast(*this); + self.AllocateExternalPointerEntries(isolate); self.SetResource(isolate, resource); isolate->heap()->RegisterExternalString(*this); if (is_internalized) self.Hash(); // Force regeneration of the hash value. @@ -519,6 +531,15 @@ Handle<Object> String::ToNumber(Isolate* isolate, Handle<String> subject) { String::FlatContent String::GetFlatContent( const DisallowHeapAllocation& no_gc) { +#if DEBUG + // Check that this method is called only from the main thread. + { + Isolate* isolate; + // We don't have to check read only strings as those won't move. + DCHECK_IMPLIES(GetIsolateFromHeapObject(*this, &isolate), + ThreadId::Current() == isolate->thread_id()); + } +#endif USE(no_gc); int length = this->length(); StringShape shape(*this); @@ -527,7 +548,7 @@ String::FlatContent String::GetFlatContent( if (shape.representation_tag() == kConsStringTag) { ConsString cons = ConsString::cast(string); if (cons.second().length() != 0) { - return FlatContent(); + return FlatContent(no_gc); } string = cons.first(); shape = StringShape(string); @@ -553,7 +574,7 @@ String::FlatContent String::GetFlatContent( } else { start = ExternalOneByteString::cast(string).GetChars(); } - return FlatContent(start + offset, length); + return FlatContent(start + offset, length, no_gc); } else { DCHECK_EQ(shape.encoding_tag(), kTwoByteStringTag); const uc16* start; @@ -562,7 +583,7 @@ String::FlatContent String::GetFlatContent( } else { start = ExternalTwoByteString::cast(string).GetChars(); } - return FlatContent(start + offset, length); + return FlatContent(start + offset, length, no_gc); } } @@ -618,11 +639,9 @@ std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls, } template <typename sinkchar> -void String::WriteToFlat(String src, sinkchar* sink, int f, int t) { +void String::WriteToFlat(String source, sinkchar* sink, int from, int to) { DisallowHeapAllocation no_gc; - String source = src; - int from = f; - int to = t; + SharedStringAccessGuardIfNeeded access_guard(source); while (from < to) { DCHECK_LE(0, from); DCHECK_LE(to, source.length()); @@ -638,13 +657,17 @@ void String::WriteToFlat(String src, sinkchar* sink, int f, int t) { return; } case kOneByteStringTag | kSeqStringTag: { - CopyChars(sink, SeqOneByteString::cast(source).GetChars(no_gc) + from, - to - from); + CopyChars( + sink, + SeqOneByteString::cast(source).GetChars(no_gc, access_guard) + from, + to - from); return; } case kTwoByteStringTag | kSeqStringTag: { - CopyChars(sink, SeqTwoByteString::cast(source).GetChars(no_gc) + from, - to - from); + CopyChars( + sink, + SeqTwoByteString::cast(source).GetChars(no_gc, access_guard) + from, + to - from); return; } case kOneByteStringTag | kConsStringTag: @@ -677,9 +700,10 @@ void String::WriteToFlat(String src, sinkchar* sink, int f, int t) { if (to - boundary == 1) { sink[boundary - from] = static_cast<sinkchar>(second.Get(0)); } else if (second.IsSeqOneByteString()) { - CopyChars(sink + boundary - from, - SeqOneByteString::cast(second).GetChars(no_gc), - to - boundary); + CopyChars( + sink + boundary - from, + SeqOneByteString::cast(second).GetChars(no_gc, access_guard), + to - boundary); } else { WriteToFlat(second, sink + boundary - from, 0, to - boundary); } @@ -1510,24 +1534,19 @@ int ExternalString::ExternalPayloadSize() const { } FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str) - : Relocatable(isolate), str_(str.location()), length_(str->length()) { + : Relocatable(isolate), str_(str), length_(str->length()) { +#if DEBUG + // Check that this constructor is called only from the main thread. + DCHECK_EQ(ThreadId::Current(), isolate->thread_id()); +#endif PostGarbageCollection(); } -FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input) - : Relocatable(isolate), - str_(nullptr), - is_one_byte_(true), - length_(input.length()), - start_(input.begin()) {} - void FlatStringReader::PostGarbageCollection() { - if (str_ == nullptr) return; - Handle<String> str(str_); - DCHECK(str->IsFlat()); + DCHECK(str_->IsFlat()); DisallowHeapAllocation no_gc; // This does not actually prevent the vector from being relocated later. - String::FlatContent content = str->GetFlatContent(no_gc); + String::FlatContent content = str_->GetFlatContent(no_gc); DCHECK(content.IsFlat()); is_one_byte_ = content.IsOneByte(); if (is_one_byte_) { |