Bug 1192699 - eliminate the two-stage system fontlist initialization under DirectWrite. r=m_kato, a=ritu
authorJohn Daggett <jdaggett@mozilla.com>
Wed, 19 Aug 2015 12:41:17 +0900
changeset 288796 fbc314dea701b3c8350d952240644b280c208568
parent 288795 4345fbf90ea4af6cd2b6a9158d6a190dea425576
child 288797 7a1b970bcbfba9acffb9cc6f3ab8dd87dee6ac56
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato, ritu
bugs1192699
milestone42.0a2
Bug 1192699 - eliminate the two-stage system fontlist initialization under DirectWrite. r=m_kato, a=ritu
gfx/thebes/gfxDWriteFontList.cpp
gfx/thebes/gfxDWriteFontList.h
gfx/thebes/gfxTextRun.cpp
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -699,17 +699,17 @@ gfxDWriteFontEntry::AddSizeOfIncludingTh
     aSizes->mFontListSize += aMallocSizeOf(this);
     AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // gfxDWriteFontList
 
 gfxDWriteFontList::gfxDWriteFontList()
-    : mInitialized(false), mForceGDIClassicMaxFontSize(0.0)
+    : mForceGDIClassicMaxFontSize(0.0)
 {
 }
 
 // bug 602792 - CJK systems default to large CJK fonts which cause excessive
 //   I/O strain during cold startup due to dwrite caching bugs.  Default to
 //   Arial to avoid this.
 
 gfxFontFamily *
@@ -839,138 +839,74 @@ gfxDWriteFontList::MakePlatformFont(cons
         // We don't know how to deal with 0 faces either.
         delete entry;
         return nullptr;
     }
 
     return entry;
 }
 
