Issue #2490 - Part 4: Make css::Rule wrappercached.

This commit is contained in:
Moonchild 2024-03-30 12:39:15 +01:00 committed by roytam1
commit 1342838b3f
9 changed files with 208 additions and 18 deletions

View file

@ -18,10 +18,24 @@ namespace dom {
class TabChildGlobal;
class ProcessGlobal;
} // namespace dom
namespace css {
class ImportRule;
class NameSpaceRule;
class StyleRule;
class MediaRule;
class DocumentRule;
} // namespace css
class CSSSupportsRule;
} // namespace mozilla
class SandboxPrivate;
class nsInProcessTabChildGlobal;
class nsWindowRoot;
class nsCSSFontFaceRule;
class nsCSSFontFeatureValuesRule;
class nsCSSKeyframeRule;
class nsCSSKeyframesRule;
class nsCSSPageRule;
class nsCSSCounterStyleRule;
#define NS_WRAPPERCACHE_IID \
{ 0x6f3179a1, 0x36f7, 0x4a5c, \
@ -163,7 +177,7 @@ public:
/**
* Returns true if the object has a non-gray wrapper.
*/
bool IsBlack();
bool IsBlack() const;
/**
* Returns true if the object has a black wrapper,
@ -271,11 +285,27 @@ protected:
}
private:
// Friend declarations for things that need to be able to call
// SetIsNotDOMBinding(). The goal is to get rid of all of these, and
// SetIsNotDOMBinding() too.
friend class mozilla::dom::TabChildGlobal;
friend class mozilla::dom::ProcessGlobal;
friend class SandboxPrivate;
friend class nsInProcessTabChildGlobal;
friend class nsWindowRoot;
friend class mozilla::css::ImportRule;
friend class mozilla::css::NameSpaceRule;
friend class mozilla::css::StyleRule;
friend class mozilla::css::MediaRule;
friend class mozilla::css::DocumentRule;
friend class mozilla::CSSSupportsRule;
friend class nsCSSFontFaceRule;
friend class nsCSSFontFeatureValuesRule;
friend class nsCSSKeyframeRule;
friend class nsCSSKeyframesRule;
friend class nsCSSPageRule;
friend class nsCSSCounterStyleRule;
void SetIsNotDOMBinding()
{
MOZ_ASSERT(!mWrapper && !(GetWrapperFlags() & ~WRAPPER_IS_NOT_DOM_BINDING),

View file

@ -21,7 +21,7 @@ nsWrapperCache::GetWrapper() const
}
inline bool
nsWrapperCache::IsBlack()
nsWrapperCache::IsBlack() const
{
JSObject* o = GetWrapperPreserveColor();
return o && !JS::ObjectIsMarkedGray(o);

View file

@ -55,6 +55,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
// nsIDOMCSSRule interface
NS_DECL_NSIDOMCSSRULE

View file

@ -55,6 +55,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
override MOZ_MUST_OVERRIDE;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
// nsIDOMCSSRule interface
NS_DECL_NSIDOMCSSRULE

View file

@ -12,6 +12,7 @@
#include "mozilla/MemoryReporting.h"
#include "nsISupports.h"
#include "nsIDOMCSSRule.h"
#include "nsWrapperCache.h"
class nsIDocument;
struct nsRuleData;
@ -29,7 +30,9 @@ class GroupRule;
DECL_STYLE_RULE_INHERIT_NO_DOMRULE \
virtual nsIDOMCSSRule* GetDOMRule() override;
class Rule : public nsISupports {
class Rule : public nsISupports
, public nsWrapperCache
{
protected:
Rule(uint32_t aLineNumber, uint32_t aColumnNumber)
: mSheet(nullptr),
@ -52,7 +55,7 @@ protected:
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(Rule)
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(Rule)
// Return true if this rule is known to be a cycle collection leaf, in the
// sense that it doesn't have any outgoing owning edges.
virtual bool IsCCLeaf() const MOZ_MUST_OVERRIDE;

View file

@ -1442,6 +1442,7 @@ StyleRule::StyleRule(nsCSSSelectorList* aSelector,
mSelector(aSelector),
mDeclaration(aDeclaration)
{
SetIsNotDOMBinding();
NS_PRECONDITION(aDeclaration, "must have a declaration");
mDeclaration->SetOwningRule(this);
@ -1453,6 +1454,7 @@ StyleRule::StyleRule(const StyleRule& aCopy)
mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nullptr),
mDeclaration(new Declaration(*aCopy.mDeclaration))
{
SetIsNotDOMBinding();
mDeclaration->SetOwningRule(this);
// rest is constructed lazily on existing data
}
@ -1680,6 +1682,12 @@ StyleRule::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
return n;
}
/* virtual */ JSObject*
StyleRule::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
} // namespace css
} // namespace mozilla

