Bug 1124545 - Avoid creating the mergedFeatures hash table when possible. r=jdaggett.

When scrolling all the way through
https://bugzilla.mozilla.org/show_bug.cgi?id=MNG, |mergedFeatures| gets
initialized more than 50,000 times -- each one involving a heap allocation for
the entry storage -- but it never has anything put into it.

This patch refactors MergeFontFeatures to move |mergedFeatures| inside it. It
now doesn't get created in the common case.

--HG--
extra : rebase_source : 5a8d44b30f90169b70e5f50a5e38bbe57f02b12b
This commit is contained in:
Nicholas Nethercote 2015-01-21 22:41:02 -08:00
parent 96ba494c97
commit 7d9cc5ecf2
4 changed files with 48 additions and 50 deletions

View File

@ -442,34 +442,37 @@ LookupAlternateValues(gfxFontFeatureValueSet *featureLookup,
}
}
/* static */ bool
/* static */ void
gfxFontShaper::MergeFontFeatures(
const gfxFontStyle *aStyle,
const nsTArray<gfxFontFeature>& aFontFeatures,
bool aDisableLigatures,
const nsAString& aFamilyName,
bool aAddSmallCaps,
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures)
PLDHashOperator (*aHandleFeature)(const uint32_t&, uint32_t&, void*),
void* aHandleFeatureData)
{
uint32_t numAlts = aStyle->alternateValues.Length();
const nsTArray<gfxFontFeature>& styleRuleFeatures =
aStyle->featureSettings;
// bail immediately if nothing to do
// Bail immediately if nothing to do, which is the common case.
if (styleRuleFeatures.IsEmpty() &&
aFontFeatures.IsEmpty() &&
!aDisableLigatures &&
aStyle->variantCaps == NS_FONT_VARIANT_CAPS_NORMAL &&
aStyle->variantSubSuper == NS_FONT_VARIANT_POSITION_NORMAL &&
numAlts == 0) {
return false;
return;
}
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
// Ligature features are enabled by default in the generic shaper,
// so we explicitly turn them off if necessary (for letter-spacing)
if (aDisableLigatures) {
aMergedFeatures.Put(HB_TAG('l','i','g','a'), 0);
aMergedFeatures.Put(HB_TAG('c','l','i','g'), 0);
mergedFeatures.Put(HB_TAG('l','i','g','a'), 0);
mergedFeatures.Put(HB_TAG('c','l','i','g'), 0);
}
// add feature values from font
@ -478,7 +481,7 @@ gfxFontShaper::MergeFontFeatures(
count = aFontFeatures.Length();
for (i = 0; i < count; i++) {
const gfxFontFeature& feature = aFontFeatures.ElementAt(i);
aMergedFeatures.Put(feature.mTag, feature.mValue);
mergedFeatures.Put(feature.mTag, feature.mValue);
}
// font-variant-caps - handled here due to the need for fallback handling
@ -486,27 +489,27 @@ gfxFontShaper::MergeFontFeatures(
uint32_t variantCaps = aStyle->variantCaps;
switch (variantCaps) {
case NS_FONT_VARIANT_CAPS_ALLSMALL:
aMergedFeatures.Put(HB_TAG('c','2','s','c'), 1);
mergedFeatures.Put(HB_TAG('c','2','s','c'), 1);
// fall through to the small-caps case
case NS_FONT_VARIANT_CAPS_SMALLCAPS:
aMergedFeatures.Put(HB_TAG('s','m','c','p'), 1);
mergedFeatures.Put(HB_TAG('s','m','c','p'), 1);
break;
case NS_FONT_VARIANT_CAPS_ALLPETITE:
aMergedFeatures.Put(aAddSmallCaps ? HB_TAG('c','2','s','c') :
HB_TAG('c','2','p','c'), 1);
mergedFeatures.Put(aAddSmallCaps ? HB_TAG('c','2','s','c') :
HB_TAG('c','2','p','c'), 1);
// fall through to the petite-caps case
case NS_FONT_VARIANT_CAPS_PETITECAPS:
aMergedFeatures.Put(aAddSmallCaps ? HB_TAG('s','m','c','p') :
HB_TAG('p','c','a','p'), 1);
mergedFeatures.Put(aAddSmallCaps ? HB_TAG('s','m','c','p') :
HB_TAG('p','c','a','p'), 1);
break;
case NS_FONT_VARIANT_CAPS_TITLING:
aMergedFeatures.Put(HB_TAG('t','i','t','l'), 1);
mergedFeatures.Put(HB_TAG('t','i','t','l'), 1);
break;
case NS_FONT_VARIANT_CAPS_UNICASE:
aMergedFeatures.Put(HB_TAG('u','n','i','c'), 1);
mergedFeatures.Put(HB_TAG('u','n','i','c'), 1);
break;
default:
@ -516,10 +519,10 @@ gfxFontShaper::MergeFontFeatures(
// font-variant-position - handled here due to the need for fallback
switch (aStyle->variantSubSuper) {
case NS_FONT_VARIANT_POSITION_SUPER:
aMergedFeatures.Put(HB_TAG('s','u','p','s'), 1);
mergedFeatures.Put(HB_TAG('s','u','p','s'), 1);
break;
case NS_FONT_VARIANT_POSITION_SUB:
aMergedFeatures.Put(HB_TAG('s','u','b','s'), 1);
mergedFeatures.Put(HB_TAG('s','u','b','s'), 1);
break;
default:
break;
@ -536,7 +539,7 @@ gfxFontShaper::MergeFontFeatures(
count = featureList.Length();
for (i = 0; i < count; i++) {
const gfxFontFeature& feature = featureList.ElementAt(i);
aMergedFeatures.Put(feature.mTag, feature.mValue);
mergedFeatures.Put(feature.mTag, feature.mValue);
}
}
@ -544,10 +547,12 @@ gfxFontShaper::MergeFontFeatures(
count = styleRuleFeatures.Length();
for (i = 0; i < count; i++) {
const gfxFontFeature& feature = styleRuleFeatures.ElementAt(i);
aMergedFeatures.Put(feature.mTag, feature.mValue);
mergedFeatures.Put(feature.mTag, feature.mValue);
}
return aMergedFeatures.Count() != 0;
if (mergedFeatures.Count() != 0) {
mergedFeatures.Enumerate(aHandleFeature, aHandleFeatureData);
}
}
void

View File

@ -636,14 +636,15 @@ public:
gfxFont *GetFont() const { return mFont; }
// returns true if features exist in output, false otherwise
static bool
static void
MergeFontFeatures(const gfxFontStyle *aStyle,
const nsTArray<gfxFontFeature>& aFontFeatures,
bool aDisableLigatures,
const nsAString& aFamilyName,
bool aAddSmallCaps,
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures);
PLDHashOperator (*aHandleFeature)(const uint32_t&,
uint32_t&, void*),
void* aHandleFeatureData);
protected:
// the font this shaper is working with

View File

@ -152,20 +152,15 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
}
gr_feature_val *grFeatures = gr_face_featureval_for_lang(mGrFace, grLang);
// if style contains font-specific features
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
if (MergeFontFeatures(style,
mFont->GetFontEntry()->mFeatureSettings,
aShapedText->DisableLigatures(),
mFont->GetFontEntry()->FamilyName(),
mFallbackToSmallCaps,
mergedFeatures))
{
// enumerate result and insert into Graphite feature list
GrFontFeatures f = {mGrFace, grFeatures};
mergedFeatures.Enumerate(AddFeature, &f);
}
// insert any merged features into Graphite feature list
GrFontFeatures f = {mGrFace, grFeatures};
MergeFontFeatures(style,
mFont->GetFontEntry()->mFeatureSettings,
aShapedText->DisableLigatures(),
mFont->GetFontEntry()->FamilyName(),
mFallbackToSmallCaps,
AddFeature,
&f);
size_t numChars = gr_count_unicode_characters(gr_utf16,
aText, aText + aLength,

View File

@ -1272,9 +1272,6 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
const gfxFontStyle *style = mFont->GetStyle();
nsAutoTArray<hb_feature_t,20> features;
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
// determine whether petite-caps falls back to small-caps
bool addSmallCaps = false;
if (style->variantCaps != NS_FONT_VARIANT_CAPS_NORMAL) {
@ -1291,16 +1288,16 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
}
gfxFontEntry *entry = mFont->GetFontEntry();
if (MergeFontFeatures(style,
entry->mFeatureSettings,
aShapedText->DisableLigatures(),
entry->FamilyName(),
addSmallCaps,
mergedFeatures))
{
// enumerate result and insert into hb_feature array
mergedFeatures.Enumerate(AddOpenTypeFeature, &features);
}
// insert any merged features into hb_feature array
nsAutoTArray<hb_feature_t,20> features;
MergeFontFeatures(style,
entry->mFeatureSettings,
aShapedText->DisableLigatures(),
entry->FamilyName(),
addSmallCaps,
AddOpenTypeFeature,
&features);
bool isRightToLeft = aShapedText->IsRightToLeft();
hb_buffer_t *buffer = hb_buffer_create();