Changeset 244315 in webkit


Ignore:
Timestamp:
Apr 15, 2019 5:51:04 PM (5 years ago)
Author:
mmaxfield@apple.com
Message:

[Cocoa] FontPlatformData objects aren't cached at all when using font-family:system-ui
https://bugs.webkit.org/show_bug.cgi?id=196846
<rdar://problem/49499971>

Reviewed by Simon Fraser and Darin Adler.

PerformanceTests:

  • Layout/system-ui-rebuild-emoji.html: Added.

Source/WebCore:

When adding the special codepath for system-ui to behave as an entire list of fonts rather than a single item,
I never added a cache for the FontPlatformData objects that codepath creates. The non-system-ui codepath already
has a cache in fontPlatformDataCache() in FontCache.cpp.

This patch causes a 16.8x performance improvement on the attached benchmark.

Test: PerformanceTests/Layout/system-ui-rebuild-emoji.html

  • page/cocoa/MemoryReleaseCocoa.mm:

(WebCore::platformReleaseMemory):

  • platform/graphics/cocoa/FontCacheCoreText.cpp:

(WebCore::invalidateFontCache):

  • platform/graphics/cocoa/FontFamilySpecificationCoreText.cpp:

(WebCore::FontFamilySpecificationKey::FontFamilySpecificationKey):
(WebCore::FontFamilySpecificationKey::operator== const):
(WebCore::FontFamilySpecificationKey::operator!= const):
(WebCore::FontFamilySpecificationKey::isHashTableDeletedValue const):
(WebCore::FontFamilySpecificationKey::computeHash const):
(WebCore::FontFamilySpecificationKeyHash::hash):
(WebCore::FontFamilySpecificationKeyHash::equal):
(WebCore::fontMap):
(WebCore::clearFontFamilySpecificationCoreTextCache):
(WebCore::FontFamilySpecificationCoreText::fontRanges const):

  • platform/graphics/cocoa/FontFamilySpecificationCoreText.h:
  • platform/graphics/mac/ComplexTextControllerCoreText.mm:

(WebCore::ComplexTextController::collectComplexTextRunsForCharacters):
(WebCore::safeCFEqual): Deleted.

Source/WTF:

  • wtf/RetainPtr.h:

(WTF::safeCFEqual):
(WTF::safeCFHash):

