Bug 1419661, if ExtendedDOMSlots are used before slots, use FatSlots to have fewer allocations, r=mrbkap

This commit is contained in:
Olli Pettay 2018-06-30 01:30:37 +03:00
Родитель 264c53b6fe
Коммит 2e00f64ed1
4 изменённых файлов: 101 добавлений и 26 удалений

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

@ -645,7 +645,7 @@ static_assert(sizeof(FragmentOrElement::nsDOMSlots) <= MaxDOMSlotSizeAllowed,
"DOM slots cannot be grown without consideration");
void
nsIContent::nsExtendedContentSlots::Unlink()
nsIContent::nsExtendedContentSlots::UnlinkExtendedSlots()
{
mBindingParent = nullptr;
mXBLInsertionPoint = nullptr;
@ -654,7 +654,7 @@ nsIContent::nsExtendedContentSlots::Unlink()
}
void
nsIContent::nsExtendedContentSlots::Traverse(nsCycleCollectionTraversalCallback& aCb)
nsIContent::nsExtendedContentSlots::TraverseExtendedSlots(nsCycleCollectionTraversalCallback& aCb)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mBindingParent");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mBindingParent));
@ -679,10 +679,13 @@ FragmentOrElement::nsDOMSlots::nsDOMSlots()
: nsIContent::nsContentSlots(),
mDataset(nullptr)
{
MOZ_COUNT_CTOR(nsDOMSlots);
}
FragmentOrElement::nsDOMSlots::~nsDOMSlots()
{
MOZ_COUNT_DTOR(nsDOMSlots);
if (mAttributeMap) {
mAttributeMap->DropReference();
}
@ -723,8 +726,8 @@ size_t
FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
if (mExtendedSlots) {
n += aMallocSizeOf(mExtendedSlots.get());
if (OwnsExtendedSlots()) {
n += aMallocSizeOf(GetExtendedContentSlots());
}
if (mAttributeMap) {
@ -758,9 +761,9 @@ FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots()
}
void
FragmentOrElement::nsExtendedDOMSlots::Unlink()
FragmentOrElement::nsExtendedDOMSlots::UnlinkExtendedSlots()
{
nsIContent::nsExtendedContentSlots::Unlink();
nsIContent::nsExtendedContentSlots::UnlinkExtendedSlots();
// Don't clear mXBLBinding, it'll be done in
// BindingManager::RemovedFromDocument from FragmentOrElement::Unlink.
@ -780,9 +783,9 @@ FragmentOrElement::nsExtendedDOMSlots::Unlink()
}
void
FragmentOrElement::nsExtendedDOMSlots::Traverse(nsCycleCollectionTraversalCallback& aCb)
FragmentOrElement::nsExtendedDOMSlots::TraverseExtendedSlots(nsCycleCollectionTraversalCallback& aCb)
{
nsIContent::nsExtendedContentSlots::Traverse(aCb);
nsIContent::nsExtendedContentSlots::TraverseExtendedSlots(aCb);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mSMILOverrideStyle");
aCb.NoteXPCOMChild(mSMILOverrideStyle.get());

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

@ -171,14 +171,14 @@ public:
* accessed through the DOM.
*/
class nsExtendedDOMSlots final : public nsIContent::nsExtendedContentSlots
class nsExtendedDOMSlots : public nsIContent::nsExtendedContentSlots
{
public:
nsExtendedDOMSlots();
~nsExtendedDOMSlots() final;
~nsExtendedDOMSlots();
void Traverse(nsCycleCollectionTraversalCallback&) final;
void Unlink() final;
void TraverseExtendedSlots(nsCycleCollectionTraversalCallback&) final;
void UnlinkExtendedSlots() final;
/**
* SMIL Overridde style rules (for SMIL animation of CSS properties)
@ -223,11 +223,11 @@ public:
};
class nsDOMSlots final : public nsIContent::nsContentSlots
class nsDOMSlots : public nsIContent::nsContentSlots
{
public:
nsDOMSlots();
~nsDOMSlots() final;
~nsDOMSlots();
void Traverse(nsCycleCollectionTraversalCallback&) final;
void Unlink() final;
@ -263,6 +263,29 @@ public:
RefPtr<nsDOMTokenList> mClassList;
};
/**
* In case ExtendedDOMSlots is needed before normal DOMSlots, an instance of
* FatSlots class, which combines those two slot types, is created.
* This way we can avoid extra allocation for ExtendedDOMSlots.
* FatSlots is useful for example when creating Custom Elements.
*/
class FatSlots final : public nsDOMSlots, public nsExtendedDOMSlots
{
public:
FatSlots()
: nsDOMSlots()
, nsExtendedDOMSlots()
{
MOZ_COUNT_CTOR(FatSlots);
SetExtendedContentSlots(this, false);
}
~FatSlots() final
{
MOZ_COUNT_DTOR(FatSlots);
}
};
protected:
void GetMarkup(bool aIncludeSelf, nsAString& aMarkup);
void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError);
@ -290,7 +313,18 @@ protected:
nsExtendedDOMSlots* ExtendedDOMSlots()
{
return static_cast<nsExtendedDOMSlots*>(ExtendedContentSlots());
nsContentSlots* slots = GetExistingContentSlots();
if (!slots) {
FatSlots* fatSlots = new FatSlots();
mSlots = fatSlots;
return fatSlots;
}
if (!slots->GetExtendedContentSlots()) {
slots->SetExtendedContentSlots(CreateExtendedSlots(), true);
}
return static_cast<nsExtendedDOMSlots*>(slots->GetExtendedContentSlots());
}
const nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const

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

@ -791,8 +791,8 @@ protected:
nsExtendedContentSlots();
virtual ~nsExtendedContentSlots();
virtual void Traverse(nsCycleCollectionTraversalCallback&);
virtual void Unlink();
virtual void TraverseExtendedSlots(nsCycleCollectionTraversalCallback&);
virtual void UnlinkExtendedSlots();
/**
* The nearest enclosing content node with a binding that created us.
@ -821,11 +821,24 @@ protected:
class nsContentSlots : public nsINode::nsSlots
{
public:
nsContentSlots()
: nsINode::nsSlots()
, mExtendedSlots(0)
{
}
~nsContentSlots()
{
if (!(mExtendedSlots & sNonOwningExtendedSlotsFlag)) {
delete GetExtendedContentSlots();
}
}
void Traverse(nsCycleCollectionTraversalCallback& aCb) override
{
nsINode::nsSlots::Traverse(aCb);
if (mExtendedSlots) {
mExtendedSlots->Traverse(aCb);
GetExtendedContentSlots()->TraverseExtendedSlots(aCb);
}
}
@ -833,11 +846,33 @@ protected:
{
nsINode::nsSlots::Unlink();
if (mExtendedSlots) {
mExtendedSlots->Unlink();
GetExtendedContentSlots()->UnlinkExtendedSlots();
}
}
mozilla::UniquePtr<nsExtendedContentSlots> mExtendedSlots;
void SetExtendedContentSlots(nsExtendedContentSlots* aSlots, bool aOwning)
{
mExtendedSlots = reinterpret_cast<uintptr_t>(aSlots);
if (!aOwning) {
mExtendedSlots |= sNonOwningExtendedSlotsFlag;
}
}
bool OwnsExtendedSlots() const
{
return !(mExtendedSlots & sNonOwningExtendedSlotsFlag);
}
nsExtendedContentSlots* GetExtendedContentSlots() const
{
return reinterpret_cast<nsExtendedContentSlots*>(
mExtendedSlots & ~sNonOwningExtendedSlotsFlag);
}
private:
static const uintptr_t sNonOwningExtendedSlotsFlag = 1u;
uintptr_t mExtendedSlots;
};
// Override from nsINode
@ -869,22 +904,22 @@ protected:
const nsExtendedContentSlots* GetExistingExtendedContentSlots() const
{
const nsContentSlots* slots = GetExistingContentSlots();
return slots ? slots->mExtendedSlots.get() : nullptr;
return slots ? slots->GetExtendedContentSlots() : nullptr;
}
nsExtendedContentSlots* GetExistingExtendedContentSlots()
{
nsContentSlots* slots = GetExistingContentSlots();
return slots ? slots->mExtendedSlots.get() : nullptr;
return slots ? slots->GetExtendedContentSlots() : nullptr;
}
nsExtendedContentSlots* ExtendedContentSlots()
{
nsContentSlots* slots = ContentSlots();
if (!slots->mExtendedSlots) {
slots->mExtendedSlots.reset(CreateExtendedSlots());
if (!slots->GetExtendedContentSlots()) {
slots->SetExtendedContentSlots(CreateExtendedSlots(), true);
}
return slots->mExtendedSlots.get();
return slots->GetExtendedContentSlots();
}
/**

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

@ -651,7 +651,10 @@ impl<'le> GeckoElement<'le> {
#[inline]
fn extended_slots(&self) -> Option<&structs::FragmentOrElement_nsExtendedDOMSlots> {
self.dom_slots().and_then(|s| unsafe {
(s._base.mExtendedSlots.mPtr as *const structs::FragmentOrElement_nsExtendedDOMSlots)
// For the bit usage, see nsContentSlots::GetExtendedSlots.
let e_slots = s._base.mExtendedSlots &
!structs::nsIContent_nsContentSlots_sNonOwningExtendedSlotsFlag;
(e_slots as *const structs::FragmentOrElement_nsExtendedDOMSlots)
.as_ref()
})
}