Title: [143601] trunk/Source/WebCore
Revision
143601
Author
akl...@apple.com
Date
2013-02-21 07:44:02 -0800 (Thu, 21 Feb 2013)

Log Message

GlyphPage: Bake per-glyph font data array into same allocation as GlyphPage.

A hopeful fix for REGRESSION(r143125): ~5% performance hit on Chromium's intl2 page cycler
<http://webkit.org/b/108835>

Reviewed by Antti Koivisto.

Rewire GlyphPage so that we have to decide at creation time whether there will be a per-glyph
array of SimpleFontData* or not. This removes one allocation and one step of indirection for
pages with glyphs from mixed fonts.

* platform/graphics/GlyphPage.h:
(WebCore::GlyphPage::createForMixedFontData):
(WebCore::GlyphPage::createForSingleFontData):
(WebCore::GlyphPage::createCopiedSystemFallbackPage):
(WebCore::GlyphPage::~GlyphPage):
(WebCore::GlyphPage::glyphDataForIndex):
(WebCore::GlyphPage::fontDataForCharacter):
(WebCore::GlyphPage::setGlyphDataForIndex):
(WebCore::GlyphPage::removeFontDataFromSystemFallbackPage):
(WebCore::GlyphPage::GlyphPage):
(WebCore::GlyphPage::hasPerGlyphFontData):
(GlyphPage):
* platform/graphics/GlyphPageTreeNode.cpp:
(WebCore::GlyphPageTreeNode::initializePage):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (143600 => 143601)


--- trunk/Source/WebCore/ChangeLog	2013-02-21 15:38:04 UTC (rev 143600)
+++ trunk/Source/WebCore/ChangeLog	2013-02-21 15:44:02 UTC (rev 143601)
@@ -1,3 +1,31 @@
+2013-02-21  Andreas Kling  <akl...@apple.com>
+
+        GlyphPage: Bake per-glyph font data array into same allocation as GlyphPage.
+
+        A hopeful fix for REGRESSION(r143125): ~5% performance hit on Chromium's intl2 page cycler
+        <http://webkit.org/b/108835>
+
+        Reviewed by Antti Koivisto.
+
+        Rewire GlyphPage so that we have to decide at creation time whether there will be a per-glyph
+        array of SimpleFontData* or not. This removes one allocation and one step of indirection for
+        pages with glyphs from mixed fonts.
+
+        * platform/graphics/GlyphPage.h:
+        (WebCore::GlyphPage::createForMixedFontData):
+        (WebCore::GlyphPage::createForSingleFontData):
+        (WebCore::GlyphPage::createCopiedSystemFallbackPage):
+        (WebCore::GlyphPage::~GlyphPage):
+        (WebCore::GlyphPage::glyphDataForIndex):
+        (WebCore::GlyphPage::fontDataForCharacter):
+        (WebCore::GlyphPage::setGlyphDataForIndex):
+        (WebCore::GlyphPage::removeFontDataFromSystemFallbackPage):
+        (WebCore::GlyphPage::GlyphPage):
+        (WebCore::GlyphPage::hasPerGlyphFontData):
+        (GlyphPage):
+        * platform/graphics/GlyphPageTreeNode.cpp:
+        (WebCore::GlyphPageTreeNode::initializePage):
+
 2013-02-21  Xan Lopez  <xlo...@rim.com>
 
         [BlackBerry] MediaPlayerPrivateBlackBerry: include Logging.h

Modified: trunk/Source/WebCore/platform/graphics/GlyphPage.h (143600 => 143601)


--- trunk/Source/WebCore/platform/graphics/GlyphPage.h	2013-02-21 15:38:04 UTC (rev 143600)
+++ trunk/Source/WebCore/platform/graphics/GlyphPage.h	2013-02-21 15:44:02 UTC (rev 143601)
@@ -53,6 +53,11 @@
     const SimpleFontData* fontData;
 };
 
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
+#endif
+
 // A GlyphPage contains a fixed-size set of GlyphData mappings for a contiguous
 // range of characters in the Unicode code space. GlyphPages are indexed
 // starting from 0 and incrementing for each 256 glyphs.
