Don't call ValueAppended on every single inline style mutation. Should be a
tad faster, and actually serialize better. Bug 288574, r+sr=dbaron, a=asa. git-svn-id: svn://10.0.0.236/trunk@172819 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -646,35 +646,42 @@ nsCSSExpandedDataBlock::ComputeSize()
|
||||
PRUint32 increment = 0;
|
||||
switch (nsCSSProps::kTypeTable[iProp]) {
|
||||
case eCSSType_Value: {
|
||||
#ifdef DEBUG
|
||||
nsCSSValue* val = NS_STATIC_CAST(nsCSSValue*, prop);
|
||||
if (val->GetUnit() != eCSSUnit_Null) {
|
||||
increment = CDBValueStorage_advance;
|
||||
}
|
||||
NS_ASSERTION(val->GetUnit() != eCSSUnit_Null,
|
||||
"null value while computing size");
|
||||
#endif
|
||||
increment = CDBValueStorage_advance;
|
||||
} break;
|
||||
|
||||
case eCSSType_Rect: {
|
||||
#ifdef DEBUG
|
||||
nsCSSRect* val = NS_STATIC_CAST(nsCSSRect*, prop);
|
||||
if (val->HasValue()) {
|
||||
increment = CDBRectStorage_advance;
|
||||
}
|
||||
NS_ASSERTION(val->HasValue(),
|
||||
"Valueless rect while computing size");
|
||||
#endif
|
||||
increment = CDBRectStorage_advance;
|
||||
} break;
|
||||
|
||||
case eCSSType_ValuePair: {
|
||||
#ifdef DEBUG
|
||||
nsCSSValuePair* val = NS_STATIC_CAST(nsCSSValuePair*, prop);
|
||||
if (val->mXValue.GetUnit() != eCSSUnit_Null ||
|
||||
val->mYValue.GetUnit() != eCSSUnit_Null) {
|
||||
increment = CDBValuePairStorage_advance;
|
||||
}
|
||||
NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
|
||||
val->mYValue.GetUnit() != eCSSUnit_Null,
|
||||
"Valueless pair while computing size");
|
||||
#endif
|
||||
increment = CDBValuePairStorage_advance;
|
||||
} break;
|
||||
|
||||
case eCSSType_ValueList:
|
||||
case eCSSType_CounterData:
|
||||
case eCSSType_Quotes:
|
||||
case eCSSType_Shadow: {
|
||||
#ifdef DEBUG
|
||||
void* val = *NS_STATIC_CAST(void**, prop);
|
||||
if (val) {
|
||||
increment = CDBPointerStorage_advance;
|
||||
}
|
||||
NS_ASSERTION(val, "Null pointer while computing size");
|
||||
#endif
|
||||
increment = CDBPointerStorage_advance;
|
||||
} break;
|
||||
}
|
||||
if ((mPropertiesImportant[iHigh] & (1 << iLow)) == 0)
|
||||
@@ -732,7 +739,6 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock,
|
||||
NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands,
|
||||
"out of range");
|
||||
void *prop = PropertyAt(iProp);
|
||||
PRBool present = PR_FALSE;
|
||||
PRBool important =
|
||||
(mPropertiesImportant[iHigh] & (1 << iLow)) != 0;
|
||||
char *&cursor = important ? cursor_important : cursor_normal;
|
||||
@@ -741,42 +747,39 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock,
|
||||
switch (nsCSSProps::kTypeTable[iProp]) {
|
||||
case eCSSType_Value: {
|
||||
nsCSSValue* val = NS_STATIC_CAST(nsCSSValue*, prop);
|
||||
if (val->GetUnit() != eCSSUnit_Null) {
|
||||
CDBValueStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBValueStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
memcpy(&storage->value, val, sizeof(nsCSSValue));
|
||||
new (val) nsCSSValue();
|
||||
cursor += CDBValueStorage_advance;
|
||||
present = PR_TRUE;
|
||||
}
|
||||
NS_ASSERTION(val->GetUnit() != eCSSUnit_Null,
|
||||
"Null value while compressing");
|
||||
CDBValueStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBValueStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
memcpy(&storage->value, val, sizeof(nsCSSValue));
|
||||
new (val) nsCSSValue();
|
||||
cursor += CDBValueStorage_advance;
|
||||
} break;
|
||||
|
||||
case eCSSType_Rect: {
|
||||
nsCSSRect* val = NS_STATIC_CAST(nsCSSRect*, prop);
|
||||
if (val->HasValue()) {
|
||||
CDBRectStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBRectStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
memcpy(&storage->value, val, sizeof(nsCSSRect));
|
||||
new (val) nsCSSRect();
|
||||
cursor += CDBRectStorage_advance;
|
||||
present = PR_TRUE;
|
||||
}
|
||||
NS_ASSERTION(val->HasValue(),
|
||||
"Valueless rect while compressing");
|
||||
CDBRectStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBRectStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
memcpy(&storage->value, val, sizeof(nsCSSRect));
|
||||
new (val) nsCSSRect();
|
||||
cursor += CDBRectStorage_advance;
|
||||
} break;
|
||||
|
||||
case eCSSType_ValuePair: {
|
||||
nsCSSValuePair* val = NS_STATIC_CAST(nsCSSValuePair*, prop);
|
||||
if (val->mXValue.GetUnit() != eCSSUnit_Null ||
|
||||
val->mYValue.GetUnit() != eCSSUnit_Null) {
|
||||
CDBValuePairStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBValuePairStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
memcpy(&storage->value, val, sizeof(nsCSSValuePair));
|
||||
new (val) nsCSSValuePair();
|
||||
cursor += CDBValuePairStorage_advance;
|
||||
present = PR_TRUE;
|
||||
}
|
||||
NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
|
||||
val->mYValue.GetUnit() != eCSSUnit_Null,
|
||||
"Valueless pair while compressing");
|
||||
CDBValuePairStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBValuePairStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
memcpy(&storage->value, val, sizeof(nsCSSValuePair));
|
||||
new (val) nsCSSValuePair();
|
||||
cursor += CDBValuePairStorage_advance;
|
||||
} break;
|
||||
|
||||
case eCSSType_ValueList:
|
||||
@@ -784,21 +787,17 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock,
|
||||
case eCSSType_Quotes:
|
||||
case eCSSType_Shadow: {
|
||||
void*& val = *NS_STATIC_CAST(void**, prop);
|
||||
if (val) {
|
||||
CDBPointerStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBPointerStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
storage->value = val;
|
||||
val = nsnull;
|
||||
cursor += CDBPointerStorage_advance;
|
||||
present = PR_TRUE;
|
||||
}
|
||||
NS_ASSERTION(val, "Null pointer while compressing");
|
||||
CDBPointerStorage *storage =
|
||||
NS_REINTERPRET_CAST(CDBPointerStorage*, cursor);
|
||||
storage->property = iProp;
|
||||
storage->value = val;
|
||||
val = nsnull;
|
||||
cursor += CDBPointerStorage_advance;
|
||||
} break;
|
||||
}
|
||||
if (present) {
|
||||
result->mStyleBits |= nsCachedStyleData::GetBitForSID(
|
||||
nsCSSProps::kSIDTable[iProp]);
|
||||
}
|
||||
result->mStyleBits |=
|
||||
nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -212,11 +212,10 @@ private:
|
||||
(eCSSProperty_COUNT_no_shorthands + (kPropertiesSetChunkSize-1)) /
|
||||
kPropertiesSetChunkSize };
|
||||
/*
|
||||
* mPropertiesSet stores a bit for every property that may be
|
||||
* present, to optimize compression of blocks with small numbers of
|
||||
* properties (the norm). The code does not rely on it to be exact;
|
||||
* it is allowable, although slower, if a bit is erroneously set
|
||||
* even though the property is not present.
|
||||
* mPropertiesSet stores a bit for every property that is present,
|
||||
* to optimize compression of blocks with small numbers of
|
||||
* properties (the norm) and to allow quickly checking whether a
|
||||
* property is set in this block.
|
||||
*/
|
||||
property_set_type mPropertiesSet[kPropertiesSetChunkCount];
|
||||
/*
|
||||
|
||||
@@ -136,6 +136,7 @@ public:
|
||||
mImportantData->Destroy();
|
||||
mImportantData = nsnull;
|
||||
}
|
||||
mOrder.Clear();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -248,18 +248,23 @@ protected:
|
||||
PRBool ParseDeclaration(nsresult& aErrorCode,
|
||||
nsCSSDeclaration* aDeclaration,
|
||||
PRBool aCheckForBraces,
|
||||
PRBool aMustCallValueAppended,
|
||||
PRBool* aChanged);
|
||||
// After a parse error parsing |aPropID|, clear the data in
|
||||
// |mTempData|.
|
||||
void ClearTempData(nsCSSProperty aPropID);
|
||||
// After a successful parse of |aPropID|, transfer data from
|
||||
// |mTempData| to |mData|. Set |*aChanged| to true if something
|
||||
// changed, but leave it unmodified otherwise.
|
||||
// changed, but leave it unmodified otherwise. If aMustCallValueAppended
|
||||
// is false, will not call ValueAppended on aDeclaration if the property
|
||||
// is already set in it.
|
||||
void TransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
nsCSSProperty aPropID, PRBool aIsImportant,
|
||||
PRBool aMustCallValueAppended,
|
||||
PRBool* aChanged);
|
||||
void DoTransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
nsCSSProperty aPropID, PRBool aIsImportant,
|
||||
PRBool aMustCallValueAppended,
|
||||
PRBool* aChanged);
|
||||
PRBool ParseProperty(nsresult& aErrorCode, nsCSSProperty aPropID);
|
||||
PRBool ParseSingleValueProperty(nsresult& aErrorCode, nsCSSValue& aValue,
|
||||
@@ -781,7 +786,10 @@ CSSParserImpl::ParseAndAppendDeclaration(const nsAString& aBuffer,
|
||||
}
|
||||
|
||||
do {
|
||||
if (!ParseDeclaration(errorCode, aDeclaration, PR_FALSE, aChanged)) {
|
||||
// If we cleared the old decl, then we want to be calling
|
||||
// ValueAppended as we parse.
|
||||
if (!ParseDeclaration(errorCode, aDeclaration, PR_FALSE,
|
||||
aClearOldDecl, aChanged)) {
|
||||
NS_ASSERTION(errorCode != nsresult(-1), "-1 is no longer used for EOF");
|
||||
rv = errorCode;
|
||||
|
||||
@@ -882,7 +890,7 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID,
|
||||
aDeclaration->ExpandTo(&mData);
|
||||
nsresult result = NS_OK;
|
||||
if (ParseProperty(errorCode, aPropID)) {
|
||||
TransferTempData(aDeclaration, aPropID, PR_FALSE, aChanged);
|
||||
TransferTempData(aDeclaration, aPropID, PR_FALSE, PR_FALSE, aChanged);
|
||||
} else {
|
||||
NS_ConvertASCIItoUTF16 propName(nsCSSProps::GetStringValue(aPropID));
|
||||
const PRUnichar *params[] = {
|
||||
@@ -2697,7 +2705,7 @@ CSSParserImpl::ParseDeclarationBlock(nsresult& aErrorCode,
|
||||
for (;;) {
|
||||
PRBool changed;
|
||||
if (!ParseDeclaration(aErrorCode, declaration, aCheckForBraces,
|
||||
&changed)) {
|
||||
PR_TRUE, &changed)) {
|
||||
if (!SkipDeclaration(aErrorCode, aCheckForBraces)) {
|
||||
break;
|
||||
}
|
||||
@@ -3075,6 +3083,7 @@ PRBool
|
||||
CSSParserImpl::ParseDeclaration(nsresult& aErrorCode,
|
||||
nsCSSDeclaration* aDeclaration,
|
||||
PRBool aCheckForBraces,
|
||||
PRBool aMustCallValueAppended,
|
||||
PRBool* aChanged)
|
||||
{
|
||||
mTempData.AssertInitialState();
|
||||
@@ -3148,7 +3157,8 @@ CSSParserImpl::ParseDeclaration(nsresult& aErrorCode,
|
||||
ClearTempData(propID);
|
||||
return PR_FALSE;
|
||||
}
|
||||
TransferTempData(aDeclaration, propID, isImportant, aChanged);
|
||||
TransferTempData(aDeclaration, propID, isImportant,
|
||||
aMustCallValueAppended, aChanged);
|
||||
return PR_TRUE;
|
||||
}
|
||||
else {
|
||||
@@ -3193,12 +3203,14 @@ CSSParserImpl::ParseDeclaration(nsresult& aErrorCode,
|
||||
ClearTempData(propID);
|
||||
return PR_FALSE;
|
||||
}
|
||||
TransferTempData(aDeclaration, propID, isImportant, aChanged);
|
||||
TransferTempData(aDeclaration, propID, isImportant,
|
||||
aMustCallValueAppended, aChanged);
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (eCSSToken_Symbol == tk->mType) {
|
||||
if (';' == tk->mSymbol) {
|
||||
TransferTempData(aDeclaration, propID, isImportant, aChanged);
|
||||
TransferTempData(aDeclaration, propID, isImportant,
|
||||
aMustCallValueAppended, aChanged);
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (!aCheckForBraces) {
|
||||
@@ -3212,7 +3224,8 @@ CSSParserImpl::ParseDeclaration(nsresult& aErrorCode,
|
||||
}
|
||||
if ('}' == tk->mSymbol) {
|
||||
UngetToken();
|
||||
TransferTempData(aDeclaration, propID, isImportant, aChanged);
|
||||
TransferTempData(aDeclaration, propID, isImportant,
|
||||
aMustCallValueAppended, aChanged);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
@@ -3242,14 +3255,17 @@ CSSParserImpl::ClearTempData(nsCSSProperty aPropID)
|
||||
void
|
||||
CSSParserImpl::TransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
nsCSSProperty aPropID, PRBool aIsImportant,
|
||||
PRBool aMustCallValueAppended,
|
||||
PRBool* aChanged)
|
||||
{
|
||||
if (nsCSSProps::IsShorthand(aPropID)) {
|
||||
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID) {
|
||||
DoTransferTempData(aDeclaration, *p, aIsImportant, aChanged);
|
||||
DoTransferTempData(aDeclaration, *p, aIsImportant,
|
||||
aMustCallValueAppended, aChanged);
|
||||
}
|
||||
} else {
|
||||
DoTransferTempData(aDeclaration, aPropID, aIsImportant, aChanged);
|
||||
DoTransferTempData(aDeclaration, aPropID, aIsImportant,
|
||||
aMustCallValueAppended, aChanged);
|
||||
}
|
||||
mTempData.AssertInitialState();
|
||||
}
|
||||
@@ -3260,6 +3276,7 @@ CSSParserImpl::TransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
void
|
||||
CSSParserImpl::DoTransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
nsCSSProperty aPropID, PRBool aIsImportant,
|
||||
PRBool aMustCallValueAppended,
|
||||
PRBool* aChanged)
|
||||
{
|
||||
NS_ASSERTION(mTempData.HasPropertyBit(aPropID), "oops");
|
||||
@@ -3273,11 +3290,14 @@ CSSParserImpl::DoTransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aMustCallValueAppended || !mData.HasPropertyBit(aPropID)) {
|
||||
aDeclaration->ValueAppended(aPropID);
|
||||
}
|
||||
|
||||
mData.SetPropertyBit(aPropID);
|
||||
mTempData.ClearPropertyBit(aPropID);
|
||||
|
||||
aDeclaration->ValueAppended(aPropID);
|
||||
|
||||
/*
|
||||
* Save needless copying and allocation by calling the destructor in
|
||||
* the destination, copying memory directly, and then using placement
|
||||
@@ -3294,6 +3314,12 @@ CSSParserImpl::DoTransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
dest->~nsCSSValue();
|
||||
memcpy(dest, source, sizeof(nsCSSValue));
|
||||
new (source) nsCSSValue();
|
||||
if (dest->GetUnit() == eCSSUnit_Null) {
|
||||
// Some of our property parsers actually want to _clear_ properties in
|
||||
// mData (eg the "font" shorthand parser does for system fonts). We've
|
||||
// cleared the data; now clear the bit too.
|
||||
mData.ClearPropertyBit(aPropID);
|
||||
}
|
||||
} break;
|
||||
|
||||
case eCSSType_Rect: {
|
||||
@@ -5346,6 +5372,13 @@ PRBool CSSParserImpl::ParseFont(nsresult& aErrorCode)
|
||||
else {
|
||||
AppendValue(eCSSProperty_font_family, family); // keyword value overrides everything else
|
||||
nsCSSValue empty;
|
||||
// XXXbz this is actually _clearing_ the values for the following
|
||||
// properties in mTempData, but setting the bit for them. We need that
|
||||
// because we want to clear out the values in mData when all is said
|
||||
// and done. See the code in TransferTempData that handles this. The
|
||||
// end result is that mData always has its property bits set like it
|
||||
// should, but mTempData can, in fact, have bits set for properties
|
||||
// that are not set...
|
||||
AppendValue(eCSSProperty_font_style, empty);
|
||||
AppendValue(eCSSProperty_font_variant, empty);
|
||||
AppendValue(eCSSProperty_font_weight, empty);
|
||||
|
||||
Reference in New Issue
Block a user