Loading layout/style/nsCSSDataBlock.cpp +46 −120 Original line number Diff line number Diff line Loading @@ -48,34 +48,6 @@ namespace css = mozilla::css; enum { CDBValueStorage_advance = sizeof(CDBValueStorage) }; /* * Define a bunch of utility functions for getting the property or any * of the value types when the cursor is at the beginning of the storage * for the property-value pair. The versions taking a non-const cursor * argument return a reference so that the caller can assign into the * result. */ inline nsCSSProperty& PropertyAtCursor(char *aCursor) { return *reinterpret_cast<nsCSSProperty*>(aCursor); } inline nsCSSProperty PropertyAtCursor(const char *aCursor) { return *reinterpret_cast<const nsCSSProperty*>(aCursor); } inline nsCSSValue* ValueAtCursor(char *aCursor) { return & reinterpret_cast<CDBValueStorage*>(aCursor)->value; } inline const nsCSSValue* ValueAtCursor(const char *aCursor) { return & reinterpret_cast<const CDBValueStorage*>(aCursor)->value; } /** * Does a fast move of aSource to aDest. The previous value in * aDest is cleanly destroyed, and aSource is cleared. Returns Loading Loading @@ -164,16 +136,13 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const nsIDocument* doc = aRuleData->mPresContext->Document(); const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); for (PRUint32 i = 0; i < mNumProps; i++) { nsCSSProperty iProp = PropertyAtIndex(i); if (nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]) & aRuleData->mSIDs) { nsCSSValue* target = aRuleData->ValueFor(iProp); if (target->GetUnit() == eCSSUnit_Null) { const nsCSSValue *val = ValueAtCursor(cursor); const nsCSSValue *val = ValueAtIndex(i); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops"); if (ShouldStartImageLoads(aRuleData, iProp)) { TryToStartImageLoad(*val, doc, iProp); Loading @@ -197,9 +166,7 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const } } } cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); } const nsCSSValue* Loading @@ -216,17 +183,11 @@ nsCSSCompressedDataBlock::ValueFor(nsCSSProperty aProperty) const mStyleBits)) return nsnull; const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); if (iProp == aProperty) { return ValueAtCursor(cursor); for (PRUint32 i = 0; i < mNumProps; i++) { if (PropertyAtIndex(i) == aProperty) { return ValueAtIndex(i); } cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); return nsnull; } Loading Loading @@ -254,56 +215,35 @@ nsCSSCompressedDataBlock::TryReplaceValue(nsCSSProperty aProperty, nsCSSCompressedDataBlock* nsCSSCompressedDataBlock::Clone() const { const char *cursor = Block(), *cursor_end = BlockEnd(); char *result_cursor; nsAutoPtr<nsCSSCompressedDataBlock> result (new(cursor_end - cursor) nsCSSCompressedDataBlock()); if (!result) return nsnull; result_cursor = result->Block(); nsAutoPtr<nsCSSCompressedDataBlock> result(new(mNumProps) nsCSSCompressedDataBlock(mNumProps)); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); PropertyAtCursor(result_cursor) = iProp; result->mStyleBits = mStyleBits; const nsCSSValue* val = ValueAtCursor(cursor); nsCSSValue *result_val = ValueAtCursor(result_cursor); new (result_val) nsCSSValue(*val); cursor += CDBValueStorage_advance; result_cursor += CDBValueStorage_advance; for (PRUint32 i = 0; i < mNumProps; i++) { result->SetPropertyAtIndex(i, PropertyAtIndex(i)); result->CopyValueToIndex(i, ValueAtIndex(i)); } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); result->SetBlockEnd(result_cursor); result->mStyleBits = mStyleBits; NS_ABORT_IF_FALSE(result->DataSize() == DataSize(), "wrong size"); return result.forget(); } nsCSSCompressedDataBlock::~nsCSSCompressedDataBlock() { const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(PropertyAtCursor(cursor)), "out of range"); const nsCSSValue* val = ValueAtCursor(cursor); for (PRUint32 i = 0; i < mNumProps; i++) { #ifdef DEBUG (void)PropertyAtIndex(i); // this checks the property is in range #endif const nsCSSValue* val = ValueAtIndex(i); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops"); val->~nsCSSValue(); cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); } /* static */ nsCSSCompressedDataBlock* nsCSSCompressedDataBlock::CreateEmptyBlock() { nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock(); result->SetBlockEnd(result->Block()); nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock(0); return result; } Loading @@ -311,12 +251,8 @@ size_t nsCSSCompressedDataBlock::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const { size_t n = aMallocSizeOf(this); const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { n += ValueAtCursor(cursor)->SizeOfExcludingThis(aMallocSizeOf); cursor += CDBValueStorage_advance; for (PRUint32 i = 0; i < mNumProps; i++) { n += ValueAtIndex(i)->SizeOfExcludingThis(aMallocSizeOf); } return n; } Loading @@ -341,10 +277,8 @@ nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock, * Save needless copying and allocation by copying the memory * corresponding to the stored data in the compressed block. */ const char* cursor = aBlock->Block(); const char* cursor_end = aBlock->BlockEnd(); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); for (PRUint32 i = 0; i < aBlock->mNumProps; i++) { nsCSSProperty iProp = aBlock->PropertyAtIndex(i); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); NS_ABORT_IF_FALSE(!HasPropertyBit(iProp), "compressed block has property multiple times"); Loading @@ -352,7 +286,7 @@ nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock, if (aImportant) SetImportantBit(iProp); const nsCSSValue* val = ValueAtCursor(cursor); const nsCSSValue* val = aBlock->ValueAtIndex(i); nsCSSValue* dest = PropertyAt(iProp); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops"); NS_ABORT_IF_FALSE(dest->GetUnit() == eCSSUnit_Null, Loading @@ -361,12 +295,11 @@ nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock, dest->~nsCSSValue(); #endif memcpy(dest, val, sizeof(nsCSSValue)); cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); // Don't destroy remnants of what we just copied aBlock->SetBlockEnd(aBlock->Block()); // Set the number of properties to zero so that we don't destroy the // remnants of what we just copied. aBlock->SetNumPropsToZero(); delete aBlock; } Loading @@ -383,10 +316,11 @@ nsCSSExpandedDataBlock::Expand(nsCSSCompressedDataBlock *aNormalBlock, } } nsCSSExpandedDataBlock::ComputeSizeResult nsCSSExpandedDataBlock::ComputeSize() void nsCSSExpandedDataBlock::ComputeNumProps(PRUint32* aNumPropsNormal, PRUint32* aNumPropsImportant) { ComputeSizeResult result = {0, 0}; *aNumPropsNormal = *aNumPropsImportant = 0; for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) { if (!mPropertiesSet.HasPropertyInChunk(iHigh)) continue; Loading @@ -400,12 +334,11 @@ nsCSSExpandedDataBlock::ComputeSize() NS_ABORT_IF_FALSE(PropertyAt(iProp)->GetUnit() != eCSSUnit_Null, "null value while computing size"); if (mPropertiesImportant.HasPropertyAt(iHigh, iLow)) result.important += CDBValueStorage_advance; (*aNumPropsImportant)++; else result.normal += CDBValueStorage_advance; (*aNumPropsNormal)++; } } return result; } void Loading @@ -413,19 +346,19 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, nsCSSCompressedDataBlock **aImportantBlock) { nsAutoPtr<nsCSSCompressedDataBlock> result_normal, result_important; char *cursor_normal, *cursor_important; PRUint32 i_normal = 0, i_important = 0; ComputeSizeResult size = ComputeSize(); PRUint32 numPropsNormal, numPropsImportant; ComputeNumProps(&numPropsNormal, &numPropsImportant); result_normal = new(size.normal) nsCSSCompressedDataBlock(); cursor_normal = result_normal->Block(); result_normal = new(numPropsNormal) nsCSSCompressedDataBlock(numPropsNormal); if (size.important != 0) { result_important = new(size.important) nsCSSCompressedDataBlock(); cursor_important = result_important->Block(); if (numPropsImportant != 0) { result_important = new(numPropsImportant) nsCSSCompressedDataBlock(numPropsImportant); } else { result_important = nsnull; cursor_important = nsnull; } /* Loading @@ -443,32 +376,25 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); bool important = mPropertiesImportant.HasPropertyAt(iHigh, iLow); char *&cursor = important ? cursor_important : cursor_normal; nsCSSCompressedDataBlock *result = important ? result_important : result_normal; PRUint32* ip = important ? &i_important : &i_normal; nsCSSValue* val = PropertyAt(iProp); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "Null value while compressing"); CDBValueStorage *storage = reinterpret_cast<CDBValueStorage*>(cursor); storage->property = iProp; memcpy(&storage->value, val, sizeof(nsCSSValue)); result->SetPropertyAtIndex(*ip, iProp); result->RawCopyValueToIndex(*ip, val); new (val) nsCSSValue(); cursor += CDBValueStorage_advance; (*ip)++; result->mStyleBits |= nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]); } } result_normal->SetBlockEnd(cursor_normal); NS_ABORT_IF_FALSE(result_normal->DataSize() == ptrdiff_t(size.normal), "size miscalculation"); NS_ABORT_IF_FALSE(numPropsNormal == i_normal, "bad numProps"); if (result_important) { result_important->SetBlockEnd(cursor_important); NS_ABORT_IF_FALSE(result_important->DataSize() == ptrdiff_t(size.important), "size miscalculation"); NS_ABORT_IF_FALSE(numPropsImportant == i_important, "bad numProps"); } ClearSets(); Loading layout/style/nsCSSDataBlock.h +75 −45 Original line number Diff line number Diff line Loading @@ -55,16 +55,6 @@ class Declaration; } } /* * nsCSSCompressedDataBlock holds property-value pairs corresponding * to CSS declaration blocks. Each pair is stored in a CDBValueStorage * object; these objects form an array at the end of the data block. */ struct CDBValueStorage { nsCSSProperty property; nsCSSValue value; }; /** * An |nsCSSCompressedDataBlock| holds a usually-immutable chunk of * property-value data for a CSS declaration block (which we misname a Loading @@ -77,7 +67,9 @@ private: // Only this class (via |CreateEmptyBlock|) or nsCSSExpandedDataBlock // (in |Compress|) can create compressed data blocks. nsCSSCompressedDataBlock() : mStyleBits(0) {} nsCSSCompressedDataBlock(PRUint32 aNumProps) : mStyleBits(0), mNumProps(aNumProps) {} public: ~nsCSSCompressedDataBlock(); Loading Loading @@ -124,47 +116,87 @@ public: size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; private: void* operator new(size_t aBaseSize, size_t aDataSize) { void* operator new(size_t aBaseSize, PRUint32 aNumProps) { NS_ABORT_IF_FALSE(aBaseSize == sizeof(nsCSSCompressedDataBlock), "unexpected size for nsCSSCompressedDataBlock"); return ::operator new(aBaseSize + aDataSize); return ::operator new(aBaseSize + DataSize(aNumProps)); } /** * Delete all the data stored in this block, and the block itself. */ void Destroy(); public: // Ideally, |nsCSSProperty| would be |enum nsCSSProperty : PRInt16|. But // not all of the compilers we use are modern enough to support small // enums. So we manually squeeze nsCSSProperty into 16 bits ourselves. // The static assertion below ensures it fits. typedef PRInt16 CompressedCSSProperty; static const size_t MaxCompressedCSSProperty = PR_INT16_MAX; private: static size_t DataSize(PRUint32 aNumProps) { return size_t(aNumProps) * (sizeof(nsCSSValue) + sizeof(CompressedCSSProperty)); } PRInt32 mStyleBits; // the structs for which we have data, according to // |nsCachedStyleData::GetBitForSID|. PRUint32 mDataSize; // CDBValueStorage elements are stored after these fields. Space for them PRUint32 mNumProps; // nsCSSValue elements are stored after these fields, and // nsCSSProperty elements are stored -- each one compressed as a // CompressedCSSProperty -- after the nsCSSValue elements. Space for them // is allocated in |operator new| above. The static assertions following // this class make sure that the CDBValueStorage elements are aligned // this class make sure that the value and property elements are aligned // appropriately. char* Block() { return (char*)this + sizeof(*this); } char* BlockEnd() { return Block() + mDataSize; } const char* Block() const { return (char*)this + sizeof(*this); } const char* BlockEnd() const { return Block() + mDataSize; } void SetBlockEnd(char *blockEnd) { /* * Note: if we ever change nsCSSDeclaration to store the declarations * in order and also store repeated declarations of the same property, * then we need to worry about checking for integer overflow here. */ NS_ABORT_IF_FALSE(size_t(blockEnd - Block()) <= size_t(PR_UINT32_MAX), "overflow of mDataSize"); mDataSize = PRUint32(blockEnd - Block()); nsCSSValue* Values() const { return (nsCSSValue*)(this + 1); } CompressedCSSProperty* CompressedProperties() const { return (CompressedCSSProperty*)(Values() + mNumProps); } nsCSSValue* ValueAtIndex(PRUint32 i) const { NS_ABORT_IF_FALSE(i < mNumProps, "value index out of range"); return Values() + i; } nsCSSProperty PropertyAtIndex(PRUint32 i) const { NS_ABORT_IF_FALSE(i < mNumProps, "property index out of range"); nsCSSProperty prop = (nsCSSProperty)CompressedProperties()[i]; NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(prop), "out of range"); return prop; } void CopyValueToIndex(PRUint32 i, nsCSSValue* aValue) { new (ValueAtIndex(i)) nsCSSValue(*aValue); } void RawCopyValueToIndex(PRUint32 i, nsCSSValue* aValue) { memcpy(ValueAtIndex(i), aValue, sizeof(nsCSSValue)); } void SetPropertyAtIndex(PRUint32 i, nsCSSProperty aProperty) { NS_ABORT_IF_FALSE(i < mNumProps, "set property index out of range"); CompressedProperties()[i] = (CompressedCSSProperty)aProperty; } void SetNumPropsToZero() { mNumProps = 0; } ptrdiff_t DataSize() const { return mDataSize; } }; /* Make sure the CDBValueStorage elements are aligned appropriately. */ // Make sure the values and properties are aligned appropriately. (These // assertions are stronger than necessary to keep them simple.) MOZ_STATIC_ASSERT(sizeof(nsCSSCompressedDataBlock) == 8, "nsCSSCompressedDataBlock's size has changed"); MOZ_STATIC_ASSERT(NS_ALIGNMENT_OF(CDBValueStorage) <= 8, "CDBValueStorage needs too much alignment"); MOZ_STATIC_ASSERT(NS_ALIGNMENT_OF(nsCSSValue) == 4 || NS_ALIGNMENT_OF(nsCSSValue) == 8, "nsCSSValue doesn't align with nsCSSCompressedDataBlock"); MOZ_STATIC_ASSERT(NS_ALIGNMENT_OF(nsCSSCompressedDataBlock::CompressedCSSProperty) == 2, "CompressedCSSProperty doesn't align with nsCSSValue"); // Make sure that sizeof(CompressedCSSProperty) is big enough. MOZ_STATIC_ASSERT(eCSSProperty_COUNT_no_shorthands <= nsCSSCompressedDataBlock::MaxCompressedCSSProperty, "nsCSSProperty doesn't fit in StoredSizeOfCSSProperty"); class nsCSSExpandedDataBlock { friend class nsCSSCompressedDataBlock; Loading Loading @@ -251,13 +283,11 @@ public: private: /** * Compute the size that will be occupied by the result of * |Compress|. * Compute the number of properties that will be present in the * result of |Compress|. */ struct ComputeSizeResult { PRUint32 normal, important; }; ComputeSizeResult ComputeSize(); void ComputeNumProps(PRUint32* aNumPropsNormal, PRUint32* aNumPropsImportant); void DoExpand(nsCSSCompressedDataBlock *aBlock, bool aImportant); Loading Loading
layout/style/nsCSSDataBlock.cpp +46 −120 Original line number Diff line number Diff line Loading @@ -48,34 +48,6 @@ namespace css = mozilla::css; enum { CDBValueStorage_advance = sizeof(CDBValueStorage) }; /* * Define a bunch of utility functions for getting the property or any * of the value types when the cursor is at the beginning of the storage * for the property-value pair. The versions taking a non-const cursor * argument return a reference so that the caller can assign into the * result. */ inline nsCSSProperty& PropertyAtCursor(char *aCursor) { return *reinterpret_cast<nsCSSProperty*>(aCursor); } inline nsCSSProperty PropertyAtCursor(const char *aCursor) { return *reinterpret_cast<const nsCSSProperty*>(aCursor); } inline nsCSSValue* ValueAtCursor(char *aCursor) { return & reinterpret_cast<CDBValueStorage*>(aCursor)->value; } inline const nsCSSValue* ValueAtCursor(const char *aCursor) { return & reinterpret_cast<const CDBValueStorage*>(aCursor)->value; } /** * Does a fast move of aSource to aDest. The previous value in * aDest is cleanly destroyed, and aSource is cleared. Returns Loading Loading @@ -164,16 +136,13 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const nsIDocument* doc = aRuleData->mPresContext->Document(); const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); for (PRUint32 i = 0; i < mNumProps; i++) { nsCSSProperty iProp = PropertyAtIndex(i); if (nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]) & aRuleData->mSIDs) { nsCSSValue* target = aRuleData->ValueFor(iProp); if (target->GetUnit() == eCSSUnit_Null) { const nsCSSValue *val = ValueAtCursor(cursor); const nsCSSValue *val = ValueAtIndex(i); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops"); if (ShouldStartImageLoads(aRuleData, iProp)) { TryToStartImageLoad(*val, doc, iProp); Loading @@ -197,9 +166,7 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const } } } cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); } const nsCSSValue* Loading @@ -216,17 +183,11 @@ nsCSSCompressedDataBlock::ValueFor(nsCSSProperty aProperty) const mStyleBits)) return nsnull; const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); if (iProp == aProperty) { return ValueAtCursor(cursor); for (PRUint32 i = 0; i < mNumProps; i++) { if (PropertyAtIndex(i) == aProperty) { return ValueAtIndex(i); } cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); return nsnull; } Loading Loading @@ -254,56 +215,35 @@ nsCSSCompressedDataBlock::TryReplaceValue(nsCSSProperty aProperty, nsCSSCompressedDataBlock* nsCSSCompressedDataBlock::Clone() const { const char *cursor = Block(), *cursor_end = BlockEnd(); char *result_cursor; nsAutoPtr<nsCSSCompressedDataBlock> result (new(cursor_end - cursor) nsCSSCompressedDataBlock()); if (!result) return nsnull; result_cursor = result->Block(); nsAutoPtr<nsCSSCompressedDataBlock> result(new(mNumProps) nsCSSCompressedDataBlock(mNumProps)); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); PropertyAtCursor(result_cursor) = iProp; result->mStyleBits = mStyleBits; const nsCSSValue* val = ValueAtCursor(cursor); nsCSSValue *result_val = ValueAtCursor(result_cursor); new (result_val) nsCSSValue(*val); cursor += CDBValueStorage_advance; result_cursor += CDBValueStorage_advance; for (PRUint32 i = 0; i < mNumProps; i++) { result->SetPropertyAtIndex(i, PropertyAtIndex(i)); result->CopyValueToIndex(i, ValueAtIndex(i)); } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); result->SetBlockEnd(result_cursor); result->mStyleBits = mStyleBits; NS_ABORT_IF_FALSE(result->DataSize() == DataSize(), "wrong size"); return result.forget(); } nsCSSCompressedDataBlock::~nsCSSCompressedDataBlock() { const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(PropertyAtCursor(cursor)), "out of range"); const nsCSSValue* val = ValueAtCursor(cursor); for (PRUint32 i = 0; i < mNumProps; i++) { #ifdef DEBUG (void)PropertyAtIndex(i); // this checks the property is in range #endif const nsCSSValue* val = ValueAtIndex(i); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops"); val->~nsCSSValue(); cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); } /* static */ nsCSSCompressedDataBlock* nsCSSCompressedDataBlock::CreateEmptyBlock() { nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock(); result->SetBlockEnd(result->Block()); nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock(0); return result; } Loading @@ -311,12 +251,8 @@ size_t nsCSSCompressedDataBlock::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const { size_t n = aMallocSizeOf(this); const char* cursor = Block(); const char* cursor_end = BlockEnd(); while (cursor < cursor_end) { n += ValueAtCursor(cursor)->SizeOfExcludingThis(aMallocSizeOf); cursor += CDBValueStorage_advance; for (PRUint32 i = 0; i < mNumProps; i++) { n += ValueAtIndex(i)->SizeOfExcludingThis(aMallocSizeOf); } return n; } Loading @@ -341,10 +277,8 @@ nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock, * Save needless copying and allocation by copying the memory * corresponding to the stored data in the compressed block. */ const char* cursor = aBlock->Block(); const char* cursor_end = aBlock->BlockEnd(); while (cursor < cursor_end) { nsCSSProperty iProp = PropertyAtCursor(cursor); for (PRUint32 i = 0; i < aBlock->mNumProps; i++) { nsCSSProperty iProp = aBlock->PropertyAtIndex(i); NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); NS_ABORT_IF_FALSE(!HasPropertyBit(iProp), "compressed block has property multiple times"); Loading @@ -352,7 +286,7 @@ nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock, if (aImportant) SetImportantBit(iProp); const nsCSSValue* val = ValueAtCursor(cursor); const nsCSSValue* val = aBlock->ValueAtIndex(i); nsCSSValue* dest = PropertyAt(iProp); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "oops"); NS_ABORT_IF_FALSE(dest->GetUnit() == eCSSUnit_Null, Loading @@ -361,12 +295,11 @@ nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock, dest->~nsCSSValue(); #endif memcpy(dest, val, sizeof(nsCSSValue)); cursor += CDBValueStorage_advance; } NS_ABORT_IF_FALSE(cursor == cursor_end, "inconsistent data"); // Don't destroy remnants of what we just copied aBlock->SetBlockEnd(aBlock->Block()); // Set the number of properties to zero so that we don't destroy the // remnants of what we just copied. aBlock->SetNumPropsToZero(); delete aBlock; } Loading @@ -383,10 +316,11 @@ nsCSSExpandedDataBlock::Expand(nsCSSCompressedDataBlock *aNormalBlock, } } nsCSSExpandedDataBlock::ComputeSizeResult nsCSSExpandedDataBlock::ComputeSize() void nsCSSExpandedDataBlock::ComputeNumProps(PRUint32* aNumPropsNormal, PRUint32* aNumPropsImportant) { ComputeSizeResult result = {0, 0}; *aNumPropsNormal = *aNumPropsImportant = 0; for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) { if (!mPropertiesSet.HasPropertyInChunk(iHigh)) continue; Loading @@ -400,12 +334,11 @@ nsCSSExpandedDataBlock::ComputeSize() NS_ABORT_IF_FALSE(PropertyAt(iProp)->GetUnit() != eCSSUnit_Null, "null value while computing size"); if (mPropertiesImportant.HasPropertyAt(iHigh, iLow)) result.important += CDBValueStorage_advance; (*aNumPropsImportant)++; else result.normal += CDBValueStorage_advance; (*aNumPropsNormal)++; } } return result; } void Loading @@ -413,19 +346,19 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, nsCSSCompressedDataBlock **aImportantBlock) { nsAutoPtr<nsCSSCompressedDataBlock> result_normal, result_important; char *cursor_normal, *cursor_important; PRUint32 i_normal = 0, i_important = 0; ComputeSizeResult size = ComputeSize(); PRUint32 numPropsNormal, numPropsImportant; ComputeNumProps(&numPropsNormal, &numPropsImportant); result_normal = new(size.normal) nsCSSCompressedDataBlock(); cursor_normal = result_normal->Block(); result_normal = new(numPropsNormal) nsCSSCompressedDataBlock(numPropsNormal); if (size.important != 0) { result_important = new(size.important) nsCSSCompressedDataBlock(); cursor_important = result_important->Block(); if (numPropsImportant != 0) { result_important = new(numPropsImportant) nsCSSCompressedDataBlock(numPropsImportant); } else { result_important = nsnull; cursor_important = nsnull; } /* Loading @@ -443,32 +376,25 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(iProp), "out of range"); bool important = mPropertiesImportant.HasPropertyAt(iHigh, iLow); char *&cursor = important ? cursor_important : cursor_normal; nsCSSCompressedDataBlock *result = important ? result_important : result_normal; PRUint32* ip = important ? &i_important : &i_normal; nsCSSValue* val = PropertyAt(iProp); NS_ABORT_IF_FALSE(val->GetUnit() != eCSSUnit_Null, "Null value while compressing"); CDBValueStorage *storage = reinterpret_cast<CDBValueStorage*>(cursor); storage->property = iProp; memcpy(&storage->value, val, sizeof(nsCSSValue)); result->SetPropertyAtIndex(*ip, iProp); result->RawCopyValueToIndex(*ip, val); new (val) nsCSSValue(); cursor += CDBValueStorage_advance; (*ip)++; result->mStyleBits |= nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]); } } result_normal->SetBlockEnd(cursor_normal); NS_ABORT_IF_FALSE(result_normal->DataSize() == ptrdiff_t(size.normal), "size miscalculation"); NS_ABORT_IF_FALSE(numPropsNormal == i_normal, "bad numProps"); if (result_important) { result_important->SetBlockEnd(cursor_important); NS_ABORT_IF_FALSE(result_important->DataSize() == ptrdiff_t(size.important), "size miscalculation"); NS_ABORT_IF_FALSE(numPropsImportant == i_important, "bad numProps"); } ClearSets(); Loading
layout/style/nsCSSDataBlock.h +75 −45 Original line number Diff line number Diff line Loading @@ -55,16 +55,6 @@ class Declaration; } } /* * nsCSSCompressedDataBlock holds property-value pairs corresponding * to CSS declaration blocks. Each pair is stored in a CDBValueStorage * object; these objects form an array at the end of the data block. */ struct CDBValueStorage { nsCSSProperty property; nsCSSValue value; }; /** * An |nsCSSCompressedDataBlock| holds a usually-immutable chunk of * property-value data for a CSS declaration block (which we misname a Loading @@ -77,7 +67,9 @@ private: // Only this class (via |CreateEmptyBlock|) or nsCSSExpandedDataBlock // (in |Compress|) can create compressed data blocks. nsCSSCompressedDataBlock() : mStyleBits(0) {} nsCSSCompressedDataBlock(PRUint32 aNumProps) : mStyleBits(0), mNumProps(aNumProps) {} public: ~nsCSSCompressedDataBlock(); Loading Loading @@ -124,47 +116,87 @@ public: size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; private: void* operator new(size_t aBaseSize, size_t aDataSize) { void* operator new(size_t aBaseSize, PRUint32 aNumProps) { NS_ABORT_IF_FALSE(aBaseSize == sizeof(nsCSSCompressedDataBlock), "unexpected size for nsCSSCompressedDataBlock"); return ::operator new(aBaseSize + aDataSize); return ::operator new(aBaseSize + DataSize(aNumProps)); } /** * Delete all the data stored in this block, and the block itself. */ void Destroy(); public: // Ideally, |nsCSSProperty| would be |enum nsCSSProperty : PRInt16|. But // not all of the compilers we use are modern enough to support small // enums. So we manually squeeze nsCSSProperty into 16 bits ourselves. // The static assertion below ensures it fits. typedef PRInt16 CompressedCSSProperty; static const size_t MaxCompressedCSSProperty = PR_INT16_MAX; private: static size_t DataSize(PRUint32 aNumProps) { return size_t(aNumProps) * (sizeof(nsCSSValue) + sizeof(CompressedCSSProperty)); } PRInt32 mStyleBits; // the structs for which we have data, according to // |nsCachedStyleData::GetBitForSID|. PRUint32 mDataSize; // CDBValueStorage elements are stored after these fields. Space for them PRUint32 mNumProps; // nsCSSValue elements are stored after these fields, and // nsCSSProperty elements are stored -- each one compressed as a // CompressedCSSProperty -- after the nsCSSValue elements. Space for them // is allocated in |operator new| above. The static assertions following // this class make sure that the CDBValueStorage elements are aligned // this class make sure that the value and property elements are aligned // appropriately. char* Block() { return (char*)this + sizeof(*this); } char* BlockEnd() { return Block() + mDataSize; } const char* Block() const { return (char*)this + sizeof(*this); } const char* BlockEnd() const { return Block() + mDataSize; } void SetBlockEnd(char *blockEnd) { /* * Note: if we ever change nsCSSDeclaration to store the declarations * in order and also store repeated declarations of the same property, * then we need to worry about checking for integer overflow here. */ NS_ABORT_IF_FALSE(size_t(blockEnd - Block()) <= size_t(PR_UINT32_MAX), "overflow of mDataSize"); mDataSize = PRUint32(blockEnd - Block()); nsCSSValue* Values() const { return (nsCSSValue*)(this + 1); } CompressedCSSProperty* CompressedProperties() const { return (CompressedCSSProperty*)(Values() + mNumProps); } nsCSSValue* ValueAtIndex(PRUint32 i) const { NS_ABORT_IF_FALSE(i < mNumProps, "value index out of range"); return Values() + i; } nsCSSProperty PropertyAtIndex(PRUint32 i) const { NS_ABORT_IF_FALSE(i < mNumProps, "property index out of range"); nsCSSProperty prop = (nsCSSProperty)CompressedProperties()[i]; NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(prop), "out of range"); return prop; } void CopyValueToIndex(PRUint32 i, nsCSSValue* aValue) { new (ValueAtIndex(i)) nsCSSValue(*aValue); } void RawCopyValueToIndex(PRUint32 i, nsCSSValue* aValue) { memcpy(ValueAtIndex(i), aValue, sizeof(nsCSSValue)); } void SetPropertyAtIndex(PRUint32 i, nsCSSProperty aProperty) { NS_ABORT_IF_FALSE(i < mNumProps, "set property index out of range"); CompressedProperties()[i] = (CompressedCSSProperty)aProperty; } void SetNumPropsToZero() { mNumProps = 0; } ptrdiff_t DataSize() const { return mDataSize; } }; /* Make sure the CDBValueStorage elements are aligned appropriately. */ // Make sure the values and properties are aligned appropriately. (These // assertions are stronger than necessary to keep them simple.) MOZ_STATIC_ASSERT(sizeof(nsCSSCompressedDataBlock) == 8, "nsCSSCompressedDataBlock's size has changed"); MOZ_STATIC_ASSERT(NS_ALIGNMENT_OF(CDBValueStorage) <= 8, "CDBValueStorage needs too much alignment"); MOZ_STATIC_ASSERT(NS_ALIGNMENT_OF(nsCSSValue) == 4 || NS_ALIGNMENT_OF(nsCSSValue) == 8, "nsCSSValue doesn't align with nsCSSCompressedDataBlock"); MOZ_STATIC_ASSERT(NS_ALIGNMENT_OF(nsCSSCompressedDataBlock::CompressedCSSProperty) == 2, "CompressedCSSProperty doesn't align with nsCSSValue"); // Make sure that sizeof(CompressedCSSProperty) is big enough. MOZ_STATIC_ASSERT(eCSSProperty_COUNT_no_shorthands <= nsCSSCompressedDataBlock::MaxCompressedCSSProperty, "nsCSSProperty doesn't fit in StoredSizeOfCSSProperty"); class nsCSSExpandedDataBlock { friend class nsCSSCompressedDataBlock; Loading Loading @@ -251,13 +283,11 @@ public: private: /** * Compute the size that will be occupied by the result of * |Compress|. * Compute the number of properties that will be present in the * result of |Compress|. */ struct ComputeSizeResult { PRUint32 normal, important; }; ComputeSizeResult ComputeSize(); void ComputeNumProps(PRUint32* aNumPropsNormal, PRUint32* aNumPropsImportant); void DoExpand(nsCSSCompressedDataBlock *aBlock, bool aImportant); Loading