@@ -63,33 +68,33 @@
 // to be overriding the parent's node, but provide no additional information.
 class GlyphPage : public RefCounted<GlyphPage> {
 public:
-    static PassRefPtr<GlyphPage> createUninitialized(GlyphPageTreeNode* owner)
+    static PassRefPtr<GlyphPage> createForMixedFontData(GlyphPageTreeNode* owner)
     {
-        return adoptRef(new GlyphPage(owner, false));
+        void* slot = fastMalloc(sizeof(GlyphPage) + sizeof(SimpleFontData*) * GlyphPage::size);
+        return adoptRef(new (slot) GlyphPage(owner));
     }
 
-    static PassRefPtr<GlyphPage> createZeroedSystemFallbackPage(GlyphPageTreeNode* owner)
+    static PassRefPtr<GlyphPage> createForSingleFontData(GlyphPageTreeNode* owner, const SimpleFontData* fontData)
     {
-        return adoptRef(new GlyphPage(owner, true));
+        ASSERT(fontData);
+        return adoptRef(new GlyphPage(owner, fontData));
     }
 
     PassRefPtr<GlyphPage> createCopiedSystemFallbackPage(GlyphPageTreeNode* owner) const
     {
-        RefPtr<GlyphPage> page = GlyphPage::createUninitialized(owner);
+        RefPtr<GlyphPage> page = GlyphPage::createForMixedFontData(owner);
         memcpy(page->m_glyphs, m_glyphs, sizeof(m_glyphs));
-        page->m_fontDataForAllGlyphs = m_fontDataForAllGlyphs;
-        if (m_perGlyphFontData) {
-            page->m_perGlyphFontData = static_cast<const SimpleFontData**>(fastMalloc(size * sizeof(SimpleFontData*)));
-            memcpy(page->m_perGlyphFontData, m_perGlyphFontData, size * sizeof(SimpleFontData*));
+        if (hasPerGlyphFontData())
+            memcpy(page->m_perGlyphFontData, m_perGlyphFontData, sizeof(SimpleFontData*) * GlyphPage::size);
+        else {
+            for (size_t i = 0; i < GlyphPage::size; ++i) {
+                page->m_perGlyphFontData[i] = m_glyphs[i] ? m_fontDataForAllGlyphs : 0;
+            }
         }
         return page.release();
     }
 
-    ~GlyphPage()
-    {
-        if (m_perGlyphFontData)
-            fastFree(m_perGlyphFontData);
-    }
+    ~GlyphPage() { }
 
     static const size_t size = 256; // Covers Latin-1 in a single page.
 
@@ -103,11 +108,9 @@
     {
         ASSERT_WITH_SECURITY_IMPLICATION(index < size);
         Glyph glyph = m_glyphs[index];
-        if (m_perGlyphFontData)
+        if (hasPerGlyphFontData())
             return GlyphData(glyph, m_perGlyphFontData[index]);
-        if (!glyph)
-            return GlyphData(0, 0);
-        return GlyphData(glyph, m_fontDataForAllGlyphs);
+        return GlyphData(glyph, glyph ? m_fontDataForAllGlyphs : 0);
     }
 
     Glyph glyphAt(unsigned index) const
@@ -119,12 +122,9 @@
     const SimpleFontData* fontDataForCharacter(UChar32 c) const
     {
         unsigned index = indexForCharacter(c);
-        if (m_perGlyphFontData)
+        if (hasPerGlyphFontData())
             return m_perGlyphFontData[index];
-        Glyph glyph = m_glyphs[index];
-        if (!glyph)
-            return 0;
-        return m_fontDataForAllGlyphs;
+        return m_glyphs[index] ? m_fontDataForAllGlyphs : 0;
     }
 
     void setGlyphDataForCharacter(UChar32 c, Glyph g, const SimpleFontData* f)
@@ -138,29 +138,13 @@
         m_glyphs[index] = glyph;
 
         // GlyphPage getters will always return a null SimpleFontData* for glyph #0 if there's no per-glyph font array.
-        if (m_perGlyphFontData) {
+        if (hasPerGlyphFontData()) {
             m_perGlyphFontData[index] = glyph ? fontData : 0;
             return;
         }
 
-        if (!glyph)
-            return;
-
-        // A glyph index without a font data pointer makes no sense.
-        ASSERT(fontData);
-
-        if (!m_fontDataForAllGlyphs)
-            m_fontDataForAllGlyphs = fontData;
-
-        if (m_fontDataForAllGlyphs == fontData)
-            return;
-
-        // This GlyphPage houses glyphs from multiple fonts, transition to an array of SimpleFontData pointers.
-        const SimpleFontData* oldFontData = m_fontDataForAllGlyphs;
-        m_perGlyphFontData = static_cast<const SimpleFontData**>(fastMalloc(size * sizeof(SimpleFontData*)));
-        for (unsigned i = 0; i < size; ++i)
-            m_perGlyphFontData[i] = m_glyphs[i] ? oldFontData : 0;
-        m_perGlyphFontData[index] = fontData;
+        // A single-font GlyphPage already assigned m_fontDataForAllGlyphs in the constructor.
+        ASSERT(!glyph || fontData == m_fontDataForAllGlyphs);
     }
 
     void setGlyphDataForIndex(unsigned index, const GlyphData& glyphData)
@@ -168,15 +152,10 @@
         setGlyphDataForIndex(index, glyphData.glyph, glyphData.fontData);
     }
 
-    void clearForFontData(const SimpleFontData* fontData)
+    void removeFontDataFromSystemFallbackPage(const SimpleFontData* fontData)
     {
-        if (!m_perGlyphFontData) {
-            if (m_fontDataForAllGlyphs == fontData) {
-                memset(m_glyphs, 0, sizeof(m_glyphs));
-                m_fontDataForAllGlyphs = 0;
-            }
-            return;
-        }
+        // This method should only be called on the system fallback page, which is never single-font.
+        ASSERT(hasPerGlyphFontData());
         for (size_t i = 0; i < size; ++i) {
             if (m_perGlyphFontData[i] == fontData) {
                 m_glyphs[i] = 0;
@@ -191,22 +170,29 @@
     bool fill(unsigned offset, unsigned length, UChar* characterBuffer, unsigned bufferLength, const SimpleFontData*);
 
 private:
-    GlyphPage(GlyphPageTreeNode* owner, bool clearGlyphs)
-        : m_fontDataForAllGlyphs(0)
-        , m_perGlyphFontData(0)
+    explicit GlyphPage(GlyphPageTreeNode* owner, const SimpleFontData* fontDataForAllGlyphs = 0)
+        : m_fontDataForAllGlyphs(fontDataForAllGlyphs)
         , m_owner(owner)
     {
-        if (clearGlyphs)
-            memset(m_glyphs, 0, sizeof(m_glyphs));
+        memset(m_glyphs, 0, sizeof(m_glyphs));
+        if (hasPerGlyphFontData())
+            memset(m_perGlyphFontData, 0, sizeof(SimpleFontData*) * GlyphPage::size);
     }
 
-    const SimpleFontData* m_fontDataForAllGlyphs;
-    const SimpleFontData** m_perGlyphFontData;
+    bool hasPerGlyphFontData() const { return !m_fontDataForAllGlyphs; }
 
+    const SimpleFontData* m_fontDataForAllGlyphs;
     GlyphPageTreeNode* m_owner;
     Glyph m_glyphs[size];
+
+    // NOTE: This array has (GlyphPage::size) elements if m_fontDataForAllGlyphs is null.
+    const SimpleFontData* m_perGlyphFontData[0];
 };
 
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
+
 } // namespace WebCore
 
 #endif // GlyphPage_h

Modified: trunk/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp (143600 => 143601)


--- trunk/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp	2013-02-21 15:38:04 UTC (rev 143600)
+++ trunk/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp	2013-02-21 15:44:02 UTC (rev 143601)
@@ -201,15 +201,17 @@
                 }
             }
 