View file

@ -363,6 +363,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
private:
~StyleRule();

View file

@ -38,6 +38,7 @@
#include "nsIURI.h"
#include "mozAutoDocUpdate.h"
#include "nsCCUncollectableMarker.h"
#include "nsWrapperCacheInlines.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -58,20 +59,25 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(Rule)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Rule)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Rule)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_0(Rule)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(Rule)
bool
Rule::IsCCLeaf() const
{
return true;
return !PreservingWrapper();
}
bool
Rule::IsKnownLive() const
{
if (IsBlack()) {
return true;
}
StyleSheet* sheet = GetStyleSheet();
if (!sheet) {
return false;
@ -90,10 +96,10 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Rule)
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Rule)
// Note that we can't make use of IsKnownLive() here directly, because we may
// be subclassed by something that needs tracing. Once we have a wrapper
// cache we should be able to do better here.
return tmp->IsCCLeaf();
// Please see documentation for nsCycleCollectionParticipant::CanSkip* for why
// we need to check HasNothingToTrace here but not in the other two CanSkip
// methods.
return tmp->IsCCLeaf() || (tmp->IsKnownLive() && tmp->HasNothingToTrace(tmp));
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Rule)
@ -217,6 +223,7 @@ ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec,
, mURLSpec(aURLSpec)
, mMedia(aMedia)
{
SetIsNotDOMBinding();
// XXXbz This is really silly.... the mMedia here will be replaced
// with itself if we manage to load a sheet. Which should really
// never fail nowadays, in sane cases.
@ -226,6 +233,7 @@ ImportRule::ImportRule(const ImportRule& aCopy)
: Rule(aCopy),
mURLSpec(aCopy.mURLSpec)
{
SetIsNotDOMBinding();
// Whether or not an @import rule has a null sheet is a permanent
// property of that @import rule, since it is null only if the target
// sheet failed security checks.
@ -415,6 +423,14 @@ ImportRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
// - mChildSheet, because it is measured via CSSStyleSheetInner::mSheets
}
/* virtual */ JSObject*
ImportRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
GroupRule::GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber)
: Rule(aLineNumber, aColumnNumber)
{
@ -656,11 +672,13 @@ GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
MediaRule::MediaRule(uint32_t aLineNumber, uint32_t aColumnNumber)
: GroupRule(aLineNumber, aColumnNumber)
{
SetIsNotDOMBinding();
}
MediaRule::MediaRule(const MediaRule& aCopy)
: GroupRule(aCopy)
{
SetIsNotDOMBinding();
if (aCopy.mMedia) {
mMedia = aCopy.mMedia->Clone();
// XXXldb This doesn't really make sense.
@ -869,6 +887,13 @@ MediaRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return n;
}
/* virtual */ JSObject*
MediaRule::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
void
MediaRule::AppendConditionText(nsAString& aOutput)
{
@ -882,12 +907,14 @@ MediaRule::AppendConditionText(nsAString& aOutput)
DocumentRule::DocumentRule(uint32_t aLineNumber, uint32_t aColumnNumber)
: GroupRule(aLineNumber, aColumnNumber)
{
SetIsNotDOMBinding();
}
DocumentRule::DocumentRule(const DocumentRule& aCopy)
: GroupRule(aCopy)
, mURLs(new URL(*aCopy.mURLs))
{
SetIsNotDOMBinding();
}
DocumentRule::~DocumentRule()
@ -1110,6 +1137,14 @@ DocumentRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return n;
}
/* virtual */ JSObject*
DocumentRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
void
DocumentRule::AppendConditionText(nsAString& aCssText)
{
@ -1145,6 +1180,7 @@ NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec,
mPrefix(aPrefix),
mURLSpec(aURLSpec)
{
SetIsNotDOMBinding();
}
NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
@ -1152,6 +1188,7 @@ NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
mPrefix(aCopy.mPrefix),
mURLSpec(aCopy.mURLSpec)
{
SetIsNotDOMBinding();
}
NameSpaceRule::~NameSpaceRule()
@ -1277,6 +1314,13 @@ NameSpaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
// - mURLSpec
}
/* virtual */ JSObject*
NameSpaceRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
} // namespace css
} // namespace mozilla
@ -1762,6 +1806,13 @@ nsCSSFontFaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
// - mDecl
}
/* virtual */ JSObject*
nsCSSFontFaceRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
// -----------------------------------
// nsCSSFontFeatureValuesRule
@ -2009,6 +2060,14 @@ nsCSSFontFeatureValuesRule::SizeOfIncludingThis(
return aMallocSizeOf(this);
}
/* virtual */ JSObject*
nsCSSFontFeatureValuesRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
// -------------------------------------------
// nsCSSKeyframeStyleDeclaration
//
@ -2098,6 +2157,7 @@ nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy)
, mKeys(aCopy.mKeys)
, mDeclaration(new css::Declaration(*aCopy.mDeclaration))
{
SetIsNotDOMBinding();
mDeclaration->SetOwningRule(this);
}
@ -2317,6 +2377,13 @@ nsCSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
// - mDOMDeclaration
}
/* virtual */ JSObject*
nsCSSKeyframeRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
// -------------------------------------------
// nsCSSKeyframesRule
@ -2329,6 +2396,7 @@ nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy)
: GroupRule(aCopy),
mName(aCopy.mName)
{
SetIsNotDOMBinding();
}
nsCSSKeyframesRule::~nsCSSKeyframesRule()
@ -2573,6 +2641,14 @@ nsCSSKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return n;
}
/* virtual */ JSObject*
nsCSSKeyframesRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
// -------------------------------------------
// nsCSSPageStyleDeclaration
//
@ -2661,6 +2737,7 @@ nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy)
: Rule(aCopy)
, mDeclaration(new css::Declaration(*aCopy.mDeclaration))
{
SetIsNotDOMBinding();
mDeclaration->SetOwningRule(this);
}
@ -2809,6 +2886,14 @@ nsCSSPageRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return aMallocSizeOf(this);
}
/* virtual */ JSObject*
nsCSSPageRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
namespace mozilla {
CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
@ -2818,6 +2903,7 @@ CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
, mUseGroup(aConditionMet)
, mCondition(aCondition)
{
SetIsNotDOMBinding();
}
CSSSupportsRule::~CSSSupportsRule()
@ -2829,6 +2915,7 @@ CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
mUseGroup(aCopy.mUseGroup),
mCondition(aCopy.mCondition)
{
SetIsNotDOMBinding();
}
#ifdef DEBUG
@ -2964,6 +3051,14 @@ CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return n;
}
/* virtual */ JSObject*
CSSSupportsRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}
} // namespace mozilla
// -------------------------------------------
@ -2975,6 +3070,7 @@ nsCSSCounterStyleRule::nsCSSCounterStyleRule(const nsCSSCounterStyleRule& aCopy)
, mName(aCopy.mName)
, mGeneration(aCopy.mGeneration)
{
SetIsNotDOMBinding();
for (size_t i = 0; i < ArrayLength(mValues); ++i) {
mValues[i] = aCopy.mValues[i];
}
@ -3434,3 +3530,11 @@ nsCSSCounterStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this);
}
/* virtual */ JSObject*
nsCSSCounterStyleRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
return nullptr;
}

