Commit bdb9ed5e authored by mitz@apple.com's avatar mitz@apple.com

WebCore:

        Reviewed by Ada Chan and Sam Weinig.

        - WebCore changes for https://bugs.webkit.org/show_bug.cgi?id=17097
          <rdar://problem/5715471> CGFontRefs (and HFONTs on Windows) leak because FontCache grows without bound

        Added a way for clients to let the cache know that they no longer need
        font data, which lets the cache release it. Changed clients to track
        most of the font data they get from the cache so that they can later
        release it. Some instances of font data -- namely, those used for system
        font fallback -- are still not tracked and will therefore remain in the
        cache indefinitely.

        * WebCore.base.exp: Added exports for WebCoreStatistics in WebKit.

        * platform/graphics/Font.cpp:
        (WebCore::Font::Font): Changed to use FontFallbackList::create().
        (WebCore::Font::update): Ditto.

        * platform/graphics/FontCache.cpp:
        (WebCore::FontCache::getCachedFontData): Added code to track the number
        of times a SimpleFontData instance has been requested from the cache,
        remove requested instances from the inactive list, and purge inactive
        font data if the inactive list has grown above its maximum allowed size.
        (WebCore::FontCache::releaseFontData): Added. Called by clients to let
        the cache know that they no longer need the font data. Adds the font
        data to the inactive list if the last client has released it.
        (WebCore::FontCache::purgeInactiveFontData): Added. Removes inactive
        font data from the cache (and the inactive list).
        (WebCore::FontCache::fontDataCount): Added to provide statistics.
        (WebCore::FontCache::inactiveFontDataCount): Ditto.

        * platform/graphics/FontCache.h:

        * platform/graphics/FontData.h:
        (WebCore::FontData::FontData): Added a member variable to store the
        highest glyph page tree level in which there is a node for this FontData.
        This is used to limit the depth of the search when pruning glyph page
        trees.
        (WebCore::FontData::setMaxGlyphPageTreeLevel): Added this accessor.
        (WebCore::FontData::maxGlyphPageTreeLevel): Ditto.

        * platform/graphics/FontFallbackList.cpp:
        (WebCore::FontFallbackList::FontFallbackList): Changed to start with a
        refcount of 1.
        (WebCore::FontFallbackList::invalidate): Added a call to
        releaseFontData().
        (WebCore::FontFallbackList::releaseFontData): Added. Lets the font cache
        know that we no longer need the FontData in our font list.
        (WebCore::FontFallbackList::fontDataAt): Changed to record in the font
        list whether the font data is a custom font data or not.
        (WebCore::FontFallbackList::setPlatformFont): Ditto.

        * platform/graphics/FontFallbackList.h:
        (WebCore::FontFallbackList::create): Added and made the constructor
        private.
        (WebCore::FontFallbackList::~FontFallbackList): Added a call to
        releaseFontData().

        * platform/graphics/GlyphPageTreeNode.cpp:
        (WebCore::GlyphPageTreeNode::treeGlyphPageCount): Added to provide
        statistics.
        (WebCore::GlyphPageTreeNode::pageCount): Ditto.

        (WebCore::GlyphPageTreeNode::pruneTreeFontData): Added.
        (WebCore::GlyphPageTreeNode::getChild): Added code to update the font
        data's maximum glyph page tree level.
        (WebCore::GlyphPageTreeNode::pruneFontData): Added.

        * platform/graphics/GlyphPageTreeNode.h:

        * platform/graphics/SimpleFontData.cpp:
        (WebCore::SimpleFontData::~SimpleFontData): Added code to let the font
        cache know that we no longer need the small caps font data and to prune
        the glyph page trees.