-            m_page = GlyphPage::createUninitialized(this);
-
             // Now that we have a buffer full of characters, we want to get back an array
             // of glyph indices.  This part involves calling into the platform-specific 
             // routine of our glyph map for actually filling in the page with the glyphs.
             // Success is not guaranteed. For example, Times fails to fill page 260, giving glyph data
             // for only 128 out of 256 characters.
             bool haveGlyphs;
-            if (fontData->isSegmented()) {
+            if (!fontData->isSegmented()) {
+                m_page = GlyphPage::createForSingleFontData(this, static_cast<const SimpleFontData*>(fontData));
+                haveGlyphs = fill(m_page.get(), 0, GlyphPage::size, buffer, bufferLength, static_cast<const SimpleFontData*>(fontData));
+            } else {
+                m_page = GlyphPage::createForMixedFontData(this);
                 haveGlyphs = false;
 
                 const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
@@ -225,7 +227,7 @@
                     int to = 1 + min(static_cast<int>(range.to()) - static_cast<int>(start), static_cast<int>(GlyphPage::size) - 1);
                     if (from < static_cast<int>(GlyphPage::size) && to > 0) {
                         if (haveGlyphs && !scratchPage) {
-                            scratchPage = GlyphPage::createUninitialized(this);
+                            scratchPage = GlyphPage::createForMixedFontData(this);
                             pageToFill = scratchPage.get();
                         }
 
@@ -246,8 +248,7 @@
                         }
                     }
                 }
-            } else
-                haveGlyphs = fill(m_page.get(), 0, GlyphPage::size, buffer, bufferLength, static_cast<const SimpleFontData*>(fontData));
+            }
 
             if (!haveGlyphs)
                 m_page = 0;
@@ -279,7 +280,7 @@
                 m_page = parentPage;
             } else {
                 // Combine the parent's glyphs and ours to form a new more complete page.
-                m_page = GlyphPage::createUninitialized(this);
+                m_page = GlyphPage::createForMixedFontData(this);
 
                 // Overlay the parent page on the fallback page. Check if the fallback font
                 // has added anything.
@@ -307,7 +308,7 @@
         if (parentPage)
             m_page = parentPage->createCopiedSystemFallbackPage(this);
         else
-            m_page = GlyphPage::createZeroedSystemFallbackPage(this);
+            m_page = GlyphPage::createForMixedFontData(this);
     }
 }
 
@@ -369,7 +370,7 @@
 
     // Prune fall back child (if any) of this font.
     if (m_systemFallbackChild && m_systemFallbackChild->m_page)
-        m_systemFallbackChild->m_page->clearForFontData(fontData);
+        m_systemFallbackChild->m_page->removeFontDataFromSystemFallbackPage(fontData);
 
     // Prune any branch that contains this FontData.
     if (OwnPtr<GlyphPageTreeNode> node = m_children.take(fontData)) {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to