-#ifdef DEBUG_DWRITE_STARTUP
-
-#define LOGREGISTRY(msg) LogRegistryEvent(msg)
-
-// for use when monitoring process
-static void LogRegistryEvent(const wchar_t *msg)
-{
-    HKEY dummyKey;
-    HRESULT hr;
-    wchar_t buf[512];
-
-    wsprintfW(buf, L" log %s", msg);
-    hr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
-    if (SUCCEEDED(hr)) {
-        RegCloseKey(dummyKey);
-    }
-}
-#else
-
-#define LOGREGISTRY(msg)
-
-#endif
-
 nsresult
 gfxDWriteFontList::InitFontList()
 {
-    LOGREGISTRY(L"InitFontList start");
-
-    mInitialized = false;
-
-    LARGE_INTEGER frequency;        // ticks per second
-    LARGE_INTEGER t1, t2, t3;           // ticks
+    LARGE_INTEGER frequency;          // ticks per second
+    LARGE_INTEGER t1, t2, t3, t4, t5; // ticks
     double elapsedTime, upTime;
     char nowTime[256], nowDate[256];
 
-    if (LOG_FONTINIT_ENABLED()) {    
-        GetTimeFormat(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, 
+    if (LOG_FONTINIT_ENABLED()) {
+        GetTimeFormat(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT,
                       nullptr, nullptr, nowTime, 256);
         GetDateFormat(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256);
+        upTime = (double) GetTickCount();
     }
-    upTime = (double) GetTickCount();
     QueryPerformanceFrequency(&frequency);
-    QueryPerformanceCounter(&t1);
+    QueryPerformanceCounter(&t1); // start
 
     HRESULT hr;
-    mGDIFontTableAccess = Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading", false);
+    mGDIFontTableAccess =
+        Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading",
+                             false);
 
     gfxPlatformFontList::InitFontList();
 
     mFontSubstitutes.Clear();
     mNonExistingFonts.Clear();
 
-    QueryPerformanceCounter(&t2);
-
     hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
         GetGdiInterop(getter_AddRefs(mGDIInterop));
     if (FAILED(hr)) {
         return NS_ERROR_FAILURE;
     }
 
-    LOGREGISTRY(L"InitFontList end");
-
-    QueryPerformanceCounter(&t3);
-
-    if (LOG_FONTINIT_ENABLED()) {
-        // determine dwrite version
-        nsAutoString dwriteVers;
-        gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", dwriteVers);
-        LOG_FONTINIT(("InitFontList\n"));
-        LOG_FONTINIT(("Start: %s %s\n", nowDate, nowTime));
-        LOG_FONTINIT(("Uptime: %9.3f s\n", upTime/1000));
-        LOG_FONTINIT(("dwrite version: %s\n", 
-                      NS_ConvertUTF16toUTF8(dwriteVers).get()));
-    }
-
-    elapsedTime = (t3.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
-    LOG_FONTINIT(("Total time in InitFontList:    %9.3f ms\n", elapsedTime));
-    elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
-    LOG_FONTINIT((" --- gfxPlatformFontList init: %9.3f ms\n", elapsedTime));
-    elapsedTime = (t3.QuadPart - t2.QuadPart) * 1000.0 / frequency.QuadPart;
-    LOG_FONTINIT((" --- GdiInterop object:        %9.3f ms\n", elapsedTime));
+    QueryPerformanceCounter(&t2); // base-class/interop initialization
 
-    return NS_OK;
-}
-
-nsresult
-gfxDWriteFontList::DelayedInitFontList()
-{
-    LOGREGISTRY(L"DelayedInitFontList start");
-
-    LARGE_INTEGER frequency;        // ticks per second
-    LARGE_INTEGER t1, t2, t3;           // ticks
-    double elapsedTime, upTime;
-    char nowTime[256], nowDate[256];
-
-    if (LOG_FONTINIT_ENABLED()) {    
-        GetTimeFormat(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, 
-                      nullptr, nullptr, nowTime, 256);
-        GetDateFormat(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256);
-    }
-
-    upTime = (double) GetTickCount();
-    QueryPerformanceFrequency(&frequency);
-    QueryPerformanceCounter(&t1);
-
-    HRESULT hr;
     nsRefPtr<IDWriteFactory> factory =
         gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
 
-    LOGREGISTRY(L"calling GetSystemFontCollection");
     hr = factory->GetSystemFontCollection(getter_AddRefs(mSystemFonts));
     NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!");
-    LOGREGISTRY(L"GetSystemFontCollection done");
 
     if (FAILED(hr)) {
         return NS_ERROR_FAILURE;
     }
 
-    QueryPerformanceCounter(&t2);
+    QueryPerformanceCounter(&t3); // system font collection
 
     GetFontsFromCollection(mSystemFonts);
 
+    // if no fonts found, something is out of whack, bail and use GDI backend
+    NS_ASSERTION(mFontFamilies.Count() != 0,
+                 "no fonts found in the system fontlist -- holy crap batman!");
+    if (mFontFamilies.Count() == 0) {
+        return NS_ERROR_FAILURE;
+    }
+
+    QueryPerformanceCounter(&t4); // iterate over system fonts
+
 #ifdef MOZ_BUNDLED_FONTS
     mBundledFonts = CreateBundledFontsCollection(factory);
     if (mBundledFonts) {
         GetFontsFromCollection(mBundledFonts);
     }
 #endif
 
     mOtherFamilyNamesInitialized = true;
@@ -978,17 +914,17 @@ gfxDWriteFontList::DelayedInitFontList()
 
     // bug 642093 - DirectWrite does not support old bitmap (.fon)
     // font files, but a few of these such as "Courier" and "MS Sans Serif"
     // are frequently specified in shoddy CSS, without appropriate fallbacks.
     // By mapping these to TrueType equivalents, we provide better consistency
     // with both pre-DW systems and with IE9, which appears to do the same.
     GetDirectWriteSubstitutes();
 
-    // bug 551313 - DirectWrite creates a Gill Sans family out of 
+    // bug 551313 - DirectWrite creates a Gill Sans family out of
     // poorly named members of the Gill Sans MT family containing
     // only Ultra Bold weights.  This causes big problems for pages
     // using Gill Sans which is usually only available on OSX
 
     nsAutoString nameGillSans(L"Gill Sans");
     nsAutoString nameGillSansMT(L"Gill Sans MT");
     BuildKeyNameFromFontName(nameGillSans);
     BuildKeyNameFromFontName(nameGillSansMT);
@@ -1050,46 +986,49 @@ gfxDWriteFontList::DelayedInitFontList()
         }
     }
     mForceGDIClassicMaxFontSize =
         Preferences::GetInt("gfx.font_rendering.cleartype_params.force_gdi_classic_max_size",
                             mForceGDIClassicMaxFontSize);
 
     GetPrefsAndStartLoader();
 
-    LOGREGISTRY(L"DelayedInitFontList end");
-
-    QueryPerformanceCounter(&t3);
+    QueryPerformanceCounter(&t5); // misc initialization
 
     if (LOG_FONTINIT_ENABLED()) {
         // determine dwrite version
         nsAutoString dwriteVers;
         gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", dwriteVers);
-        LOG_FONTINIT(("DelayedInitFontList\n"));
-        LOG_FONTINIT(("Start: %s %s\n", nowDate, nowTime));
-        LOG_FONTINIT(("Uptime: %9.3f s\n", upTime/1000));
-        LOG_FONTINIT(("dwrite version: %s\n", 
+        LOG_FONTINIT(("(fontinit) Start: %s %s\n", nowDate, nowTime));
+        LOG_FONTINIT(("(fontinit) Uptime: %9.3f s\n", upTime/1000));
+        LOG_FONTINIT(("(fontinit) dwrite version: %s\n",
                       NS_ConvertUTF16toUTF8(dwriteVers).get()));
     }
 
-    elapsedTime = (t3.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
+    elapsedTime = (t5.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
     Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_TOTAL, elapsedTime);
     Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_COUNT,
                           mSystemFonts->GetFontFamilyCount());
     LOG_FONTINIT((
-       "Total time in DelayedInitFontList:    %9.3f ms (families: %d, %s)\n",
+       "(fontinit) Total time in InitFontList:    %9.3f ms (families: %d, %s)\n",
        elapsedTime, mSystemFonts->GetFontFamilyCount(),
        (mGDIFontTableAccess ? "gdi table access" : "dwrite table access")));
 
     elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
-    Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_COLLECT, elapsedTime);
-    LOG_FONTINIT((" --- GetSystemFontCollection:  %9.3f ms\n", elapsedTime));
+    LOG_FONTINIT(("(fontinit)  --- base/interop obj initialization init: %9.3f ms\n", elapsedTime));
 
     elapsedTime = (t3.QuadPart - t2.QuadPart) * 1000.0 / frequency.QuadPart;
-    LOG_FONTINIT((" --- iterate over families:    %9.3f ms\n", elapsedTime));
+    Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_COLLECT, elapsedTime);
+    LOG_FONTINIT(("(fontinit)  --- GetSystemFontCollection:  %9.3f ms\n", elapsedTime));
+
+    elapsedTime = (t4.QuadPart - t3.QuadPart) * 1000.0 / frequency.QuadPart;
+    LOG_FONTINIT(("(fontinit)  --- iterate over families:    %9.3f ms\n", elapsedTime));
+
+    elapsedTime = (t5.QuadPart - t4.QuadPart) * 1000.0 / frequency.QuadPart;
+    LOG_FONTINIT(("(fontinit)  --- misc initialization:    %9.3f ms\n", elapsedTime));
 
     return NS_OK;
 }
 
 void
 gfxDWriteFontList::GetFontsFromCollection(IDWriteFontCollection* aCollection)
 {
     for (UINT32 i = 0; i < aCollection->GetFontFamilyCount(); i++) {
@@ -1303,48 +1242,32 @@ gfxDWriteFontList::GetStandardFamilyName
     return false;
 }
 
 gfxFontFamily*
 gfxDWriteFontList::FindFamily(const nsAString& aFamily,
                               nsIAtom* aLanguage,
                               bool aUseSystemFonts)
 {
-    if (!mInitialized) {
-        mInitialized = true;
-        DelayedInitFontList();
-    }
-
     nsAutoString keyName(aFamily);
     BuildKeyNameFromFontName(keyName);
 
     gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
     if (ff) {
         return ff;
     }
 
     if (mNonExistingFonts.Contains(keyName)) {
         return nullptr;
     }
 
     return gfxPlatformFontList::FindFamily(aFamily);
 }
 
 void
-gfxDWriteFontList::GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray)
-{
-    if (!mInitialized) {
-        mInitialized = true;
-        DelayedInitFontList();
-    }
-
-    return gfxPlatformFontList::GetFontFamilyList(aFamilyArray);
-}
-
-void
 gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                                           FontListSizes* aSizes) const
 {
     gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
 
     aSizes->mFontListSize +=
         SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf);
 
