File bad-font-gc2.patch of Package nodejs-electron

Chromium 123 was buggy, with tabs regularly hanging/crashing. The culprit
was the GC cleaning up font cache stuff, and deadlocking in a FontCacheKey
destructor:

Thread 54 (Thread 0x7fffc55fe6c0 (LWP 413811) "Chrome_InProcRe"):
#0  0x00007ffff6720719 in syscall () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x000055555c1752d9 in partition_alloc::internal::SpinningMutex::LockSlow() ()
#2  0x000055555c185529 in allocator_shim::internal::PartitionFree(allocator_shim::AllocatorDispatch const*, void*, void*) ()
#3  0x000055555f7db46b in blink::FontCacheKey::~FontCacheKey() ()
#4  0x000055555f7db6f4 in WTF::WeakProcessingHashTableHelper<(WTF::WeakHandlingFlag)1, blink::FontCacheKey, WTF::KeyValuePair<blink::FontCacheKey, cppgc::internal::BasicMember<blink::SegmentedFontData const, cppgc::internal::WeakMemberTag, cppgc::internal::DijkstraWriteBarrierPolicy, cppgc::internal::DisabledCheckingPolicy, cppgc::internal::CompressedPointer> >, WTF::KeyValuePairExtractor, WTF::HashMapValueTraits<WTF::HashTraits<blink::FontCacheKey>, WTF::HashTraits<cppgc::internal::BasicMember<blink::SegmentedFontData const, cppgc::internal::WeakMemberTag, cppgc::internal::DijkstraWriteBarrierPolicy, cppgc::internal::DisabledCheckingPolicy, cppgc::internal::CompressedPointer> > >, WTF::HashTraits<blink::FontCacheKey>, blink::HeapAllocator>::Process(cppgc::LivenessBroker const&, void const*) ()
#5  0x0000555559544bef in cppgc::internal::MarkerBase::ProcessWeakness() ()
#6  0x000055555954487e in cppgc::internal::MarkerBase::LeaveAtomicPause() ()
#7  0x0000555558e8115a in v8::internal::CppHeap::FinishMarkingAndStartSweeping() ()
#8  0x0000555558ebcdc0 in v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*) ()
#9  0x0000555558ecfe14 in v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)::$_0::operator()() const ()
#10 0x0000555558ecfb65 in void heap::base::Stack::SetMarkerAndCallbackImpl<v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)::$_0>(heap::base::Stack*, void*, void const*) ()
--Type <RET> for more, q to quit, c to continue without paging--
#11 0x000055555955216b in PushAllRegistersAndIterateStack ()
#12 0x0000555558eb8c19 in v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) ()
#13 0x0000555558eba3eb in v8::internal::Heap::FinalizeIncrementalMarkingAtomically(v8::internal::GarbageCollectionReason) ()
#14 0x0000555558ed20db in v8::internal::IncrementalMarkingJob::Task::RunInternal() ()
#15 0x000055555c0c49d6 in base::TaskAnnotator::RunTaskImpl(base::PendingTask&) ()
#16 0x000055555c0daf88 in base::sequence_manager::internal::ThreadControllerImpl::DoWork(base::sequence_manager::internal::ThreadControllerImpl::WorkType) ()
#17 0x000055555c0c49d6 in base::TaskAnnotator::RunTaskImpl(base::PendingTask&) ()
#18 0x000055555c0dd8f9 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::LazyNow*) ()
#19 0x000055555c0dd3bf in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() ()
#20 0x000055555c0ddd75 in non-virtual thunk to base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() ()
#21 0x000055555c07eb4f in base::MessagePumpDefault::Run(base::MessagePump::Delegate*) ()
#22 0x000055555c0de110 in base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) ()
#23 0x000055555c0a4c26 in base::RunLoop::Run(base::Location const&) ()
#24 0x000055555c100155 in base::Thread::Run(base::RunLoop*) ()
#25 0x000055555c100342 in base::Thread::ThreadMain() ()


The commit below modified font stuff to go from using scoped_refptrs to
getting cleaned up via GC. Reverting it fixes chromium's behavior for us.
It would be good to get a proper fix for this, but reverting this will
have to do for now.


commit bff9ec6754f7bf97c61d84663ee2ccc5055e9eb3
Author: Ian Kilpatrick <ikilpatrick@chromium.org>
Date:   Tue Feb 13 19:15:19 2024 +0000

    [gc] Make SimpleFontData & FontPlatformData & friends gc'd.
    
    The largest change is making the associated caches for these objects
    weak collections instead of relying on the relatively complex purging
    logic.
    
    https://variable-lizards.glitch.me/ appears not to leak.
    
    There should be no user-visible behaviour change.
    
    Bug: 41490008
    Change-Id: Iba581842459cf31f7f4fe60d83665f393a7d06a3
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5262982
    Reviewed-by: Caleb Raitto <caraitto@chromium.org>
    Reviewed-by: Dominik Röttsches <drott@chromium.org>
    Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#1259965}

--- a/third_party/blink/renderer/core/css/binary_data_font_face_source.cc
+++ b/third_party/blink/renderer/core/css/binary_data_font_face_source.cc
@@ -36,10 +36,10 @@ bool BinaryDataFontFaceSource::IsValid()
   return custom_platform_data_.get();
 }
 
-SimpleFontData* BinaryDataFontFaceSource::CreateFontData(
+scoped_refptr<SimpleFontData> BinaryDataFontFaceSource::CreateFontData(
     const FontDescription& font_description,
     const FontSelectionCapabilities& font_selection_capabilities) {
-  return MakeGarbageCollected<SimpleFontData>(
+  return SimpleFontData::Create(
       custom_platform_data_->GetFontPlatformData(
           font_description.EffectiveFontSize(),
           font_description.AdjustedSpecifiedSize(),
@@ -56,7 +56,7 @@ SimpleFontData* BinaryDataFontFaceSource
               : ResolvedFontFeatures(),
           font_description.Orientation(), font_description.VariationSettings(),
           font_description.GetFontPalette()),
-      MakeGarbageCollected<CustomFontData>());
+      CustomFontData::Create());
 }
 
 }  // namespace blink
--- a/third_party/blink/renderer/core/css/binary_data_font_face_source.h
+++ b/third_party/blink/renderer/core/css/binary_data_font_face_source.h
@@ -20,8 +20,9 @@ class BinaryDataFontFaceSource final : p
   bool IsValid() const override;
 
  private:
-  SimpleFontData* CreateFontData(const FontDescription&,
-                                 const FontSelectionCapabilities&) override;
+  scoped_refptr<SimpleFontData> CreateFontData(
+      const FontDescription&,
+      const FontSelectionCapabilities&) override;
 
   scoped_refptr<FontCustomPlatformData> custom_platform_data_;
 };
--- a/third_party/blink/renderer/core/css/css_custom_font_data.h
+++ b/third_party/blink/renderer/core/css/css_custom_font_data.h
@@ -31,18 +31,13 @@ class CSSCustomFontData final : public C
  public:
   enum FallbackVisibility { kInvisibleFallback, kVisibleFallback };
 
-  CSSCustomFontData(CSSFontFaceSource* source, FallbackVisibility visibility)
-      : font_face_source_(source), fallback_visibility_(visibility) {
-    if (source) {
-      is_loading_ = source->IsLoading();
-    }
+  static scoped_refptr<CSSCustomFontData> Create(
+      CSSFontFaceSource* source,
+      FallbackVisibility visibility) {
+    return base::AdoptRef(new CSSCustomFontData(source, visibility));
   }
-  ~CSSCustomFontData() override = default;
 
-  void Trace(Visitor* visitor) const override {
-    visitor->Trace(font_face_source_);
-    CustomFontData::Trace(visitor);
-  }
+  ~CSSCustomFontData() override = default;
 
   bool ShouldSkipDrawing() const override {
     if (font_face_source_) {
@@ -66,7 +61,16 @@ class CSSCustomFontData final : public C
   }
 
  private:
-  Member<CSSFontFaceSource> font_face_source_;
+  CSSCustomFontData(CSSFontFaceSource* source, FallbackVisibility visibility)
+      : font_face_source_(source), fallback_visibility_(visibility) {
+    if (source) {
+      is_loading_ = source->IsLoading();
+    }
+  }
+
+  // TODO(Oilpan): consider moving (Custom)FontFace hierarchy to the heap,
+  // thereby making this reference a Member<>.
+  WeakPersistent<CSSFontFaceSource> font_face_source_;
   FallbackVisibility fallback_visibility_;
   mutable bool is_loading_ = false;
 };
--- a/third_party/blink/renderer/core/css/css_font_face.cc
+++ b/third_party/blink/renderer/core/css/css_font_face.cc
@@ -114,7 +114,7 @@ bool CSSFontFace::FallbackVisibilityChan
   return true;
 }
 
