зеркало из https://github.com/mozilla/pjs.git
Bugs 20724, 23715. Add a fixed-size allocator for nsXULAttribute objects. Always atomize 'id' attributes so nsXULElement::GetID() can be fast. r=hyatt
This commit is contained in:
Родитель
c4b022703a
Коммит
c592a32ef5
|
@ -137,6 +137,70 @@ nsClassList::ParseClasses(nsClassList** aList, const nsString& aClassString)
|
|||
// nsXULAttribute
|
||||
//
|
||||
|
||||
PRInt32 nsXULAttribute::gRefCnt;
|
||||
nsIAtom* nsXULAttribute::kIdAtom;
|
||||
|
||||
const PRInt32 nsXULAttribute::kBlockSize = 512;
|
||||
|
||||
nsXULAttribute* nsXULAttribute::gFreeList;
|
||||
|
||||
void*
|
||||
nsXULAttribute::operator new(size_t aSize)
|
||||
{
|
||||
// Simple fixed size allocator for nsXULAttribute objects. Look
|
||||
// for an object on the |gFreeList|, if there isn't one, create a
|
||||
// new block of 'em.
|
||||
if (aSize != sizeof(nsXULAttribute))
|
||||
return ::operator new(aSize);
|
||||
|
||||
nsXULAttribute* result = gFreeList;
|
||||
|
||||
if (result) {
|
||||
gFreeList = gFreeList->mNext;
|
||||
}
|
||||
else {
|
||||
// Create a chunk o' memory for the freelist.
|
||||
nsXULAttribute* block =
|
||||
NS_STATIC_CAST(nsXULAttribute*, ::operator new(kBlockSize * sizeof(nsXULAttribute)));
|
||||
|
||||
if (! block)
|
||||
return nsnull;
|
||||
|
||||
// Thread it.
|
||||
for (PRInt32 i = 1; i < kBlockSize - 1; ++i)
|
||||
block[i].mNext = &block[i + 1];
|
||||
|
||||
block[kBlockSize - 1].mNext = nsnull;
|
||||
|
||||
result = block;
|
||||
gFreeList = &block[1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsXULAttribute::operator delete(void* aObject, size_t aSize)
|
||||
{
|
||||
// Return |aObject| to |gFreeList|, if we can.
|
||||
if (! aObject)
|
||||
return;
|
||||
|
||||
if (aSize != sizeof(nsXULAttribute)) {
|
||||
::operator delete(aObject);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCRT::memset(aObject, 0xdd, aSize);
|
||||
#endif
|
||||
|
||||
nsXULAttribute* doomed = NS_STATIC_CAST(nsXULAttribute*, aObject);
|
||||
|
||||
doomed->mNext = gFreeList;
|
||||
gFreeList = doomed;
|
||||
}
|
||||
|
||||
nsXULAttribute::nsXULAttribute(nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
|
@ -149,6 +213,11 @@ nsXULAttribute::nsXULAttribute(nsIContent* aContent,
|
|||
mValue(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
if (gRefCnt++ == 0) {
|
||||
kIdAtom = NS_NewAtom("id");
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(aName);
|
||||
SetValueInternal(aValue);
|
||||
}
|
||||
|
@ -157,6 +226,10 @@ nsXULAttribute::~nsXULAttribute()
|
|||
{
|
||||
NS_IF_RELEASE(mName);
|
||||
ReleaseValue();
|
||||
|
||||
if (--gRefCnt == 0) {
|
||||
NS_IF_RELEASE(kIdAtom);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -444,7 +517,13 @@ nsresult
|
|||
nsXULAttribute::SetValueInternal(const nsString& aValue)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> newAtom;
|
||||
if (aValue.Length() <= kMaxAtomValueLength) {
|
||||
|
||||
// Atomize the value if it is short, or if it is the 'id'
|
||||
// attribute. We atomize the 'id' attribute to "prime" the global
|
||||
// atom table: the style system frequently asks for it, and if the
|
||||
// table is "unprimed" we see quite a bit of thrashing as the 'id'
|
||||
// value is repeatedly added and then removed from the atom table.
|
||||
if ((aValue.Length() <= kMaxAtomValueLength) || (mName == kIdAtom)) {
|
||||
newAtom = getter_AddRefs( NS_NewAtom(aValue.GetUnicode()) );
|
||||
}
|
||||
|
||||
|
@ -472,6 +551,22 @@ nsXULAttribute::SetValueInternal(const nsString& aValue)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULAttribute::GetValueAsAtom(nsIAtom** aResult)
|
||||
{
|
||||
if (! mValue) {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
else if (IsStringValue()) {
|
||||
*aResult = NS_NewAtom((const PRUnichar*) mValue);
|
||||
}
|
||||
else {
|
||||
*aResult = (nsIAtom*)(PRWord(mValue) & ~PRWord(kTypeMask));
|
||||
NS_ADDREF(*aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
|
|
|
@ -97,6 +97,20 @@ class nsXULAttribute : public nsIDOMAttr,
|
|||
public nsIScriptObjectOwner
|
||||
{
|
||||
protected:
|
||||
static PRInt32 gRefCnt;
|
||||
static nsIAtom* kIdAtom;
|
||||
|
||||
// A global fixed-size allocator for nsXULAttribute
|
||||
// objects. |kBlockSize| is the number of nsXULAttribute objects
|
||||
// the live together in a contiguous block of memory.
|
||||
static const PRInt32 kBlockSize;
|
||||
|
||||
// The head of the free list for free nsXULAttribute objects.
|
||||
static nsXULAttribute* gFreeList;
|
||||
|
||||
static void* operator new(size_t aSize);
|
||||
static void operator delete(void* aObject, size_t aSize);
|
||||
|
||||
nsXULAttribute(nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aName,
|
||||
|
@ -131,9 +145,14 @@ public:
|
|||
PRInt32 GetNameSpaceID() const { return mNameSpaceID; }
|
||||
nsIAtom* GetName() const { return mName; }
|
||||
nsresult SetValueInternal(const nsString& aValue);
|
||||
nsresult GetValueAsAtom(nsIAtom** aResult);
|
||||
|
||||
protected:
|
||||
nsIContent* mContent; // The content object that owns the attribute
|
||||
union {
|
||||
nsIContent* mContent; // The content object that owns the attribute
|
||||
nsXULAttribute* mNext; // For objects on the freelist
|
||||
};
|
||||
|
||||
void* mScriptObject; // The attribute's script object, if reified
|
||||
PRInt32 mNameSpaceID; // The attribute namespace
|
||||
nsIAtom* mName; // The attribute name
|
||||
|
|
|
@ -3327,17 +3327,36 @@ nsXULElement::GetElementsByAttribute(nsIDOMNode* aNode,
|
|||
NS_IMETHODIMP
|
||||
nsXULElement::GetID(nsIAtom*& aResult) const
|
||||
{
|
||||
nsAutoString value;
|
||||
GetAttribute(kNameSpaceID_None, kIdAtom, value);
|
||||
aResult = nsnull;
|
||||
|
||||
if (value.Length() > 0)
|
||||
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
|
||||
else
|
||||
{
|
||||
aResult = kNullAtom;
|
||||
NS_ADDREF(kNullAtom);
|
||||
}
|
||||
return NS_OK;
|
||||
if (mSlots && mSlots->mAttributes) {
|
||||
// Take advantage of the fact that the 'id' attribute will
|
||||
// already be atomized.
|
||||
PRInt32 count = mSlots->mAttributes->Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsXULAttribute* attr =
|
||||
NS_REINTERPRET_CAST(nsXULAttribute*, mSlots->mAttributes->ElementAt(i));
|
||||
|
||||
if ((attr->GetNameSpaceID() == kNameSpaceID_None) && (attr->GetName() == kIdAtom)) {
|
||||
nsIAtom* result;
|
||||
attr->GetValueAsAtom(&result);
|
||||
aResult = result; // transfer refcnt
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mPrototype) {
|
||||
PRInt32 count = mPrototype->mNumAttributes;
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) && (attr->mName.get() == kIdAtom)) {
|
||||
aResult = NS_NewAtom(attr->mValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -137,6 +137,70 @@ nsClassList::ParseClasses(nsClassList** aList, const nsString& aClassString)
|
|||
// nsXULAttribute
|
||||
//
|
||||
|
||||
PRInt32 nsXULAttribute::gRefCnt;
|
||||
nsIAtom* nsXULAttribute::kIdAtom;
|
||||
|
||||
const PRInt32 nsXULAttribute::kBlockSize = 512;
|
||||
|
||||
nsXULAttribute* nsXULAttribute::gFreeList;
|
||||
|
||||
void*
|
||||
nsXULAttribute::operator new(size_t aSize)
|
||||
{
|
||||
// Simple fixed size allocator for nsXULAttribute objects. Look
|
||||
// for an object on the |gFreeList|, if there isn't one, create a
|
||||
// new block of 'em.
|
||||
if (aSize != sizeof(nsXULAttribute))
|
||||
return ::operator new(aSize);
|
||||
|
||||
nsXULAttribute* result = gFreeList;
|
||||
|
||||
if (result) {
|
||||
gFreeList = gFreeList->mNext;
|
||||
}
|
||||
else {
|
||||
// Create a chunk o' memory for the freelist.
|
||||
nsXULAttribute* block =
|
||||
NS_STATIC_CAST(nsXULAttribute*, ::operator new(kBlockSize * sizeof(nsXULAttribute)));
|
||||
|
||||
if (! block)
|
||||
return nsnull;
|
||||
|
||||
// Thread it.
|
||||
for (PRInt32 i = 1; i < kBlockSize - 1; ++i)
|
||||
block[i].mNext = &block[i + 1];
|
||||
|
||||
block[kBlockSize - 1].mNext = nsnull;
|
||||
|
||||
result = block;
|
||||
gFreeList = &block[1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsXULAttribute::operator delete(void* aObject, size_t aSize)
|
||||
{
|
||||
// Return |aObject| to |gFreeList|, if we can.
|
||||
if (! aObject)
|
||||
return;
|
||||
|
||||
if (aSize != sizeof(nsXULAttribute)) {
|
||||
::operator delete(aObject);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCRT::memset(aObject, 0xdd, aSize);
|
||||
#endif
|
||||
|
||||
nsXULAttribute* doomed = NS_STATIC_CAST(nsXULAttribute*, aObject);
|
||||
|
||||
doomed->mNext = gFreeList;
|
||||
gFreeList = doomed;
|
||||
}
|
||||
|
||||
nsXULAttribute::nsXULAttribute(nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
|
@ -149,6 +213,11 @@ nsXULAttribute::nsXULAttribute(nsIContent* aContent,
|
|||
mValue(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
if (gRefCnt++ == 0) {
|
||||
kIdAtom = NS_NewAtom("id");
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(aName);
|
||||
SetValueInternal(aValue);
|
||||
}
|
||||
|
@ -157,6 +226,10 @@ nsXULAttribute::~nsXULAttribute()
|
|||
{
|
||||
NS_IF_RELEASE(mName);
|
||||
ReleaseValue();
|
||||
|
||||
if (--gRefCnt == 0) {
|
||||
NS_IF_RELEASE(kIdAtom);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -444,7 +517,13 @@ nsresult
|
|||
nsXULAttribute::SetValueInternal(const nsString& aValue)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> newAtom;
|
||||
if (aValue.Length() <= kMaxAtomValueLength) {
|
||||
|
||||
// Atomize the value if it is short, or if it is the 'id'
|
||||
// attribute. We atomize the 'id' attribute to "prime" the global
|
||||
// atom table: the style system frequently asks for it, and if the
|
||||
// table is "unprimed" we see quite a bit of thrashing as the 'id'
|
||||
// value is repeatedly added and then removed from the atom table.
|
||||
if ((aValue.Length() <= kMaxAtomValueLength) || (mName == kIdAtom)) {
|
||||
newAtom = getter_AddRefs( NS_NewAtom(aValue.GetUnicode()) );
|
||||
}
|
||||
|
||||
|
@ -472,6 +551,22 @@ nsXULAttribute::SetValueInternal(const nsString& aValue)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULAttribute::GetValueAsAtom(nsIAtom** aResult)
|
||||
{
|
||||
if (! mValue) {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
else if (IsStringValue()) {
|
||||
*aResult = NS_NewAtom((const PRUnichar*) mValue);
|
||||
}
|
||||
else {
|
||||
*aResult = (nsIAtom*)(PRWord(mValue) & ~PRWord(kTypeMask));
|
||||
NS_ADDREF(*aResult);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
|
|
|
@ -97,6 +97,20 @@ class nsXULAttribute : public nsIDOMAttr,
|
|||
public nsIScriptObjectOwner
|
||||
{
|
||||
protected:
|
||||
static PRInt32 gRefCnt;
|
||||
static nsIAtom* kIdAtom;
|
||||
|
||||
// A global fixed-size allocator for nsXULAttribute
|
||||
// objects. |kBlockSize| is the number of nsXULAttribute objects
|
||||
// the live together in a contiguous block of memory.
|
||||
static const PRInt32 kBlockSize;
|
||||
|
||||
// The head of the free list for free nsXULAttribute objects.
|
||||
static nsXULAttribute* gFreeList;
|
||||
|
||||
static void* operator new(size_t aSize);
|
||||
static void operator delete(void* aObject, size_t aSize);
|
||||
|
||||
nsXULAttribute(nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aName,
|
||||
|
@ -131,9 +145,14 @@ public:
|
|||
PRInt32 GetNameSpaceID() const { return mNameSpaceID; }
|
||||
nsIAtom* GetName() const { return mName; }
|
||||
nsresult SetValueInternal(const nsString& aValue);
|
||||
nsresult GetValueAsAtom(nsIAtom** aResult);
|
||||
|
||||
protected:
|
||||
nsIContent* mContent; // The content object that owns the attribute
|
||||
union {
|
||||
nsIContent* mContent; // The content object that owns the attribute
|
||||
nsXULAttribute* mNext; // For objects on the freelist
|
||||
};
|
||||
|
||||
void* mScriptObject; // The attribute's script object, if reified
|
||||
PRInt32 mNameSpaceID; // The attribute namespace
|
||||
nsIAtom* mName; // The attribute name
|
||||
|
|
|
@ -3327,17 +3327,36 @@ nsXULElement::GetElementsByAttribute(nsIDOMNode* aNode,
|
|||
NS_IMETHODIMP
|
||||
nsXULElement::GetID(nsIAtom*& aResult) const
|
||||
{
|
||||
nsAutoString value;
|
||||
GetAttribute(kNameSpaceID_None, kIdAtom, value);
|
||||
aResult = nsnull;
|
||||
|
||||
if (value.Length() > 0)
|
||||
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
|
||||
else
|
||||
{
|
||||
aResult = kNullAtom;
|
||||
NS_ADDREF(kNullAtom);
|
||||
}
|
||||
return NS_OK;
|
||||
if (mSlots && mSlots->mAttributes) {
|
||||
// Take advantage of the fact that the 'id' attribute will
|
||||
// already be atomized.
|
||||
PRInt32 count = mSlots->mAttributes->Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsXULAttribute* attr =
|
||||
NS_REINTERPRET_CAST(nsXULAttribute*, mSlots->mAttributes->ElementAt(i));
|
||||
|
||||
if ((attr->GetNameSpaceID() == kNameSpaceID_None) && (attr->GetName() == kIdAtom)) {
|
||||
nsIAtom* result;
|
||||
attr->GetValueAsAtom(&result);
|
||||
aResult = result; // transfer refcnt
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mPrototype) {
|
||||
PRInt32 count = mPrototype->mNumAttributes;
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) && (attr->mName.get() == kIdAtom)) {
|
||||
aResult = NS_NewAtom(attr->mValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
Загрузка…
Ссылка в новой задаче