View file

@ -93,6 +93,9 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const override MOZ_MUST_OVERRIDE;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
protected:
void AppendConditionText(nsAString& aOutput);
@ -167,6 +170,9 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const override MOZ_MUST_OVERRIDE;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
protected:
void AppendConditionText(nsAString& aOutput);
@ -234,11 +240,18 @@ class nsCSSFontFaceRule final : public mozilla::css::Rule,
{
public:
nsCSSFontFaceRule(uint32_t aLineNumber, uint32_t aColumnNumber)
: mozilla::css::Rule(aLineNumber, aColumnNumber) {}
: mozilla::css::Rule(aLineNumber, aColumnNumber)
{
SetIsNotDOMBinding();
}
nsCSSFontFaceRule(const nsCSSFontFaceRule& aCopy)
// copy everything except our reference count
: mozilla::css::Rule(aCopy), mDecl(aCopy.mDecl) {}
: mozilla::css::Rule(aCopy)
, mDecl(aCopy.mDecl)
{
SetIsNotDOMBinding();
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsCSSFontFaceRule, mozilla::css::Rule)
@ -263,6 +276,9 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
void GetDescriptors(mozilla::CSSFontFaceDescriptors& aDescriptors) const
{ aDescriptors = mDecl.mDescriptors; }
@ -299,13 +315,19 @@ class nsCSSFontFeatureValuesRule final : public mozilla::css::Rule,
{
public:
nsCSSFontFeatureValuesRule(uint32_t aLineNumber, uint32_t aColumnNumber)
: mozilla::css::Rule(aLineNumber, aColumnNumber) {}
: mozilla::css::Rule(aLineNumber, aColumnNumber)
{
SetIsNotDOMBinding();
}
nsCSSFontFeatureValuesRule(const nsCSSFontFeatureValuesRule& aCopy)
// copy everything except our reference count
: mozilla::css::Rule(aCopy),
mFamilyList(aCopy.mFamilyList),
mFeatureValues(aCopy.mFeatureValues) {}
: mozilla::css::Rule(aCopy)
, mFamilyList(aCopy.mFamilyList)
, mFeatureValues(aCopy.mFeatureValues)
{
SetIsNotDOMBinding();
}
NS_DECL_ISUPPORTS_INHERITED
virtual bool IsCCLeaf() const override;
@ -337,6 +359,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
~nsCSSFontFeatureValuesRule() {}
@ -385,6 +409,7 @@ public:
, mKeys(mozilla::Move(aKeys))
, mDeclaration(mozilla::Move(aDeclaration))
{
SetIsNotDOMBinding();
mDeclaration->SetOwningRule(this);
}
private:
@ -416,6 +441,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void DoGetKeyText(nsAString &aKeyText) const;
private:
@ -434,6 +461,7 @@ public:
: mozilla::css::GroupRule(aLineNumber, aColumnNumber)
, mName(aName)
{
SetIsNotDOMBinding();
}
private:
nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy);
@ -466,6 +494,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
private:
uint32_t FindRuleIndexForKey(const nsAString& aKey);
@ -510,6 +540,7 @@ public:
: mozilla::css::Rule(aLineNumber, aColumnNumber)
, mDeclaration(aDeclaration)
{
SetIsNotDOMBinding();
mDeclaration->SetOwningRule(this);
}
private:
@ -539,6 +570,9 @@ public:
void ChangeDeclaration(mozilla::css::Declaration* aDeclaration);
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
private:
RefPtr<mozilla::css::Declaration> mDeclaration;
// lazily created when needed:
@ -547,8 +581,8 @@ private:
namespace mozilla {
class CSSSupportsRule : public css::GroupRule,
public nsIDOMCSSSupportsRule
class CSSSupportsRule final : public css::GroupRule,
public nsIDOMCSSSupportsRule
{
public:
CSSSupportsRule(bool aConditionMet, const nsString& aCondition,
@ -584,6 +618,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
virtual ~CSSSupportsRule();
@ -603,6 +639,7 @@ public:
, mName(aName)
, mGeneration(0)
{
SetIsNotDOMBinding();
}
private:
@ -651,6 +688,8 @@ public:
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
private:
typedef NS_STDCALL_FUNCPROTO(nsresult, Getter, nsCSSCounterStyleRule,
GetSymbols, (nsAString&));