MiscContainer* nsAttrValue::ClearMiscContainer() { MiscContainer* cont = nullptr; if (BaseType() == eOtherBase) { cont = GetMiscContainer(); if (cont->IsRefCounted() && cont->mValue.mRefCount > 1) { // This MiscContainer is shared, we need a new one. NS_RELEASE(cont); cont = new MiscContainer; SetPtrValueAndType(cont, eOtherBase); } else { switch (cont->mType) { case eCSSStyleRule: { MOZ_ASSERT(cont->mValue.mRefCount == 1); cont->Release(); cont->Evict(); NS_RELEASE(cont->mValue.mCSSStyleRule); break; } case eURL: { NS_RELEASE(cont->mValue.mURL); break; } case eImage: { NS_RELEASE(cont->mValue.mImage); break; } case eAtomArray: { delete cont->mValue.mAtomArray; break; } case eIntMarginValue: { delete cont->mValue.mIntMargin; break; } default: { break; } } } ResetMiscAtomOrString(); } else { ResetIfSet(); } return cont; }
size_t nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { size_t n = 0; switch (BaseType()) { case eStringBase: { nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr()); n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0; break; } case eOtherBase: { MiscContainer* container = GetMiscContainer(); if (!container) { break; } if (container->IsRefCounted() && container->mValue.mRefCount > 1) { // We don't report this MiscContainer at all in order to avoid // twice-reporting it. // TODO DMD, bug 1027551 - figure out how to report this ref-counted // object just once. break; } n += aMallocSizeOf(container); void* otherPtr = MISC_STR_PTR(container); // We only count the size of the object pointed by otherPtr if it's a // string. When it's an atom, it's counted separatly. if (otherPtr && static_cast<ValueBaseType>(container->mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == eStringBase) { nsStringBuffer* str = static_cast<nsStringBuffer*>(otherPtr); n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0; } if (Type() == eCSSDeclaration && container->mValue.mCSSDeclaration) { // TODO: mCSSDeclaration might be owned by another object which // would make us count them twice, bug 677493. // Bug 1281964: For ServoDeclarationBlock if we do measure we'll // need a way to call the Servo heap_size_of function. //n += container->mCSSDeclaration->SizeOfIncludingThis(aMallocSizeOf); } else if (Type() == eAtomArray && container->mValue.mAtomArray) { // Don't measure each nsIAtom, they are measured separatly. n += container->mValue.mAtomArray->ShallowSizeOfIncludingThis(aMallocSizeOf); } break; } case eAtomBase: // Atoms are counted separately. case eIntegerBase: // The value is in mBits, nothing to do. break; } return n; }
void nsAttrValue::Reset() { switch(BaseType()) { case eStringBase: { nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr()); if (str) { str->Release(); } break; } case eOtherBase: { MiscContainer* cont = GetMiscContainer(); if (cont->IsRefCounted() && cont->mValue.mRefCount > 1) { NS_RELEASE(cont); break; } delete ClearMiscContainer(); break; } case eAtomBase: { nsIAtom* atom = GetAtomValue(); NS_RELEASE(atom); break; } case eIntegerBase: { break; } } mBits = 0; }
void nsAttrValue::SetTo(const nsAttrValue& aOther) { if (this == &aOther) { return; } switch (aOther.BaseType()) { case eStringBase: { ResetIfSet(); nsStringBuffer* str = static_cast<nsStringBuffer*>(aOther.GetPtr()); if (str) { str->AddRef(); SetPtrValueAndType(str, eStringBase); } return; } case eOtherBase: { break; } case eAtomBase: { ResetIfSet(); nsIAtom* atom = aOther.GetAtomValue(); NS_ADDREF(atom); SetPtrValueAndType(atom, eAtomBase); return; } case eIntegerBase: { ResetIfSet(); mBits = aOther.mBits; return; } } MiscContainer* otherCont = aOther.GetMiscContainer(); if (otherCont->IsRefCounted()) { delete ClearMiscContainer(); NS_ADDREF(otherCont); SetPtrValueAndType(otherCont, eOtherBase); return; } MiscContainer* cont = EnsureEmptyMiscContainer(); switch (otherCont->mType) { case eInteger: { cont->mValue.mInteger = otherCont->mValue.mInteger; break; } case eEnum: { cont->mValue.mEnumValue = otherCont->mValue.mEnumValue; break; } case ePercent: { cont->mValue.mPercent = otherCont->mValue.mPercent; break; } case eColor: { cont->mValue.mColor = otherCont->mValue.mColor; break; } case eCSSStyleRule: { MOZ_CRASH("These should be refcounted!"); } case eURL: { NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL); break; } case eImage: { NS_ADDREF(cont->mValue.mImage = otherCont->mValue.mImage); break; } case eAtomArray: { if (!EnsureEmptyAtomArray() || !GetAtomArrayValue()->AppendElements(*otherCont->mValue.mAtomArray)) { Reset(); return; } break; } case eDoubleValue: { cont->mDoubleValue = otherCont->mDoubleValue; break; } case eIntMarginValue: { if (otherCont->mValue.mIntMargin) cont->mValue.mIntMargin = new nsIntMargin(*otherCont->mValue.mIntMargin); break; } default: { if (IsSVGType(otherCont->mType)) { // All SVG types are just pointers to classes and will therefore have // the same size so it doesn't really matter which one we assign cont->mValue.mSVGAngle = otherCont->mValue.mSVGAngle; } else { NS_NOTREACHED("unknown type stored in MiscContainer"); } break; } } void* otherPtr = MISC_STR_PTR(otherCont); if (otherPtr) { if (static_cast<ValueBaseType>(otherCont->mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == eStringBase) { static_cast<nsStringBuffer*>(otherPtr)->AddRef(); } else { static_cast<nsIAtom*>(otherPtr)->AddRef(); } cont->mStringBits = otherCont->mStringBits; } // Note, set mType after switch-case, otherwise EnsureEmptyAtomArray doesn't // work correctly. cont->mType = otherCont->mType; }