Bug 1348606 - Use a threadsafe array for counters. r=xidorn

MozReview-Commit-ID: KgTgcD5mGqr
This commit is contained in:
Bobby Holley 2017-03-22 15:01:52 -07:00
Родитель b9b58624ea
Коммит fee01f78fb
9 изменённых файлов: 73 добавлений и 20 удалений

Просмотреть файл

@ -1741,7 +1741,7 @@ nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
case eStyleContentType_Counter: case eStyleContentType_Counter:
case eStyleContentType_Counters: { case eStyleContentType_Counters: {
nsCSSValue::Array* counters = data.GetCounters(); nsCSSValue::ThreadSafeArray* counters = data.GetCounters();
nsCounterList* counterList = mCounterManager.CounterListFor( nsCounterList* counterList = mCounterManager.CounterListFor(
nsDependentString(counters->Item(0).GetStringBufferValue())); nsDependentString(counters->Item(0).GetStringBufferValue()));

Просмотреть файл

@ -79,7 +79,7 @@ struct nsCounterUseNode : public nsCounterNode {
// The same structure passed through the style system: an array // The same structure passed through the style system: an array
// containing the values in the counter() or counters() in the order // containing the values in the counter() or counters() in the order
// given in the CSS spec. // given in the CSS spec.
RefPtr<nsCSSValue::Array> mCounterFunction; RefPtr<nsCSSValue::ThreadSafeArray> mCounterFunction;
nsPresContext* mPresContext; nsPresContext* mPresContext;
RefPtr<mozilla::CounterStyle> mCounterStyle; RefPtr<mozilla::CounterStyle> mCounterStyle;
@ -89,7 +89,7 @@ struct nsCounterUseNode : public nsCounterNode {
// args go directly to member variables here and of nsGenConNode // args go directly to member variables here and of nsGenConNode
nsCounterUseNode(nsPresContext* aPresContext, nsCounterUseNode(nsPresContext* aPresContext,
nsCSSValue::Array* aCounterFunction, nsCSSValue::ThreadSafeArray* aCounterFunction,
uint32_t aContentIndex, bool aAllCounters) uint32_t aContentIndex, bool aAllCounters)
: nsCounterNode(aContentIndex, USE) : nsCounterNode(aContentIndex, USE)
, mCounterFunction(aCounterFunction) , mCounterFunction(aCounterFunction)

Просмотреть файл

@ -958,7 +958,7 @@ void
Gecko_SetContentDataArray(nsStyleContentData* aContent, Gecko_SetContentDataArray(nsStyleContentData* aContent,
nsStyleContentType aType, uint32_t aLen) nsStyleContentType aType, uint32_t aLen)
{ {
nsCSSValue::Array* arr = nsCSSValue::Array::Create(aLen); nsCSSValue::ThreadSafeArray* arr = nsCSSValue::ThreadSafeArray::Create(aLen);
aContent->SetCounters(aType, arr); aContent->SetCounters(aType, arr);
} }

Просмотреть файл

@ -8026,8 +8026,8 @@ CSSParserImpl::ParseCounter(nsCSSValue& aValue)
break; break;
} }
RefPtr<nsCSSValue::Array> val = RefPtr<nsCSSValue::ThreadSafeArray> val =
nsCSSValue::Array::Create(unit == eCSSUnit_Counter ? 2 : 3); nsCSSValue::ThreadSafeArray::Create(unit == eCSSUnit_Counter ? 2 : 3);
val->Item(0).SetStringValue(mToken.mIdent, eCSSUnit_Ident); val->Item(0).SetStringValue(mToken.mIdent, eCSSUnit_Ident);
@ -8058,7 +8058,7 @@ CSSParserImpl::ParseCounter(nsCSSValue& aValue)
break; break;
} }
aValue.SetArrayValue(val, unit); aValue.SetThreadSafeArrayValue(val, unit);
return true; return true;
} }

Просмотреть файл

