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:
bzbarsky%mit.edu
2005-04-28 20:19:24 +00:00
parent 6c8d8dbd45
commit 13aba10e80
4 changed files with 104 additions and 72 deletions

View File

@@ -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]);
}
}

View File

@@ -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];
/*

View File

@@ -136,6 +136,7 @@ public:
mImportantData->Destroy();
mImportantData = nsnull;
}
mOrder.Clear();
}
#ifdef DEBUG

View File

@@ -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);