WebKit/mac:

        Reviewed by Ada Chan.

        - WebKit/mac changes for https://bugs.webkit.org/show_bug.cgi?id=17097
          <rdar://problem/5715471> CGFontRefs (and HFONTs on Windows) leak because FontCache grows without bound

        Added font cache statistics and a function to purge inactive font data.

        * Misc/WebCoreStatistics.h:
        * Misc/WebCoreStatistics.mm:
        (+[WebCoreStatistics cachedFontDataCount]):
        (+[WebCoreStatistics cachedFontDataInactiveCount]):
        (+[WebCoreStatistics purgeInactiveFontData]):
        (+[WebCoreStatistics glyphPageCount]):

WebKit/win:

        Reviewed by Ada Chan.

        - WebKit/win changes for https://bugs.webkit.org/show_bug.cgi?id=17097
          <rdar://problem/5715471> CGFontRefs (and HFONTs on Windows) leak because FontCache grows without bound

        Added font cache statistics and a function to purge inactive font data.

        * Interfaces/IWebCoreStatistics.idl:
        * WebCoreStatistics.cpp:
        (WebCoreStatistics::cachedFontDataCount):
        (WebCoreStatistics::cachedFontDataInactiveCount):
        (WebCoreStatistics::purgeInactiveFontData):
        (WebCoreStatistics::glyphPageCount):
        * WebCoreStatistics.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@33056 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 323e9bf1