--- a/gfx/thebes/gfxDWriteFontList.h
+++ b/gfx/thebes/gfxDWriteFontList.h
@@ -363,18 +363,16 @@ public:
 
     IDWriteGdiInterop *GetGDIInterop() { return mGDIInterop; }
     bool UseGDIFontTableAccess() { return mGDIFontTableAccess; }
 
     virtual gfxFontFamily* FindFamily(const nsAString& aFamily,
                                       nsIAtom* aLanguage = nullptr,
                                       bool aUseSystemFonts = false);
 
-    virtual void GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray);
-
     gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; }
 
     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontListSizes* aSizes) const;
     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontListSizes* aSizes) const;
 
 private:
@@ -407,19 +405,16 @@ private:
     nsTArray<nsString> mNonExistingFonts;
 
     /**
      * Table of font substitutes, we grab this from the registry to get
      * alternative font names.
      */
     FontFamilyTable mFontSubstitutes;
 
-    bool mInitialized;
-    virtual nsresult DelayedInitFontList();
-
     virtual already_AddRefed<FontInfoData> CreateFontInfoData();
 
     gfxFloat mForceGDIClassicMaxFontSize;
 
     // whether to use GDI font table access routines
     bool mGDIFontTableAccess;
     nsRefPtr<IDWriteGdiInterop> mGDIInterop;
 
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -24,16 +24,20 @@
 #include "mozilla/Likely.h"
 #include "gfx2DGlue.h"
 #include "mozilla/gfx/Logging.h"        // for gfxCriticalError
 
 #if defined(MOZ_WIDGET_GTK)
 #include "gfxPlatformGtk.h" // xxx - for UseFcFontList
 #endif
 