@ -172,6 +172,10 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
mValue.mArray = aCopy.mValue.mArray; mValue.mArray = aCopy.mValue.mArray;
mValue.mArray->AddRef(); mValue.mArray->AddRef();
} }
else if (UnitHasThreadSafeArrayValue()) {
mValue.mThreadSafeArray = aCopy.mValue.mThreadSafeArray;
mValue.mThreadSafeArray->AddRef();
}
else if (eCSSUnit_URL == mUnit) { else if (eCSSUnit_URL == mUnit) {
mValue.mURL = aCopy.mValue.mURL; mValue.mURL = aCopy.mValue.mURL;
mValue.mURL->AddRef(); mValue.mURL->AddRef();
@ -288,6 +292,9 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
else if (UnitHasArrayValue()) { else if (UnitHasArrayValue()) {
return *mValue.mArray == *aOther.mValue.mArray; return *mValue.mArray == *aOther.mValue.mArray;
} }
else if (UnitHasThreadSafeArrayValue()) {
return *mValue.mThreadSafeArray == *aOther.mValue.mThreadSafeArray;
}
else if (eCSSUnit_URL == mUnit) { else if (eCSSUnit_URL == mUnit) {
return mValue.mURL->Equals(*aOther.mValue.mURL); return mValue.mURL->Equals(*aOther.mValue.mURL);
} }
@ -436,6 +443,9 @@ void nsCSSValue::DoReset()
DO_RELEASE(mComplexColor); DO_RELEASE(mComplexColor);
} else if (UnitHasArrayValue()) { } else if (UnitHasArrayValue()) {
DO_RELEASE(mArray); DO_RELEASE(mArray);
} else if (UnitHasThreadSafeArrayValue()) {
// ThreadSafe arrays are ok to release on any thread.
mValue.mThreadSafeArray->Release();
} else if (eCSSUnit_URL == mUnit) { } else if (eCSSUnit_URL == mUnit) {
DO_RELEASE(mURL); DO_RELEASE(mURL);
} else if (eCSSUnit_Image == mUnit) { } else if (eCSSUnit_Image == mUnit) {
@ -571,6 +581,15 @@ void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
mValue.mArray->AddRef(); mValue.mArray->AddRef();
} }
void nsCSSValue::SetThreadSafeArrayValue(nsCSSValue::ThreadSafeArray* aValue, nsCSSUnit aUnit)
{
Reset();
mUnit = aUnit;
MOZ_ASSERT(UnitHasThreadSafeArrayValue(), "bad unit");
mValue.mThreadSafeArray = aValue;
mValue.mThreadSafeArray->AddRef();
}
void nsCSSValue::SetURLValue(mozilla::css::URLValue* aValue) void nsCSSValue::SetURLValue(mozilla::css::URLValue* aValue)
{ {
Reset(); Reset();
@ -1339,10 +1358,29 @@ nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult); nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult);
} }
} }
else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Symbols) { else if (eCSSUnit_Counter <= unit && unit <= eCSSUnit_Counters) {
switch (unit) { switch (unit) {
case eCSSUnit_Counter: aResult.AppendLiteral("counter("); break; case eCSSUnit_Counter: aResult.AppendLiteral("counter("); break;
case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break; case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break;
default: MOZ_ASSERT_UNREACHABLE("bad enum");
}
nsCSSValue::ThreadSafeArray *array = GetThreadSafeArrayValue();
bool mark = false;
for (size_t i = 0, i_end = array->Count(); i < i_end; ++i) {
if (mark && array->Item(i).GetUnit() != eCSSUnit_Null) {
aResult.AppendLiteral(", ");
}
nsCSSPropertyID prop = (i == array->Count() - 1)
? eCSSProperty_list_style_type : aProperty;
if (array->Item(i).GetUnit() != eCSSUnit_Null) {
array->Item(i).AppendToString(prop, aResult, aSerialization);
mark = true;
}
}
}
else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Symbols) {
switch (unit) {
case eCSSUnit_Cubic_Bezier: aResult.AppendLiteral("cubic-bezier("); break; case eCSSUnit_Cubic_Bezier: aResult.AppendLiteral("cubic-bezier("); break;
case eCSSUnit_Steps: aResult.AppendLiteral("steps("); break; case eCSSUnit_Steps: aResult.AppendLiteral("steps("); break;
case eCSSUnit_Symbols: aResult.AppendLiteral("symbols("); break; case eCSSUnit_Symbols: aResult.AppendLiteral("symbols("); break;
@ -1386,10 +1424,7 @@ nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
} }
continue; continue;
} }
nsCSSPropertyID prop = nsCSSPropertyID prop = aProperty;
((eCSSUnit_Counter <= unit && unit <= eCSSUnit_Counters) &&
i == array->Count() - 1)
? eCSSProperty_list_style_type : aProperty;
if (array->Item(i).GetUnit() != eCSSUnit_Null) { if (array->Item(i).GetUnit() != eCSSUnit_Null) {
array->Item(i).AppendToString(prop, aResult, aSerialization); array->Item(i).AppendToString(prop, aResult, aSerialization);
mark = true; mark = true;

Просмотреть файл

@ -443,9 +443,9 @@ enum nsCSSUnit {
eCSSUnit_Font_Format = 16, // (char16_t*) a font format name eCSSUnit_Font_Format = 16, // (char16_t*) a font format name
eCSSUnit_Element = 17, // (char16_t*) an element id eCSSUnit_Element = 17, // (char16_t*) an element id
eCSSUnit_Array = 20, // (nsCSSValue::Array*) a list of values eCSSUnit_Counter = 20, // (nsCSSValue::ThreadSafeArray*) a counter(string,[string]) value
eCSSUnit_Counter = 21, // (nsCSSValue::Array*) a counter(string,[string]) value eCSSUnit_Counters = 21, // (nsCSSValue::ThreadSafeArray*) a counters(string,string[,string]) value
eCSSUnit_Counters = 22, // (nsCSSValue::Array*) a counters(string,string[,string]) value eCSSUnit_Array = 22, // (nsCSSValue::Array*) a list of values
eCSSUnit_Cubic_Bezier = 23, // (nsCSSValue::Array*) a list of float values eCSSUnit_Cubic_Bezier = 23, // (nsCSSValue::Array*) a list of float values
eCSSUnit_Steps = 24, // (nsCSSValue::Array*) a list of (integer, enumerated) eCSSUnit_Steps = 24, // (nsCSSValue::Array*) a list of (integer, enumerated)
eCSSUnit_Symbols = 25, // (nsCSSValue::Array*) a symbols(enumerated, symbols) value eCSSUnit_Symbols = 25, // (nsCSSValue::Array*) a symbols(enumerated, symbols) value
@ -582,6 +582,8 @@ class nsCSSValue {
public: public:
struct Array; struct Array;
friend struct Array; friend struct Array;
struct ThreadSafeArray;
friend struct ThreadSafeArray;
friend struct mozilla::css::URLValueData; friend struct mozilla::css::URLValueData;
@ -679,6 +681,8 @@ public:
bool UnitHasStringValue() const bool UnitHasStringValue() const
{ return eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Element; } { return eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Element; }
bool UnitHasThreadSafeArrayValue() const
{ return eCSSUnit_Counter <= mUnit && mUnit <= eCSSUnit_Counters; }
bool UnitHasArrayValue() const bool UnitHasArrayValue() const
{ return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Divided; } { return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Divided; }
@ -783,6 +787,12 @@ public:
return mValue.mArray; return mValue.mArray;
} }
ThreadSafeArray* GetThreadSafeArrayValue() const
{
MOZ_ASSERT(UnitHasThreadSafeArrayValue(), "not a threadsafe array value");
return mValue.mThreadSafeArray;
}
nsIURI* GetURLValue() const nsIURI* GetURLValue() const
{ {
MOZ_ASSERT(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image, MOZ_ASSERT(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
@ -922,6 +932,7 @@ public:
void SetComplexColorValue( void SetComplexColorValue(
already_AddRefed<mozilla::css::ComplexColorValue> aValue); already_AddRefed<mozilla::css::ComplexColorValue> aValue);
void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit); void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
void SetThreadSafeArrayValue(nsCSSValue::ThreadSafeArray* aArray, nsCSSUnit aUnit);
void SetURLValue(mozilla::css::URLValue* aURI); void SetURLValue(mozilla::css::URLValue* aURI);
void SetImageValue(mozilla::css::ImageValue* aImage); void SetImageValue(mozilla::css::ImageValue* aImage);
void SetGradientValue(nsCSSValueGradient* aGradient); void SetGradientValue(nsCSSValueGradient* aGradient);
@ -1022,6 +1033,7 @@ protected:
nscolor mColor; nscolor mColor;
nsIAtom* MOZ_OWNING_REF mAtom; nsIAtom* MOZ_OWNING_REF mAtom;
Array* MOZ_OWNING_REF mArray; Array* MOZ_OWNING_REF mArray;
ThreadSafeArray* MOZ_OWNING_REF mThreadSafeArray;
mozilla::css::URLValue* MOZ_OWNING_REF mURL; mozilla::css::URLValue* MOZ_OWNING_REF mURL;
mozilla::css::ImageValue* MOZ_OWNING_REF mImage; mozilla::css::ImageValue* MOZ_OWNING_REF mImage;
mozilla::css::GridTemplateAreasValue* MOZ_OWNING_REF mGridTemplateAreas; mozilla::css::GridTemplateAreasValue* MOZ_OWNING_REF mGridTemplateAreas;
@ -1041,6 +1053,9 @@ protected:
} mValue; } mValue;
}; };
// We use this macro to declare equivalent logic for Array and ThreadSafeArray.
// It would be much nicer to use a superclass, but the dynamically-sized nature
// of the interesting part of the class makes that tricky.
#define DECLARE_CSS_ARRAY(className, refcntMacro) \ #define DECLARE_CSS_ARRAY(className, refcntMacro) \
struct nsCSSValue::className final { \ struct nsCSSValue::className final { \
\ \
@ -1133,6 +1148,7 @@ private: \
}; };
DECLARE_CSS_ARRAY(Array, NS_INLINE_DECL_REFCOUNTING) DECLARE_CSS_ARRAY(Array, NS_INLINE_DECL_REFCOUNTING)
DECLARE_CSS_ARRAY(ThreadSafeArray, NS_INLINE_DECL_THREADSAFE_REFCOUNTING)
#undef DECLARE_CSS_ARRAY #undef DECLARE_CSS_ARRAY
// Prefer nsCSSValue::Array for lists of fixed size. // Prefer nsCSSValue::Array for lists of fixed size.

Просмотреть файл

@ -1315,7 +1315,7 @@ nsComputedDOMStyle::DoGetContent()
str.AppendLiteral("counters("); str.AppendLiteral("counters(");
} }
// WRITE ME // WRITE ME
nsCSSValue::Array* a = data.GetCounters(); nsCSSValue::ThreadSafeArray* a = data.GetCounters();
nsStyleUtil::AppendEscapedCSSIdent( nsStyleUtil::AppendEscapedCSSIdent(
nsDependentString(a->Item(0).GetStringBufferValue()), str); nsDependentString(a->Item(0).GetStringBufferValue()), str);