2008-05-12 Dan Bernstein <mitz@apple.com>
Reviewed by Ada Chan and Sam Weinig.
- WebCore changes for https://bugs.webkit.org/show_bug.cgi?id=17097
<rdar://problem/5715471> CGFontRefs (and HFONTs on Windows) leak because FontCache grows without bound
Added a way for clients to let the cache know that they no longer need
font data, which lets the cache release it. Changed clients to track
most of the font data they get from the cache so that they can later
release it. Some instances of font data -- namely, those used for system
font fallback -- are still not tracked and will therefore remain in the
cache indefinitely.
* WebCore.base.exp: Added exports for WebCoreStatistics in WebKit.
* platform/graphics/Font.cpp:
(WebCore::Font::Font): Changed to use FontFallbackList::create().
(WebCore::Font::update): Ditto.
* platform/graphics/FontCache.cpp:
(WebCore::FontCache::getCachedFontData): Added code to track the number
of times a SimpleFontData instance has been requested from the cache,
remove requested instances from the inactive list, and purge inactive
font data if the inactive list has grown above its maximum allowed size.
(WebCore::FontCache::releaseFontData): Added. Called by clients to let
the cache know that they no longer need the font data. Adds the font
data to the inactive list if the last client has released it.
(WebCore::FontCache::purgeInactiveFontData): Added. Removes inactive
font data from the cache (and the inactive list).
(WebCore::FontCache::fontDataCount): Added to provide statistics.
(WebCore::FontCache::inactiveFontDataCount): Ditto.
* platform/graphics/FontCache.h:
* platform/graphics/FontData.h:
(WebCore::FontData::FontData): Added a member variable to store the
highest glyph page tree level in which there is a node for this FontData.
This is used to limit the depth of the search when pruning glyph page
trees.
(WebCore::FontData::setMaxGlyphPageTreeLevel): Added this accessor.
(WebCore::FontData::maxGlyphPageTreeLevel): Ditto.
* platform/graphics/FontFallbackList.cpp:
(WebCore::FontFallbackList::FontFallbackList): Changed to start with a
refcount of 1.
(WebCore::FontFallbackList::invalidate): Added a call to
releaseFontData().
(WebCore::FontFallbackList::releaseFontData): Added. Lets the font cache
know that we no longer need the FontData in our font list.
(WebCore::FontFallbackList::fontDataAt): Changed to record in the font
list whether the font data is a custom font data or not.
(WebCore::FontFallbackList::setPlatformFont): Ditto.
* platform/graphics/FontFallbackList.h:
(WebCore::FontFallbackList::create): Added and made the constructor
private.
(WebCore::FontFallbackList::~FontFallbackList): Added a call to
releaseFontData().
* platform/graphics/GlyphPageTreeNode.cpp:
(WebCore::GlyphPageTreeNode::treeGlyphPageCount): Added to provide
statistics.
(WebCore::GlyphPageTreeNode::pageCount): Ditto.
(WebCore::GlyphPageTreeNode::pruneTreeFontData): Added.
(WebCore::GlyphPageTreeNode::getChild): Added code to update the font
data's maximum glyph page tree level.
(WebCore::GlyphPageTreeNode::pruneFontData): Added.
* platform/graphics/GlyphPageTreeNode.h:
* platform/graphics/SimpleFontData.cpp:
(WebCore::SimpleFontData::~SimpleFontData): Added code to let the font
cache know that we no longer need the small caps font data and to prune
the glyph page trees.
2008-05-12 Anders Carlsson <andersca@apple.com>
Reviewed by Alexey.
......@@ -360,6 +360,7 @@ __ZN7WebCore16createFullMarkupEPKNS_5RangeE
__ZN7WebCore16enclosingIntRectERK7_NSRect
__ZN7WebCore16isEndOfParagraphERKNS_15VisiblePositionE
__ZN7WebCore17DOMImplementation14isTextMIMETypeERKNS_6StringE
__ZN7WebCore17GlyphPageTreeNode18treeGlyphPageCountEv
__ZN7WebCore17equalIgnoringCaseEPNS_10StringImplES1_
__ZN7WebCore18PlatformMouseEventC1EP7NSEvent
__ZN7WebCore18isStartOfParagraphERKNS_15VisiblePositionE
......@@ -578,6 +579,9 @@ __ZN7WebCore8Settings41setNeedsKeyboardEventDisambiguationQuirksEb
__ZN7WebCore8blankURLEv
__ZN7WebCore8parseURLERKNS_6StringE
__ZN7WebCore9FloatRectC1ERK7_NSRect
__ZN7WebCore9FontCache13fontDataCountEv
__ZN7WebCore9FontCache21inactiveFontDataCountEv
__ZN7WebCore9FontCache21purgeInactiveFontDataEi
__ZN7WebCore9FrameTree11appendChildEN3WTF10PassRefPtrINS_5FrameEEE
__ZN7WebCore9FrameTree7setNameERKNS_12AtomicStringE
__ZN7WebCore9FrameView12setMediaTypeERKNS_6StringE
......
......@@ -293,7 +293,7 @@ Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
}
Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
: m_fontList(new FontFallbackList)
: m_fontList(FontFallbackList::create())
, m_pageZero(0)
, m_cachedPrimaryFont(0)
, m_letterSpacing(0)
......@@ -500,7 +500,7 @@ void Font::update(PassRefPtr<FontSelector> fontSelector) const
// won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
// and could eventually be rectified by using RefPtrs for Fonts themselves.
if (!m_fontList)
m_fontList = new FontFallbackList();
m_fontList = FontFallbackList::create();
m_fontList->invalidate(fontSelector);
m_cachedPrimaryFont = 0;
m_pageZero = 0;
......
......@@ -36,6 +36,7 @@
#include "FontSelector.h"
#include "StringHash.h"
#include <wtf/HashMap.h>
#include <wtf/ListHashSet.h>
using namespace WTF;
......@@ -214,25 +215,87 @@ struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
}
};
typedef HashMap<FontPlatformData, SimpleFontData*, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache;
typedef HashMap<FontPlatformData, pair<SimpleFontData*, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache;
static FontDataCache* gFontDataCache = 0;
const int cMaxInactiveFontData = 120; // Pretty Low Threshold
const float cInactiveFontDataPurgeRatio = 0.2f;
static ListHashSet<const SimpleFontData*>* gInactiveFontData = 0;
SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData)
{
if (!platformData)
return 0;
if (!gFontDataCache)
if (!gFontDataCache) {
gFontDataCache = new FontDataCache;
gInactiveFontData = new ListHashSet<const SimpleFontData*>;
}
SimpleFontData* result = gFontDataCache->get(*platformData);
if (!result) {
result = new SimpleFontData(*platformData);
gFontDataCache->set(*platformData, result);
FontDataCache::iterator result = gFontDataCache->find(*platformData);
if (result == gFontDataCache->end()) {
if (gInactiveFontData->size() > cMaxInactiveFontData)
purgeInactiveFontData(cMaxInactiveFontData * cInactiveFontDataPurgeRatio);
pair<SimpleFontData*, unsigned> newValue(new SimpleFontData(*platformData), 1);
gFontDataCache->set(*platformData, newValue);
return newValue.first;
}
return result;
if (!result.get()->second.second++) {
ASSERT(gInactiveFontData->contains(result.get()->second.first));
gInactiveFontData->remove(result.get()->second.first);
}
return result.get()->second.first;
}
void FontCache::releaseFontData(const SimpleFontData* fontData)
{
ASSERT(gFontDataCache);
ASSERT(!fontData->isCustomFont());
FontDataCache::iterator it = gFontDataCache->find(static_cast<const SimpleFontData*>(fontData)->platformData());
ASSERT(it != gFontDataCache->end());
if (!--it->second.second)
gInactiveFontData->add(static_cast<const SimpleFontData*>(fontData));
}
void FontCache::purgeInactiveFontData(int count)
{
if (!gInactiveFontData)
return;
ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end();
ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin();
for (int i = 0; i < count && it != end; ++it, ++i) {
const SimpleFontData* fontData = *it.get();
gFontDataCache->remove(fontData->platformData());
delete fontData;
}
if (it == end) {
// Removed everything
gInactiveFontData->clear();
} else {
for (int i = 0; i < count; ++i)
gInactiveFontData->remove(gInactiveFontData->begin());
}
}
size_t FontCache::fontDataCount()
{
if (gFontDataCache)
return gFontDataCache->size();
return 0;
}
size_t FontCache::inactiveFontDataCount()
{
if (gInactiveFontData)
return gInactiveFontData->size();
return 0;
}
const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector)
......
......@@ -50,8 +50,10 @@ class SimpleFontData;
class FontCache {
public:
static const FontData* getFontData(const Font&, int& familyIndex, FontSelector*);
static void releaseFontData(const SimpleFontData*);
// This method is implemented by the platform.
// FIXME: Font data returned by this method never go inactive because callers don't track and release them.
static const SimpleFontData* getFontDataForCharacters(const Font&, const UChar* characters, int length);
// Also implemented by the platform.
......@@ -66,7 +68,11 @@ public:
static FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false);
static SimpleFontData* getCachedFontData(const FontPlatformData*);
static FontPlatformData* getLastResortFallbackFont(const FontDescription&);
static size_t fontDataCount();
static size_t inactiveFontDataCount();
static void purgeInactiveFontData(int count = INT_MAX);
private:
// These methods are implemented by each platform.
static FontPlatformData* getSimilarFontPlatformData(const Font&);
......
......@@ -35,6 +35,11 @@ class SimpleFontData;
class FontData : Noncopyable {
public:
FontData()
: m_maxGlyphPageTreeLevel(0)
{
}
virtual ~FontData();
virtual const SimpleFontData* fontDataForCharacter(UChar32) const = 0;
......@@ -42,6 +47,12 @@ public:
virtual bool isCustomFont() const = 0;
virtual bool isLoading() const = 0;
virtual bool isSegmented() const = 0;
void setMaxGlyphPageTreeLevel(unsigned level) const { m_maxGlyphPageTreeLevel = level; }
unsigned maxGlyphPageTreeLevel() const { return m_maxGlyphPageTreeLevel; }
private:
mutable unsigned m_maxGlyphPageTreeLevel;
};
} // namespace WebCore
......
......@@ -36,8 +36,7 @@
namespace WebCore {
FontFallbackList::FontFallbackList()
: RefCounted<FontFallbackList>(0)
, m_familyIndex(0)
: m_familyIndex(0)
, m_pitch(UnknownPitch)
, m_loadingCustomFonts(false)
, m_fontSelector(0)
......@@ -46,6 +45,7 @@ FontFallbackList::FontFallbackList()
void FontFallbackList::invalidate(PassRefPtr<FontSelector> fontSelector)
{
releaseFontData();
m_fontList.clear();
m_familyIndex = 0;
m_pitch = UnknownPitch;
......@@ -53,6 +53,17 @@ void FontFallbackList::invalidate(PassRefPtr<FontSelector> fontSelector)
m_fontSelector = fontSelector;
}
void FontFallbackList::releaseFontData()
{
unsigned numFonts = m_fontList.size();
for (unsigned i = 0; i < numFonts; ++i) {
if (!m_fontList[i].second) {
ASSERT(!m_fontList[i].first->isSegmented());
FontCache::releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first));
}
}
}
void FontFallbackList::determinePitch(const Font* font) const
{
const FontData* fontData = primaryFont(font);
......@@ -71,7 +82,7 @@ void FontFallbackList::determinePitch(const Font* font) const
const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realizedFontIndex) const
{
if (realizedFontIndex < m_fontList.size())
return m_fontList[realizedFontIndex]; // This fallback font is already in our list.
return m_fontList[realizedFontIndex].first; // This fallback font is already in our list.
// Make sure we're not passing in some crazy value here.
ASSERT(realizedFontIndex == m_fontList.size());
......@@ -85,7 +96,7 @@ const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realized
// |m_familyIndex| as it scans for the right font to make.
const FontData* result = FontCache::getFontData(*font, m_familyIndex, m_fontSelector.get());
if (result) {
m_fontList.append(result);
m_fontList.append(pair<const FontData*, bool>(result, result->isCustomFont()));
if (result->isLoading())
m_loadingCustomFonts = true;
}
......@@ -110,7 +121,8 @@ const FontData* FontFallbackList::fontDataForCharacters(const Font* font, const
void FontFallbackList::setPlatformFont(const FontPlatformData& platformData)
{
m_familyIndex = cAllFamiliesScanned;
m_fontList.append(FontCache::getCachedFontData(&platformData));
const FontData* fontData = FontCache::getCachedFontData(&platformData);
m_fontList.append(pair<const FontData*, bool>(fontData, fontData->isCustomFont()));
}
}
......@@ -41,8 +41,9 @@ const int cAllFamiliesScanned = -1;
class FontFallbackList : public RefCounted<FontFallbackList> {
public:
FontFallbackList();
static PassRefPtr<FontFallbackList> create() { return adoptRef(new FontFallbackList()); }
~FontFallbackList() { releaseFontData(); }
void invalidate(PassRefPtr<FontSelector>);
bool isFixedPitch(const Font* f) const { if (m_pitch == UnknownPitch) determinePitch(f); return m_pitch == FixedPitch; };
......@@ -53,13 +54,17 @@ public:
FontSelector* fontSelector() const { return m_fontSelector.get(); }
private:
FontFallbackList();
const FontData* primaryFont(const Font* f) const { return fontDataAt(f, 0); }
const FontData* fontDataAt(const Font*, unsigned index) const;
const FontData* fontDataForCharacters(const Font*, const UChar*, int length) const;
void setPlatformFont(const FontPlatformData&);
mutable Vector<const FontData*, 1> m_fontList;
void releaseFontData();
mutable Vector<pair<const FontData*, bool>, 1> m_fontList;
mutable int m_familyIndex;
mutable Pitch m_pitch;
mutable bool m_loadingCustomFonts;
......
......@@ -65,6 +65,31 @@ GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber)
return node;
}
size_t GlyphPageTreeNode::treeGlyphPageCount()
{
size_t count = 0;
if (roots) {
HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end();
for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it)
count += it->second->pageCount();
}
if (pageZeroRoot)
count += pageZeroRoot->pageCount();
return count;
}
size_t GlyphPageTreeNode::pageCount() const
{
size_t count = m_page && m_page->owner() == this ? 1 : 0;
HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator end = m_children.end();
for (HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator it = m_children.begin(); it != end; ++it)
count += it->second->pageCount();
return count;
}
void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData)
{
// Enumerate all the roots and prune any tree that contains our custom font data.
......@@ -78,6 +103,18 @@ void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData)
pageZeroRoot->pruneCustomFontData(fontData);
}
void GlyphPageTreeNode::pruneTreeFontData(const SimpleFontData* fontData)
{
if (roots) {
HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end();
for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it)
it->second->pruneFontData(fontData);
}
if (pageZeroRoot)
pageZeroRoot->pruneFontData(fontData);
}
GlyphPageTreeNode::~GlyphPageTreeNode()
{
deleteAllValues(m_children);
......@@ -264,9 +301,10 @@ GlyphPageTreeNode* GlyphPageTreeNode::getChild(const FontData* fontData, unsigne
#ifndef NDEBUG
child->m_pageNumber = m_pageNumber;
#endif
if (fontData)
if (fontData) {
m_children.set(fontData, child);
else {
fontData->setMaxGlyphPageTreeLevel(max(fontData->maxGlyphPageTreeLevel(), child->m_level));
} else {
m_systemFallbackChild = child;
child->m_isSystemFallback = true;
}
......@@ -298,4 +336,36 @@ void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData)
it->second->pruneCustomFontData(fontData);
}
void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned level)
{
ASSERT(fontData);
if (!fontData)
return;
// Prune any branch that contains this FontData.
HashMap<const FontData*, GlyphPageTreeNode*>::iterator child = m_children.find(fontData);
if (child == m_children.end()) {
// If there is no level-1 node for fontData, then there is no deeper node for it in this tree.
if (!level)
return;
} else {
GlyphPageTreeNode* node = child->second;
m_children.remove(fontData);
unsigned customFontCount = node->m_customFontCount;
delete node;
if (customFontCount) {
for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent)
curr->m_customFontCount -= customFontCount;
}
}
level++;
if (level > fontData->maxGlyphPageTreeLevel())
return;
HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end();
for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it)
it->second->pruneFontData(fontData, level);
}
}
......@@ -134,8 +134,10 @@ public:
}
static void pruneTreeCustomFontData(const FontData*);
static void pruneTreeFontData(const SimpleFontData*);
void pruneCustomFontData(const FontData*);
void pruneFontData(const SimpleFontData*, unsigned level = 0);
GlyphPageTreeNode* parent() const { return m_parent; }
GlyphPageTreeNode* getChild(const FontData*, unsigned pageNumber);
......@@ -149,6 +151,9 @@ public:
// The system fallback font has special rules (see above).
bool isSystemFallback() const { return m_isSystemFallback; }
static size_t treeGlyphPageCount();
size_t pageCount() const;
private:
static GlyphPageTreeNode* getRoot(unsigned pageNumber);
void initializePage(const FontData*, unsigned pageNumber);
......
......@@ -30,6 +30,7 @@
#include "config.h"
#include "SimpleFontData.h"
#include "FontCache.h"
#if ENABLE(SVG_FONTS)
#include "SVGFontData.h"
#include "SVGFontFaceElement.h"
......@@ -115,13 +116,16 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool
SimpleFontData::~SimpleFontData()
{
if (!isCustomFont()) {
if (m_smallCapsFontData)
FontCache::releaseFontData(m_smallCapsFontData);
GlyphPageTreeNode::pruneTreeFontData(this);
}
#if ENABLE(SVG_FONTS) && !PLATFORM(QT)
if (!m_svgFontData || !m_svgFontData->svgFontFaceElement())
#endif
platformDestroy();
// We only get deleted when the cache gets cleared. Since the smallCapsRenderer is also in that cache,
// it will be deleted then, so we don't need to do anything here.
}
float SimpleFontData::widthForGlyph(Glyph glyph) const
......
2008-05-12 Dan Bernstein <mitz@apple.com>
Reviewed by Ada Chan.
- WebKit/mac changes for https://bugs.webkit.org/show_bug.cgi?id=17097
<rdar://problem/5715471> CGFontRefs (and HFONTs on Windows) leak because FontCache grows without bound
Added font cache statistics and a function to purge inactive font data.
* Misc/WebCoreStatistics.h:
* Misc/WebCoreStatistics.mm:
(+[WebCoreStatistics cachedFontDataCount]):
(+[WebCoreStatistics cachedFontDataInactiveCount]):
(+[WebCoreStatistics purgeInactiveFontData]):
(+[WebCoreStatistics glyphPageCount]):
2008-05-12 Mark Rowe <mrowe@apple.com>
Reviewed by Tim Hatcher.
......
......@@ -50,6 +50,11 @@
+ (size_t)iconRecordCount;
+ (size_t)iconsWithDataCount;
+ (size_t)cachedFontDataCount;
+ (size_t)cachedFontDataInactiveCount;
+ (void)purgeInactiveFontData;
+ (size_t)glyphPageCount;
+ (BOOL)shouldPrintExceptions;
+ (void)setShouldPrintExceptions:(BOOL)print;
......
......@@ -31,8 +31,10 @@
#import "WebCache.h"
#import "WebFrameInternal.h"
#import <JavaScriptCore/interpreter.h>
#import <WebCore/FontCache.h>
#import <WebCore/Frame.h>
#import <WebCore/GCController.h>
#import <WebCore/GlyphPageTreeNode.h>
#import <WebCore/IconDatabase.h>
#import <WebCore/RenderTreeAsText.h>
#import <WebCore/RenderView.h>
......@@ -116,6 +118,26 @@ using namespace WebCore;
return iconDatabase()->iconRecordCountWithData();
}
+ (size_t)cachedFontDataCount
{
return FontCache::fontDataCount();
}
+ (size_t)cachedFontDataInactiveCount
{
return FontCache::inactiveFontDataCount();
}
+ (void)purgeInactiveFontData
{
FontCache::purgeInactiveFontData();
}
+ (size_t)glyphPageCount
{
return GlyphPageTreeNode::treeGlyphPageCount();
}
+ (BOOL)shouldPrintExceptions
{
JSLock lock;
......
2008-05-12 Dan Bernstein <mitz@apple.com>
Reviewed by Ada Chan.
- WebKit/win changes for https://bugs.webkit.org/show_bug.cgi?id=17097
<rdar://problem/5715471> CGFontRefs (and HFONTs on Windows) leak because FontCache grows without bound
Added font cache statistics and a function to purge inactive font data.
* Interfaces/IWebCoreStatistics.idl:
* WebCoreStatistics.cpp:
(WebCoreStatistics::cachedFontDataCount):
(WebCoreStatistics::cachedFontDataInactiveCount):
(WebCoreStatistics::purgeInactiveFontData):
(WebCoreStatistics::glyphPageCount):
* WebCoreStatistics.h:
2008-05-12 Adam Roben <aroben@apple.com>
Build fix
......
......@@ -46,4 +46,9 @@ interface IWebCoreStatistics : IUnknown
HRESULT iconRetainedPageURLCount([out, retval] UINT* count);
HRESULT iconRecordCount([out, retval] UINT* count);
HRESULT iconsWithDataCount([out, retval] UINT* count);
HRESULT cachedFontDataCount([out, retval] UINT* count);
HRESULT cachedFontDataInactiveCount([out, retval] UINT* count);
HRESULT purgeInactiveFontData();
HRESULT glyphPageCount([out, retval] UINT* count);
}
......@@ -27,6 +27,8 @@
#include "WebKitDLL.h"
#include "WebCoreStatistics.h"
#include <WebCore/FontCache.h>
#include <WebCore/GlyphPageTreeNode.h>
#include <WebCore/IconDatabase.h>
#pragma warning(push, 0)
......@@ -167,3 +169,36 @@ HRESULT STDMETHODCALLTYPE WebCoreStatistics::iconsWithDataCount(
*count = (UINT) iconDatabase()->iconRecordCountWithData();
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebCoreStatistics::cachedFontDataCount(