diff --git a/third_party/blink/renderer/platform/bindings/parkable_string.cc b/third_party/blink/renderer/platform/bindings/parkable_string.cc index dff2052575489..5b7bbb331d0c3 100644 --- a/third_party/blink/renderer/platform/bindings/parkable_string.cc +++ b/third_party/blink/renderer/platform/bindings/parkable_string.cc @@ -514,6 +514,12 @@ bool ParkableStringImpl::Park(ParkingMode mode) { // Making the string old to cancel parking if it is accessed/locked before // parking is complete. metadata_->age_ = Age::kOld; + LOG(ERROR) << "[POC] Park() len=" << string_.length() + << " lock_depth=" << metadata_->lock_depth_ << " refs=" + << (string_.IsNull() ? -1 + : (string_.Impl()->HasOneRef() ? 1 : 2)) + << " has_compressed=" << has_compressed_data() + << " CanParkNow=" << CanParkNow(); if (!CanParkNow()) return false; @@ -583,6 +589,11 @@ bool ParkableStringImpl::ParkInternal(ParkingMode mode) { void ParkableStringImpl::DiscardUncompressedData() { // Must unpoison the memory before releasing it. AsanUnpoisonString(string_); + LOG(ERROR) << "[POC] DiscardUncompressedData freeing StringImpl chars=" + << static_cast(string_.IsNull() || !string_.Is8Bit() + ? nullptr + : string_.Span8().data()) + << " len=" << (string_.IsNull() ? 0 : string_.length()); string_ = String(); metadata_->state_ = State::kParked; diff --git a/third_party/blink/renderer/platform/bindings/string_resource.h b/third_party/blink/renderer/platform/bindings/string_resource.h index 8e9188ff9a6b1..4ab55c182c0ea 100644 --- a/third_party/blink/renderer/platform/bindings/string_resource.h +++ b/third_party/blink/renderer/platform/bindings/string_resource.h @@ -7,7 +7,12 @@ #include "base/compiler_specific.h" #include "base/dcheck_is_on.h" +#include "base/functional/bind.h" +#include "base/logging.h" +#include "base/task/single_thread_task_runner.h" +#include "base/threading/platform_thread.h" #include "third_party/blink/renderer/platform/bindings/parkable_string.h" +#include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h" #include "third_party/blink/renderer/platform/bindings/v8_external_memory_accounter.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -300,7 +305,36 @@ class ParkableStringResource8 final : public StringResource8Base { size_t length() const override { return GetParkableString().length(); } const char* data() const override { - return GetParkableString().SpanChar().data(); + // ToString() acquires metadata_->lock_, calls MakeYoung()+Unpark(), then + // RELEASES the lock and returns a const String& whose backing buffer is + // returned here as a raw char*. lock_depth_ is never incremented. + const char* result = GetParkableString().SpanChar().data(); + if (!IsMainThread() && GetParkableString().may_be_parked()) { + // ---- POC race-widening instrumentation ---- + // In production the window between ParkableStringImpl::ToString() + // releasing metadata_->lock_ and the caller (V8 String::WriteToFlat + // -> CopyChars) consuming |result| is on the order of nanoseconds. + // We (a) widen it with a sleep and (b) deterministically schedule the + // production callback ParkableStringManager::OnMemoryPressure(CRITICAL) + // (== exactly what fires under real OS critical memory pressure) inside + // that window. That callback runs ParkAll(kCompress) -> Park() -> + // DiscardUncompressedData(), freeing the StringImpl whose chars + // |result| points into. + LOG(ERROR) << "[POC] ParkableStringResource8::data() on bg thread, " + << "ptr=" << static_cast(result) + << " may_be_parked=1 -- widening race window"; + base::SingleThreadTaskRunner::GetMainThreadDefault()->PostTask( + FROM_HERE, base::BindOnce([] { + LOG(ERROR) << "[POC] main-thread: invoking " + "ParkableStringManager::OnMemoryPressure(CRITICAL)"; + ParkableStringManager::Instance().OnMemoryPressure( + base::MEMORY_PRESSURE_LEVEL_CRITICAL); + })); + base::PlatformThread::Sleep(base::Seconds(3)); + LOG(ERROR) << "[POC] bg thread resuming, returning ptr=" + << static_cast(result); + } + return result; } }; diff --git a/v8/src/maglev/maglev-graph-builder.cc b/v8/src/maglev/maglev-graph-builder.cc index 81afa73b592..c77edc72639 100644 --- a/v8/src/maglev/maglev-graph-builder.cc +++ b/v8/src/maglev/maglev-graph-builder.cc @@ -2547,6 +2547,12 @@ ReduceResult MaglevGraphBuilder::BuildStringConcat(ValueNode* left, Handle left_string; Handle right_string; if (left_cst.ToHandle(&left_string) && right_cst.ToHandle(&right_string)) { + fprintf(stderr, + "[POC] Maglev BuildStringConcat const-folding: left(sliced=%d " + "ext=%d len=%d) right(len=%d) bg=%d\n", + IsSlicedString(*left_string), IsExternalString(*left_string), + left_string->length(), right_string->length(), + local_isolate()->is_main_thread() ? 0 : 1); Handle concatenated; if (compiler::utils::ConcatenateStrings(left_string, right_string, broker()) .ToHandle(&concatenated)) {