+#ifdef XP_WIN
+#include "gfxWindowsPlatform.h"
+#endif
+
 #include "cairo.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::unicode;
 using mozilla::services::GetObserverService;
 
 static const char16_t kEllipsisChar[] = { 0x2026, 0x0 };
@@ -1906,16 +1910,22 @@ gfxFontGroup::GetDefaultFont()
     if (!mDefaultFont) {
         // an empty font list at this point is fatal; we're not going to
         // be able to do even the most basic layout operations
 
         // annotate crash report with fontlist info
         nsAutoCString fontInitInfo;
         fontInitInfo.AppendPrintf("no fonts - init: %d fonts: %d loader: %d",
                                   numInits, numFonts, loaderState);
+#ifdef XP_WIN
+        bool dwriteEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
+        double upTime = (double) GetTickCount();
+        fontInitInfo.AppendPrintf(" backend: %s system-uptime: %9.3f sec",
+                                  dwriteEnabled ? "directwrite" : "gdi", upTime);
+#endif
         gfxCriticalError() << fontInitInfo.get();
 
         char msg[256]; // CHECK buffer length if revising message below
         nsAutoString families;
         mFamilyList.ToString(families);
         snprintf_literal(msg, "unable to find a usable font (%.220s)",
                          NS_ConvertUTF16toUTF8(families).get());
         NS_RUNTIMEABORT(msg);