-const SimpleFontData* CSSFontFace::GetFontData(
+scoped_refptr<SimpleFontData> CSSFontFace::GetFontData(
     const FontDescription& font_description) {
   if (!IsValid()) {
     return nullptr;
@@ -140,7 +140,7 @@ const SimpleFontData* CSSFontFace::GetFo
       return nullptr;
     }
 
-    if (const SimpleFontData* result =
+    if (scoped_refptr<SimpleFontData> result =
             source->GetFontData(size_adjusted_description,
                                 font_face_->GetFontSelectionCapabilities())) {
       // The font data here is created using the primary font's description.
@@ -149,7 +149,7 @@ const SimpleFontData* CSSFontFace::GetFo
       if (size_adjusted_description.HasSizeAdjust()) {
         if (auto adjusted_size =
                 FontSizeFunctions::MetricsMultiplierAdjustedFontSize(
-                    result, size_adjusted_description)) {
+                    result.get(), size_adjusted_description)) {
           size_adjusted_description.SetAdjustedSize(adjusted_size.value());
           result =
               source->GetFontData(size_adjusted_description,
--- a/third_party/blink/renderer/core/css/css_font_face.h
+++ b/third_party/blink/renderer/core/css/css_font_face.h
@@ -76,7 +76,7 @@ class CORE_EXPORT CSSFontFace final : pu
   bool FontLoaded(CSSFontFaceSource*);
   bool FallbackVisibilityChanged(RemoteFontFaceSource*);
 
-  const SimpleFontData* GetFontData(const FontDescription&);
+  scoped_refptr<SimpleFontData> GetFontData(const FontDescription&);
 
   FontFace::LoadStatusType LoadStatus() const {
     return font_face_->LoadStatus();
--- a/third_party/blink/renderer/core/css/css_font_face_source.cc
+++ b/third_party/blink/renderer/core/css/css_font_face_source.cc
@@ -31,11 +31,22 @@
 #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 
+namespace {
+// An excessive amount of SimpleFontData objects is generated from
+// CSSFontFaceSource if a lot of varying FontDescriptions point to a web
+// font. These FontDescriptions can vary in size, font-feature-settings or
+// font-variation settings. Well known cases are animations of font-variation
+// settings, compare crbug.com/778352. For a start, let's reduce this number to
+// 1024, which is still a large number and should have enough steps for font
+// animations from the same font face source, but avoids unbounded growth.
+const size_t kMaxCachedFontData = 1024;
+}  // namespace
+
 namespace blink {
 
 CSSFontFaceSource::~CSSFontFaceSource() = default;
 
-const SimpleFontData* CSSFontFaceSource::GetFontData(
+scoped_refptr<SimpleFontData> CSSFontFaceSource::GetFontData(
     const FontDescription& font_description,
     const FontSelectionCapabilities& font_selection_capabilities) {
   // If the font hasn't loaded or an error occurred, then we've got nothing.
@@ -53,12 +64,52 @@ const SimpleFontData* CSSFontFaceSource:
   FontCacheKey key =
       font_description.CacheKey(FontFaceCreationParams(), is_unique_match);
 
-  auto result = font_data_table_.insert(key, nullptr);
-  if (result.is_new_entry) {
-    result.stored_value->value =
-        CreateFontData(font_description, font_selection_capabilities);
+  // Get or create the font data. Take care to avoid dangling references into
+  // font_data_table_, because it is modified below during pruning.
+  scoped_refptr<SimpleFontData> font_data;
+  {
+    auto* it = font_data_table_.insert(key, nullptr).stored_value;
+    if (!it->value) {
+      it->value = CreateFontData(font_description, font_selection_capabilities);
+    }
+    font_data = it->value;
+  }
+
+  font_cache_key_age.PrependOrMoveToFirst(key);
+  PruneOldestIfNeeded();
+
+  DCHECK_LE(font_data_table_.size(), kMaxCachedFontData);
+  // No release, because fontData is a reference to a RefPtr that is held in the
+  // font_data_table_.
+  return font_data;
+}
+
+void CSSFontFaceSource::PruneOldestIfNeeded() {
+  if (font_cache_key_age.size() > kMaxCachedFontData) {
+    DCHECK_EQ(font_cache_key_age.size() - 1, kMaxCachedFontData);
+    const FontCacheKey& key = font_cache_key_age.back();
+    auto font_data_entry = font_data_table_.Take(key);
+    font_cache_key_age.pop_back();
+    DCHECK_EQ(font_cache_key_age.size(), kMaxCachedFontData);
+    if (font_data_entry && font_data_entry->GetCustomFontData()) {
+      font_data_entry->GetCustomFontData()->ClearFontFaceSource();
+    }
+  }
+}
+
+void CSSFontFaceSource::PruneTable() {
+  if (font_data_table_.empty()) {
+    return;
+  }
+
+  for (const auto& item : font_data_table_) {
+    SimpleFontData* font_data = item.value.get();
+    if (font_data && font_data->GetCustomFontData()) {
+      font_data->GetCustomFontData()->ClearFontFaceSource();
+    }
   }
-  return result.stored_value->value.Get();
+  font_cache_key_age.clear();
+  font_data_table_.clear();
 }
 
 }  // namespace blink
--- a/third_party/blink/renderer/core/css/css_font_face_source.h
+++ b/third_party/blink/renderer/core/css/css_font_face_source.h
@@ -30,9 +30,7 @@
 #include "third_party/blink/renderer/core/css/font_display.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
 #include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
@@ -71,8 +69,8 @@ class CORE_EXPORT CSSFontFaceSource
     return nullptr;
   }
 
-  const SimpleFontData* GetFontData(const FontDescription&,
-                                    const FontSelectionCapabilities&);
+  scoped_refptr<SimpleFontData> GetFontData(const FontDescription&,
+                                            const FontSelectionCapabilities&);
 
   // TODO(https://crbug.com/947461): IsLocalFontAvailable must not have a
   // FontDescription argument.
@@ -93,29 +91,28 @@ class CORE_EXPORT CSSFontFaceSource
   virtual bool HadBlankText() { return false; }
   virtual void PaintRequested() {}
 
-  virtual void Trace(Visitor* visitor) const {
-    visitor->Trace(font_data_table_);
-  }
+  virtual void Trace(Visitor* visitor) const {}
 
  protected:
   CSSFontFaceSource() = default;
-  virtual const SimpleFontData* CreateFontData(
+  virtual scoped_refptr<SimpleFontData> CreateFontData(
       const FontDescription&,
       const FontSelectionCapabilities&) = 0;
-
-  void ClearTable() { font_data_table_.clear(); }
+  void PruneTable();
 
   // Report the font lookup for metrics collection. Only used for local font
   // face sources currently.
   virtual void ReportFontLookup(const FontDescription& font_description,
-                                const SimpleFontData* font_data,
+                                SimpleFontData* font_data,
                                 bool is_loading_fallback = false) {}
 
  private:
-  using FontDataTable =
-      HeapHashMap<FontCacheKey, WeakMember<const SimpleFontData>>;
+  void PruneOldestIfNeeded();
+  using FontDataTable = HashMap<FontCacheKey, scoped_refptr<SimpleFontData>>;
+  using FontCacheKeyAgeList = LinkedHashSet<FontCacheKey>;
 
   FontDataTable font_data_table_;
+  FontCacheKeyAgeList font_cache_key_age;
 };
 
 }  // namespace blink
--- a/third_party/blink/renderer/core/css/css_font_selector.cc
+++ b/third_party/blink/renderer/core/css/css_font_selector.cc
@@ -162,7 +162,7 @@ void CSSFontSelector::FontCacheInvalidat
   DispatchInvalidationCallbacks(FontInvalidationReason::kGeneralInvalidation);
 }
 
-const FontData* CSSFontSelector::GetFontData(
+scoped_refptr<FontData> CSSFontSelector::GetFontData(
     const FontDescription& font_description,
     const FontFamily& font_family) {
   const auto& family_name = font_family.FamilyName();
@@ -252,13 +252,13 @@ const FontData* CSSFontSelector::GetFont
       family_name, request_description.GetScript(),
       request_description.GenericFamily(), settings_family_name);
 
-  const SimpleFontData* font_data =
+  scoped_refptr<SimpleFontData> font_data =
       FontCache::Get().GetFontData(request_description, settings_family_name);
   if (font_data && request_description.HasSizeAdjust()) {
     DCHECK(RuntimeEnabledFeatures::CSSFontSizeAdjustEnabled());
     if (auto adjusted_size =
             FontSizeFunctions::MetricsMultiplierAdjustedFontSize(
-                font_data, request_description)) {
+                font_data.get(), request_description)) {
       FontDescription size_adjusted_description(request_description);
       size_adjusted_description.SetAdjustedSize(adjusted_size.value());
       font_data = FontCache::Get().GetFontData(size_adjusted_description,
--- a/third_party/blink/renderer/core/css/css_font_selector.h
+++ b/third_party/blink/renderer/core/css/css_font_selector.h
@@ -49,8 +49,8 @@ class CORE_EXPORT CSSFontSelector : publ
 
   unsigned Version() const override { return font_face_cache_->Version(); }
 
-  const FontData* GetFontData(const FontDescription&,
-                              const FontFamily&) override;
+  scoped_refptr<FontData> GetFontData(const FontDescription&,
+                                      const FontFamily&) override;
 
   void FontFaceInvalidated(FontInvalidationReason) override;
 
--- a/third_party/blink/renderer/core/css/css_font_selector_base.cc
+++ b/third_party/blink/renderer/core/css/css_font_selector_base.cc
@@ -87,21 +87,21 @@ void CSSFontSelectorBase::ReportFailedLo
 void CSSFontSelectorBase::ReportFontLookupByUniqueOrFamilyName(
     const AtomicString& name,
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data) {
+    scoped_refptr<SimpleFontData> resulting_font_data) {
   if (FontMatchingMetrics* font_matching_metrics = GetFontMatchingMetrics()) {
     font_matching_metrics->ReportFontLookupByUniqueOrFamilyName(
-        name, font_description, resulting_font_data);
+        name, font_description, resulting_font_data.get());
   }
 }
 
 void CSSFontSelectorBase::ReportFontLookupByUniqueNameOnly(
     const AtomicString& name,
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data,
+    scoped_refptr<SimpleFontData> resulting_font_data,
     bool is_loading_fallback) {
   if (FontMatchingMetrics* font_matching_metrics = GetFontMatchingMetrics()) {
     font_matching_metrics->ReportFontLookupByUniqueNameOnly(
-        name, font_description, resulting_font_data, is_loading_fallback);
+        name, font_description, resulting_font_data.get(), is_loading_fallback);
   }
 }
 
@@ -109,20 +109,20 @@ void CSSFontSelectorBase::ReportFontLook
     UChar32 fallback_character,
     FontFallbackPriority fallback_priority,
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data) {
+    scoped_refptr<SimpleFontData> resulting_font_data) {
   if (FontMatchingMetrics* font_matching_metrics = GetFontMatchingMetrics()) {
     font_matching_metrics->ReportFontLookupByFallbackCharacter(
         fallback_character, fallback_priority, font_description,
-        resulting_font_data);
+        resulting_font_data.get());
   }
 }
 
 void CSSFontSelectorBase::ReportLastResortFallbackFontLookup(
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data) {
+    scoped_refptr<SimpleFontData> resulting_font_data) {
   if (FontMatchingMetrics* font_matching_metrics = GetFontMatchingMetrics()) {
     font_matching_metrics->ReportLastResortFallbackFontLookup(
-        font_description, resulting_font_data);
+        font_description, resulting_font_data.get());
   }
 }
 
--- a/third_party/blink/renderer/core/css/css_font_selector_base.h
+++ b/third_party/blink/renderer/core/css/css_font_selector_base.h
@@ -46,23 +46,23 @@ class CORE_EXPORT CSSFontSelectorBase :
   void ReportFontLookupByUniqueOrFamilyName(
       const AtomicString& name,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) override;
+      scoped_refptr<SimpleFontData> resulting_font_data) override;
 
   void ReportFontLookupByUniqueNameOnly(
       const AtomicString& name,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data,
+      scoped_refptr<SimpleFontData> resulting_font_data,
       bool is_loading_fallback = false) override;
 
   void ReportFontLookupByFallbackCharacter(
       UChar32 fallback_character,
       FontFallbackPriority fallback_priority,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) override;
+      scoped_refptr<SimpleFontData> resulting_font_data) override;
 
   void ReportLastResortFallbackFontLookup(
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) override;
+      scoped_refptr<SimpleFontData> resulting_font_data) override;
 
   void ReportFontFamilyLookupByGenericFamily(
       const AtomicString& generic_font_family_name,
--- a/third_party/blink/renderer/core/css/css_segmented_font_face.cc
+++ b/third_party/blink/renderer/core/css/css_segmented_font_face.cc
@@ -38,16 +38,42 @@
 #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 
+// See comment below in CSSSegmentedFontFace::GetFontData - the cache from
+// CSSSegmentedFontFace (which represents a group of @font-face declarations
+// with identical FontSelectionCapabilities but differing by unicode-range) to
+// FontData/SegmentedFontData, (i.e. the actual font blobs that can be used for
+// shaping and painting retrieved from a CSSFontFaceSource) is usually small
+// (less than a dozen, up to tens) for non-animation-cases, but grows fast to
+// thousands when animating variable font parameters. Set a limit until we start
+// dropping cache entries in animation scenarios.
+static constexpr size_t kFontDataTableMaxSize = 250;
+
 namespace blink {
 
+// static
+CSSSegmentedFontFace* CSSSegmentedFontFace::Create(
+    FontSelectionCapabilities capabilities) {
+  return MakeGarbageCollected<CSSSegmentedFontFace>(capabilities);
+}
+
 CSSSegmentedFontFace::CSSSegmentedFontFace(
     FontSelectionCapabilities font_selection_capabilities)
     : font_selection_capabilities_(font_selection_capabilities),
+      font_data_table_(kFontDataTableMaxSize),
       font_faces_(MakeGarbageCollected<FontFaceList>()),
       approximate_character_count_(0) {}
 
 CSSSegmentedFontFace::~CSSSegmentedFontFace() = default;
 
+void CSSSegmentedFontFace::PruneTable() {
+  // Make sure the glyph page tree prunes out all uses of this custom font.
+  if (!font_data_table_.size()) {
+    return;
+  }
+
+  font_data_table_.Clear();
+}
+
 bool CSSSegmentedFontFace::IsValid() const {
   // Valid if at least one font face is valid.
   return font_faces_->ForEachUntilTrue(
@@ -57,12 +83,12 @@ bool CSSSegmentedFontFace::IsValid() con
 }
 
 void CSSSegmentedFontFace::FontFaceInvalidated() {
-  font_data_table_.clear();
+  PruneTable();
 }
 
 void CSSSegmentedFontFace::AddFontFace(FontFace* font_face,
                                        bool css_connected) {
-  font_data_table_.clear();
+  PruneTable();
   font_face->CssFontFace()->AddSegmentedFontFace(this);
   font_faces_->Insert(font_face, css_connected);
 }
@@ -72,11 +98,11 @@ void CSSSegmentedFontFace::RemoveFontFac
     return;
   }
 
-  font_data_table_.clear();
+  PruneTable();
   font_face->CssFontFace()->RemoveSegmentedFontFace(this);
 }
 
-const FontData* CSSSegmentedFontFace::GetFontData(
+scoped_refptr<FontData> CSSSegmentedFontFace::GetFontData(
     const FontDescription& font_description) {
   if (!IsValid()) {
     return nullptr;
@@ -98,16 +124,16 @@ const FontData* CSSSegmentedFontFace::Ge
   // usually only a small number of FontData/SegmentedFontData instances created
   // per CSSSegmentedFontFace. Whereas in variable font animations, this number
   // grows rapidly.
-  auto it = font_data_table_.find(key);
+  auto it = font_data_table_.Get(key);
   if (it != font_data_table_.end()) {
-    const SegmentedFontData* cached_font_data = it->value.Get();
+    scoped_refptr<SegmentedFontData> cached_font_data = it->second;
     if (cached_font_data && cached_font_data->NumFaces()) {
       return cached_font_data;
     }
   }
 
-  SegmentedFontData* created_font_data =
-      MakeGarbageCollected<SegmentedFontData>();
+  scoped_refptr<SegmentedFontData> created_font_data =
+      SegmentedFontData::Create();
 
   FontDescription requested_font_description(font_description);
   const FontSelectionRequest& font_selection_request =
@@ -126,16 +152,26 @@ const FontData* CSSSegmentedFontFace::Ge
     if (!font_face->CssFontFace()->IsValid()) {
       return;
     }
-    if (const SimpleFontData* face_font_data =
+    if (scoped_refptr<SimpleFontData> face_font_data =
             font_face->CssFontFace()->GetFontData(requested_font_description)) {
       DCHECK(!face_font_data->IsSegmented());
-      created_font_data->AppendFace(MakeGarbageCollected<FontDataForRangeSet>(
-          std::move(face_font_data), font_face->CssFontFace()->Ranges()));
+      if (face_font_data->IsCustomFont()) {
+        created_font_data->AppendFace(base::AdoptRef(new FontDataForRangeSet(
+            std::move(face_font_data), font_face->CssFontFace()->Ranges())));
+      } else {
+        created_font_data->AppendFace(
+            base::AdoptRef(new FontDataForRangeSetFromCache(
+                std::move(face_font_data),
+                font_face->CssFontFace()->Ranges())));
+      }
     }
   });
 
   if (created_font_data->NumFaces()) {
-    font_data_table_.insert(std::move(key), created_font_data);
+    scoped_refptr<SegmentedFontData> put_to_cache(created_font_data);
+    font_data_table_.Put(std::move(key), std::move(put_to_cache));
+    // No release, we have a reference to an object in the cache which should
+    // retain the ref count it has.
     return created_font_data;
   }
 
@@ -186,7 +222,6 @@ void CSSSegmentedFontFace::Match(const S
 }
 
 void CSSSegmentedFontFace::Trace(Visitor* visitor) const {
-  visitor->Trace(font_data_table_);
   visitor->Trace(font_faces_);
 }
 
--- a/third_party/blink/renderer/core/css/css_segmented_font_face.h
+++ b/third_party/blink/renderer/core/css/css_segmented_font_face.h
@@ -32,7 +32,6 @@
 #include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
 #include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
 #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -84,6 +83,8 @@ class FontFaceList : public GarbageColle
 class CSSSegmentedFontFace final
     : public GarbageCollected<CSSSegmentedFontFace> {
  public:
+  static CSSSegmentedFontFace* Create(FontSelectionCapabilities);
+
   explicit CSSSegmentedFontFace(FontSelectionCapabilities);
   ~CSSSegmentedFontFace();
 
@@ -99,7 +100,7 @@ class CSSSegmentedFontFace final
   void RemoveFontFace(FontFace*);
   bool IsEmpty() const { return font_faces_->IsEmpty(); }
 
-  const FontData* GetFontData(const FontDescription&);
+  scoped_refptr<FontData> GetFontData(const FontDescription&);
 
   bool CheckFont(UChar32) const;
   void Match(const String&, HeapVector<Member<FontFace>>*) const;
@@ -112,11 +113,12 @@ class CSSSegmentedFontFace final
   void Trace(Visitor*) const;
 
  private:
+  void PruneTable();
   bool IsValid() const;
 
   FontSelectionCapabilities font_selection_capabilities_;
 
-  HeapHashMap<FontCacheKey, WeakMember<const SegmentedFontData>>
+  base::HashingLRUCache<FontCacheKey, scoped_refptr<SegmentedFontData>>
       font_data_table_;
 
   // All non-CSS-connected FontFaces are stored after the CSS-connected ones.
--- a/third_party/blink/renderer/core/css/font_face_cache.cc
+++ b/third_party/blink/renderer/core/css/font_face_cache.cc
@@ -85,8 +85,8 @@ void FontFaceCache::CapabilitiesSet::Add
   const auto result =
       map_.insert(font_face->GetFontSelectionCapabilities(), nullptr);
   if (result.is_new_entry) {
-    result.stored_value->value = MakeGarbageCollected<CSSSegmentedFontFace>(
-        font_face->GetFontSelectionCapabilities());
+    result.stored_value->value =
+        CSSSegmentedFontFace::Create(font_face->GetFontSelectionCapabilities());
   }
 
   result.stored_value->value->AddFontFace(font_face, css_connected);
--- a/third_party/blink/renderer/core/css/local_font_face_source.cc
+++ b/third_party/blink/renderer/core/css/local_font_face_source.cc
@@ -52,22 +52,23 @@ bool LocalFontFaceSource::IsLocalFontAva
   return font_available;
 }
 
-const SimpleFontData* LocalFontFaceSource::CreateLoadingFallbackFontData(
+scoped_refptr<SimpleFontData>
+LocalFontFaceSource::CreateLoadingFallbackFontData(
     const FontDescription& font_description) {
   FontCachePurgePreventer font_cache_purge_preventer;
-  const SimpleFontData* temporary_font =
-      FontCache::Get().GetLastResortFallbackFont(font_description);
+  scoped_refptr<SimpleFontData> temporary_font =
+      FontCache::Get().GetLastResortFallbackFont(font_description,
+                                                 kDoNotRetain);
   if (!temporary_font) {
     NOTREACHED();
     return nullptr;
   }
-  CSSCustomFontData* css_font_data = MakeGarbageCollected<CSSCustomFontData>(
-      this, CSSCustomFontData::kVisibleFallback);
-  return MakeGarbageCollected<SimpleFontData>(&temporary_font->PlatformData(),
-                                              css_font_data);
+  scoped_refptr<CSSCustomFontData> css_font_data =
+      CSSCustomFontData::Create(this, CSSCustomFontData::kVisibleFallback);
+  return SimpleFontData::Create(temporary_font->PlatformData(), css_font_data);
 }
 
-const SimpleFontData* LocalFontFaceSource::CreateFontData(
+scoped_refptr<SimpleFontData> LocalFontFaceSource::CreateFontData(
     const FontDescription& font_description,
     const FontSelectionCapabilities&) {
   if (!IsValid()) {
@@ -84,9 +85,9 @@ const SimpleFontData* LocalFontFaceSourc
   }
 
   if (IsValid() && IsLoading()) {
-    const SimpleFontData* fallback_font_data =
+    scoped_refptr<SimpleFontData> fallback_font_data =
         CreateLoadingFallbackFontData(font_description);
-    ReportFontLookup(font_description, fallback_font_data,
+    ReportFontLookup(font_description, fallback_font_data.get(),
                      true /* is_loading_fallback */);
     return fallback_font_data;
   }
@@ -110,10 +111,10 @@ const SimpleFontData* LocalFontFaceSourc
 #endif
   // TODO(https://crbug.com/1302264): Enable passing down of font-palette
   // information here (font_description.GetFontPalette()).
-  const SimpleFontData* font_data = FontCache::Get().GetFontData(
+  scoped_refptr<SimpleFontData> font_data = FontCache::Get().GetFontData(
       unstyled_description, font_name_, AlternateFontName::kLocalUniqueFace);
-  histograms_.Record(font_data);
-  ReportFontLookup(unstyled_description, font_data);
+  histograms_.Record(font_data.get());
+  ReportFontLookup(unstyled_description, font_data.get());
   return font_data;
 }
 
@@ -132,7 +133,7 @@ void LocalFontFaceSource::BeginLoadIfNee
 }
 
 void LocalFontFaceSource::NotifyFontUniqueNameLookupReady() {
-  ClearTable();
+  PruneTable();
 
   if (face_->FontLoaded(this)) {
     font_selector_->FontFaceInvalidated(
@@ -168,7 +169,7 @@ void LocalFontFaceSource::Trace(Visitor*
 
 void LocalFontFaceSource::ReportFontLookup(
     const FontDescription& font_description,
-    const SimpleFontData* font_data,
+    SimpleFontData* font_data,
     bool is_loading_fallback) {
   font_selector_->ReportFontLookupByUniqueNameOnly(
       font_name_, font_description, font_data, is_loading_fallback);
--- a/third_party/blink/renderer/core/css/local_font_face_source.h
+++ b/third_party/blink/renderer/core/css/local_font_face_source.h
@@ -48,15 +48,16 @@ class LocalFontFaceSource final : public
   void NotifyFontUniqueNameLookupReady();
 
  protected:
-  const SimpleFontData* CreateLoadingFallbackFontData(const FontDescription&);
+  scoped_refptr<SimpleFontData> CreateLoadingFallbackFontData(
+      const FontDescription&);
 
  private:
-  const SimpleFontData* CreateFontData(
+  scoped_refptr<SimpleFontData> CreateFontData(
       const FontDescription&,
       const FontSelectionCapabilities&) override;
 
   void ReportFontLookup(const FontDescription& font_description,
-                        const SimpleFontData* font_data,
+                        SimpleFontData* font_data,
                         bool is_loading_fallback = false) override;
 
   class LocalFontHistograms {
--- a/third_party/blink/renderer/core/css/offscreen_font_selector.cc
+++ b/third_party/blink/renderer/core/css/offscreen_font_selector.cc
@@ -39,7 +39,7 @@ void OffscreenFontSelector::RegisterForI
 void OffscreenFontSelector::UnregisterForInvalidationCallbacks(
     FontSelectorClient* client) {}
 
-const FontData* OffscreenFontSelector::GetFontData(
+scoped_refptr<FontData> OffscreenFontSelector::GetFontData(
     const FontDescription& font_description,
     const FontFamily& font_family) {
   const auto& family_name = font_family.FamilyName();
@@ -60,11 +60,11 @@ const FontData* OffscreenFontSelector::G
       family_name, font_description.GetScript(),
       font_description.GenericFamily(), settings_family_name);
 
-  const auto* font_data =
+  auto font_data =
       FontCache::Get().GetFontData(font_description, settings_family_name);
 
   ReportFontLookupByUniqueOrFamilyName(settings_family_name, font_description,
-                                       font_data);
+                                       font_data.get());
 
   return font_data;
 }
--- a/third_party/blink/renderer/core/css/offscreen_font_selector.h
+++ b/third_party/blink/renderer/core/css/offscreen_font_selector.h
@@ -26,8 +26,8 @@ class CORE_EXPORT OffscreenFontSelector
 
   unsigned Version() const override { return 1; }
 
-  const FontData* GetFontData(const FontDescription&,
-                              const FontFamily&) override;
+  scoped_refptr<FontData> GetFontData(const FontDescription&,
+                                      const FontFamily&) override;
 
   void RegisterForInvalidationCallbacks(FontSelectorClient*) override;
   void UnregisterForInvalidationCallbacks(FontSelectorClient*) override;
--- a/third_party/blink/renderer/core/css/remote_font_face_source.cc
+++ b/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -240,7 +240,8 @@ void RemoteFontFaceSource::NotifyFinishe
   }
 
   ClearResource();
-  ClearTable();
+
+  PruneTable();
 
   if (GetDocument()) {
     if (!GetDocument()->RenderingHasBegun()) {
@@ -305,7 +306,7 @@ bool RemoteFontFaceSource::UpdatePeriod(
   // Invalidate the font if its fallback visibility has changed.
   if (IsLoading() && period_ != new_period &&
       (period_ == kBlockPeriod || new_period == kBlockPeriod)) {
-    ClearTable();
+    PruneTable();
     if (face_->FallbackVisibilityChanged(this)) {
       font_selector_->FontFaceInvalidated(
           FontInvalidationReason::kGeneralInvalidation);
@@ -349,7 +350,7 @@ bool RemoteFontFaceSource::IsLowPriority
   return is_intervention_triggered_;
 }
 
-const SimpleFontData* RemoteFontFaceSource::CreateFontData(
+scoped_refptr<SimpleFontData> RemoteFontFaceSource::CreateFontData(
     const FontDescription& font_description,
     const FontSelectionCapabilities& font_selection_capabilities) {
   if (period_ == kFailurePeriod || !IsValid()) {
@@ -362,7 +363,7 @@ const SimpleFontData* RemoteFontFaceSour
 
   histograms_.RecordFallbackTime();
 
-  return MakeGarbageCollected<SimpleFontData>(
+  return SimpleFontData::Create(
       custom_font_data_->GetFontPlatformData(
           font_description.EffectiveFontSize(),
           font_description.AdjustedSpecifiedSize(),
@@ -379,24 +380,25 @@ const SimpleFontData* RemoteFontFaceSour
               : ResolvedFontFeatures(),
           font_description.Orientation(), font_description.VariationSettings(),
           font_description.GetFontPalette()),
-      MakeGarbageCollected<CustomFontData>());
+      CustomFontData::Create());
 }
 
-const SimpleFontData* RemoteFontFaceSource::CreateLoadingFallbackFontData(
+scoped_refptr<SimpleFontData>
+RemoteFontFaceSource::CreateLoadingFallbackFontData(
     const FontDescription& font_description) {
   // This temporary font is not retained and should not be returned.
   FontCachePurgePreventer font_cache_purge_preventer;
-  const SimpleFontData* temporary_font =
-      FontCache::Get().GetLastResortFallbackFont(font_description);
+  scoped_refptr<SimpleFontData> temporary_font =
+      FontCache::Get().GetLastResortFallbackFont(font_description,
+                                                 kDoNotRetain);
   if (!temporary_font) {
     DUMP_WILL_BE_NOTREACHED_NORETURN();
     return nullptr;
   }
-  CSSCustomFontData* css_font_data = MakeGarbageCollected<CSSCustomFontData>(
+  scoped_refptr<CSSCustomFontData> css_font_data = CSSCustomFontData::Create(
       this, period_ == kBlockPeriod ? CSSCustomFontData::kInvisibleFallback
                                     : CSSCustomFontData::kVisibleFallback);
-  return MakeGarbageCollected<SimpleFontData>(&temporary_font->PlatformData(),
-                                              css_font_data);
+  return SimpleFontData::Create(temporary_font->PlatformData(), css_font_data);
 }
 
 void RemoteFontFaceSource::BeginLoadIfNeeded() {
--- a/third_party/blink/renderer/core/css/remote_font_face_source.h
+++ b/third_party/blink/renderer/core/css/remote_font_face_source.h
@@ -66,10 +66,11 @@ class RemoteFontFaceSource final : publi
   void Trace(Visitor*) const override;
 
  protected:
-  const SimpleFontData* CreateFontData(
+  scoped_refptr<SimpleFontData> CreateFontData(
       const FontDescription&,
       const FontSelectionCapabilities&) override;
-  const SimpleFontData* CreateLoadingFallbackFontData(const FontDescription&);
+  scoped_refptr<SimpleFontData> CreateLoadingFallbackFontData(
+      const FontDescription&);
 
  private:
   // Periods of the Font Display Timeline.
--- a/third_party/blink/renderer/core/frame/font_matching_metrics.cc
+++ b/third_party/blink/renderer/core/frame/font_matching_metrics.cc
@@ -127,7 +127,7 @@ void FontMatchingMetrics::ReportLocalFon
 }
 
 void FontMatchingMetrics::InsertFontHashIntoMap(IdentifiableTokenKey input_key,
-                                                const SimpleFontData* font_data,
+                                                SimpleFontData* font_data,
                                                 TokenToTokenHashMap& hash_map) {
   DCHECK(IdentifiabilityStudyShouldSampleFonts());
   if (hash_map.Contains(input_key)) {
@@ -160,7 +160,7 @@ FontMatchingMetrics::GetTokenBuilderWith
 void FontMatchingMetrics::ReportFontLookupByUniqueOrFamilyName(
     const AtomicString& name,
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data) {
+    SimpleFontData* resulting_font_data) {
   Dactyloscoper::TraceFontLookup(
       execution_context_, name, font_description,
       Dactyloscoper::FontLookupType::kUniqueOrFamilyName);
@@ -184,7 +184,7 @@ void FontMatchingMetrics::ReportFontLook
 void FontMatchingMetrics::ReportFontLookupByUniqueNameOnly(
     const AtomicString& name,
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data,
+    SimpleFontData* resulting_font_data,
     bool is_loading_fallback) {
   // We ignore lookups that result in loading fallbacks for now as they should
   // only be temporary.
@@ -217,7 +217,7 @@ void FontMatchingMetrics::ReportFontLook
     UChar32 fallback_character,
     FontFallbackPriority fallback_priority,
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data) {
+    SimpleFontData* resulting_font_data) {
   if (!IdentifiabilityStudySettings::Get()->ShouldSampleType(
           IdentifiableSurface::Type::kLocalFontLookupByFallbackCharacter)) {
     return;
@@ -236,7 +236,7 @@ void FontMatchingMetrics::ReportFontLook
 
 void FontMatchingMetrics::ReportLastResortFallbackFontLookup(
     const FontDescription& font_description,
-    const SimpleFontData* resulting_font_data) {
+    SimpleFontData* resulting_font_data) {
   if (!IdentifiabilityStudySettings::Get()->ShouldSampleType(
           IdentifiableSurface::Type::kLocalFontLookupAsLastResort)) {
     return;
@@ -361,8 +361,7 @@ void FontMatchingMetrics::PublishAllMetr
   PublishEmojiGlyphMetrics();
 }
 
-int64_t FontMatchingMetrics::GetHashForFontData(
-    const SimpleFontData* font_data) {
+int64_t FontMatchingMetrics::GetHashForFontData(SimpleFontData* font_data) {
   return font_data ? FontGlobalContext::Get()
                          .GetOrComputeTypefaceDigest(font_data->PlatformData())
                          .ToUkmMetricValue()
@@ -370,7 +369,7 @@ int64_t FontMatchingMetrics::GetHashForF
 }
 
 IdentifiableToken FontMatchingMetrics::GetPostScriptNameTokenForFontData(
-    const SimpleFontData* font_data) {
+    SimpleFontData* font_data) {
   DCHECK(font_data);
   return FontGlobalContext::Get().GetOrComputePostScriptNameDigest(
       font_data->PlatformData());
--- a/third_party/blink/renderer/core/frame/font_matching_metrics.h
+++ b/third_party/blink/renderer/core/frame/font_matching_metrics.h
@@ -100,16 +100,15 @@ class FontMatchingMetrics {
   void ReportFontLookupByUniqueOrFamilyName(
       const AtomicString& name,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data);
+      SimpleFontData* resulting_font_data);
 
   // Reports a local font was looked up by a name and font description. This
   // only includes lookups where the name is allowed to match PostScript names
   // and full font names, but not family names.
-  void ReportFontLookupByUniqueNameOnly(
-      const AtomicString& name,
-      const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data,
-      bool is_loading_fallback = false);
+  void ReportFontLookupByUniqueNameOnly(const AtomicString& name,
+                                        const FontDescription& font_description,
+                                        SimpleFontData* resulting_font_data,
+                                        bool is_loading_fallback = false);
 
   // Reports a font was looked up by a fallback character, fallback priority,
   // and a font description.
@@ -117,12 +116,12 @@ class FontMatchingMetrics {
       UChar32 fallback_character,
       FontFallbackPriority fallback_priority,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data);
+      SimpleFontData* resulting_font_data);
 
   // Reports a last-resort fallback font was looked up by a font description.
   void ReportLastResortFallbackFontLookup(
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data);
+      SimpleFontData* resulting_font_data);
 
   // Reports a generic font family name was matched according to the script and
   // the user's preferences to a font family name.
@@ -171,7 +170,7 @@ class FontMatchingMetrics {
   // nullptr, then the typeface digest will also be saved with its PostScript
   // name in |font_load_postscript_name_|.
   void InsertFontHashIntoMap(IdentifiableTokenKey input_key,
-                             const SimpleFontData* font_data,
+                             SimpleFontData* font_data,
                              TokenToTokenHashMap& hash_map);
 
   // Reports a local font's existence was looked up by a name, but its actual
@@ -194,14 +193,14 @@ class FontMatchingMetrics {
 
   // Get a hash that uniquely represents the font data. Returns 0 if |font_data|
   // is nullptr.
-  int64_t GetHashForFontData(const SimpleFontData* font_data);
+  int64_t GetHashForFontData(SimpleFontData* font_data);
 
   void Initialize();
 
   // Get a token that uniquely represents the typeface's PostScript name. May
   // represent the empty string if no PostScript name was found.
   IdentifiableToken GetPostScriptNameTokenForFontData(
-      const SimpleFontData* font_data);
+      SimpleFontData* font_data);
 
   TokenToTokenHashMap font_lookups_by_unique_or_family_name_;
   TokenToTokenHashMap font_lookups_by_unique_name_only_;
--- a/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc
+++ b/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc
@@ -132,8 +132,8 @@ class PopupMenuCSSFontSelector : public
 
   // We don't override willUseFontData() for now because the old PopupListBox
   // only worked with fonts loaded when opening the popup.
-  const FontData* GetFontData(const FontDescription&,
-                              const FontFamily&) override;
+  scoped_refptr<FontData> GetFontData(const FontDescription&,
+                                      const FontFamily&) override;
 
   void Trace(Visitor*) const override;
 
@@ -152,7 +152,7 @@ PopupMenuCSSFontSelector::PopupMenuCSSFo
 
 PopupMenuCSSFontSelector::~PopupMenuCSSFontSelector() = default;
 
-const FontData* PopupMenuCSSFontSelector::GetFontData(
+scoped_refptr<FontData> PopupMenuCSSFontSelector::GetFontData(
     const FontDescription& description,
     const FontFamily& font_family) {
   return owner_font_selector_->GetFontData(description, font_family);
--- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -122,7 +122,6 @@
 #include "third_party/blink/renderer/platform/fonts/font_custom_platform_data.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/text/text_run.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -200,10 +199,10 @@ HeapVector<Member<CSSStyleRule>> FilterD
 }
 
 void CollectPlatformFontsFromRunFontDataList(
-    const HeapVector<ShapeResult::RunFontData>& run_font_data_list,
+    const Vector<ShapeResult::RunFontData>& run_font_data_list,
     HashMap<std::pair<int, String>, std::pair<int, String>>* font_stats) {
   for (const auto& run_font_data : run_font_data_list) {
-    const auto* simple_font_data = run_font_data.font_data_.Get();
+    const auto* simple_font_data = run_font_data.font_data_;
     String family_name = simple_font_data->PlatformData().FontFamilyName();
     if (family_name.IsNull())
       family_name = "";
@@ -1733,8 +1732,7 @@ void InspectorCSSAgent::CollectPlatformF
     if (!shape_result) {
       continue;
     }
-    HeapVector<ShapeResult::RunFontData> run_font_data_list;
-    ClearCollectionScope clear_scope(&run_font_data_list);
+    Vector<ShapeResult::RunFontData> run_font_data_list;
     shape_result->GetRunFontData(&run_font_data_list);
     CollectPlatformFontsFromRunFontDataList(run_font_data_list, font_stats);
   }
--- a/third_party/blink/renderer/core/layout/inline/inline_box_state.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_box_state.cc
@@ -19,7 +19,6 @@
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/svg/svg_length_functions.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"
 
 namespace blink {
 
@@ -174,8 +173,7 @@ void InlineBoxState::EnsureTextMetrics(c
 
 void InlineBoxState::AccumulateUsedFonts(const ShapeResultView* shape_result) {
   const auto baseline_type = style->GetFontBaseline();
-  HeapHashSet<Member<const SimpleFontData>> fallback_fonts;
-  ClearCollectionScope clear_scope(&fallback_fonts);
+  HashSet<const SimpleFontData*> fallback_fonts;
   shape_result->FallbackFonts(&fallback_fonts);
   for (const SimpleFontData* const fallback_font : fallback_fonts) {
     FontHeight fallback_metrics =
--- a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
+++ b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
@@ -17,7 +17,6 @@
 #include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
 #include "third_party/blink/renderer/core/layout/physical_box_fragment.h"
 #include "third_party/blink/renderer/platform/fonts/font_height.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"
 
 namespace blink {
 
@@ -38,10 +37,11 @@ std::tuple<LayoutUnit, LayoutUnit> Adjus
       primary_font_data->GetFontMetrics().FixedAscent(font_baseline);
   const LayoutUnit primary_descent = line_height - primary_ascent;
 
+  DCHECK(IsMainThread());
+  DEFINE_STATIC_LOCAL(Vector<ShapeResult::RunFontData>, run_fonts, ());
+  DCHECK_EQ(run_fonts.size(), 0u);
   // We don't use ShapeResultView::FallbackFonts() because we can't know if the
   // primary font is actually used with FallbackFonts().
-  HeapVector<ShapeResult::RunFontData> run_fonts;
-  ClearCollectionScope clear_scope(&run_fonts);
   shape_view.GetRunFontData(&run_fonts);
   const LayoutUnit kNoDiff = LayoutUnit::Max();
   LayoutUnit over_diff = kNoDiff;
@@ -65,6 +65,7 @@ std::tuple<LayoutUnit, LayoutUnit> Adjus
     over_diff = std::min(over_diff, current_over_diff);
     under_diff = std::min(under_diff, current_under_diff);
   }
+  run_fonts.resize(0);
   if (over_diff == kNoDiff)
     over_diff = LayoutUnit();
   if (under_diff == kNoDiff)
@@ -85,8 +86,7 @@ FontHeight ComputeEmHeight(const Logical
     FontHeight result_height;
     // We don't use ShapeResultView::FallbackFonts() because we can't know if
     // the primary font is actually used with FallbackFonts().
-    HeapVector<ShapeResult::RunFontData> run_fonts;
-    ClearCollectionScope clear_scope(&run_fonts);
+    Vector<ShapeResult::RunFontData> run_fonts;
     shape_result_view->GetRunFontData(&run_fonts);
     for (const auto& run_font : run_fonts) {
       const SimpleFontData* font_data = run_font.font_data_;
--- a/third_party/blink/renderer/core/layout/layout_font_accessor_win.cc
+++ b/third_party/blink/renderer/core/layout/layout_font_accessor_win.cc
@@ -16,7 +16,6 @@
 #include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"
 
 namespace blink {
 
@@ -36,8 +35,7 @@ void GetFontsUsedByFragment(const Physic
             shape_result_view->PrimaryFont()->PlatformData().FontFamilyName();
         if (!font_family.empty())
           result.font_names.insert(font_family);
-        HeapHashSet<Member<const SimpleFontData>> fallback_font_data;
-        ClearCollectionScope clear_scope(&fallback_font_data);
+        HashSet<const SimpleFontData*> fallback_font_data;
         shape_result_view->FallbackFonts(&fallback_font_data);
         for (const SimpleFontData* font_data : fallback_font_data) {
           result.font_names.insert(font_data->PlatformData().FontFamilyName());
--- a/third_party/blink/renderer/modules/font_access/font_metadata.cc
+++ b/third_party/blink/renderer/modules/font_access/font_metadata.cc
@@ -75,7 +75,7 @@ void FontMetadata::BlobImpl(ScriptPromis
   SetUpFontUniqueLookupIfNecessary();
 
   FontDescription description;
-  const SimpleFontData* font_data =
+  scoped_refptr<SimpleFontData> font_data =
       FontCache::Get().GetFontData(description, AtomicString(postscriptName),
                                    AlternateFontName::kLocalUniqueFace);
   if (!font_data) {
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -634,6 +634,7 @@ component("platform") {
     "fonts/font_cache_memory_dump_provider.h",
     "fonts/font_custom_platform_data.cc",
     "fonts/font_custom_platform_data.h",
+    "fonts/font_data.cc",
     "fonts/font_data.h",
     "fonts/font_data_cache.cc",
     "fonts/font_data_cache.h",
--- a/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
+++ b/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
@@ -127,7 +127,7 @@ sk_sp<SkTypeface> FontCache::CreateLocal
   return nullptr;
 }
 
-const SimpleFontData* FontCache::PlatformFallbackFontForCharacter(
+scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
     const FontDescription& font_description,
     UChar32 c,
     const SimpleFontData*,
@@ -158,7 +158,7 @@ const SimpleFontData* FontCache::Platfor
   if (fallback_priority == FontFallbackPriority::kEmojiEmoji &&
       base::FeatureList::IsEnabled(features::kGMSCoreEmoji)) {
     auto skia_fallback_is_noto_color_emoji = [&]() {
-      const FontPlatformData* skia_fallback_result = GetFontPlatformData(
+      FontPlatformData* skia_fallback_result = GetFontPlatformData(
           font_description, FontFaceCreationParams(family_name));
 
       // Determining the PostScript name is required as Skia on Android gives
@@ -175,14 +175,15 @@ const SimpleFontData* FontCache::Platfor
     };
 
     if (family_name.empty() || skia_fallback_is_noto_color_emoji()) {
-      const FontPlatformData* emoji_gms_core_font = GetFontPlatformData(
+      FontPlatformData* emoji_gms_core_font = GetFontPlatformData(
           font_description,
           FontFaceCreationParams(AtomicString(kNotoColorEmojiCompat)));
       if (emoji_gms_core_font) {
         SkTypeface* probe_coverage_typeface = emoji_gms_core_font->Typeface();
         if (probe_coverage_typeface &&
             probe_coverage_typeface->unicharToGlyph(c)) {
-          return FontDataFromFontPlatformData(emoji_gms_core_font);
+          return FontDataFromFontPlatformData(emoji_gms_core_font,
+                                              kDoNotRetain);
         }
       }
     }
@@ -192,10 +193,12 @@ const SimpleFontData* FontCache::Platfor
   // font was not found or an OEM emoji font was not to be overridden.
 
   if (family_name.empty())
-    return GetLastResortFallbackFont(font_description);
+    return GetLastResortFallbackFont(font_description, kDoNotRetain);
 
-  return FontDataFromFontPlatformData(GetFontPlatformData(
-      font_description, FontFaceCreationParams(family_name)));
+  return FontDataFromFontPlatformData(
+      GetFontPlatformData(font_description,
+                          FontFaceCreationParams(family_name)),
+      kDoNotRetain);
 }
 
 // static
--- a/third_party/blink/renderer/platform/fonts/custom_font_data.h
+++ b/third_party/blink/renderer/platform/fonts/custom_font_data.h
@@ -22,8 +22,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_CUSTOM_FONT_DATA_H_
 
 #include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
 
 namespace blink {
 
@@ -34,17 +34,22 @@ namespace blink {
 //  * `BinaryDataFontFaceSource` as loaded font resource
 //  * `LocalFontFaceSource` as derived class `CSSCustomFontData`
 //  * `RemoteFontFaceSource` as derived class `CSSCustomFontData`
-class PLATFORM_EXPORT CustomFontData : public GarbageCollected<CustomFontData> {
+class PLATFORM_EXPORT CustomFontData : public RefCounted<CustomFontData> {
  public:
-  CustomFontData() = default;
+  static scoped_refptr<CustomFontData> Create() {
+    return base::AdoptRef(new CustomFontData());
+  }
+
   virtual ~CustomFontData() = default;
-  virtual void Trace(Visitor*) const {}
 
   virtual void BeginLoadIfNeeded() const {}
   virtual bool IsLoading() const { return false; }
   virtual bool IsLoadingFallback() const { return false; }
   virtual bool ShouldSkipDrawing() const { return false; }
   virtual bool IsPendingDataUrl() const { return false; }
+
+ protected:
+  CustomFontData() = default;
 };
 
 }  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/font_cache.cc
+++ b/third_party/blink/renderer/platform/fonts/font_cache.cc
@@ -87,7 +87,10 @@ FontCache& FontCache::Get() {
   return FontGlobalContext::GetFontCache();
 }
 
-FontCache::FontCache() : font_manager_(sk_ref_sp(static_font_manager_)) {
+FontCache::FontCache()
+    : font_manager_(sk_ref_sp(static_font_manager_)),
+      font_platform_data_cache_(FontPlatformDataCache::Create()),
+      font_data_cache_(FontDataCache::Create()) {
 #if BUILDFLAG(IS_WIN)
   if (!font_manager_ || should_use_test_font_mgr) {
     // This code path is only for unit tests. This SkFontMgr does not work in
@@ -113,14 +116,12 @@ FontCache::~FontCache() = default;
 
 void FontCache::Trace(Visitor* visitor) const {
   visitor->Trace(font_cache_clients_);
-  visitor->Trace(font_platform_data_cache_);
-  visitor->Trace(fallback_list_shaper_cache_);
-  visitor->Trace(font_data_cache_);
   visitor->Trace(font_fallback_map_);
+  visitor->Trace(fallback_list_shaper_cache_);
 }
 
 #if !BUILDFLAG(IS_MAC)
-const FontPlatformData* FontCache::SystemFontPlatformData(
+FontPlatformData* FontCache::SystemFontPlatformData(
     const FontDescription& font_description) {
   const AtomicString& family = FontCache::SystemFontFamily();
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) || \
@@ -135,7 +136,7 @@ const FontPlatformData* FontCache::Syste
 }
 #endif
 
-const FontPlatformData* FontCache::GetFontPlatformData(
+FontPlatformData* FontCache::GetFontPlatformData(
     const FontDescription& font_description,
     const FontFaceCreationParams& creation_params,
     AlternateFontName alternate_font_name) {
@@ -153,7 +154,7 @@ const FontPlatformData* FontCache::GetFo
   }
 #endif
 
-  return font_platform_data_cache_.GetOrCreateFontPlatformData(
+  return font_platform_data_cache_->GetOrCreateFontPlatformData(
       this, font_description, creation_params, alternate_font_name);
 }
 
@@ -175,26 +176,34 @@ void FontCache::AcceptLanguagesChanged(c
   Get().InvalidateShapeCache();
 }
 
-const SimpleFontData* FontCache::GetFontData(
+scoped_refptr<SimpleFontData> FontCache::GetFontData(
     const FontDescription& font_description,
     const AtomicString& family,
-    AlternateFontName altername_font_name) {
-  if (const FontPlatformData* platform_data = GetFontPlatformData(
+    AlternateFontName altername_font_name,
+    ShouldRetain should_retain) {
+  if (FontPlatformData* platform_data = GetFontPlatformData(
           font_description,
           FontFaceCreationParams(
               AdjustFamilyNameToAvoidUnsupportedFonts(family)),
           altername_font_name)) {
     return FontDataFromFontPlatformData(
-        platform_data, font_description.SubpixelAscentDescent());
+        platform_data, should_retain, font_description.SubpixelAscentDescent());
   }
 
   return nullptr;
 }
 
-const SimpleFontData* FontCache::FontDataFromFontPlatformData(
+scoped_refptr<SimpleFontData> FontCache::FontDataFromFontPlatformData(
     const FontPlatformData* platform_data,
+    ShouldRetain should_retain,
     bool subpixel_ascent_descent) {
-  return font_data_cache_.Get(platform_data, subpixel_ascent_descent);
+#if DCHECK_IS_ON()
+  if (should_retain == kDoNotRetain)
+    DCHECK(purge_prevent_count_);
+#endif
+
+  return font_data_cache_->Get(platform_data, should_retain,
+                               subpixel_ascent_descent);
 }
 
 bool FontCache::IsPlatformFamilyMatchAvailable(
@@ -223,7 +232,15 @@ String FontCache::FirstAvailableOrFirst(
       gfx::FontList::FirstAvailableOrFirst(families.Utf8().c_str()));
 }
 
-const SimpleFontData* FontCache::FallbackFontForCharacter(
+SimpleFontData* FontCache::GetNonRetainedLastResortFallbackFont(
+    const FontDescription& font_description) {
+  auto font = GetLastResortFallbackFont(font_description, kDoNotRetain);
+  if (font)
+    font->AddRef();
+  return font.get();
+}
+
+scoped_refptr<SimpleFontData> FontCache::FallbackFontForCharacter(
     const FontDescription& description,
     UChar32 lookup_char,
     const SimpleFontData* font_data_to_substitute,
@@ -240,12 +257,21 @@ const SimpleFontData* FontCache::Fallbac
       Character::IsNonCharacter(lookup_char))
     return nullptr;
   base::ElapsedTimer timer;
-  const SimpleFontData* result = PlatformFallbackFontForCharacter(
+  scoped_refptr<SimpleFontData> result = PlatformFallbackFontForCharacter(
       description, lookup_char, font_data_to_substitute, fallback_priority);
   FontPerformance::AddSystemFallbackFontTime(timer.Elapsed());
   return result;
 }
 
+void FontCache::ReleaseFontData(const SimpleFontData* font_data) {
+  font_data_cache_->Release(font_data);
+}
+
+void FontCache::PurgePlatformFontDataCache() {
+  TRACE_EVENT0("fonts,ui", "FontCache::PurgePlatformFontDataCache");
+  font_platform_data_cache_->Purge(*font_data_cache_);
+}
+
 void FontCache::PurgeFallbackListShaperCache() {
   TRACE_EVENT0("fonts,ui", "FontCache::PurgeFallbackListShaperCache");
   for (auto& shape_cache : fallback_list_shaper_cache_.Values()) {
@@ -257,13 +283,17 @@ void FontCache::InvalidateShapeCache() {
   PurgeFallbackListShaperCache();
 }
 
-void FontCache::Purge() {
+void FontCache::Purge(PurgeSeverity purge_severity) {
   // Ideally we should never be forcing the purge while the
   // FontCachePurgePreventer is in scope, but we call purge() at any timing
   // via MemoryPressureListenerRegistry.
   if (purge_prevent_count_)
     return;
 
+  if (!font_data_cache_->Purge(purge_severity))
+    return;
+
+  PurgePlatformFontDataCache();
   PurgeFallbackListShaperCache();
 }
 
@@ -279,15 +309,14 @@ uint16_t FontCache::Generation() {
 
 void FontCache::Invalidate() {
   TRACE_EVENT0("fonts,ui", "FontCache::Invalidate");
-  font_platform_data_cache_.Clear();
-  font_data_cache_.Clear();
+  font_platform_data_cache_->Clear();
   generation_++;
 
   for (const auto& client : font_cache_clients_) {
     client->FontCacheInvalidated();
   }
 
-  Purge();
+  Purge(kForcePurge);
 }
 
 void FontCache::CrashWithFontInfo(const FontDescription* font_description) {
@@ -320,6 +349,16 @@ void FontCache::CrashWithFontInfo(const
   CHECK(false);
 }
 
+void FontCache::DumpFontPlatformDataCache(
+    base::trace_event::ProcessMemoryDump* memory_dump) {
+  DCHECK(IsMainThread());
+  base::trace_event::MemoryAllocatorDump* dump =
+      memory_dump->CreateAllocatorDump("font_caches/font_platform_data_cache");
+  dump->AddScalar("size", "bytes", font_platform_data_cache_->ByteSize());
+  memory_dump->AddSuballocation(dump->guid(),
+                                WTF::Partitions::kAllocatedObjectPoolName);
+}
+
 void FontCache::DumpShapeResultCache(
     base::trace_event::ProcessMemoryDump* memory_dump) {
   DCHECK(IsMainThread());
--- a/third_party/blink/renderer/platform/fonts/font_cache.h
+++ b/third_party/blink/renderer/platform/fonts/font_cache.h
@@ -36,13 +36,13 @@
 #include <string>
 
 #include "base/gtest_prod_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/fonts/fallback_list_composite_key.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache_client.h"
 #include "third_party/blink/renderer/platform/fonts/font_data_cache.h"
 #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h"
 #include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
-#include "third_party/blink/renderer/platform/fonts/font_platform_data_cache.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
@@ -75,6 +75,7 @@ class FontFaceCreationParams;
 class FontFallbackMap;
 class FontGlobalContext;
 class FontPlatformData;
+class FontPlatformDataCache;
 class SimpleFontData;
 class WebFontPrewarmer;
 
@@ -106,7 +107,9 @@ class PLATFORM_EXPORT FontCache final {
 
   void Trace(Visitor*) const;
 
-  const SimpleFontData* FallbackFontForCharacter(
+  void ReleaseFontData(const SimpleFontData*);
+
+  scoped_refptr<SimpleFontData> FallbackFontForCharacter(
       const FontDescription&,
       UChar32,
       const SimpleFontData* font_data_to_substitute,
@@ -115,11 +118,14 @@ class PLATFORM_EXPORT FontCache final {
   // Also implemented by the platform.
   void PlatformInit();
 
-  const SimpleFontData* GetFontData(
+  scoped_refptr<SimpleFontData> GetFontData(
       const FontDescription&,
       const AtomicString&,
-      AlternateFontName = AlternateFontName::kAllowAlternate);
-  const SimpleFontData* GetLastResortFallbackFont(const FontDescription&);
+      AlternateFontName = AlternateFontName::kAllowAlternate,
+      ShouldRetain = kRetain);
+  scoped_refptr<SimpleFontData> GetLastResortFallbackFont(const FontDescription&,
+                                                   ShouldRetain = kRetain);
+  SimpleFontData* GetNonRetainedLastResortFallbackFont(const FontDescription&);
 
   // Should be used in determining whether family names listed in font-family:
   // ... are available locally. Only returns true if family name matches.
@@ -212,12 +218,12 @@ class PLATFORM_EXPORT FontCache final {
     return *status_font_family_name_;
   }
 
-  const SimpleFontData* GetFallbackFamilyNameFromHardcodedChoices(
+  scoped_refptr<SimpleFontData> GetFallbackFamilyNameFromHardcodedChoices(
       const FontDescription&,
       UChar32 codepoint,
       FontFallbackPriority fallback_priority);
 
-  const SimpleFontData* GetDWriteFallbackFamily(
+  scoped_refptr<SimpleFontData> GetDWriteFallbackFamily(
       const FontDescription&,
       UChar32 codepoint,
       FontFallbackPriority fallback_priority);
@@ -245,8 +251,9 @@ class PLATFORM_EXPORT FontCache final {
                                   gfx::FallbackFontData*);
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
 
-  const SimpleFontData* FontDataFromFontPlatformData(
+  scoped_refptr<SimpleFontData> FontDataFromFontPlatformData(
       const FontPlatformData*,
+      ShouldRetain = kRetain,
       bool subpixel_ascent_descent = false);
 
   void InvalidateShapeCache();
@@ -254,6 +261,7 @@ class PLATFORM_EXPORT FontCache final {
   static void CrashWithFontInfo(const FontDescription*);
 
   // Memory reporting
+  void DumpFontPlatformDataCache(base::trace_event::ProcessMemoryDump*);
   void DumpShapeResultCache(base::trace_event::ProcessMemoryDump*);
 
   FontFallbackMap& GetFontFallbackMap();
@@ -268,7 +276,7 @@ class PLATFORM_EXPORT FontCache final {
   // elements.
   using Bcp47Vector = WTF::Vector<const char*, 4>;
 
-  const SimpleFontData* PlatformFallbackFontForCharacter(
+  scoped_refptr<SimpleFontData> PlatformFallbackFontForCharacter(
       const FontDescription&,
       UChar32,
       const SimpleFontData* font_data_to_substitute,
@@ -283,26 +291,26 @@ class PLATFORM_EXPORT FontCache final {
   friend class FontGlobalContext;
   FontCache();
 
-  void Purge();
+  void Purge(PurgeSeverity = kPurgeIfNeeded);
 
   void DisablePurging() { purge_prevent_count_++; }
   void EnablePurging() {
     DCHECK(purge_prevent_count_);
     if (!--purge_prevent_count_)
-      Purge();
+      Purge(kPurgeIfNeeded);
   }
 
   // FIXME: This method should eventually be removed.
-  const FontPlatformData* GetFontPlatformData(
+  FontPlatformData* GetFontPlatformData(
       const FontDescription&,
       const FontFaceCreationParams&,
       AlternateFontName = AlternateFontName::kAllowAlternate);
 #if !BUILDFLAG(IS_MAC)
-  const FontPlatformData* SystemFontPlatformData(const FontDescription&);
+  FontPlatformData* SystemFontPlatformData(const FontDescription&);
 #endif  // !BUILDFLAG(IS_MAC)
 
   // These methods are implemented by each platform.
-  const FontPlatformData* CreateFontPlatformData(
+  std::unique_ptr<FontPlatformData> CreateFontPlatformData(
       const FontDescription&,
       const FontFaceCreationParams&,
       float font_size,
@@ -321,8 +329,9 @@ class PLATFORM_EXPORT FontCache final {
 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) ||
         // BUILDFLAG(IS_CHROMEOS)
 
-  const SimpleFontData* FallbackOnStandardFontStyle(const FontDescription&,
-                                                    UChar32);
+  scoped_refptr<SimpleFontData> FallbackOnStandardFontStyle(
+      const FontDescription&,
+      UChar32);
 
   // Don't purge if this count is > 0;
   int purge_prevent_count_ = 0;
@@ -356,16 +365,17 @@ class PLATFORM_EXPORT FontCache final {
   uint16_t generation_ = 0;
   bool platform_init_ = false;
   HeapHashSet<WeakMember<FontCacheClient>> font_cache_clients_;
-  FontPlatformDataCache font_platform_data_cache_;
+  std::unique_ptr<FontPlatformDataCache> font_platform_data_cache_;
   HeapHashMap<FallbackListCompositeKey,
               WeakMember<ShapeCache>,
               FallbackListCompositeKeyTraits>
       fallback_list_shaper_cache_;
 
-  FontDataCache font_data_cache_;
+  std::unique_ptr<FontDataCache> font_data_cache_;
 
   Member<FontFallbackMap> font_fallback_map_;
 
+  void PurgePlatformFontDataCache();
   void PurgeFallbackListShaperCache();
 
   friend class SimpleFontData;  // For fontDataFromFontPlatformData
--- a/third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.cc
+++ b/third_party/blink/renderer/platform/fonts/font_cache_memory_dump_provider.cc
@@ -21,6 +21,7 @@ bool FontCacheMemoryDumpProvider::OnMemo
   DCHECK(IsMainThread());
   if (auto* context = FontGlobalContext::TryGet()) {
     FontCache& cache = context->GetFontCache();
+    cache.DumpFontPlatformDataCache(memory_dump);
     cache.DumpShapeResultCache(memory_dump);
   }
   return true;
--- a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
+++ b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
@@ -103,7 +103,7 @@ FontCustomPlatformData::~FontCustomPlatf
   }
 }
 
-const FontPlatformData* FontCustomPlatformData::GetFontPlatformData(
+FontPlatformData FontCustomPlatformData::GetFontPlatformData(
     float size,
     float adjusted_specified_size,
     bool bold,
@@ -276,11 +276,10 @@ const FontPlatformData* FontCustomPlatfo
       return_typeface = palette_typeface;
     }
   }
-  return MakeGarbageCollected<FontPlatformData>(
-      std::move(return_typeface), std::string(), size,
-      synthetic_bold && !base_typeface_->isBold(),
-      synthetic_italic && !base_typeface_->isItalic(), text_rendering,
-      resolved_font_features, orientation);
+  return FontPlatformData(std::move(return_typeface), std::string(), size,
+                          synthetic_bold && !base_typeface_->isBold(),
+                          synthetic_italic && !base_typeface_->isItalic(),
+                          text_rendering, resolved_font_features, orientation);
 }
 
 Vector<VariationAxis> FontCustomPlatformData::GetVariationAxes() const {
--- a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h
+++ b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h
@@ -68,7 +68,7 @@ class PLATFORM_EXPORT FontCustomPlatform
   // adjusted_specified_size should come from AdjustedSpecifiedSize() of
   // FontDescription. The latter is needed for correctly applying
   // font-optical-sizing: auto; independent of zoom level.
-  const FontPlatformData* GetFontPlatformData(
+  FontPlatformData GetFontPlatformData(
       float size,
       float adjusted_specified_size,
       bool bold,
--- /dev/null
+++ b/third_party/blink/renderer/platform/fonts/font_data.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/fonts/font_data.h"
+
+namespace blink {
+
+FontData::~FontData() = default;
+
+}  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/font_data.h
+++ b/third_party/blink/renderer/platform/fonts/font_data.h
@@ -27,24 +27,23 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_DATA_H_
 
 #include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
 
 namespace blink {
 
 class SimpleFontData;
 
-class PLATFORM_EXPORT FontData : public GarbageCollected<FontData> {
+class PLATFORM_EXPORT FontData : public RefCounted<FontData> {
  public:
   FontData() = default;
   FontData(const FontData&) = delete;
   FontData& operator=(const FontData&) = delete;
-  virtual ~FontData() = default;
 
-  virtual void Trace(Visitor*) const {}
+  virtual ~FontData();
 
   virtual const SimpleFontData* FontDataForCharacter(UChar32) const = 0;
   virtual bool IsCustomFont() const = 0;
--- a/third_party/blink/renderer/platform/fonts/font_data_cache.cc
+++ b/third_party/blink/renderer/platform/fonts/font_data_cache.cc
@@ -36,8 +36,23 @@
 
 namespace blink {
 
-const SimpleFontData* FontDataCache::Get(const FontPlatformData* platform_data,
-                                         bool subpixel_ascent_descent) {
+#if !BUILDFLAG(IS_ANDROID)
+const unsigned kCMaxInactiveFontData = 250;
+const unsigned kCTargetInactiveFontData = 200;
+#else
+const unsigned kCMaxInactiveFontData = 225;
+const unsigned kCTargetInactiveFontData = 200;
+#endif
+
+// static
+std::unique_ptr<FontDataCache> FontDataCache::Create() {
+  return std::make_unique<FontDataCache>();
+}
+
+scoped_refptr<SimpleFontData> FontDataCache::Get(
+    const FontPlatformData* platform_data,
+    ShouldRetain should_retain,
+    bool subpixel_ascent_descent) {
   if (!platform_data)
     return nullptr;
 
@@ -50,12 +65,98 @@ const SimpleFontData* FontDataCache::Get
     return nullptr;
   }
 
-  auto add_result = cache_.insert(platform_data, nullptr);
-  if (add_result.is_new_entry) {
-    add_result.stored_value->value = MakeGarbageCollected<SimpleFontData>(
-        platform_data, nullptr, subpixel_ascent_descent);
+  Cache::iterator result = cache_.find(platform_data);
+  if (result == cache_.end()) {
+    std::pair<scoped_refptr<SimpleFontData>, unsigned> new_value(
+        SimpleFontData::Create(*platform_data, nullptr,
+                               subpixel_ascent_descent),
+        should_retain == kRetain ? 1 : 0);
+    // The new SimpleFontData takes a copy of the incoming FontPlatformData
+    // object. The incoming key may be temporary. So, for cache storage, take
+    // the address of the newly created FontPlatformData that is copied an owned
+    // by SimpleFontData.
+    cache_.Set(&new_value.first->PlatformData(), new_value);
+    if (should_retain == kDoNotRetain)
+      inactive_font_data_.insert(new_value.first);
+    return std::move(new_value.first);
+  }
+
+  if (!result.Get()->value.second) {
+    DCHECK(inactive_font_data_.Contains(result.Get()->value.first));
+    inactive_font_data_.erase(result.Get()->value.first);
+  }
+
+  if (should_retain == kRetain) {
+    result.Get()->value.second++;
+  } else if (!result.Get()->value.second) {
+    // If shouldRetain is DoNotRetain and count is 0, we want to remove the
+    // fontData from m_inactiveFontData (above) and re-add here to update LRU
+    // position.
+    inactive_font_data_.insert(result.Get()->value.first);
+  }
+
+  return result.Get()->value.first;
+}
+
+bool FontDataCache::Contains(const FontPlatformData* font_platform_data) const {
+  return cache_.Contains(font_platform_data);
+}
+
+void FontDataCache::Release(const SimpleFontData* font_data) {
+  DCHECK(!font_data->IsCustomFont());
+
+  Cache::iterator it = cache_.find(&(font_data->PlatformData()));
+  if (it == cache_.end())
+    return;
+
+  DCHECK(it->value.second);
+  if (!--it->value.second)
+    inactive_font_data_.insert(it->value.first);
+}
+
+bool FontDataCache::Purge(PurgeSeverity purge_severity) {
+  if (purge_severity == kForcePurge)
+    return PurgeLeastRecentlyUsed(INT_MAX);
+
+  if (inactive_font_data_.size() > kCMaxInactiveFontData)
+    return PurgeLeastRecentlyUsed(inactive_font_data_.size() -
+                                  kCTargetInactiveFontData);
+
+  return false;
+}
+
+bool FontDataCache::PurgeLeastRecentlyUsed(int count) {
+  // Guard against reentry when e.g. a deleted FontData releases its small caps
+  // FontData.
+  if (is_purging_)
+    return false;
+
+  base::AutoReset<bool> is_purging_auto_reset(&is_purging_, true);
+
+  Vector<scoped_refptr<SimpleFontData>, 20> font_data_to_delete;
+  auto end = inactive_font_data_.end();
+  auto it = inactive_font_data_.begin();
+  for (int i = 0; i < count && it != end; ++it, ++i) {
+    const scoped_refptr<SimpleFontData>& font_data = *it;
+    cache_.erase(&(font_data->PlatformData()));
+    // We should not delete SimpleFontData here because deletion can modify
+    // m_inactiveFontData. See http://trac.webkit.org/changeset/44011
+    font_data_to_delete.push_back(font_data);
+  }
+
+  if (it == end) {
+    // Removed everything
+    inactive_font_data_.clear();
+  } else {
+    for (int i = 0; i < count; ++i)
+      inactive_font_data_.erase(inactive_font_data_.begin());
   }
-  return add_result.stored_value->value;
+
+  bool did_work = font_data_to_delete.size();
+
+  font_data_to_delete.clear();
+
+  return did_work;
 }
 
 }  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/font_data_cache.h
+++ b/third_party/blink/renderer/platform/fonts/font_data_cache.h
@@ -33,10 +33,14 @@
 
 #include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
 
 namespace blink {
 
+enum ShouldRetain { kRetain, kDoNotRetain };
+enum PurgeSeverity { kPurgeIfNeeded, kForcePurge };
+
 struct FontDataCacheKeyHashTraits : GenericHashTraits<const FontPlatformData*> {
   STATIC_ONLY(FontDataCacheKeyHashTraits);
   static unsigned GetHash(const FontPlatformData* platform_data) {
@@ -51,24 +55,36 @@ struct FontDataCacheKeyHashTraits : Gene
 };
 
 class FontDataCache final {
-  DISALLOW_NEW();
+  USING_FAST_MALLOC(FontDataCache);
 
  public:
+  static std::unique_ptr<FontDataCache> Create();
+
   FontDataCache() = default;
   FontDataCache(const FontDataCache&) = delete;
   FontDataCache& operator=(const FontDataCache&) = delete;
 
-  void Trace(Visitor* visitor) const { visitor->Trace(cache_); }
-
-  const SimpleFontData* Get(const FontPlatformData*,
-                            bool subpixel_ascent_descent = false);
-  void Clear() { cache_.clear(); }
+  scoped_refptr<SimpleFontData> Get(const FontPlatformData*,
+                                    ShouldRetain = kRetain,
+                                    bool subpixel_ascent_descent = false);
+  bool Contains(const FontPlatformData*) const;
+  void Release(const SimpleFontData*);
+
+  // Purges items in FontDataCache according to provided severity.
+  // Returns true if any removal of cache items actually occurred.
+  bool Purge(PurgeSeverity);
 
  private:
-  HeapHashMap<Member<const FontPlatformData>,
-              WeakMember<const SimpleFontData>,
-              FontDataCacheKeyHashTraits>
-      cache_;
+  bool PurgeLeastRecentlyUsed(int count);
+
+  typedef HashMap<const FontPlatformData*,
+                  std::pair<scoped_refptr<SimpleFontData>, unsigned>,
+                  FontDataCacheKeyHashTraits>
+      Cache;
+
+  Cache cache_;
+  LinkedHashSet<scoped_refptr<SimpleFontData>> inactive_font_data_;
+  bool is_purging_ = false;
 };
 
 }  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/font_data_for_range_set.cc
+++ b/third_party/blink/renderer/platform/fonts/font_data_for_range_set.cc
@@ -13,4 +13,10 @@ FontDataForRangeSet::FontDataForRangeSet
   range_set_ = other.range_set_;
 }
 
+FontDataForRangeSetFromCache::~FontDataForRangeSetFromCache() {
+  if (font_data_ && !font_data_->IsCustomFont()) {
+    FontCache::Get().ReleaseFontData(font_data_.get());
+  }
+}
+
 }  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/font_data_for_range_set.h
+++ b/third_party/blink/renderer/platform/fonts/font_data_for_range_set.h
@@ -37,19 +37,17 @@ namespace blink {
 class SimpleFontData;
 
 class PLATFORM_EXPORT FontDataForRangeSet
-    : public GarbageCollected<FontDataForRangeSet> {
+    : public RefCounted<FontDataForRangeSet> {
  public:
   explicit FontDataForRangeSet(
-      const SimpleFontData* font_data = nullptr,
+      scoped_refptr<SimpleFontData> font_data = nullptr,
       scoped_refptr<UnicodeRangeSet> range_set = nullptr)
-      : font_data_(font_data), range_set_(std::move(range_set)) {}
+      : font_data_(std::move(font_data)), range_set_(std::move(range_set)) {}
 
   FontDataForRangeSet(const FontDataForRangeSet& other);
 
   virtual ~FontDataForRangeSet() = default;
 
-  void Trace(Visitor* visitor) const { visitor->Trace(font_data_); }
-
   bool Contains(UChar32 test_char) const {
     return !range_set_ || range_set_->Contains(test_char);
   }
@@ -57,8 +55,8 @@ class PLATFORM_EXPORT FontDataForRangeSe
     return !range_set_ || range_set_->IsEntireRange();
   }
   UnicodeRangeSet* Ranges() const { return range_set_.get(); }
-  bool HasFontData() const { return font_data_; }
-  const SimpleFontData* FontData() const { return font_data_.Get(); }
+  bool HasFontData() const { return font_data_.get(); }
+  const SimpleFontData* FontData() const { return font_data_.get(); }
 
   // TODO(xiaochengh): |FontData::IsLoadingFallback()| returns true if the
   // FontData is a pending custom font. We should rename it for better clarity.
@@ -71,10 +69,20 @@ class PLATFORM_EXPORT FontDataForRangeSe
   }
 
  protected:
-  Member<const SimpleFontData> font_data_;
+  scoped_refptr<SimpleFontData> font_data_;
   scoped_refptr<UnicodeRangeSet> range_set_;
 };
 
+class PLATFORM_EXPORT FontDataForRangeSetFromCache
+    : public FontDataForRangeSet {
+ public:
+  explicit FontDataForRangeSetFromCache(
+      scoped_refptr<SimpleFontData> font_data,
+      scoped_refptr<UnicodeRangeSet> range_set = nullptr)
+      : FontDataForRangeSet(std::move(font_data), std::move(range_set)) {}
+  ~FontDataForRangeSetFromCache() override;
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_DATA_FOR_RANGE_SET_H_
--- a/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
@@ -73,8 +73,8 @@ void FontFallbackIterator::WillUseRange(
   selector->WillUseRange(font_description_, family, range_set);
 }
 
-FontDataForRangeSet* FontFallbackIterator::UniqueOrNext(
-    FontDataForRangeSet* candidate,
+scoped_refptr<FontDataForRangeSet> FontFallbackIterator::UniqueOrNext(
+    scoped_refptr<FontDataForRangeSet> candidate,
     const HintCharList& hint_list) {
   if (!candidate->HasFontData())
     return Next(hint_list);
@@ -117,17 +117,17 @@ bool FontFallbackIterator::NeedsHintList
   return font_data->IsSegmented();
 }
 
-FontDataForRangeSet* FontFallbackIterator::Next(const HintCharList& hint_list) {
+scoped_refptr<FontDataForRangeSet> FontFallbackIterator::Next(const HintCharList& hint_list) {
   if (fallback_stage_ == kOutOfLuck)
-    return MakeGarbageCollected<FontDataForRangeSet>();
+    return base::AdoptRef(new FontDataForRangeSet());
 
   if (fallback_stage_ == kFallbackPriorityFonts) {
     // Only try one fallback priority font,
     // then proceed to regular system fallback.
     fallback_stage_ = kSystemFonts;
-    FontDataForRangeSet* fallback_priority_font_range =
-        MakeGarbageCollected<FontDataForRangeSet>(
-            FallbackPriorityFont(hint_list[0]));
+    scoped_refptr<FontDataForRangeSet> fallback_priority_font_range =
+        base::AdoptRef(
+            new FontDataForRangeSet(FallbackPriorityFont(hint_list[0])));
     if (fallback_priority_font_range->HasFontData())
       return UniqueOrNext(std::move(fallback_priority_font_range), hint_list);
     return Next(hint_list);
@@ -135,11 +135,11 @@ FontDataForRangeSet* FontFallbackIterato
 
   if (fallback_stage_ == kSystemFonts) {
     // We've reached pref + system fallback.
-    const SimpleFontData* system_font = UniqueSystemFontForHintList(hint_list);
+    scoped_refptr<SimpleFontData> system_font = UniqueSystemFontForHintList(hint_list);
     if (system_font) {
       // Fallback fonts are not retained in the FontDataCache.
-      return UniqueOrNext(
-          MakeGarbageCollected<FontDataForRangeSet>(system_font), hint_list);
+      return UniqueOrNext(base::AdoptRef(new FontDataForRangeSet(system_font)),
+                          hint_list);
     }
 
     // If we don't have options from the system fallback anymore or had
@@ -149,16 +149,18 @@ FontDataForRangeSet* FontFallbackIterato
     // LastResort font, not just Times or Arial.
     FontCache& font_cache = FontCache::Get();
     fallback_stage_ = kFirstCandidateForNotdefGlyph;
-    const SimpleFontData* last_resort =
-        font_cache.GetLastResortFallbackFont(font_description_);
+    scoped_refptr<SimpleFontData> last_resort =
+        font_cache.GetLastResortFallbackFont(font_description_).get();
 
     if (FontSelector* font_selector = font_fallback_list_->GetFontSelector()) {
-      font_selector->ReportLastResortFallbackFontLookup(font_description_,
-                                                        last_resort);
+      font_selector->ReportLastResortFallbackFontLookup(
+          font_description_,
+          last_resort.get());
     }
 
-    return UniqueOrNext(MakeGarbageCollected<FontDataForRangeSet>(last_resort),
-                        hint_list);
+    return UniqueOrNext(
+        base::AdoptRef(new FontDataForRangeSetFromCache(last_resort)),
+        hint_list);
   }
 
   if (fallback_stage_ == kFirstCandidateForNotdefGlyph) {
@@ -189,13 +191,13 @@ FontDataForRangeSet* FontFallbackIterato
     // Skip forward to the next font family for the next call to next().
     current_font_data_index_++;
     if (!font_data->IsLoading()) {
-      SimpleFontData* non_segmented =
+      scoped_refptr<SimpleFontData> non_segmented =
           const_cast<SimpleFontData*>(To<SimpleFontData>(font_data));
       // The fontData object that we have here is tracked in m_fontList of
       // FontFallbackList and gets released in the font cache when the
       // FontFallbackList is destroyed.
       return UniqueOrNext(
-          MakeGarbageCollected<FontDataForRangeSet>(non_segmented), hint_list);
+          base::AdoptRef(new FontDataForRangeSet(non_segmented)), hint_list);
     }
     return Next(hint_list);
   }
@@ -209,7 +211,7 @@ FontDataForRangeSet* FontFallbackIterato
   }
 
   DCHECK_LT(segmented_face_index_, segmented->NumFaces());
-  FontDataForRangeSet* current_segmented_face =
+  scoped_refptr<FontDataForRangeSet> current_segmented_face =
       segmented->FaceAt(segmented_face_index_);
   segmented_face_index_++;
 
@@ -220,7 +222,7 @@ FontDataForRangeSet* FontFallbackIterato
     current_font_data_index_++;
   }
 
-  if (RangeSetContributesForHint(hint_list, current_segmented_face)) {
+  if (RangeSetContributesForHint(hint_list, current_segmented_face.get())) {
     const SimpleFontData* current_segmented_face_font_data =
         current_segmented_face->FontData();
     if (const CustomFontData* current_segmented_face_custom_font_data =
@@ -234,15 +236,17 @@ FontDataForRangeSet* FontFallbackIterato
   return Next(hint_list);
 }
 
-const SimpleFontData* FontFallbackIterator::FallbackPriorityFont(UChar32 hint) {
-  const SimpleFontData* font_data = FontCache::Get().FallbackFontForCharacter(
-      font_description_, hint,
-      font_fallback_list_->PrimarySimpleFontData(font_description_),
-      font_fallback_priority_);
+scoped_refptr<SimpleFontData> FontFallbackIterator::FallbackPriorityFont(
+    UChar32 hint) {
+  scoped_refptr<SimpleFontData> font_data =
+      FontCache::Get().FallbackFontForCharacter(
+          font_description_, hint,
+          font_fallback_list_->PrimarySimpleFontData(font_description_),
+          font_fallback_priority_);
 
   if (FontSelector* font_selector = font_fallback_list_->GetFontSelector()) {
     font_selector->ReportFontLookupByFallbackCharacter(
-        hint, font_fallback_priority_, font_description_, font_data);
+        hint, font_fallback_priority_, font_description_, font_data.get());
   }
   return font_data;
 }
@@ -268,7 +272,7 @@ static inline unsigned ChooseHintIndex(
   return 0;
 }
 
-const SimpleFontData* FontFallbackIterator::UniqueSystemFontForHintList(
+scoped_refptr<SimpleFontData> FontFallbackIterator::UniqueSystemFontForHintList(
     const HintCharList& hint_list) {
   // When we're asked for a fallback for the same characters again, we give up
   // because the shaper must have previously tried shaping with the font
@@ -283,13 +287,13 @@ const SimpleFontData* FontFallbackIterat
     return nullptr;
   previously_asked_for_hint_.insert(hint);
 
-  const SimpleFontData* font_data = font_cache.FallbackFontForCharacter(
+  scoped_refptr<SimpleFontData> font_data = font_cache.FallbackFontForCharacter(
       font_description_, hint,
       font_fallback_list_->PrimarySimpleFontData(font_description_));
 
   if (FontSelector* font_selector = font_fallback_list_->GetFontSelector()) {
     font_selector->ReportFontLookupByFallbackCharacter(
-        hint, FontFallbackPriority::kText, font_description_, font_data);
+        hint, FontFallbackPriority::kText, font_description_, font_data.get());
   }
   return font_data;
 }
--- a/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
@@ -5,13 +5,14 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_FALLBACK_ITERATOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_FALLBACK_ITERATOR_H_
 
+#include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/platform/fonts/font_data_for_range_set.h"
 #include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
@@ -49,7 +50,7 @@ class PLATFORM_EXPORT FontFallbackIterat
   // Some system fallback APIs (Windows, Android) require a character, or a
   // portion of the string to be passed.  On Mac and Linux, we get a list of
   // fonts without passing in characters.
-  FontDataForRangeSet* Next(const HintCharList& hint_list);
+  scoped_refptr<FontDataForRangeSet> Next(const HintCharList& hint_list);
 
   void Reset();
 
@@ -59,11 +60,12 @@ class PLATFORM_EXPORT FontFallbackIterat
   bool AlreadyLoadingRangeForHintChar(UChar32 hint_char);
   void WillUseRange(const AtomicString& family, const FontDataForRangeSet&);
 
-  FontDataForRangeSet* UniqueOrNext(FontDataForRangeSet* candidate,
-                                    const HintCharList& hint_list);
+  scoped_refptr<FontDataForRangeSet> UniqueOrNext(
+      scoped_refptr<FontDataForRangeSet> candidate,
+      const HintCharList& hint_list);
 
-  const SimpleFontData* FallbackPriorityFont(UChar32 hint);
-  const SimpleFontData* UniqueSystemFontForHintList(
+  scoped_refptr<SimpleFontData> FallbackPriorityFont(UChar32 hint);
+  scoped_refptr<SimpleFontData> UniqueSystemFontForHintList(
       const HintCharList& hint_list);
 
   const FontDescription& font_description_;
@@ -91,8 +93,8 @@ class PLATFORM_EXPORT FontFallbackIterat
   // candidate to be used for rendering the .notdef glyph, and set HasNext() to
   // false.
   HashSet<uint32_t> unique_font_data_for_range_sets_returned_;
-  FontDataForRangeSet* first_candidate_ = nullptr;
-  HeapVector<Member<FontDataForRangeSet>> tracked_loading_range_sets_;
+  scoped_refptr<FontDataForRangeSet> first_candidate_;
+  Vector<scoped_refptr<FontDataForRangeSet>> tracked_loading_range_sets_;
   FontFallbackPriority font_fallback_priority_;
 };
 
--- a/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
@@ -52,9 +52,17 @@ FontFallbackList::FontFallbackList(FontS
       is_invalid_(false),
       nullify_primary_font_data_for_test_(false) {}
 
+FontFallbackList::~FontFallbackList() {
+  unsigned num_fonts = font_list_.size();
+  for (unsigned i = 0; i < num_fonts; ++i) {
+    if (!font_list_[i]->IsCustomFont()) {
+      DCHECK(!font_list_[i]->IsSegmented());
+      FontCache::Get().ReleaseFontData(To<SimpleFontData>(font_list_[i].get()));
+    }
+  }
+}
+
 void FontFallbackList::Trace(Visitor* visitor) const {
-  visitor->Trace(font_list_);
-  visitor->Trace(cached_primary_simple_font_data_);
   visitor->Trace(font_selector_);
   visitor->Trace(ng_shape_cache_);
   visitor->Trace(shape_cache_);
@@ -98,8 +106,8 @@ const SimpleFontData* FontFallbackList::
         return font_data->FontDataForCharacter(kSpaceCharacter);
 
       FontCache& font_cache = FontCache::Get();
-      const SimpleFontData* last_resort_fallback =
-          font_cache.GetLastResortFallbackFont(font_description);
+      SimpleFontData* last_resort_fallback =
+          font_cache.GetLastResortFallbackFont(font_description).get();
       DCHECK(last_resort_fallback);
       return last_resort_fallback;
     }
@@ -137,7 +145,7 @@ const SimpleFontData* FontFallbackList::
   }
 }
 
-const FontData* FontFallbackList::GetFontData(
+scoped_refptr<FontData> FontFallbackList::GetFontData(
     const FontDescription& font_description) {
   const FontFamily* curr_family = &font_description.Family();
   for (int i = 0; curr_family && i < family_index_; i++)
@@ -148,7 +156,7 @@ const FontData* FontFallbackList::GetFon
     if (!font_selector_) {
       // Don't query system fonts for empty font family name.
       if (!curr_family->FamilyName().empty()) {
-        if (auto* result = FontCache::Get().GetFontData(
+        if (auto result = FontCache::Get().GetFontData(
                 font_description, curr_family->FamilyName())) {
           return result;
         }
@@ -156,7 +164,7 @@ const FontData* FontFallbackList::GetFon
       continue;
     }
 
-    const FontData* result =
+    scoped_refptr<FontData> result =
         font_selector_->GetFontData(font_description, *curr_family);
     // Don't query system fonts for empty font family name.
     if (!result && !curr_family->FamilyName().empty()) {
@@ -164,7 +172,7 @@ const FontData* FontFallbackList::GetFon
                                             curr_family->FamilyName());
       font_selector_->ReportFontLookupByUniqueOrFamilyName(
           curr_family->FamilyName(), font_description,
-          DynamicTo<SimpleFontData>(result));
+          DynamicTo<SimpleFontData>(result.get()));
     }
     if (result) {
       font_selector_->ReportSuccessfulFontFamilyMatch(
@@ -181,18 +189,18 @@ const FontData* FontFallbackList::GetFon
     FontFamily font_family;
     font_family.SetFamily(font_family_names::kWebkitStandard,
                           FontFamily::Type::kGenericFamily);
-    if (const FontData* data =
+    if (scoped_refptr<FontData> data =
             font_selector_->GetFontData(font_description, font_family)) {
       return data;
     }
   }
 
   // Still no result. Hand back our last resort fallback font.
-  auto* last_resort =
+  auto last_resort =
       FontCache::Get().GetLastResortFallbackFont(font_description);
   if (font_selector_) {
     font_selector_->ReportLastResortFallbackFontLookup(font_description,
-                                                       last_resort);
+                                                       last_resort.get());
   }
   return last_resort;
 }
@@ -202,7 +210,7 @@ const FontData* FontFallbackList::FontDa
     unsigned realized_font_index) {
   // This fallback font is already in our list.
   if (realized_font_index < font_list_.size())
-    return font_list_[realized_font_index].Get();
+    return font_list_[realized_font_index].get();
 
   // Make sure we're not passing in some crazy value here.
   DCHECK_EQ(realized_font_index, font_list_.size());
@@ -216,7 +224,7 @@ const FontData* FontFallbackList::FontDa
   // the same spot in the list twice.  GetFontData will adjust our
   // |family_index_| as it scans for the right font to make.
   DCHECK_EQ(FontCache::Get().Generation(), generation_);
-  const FontData* result = GetFontData(font_description);
+  scoped_refptr<FontData> result = GetFontData(font_description);
   if (result) {
     font_list_.push_back(result);
     if (result->IsLoadingFallback())
@@ -224,7 +232,7 @@ const FontData* FontFallbackList::FontDa
     if (result->IsCustomFont())
       has_custom_font_ = true;
   }
-  return result;
+  return result.get();
 }
 
 bool FontFallbackList::ComputeCanShapeWordByWord(
--- a/third_party/blink/renderer/platform/fonts/font_fallback_list.h
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_list.h
@@ -49,6 +49,7 @@ class PLATFORM_EXPORT FontFallbackList
 
   FontFallbackList(const FontFallbackList&) = delete;
   FontFallbackList& operator=(const FontFallbackList&) = delete;
+  ~FontFallbackList();
 
   void Trace(Visitor*) const;
 
@@ -116,7 +117,7 @@ class PLATFORM_EXPORT FontFallbackList
   bool HasCustomFont() const { return has_custom_font_; }
 
  private:
-  const FontData* GetFontData(const FontDescription&);
+  scoped_refptr<FontData> GetFontData(const FontDescription&);
 
   const SimpleFontData* DeterminePrimarySimpleFontData(const FontDescription&);
   const SimpleFontData* DeterminePrimarySimpleFontDataCore(
@@ -124,8 +125,8 @@ class PLATFORM_EXPORT FontFallbackList
 
   bool ComputeCanShapeWordByWord(const FontDescription&);
 
-  HeapVector<Member<const FontData>, 1> font_list_;
-  Member<const SimpleFontData> cached_primary_simple_font_data_ = nullptr;
+  Vector<scoped_refptr<FontData>, 1> font_list_;
+  const SimpleFontData* cached_primary_simple_font_data_ = nullptr;
   const Member<FontSelector> font_selector_;
   int family_index_ = 0;
   const uint16_t generation_;
--- a/third_party/blink/renderer/platform/fonts/font_platform_data.cc
+++ b/third_party/blink/renderer/platform/fonts/font_platform_data.cc
@@ -159,10 +159,6 @@ FontPlatformData::FontPlatformData(sk_sp
 
 FontPlatformData::~FontPlatformData() = default;
 
-void FontPlatformData::Trace(Visitor* visitor) const {
-  visitor->Trace(harfbuzz_face_);
-}
-
 #if BUILDFLAG(IS_MAC)
 CTFontRef FontPlatformData::CtFont() const {
   return SkTypeface_GetCTFontRef(typeface_.get());
@@ -214,10 +210,11 @@ SkTypeface* FontPlatformData::Typeface()
 
 HarfBuzzFace* FontPlatformData::GetHarfBuzzFace() const {
   if (!harfbuzz_face_) {
-    harfbuzz_face_ = MakeGarbageCollected<HarfBuzzFace>(this, UniqueID());
+    harfbuzz_face_ =
+        HarfBuzzFace::Create(const_cast<FontPlatformData*>(this), UniqueID());
   }
 
-  return harfbuzz_face_.Get();
+  return harfbuzz_face_.get();
 }
 
 bool FontPlatformData::HasSpaceInLigaturesOrKerning(
@@ -247,7 +244,7 @@ unsigned FontPlatformData::GetHash() con
 }
 
 #if !BUILDFLAG(IS_MAC)
-bool FontPlatformData::FontContainsCharacter(UChar32 character) const {
+bool FontPlatformData::FontContainsCharacter(UChar32 character) {
   return CreateSkFont().unicharToGlyph(character);
 }
 #endif
--- a/third_party/blink/renderer/platform/fonts/font_platform_data.h
+++ b/third_party/blink/renderer/platform/fonts/font_platform_data.h
@@ -39,8 +39,6 @@
 #include "third_party/blink/renderer/platform/fonts/font_orientation.h"
 #include "third_party/blink/renderer/platform/fonts/resolved_font_features.h"
 #include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -61,8 +59,9 @@ namespace blink {
 class HarfBuzzFace;
 class OpenTypeVerticalData;
 
-class PLATFORM_EXPORT FontPlatformData
-    : public GarbageCollected<FontPlatformData> {
+class PLATFORM_EXPORT FontPlatformData {
+  USING_FAST_MALLOC(FontPlatformData);
+
  public:
   // Used for deleted values in the font cache's hash tables. The hash table
   // will create us with this structure, and it will compare other values
@@ -83,8 +82,6 @@ class PLATFORM_EXPORT FontPlatformData
                    FontOrientation = FontOrientation::kHorizontal);
   ~FontPlatformData();
 
-  void Trace(Visitor*) const;
-
 #if BUILDFLAG(IS_MAC)
   // Returns nullptr for FreeType backed SkTypefaces, compare
   // FontCustomPlatformData, which are used for variable fonts on Mac OS
@@ -130,7 +127,7 @@ class PLATFORM_EXPORT FontPlatformData
 
   bool IsHashTableDeletedValue() const { return is_hash_table_deleted_value_; }
 #if !BUILDFLAG(IS_MAC)
-  bool FontContainsCharacter(UChar32 character) const;
+  bool FontContainsCharacter(UChar32 character);
 #endif
 
 #if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC)
@@ -186,7 +183,7 @@ class PLATFORM_EXPORT FontPlatformData
   WebFontRenderStyle style_;
 #endif
 
-  mutable Member<HarfBuzzFace> harfbuzz_face_;
+  mutable scoped_refptr<HarfBuzzFace> harfbuzz_face_;
   bool is_hash_table_deleted_value_ = false;
 };
 
--- a/third_party/blink/renderer/platform/fonts/font_platform_data_cache.cc
+++ b/third_party/blink/renderer/platform/fonts/font_platform_data_cache.cc
@@ -38,13 +38,20 @@
 
 namespace blink {
 
+// static
+std::unique_ptr<FontPlatformDataCache> FontPlatformDataCache::Create() {
+  return std::make_unique<FontPlatformDataCache>();
+}
+
 FontPlatformDataCache::FontPlatformDataCache()
     : font_size_limit_(std::nextafter(
           (static_cast<float>(std::numeric_limits<unsigned>::max()) - 2.f) /
               static_cast<float>(blink::FontCacheKey::PrecisionMultiplier()),
           0.f)) {}
 
-const FontPlatformData* FontPlatformDataCache::GetOrCreateFontPlatformData(
+FontPlatformDataCache::~FontPlatformDataCache() = default;
+
+FontPlatformData* FontPlatformDataCache::GetOrCreateFontPlatformData(
     FontCache* font_cache,
     const FontDescription& font_description,
     const FontFaceCreationParams& creation_params,
@@ -60,13 +67,15 @@ const FontPlatformData* FontPlatformData
 
   auto it = map_.find(key);
   if (it != map_.end()) {
-    return it->value.Get();
+    return it->value.get();
   }
 
-  if (const FontPlatformData* result = font_cache->CreateFontPlatformData(
-          font_description, creation_params, size, alternate_font_name)) {
-    map_.insert(key, result);
-    return result;
+  if (std::unique_ptr<FontPlatformData> result =
+          font_cache->CreateFontPlatformData(font_description, creation_params,
+                                             size, alternate_font_name)) {
+    FontPlatformData* result_ptr = result.get();
+    map_.insert(key, std::move(result));
+    return result_ptr;
   }
 
   if (alternate_font_name != AlternateFontName::kAllowAlternate ||
@@ -82,16 +91,35 @@ const FontPlatformData* FontPlatformData
     return nullptr;
 
   FontFaceCreationParams create_by_alternate_family(alternate_name);
-  if (const FontPlatformData* result = GetOrCreateFontPlatformData(
+  if (FontPlatformData* result = GetOrCreateFontPlatformData(
           font_cache, font_description, create_by_alternate_family,
           AlternateFontName::kNoAlternate)) {
     // Cache the platform_data under the old name.
     // "accessibility/font-changed.html" reaches here.
-    map_.insert(key, result);
+    map_.insert(key, std::make_unique<FontPlatformData>(*result));
     return result;
   }
 
   return nullptr;
 }
 
+size_t FontPlatformDataCache::ByteSize() const {
+  return map_.size() * sizeof(std::unique_ptr<FontPlatformData>);
+}
+
+void FontPlatformDataCache::Clear() {
+  map_.clear();
+}
+
+void FontPlatformDataCache::Purge(const FontDataCache& font_data_cache) {
+  Vector<FontCacheKey> keys_to_remove;
+  keys_to_remove.ReserveInitialCapacity(map_.size());
+  for (auto& entry : map_) {
+    if (entry.value && !font_data_cache.Contains(entry.value.get())) {
+      keys_to_remove.push_back(entry.key);
+    }
+  }
+  map_.RemoveAll(keys_to_remove);
+}
+
 }  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/font_platform_data_cache.h
+++ b/third_party/blink/renderer/platform/fonts/font_platform_data_cache.h
@@ -31,13 +31,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_PLATFORM_DATA_CACHE_H_
 
 #include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
 
 namespace blink {
 
 enum class AlternateFontName;
 class FontCache;
+class FontDataCache;
 class FontDescription;
 class FontFaceCreationParams;
 class FontPlatformData;
@@ -45,23 +45,30 @@ class FontPlatformData;
 // `FontPlatformDataCache` is the shared cache mapping from `FontDescription`
 // to `FontPlatformData`.
 class FontPlatformDataCache final {
-  DISALLOW_NEW();
-
  public:
+  static std::unique_ptr<FontPlatformDataCache> Create();
+
   FontPlatformDataCache();
+  ~FontPlatformDataCache();
+
+  FontPlatformDataCache(const FontPlatformDataCache&) = delete;
+  FontPlatformDataCache(FontPlatformDataCache&&) = delete;
 
-  void Trace(Visitor* visitor) const { visitor->Trace(map_); }
+  FontPlatformDataCache operator=(const FontPlatformDataCache&) = delete;
+  FontPlatformDataCache operator=(FontPlatformDataCache&&) = delete;
 
-  const FontPlatformData* GetOrCreateFontPlatformData(
+  FontPlatformData* GetOrCreateFontPlatformData(
       FontCache* font_cache,
       const FontDescription& font_description,
       const FontFaceCreationParams& creation_params,
       AlternateFontName alternate_font_name);
 
-  void Clear() { map_.clear(); }
+  size_t ByteSize() const;
+  void Clear();
+  void Purge(const FontDataCache& font_data_cache);
 
  private:
-  HeapHashMap<FontCacheKey, WeakMember<const FontPlatformData>> map_;
+  HashMap<FontCacheKey, std::unique_ptr<FontPlatformData>> map_;
 
   // A maximum float value to which we limit incoming font sizes. This is the
   // smallest float so that multiplying it by
--- a/third_party/blink/renderer/platform/fonts/font_selector.h
+++ b/third_party/blink/renderer/platform/fonts/font_selector.h
@@ -53,8 +53,8 @@ class UseCounter;
 class PLATFORM_EXPORT FontSelector : public FontCacheClient {
  public:
   ~FontSelector() override = default;
-  virtual const FontData* GetFontData(const FontDescription&,
-                                      const FontFamily&) = 0;
+  virtual scoped_refptr<FontData> GetFontData(const FontDescription&,
+                                              const FontFamily&) = 0;
 
   // TODO(crbug.com/542629): The String variant of this method should be
   // replaced with a better approach, now that we only have complex text.
@@ -92,7 +92,7 @@ class PLATFORM_EXPORT FontSelector : pub
   virtual void ReportFontLookupByUniqueOrFamilyName(
       const AtomicString& name,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) = 0;
+      scoped_refptr<SimpleFontData> resulting_font_data) = 0;
 
   // Called whenever a page attempts to find a local font based on a name. This
   // only includes lookups where the name is allowed to match PostScript names
@@ -100,7 +100,7 @@ class PLATFORM_EXPORT FontSelector : pub
   virtual void ReportFontLookupByUniqueNameOnly(
       const AtomicString& name,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data,
+      scoped_refptr<SimpleFontData> resulting_font_data,
       bool is_loading_fallback = false) = 0;
 
   // Called whenever a page attempts to find a local font based on a fallback
@@ -109,12 +109,12 @@ class PLATFORM_EXPORT FontSelector : pub
       UChar32 fallback_character,
       FontFallbackPriority fallback_priority,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) = 0;
+      scoped_refptr<SimpleFontData> resulting_font_data) = 0;
 
   // Called whenever a page attempts to find a last-resort font.
   virtual void ReportLastResortFallbackFontLookup(
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) = 0;
+      scoped_refptr<SimpleFontData> resulting_font_data) = 0;
 
   virtual void ReportNotDefGlyph() const = 0;
 
--- a/third_party/blink/renderer/platform/fonts/fuchsia/font_cache_fuchsia.cc
+++ b/third_party/blink/renderer/platform/fonts/fuchsia/font_cache_fuchsia.cc
@@ -45,7 +45,7 @@ void FontCache::SetSystemFontFamily(cons
   MutableSystemFontFamily() = family_name;
 }
 
-const SimpleFontData* FontCache::PlatformFallbackFontForCharacter(
+scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
     const FontDescription& font_description,
     UChar32 character,
     const SimpleFontData* font_data_to_substitute,
@@ -67,12 +67,12 @@ const SimpleFontData* FontCache::Platfor
                           !typeface->isItalic() &&
                           font_description.SyntheticItalicAllowed();
 
-  const auto* font_data = MakeGarbageCollected<FontPlatformData>(
+  auto font_data = std::make_unique<FontPlatformData>(
       std::move(typeface), std::string(), font_description.EffectiveFontSize(),
       synthetic_bold, synthetic_italic, font_description.TextRendering(),
       ResolvedFontFeatures(), font_description.Orientation());
 
-  return FontDataFromFontPlatformData(font_data);
+  return FontDataFromFontPlatformData(font_data.get(), kDoNotRetain);
 }
 
 }  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
+++ b/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
@@ -62,7 +62,7 @@ bool FontCache::GetFontForCharacter(UCha
   }
 }
 
-const SimpleFontData* FontCache::PlatformFallbackFontForCharacter(
+scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter(
     const FontDescription& font_description,
     UChar32 c,
     const SimpleFontData*,
@@ -77,9 +77,11 @@ const SimpleFontData* FontCache::Platfor
     AtomicString family_name = GetFamilyNameForCharacter(
         font_manager_.get(), c, font_description, nullptr, fallback_priority);
     if (family_name.empty())
-      return GetLastResortFallbackFont(font_description);
-    return FontDataFromFontPlatformData(GetFontPlatformData(
-        font_description, FontFaceCreationParams(family_name)));
+      return GetLastResortFallbackFont(font_description, kDoNotRetain);
+    return FontDataFromFontPlatformData(
+        GetFontPlatformData(font_description,
+                            FontFaceCreationParams(family_name)),
+        kDoNotRetain);
   }
 
   if (fallback_priority == FontFallbackPriority::kEmojiEmoji) {
@@ -94,7 +96,7 @@ const SimpleFontData* FontCache::Platfor
   if (fallback_priority != FontFallbackPriority::kEmojiEmoji &&
       (font_description.Style() == kItalicSlopeValue ||
        font_description.Weight() >= kBoldThreshold)) {
-    const SimpleFontData* font_data =
+    scoped_refptr<SimpleFontData> font_data =
         FallbackOnStandardFontStyle(font_description, c);
     if (font_data)
       return font_data;
@@ -137,16 +139,16 @@ const SimpleFontData* FontCache::Platfor
     description.SetStyle(kNormalSlopeValue);
   }
 
-  const FontPlatformData* substitute_platform_data =
+  FontPlatformData* substitute_platform_data =
       GetFontPlatformData(description, creation_params);
   if (!substitute_platform_data)
     return nullptr;
 
-  FontPlatformData* platform_data =
-      MakeGarbageCollected<FontPlatformData>(*substitute_platform_data);
+  std::unique_ptr<FontPlatformData> platform_data(
+      new FontPlatformData(*substitute_platform_data));
   platform_data->SetSyntheticBold(should_set_synthetic_bold);
   platform_data->SetSyntheticItalic(should_set_synthetic_italic);
-  return FontDataFromFontPlatformData(platform_data);
+  return FontDataFromFontPlatformData(platform_data.get(), kDoNotRetain);
 }
 
 }  // namespace blink
--- a/third_party/blink/renderer/platform/fonts/segmented_font_data.h
+++ b/third_party/blink/renderer/platform/fonts/segmented_font_data.h
@@ -28,7 +28,6 @@
 
 #include "third_party/blink/renderer/platform/fonts/font_data.h"
 #include "third_party/blink/renderer/platform/fonts/font_data_for_range_set.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
@@ -38,21 +37,20 @@ class SimpleFontData;
 
 class PLATFORM_EXPORT SegmentedFontData : public FontData {
  public:
-  SegmentedFontData() = default;
-
-  void Trace(Visitor* visitor) const override {
-    visitor->Trace(faces_);
-    FontData::Trace(visitor);
+  static scoped_refptr<SegmentedFontData> Create() {
+    return base::AdoptRef(new SegmentedFontData);
   }
 
-  void AppendFace(FontDataForRangeSet* font_data_for_range_set) {
+  void AppendFace(scoped_refptr<FontDataForRangeSet> font_data_for_range_set) {
     faces_.push_back(std::move(font_data_for_range_set));
   }
   unsigned NumFaces() const { return faces_.size(); }
-  FontDataForRangeSet* FaceAt(unsigned i) const { return faces_[i].Get(); }
+  scoped_refptr<FontDataForRangeSet> FaceAt(unsigned i) const { return faces_[i]; }
   bool ContainsCharacter(UChar32) const;
 
  private:
+  SegmentedFontData() = default;
+
   const SimpleFontData* FontDataForCharacter(UChar32) const override;
 
   bool IsCustomFont() const override;
@@ -61,7 +59,7 @@ class PLATFORM_EXPORT SegmentedFontData
   bool IsSegmented() const override;
   bool ShouldSkipDrawing() const override;
 
-  HeapVector<Member<FontDataForRangeSet>, 1> faces_;
+  Vector<scoped_refptr<FontDataForRangeSet>, 1> faces_;
 };
 
 template <>
--- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
@@ -127,7 +127,7 @@ Vector<double> CachingWordShaper::Indivi
                                             total_width);
 }
 
-HeapVector<ShapeResult::RunFontData> CachingWordShaper::GetRunFontData(
+Vector<ShapeResult::RunFontData> CachingWordShaper::GetRunFontData(
     const TextRun& run) const {
   ShapeResultBuffer buffer;
   ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer);
--- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
@@ -26,6 +26,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CACHING_WORD_SHAPER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CACHING_WORD_SHAPER_H_
 
+#include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
 #include "third_party/blink/renderer/platform/text/text_run.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -59,7 +60,7 @@ class PLATFORM_EXPORT CachingWordShaper
   CharacterRange GetCharacterRange(const TextRun&, unsigned from, unsigned to);
   Vector<double> IndividualCharacterAdvances(const TextRun&);
 
-  HeapVector<ShapeResult::RunFontData> GetRunFontData(const TextRun&) const;
+  Vector<ShapeResult::RunFontData> GetRunFontData(const TextRun&) const;
 
   GlyphData EmphasisMarkGlyphData(const TextRun&) const;
 
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
@@ -65,8 +65,7 @@
 
 namespace blink {
 
-HarfBuzzFace::HarfBuzzFace(const FontPlatformData* platform_data,
-                           uint64_t unique_id)
+HarfBuzzFace::HarfBuzzFace(FontPlatformData* platform_data, uint64_t unique_id)
     : platform_data_(platform_data), unique_id_(unique_id) {
   HbFontCacheEntry* const cache_entry =
       FontGlobalContext::GetHarfBuzzFontCache().RefOrNew(unique_id_,
@@ -79,9 +78,6 @@ HarfBuzzFace::~HarfBuzzFace() {
   FontGlobalContext::GetHarfBuzzFontCache().Remove(unique_id_);
 }
 
-void HarfBuzzFace::Trace(Visitor* visitor) const {
-  visitor->Trace(platform_data_);
-}
 
 bool& GetIgnoreVariationSelectors() {
   DEFINE_THREAD_SAFE_STATIC_LOCAL(WTF::ThreadSpecific<bool>,
@@ -486,8 +482,7 @@ static hb_blob_t* HarfBuzzSkiaGetTable(h
 }
 
 // TODO(yosin): We should move |CreateFace()| to "harfbuzz_font_cache.cc".
-static hb::unique_ptr<hb_face_t> CreateFace(
-    const FontPlatformData* platform_data) {
+static hb::unique_ptr<hb_face_t> CreateFace(FontPlatformData* platform_data) {
   hb::unique_ptr<hb_face_t> face;
 
   sk_sp<SkTypeface> typeface = sk_ref_sp(platform_data->Typeface());
@@ -535,9 +530,8 @@ static scoped_refptr<HbFontCacheEntry> C
   return cache_entry;
 }
 
-HbFontCacheEntry* HarfBuzzFontCache::RefOrNew(
-    uint64_t unique_id,
-    const FontPlatformData* platform_data) {
+HbFontCacheEntry* HarfBuzzFontCache::RefOrNew(uint64_t unique_id,
+                                              FontPlatformData* platform_data) {
   const auto& result = font_map_.insert(unique_id, nullptr);
   if (result.is_new_entry) {
     hb::unique_ptr<hb_face_t> face = CreateFace(platform_data);
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h
@@ -34,11 +34,10 @@
 #include "third_party/blink/renderer/platform/fonts/glyph.h"
 #include "third_party/blink/renderer/platform/fonts/typesetting_features.h"
 #include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 #include "third_party/blink/renderer/platform/wtf/text/character_names.h"
 
 #include <hb.h>
@@ -52,16 +51,18 @@ struct HarfBuzzFontData;
 
 // |HarfBuzzFace| is a thread specific data associated to |FontPlatformData|,
 // hold by |HarfBuzzFontCache|.
-class PLATFORM_EXPORT HarfBuzzFace final
-    : public GarbageCollected<HarfBuzzFace> {
+class PLATFORM_EXPORT HarfBuzzFace final : public RefCounted<HarfBuzzFace> {
+  USING_FAST_MALLOC(HarfBuzzFace);
  public:
-  HarfBuzzFace(const FontPlatformData* platform_data, uint64_t);
+  static scoped_refptr<HarfBuzzFace> Create(FontPlatformData* platform_data,
+                                            uint64_t unique_id) {
+    return base::AdoptRef(new HarfBuzzFace(platform_data, unique_id));
+  }
+
   HarfBuzzFace(const HarfBuzzFace&) = delete;
   HarfBuzzFace& operator=(const HarfBuzzFace&) = delete;
   ~HarfBuzzFace();
 
-  void Trace(Visitor*) const;
-
   enum VerticalLayoutCallbacks { kPrepareForVerticalLayout, kNoVerticalLayout };
 
   // In order to support the restricting effect of unicode-range optionally a
@@ -97,10 +98,11 @@ class PLATFORM_EXPORT HarfBuzzFace final
   static void SetIgnoreVariationSelectors(bool value);
 
  private:
+  HarfBuzzFace(FontPlatformData* platform_data, uint64_t);
 
   void PrepareHarfBuzzFontData();
 
-  Member<const FontPlatformData> platform_data_;
+  FontPlatformData* const platform_data_;
   const uint64_t unique_id_;
   // TODO(crbug.com/1489080): When briefly given MiraclePtr protection,
   // these members were both found dangling.
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
@@ -49,7 +49,7 @@ class HarfBuzzFontCache final {
   ~HarfBuzzFontCache();
 
   HbFontCacheEntry* RefOrNew(uint64_t unique_id,
-                             const FontPlatformData* platform_data);
+                             FontPlatformData* platform_data);
   void Remove(uint64_t unique_id);
 
  private:
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -853,7 +853,7 @@ void HarfBuzzShaper::ShapeSegment(
     fallback_chars_hint.ReserveInitialCapacity(range_data->end -
                                                range_data->start);
   }
-  FontDataForRangeSet* current_font_data_for_range_set = nullptr;
+  scoped_refptr<FontDataForRangeSet> current_font_data_for_range_set;
   FallbackFontStage fallback_stage = kIntermediate;
   while (!range_data->reshape_queue.empty()) {
     ReshapeQueueItem current_queue_item = range_data->reshape_queue.TakeFirst();
@@ -934,7 +934,7 @@ void HarfBuzzShaper::ShapeSegment(
     if (needs_caps_handling) {
       case_map_intend = caps_support.NeedsCaseChange(small_caps_behavior);
       if (caps_support.NeedsSyntheticFont(small_caps_behavior)) {
-        adjusted_font = font_data->SmallCapsFontData(font_description);
+        adjusted_font = font_data->SmallCapsFontData(font_description).get();
       }
     }
 
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -79,10 +79,9 @@ ASSERT_SIZE(ShapeResult::RunInfo, SameSi
 
 struct SameSizeAsShapeResult {
   float width;
-  UntracedMember<void*> deprecated_ink_bounds_;
-  Vector<int> runs_;
-  Vector<int> character_position_;
-  UntracedMember<void*> primary_font_;
+  UntracedMember<void*> member;
+  Vector<int> vectors[2];
+  void *pointer;
   unsigned start_index_;
   unsigned num_characters_;
   unsigned bitfields : 32;
@@ -396,7 +395,7 @@ void ShapeResult::RunInfo::CharacterInde
   }
 }
 
-ShapeResult::ShapeResult(const SimpleFontData* font_data,
+ShapeResult::ShapeResult(scoped_refptr<const SimpleFontData> font_data,
                          unsigned start_index,
                          unsigned num_characters,
                          TextDirection direction)
@@ -432,7 +431,6 @@ void ShapeResult::Trace(Visitor* visitor
   visitor->Trace(deprecated_ink_bounds_);
   visitor->Trace(runs_);
   visitor->Trace(character_position_);
-  visitor->Trace(primary_font_);
 }
 
 size_t ShapeResult::ByteSize() const {
@@ -732,10 +730,10 @@ bool ShapeResult::HasFallbackFonts(const
   return false;
 }
 
-void ShapeResult::GetRunFontData(HeapVector<RunFontData>* font_data) const {
+void ShapeResult::GetRunFontData(Vector<RunFontData>* font_data) const {
   for (const auto& run : runs_) {
     font_data->push_back(
-        RunFontData({run->font_data_.Get(), run->glyph_data_.size()}));
+        RunFontData({run->font_data_.get(), run->glyph_data_.size()}));
   }
 }
 
@@ -750,7 +748,7 @@ float ShapeResult::ForEachGlyphImpl(floa
   for (const auto& glyph_data : run.glyph_data_) {
     glyph_callback(context, run.start_index_ + glyph_data.character_index,
                    glyph_data.glyph, *glyph_offsets, total_advance,
-                   is_horizontal, run.canvas_rotation_, run.font_data_.Get());
+                   is_horizontal, run.canvas_rotation_, run.font_data_.get());
     total_advance += glyph_data.advance;
     ++glyph_offsets;
   }
@@ -785,7 +783,7 @@ float ShapeResult::ForEachGlyphImpl(floa
   auto total_advance = initial_advance;
   unsigned run_start = run.start_index_ + index_offset;
   bool is_horizontal = HB_DIRECTION_IS_HORIZONTAL(run.direction_);
-  const SimpleFontData* font_data = run.font_data_.Get();
+  const SimpleFontData* font_data = run.font_data_.get();
 
   if (run.IsLtr()) {  // Left-to-right
     for (const auto& glyph_data : run.glyph_data_) {
@@ -1738,7 +1736,7 @@ unsigned ShapeResult::CopyRangeInternal(
 ShapeResult* ShapeResult::SubRange(unsigned start_offset,
                                    unsigned end_offset) const {
   ShapeResult* sub_range =
-      MakeGarbageCollected<ShapeResult>(primary_font_.Get(), 0, 0, Direction());
+      MakeGarbageCollected<ShapeResult>(primary_font_.get(), 0, 0, Direction());
   CopyRange(start_offset, end_offset, sub_range);
   return sub_range;
 }
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -136,7 +136,7 @@ typedef void (*GraphemeClusterCallback)(
 
 class PLATFORM_EXPORT ShapeResult : public GarbageCollected<ShapeResult> {
  public:
-  ShapeResult(const SimpleFontData*,
+  ShapeResult(scoped_refptr<const SimpleFontData>,
               unsigned start_index,
               unsigned num_characters,
               TextDirection);
@@ -149,7 +149,7 @@ class PLATFORM_EXPORT ShapeResult : publ
   void Trace(Visitor*) const;
 
   static ShapeResult* CreateEmpty(const ShapeResult& other) {
-    return MakeGarbageCollected<ShapeResult>(other.primary_font_.Get(), 0, 0,
+    return MakeGarbageCollected<ShapeResult>(other.primary_font_, 0, 0,
                                              other.Direction());
   }
   static const ShapeResult* CreateForTabulationCharacters(
@@ -181,7 +181,7 @@ class PLATFORM_EXPORT ShapeResult : publ
   LayoutUnit SnappedWidth() const { return LayoutUnit::FromFloatCeil(width_); }
   unsigned NumCharacters() const { return num_characters_; }
   unsigned NumGlyphs() const { return num_glyphs_; }
-  const SimpleFontData* PrimaryFont() const { return primary_font_.Get(); }
+  const SimpleFontData* PrimaryFont() const { return primary_font_.get(); }
   bool HasFallbackFonts(const SimpleFontData* primary_font) const;
 
   // TODO(eae): Remove start_x and return value once ShapeResultBuffer has been
@@ -352,12 +352,10 @@ class PLATFORM_EXPORT ShapeResult : publ
 
   // Computes the list of fonts along with the number of glyphs for each font.
   struct RunFontData {
-    DISALLOW_NEW();
-    void Trace(Visitor* visitor) const { visitor->Trace(font_data_); }
-    Member<SimpleFontData> font_data_;
+    SimpleFontData* font_data_;
     wtf_size_t glyph_count_;
   };
-  void GetRunFontData(HeapVector<RunFontData>* font_data) const;
+  void GetRunFontData(Vector<RunFontData>* font_data) const;
 
   // Iterates over, and calls the specified callback function, for all the
   // glyphs. Also tracks (and returns) a seeded total advance.
@@ -517,7 +515,7 @@ class PLATFORM_EXPORT ShapeResult : publ
   // index to x-position and O(log n) time, using binary search, from
   // x-position to character index.
   mutable HeapVector<ShapeResultCharacterData> character_position_;
-  Member<const SimpleFontData> primary_font_;
+  scoped_refptr<const SimpleFontData> primary_font_;
 
   unsigned start_index_ = 0;
   unsigned num_characters_ = 0;
@@ -572,6 +570,5 @@ PLATFORM_EXPORT std::ostream& operator<<
 }  // namespace blink
 
 WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::ShapeResult::ShapeRange)
-WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::ShapeResult::RunFontData)
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_H_
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
@@ -249,8 +249,8 @@ int ShapeResultBuffer::OffsetForPosition
   return total_offset;
 }
 
-HeapVector<ShapeResult::RunFontData> ShapeResultBuffer::GetRunFontData() const {
-  HeapVector<ShapeResult::RunFontData> font_data;
+Vector<ShapeResult::RunFontData> ShapeResultBuffer::GetRunFontData() const {
+  Vector<ShapeResult::RunFontData> font_data;
   for (const auto& result : results_)
     result->GetRunFontData(&font_data);
   return font_data;
@@ -264,9 +264,10 @@ GlyphData ShapeResultBuffer::EmphasisMar
       if (run->glyph_data_.IsEmpty())
         continue;
 
-      return GlyphData(run->glyph_data_[0].glyph,
-                       run->font_data_->EmphasisMarkFontData(font_description),
-                       run->CanvasRotation());
+      return GlyphData(
+          run->glyph_data_[0].glyph,
+          run->font_data_->EmphasisMarkFontData(font_description).get(),
+          run->CanvasRotation());
     }
   }
 
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_BUFFER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_BUFFER_H_
 
+#include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
@@ -47,7 +48,7 @@ class PLATFORM_EXPORT ShapeResultBuffer
                                              TextDirection,
                                              float total_width) const;
 
-  HeapVector<ShapeResult::RunFontData> GetRunFontData() const;
+  Vector<ShapeResult::RunFontData> GetRunFontData() const;
 
   GlyphData EmphasisMarkGlyphData(const FontDescription&) const;
 
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -79,7 +79,7 @@ struct ShapeResult::RunInfo final
         direction_(other.direction_),
         canvas_rotation_(other.canvas_rotation_) {}
 
-  void Trace(Visitor* visitor) const { visitor->Trace(font_data_); }
+  void Trace(Visitor*) const {}
 
   unsigned NumGlyphs() const { return glyph_data_.size(); }
   bool IsLtr() const { return HB_DIRECTION_IS_FORWARD(direction_); }
@@ -130,7 +130,7 @@ struct ShapeResult::RunInfo final
       return nullptr;
 
     auto* run = MakeGarbageCollected<RunInfo>(
-        font_data_.Get(), direction_, canvas_rotation_, script_,
+        font_data_.get(), direction_, canvas_rotation_, script_,
         start_index_ + start, number_of_glyphs, number_of_characters);
 
     run->glyph_data_.CopyFromRange(glyphs);
@@ -154,7 +154,7 @@ struct ShapeResult::RunInfo final
       return nullptr;
     DCHECK_LT(start_index_, other.start_index_);
     auto* run = MakeGarbageCollected<RunInfo>(
-        font_data_.Get(), direction_, canvas_rotation_, script_, start_index_,
+        font_data_.get(), direction_, canvas_rotation_, script_, start_index_,
         glyph_data_.size() + other.glyph_data_.size(),
         num_characters_ + other.num_characters_);
     // Note: We populate |graphemes_| on demand, e.g. hit testing.
@@ -374,7 +374,7 @@ struct ShapeResult::RunInfo final
   }
 
   GlyphDataCollection glyph_data_;
-  Member<SimpleFontData> font_data_;
+  scoped_refptr<SimpleFontData> font_data_;
 
   // graphemes_[i] is the number of graphemes up to (and including) the ith
   // character in the run.
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.cc
@@ -54,7 +54,7 @@ float ShapeResultTestInfo::AdvanceForTes
 
 SimpleFontData* ShapeResultTestInfo::FontDataForTesting(
     unsigned run_index) const {
-  return runs_[run_index]->font_data_.Get();
+  return runs_[run_index]->font_data_.get();
 }
 
 Vector<unsigned> ShapeResultTestInfo::CharacterIndexesForTesting() const {
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
@@ -28,9 +28,7 @@ ShapeResultView::RunInfoPart::RunInfoPar
       start_index_(start_index),
       offset_(offset),
       num_characters_(num_characters),
-      width_(width) {
-  static_assert(std::is_trivially_destructible<RunInfoPart>::value, "");
-}
+      width_(width) {}
 
 void ShapeResultView::RunInfoPart::Trace(Visitor* visitor) const {
   visitor->Trace(run_);
@@ -74,10 +72,7 @@ unsigned ShapeResultView::CharacterIndex
 // |InitData| provides values of const member variables of |ShapeResultView|
 // for constructor.
 struct ShapeResultView::InitData {
-  STACK_ALLOCATED();
-
- public:
-  const SimpleFontData* primary_font = nullptr;
+  scoped_refptr<const SimpleFontData> primary_font;
   unsigned start_index = 0;
   unsigned char_index_offset = 0;
   TextDirection direction = TextDirection::kLtr;
@@ -188,7 +183,7 @@ ShapeResult* ShapeResultView::CreateShap
   new_result->runs_.ReserveInitialCapacity(parts_.size());
   for (const auto& part : RunsOrParts()) {
     auto* new_run = MakeGarbageCollected<ShapeResult::RunInfo>(
-        part.run_->font_data_.Get(), part.run_->direction_,
+        part.run_->font_data_.get(), part.run_->direction_,
         part.run_->canvas_rotation_, part.run_->script_, part.start_index_,
         part.NumGlyphs(), part.num_characters_);
     new_run->glyph_data_.CopyFromRange(part.range_);
@@ -364,21 +359,21 @@ unsigned ShapeResultView::PreviousSafeTo
 }
 
 void ShapeResultView::GetRunFontData(
-    HeapVector<ShapeResult::RunFontData>* font_data) const {
+    Vector<ShapeResult::RunFontData>* font_data) const {
   for (const auto& part : RunsOrParts()) {
     font_data->push_back(ShapeResult::RunFontData(
-        {part.run_->font_data_.Get(),
+        {part.run_->font_data_.get(),
          static_cast<wtf_size_t>(part.end() - part.begin())}));
   }
 }
 
 void ShapeResultView::FallbackFonts(
-    HeapHashSet<Member<const SimpleFontData>>* fallback) const {
+    HashSet<const SimpleFontData*>* fallback) const {
   DCHECK(fallback);
   DCHECK(primary_font_);
   for (const auto& part : RunsOrParts()) {
     if (part.run_->font_data_ && part.run_->font_data_ != primary_font_) {
-      fallback->insert(part.run_->font_data_.Get());
+      fallback->insert(part.run_->font_data_.get());
     }
   }
 }
@@ -392,7 +387,7 @@ float ShapeResultView::ForEachGlyphImpl(
   const auto& run = part.run_;
   auto total_advance = initial_advance;
   bool is_horizontal = HB_DIRECTION_IS_HORIZONTAL(run->direction_);
-  const SimpleFontData* font_data = run->font_data_.Get();
+  const SimpleFontData* font_data = run->font_data_.get();
   const unsigned character_index_offset_for_glyph_data =
       CharacterIndexOffsetForGlyphData(part);
   for (const auto& glyph_data : part) {
@@ -435,7 +430,7 @@ float ShapeResultView::ForEachGlyphImpl(
   auto total_advance = initial_advance;
   const auto& run = part.run_;
   bool is_horizontal = HB_DIRECTION_IS_HORIZONTAL(run->direction_);
-  const SimpleFontData* font_data = run->font_data_.Get();
+  const SimpleFontData* font_data = run->font_data_.get();
   const unsigned character_index_offset_for_glyph_data =
       CharacterIndexOffsetForGlyphData(part);
   if (run->IsLtr()) {  // Left-to-right
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
@@ -10,7 +10,6 @@
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/text/text_direction.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -111,10 +110,7 @@ class PLATFORM_EXPORT ShapeResultView fi
   ShapeResultView& operator=(const ShapeResultView&) = delete;
   ~ShapeResultView() = default;
 
-  void Trace(Visitor* visitor) const {
-    visitor->Trace(parts_);
-    visitor->Trace(primary_font_);
-  }
+  void Trace(Visitor* visitor) const { visitor->Trace(parts_); }
 
   ShapeResult* CreateShapeResult() const;
 
@@ -130,7 +126,7 @@ class PLATFORM_EXPORT ShapeResultView fi
   bool IsLtr() const { return blink::IsLtr(Direction()); }
   bool IsRtl() const { return blink::IsRtl(Direction()); }
   bool HasVerticalOffsets() const { return has_vertical_offsets_; }
-  void FallbackFonts(HeapHashSet<Member<const SimpleFontData>>* fallback) const;
+  void FallbackFonts(HashSet<const SimpleFontData*>* fallback) const;
 
   unsigned PreviousSafeToBreakOffset(unsigned index) const;
 
@@ -155,8 +151,10 @@ class PLATFORM_EXPORT ShapeResultView fi
   // bounds.
   gfx::RectF ComputeInkBounds() const;
 
-  const SimpleFontData* PrimaryFont() const { return primary_font_.Get(); }
-  void GetRunFontData(HeapVector<ShapeResult::RunFontData>*) const;
+  scoped_refptr<const SimpleFontData> PrimaryFont() const {
+    return primary_font_;
+  }
+  void GetRunFontData(Vector<ShapeResult::RunFontData>*) const;
 
   void ExpandRangeToIncludePartialGlyphs(unsigned* from, unsigned* to) const;
 
@@ -288,8 +286,7 @@ class PLATFORM_EXPORT ShapeResultView fi
 
   unsigned StartIndexOffsetForRun() const { return char_index_offset_; }
 
-  HeapVector<RunInfoPart, 1> parts_;
-  Member<const SimpleFontData> const primary_font_;
+  scoped_refptr<const SimpleFontData> const primary_font_;
 
   const unsigned start_index_;
 
@@ -311,6 +308,8 @@ class PLATFORM_EXPORT ShapeResultView fi
   // with ShapeResult::SubRange
   const unsigned char_index_offset_;
 
+  HeapVector<RunInfoPart, 1> parts_;
+
  private:
   friend class ShapeResult;
 
--- a/third_party/blink/renderer/platform/fonts/simple_font_data.cc
+++ b/third_party/blink/renderer/platform/fonts/simple_font_data.cc
@@ -76,14 +76,14 @@ constexpr int32_t kFontObjectsMemoryCons
 constexpr int32_t kFontObjectsMemoryConsumption = 2128;
 #endif
 
-SimpleFontData::SimpleFontData(const FontPlatformData* platform_data,
-                               const CustomFontData* custom_data,
+SimpleFontData::SimpleFontData(const FontPlatformData& platform_data,
+                               scoped_refptr<CustomFontData> custom_data,
                                bool subpixel_ascent_descent,
                                const FontMetricsOverride& metrics_override)
     : platform_data_(platform_data),
-      font_(platform_data->size() ? platform_data->CreateSkFont()
+      font_(platform_data_.size() ? platform_data.CreateSkFont()
                                   : skia::DefaultFont()),
-      custom_font_data_(custom_data) {
+      custom_font_data_(std::move(custom_data)) {
   // Every time new SimpleFontData instance is created, Skia will ask
   // FreeType to get the metrics for glyphs by invoking
   // af_face_globals_get_metrics. There FT will allocate style_metrics_size
@@ -111,7 +111,7 @@ SimpleFontData::~SimpleFontData() {
 
 void SimpleFontData::PlatformInit(bool subpixel_ascent_descent,
                                   const FontMetricsOverride& metrics_override) {
-  if (!platform_data_->size()) {
+  if (!platform_data_.size()) {
     font_metrics_.Reset();
     avg_char_width_ = 0;
     max_char_width_ = 0;
@@ -126,7 +126,7 @@ void SimpleFontData::PlatformInit(bool s
   float descent;
 
   FontMetrics::AscentDescentWithHacks(
-      ascent, descent, *platform_data_, font_, subpixel_ascent_descent,
+      ascent, descent, platform_data_, font_, subpixel_ascent_descent,
       metrics_override.ascent_override, metrics_override.descent_override);
 
   font_metrics_.SetAscent(ascent);
@@ -164,7 +164,7 @@ void SimpleFontData::PlatformInit(bool s
 
   float line_gap;
   if (metrics_override.line_gap_override) {
-    line_gap = *metrics_override.line_gap_override * platform_data_->size();
+    line_gap = *metrics_override.line_gap_override * platform_data_.size();
   } else {
     line_gap = SkScalarToFloat(metrics.fLeading);
   }
@@ -261,39 +261,45 @@ bool SimpleFontData::IsSegmented() const
   return false;
 }
 
-SimpleFontData* SimpleFontData::SmallCapsFontData(
+scoped_refptr<SimpleFontData> SimpleFontData::SmallCapsFontData(
     const FontDescription& font_description) const {
-  if (!small_caps_) {
-    small_caps_ =
+  if (!derived_font_data_)
+    derived_font_data_ = std::make_unique<DerivedFontData>();
+  if (!derived_font_data_->small_caps) {
+    derived_font_data_->small_caps =
         CreateScaledFontData(font_description, kSmallCapsFontSizeMultiplier);
   }
-  return small_caps_;
+
+  return derived_font_data_->small_caps;
 }
 
-SimpleFontData* SimpleFontData::EmphasisMarkFontData(
+scoped_refptr<SimpleFontData> SimpleFontData::EmphasisMarkFontData(
     const FontDescription& font_description) const {
-  if (!emphasis_mark_) {
-    emphasis_mark_ =
+  if (!derived_font_data_)
+    derived_font_data_ = std::make_unique<DerivedFontData>();
+  if (!derived_font_data_->emphasis_mark) {
+    derived_font_data_->emphasis_mark =
         CreateScaledFontData(font_description, kEmphasisMarkFontSizeMultiplier);
   }
-  return emphasis_mark_;
+
+  return derived_font_data_->emphasis_mark;
 }
 
-SimpleFontData* SimpleFontData::CreateScaledFontData(
+scoped_refptr<SimpleFontData> SimpleFontData::CreateScaledFontData(
     const FontDescription& font_description,
     float scale_factor) const {
   const float scaled_size =
       lroundf(font_description.ComputedSize() * scale_factor);
-  return MakeGarbageCollected<SimpleFontData>(
-      MakeGarbageCollected<FontPlatformData>(*platform_data_, scaled_size),
-      IsCustomFont() ? MakeGarbageCollected<CustomFontData>() : nullptr);
+  return SimpleFontData::Create(
+      FontPlatformData(platform_data_, scaled_size),
+      IsCustomFont() ? CustomFontData::Create() : nullptr);
 }
 
-SimpleFontData* SimpleFontData::MetricsOverriddenFontData(
+scoped_refptr<SimpleFontData> SimpleFontData::MetricsOverriddenFontData(
     const FontMetricsOverride& metrics_override) const {
-  return MakeGarbageCollected<SimpleFontData>(
-      platform_data_, custom_font_data_, false /* subpixel_ascent_descent */,
-      metrics_override);
+  return base::AdoptRef(new SimpleFontData(platform_data_, custom_font_data_,
+                                           false /* subpixel_ascent_descent */,
+                                           metrics_override));
 }
 
 // Internal leadings can be distributed to ascent and descent.
@@ -347,7 +353,7 @@ static std::pair<int16_t, int16_t> TypoA
 
 void SimpleFontData::ComputeNormalizedTypoAscentAndDescent() const {
   // Compute em height metrics from OS/2 sTypoAscender and sTypoDescender.
-  SkTypeface* typeface = platform_data_->Typeface();
+  SkTypeface* typeface = platform_data_.Typeface();
   auto [typo_ascender, typo_descender] = TypoAscenderAndDescender(typeface);
   if (typo_ascender > 0 &&
       TrySetNormalizedTypoAscentAndDescent(typo_ascender, typo_descender)) {
@@ -434,7 +440,7 @@ const std::optional<float>& SimpleFontDa
     }
 
     // Compute vertical advance if the orientation is `kVerticalUpright`.
-    const HarfBuzzFace* hb_face = platform_data_->GetHarfBuzzFace();
+    const HarfBuzzFace* hb_face = platform_data_.GetHarfBuzzFace();
     const OpenTypeVerticalData& vertical_data = hb_face->VerticalData();
     ideographic_inline_size_ = vertical_data.AdvanceHeight(cjk_water_glyph);
   });
@@ -462,9 +468,8 @@ const HanKerning::FontData& SimpleFontDa
 }
 
 gfx::RectF SimpleFontData::PlatformBoundsForGlyph(Glyph glyph) const {
-  if (!platform_data_->size()) {
+  if (!platform_data_.size())
     return gfx::RectF();
-  }
 
   static_assert(sizeof(glyph) == 2, "Glyph id should not be truncated.");
 
@@ -477,18 +482,16 @@ void SimpleFontData::BoundsForGlyphs(con
                                      Vector<SkRect, 256>* bounds) const {
   DCHECK_EQ(glyphs.size(), bounds->size());
 
-  if (!platform_data_->size()) {
+  if (!platform_data_.size())
     return;
-  }
 
   DCHECK_EQ(bounds->size(), glyphs.size());
   SkFontGetBoundsForGlyphs(font_, glyphs, bounds->data());
 }
 
 float SimpleFontData::WidthForGlyph(Glyph glyph) const {
-  if (!platform_data_->size()) {
+  if (!platform_data_.size())
     return 0;
-  }
 
   static_assert(sizeof(glyph) == 2, "Glyph id should not be truncated.");
 
--- a/third_party/blink/renderer/platform/fonts/simple_font_data.h
+++ b/third_party/blink/renderer/platform/fonts/simple_font_data.h
@@ -40,7 +40,6 @@
 #include "third_party/blink/renderer/platform/fonts/glyph.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/han_kerning.h"
 #include "third_party/blink/renderer/platform/fonts/typesetting_features.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -75,18 +74,12 @@ class FontDescription;
 class PLATFORM_EXPORT SimpleFontData final : public FontData {
  public:
   // Used to create platform fonts.
-  SimpleFontData(
-      const FontPlatformData*,
-      const CustomFontData* custom_data = nullptr,
-      bool subpixel_ascent_descent = false,
-      const FontMetricsOverride& metrics_override = FontMetricsOverride());
-
-  void Trace(Visitor* visitor) const override {
-    visitor->Trace(platform_data_);
-    visitor->Trace(small_caps_);
-    visitor->Trace(emphasis_mark_);
-    visitor->Trace(custom_font_data_);
-    FontData::Trace(visitor);
+  static scoped_refptr<SimpleFontData> Create(
+      const FontPlatformData& platform_data,
+      scoped_refptr<CustomFontData> custom_data = nullptr,
+      bool subpixel_ascent_descent = false) {
+    return base::AdoptRef(new SimpleFontData(
+        platform_data, std::move(custom_data), subpixel_ascent_descent));
   }
 
   SimpleFontData(const SimpleFontData&) = delete;
@@ -95,11 +88,13 @@ class PLATFORM_EXPORT SimpleFontData fin
   SimpleFontData& operator=(const SimpleFontData&) = delete;
   SimpleFontData& operator=(const SimpleFontData&&) = delete;
 
-  const FontPlatformData& PlatformData() const { return *platform_data_; }
+  const FontPlatformData& PlatformData() const { return platform_data_; }
 
-  SimpleFontData* SmallCapsFontData(const FontDescription&) const;
-  SimpleFontData* EmphasisMarkFontData(const FontDescription&) const;
-  SimpleFontData* MetricsOverriddenFontData(const FontMetricsOverride&) const;
+  scoped_refptr<SimpleFontData> SmallCapsFontData(const FontDescription&) const;
+  scoped_refptr<SimpleFontData> EmphasisMarkFontData(
+      const FontDescription&) const;
+  scoped_refptr<SimpleFontData> MetricsOverriddenFontData(
+      const FontMetricsOverride&) const;
 
   FontMetrics& GetFontMetrics() { return font_metrics_; }
   const FontMetrics& GetFontMetrics() const { return font_metrics_; }
@@ -154,7 +149,7 @@ class PLATFORM_EXPORT SimpleFontData fin
 
   Glyph GlyphForCharacter(UChar32) const;
 
-  bool IsCustomFont() const override { return custom_font_data_; }
+  bool IsCustomFont() const override { return custom_font_data_.get(); }
   bool IsLoading() const override {
     return custom_font_data_ ? custom_font_data_->IsLoading() : false;
   }
@@ -169,16 +164,20 @@ class PLATFORM_EXPORT SimpleFontData fin
     return custom_font_data_ && custom_font_data_->ShouldSkipDrawing();
   }
 
-  const CustomFontData* GetCustomFontData() const {
-    return custom_font_data_.Get();
-  }
+  CustomFontData* GetCustomFontData() const { return custom_font_data_.get(); }
 
  private:
+  SimpleFontData(
+      const FontPlatformData&,
+      scoped_refptr<CustomFontData> custom_data,
+      bool subpixel_ascent_descent = false,
+      const FontMetricsOverride& metrics_override = FontMetricsOverride());
+
   void PlatformInit(bool subpixel_ascent_descent, const FontMetricsOverride&);
   void PlatformGlyphInit();
 
-  SimpleFontData* CreateScaledFontData(const FontDescription&,
-                                       float scale_factor) const;
+  scoped_refptr<SimpleFontData> CreateScaledFontData(const FontDescription&,
+                                              float scale_factor) const;
 
   void ComputeNormalizedTypoAscentAndDescent() const;
   bool TrySetNormalizedTypoAscentAndDescent(float ascent, float descent) const;
@@ -187,17 +186,30 @@ class PLATFORM_EXPORT SimpleFontData fin
   float max_char_width_ = -1;
   float avg_char_width_ = -1;
 
-  Member<const FontPlatformData> platform_data_;
+  const FontPlatformData platform_data_;
   const SkFont font_;
 
   Glyph space_glyph_ = 0;
   float space_width_ = 0;
   Glyph zero_glyph_ = 0;
 
-  mutable Member<SimpleFontData> small_caps_;
-  mutable Member<SimpleFontData> emphasis_mark_;
+  struct DerivedFontData final {
+    USING_FAST_MALLOC(DerivedFontData);
+
+   public:
+    DerivedFontData() = default;
+    DerivedFontData(const DerivedFontData&) = delete;
+    DerivedFontData(DerivedFontData&&) = delete;
+    DerivedFontData& operator=(const DerivedFontData&) = delete;
+    DerivedFontData& operator=(DerivedFontData&&) = delete;
+
+    scoped_refptr<SimpleFontData> small_caps;
+    scoped_refptr<SimpleFontData> emphasis_mark;
+  };
+
+  mutable std::unique_ptr<DerivedFontData> derived_font_data_;
 
-  Member<const CustomFontData> custom_font_data_;
+  const scoped_refptr<CustomFontData> custom_font_data_;
 
   mutable std::once_flag ideographic_inline_size_once_;
   mutable std::once_flag ideographic_advance_width_once_;
--- a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
+++ b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
@@ -94,7 +94,7 @@ AtomicString FontCache::GetFamilyNameFor
 
 void FontCache::PlatformInit() {}
 
-const SimpleFontData* FontCache::FallbackOnStandardFontStyle(
+scoped_refptr<SimpleFontData> FontCache::FallbackOnStandardFontStyle(
     const FontDescription& font_description,
     UChar32 character) {
   FontDescription substitute_description(font_description);
@@ -103,26 +103,27 @@ const SimpleFontData* FontCache::Fallbac
 
   FontFaceCreationParams creation_params(
       substitute_description.Family().FamilyName());
-  const FontPlatformData* substitute_platform_data =
+  FontPlatformData* substitute_platform_data =
       GetFontPlatformData(substitute_description, creation_params);
   if (substitute_platform_data &&
       substitute_platform_data->FontContainsCharacter(character)) {
-    FontPlatformData* platform_data =
-        MakeGarbageCollected<FontPlatformData>(*substitute_platform_data);
-    platform_data->SetSyntheticBold(font_description.Weight() >=
-                                        kBoldThreshold &&
-                                    font_description.SyntheticBoldAllowed());
-    platform_data->SetSyntheticItalic(
-        font_description.Style() == kItalicSlopeValue &&
-        font_description.SyntheticItalicAllowed());
-    return FontDataFromFontPlatformData(platform_data);
+    FontPlatformData platform_data =
+        FontPlatformData(*substitute_platform_data);
+    platform_data.SetSyntheticBold(font_description.Weight() >=
+                                       kBoldThreshold &&
+                                   font_description.SyntheticBoldAllowed());
+    platform_data.SetSyntheticItalic(font_description.Style() ==
+                                         kItalicSlopeValue &&
+                                     font_description.SyntheticItalicAllowed());
+    return FontDataFromFontPlatformData(&platform_data, kDoNotRetain);
   }
 
   return nullptr;
 }
 
-const SimpleFontData* FontCache::GetLastResortFallbackFont(
-    const FontDescription& description) {
+scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
+    const FontDescription& description,
+    ShouldRetain should_retain) {
   const FontFaceCreationParams fallback_creation_params(
       GetFallbackFontFamily(description));
   const FontPlatformData* font_platform_data = GetFontPlatformData(
@@ -195,7 +196,7 @@ const SimpleFontData* FontCache::GetLast
 #endif
 
   DCHECK(font_platform_data);
-  return FontDataFromFontPlatformData(font_platform_data);
+  return FontDataFromFontPlatformData(font_platform_data, should_retain);
 }
 
 sk_sp<SkTypeface> FontCache::CreateTypeface(
@@ -238,7 +239,7 @@ sk_sp<SkTypeface> FontCache::CreateTypef
 }
 
 #if !BUILDFLAG(IS_WIN)
-const FontPlatformData* FontCache::CreateFontPlatformData(
+std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData(
     const FontDescription& font_description,
     const FontFaceCreationParams& creation_params,
     float font_size,
@@ -293,10 +294,11 @@ const FontPlatformData* FontCache::Creat
                 ->GetResolvedFontFeatures()
           : ResolvedFontFeatures();
 
-  FontPlatformData* font_platform_data = MakeGarbageCollected<FontPlatformData>(
-      typeface, name, font_size, synthetic_bold, synthetic_italic,
-      font_description.TextRendering(), resolved_font_features,
-      font_description.Orientation());
+  std::unique_ptr<FontPlatformData> font_platform_data =
+      std::make_unique<FontPlatformData>(
+          typeface, name, font_size, synthetic_bold, synthetic_italic,
+          font_description.TextRendering(), resolved_font_features,
+          font_description.Orientation());
 
   font_platform_data->SetAvoidEmbeddedBitmaps(
       BitmapGlyphsBlockList::ShouldAvoidEmbeddedBitmapsForTypeface(*typeface));
--- a/third_party/blink/renderer/platform/testing/font_test_helpers.cc
+++ b/third_party/blink/renderer/platform/testing/font_test_helpers.cc
@@ -43,26 +43,23 @@ class TestFontSelector : public FontSele
   }
   ~TestFontSelector() override = default;
 
-  FontData* GetFontData(const FontDescription& font_description,
-                        const FontFamily&) override {
+  scoped_refptr<FontData> GetFontData(const FontDescription& font_description,
+                                      const FontFamily&) override {
     FontSelectionCapabilities normal_capabilities(
         {kNormalWidthValue, kNormalWidthValue},
         {kNormalSlopeValue, kNormalSlopeValue},
         {kNormalWeightValue, kNormalWeightValue});
-    const FontPlatformData* platform_data =
-        custom_platform_data_->GetFontPlatformData(
-            font_description.EffectiveFontSize(),
-            font_description.AdjustedSpecifiedSize(),
-            font_description.IsSyntheticBold() &&
-                font_description.SyntheticBoldAllowed(),
-            font_description.IsSyntheticItalic() &&
-                font_description.SyntheticItalicAllowed(),
-            font_description.GetFontSelectionRequest(), normal_capabilities,
-            font_description.FontOpticalSizing(),
-            font_description.TextRendering(), {},
-            font_description.Orientation());
-    return MakeGarbageCollected<SimpleFontData>(
-        platform_data, MakeGarbageCollected<CustomFontData>());
+    FontPlatformData platform_data = custom_platform_data_->GetFontPlatformData(
+        font_description.EffectiveFontSize(),
+        font_description.AdjustedSpecifiedSize(),
+        font_description.IsSyntheticBold() &&
+            font_description.SyntheticBoldAllowed(),
+        font_description.IsSyntheticItalic() &&
+            font_description.SyntheticItalicAllowed(),
+        font_description.GetFontSelectionRequest(), normal_capabilities,
+        font_description.FontOpticalSizing(), font_description.TextRendering(),
+        {}, font_description.Orientation());
+    return SimpleFontData::Create(platform_data, CustomFontData::Create());
   }
 
   void WillUseFontData(const FontDescription&,
@@ -83,20 +80,20 @@ class TestFontSelector : public FontSele
   void ReportFontLookupByUniqueOrFamilyName(
       const AtomicString& name,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) override {}
+      scoped_refptr<SimpleFontData> resulting_font_data) override {}
   void ReportFontLookupByUniqueNameOnly(
       const AtomicString& name,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data,
+      scoped_refptr<SimpleFontData> resulting_font_data,
       bool is_loading_fallback = false) override {}
   void ReportFontLookupByFallbackCharacter(
       UChar32 hint,
       FontFallbackPriority fallback_priority,
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) override {}
+      scoped_refptr<SimpleFontData> resulting_font_data) override {}
   void ReportLastResortFallbackFontLookup(
       const FontDescription& font_description,
-      const SimpleFontData* resulting_font_data) override {}
+      scoped_refptr<SimpleFontData> resulting_font_data) override {}
   void ReportNotDefGlyph() const override {}
   void ReportEmojiSegmentGlyphCoverage(unsigned, unsigned) override {}
   ExecutionContext* GetExecutionContext() const override { return nullptr; }
--- a/tools/privacy_budget/font_indexer/font_indexer.cc
+++ b/tools/privacy_budget/font_indexer/font_indexer.cc
@@ -116,7 +116,7 @@ void FontIndexer::FontListHasLoaded(base
 bool FontIndexer::DoesFontHaveDigest(WTF::AtomicString name,
                                      blink::FontDescription font_description,
                                      int64_t digest) {
-  const blink::SimpleFontData* font_data =
+  scoped_refptr<blink::SimpleFontData> font_data =
       font_cache_->GetFontData(font_description, name);
   DCHECK(font_data);
   return blink::FontGlobalContext::Get()
@@ -170,7 +170,7 @@ void FontIndexer::PrintAllFontsWithName(
   // exists and for later comparison.
   int64_t default_font_digest;
   {
-    const blink::SimpleFontData* font_data =
+    scoped_refptr<blink::SimpleFontData> font_data =
         font_cache_->GetFontData(blink::FontDescription(), name);
     default_font_digest =
         font_data ? blink::FontGlobalContext::Get()
@@ -231,7 +231,7 @@ void FontIndexer::PrintAllFontsWithName(
       for (auto slope_pair : slopes) {
         font_description.SetStyle(slope_pair.first);
 
-        if (const blink::SimpleFontData* font_data =
+        if (scoped_refptr<blink::SimpleFontData> font_data =
                 font_cache_->GetFontData(font_description, name)) {
           uint64_t typeface_digest =
               blink::FontGlobalContext::Get()
openSUSE Build Service is sponsored by