Просмотреть файл

@ -9027,7 +9027,7 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
nsStyleContentType type = nsStyleContentType type =
unit == eCSSUnit_Counter ? eStyleContentType_Counter unit == eCSSUnit_Counter ? eStyleContentType_Counter
: eStyleContentType_Counters; : eStyleContentType_Counters;
data.SetCounters(type, value.GetArrayValue()); data.SetCounters(type, value.GetThreadSafeArrayValue());
break; break;
} }
case eCSSUnit_Enumerated: case eCSSUnit_Enumerated:

Просмотреть файл

@ -3020,7 +3020,7 @@ public:
return mContent.mString; return mContent.mString;
} }
nsCSSValue::Array* GetCounters() const nsCSSValue::ThreadSafeArray* GetCounters() const
{ {
MOZ_ASSERT(mType == eStyleContentType_Counter || MOZ_ASSERT(mType == eStyleContentType_Counter ||
mType == eStyleContentType_Counters); mType == eStyleContentType_Counters);
@ -3061,7 +3061,7 @@ public:
mContent.mString = NS_strdup(aString); mContent.mString = NS_strdup(aString);
} }
void SetCounters(nsStyleContentType aType, nsCSSValue::Array* aCounters) void SetCounters(nsStyleContentType aType, nsCSSValue::ThreadSafeArray* aCounters)
{ {
MOZ_ASSERT(aType == eStyleContentType_Counter || MOZ_ASSERT(aType == eStyleContentType_Counter ||
aType == eStyleContentType_Counters); aType == eStyleContentType_Counters);
@ -3094,7 +3094,9 @@ private:
union { union {
char16_t *mString; char16_t *mString;
nsStyleImageRequest* mImage; nsStyleImageRequest* mImage;
nsCSSValue::Array* mCounters; // NB: We need threadsafe refcounts here to enable inheritance in the
// parallel style traversal.
nsCSSValue::ThreadSafeArray* mCounters;
} mContent; } mContent;
}; };