mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1762713 - Move work of InitWordCache inside of GetShapedWord to avoid extra lock-twiddling. r=lsalzman
No behavior change, but this reduces lock-management overhead. Differential Revision: https://phabricator.services.mozilla.com/D142752
This commit is contained in:
parent
a2098c0b7d
commit
9cea60e6b9
@ -2829,42 +2829,30 @@ gfxShapedWord* gfxFont::GetShapedWord(
|
||||
Script aRunScript, nsAtom* aLanguage, bool aVertical,
|
||||
int32_t aAppUnitsPerDevUnit, gfx::ShapedTextFlags aFlags,
|
||||
RoundingFlags aRounding, gfxTextPerfMetrics* aTextPerf GFX_MAYBE_UNUSED) {
|
||||
// if the cache is getting too big, flush it and start over
|
||||
uint32_t wordCacheMaxEntries =
|
||||
gfxPlatform::GetPlatform()->WordCacheMaxEntries();
|
||||
mLock.ReadLock();
|
||||
if (mWordCache->Count() > wordCacheMaxEntries) {
|
||||
// Flush the cache if it is getting overly big.
|
||||
// There's a chance another thread could race with the lock-twiddling here,
|
||||
// but that's OK; it's harmless if we end up calling ClearCacheWords twice
|
||||
// from separate threads. Internally, it will hold the lock exclusively
|
||||
// while doing its thing.
|
||||
mLock.ReadUnlock();
|
||||
NS_WARNING("flushing shaped-word cache");
|
||||
ClearCachedWords();
|
||||
mLock.ReadLock();
|
||||
// Once we've reclaimed a read lock, we can proceed knowing the cache
|
||||
// isn't growing uncontrollably.
|
||||
}
|
||||
|
||||
// if there's a cached entry for this word, just return it
|
||||
CacheHashKey key(aText, aLength, aHash, aRunScript, aLanguage,
|
||||
aAppUnitsPerDevUnit, aFlags, aRounding);
|
||||
|
||||
CacheHashEntry* entry = mWordCache->GetEntry(key);
|
||||
if (entry) {
|
||||
gfxShapedWord* sw = entry->mShapedWord.get();
|
||||
sw->ResetAge();
|
||||
{
|
||||
// If we have a word cache, attempt to look up the word in it.
|
||||
AutoReadLock lock(mLock);
|
||||
if (mWordCache) {
|
||||
// if there's a cached entry for this word, just return it
|
||||
if (CacheHashEntry* entry = mWordCache->GetEntry(key)) {
|
||||
gfxShapedWord* sw = entry->mShapedWord.get();
|
||||
sw->ResetAge();
|
||||
#ifndef RELEASE_OR_BETA
|
||||
if (aTextPerf) {
|
||||
// XXX we should make sure this is atomic
|
||||
aTextPerf->current.wordCacheHit++;
|
||||
}
|
||||
if (aTextPerf) {
|
||||
// XXX we should make sure this is atomic
|
||||
aTextPerf->current.wordCacheHit++;
|
||||
}
|
||||
#endif
|
||||
mLock.ReadUnlock();
|
||||
return sw;
|
||||
return sw;
|
||||
}
|
||||
}
|
||||
}
|
||||
mLock.ReadUnlock();
|
||||
|
||||
// We didn't find a cached word (or don't even have a cache yet), so create
|
||||
// a new gfxShapedWord and cache it. We don't have to lock during shaping,
|
||||
// only when it comes time to cache the new entry.
|
||||
|
||||
gfxShapedWord* sw =
|
||||
gfxShapedWord::Create(aText, aLength, aRunScript, aLanguage,
|
||||
@ -2878,9 +2866,21 @@ gfxShapedWord* gfxFont::GetShapedWord(
|
||||
NS_WARNING_ASSERTION(ok, "failed to shape word - expect garbled text");
|
||||
|
||||
{
|
||||
// We're going to cache the new shaped word, so lock for writing.
|
||||
// We're going to cache the new shaped word, so lock for writing now.
|
||||
AutoWriteLock lock(mLock);
|
||||
entry = mWordCache->PutEntry(key, fallible);
|
||||
if (!mWordCache) {
|
||||
mWordCache = MakeUnique<nsTHashtable<CacheHashEntry>>();
|
||||
} else {
|
||||
// If the cache is getting too big, flush it and start over.
|
||||
uint32_t wordCacheMaxEntries =
|
||||
gfxPlatform::GetPlatform()->WordCacheMaxEntries();
|
||||
if (mWordCache->Count() > wordCacheMaxEntries) {
|
||||
// Flush the cache if it is getting overly big.
|
||||
NS_WARNING("flushing shaped-word cache");
|
||||
ClearCachedWordsLocked();
|
||||
}
|
||||
}
|
||||
CacheHashEntry* entry = mWordCache->PutEntry(key, fallible);
|
||||
if (!entry) {
|
||||
NS_WARNING("failed to create word cache entry - expect missing text");
|
||||
delete sw;
|
||||
@ -3240,8 +3240,6 @@ bool gfxFont::SplitAndInitTextRun(
|
||||
}
|
||||
}
|
||||
|
||||
InitWordCache();
|
||||
|
||||
// the only flags we care about for ShapedWord construction/caching
|
||||
gfx::ShapedTextFlags flags = aTextRun->GetFlags();
|
||||
flags &= (gfx::ShapedTextFlags::TEXT_IS_RTL |
|
||||
|
@ -1877,21 +1877,6 @@ class gfxFont {
|
||||
RoundingFlags aRounding,
|
||||
gfxTextPerfMetrics* aTextPerf);
|
||||
|
||||
// Ensure the ShapedWord cache is initialized. This MUST be called before
|
||||
// any attempt to use GetShapedWord().
|
||||
void InitWordCache() {
|
||||
mLock.ReadLock();
|
||||
if (!mWordCache) {
|
||||
mLock.ReadUnlock();
|
||||
mozilla::AutoWriteLock lock(mLock);
|
||||
if (!mWordCache) {
|
||||
mWordCache = mozilla::MakeUnique<nsTHashtable<CacheHashEntry>>();
|
||||
}
|
||||
} else {
|
||||
mLock.ReadUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Called by the gfxFontCache timer to increment the age of all the words,
|
||||
// so that they'll expire after a sufficient period of non-use.
|
||||
// Returns true if the cache is now empty, otherwise false.
|
||||
@ -1901,9 +1886,13 @@ class gfxFont {
|
||||
void ClearCachedWords() {
|
||||
mozilla::AutoWriteLock lock(mLock);
|
||||
if (mWordCache) {
|
||||
mWordCache->Clear();
|
||||
ClearCachedWordsLocked();
|
||||
}
|
||||
}
|
||||
void ClearCachedWordsLocked() REQUIRES(mLock) {
|
||||
MOZ_ASSERT(mWordCache);
|
||||
mWordCache->Clear();
|
||||
}
|
||||
|
||||
// Glyph rendering/geometry has changed, so invalidate data as necessary.
|
||||
void NotifyGlyphsChanged() const;
|
||||
|
@ -1548,7 +1548,6 @@ void gfxTextRun::SetSpaceGlyph(gfxFont* aFont, DrawTarget* aDrawTarget,
|
||||
return;
|
||||
}
|
||||
|
||||
aFont->InitWordCache();
|
||||
static const uint8_t space = ' ';
|
||||
gfx::ShapedTextFlags flags =
|
||||
gfx::ShapedTextFlags::TEXT_IS_8BIT | aOrientation;
|
||||
|
Loading…
Reference in New Issue
Block a user