Location:
trunk
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/PerformanceTests/ChangeLog

    r243841 r244315  
     12019-04-15  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [Cocoa] FontPlatformData objects aren't cached at all when using font-family:system-ui
     4        https://bugs.webkit.org/show_bug.cgi?id=196846
     5        <rdar://problem/49499971>
     6
     7        Reviewed by Simon Fraser and Darin Adler.
     8
     9        * Layout/system-ui-rebuild-emoji.html: Added.
     10
    1112019-04-03  Myles C. Maxfield  <mmaxfield@apple.com>
    212
  • trunk/Source/WTF/ChangeLog

    r244289 r244315  
     12019-04-15  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [Cocoa] FontPlatformData objects aren't cached at all when using font-family:system-ui
     4        https://bugs.webkit.org/show_bug.cgi?id=196846
     5        <rdar://problem/49499971>
     6
     7        Reviewed by Simon Fraser and Darin Adler.
     8
     9        * wtf/RetainPtr.h:
     10        (WTF::safeCFEqual):
     11        (WTF::safeCFHash):
     12
    1132019-04-12  Ryosuke Niwa  <rniwa@webkit.org>
    214
  • trunk/Source/WTF/wtf/RetainPtr.h

    r239709 r244315  
    370370};
    371371
     372inline bool safeCFEqual(CFTypeRef a, CFTypeRef b)
     373{
     374    return (!a && !b) || (a && b && CFEqual(a, b));
     375}
     376
     377inline CFHashCode safeCFHash(CFTypeRef a)
     378{
     379    return a ? CFHash(a) : 0;
     380}
     381
    372382#ifdef __OBJC__
    373383template<typename T> T* dynamic_objc_cast(id object)
  • trunk/Source/WebCore/ChangeLog

    r244312 r244315  
     12019-04-15  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [Cocoa] FontPlatformData objects aren't cached at all when using font-family:system-ui
     4        https://bugs.webkit.org/show_bug.cgi?id=196846
     5        <rdar://problem/49499971>
     6
     7        Reviewed by Simon Fraser and Darin Adler.
     8
     9        When adding the special codepath for system-ui to behave as an entire list of fonts rather than a single item,
     10        I never added a cache for the FontPlatformData objects that codepath creates. The non-system-ui codepath already
     11        has a cache in fontPlatformDataCache() in FontCache.cpp.
     12
     13        This patch causes a 16.8x performance improvement on the attached benchmark.
     14
     15        Test: PerformanceTests/Layout/system-ui-rebuild-emoji.html
     16
     17        * page/cocoa/MemoryReleaseCocoa.mm:
     18        (WebCore::platformReleaseMemory):
     19        * platform/graphics/cocoa/FontCacheCoreText.cpp:
     20        (WebCore::invalidateFontCache):
     21        * platform/graphics/cocoa/FontFamilySpecificationCoreText.cpp:
     22        (WebCore::FontFamilySpecificationKey::FontFamilySpecificationKey):
     23        (WebCore::FontFamilySpecificationKey::operator== const):
     24        (WebCore::FontFamilySpecificationKey::operator!= const):
     25        (WebCore::FontFamilySpecificationKey::isHashTableDeletedValue const):
     26        (WebCore::FontFamilySpecificationKey::computeHash const):
     27        (WebCore::FontFamilySpecificationKeyHash::hash):
     28        (WebCore::FontFamilySpecificationKeyHash::equal):
     29        (WebCore::fontMap):
     30        (WebCore::clearFontFamilySpecificationCoreTextCache):
     31        (WebCore::FontFamilySpecificationCoreText::fontRanges const):
     32        * platform/graphics/cocoa/FontFamilySpecificationCoreText.h:
     33        * platform/graphics/mac/ComplexTextControllerCoreText.mm:
     34        (WebCore::ComplexTextController::collectComplexTextRunsForCharacters):
     35        (WebCore::safeCFEqual): Deleted.
     36
    1372019-04-15  Devin Rousso  <drousso@apple.com>
    238
  • trunk/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm

    r237266 r244315  
    2727#include "MemoryRelease.h"
    2828
     29#import "FontFamilySpecificationCoreText.h"
    2930#import "GCController.h"
    3031#import "IOSurfacePool.h"
     
    4748    SystemFontDatabaseCoreText::singleton().clear();
    4849#endif
     50    clearFontFamilySpecificationCoreTextCache();
    4951
    5052#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(IOSMAC)
  • trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp

    r242038 r244315  
    2828
    2929#include "Font.h"
     30#include "FontFamilySpecificationCoreText.h"
    3031#include "SystemFontDatabaseCoreText.h"
    3132#include <pal/spi/cocoa/CoreTextSPI.h>
     
    12051206    SystemFontDatabaseCoreText::singleton().clear();
    12061207#endif
     1208    clearFontFamilySpecificationCoreTextCache();
    12071209
    12081210    FontDatabase::singletonAllowingUserInstalledFonts().clear();
  • trunk/Source/WebCore/platform/graphics/cocoa/FontFamilySpecificationCoreText.cpp

    r223728 r244315  
    2727#include "FontFamilySpecificationCoreText.h"
    2828
    29 #include <pal/spi/cocoa/CoreTextSPI.h>
    3029#include "FontCache.h"
    3130#include "FontSelector.h"
     31#include <pal/spi/cocoa/CoreTextSPI.h>
     32#include <wtf/HashFunctions.h>
     33#include <wtf/HashMap.h>
    3234
    3335#include <CoreText/CoreText.h>
    3436
    3537namespace WebCore {
     38
     39struct FontFamilySpecificationKey {
     40    FontFamilySpecificationKey() = default;
     41
     42    FontFamilySpecificationKey(CTFontDescriptorRef fontDescriptor, const FontDescription& fontDescription)
     43        : fontDescriptor(fontDescriptor)
     44        , fontDescriptionKey(fontDescription)
     45    { }
     46
     47    explicit FontFamilySpecificationKey(WTF::HashTableDeletedValueType deletedValue)
     48        : fontDescriptionKey(deletedValue)
     49    { }
     50
     51    bool operator==(const FontFamilySpecificationKey& other) const
     52    {
     53        return WTF::safeCFEqual(fontDescriptor.get(), other.fontDescriptor.get()) && fontDescriptionKey == other.fontDescriptionKey;
     54    }
     55
     56    bool operator!=(const FontFamilySpecificationKey& other) const
     57    {
     58        return !(*this == other);
     59    }
     60
     61    bool isHashTableDeletedValue() const { return fontDescriptionKey.isHashTableDeletedValue(); }
     62
     63    unsigned computeHash() const
     64    {
     65        return WTF::pairIntHash(WTF::safeCFHash(fontDescriptor.get()), fontDescriptionKey.computeHash());
     66    }
     67
     68    RetainPtr<CTFontDescriptorRef> fontDescriptor;
     69    FontDescriptionKey fontDescriptionKey;
     70};
     71
     72struct FontFamilySpecificationKeyHash {
     73    static unsigned hash(const FontFamilySpecificationKey& key) { return key.computeHash(); }
     74    static bool equal(const FontFamilySpecificationKey& a, const FontFamilySpecificationKey& b) { return a == b; }
     75    static const bool safeToCompareToEmptyOrDeleted = true;
     76};
     77
     78using FontMap = HashMap<FontFamilySpecificationKey, std::unique_ptr<FontPlatformData>, FontFamilySpecificationKeyHash, WTF::SimpleClassHashTraits<FontFamilySpecificationKey>>;
     79
     80static FontMap& fontMap()
     81{
     82    static NeverDestroyed<FontMap> fontMap;
     83    return fontMap;
     84}
     85
     86void clearFontFamilySpecificationCoreTextCache()
     87{
     88    fontMap().clear();
     89}
    3690
    3791FontFamilySpecificationCoreText::FontFamilySpecificationCoreText(CTFontDescriptorRef fontDescriptor)
     
    4498FontRanges FontFamilySpecificationCoreText::fontRanges(const FontDescription& fontDescription) const
    4599{
    46     auto size = fontDescription.computedSize();
     100    auto& fontPlatformData = fontMap().ensure(FontFamilySpecificationKey(m_fontDescriptor.get(), fontDescription), [&] () {
     101        auto size = fontDescription.computedSize();
    47102
    48     auto font = adoptCF(CTFontCreateWithFontDescriptor(m_fontDescriptor.get(), size, nullptr));
     103        auto font = adoptCF(CTFontCreateWithFontDescriptor(m_fontDescriptor.get(), size, nullptr));
    49104
    50     auto fontForSynthesisComputation = font;
     105        auto fontForSynthesisComputation = font;
    51106#if USE_PLATFORM_SYSTEM_FALLBACK_LIST
    52     if (auto physicalFont = adoptCF(CTFontCopyPhysicalFont(font.get())))
    53         fontForSynthesisComputation = physicalFont;
     107        if (auto physicalFont = adoptCF(CTFontCopyPhysicalFont(font.get())))
     108            fontForSynthesisComputation = physicalFont;
    54109#endif
    55110
    56     font = preparePlatformFont(font.get(), fontDescription, nullptr, nullptr, { }, fontDescription.computedSize());
     111        font = preparePlatformFont(font.get(), fontDescription, nullptr, nullptr, { }, fontDescription.computedSize());
    57112
    58     bool syntheticBold, syntheticOblique;
    59     std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(fontForSynthesisComputation.get(), fontDescription).boldObliquePair();
     113        bool syntheticBold, syntheticOblique;
     114        std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(fontForSynthesisComputation.get(), fontDescription).boldObliquePair();
    60115
    61     FontPlatformData fontPlatformData(font.get(), size, false, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.textRenderingMode());
     116        return std::make_unique<FontPlatformData>(font.get(), size, false, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.textRenderingMode());
     117    }).iterator->value;
    62118
    63     return FontRanges(FontCache::singleton().fontForPlatformData(fontPlatformData));
     119    ASSERT(fontPlatformData);
     120
     121    return FontRanges(FontCache::singleton().fontForPlatformData(*fontPlatformData));
    64122}
    65123
  • trunk/Source/WebCore/platform/graphics/cocoa/FontFamilySpecificationCoreText.h

    r218421 r244315  
    4646};
    4747
     48void clearFontFamilySpecificationCoreTextCache();
     49
    4850}
  • trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm

    r241231 r244315  
    109109}
    110110
    111 static inline bool safeCFEqual(CFTypeRef a, CFTypeRef b)
    112 {
    113     return (!a && !b) || (a && b && CFEqual(a, b));
    114 }
    115 
    116111void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const Font* font)
    117112{
     
    197192            ASSERT(runCTFont && CFGetTypeID(runCTFont) == CTFontGetTypeID());
    198193            RetainPtr<CFTypeRef> runFontEqualityObject = FontPlatformData::objectForEqualityCheck(runCTFont);
    199             if (!safeCFEqual(runFontEqualityObject.get(), font->platformData().objectForEqualityCheck().get())) {
     194            if (!WTF::safeCFEqual(runFontEqualityObject.get(), font->platformData().objectForEqualityCheck().get())) {
    200195                // Begin trying to see if runFont matches any of the fonts in the fallback list.
    201196                for (unsigned i = 0; !m_font.fallbackRangesAt(i).isNull(); ++i) {
     
    203198                    if (!runFont)
    204199                        continue;
    205                     if (safeCFEqual(runFont->platformData().objectForEqualityCheck().get(), runFontEqualityObject.get()))
     200                    if (WTF::safeCFEqual(runFont->platformData().objectForEqualityCheck().get(), runFontEqualityObject.get()))
    206201                        break;
    207202                    runFont = nullptr;
Note: See TracChangeset for help on using the changeset viewer.